diff options
author | Romain Guy <romainguy@google.com> | 2012-09-13 20:31:08 -0700 |
---|---|---|
committer | Romain Guy <romainguy@google.com> | 2012-09-14 10:50:51 -0700 |
commit | a938f569ce206c1ed68d736181016b5b708c0084 (patch) | |
tree | 5a607bc80af329334757c13e978f7c9b978122a8 /libs/hwui/ProgramCache.cpp | |
parent | 494ac35c27a0960f57b00bf8457f1956ecf149a2 (diff) |
Fix modulation and gamma correction issues
Modulation is normally enabled in a shader when drawing with an alpha
mask (A8 texture.) Modulation is used to do one of two things:
- Colorize the primitive (to draw text in red for instance)
- Apply extra translucency (50% translucent circle filled with a bitmap)
The current implementation has four issues:
1. Unnecessary work is performed by assigning the modulation color
to vec4 fragColor early in the shader
2. The modulation color's alpha is applied twice when the primitive
is drawn with an SkShader
3. The decision to modulate is wrong and triggers when any of the
RGB channels is < 1.0. Only the alpha channel needs to be taken
into account to make the decision
4. Gamma correction is not applied properly
This change addresses all four issues above.
Change-Id: I73fcc74efc4b094bf2d1b835f10ffaa2ea4b9eb9
Diffstat (limited to 'libs/hwui/ProgramCache.cpp')
-rw-r--r-- | libs/hwui/ProgramCache.cpp | 87 |
1 files changed, 50 insertions, 37 deletions
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index be8f80af55c3..6e7f35da67b3 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -140,9 +140,9 @@ const char* gFS_Header_Uniforms_PointHasBitmap = "uniform vec2 textureDimension;\n" "uniform float pointSize;\n"; const char* gFS_Uniforms_TextureSampler = - "uniform sampler2D sampler;\n"; + "uniform sampler2D baseSampler;\n"; const char* gFS_Uniforms_ExternalTextureSampler = - "uniform samplerExternalOES sampler;\n"; + "uniform samplerExternalOES baseSampler;\n"; #define FS_UNIFORMS_DITHER \ "uniform float ditherSize;\n" \ "uniform sampler2D ditherSampler;\n" @@ -199,27 +199,27 @@ const char* gFS_Fast_SingleColor = "}\n\n"; const char* gFS_Fast_SingleTexture = "\nvoid main(void) {\n" - " gl_FragColor = texture2D(sampler, outTexCoords);\n" + " gl_FragColor = texture2D(baseSampler, outTexCoords);\n" "}\n\n"; const char* gFS_Fast_SingleModulateTexture = "\nvoid main(void) {\n" - " gl_FragColor = color.a * texture2D(sampler, outTexCoords);\n" + " gl_FragColor = color.a * texture2D(baseSampler, outTexCoords);\n" "}\n\n"; const char* gFS_Fast_SingleA8Texture = "\nvoid main(void) {\n" - " gl_FragColor = texture2D(sampler, outTexCoords);\n" + " gl_FragColor = texture2D(baseSampler, outTexCoords);\n" "}\n\n"; const char* gFS_Fast_SingleA8Texture_ApplyGamma = "\nvoid main(void) {\n" - " gl_FragColor = vec4(0.0, 0.0, 0.0, pow(texture2D(sampler, outTexCoords).a, gamma));\n" + " gl_FragColor = vec4(0.0, 0.0, 0.0, pow(texture2D(baseSampler, outTexCoords).a, gamma));\n" "}\n\n"; const char* gFS_Fast_SingleModulateA8Texture = "\nvoid main(void) {\n" - " gl_FragColor = color * texture2D(sampler, outTexCoords).a;\n" + " gl_FragColor = color * texture2D(baseSampler, outTexCoords).a;\n" "}\n\n"; const char* gFS_Fast_SingleModulateA8Texture_ApplyGamma = "\nvoid main(void) {\n" - " gl_FragColor = color * pow(texture2D(sampler, outTexCoords).a, gamma);\n" + " gl_FragColor = color * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n" "}\n\n"; const char* gFS_Fast_SingleGradient[2] = { "\nvoid main(void) {\n" @@ -243,8 +243,6 @@ const char* gFS_Main_FetchColor = " fragColor = color;\n"; const char* gFS_Main_ModulateColor = " fragColor *= color.a;\n"; -const char* gFS_Main_ModulateColor_ApplyGamma = - " fragColor *= pow(color.a, gamma);\n"; const char* gFS_Main_AccountForAA = " fragColor *= (1.0 - smoothstep(boundaryWidth, 0.5, abs(0.5 - widthProportion)))\n" " * (1.0 - smoothstep(boundaryLength, 0.5, abs(0.5 - lengthProportion)));\n"; @@ -253,15 +251,17 @@ const char* gFS_Main_AccountForAARect = const char* gFS_Main_FetchTexture[2] = { // Don't modulate - " fragColor = texture2D(sampler, outTexCoords);\n", + " fragColor = texture2D(baseSampler, outTexCoords);\n", // Modulate - " fragColor = color * texture2D(sampler, outTexCoords);\n" + " fragColor = color * texture2D(baseSampler, outTexCoords);\n" }; -const char* gFS_Main_FetchA8Texture[2] = { +const char* gFS_Main_FetchA8Texture[4] = { // Don't modulate - " fragColor = texture2D(sampler, outTexCoords);\n", + " fragColor = texture2D(baseSampler, outTexCoords);\n", + " fragColor = texture2D(baseSampler, outTexCoords);\n", // Modulate - " fragColor = color * texture2D(sampler, outTexCoords).a;\n" + " fragColor = color * texture2D(baseSampler, outTexCoords).a;\n", + " fragColor = color * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n" }; const char* gFS_Main_FetchGradient[6] = { // Linear @@ -289,29 +289,38 @@ const char* gFS_Main_BlendShadersBG = " fragColor = blendShaders(gradientColor, bitmapColor)"; const char* gFS_Main_BlendShadersGB = " fragColor = blendShaders(bitmapColor, gradientColor)"; -const char* gFS_Main_BlendShaders_Modulate[3] = { +const char* gFS_Main_BlendShaders_Modulate[6] = { // Don't modulate ";\n", + ";\n", // Modulate " * fragColor.a;\n", + " * fragColor.a;\n", // Modulate with alpha 8 texture - " * texture2D(sampler, outTexCoords).a;\n" + " * texture2D(baseSampler, outTexCoords).a;\n", + " * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n" }; -const char* gFS_Main_GradientShader_Modulate[3] = { +const char* gFS_Main_GradientShader_Modulate[6] = { // Don't modulate " fragColor = gradientColor;\n", + " fragColor = gradientColor;\n", // Modulate " fragColor = gradientColor * fragColor.a;\n", + " fragColor = gradientColor * fragColor.a;\n", // Modulate with alpha 8 texture - " fragColor = gradientColor * texture2D(sampler, outTexCoords).a;\n" + " fragColor = gradientColor * texture2D(baseSampler, outTexCoords).a;\n", + " fragColor = gradientColor * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n" }; -const char* gFS_Main_BitmapShader_Modulate[3] = { +const char* gFS_Main_BitmapShader_Modulate[6] = { // Don't modulate " fragColor = bitmapColor;\n", + " fragColor = bitmapColor;\n", // Modulate " fragColor = bitmapColor * fragColor.a;\n", + " fragColor = bitmapColor * fragColor.a;\n", // Modulate with alpha 8 texture - " fragColor = bitmapColor * texture2D(sampler, outTexCoords).a;\n" + " fragColor = bitmapColor * texture2D(baseSampler, outTexCoords).a;\n", + " fragColor = bitmapColor * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n" }; const char* gFS_Main_FragColor = " gl_FragColor = fragColor;\n"; @@ -518,6 +527,14 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description return shader; } +static bool shaderOp(const ProgramDescription& description, String8& shader, + const int modulateOp, const char** snippets) { + int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp; + op = op * 2 + description.hasGammaCorrection; + shader.append(snippets[op]); + return description.hasAlpha8Texture; +} + String8 ProgramCache::generateFragmentShader(const ProgramDescription& description) { String8 shader; @@ -661,13 +678,14 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti if (description.hasTexture || description.hasExternalTexture) { if (description.hasAlpha8Texture) { if (!description.hasGradient && !description.hasBitmap) { - shader.append(gFS_Main_FetchA8Texture[modulateOp]); + shader.append(gFS_Main_FetchA8Texture[modulateOp * 2 + + description.hasGammaCorrection]); } } else { shader.append(gFS_Main_FetchTexture[modulateOp]); } } else { - if ((!description.hasGradient && !description.hasBitmap) || description.modulate) { + if (!description.hasGradient && !description.hasBitmap) { shader.append(gFS_Main_FetchColor); } } @@ -688,32 +706,27 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti bool applyModulate = false; // Case when we have two shaders set if (description.hasGradient && description.hasBitmap) { - int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp; if (description.isBitmapFirst) { shader.append(gFS_Main_BlendShadersBG); } else { shader.append(gFS_Main_BlendShadersGB); } - shader.append(gFS_Main_BlendShaders_Modulate[op]); - applyModulate = true; + applyModulate = shaderOp(description, shader, modulateOp, + gFS_Main_BlendShaders_Modulate); } else { if (description.hasGradient) { - int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp; - shader.append(gFS_Main_GradientShader_Modulate[op]); - applyModulate = true; + applyModulate = shaderOp(description, shader, modulateOp, + gFS_Main_GradientShader_Modulate); } else if (description.hasBitmap) { - int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp; - shader.append(gFS_Main_BitmapShader_Modulate[op]); - applyModulate = true; + applyModulate = shaderOp(description, shader, modulateOp, + gFS_Main_BitmapShader_Modulate); } } + if (description.modulate && applyModulate) { - if (description.hasGammaCorrection) { - shader.append(gFS_Main_ModulateColor_ApplyGamma); - } else { - shader.append(gFS_Main_ModulateColor); - } + shader.append(gFS_Main_ModulateColor); } + // Apply the color op if needed shader.append(gFS_Main_ApplyColorOp[description.colorOp]); |