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
diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp
index 1adcd1f..0dab872 100644
--- a/services/surfaceflinger/RenderEngine/Description.cpp
+++ b/services/surfaceflinger/RenderEngine/Description.cpp
@@ -88,5 +88,9 @@
     mColorMatrixEnabled = (mtx != identity);
 }
 
+const mat4& Description::getColorMatrix() const {
+    return mColorMatrix;
+}
+
 
 } /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/Description.h
index 43b835f..8a3447c 100644
--- a/services/surfaceflinger/RenderEngine/Description.h
+++ b/services/surfaceflinger/RenderEngine/Description.h
@@ -66,6 +66,7 @@
     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;
diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
index 2e6af49..1a9f59b 100644
--- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
@@ -262,14 +262,6 @@
     }
 }
 
-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);
 }
diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
index 87eb3e4..08de646 100644
--- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
@@ -62,9 +62,6 @@
 
     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;
 };
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 8712c9a..1fabaf5 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -169,6 +169,12 @@
     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::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);
 }
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index 3d6243e..819356a 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -72,14 +72,12 @@
     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;
 };
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 8d7529c..31a961e 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -99,18 +99,16 @@
     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;