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);
|
mColorMatrixEnabled = (mtx != identity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mat4& Description::getColorMatrix() const {
|
||||||
|
return mColorMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} /* namespace android */
|
} /* namespace android */
|
||||||
|
|
|
@ -66,6 +66,7 @@ public:
|
||||||
void setColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
|
void setColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
|
||||||
void setProjectionMatrix(const mat4& mtx);
|
void setProjectionMatrix(const mat4& mtx);
|
||||||
void setColorMatrix(const mat4& mtx);
|
void setColorMatrix(const mat4& mtx);
|
||||||
|
const mat4& getColorMatrix() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mUniformsDirty;
|
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) {
|
void GLES11RenderEngine::dump(String8& result) {
|
||||||
RenderEngine::dump(result);
|
RenderEngine::dump(result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,9 +62,6 @@ protected:
|
||||||
|
|
||||||
virtual void drawMesh(const Mesh& mesh);
|
virtual void drawMesh(const Mesh& mesh);
|
||||||
|
|
||||||
virtual void beginGroup(const mat4& colorTransform);
|
|
||||||
virtual void endGroup();
|
|
||||||
|
|
||||||
virtual size_t getMaxTextureSize() const;
|
virtual size_t getMaxTextureSize() const;
|
||||||
virtual size_t getMaxViewportDims() const;
|
virtual size_t getMaxViewportDims() const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -169,6 +169,12 @@ void GLES20RenderEngine::setupLayerBlackedOut() {
|
||||||
mState.setTexture(texture);
|
mState.setTexture(texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mat4 GLES20RenderEngine::setupColorTransform(const mat4& colorTransform) {
|
||||||
|
mat4 oldTransform = mState.getColorMatrix();
|
||||||
|
mState.setColorMatrix(colorTransform);
|
||||||
|
return oldTransform;
|
||||||
|
}
|
||||||
|
|
||||||
void GLES20RenderEngine::disableTexturing() {
|
void GLES20RenderEngine::disableTexturing() {
|
||||||
mState.disableTexture();
|
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) {
|
void GLES20RenderEngine::dump(String8& result) {
|
||||||
RenderEngine::dump(result);
|
RenderEngine::dump(result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,14 +72,12 @@ protected:
|
||||||
virtual void setupLayerTexturing(const Texture& texture);
|
virtual void setupLayerTexturing(const Texture& texture);
|
||||||
virtual void setupLayerBlackedOut();
|
virtual void setupLayerBlackedOut();
|
||||||
virtual void setupFillWithColor(float r, float g, float b, float a);
|
virtual void setupFillWithColor(float r, float g, float b, float a);
|
||||||
|
virtual mat4 setupColorTransform(const mat4& colorTransform);
|
||||||
virtual void disableTexturing();
|
virtual void disableTexturing();
|
||||||
virtual void disableBlending();
|
virtual void disableBlending();
|
||||||
|
|
||||||
virtual void drawMesh(const Mesh& mesh);
|
virtual void drawMesh(const Mesh& mesh);
|
||||||
|
|
||||||
virtual void beginGroup(const mat4& colorTransform);
|
|
||||||
virtual void endGroup();
|
|
||||||
|
|
||||||
virtual size_t getMaxTextureSize() const;
|
virtual size_t getMaxTextureSize() const;
|
||||||
virtual size_t getMaxViewportDims() const;
|
virtual size_t getMaxViewportDims() const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -99,18 +99,16 @@ public:
|
||||||
virtual void setupLayerBlackedOut() = 0;
|
virtual void setupLayerBlackedOut() = 0;
|
||||||
virtual void setupFillWithColor(float r, float g, float b, float a) = 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 disableTexturing() = 0;
|
||||||
virtual void disableBlending() = 0;
|
virtual void disableBlending() = 0;
|
||||||
|
|
||||||
// drawing
|
// drawing
|
||||||
virtual void drawMesh(const Mesh& mesh) = 0;
|
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
|
// queries
|
||||||
virtual size_t getMaxTextureSize() const = 0;
|
virtual size_t getMaxTextureSize() const = 0;
|
||||||
virtual size_t getMaxViewportDims() const = 0;
|
virtual size_t getMaxViewportDims() const = 0;
|
||||||
|
|
|
@ -1872,9 +1872,9 @@ void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw,
|
||||||
if (mDaltonize) {
|
if (mDaltonize) {
|
||||||
colorMatrix = colorMatrix * mDaltonizer();
|
colorMatrix = colorMatrix * mDaltonizer();
|
||||||
}
|
}
|
||||||
engine.beginGroup(colorMatrix);
|
mat4 oldMatrix = engine.setupColorTransform(colorMatrix);
|
||||||
doComposeSurfaces(hw, dirtyRegion);
|
doComposeSurfaces(hw, dirtyRegion);
|
||||||
engine.endGroup();
|
engine.setupColorTransform(oldMatrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the swap region and clear the dirty region
|
// update the swap region and clear the dirty region
|
||||||
|
|
Loading…
Reference in New Issue