Merge "Prevent opaque windows from making framebuffer translucent"
This commit is contained in:
commit
fb469f1906
@ -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