SF: Skip render-to-texture for color transforms

In cases where SurfaceFlinger is applying a color matrix (usually for
accessibility features), we previously would perform a render-to-
texture for the initial composition, and then apply the matrix during
a copy to the framebuffer. This changes that behavior to just apply the
matrix during composition without a render-to-texture pass.

This may result in a perceived change of the image in cases with alpha
blending, since the blending is performed at a different stage of the
pipeline and the system effectively performs non-linear blends.
However, neither this nor the prior render-to-texture pass is strictly
correct in that regard, and this approach is less error-prone and
likely faster.

Change-Id: I2110ff0374f61d76df7b087dde8a1ed98990440c
This commit is contained in:
Dan Stoza 2014-10-20 15:46:09 -07:00
parent 7fc3ef0eb0
commit f008799d37
8 changed files with 18 additions and 94 deletions

View File

@ -88,5 +88,9 @@ void Description::setColorMatrix(const mat4& mtx) {
mColorMatrixEnabled = (mtx != identity);
}
const mat4& Description::getColorMatrix() const {
return mColorMatrix;
}
} /* namespace android */

View File

@ -66,6 +66,7 @@ public:
void setColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
void setProjectionMatrix(const mat4& mtx);
void setColorMatrix(const mat4& mtx);
const mat4& getColorMatrix() const;
private:
bool mUniformsDirty;

View File

@ -262,14 +262,6 @@ void GLES11RenderEngine::drawMesh(const Mesh& mesh) {
}
}
void GLES11RenderEngine::beginGroup(const mat4& /*colorTransform*/) {
// doesn't do anything in GLES 1.1
}
void GLES11RenderEngine::endGroup() {
// doesn't do anything in GLES 1.1
}
void GLES11RenderEngine::dump(String8& result) {
RenderEngine::dump(result);
}

View File

@ -62,9 +62,6 @@ protected:
virtual void drawMesh(const Mesh& mesh);
virtual void beginGroup(const mat4& colorTransform);
virtual void endGroup();
virtual size_t getMaxTextureSize() const;
virtual size_t getMaxViewportDims() const;
};

View File

@ -169,6 +169,12 @@ void GLES20RenderEngine::setupLayerBlackedOut() {
mState.setTexture(texture);
}
mat4 GLES20RenderEngine::setupColorTransform(const mat4& colorTransform) {
mat4 oldTransform = mState.getColorMatrix();
mState.setColorMatrix(colorTransform);
return oldTransform;
}
void GLES20RenderEngine::disableTexturing() {
mState.disableTexture();
}
@ -237,78 +243,6 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) {
}
}
void GLES20RenderEngine::beginGroup(const mat4& colorTransform) {
GLuint tname, name;
// create the texture
glGenTextures(1, &tname);
glBindTexture(GL_TEXTURE_2D, tname);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mVpWidth, mVpHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
// create a Framebuffer Object to render into
glGenFramebuffers(1, &name);
glBindFramebuffer(GL_FRAMEBUFFER, name);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tname, 0);
Group group;
group.texture = tname;
group.fbo = name;
group.width = mVpWidth;
group.height = mVpHeight;
group.colorTransform = colorTransform;
mGroupStack.push(group);
}
void GLES20RenderEngine::endGroup() {
const Group group(mGroupStack.top());
mGroupStack.pop();
// activate the previous render target
GLuint fbo = 0;
if (!mGroupStack.isEmpty()) {
fbo = mGroupStack.top().fbo;
}
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// set our state
Texture texture(Texture::TEXTURE_2D, group.texture);
texture.setDimensions(group.width, group.height);
glBindTexture(GL_TEXTURE_2D, group.texture);
mState.setPlaneAlpha(1.0f);
mState.setPremultipliedAlpha(true);
mState.setOpaque(false);
mState.setTexture(texture);
mState.setColorMatrix(group.colorTransform);
glDisable(GL_BLEND);
Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2, 2);
Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
Mesh::VertexArray<vec2> texCoord(mesh.getTexCoordArray<vec2>());
position[0] = vec2(0, 0);
position[1] = vec2(group.width, 0);
position[2] = vec2(group.width, group.height);
position[3] = vec2(0, group.height);
texCoord[0] = vec2(0, 0);
texCoord[1] = vec2(1, 0);
texCoord[2] = vec2(1, 1);
texCoord[3] = vec2(0, 1);
drawMesh(mesh);
// reset color matrix
mState.setColorMatrix(mat4());
// free our fbo and texture
glDeleteFramebuffers(1, &group.fbo);
glDeleteTextures(1, &group.texture);
}
void GLES20RenderEngine::dump(String8& result) {
RenderEngine::dump(result);
}

View File

@ -72,14 +72,12 @@ protected:
virtual void setupLayerTexturing(const Texture& texture);
virtual void setupLayerBlackedOut();
virtual void setupFillWithColor(float r, float g, float b, float a);
virtual mat4 setupColorTransform(const mat4& colorTransform);
virtual void disableTexturing();
virtual void disableBlending();
virtual void drawMesh(const Mesh& mesh);
virtual void beginGroup(const mat4& colorTransform);
virtual void endGroup();
virtual size_t getMaxTextureSize() const;
virtual size_t getMaxViewportDims() const;
};

View File

@ -99,18 +99,16 @@ public:
virtual void setupLayerBlackedOut() = 0;
virtual void setupFillWithColor(float r, float g, float b, float a) = 0;
virtual mat4 setupColorTransform(const mat4& /* colorTransform */) {
return mat4();
}
virtual void disableTexturing() = 0;
virtual void disableBlending() = 0;
// drawing
virtual void drawMesh(const Mesh& mesh) = 0;
// grouping
// creates a color-transform group, everything drawn in the group will be
// transformed by the given color transform when endGroup() is called.
virtual void beginGroup(const mat4& colorTransform) = 0;
virtual void endGroup() = 0;
// queries
virtual size_t getMaxTextureSize() const = 0;
virtual size_t getMaxViewportDims() const = 0;

View File

@ -1872,9 +1872,9 @@ void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw,
if (mDaltonize) {
colorMatrix = colorMatrix * mDaltonizer();
}
engine.beginGroup(colorMatrix);
mat4 oldMatrix = engine.setupColorTransform(colorMatrix);
doComposeSurfaces(hw, dirtyRegion);
engine.endGroup();
engine.setupColorTransform(oldMatrix);
}
// update the swap region and clear the dirty region