Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f008799d authored by Dan Stoza's avatar Dan Stoza
Browse files

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
parent 7fc3ef0e
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -88,5 +88,9 @@ void Description::setColorMatrix(const mat4& mtx) {
    mColorMatrixEnabled = (mtx != identity);
}

const mat4& Description::getColorMatrix() const {
    return mColorMatrix;
}


} /* namespace android */
+1 −0
Original line number Diff line number Diff line
@@ -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;
+0 −8
Original line number Diff line number Diff line
@@ -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);
}
+0 −3
Original line number Diff line number Diff line
@@ -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;
};
+6 −72
Original line number Diff line number Diff line
@@ -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);
}
Loading