Prevent opaque windows from making framebuffer translucent
To keep the code readable now that we have four different texenv configurations, this change separates the decisions about what configuration to use from the GL calls to set up the configuration. Bug: 8963244 Change-Id: Ia07a306a7809ba8f93493d0160ccbd509e948581
This commit is contained in:
parent
9e3cb55b8f
commit
29c3f35279
@ -559,31 +559,88 @@ void Layer::clearWithOpenGL(
|
||||
clearWithOpenGL(hw, clip, 0,0,0,0);
|
||||
}
|
||||
|
||||
static void setupOpenGL10(bool premultipliedAlpha, bool opaque, int alpha) {
|
||||
// OpenGL ES 1.0 doesn't support texture combiners.
|
||||
// This path doesn't properly handle opaque layers that have non-opaque
|
||||
// alpha values. The alpha channel will be copied into the framebuffer or
|
||||
// screenshot, so if the framebuffer or screenshot is blended on top of
|
||||
// something else, whatever is below the window will incorrectly show
|
||||
// through.
|
||||
if (CC_UNLIKELY(alpha < 0xFF)) {
|
||||
GLfloat floatAlpha = alpha * (1.0f / 255.0f);
|
||||
if (premultipliedAlpha) {
|
||||
glColor4f(floatAlpha, floatAlpha, floatAlpha, floatAlpha);
|
||||
} else {
|
||||
glColor4f(1.0f, 1.0f, 1.0f, floatAlpha);
|
||||
}
|
||||
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
} else {
|
||||
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
}
|
||||
}
|
||||
|
||||
static void setupOpenGL11(bool premultipliedAlpha, bool opaque, int alpha) {
|
||||
GLenum combineRGB;
|
||||
GLenum combineAlpha;
|
||||
GLenum src0Alpha;
|
||||
GLfloat envColor[4];
|
||||
|
||||
if (CC_UNLIKELY(alpha < 0xFF)) {
|
||||
// Cv = premultiplied ? Cs*alpha : Cs
|
||||
// Av = !opaque ? alpha*As : 1.0
|
||||
combineRGB = premultipliedAlpha ? GL_MODULATE : GL_REPLACE;
|
||||
combineAlpha = !opaque ? GL_MODULATE : GL_REPLACE;
|
||||
src0Alpha = GL_CONSTANT;
|
||||
envColor[0] = alpha * (1.0f / 255.0f);
|
||||
} else {
|
||||
// Cv = Cs
|
||||
// Av = opaque ? 1.0 : As
|
||||
combineRGB = GL_REPLACE;
|
||||
combineAlpha = GL_REPLACE;
|
||||
src0Alpha = opaque ? GL_CONSTANT : GL_TEXTURE;
|
||||
envColor[0] = 1.0f;
|
||||
}
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, combineRGB);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
||||
if (combineRGB == GL_MODULATE) {
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
|
||||
}
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, combineAlpha);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, src0Alpha);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
|
||||
if (combineAlpha == GL_MODULATE) {
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
|
||||
}
|
||||
if (combineRGB == GL_MODULATE || src0Alpha == GL_CONSTANT) {
|
||||
envColor[1] = envColor[0];
|
||||
envColor[2] = envColor[0];
|
||||
envColor[3] = envColor[0];
|
||||
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, envColor);
|
||||
}
|
||||
}
|
||||
|
||||
void Layer::drawWithOpenGL(
|
||||
const sp<const DisplayDevice>& hw, const Region& clip) const {
|
||||
const uint32_t fbHeight = hw->getHeight();
|
||||
const State& s(drawingState());
|
||||
|
||||
GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
|
||||
if (CC_UNLIKELY(s.alpha < 0xFF)) {
|
||||
const GLfloat alpha = s.alpha * (1.0f/255.0f);
|
||||
if (mPremultipliedAlpha) {
|
||||
glColor4f(alpha, alpha, alpha, alpha);
|
||||
} else {
|
||||
glColor4f(1, 1, 1, alpha);
|
||||
}
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
if (mFlinger->getGlesVersion() == GLES_VERSION_1_0) {
|
||||
setupOpenGL10(mPremultipliedAlpha, isOpaque(), s.alpha);
|
||||
} else {
|
||||
glColor4f(1, 1, 1, 1);
|
||||
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
if (!isOpaque()) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
|
||||
} else {
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
setupOpenGL11(mPremultipliedAlpha, isOpaque(), s.alpha);
|
||||
}
|
||||
|
||||
if (s.alpha < 0xFF || !isOpaque()) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA,
|
||||
GL_ONE_MINUS_SRC_ALPHA);
|
||||
} else {
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
LayerMesh mesh;
|
||||
|
@ -414,6 +414,22 @@ EGLContext SurfaceFlinger::createGLContext(EGLDisplay display, EGLConfig config)
|
||||
return ctxt;
|
||||
}
|
||||
|
||||
static GlesVersion parseGlesVersion(const char* str) {
|
||||
int major, minor;
|
||||
if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) {
|
||||
ALOGW("Unable to parse GL_VERSION string: \"%s\"", str);
|
||||
return GLES_VERSION_1_0;
|
||||
}
|
||||
|
||||
if (major == 1 && minor == 0) return GLES_VERSION_1_0;
|
||||
if (major == 1 && minor >= 1) return GLES_VERSION_1_1;
|
||||
if (major == 2 && minor >= 0) return GLES_VERSION_2_0;
|
||||
if (major == 3 && minor >= 0) return GLES_VERSION_3_0;
|
||||
|
||||
ALOGW("Unrecognized OpenGL ES version: %d.%d", major, minor);
|
||||
return GLES_VERSION_1_0;
|
||||
}
|
||||
|
||||
void SurfaceFlinger::initializeGL(EGLDisplay display) {
|
||||
GLExtensions& extensions(GLExtensions::getInstance());
|
||||
extensions.initWithGLStrings(
|
||||
@ -425,6 +441,8 @@ void SurfaceFlinger::initializeGL(EGLDisplay display) {
|
||||
eglQueryString(display, EGL_VERSION),
|
||||
eglQueryString(display, EGL_EXTENSIONS));
|
||||
|
||||
mGlesVersion = parseGlesVersion(extensions.getVersion());
|
||||
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
|
||||
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
|
||||
|
||||
|
@ -72,6 +72,13 @@ enum {
|
||||
eTransactionMask = 0x07
|
||||
};
|
||||
|
||||
enum GlesVersion {
|
||||
GLES_VERSION_1_0 = 0x10000,
|
||||
GLES_VERSION_1_1 = 0x10001,
|
||||
GLES_VERSION_2_0 = 0x20000,
|
||||
GLES_VERSION_3_0 = 0x30000,
|
||||
};
|
||||
|
||||
class SurfaceFlinger : public BinderService<SurfaceFlinger>,
|
||||
public BnSurfaceComposer,
|
||||
private IBinder::DeathRecipient,
|
||||
@ -121,6 +128,11 @@ public:
|
||||
// TODO: this should be made accessible only to HWComposer
|
||||
const Vector< sp<Layer> >& getLayerSortedByZForHwcDisplay(int id);
|
||||
|
||||
// return the version of the OpenGL ES composition context
|
||||
GlesVersion getGlesVersion() const {
|
||||
return mGlesVersion;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class Client;
|
||||
friend class DisplayEventConnection;
|
||||
@ -421,6 +433,7 @@ private:
|
||||
EGLConfig mEGLConfig;
|
||||
EGLDisplay mEGLDisplay;
|
||||
EGLint mEGLNativeVisualId;
|
||||
GlesVersion mGlesVersion;
|
||||
sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_DISPLAY_TYPES];
|
||||
|
||||
// Can only accessed from the main thread, these members
|
||||
|
Loading…
Reference in New Issue
Block a user