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:
parent
7fc3ef0eb0
commit
f008799d37
@ -88,5 +88,9 @@ void Description::setColorMatrix(const mat4& mtx) {
|
||||
mColorMatrixEnabled = (mtx != identity);
|
||||
}
|
||||
|
||||
const mat4& Description::getColorMatrix() const {
|
||||
return mColorMatrix;
|
||||
}
|
||||
|
||||
|
||||
} /* namespace android */
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user