diff options
author | Romain Guy <romainguy@google.com> | 2010-10-11 16:34:59 -0700 |
---|---|---|
committer | Romain Guy <romainguy@google.com> | 2010-10-11 16:34:59 -0700 |
commit | 707b2f78ccaa09965d7e030fda3a883ce9b75ea8 (patch) | |
tree | 0503326cbed34fe219dc32508456b5ce9bd03340 /libs/hwui/ProgramCache.cpp | |
parent | 7537f856f9076a84db04d8de447f6527b67166fd (diff) |
Optimize GLSL shaders.
Change-Id: I9a5e01bced63d8da0c61330a543a2b805388a59d
Diffstat (limited to 'libs/hwui/ProgramCache.cpp')
-rw-r--r-- | libs/hwui/ProgramCache.cpp | 171 |
1 files changed, 150 insertions, 21 deletions
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index 63e92a51df56..1282b7102788 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -24,6 +24,14 @@ namespace android { namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// +// Defines +/////////////////////////////////////////////////////////////////////////////// + +#define MODULATE_OP_NO_MODULATE 0 +#define MODULATE_OP_MODULATE 1 +#define MODULATE_OP_MODULATE_A8 2 + +/////////////////////////////////////////////////////////////////////////////// // Vertex shaders snippets /////////////////////////////////////////////////////////////////////////////// @@ -69,8 +77,7 @@ const char* gVS_Main_OutGradient[3] = { " sweep = (screenSpace * position).xy;\n" }; const char* gVS_Main_OutBitmapTexCoords = - " vec4 bitmapCoords = textureTransform * position;\n" - " outBitmapTexCoords = bitmapCoords.xy * textureDimension;\n"; + " outBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n"; const char* gVS_Main_Position = " gl_Position = transform * position;\n"; const char* gVS_Footer = @@ -113,12 +120,52 @@ const char* gFS_Uniforms_ColorOp[4] = { const char* gFS_Main = "\nvoid main(void) {\n" " lowp vec4 fragColor;\n"; + +// Fast cases +const char* gFS_Fast_SingleColor = + "\nvoid main(void) {\n" + " gl_FragColor = color;\n" + "}\n\n"; +const char* gFS_Fast_SingleTexture = + "\nvoid main(void) {\n" + " gl_FragColor = texture2D(sampler, outTexCoords);\n" + "}\n\n"; +const char* gFS_Fast_SingleModulateTexture = + "\nvoid main(void) {\n" + " gl_FragColor = color.a * texture2D(sampler, outTexCoords);\n" + "}\n\n"; +const char* gFS_Fast_SingleA8Texture = + "\nvoid main(void) {\n" + " gl_FragColor = vec4(0.0, 0.0, 0.0, texture2D(sampler, outTexCoords).a);\n" + "}\n\n"; +const char* gFS_Fast_SingleModulateA8Texture = + "\nvoid main(void) {\n" + " gl_FragColor = color * texture2D(sampler, outTexCoords).a;\n" + "}\n\n"; +const char* gFS_Fast_SingleGradient = + "\nvoid main(void) {\n" + " gl_FragColor = texture2D(gradientSampler, linear);\n" + "}\n\n"; +const char* gFS_Fast_SingleModulateGradient = + "\nvoid main(void) {\n" + " gl_FragColor = color.a * texture2D(gradientSampler, linear);\n" + "}\n\n"; + +// General case const char* gFS_Main_FetchColor = " fragColor = color;\n"; -const char* gFS_Main_FetchTexture = - " fragColor = color * texture2D(sampler, outTexCoords);\n"; -const char* gFS_Main_FetchA8Texture = - " fragColor = color * texture2D(sampler, outTexCoords).a;\n"; +const char* gFS_Main_FetchTexture[2] = { + // Don't modulate + " fragColor = texture2D(sampler, outTexCoords);\n", + // Modulate + " fragColor = color * texture2D(sampler, outTexCoords);\n" +}; +const char* gFS_Main_FetchA8Texture[2] = { + // Don't modulate + " fragColor = vec4(0.0, 0.0, 0.0, texture2D(sampler, outTexCoords).a);\n", + // Modulate + " fragColor = color * texture2D(sampler, outTexCoords).a;\n" +}; const char* gFS_Main_FetchGradient[3] = { // Linear " vec4 gradientColor = texture2D(gradientSampler, linear);\n", @@ -137,12 +184,30 @@ const char* gFS_Main_BlendShadersBG = " fragColor = blendShaders(gradientColor, bitmapColor)"; const char* gFS_Main_BlendShadersGB = " fragColor = blendShaders(bitmapColor, gradientColor)"; -const char* gFS_Main_BlendShaders_Modulate = - " * fragColor.a;\n"; -const char* gFS_Main_GradientShader_Modulate = - " fragColor = gradientColor * fragColor.a;\n"; -const char* gFS_Main_BitmapShader_Modulate = - " fragColor = bitmapColor * fragColor.a;\n"; +const char* gFS_Main_BlendShaders_Modulate[3] = { + // Don't modulate + ";\n", + // Modulate + " * fragColor.a;\n", + // Modulate with alpha 8 texture + " * texture2D(sampler, outTexCoords).a;\n" +}; +const char* gFS_Main_GradientShader_Modulate[3] = { + // Don't modulate + " fragColor = gradientColor;\n", + // Modulate + " fragColor = gradientColor * fragColor.a;\n", + // Modulate with alpha 8 texture + " fragColor = gradientColor * texture2D(sampler, outTexCoords).a;\n" + }; +const char* gFS_Main_BitmapShader_Modulate[3] = { + // Don't modulate + " fragColor = bitmapColor;\n", + // Modulate + " fragColor = bitmapColor * fragColor.a;\n", + // Modulate with alpha 8 texture + " fragColor = bitmapColor * texture2D(sampler, outTexCoords).a;\n" + }; const char* gFS_Main_FragColor = " gl_FragColor = fragColor;\n"; const char* gFS_Main_FragColor_Blend = @@ -317,7 +382,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti // Set the default precision String8 shader; - bool blendFramebuffer = description.framebufferMode >= SkXfermode::kPlus_Mode; + const bool blendFramebuffer = description.framebufferMode >= SkXfermode::kPlus_Mode; if (blendFramebuffer) { shader.append(gFS_Header_Extension_FramebufferFetch); } @@ -335,15 +400,72 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti shader.append(gVS_Header_Varyings_HasBitmap); } - // Uniforms - shader.append(gFS_Uniforms_Color); + int modulateOp = MODULATE_OP_NO_MODULATE; + const bool singleColor = !description.hasTexture && + !description.hasGradient && !description.hasBitmap; + + if (description.modulate || singleColor) { + shader.append(gFS_Uniforms_Color); + if (!singleColor) modulateOp = MODULATE_OP_MODULATE; + } if (description.hasTexture) { shader.append(gFS_Uniforms_TextureSampler); } if (description.hasGradient) { shader.append(gFS_Uniforms_GradientSampler[description.gradientType]); } + + // Optimization for common cases + if (!blendFramebuffer) { + bool fast = false; + + const bool noShader = !description.hasGradient && !description.hasBitmap; + const bool singleTexture = description.hasTexture && + !description.hasAlpha8Texture && noShader; + const bool singleA8Texture = description.hasTexture && + description.hasAlpha8Texture && noShader; + const bool singleGradient = !description.hasTexture && + description.hasGradient && !description.hasBitmap && + description.gradientType == ProgramDescription::kGradientLinear; + + if (singleColor) { + shader.append(gFS_Fast_SingleColor); + fast = true; + } else if (singleTexture) { + if (!description.modulate) { + shader.append(gFS_Fast_SingleTexture); + } else { + shader.append(gFS_Fast_SingleModulateTexture); + } + fast = true; + } else if (singleA8Texture) { + if (!description.modulate) { + shader.append(gFS_Fast_SingleA8Texture); + } else { + shader.append(gFS_Fast_SingleModulateA8Texture); + } + fast = true; + } else if (singleGradient) { + if (!description.modulate) { + shader.append(gFS_Fast_SingleGradient); + } else { + shader.append(gFS_Fast_SingleModulateGradient); + } + fast = true; + } + + if (fast) { + if (DEBUG_PROGRAM_CACHE) { + PROGRAM_LOGD("*** Fast case:\n"); + PROGRAM_LOGD("*** Generated fragment shader:\n\n"); + printLongString(shader); + } + + return shader; + } + } + if (description.hasBitmap) { shader.append(gFS_Uniforms_BitmapSampler); } @@ -368,12 +490,16 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti // Stores the result in fragColor directly if (description.hasTexture) { if (description.hasAlpha8Texture) { - shader.append(gFS_Main_FetchA8Texture); + if (!description.hasGradient && !description.hasBitmap) { + shader.append(gFS_Main_FetchA8Texture[modulateOp]); + } } else { - shader.append(gFS_Main_FetchTexture); + shader.append(gFS_Main_FetchTexture[modulateOp]); } } else { - shader.append(gFS_Main_FetchColor); + if ((!description.hasGradient && !description.hasBitmap) || description.modulate) { + shader.append(gFS_Main_FetchColor); + } } if (description.hasGradient) { shader.append(gFS_Main_FetchGradient[description.gradientType]); @@ -387,17 +513,20 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti } // 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); + shader.append(gFS_Main_BlendShaders_Modulate[op]); } else { if (description.hasGradient) { - shader.append(gFS_Main_GradientShader_Modulate); + int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp; + shader.append(gFS_Main_GradientShader_Modulate[op]); } else if (description.hasBitmap) { - shader.append(gFS_Main_BitmapShader_Modulate); + int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp; + shader.append(gFS_Main_BitmapShader_Modulate[op]); } } // Apply the color op if needed |