diff options
| -rw-r--r-- | libs/hwui/GlopBuilder.cpp | 1 | ||||
| -rw-r--r-- | libs/hwui/Program.h | 6 | ||||
| -rw-r--r-- | libs/hwui/ProgramCache.cpp | 174 | ||||
| -rw-r--r-- | libs/hwui/Texture.cpp | 4 | ||||
| -rw-r--r-- | libs/hwui/Texture.h | 5 |
5 files changed, 57 insertions, 133 deletions
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp index 8a6e038d8e0d..5cf52c69f0fd 100644 --- a/libs/hwui/GlopBuilder.cpp +++ b/libs/hwui/GlopBuilder.cpp @@ -605,6 +605,7 @@ void GlopBuilder::build() { } else { mDescription.hasExternalTexture = true; } + mDescription.hasLinearTexture = mOutGlop->fill.texture.texture->isLinear(); } mDescription.hasColors = mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Color; diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h index e70982f5444a..5c8f8e93fa3d 100644 --- a/libs/hwui/Program.h +++ b/libs/hwui/Program.h @@ -87,6 +87,7 @@ namespace uirenderer { #define PROGRAM_HAS_ROUND_RECT_CLIP 43 #define PROGRAM_HAS_GAMMA_CORRECTION 44 +#define PROGRAM_HAS_LINEAR_TEXTURE 45 /////////////////////////////////////////////////////////////////////////////// // Types @@ -162,7 +163,10 @@ struct ProgramDescription { bool hasDebugHighlight; bool hasRoundRectClip; + // Extra gamma correction used for text bool hasGammaCorrection; + // Set when sampling an image in linear space + bool hasLinearTexture; /** * Resets this description. All fields are reset back to the default @@ -205,6 +209,7 @@ struct ProgramDescription { hasRoundRectClip = false; hasGammaCorrection = false; + hasLinearTexture = false; } /** @@ -275,6 +280,7 @@ struct ProgramDescription { if (hasDebugHighlight) key |= programid(0x1) << PROGRAM_HAS_DEBUG_HIGHLIGHT; if (hasRoundRectClip) key |= programid(0x1) << PROGRAM_HAS_ROUND_RECT_CLIP; if (hasGammaCorrection) key |= programid(0x1) << PROGRAM_HAS_GAMMA_CORRECTION; + if (hasLinearTexture) key |= programid(0x1) << PROGRAM_HAS_LINEAR_TEXTURE; return key; } diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index 42ef76296006..00de9924ace1 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -161,9 +161,35 @@ const char* gFS_Uniforms_HasRoundRectClip = "uniform vec4 roundRectInnerRectLTRB;\n" "uniform float roundRectRadius;\n"; +const char* gFS_OETF[2] = { + "\nvec4 OETF(const vec4 linear) {\n" + " return linear;\n" + "}\n", + // We expect linear data to be scRGB so we mirror the gamma function + "\nvec4 OETF(const vec4 linear) {" + " return vec4(sign(linear.rgb) * OETF_sRGB(abs(linear.rgb)), linear.a);\n" + "}\n", +}; + +const char* gFS_Transfer_Functions = R"__SHADER__( + float OETF_sRGB(const float linear) { + // IEC 61966-2-1:1999 + return linear <= 0.0031308 ? linear * 12.92 : (pow(linear, 1.0 / 2.4) * 1.055) - 0.055; + } + + vec3 OETF_sRGB(const vec3 linear) { + return vec3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b)); + } + + float EOTF_sRGB(float srgb) { + // IEC 61966-2-1:1999 + return srgb <= 0.04045 ? srgb / 12.92 : pow((srgb + 0.055) / 1.055, 2.4); + } +)__SHADER__"; + // Dithering must be done in the quantization space // When we are writing to an sRGB framebuffer, we must do the following: -// EOCF(OECF(color) + dither) +// EOTF(OETF(color) + dither) // The dithering pattern is generated with a triangle noise generator in the range [-0.0,1.0] // TODO: Handle linear fp16 render targets const char* gFS_Gradient_Functions = R"__SHADER__( @@ -173,20 +199,6 @@ const char* gFS_Gradient_Functions = R"__SHADER__( highp float xy = p.x * p.y; return fract(xy * 95.4307) + fract(xy * 75.04961) - 1.0; } - - float OECF_sRGB(const float linear) { - // IEC 61966-2-1:1999 - return linear <= 0.0031308 ? linear * 12.92 : (pow(linear, 1.0 / 2.4) * 1.055) - 0.055; - } - - vec3 OECF_sRGB(const vec3 linear) { - return vec3(OECF_sRGB(linear.r), OECF_sRGB(linear.g), OECF_sRGB(linear.b)); - } - - float EOCF_sRGB(float srgb) { - // IEC 61966-2-1:1999 - return srgb <= 0.04045 ? srgb / 12.92 : pow((srgb + 0.055) / 1.055, 2.4); - } )__SHADER__"; const char* gFS_Gradient_Preamble[2] = { // Linear framebuffer @@ -195,8 +207,8 @@ const char* gFS_Gradient_Preamble[2] = { "}\n" "\nvec4 gammaMix(const vec4 a, const vec4 b, float v) {\n" " vec4 c = mix(a, b, v);\n" - " c.a = EOCF_sRGB(c.a);\n" // This is technically incorrect but preserves compatibility - " return vec4(OECF_sRGB(c.rgb) * c.a, c.a);\n" + " c.a = EOTF_sRGB(c.a);\n" // This is technically incorrect but preserves compatibility + " return vec4(OETF_sRGB(c.rgb) * c.a, c.a);\n" "}\n", // sRGB framebuffer "\nvec4 dither(const vec4 color) {\n" @@ -232,52 +244,6 @@ const char* gFS_Main = const char* gFS_Main_AddDither = " fragColor = dither(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(baseSampler, outTexCoords);\n" - "}\n\n"; -const char* gFS_Fast_SingleModulateTexture = - "\nvoid main(void) {\n" - " gl_FragColor = color.a * texture2D(baseSampler, outTexCoords);\n" - "}\n\n"; -const char* gFS_Fast_SingleA8Texture = - "\nvoid main(void) {\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(baseSampler, outTexCoords).a, GAMMA));\n" - "}\n\n"; -const char* gFS_Fast_SingleModulateA8Texture = - "\nvoid main(void) {\n" - " gl_FragColor = color * texture2D(baseSampler, outTexCoords).a;\n" - "}\n\n"; -const char* gFS_Fast_SingleModulateA8Texture_ApplyGamma = - "\nvoid main(void) {\n" - " gl_FragColor = color * gamma(texture2D(baseSampler, outTexCoords).a, color.rgb);\n" - "}\n\n"; -const char* gFS_Fast_SingleGradient[2] = { - "\nvoid main(void) {\n" - " gl_FragColor = dither(texture2D(gradientSampler, linear));\n" - "}\n\n", - "\nvoid main(void) {\n" - " gl_FragColor = dither(gammaMix(startColor, endColor, clamp(linear, 0.0, 1.0)));\n" - "}\n\n", -}; -const char* gFS_Fast_SingleModulateGradient[2] = { - "\nvoid main(void) {\n" - " gl_FragColor = dither(color.a * texture2D(gradientSampler, linear));\n" - "}\n\n", - "\nvoid main(void) {\n" - " gl_FragColor = dither(color.a * gammaMix(startColor, endColor, clamp(linear, 0.0, 1.0)));\n" - "}\n\n" -}; - // General case const char* gFS_Main_FetchColor = " fragColor = color;\n"; @@ -290,7 +256,7 @@ const char* gFS_Main_ApplyVertexAlphaShadowInterp = " fragColor *= texture2D(baseSampler, vec2(alpha, 0.5)).a;\n"; const char* gFS_Main_FetchTexture[2] = { // Don't modulate - " fragColor = texture2D(baseSampler, outTexCoords);\n", + " fragColor = OETF(texture2D(baseSampler, outTexCoords));\n", // Modulate " fragColor = color * texture2D(baseSampler, outTexCoords);\n" }; @@ -321,9 +287,9 @@ const char* gFS_Main_FetchGradient[6] = { " vec4 gradientColor = gammaMix(startColor, endColor, clamp(index - floor(index), 0.0, 1.0));\n" }; const char* gFS_Main_FetchBitmap = - " vec4 bitmapColor = texture2D(bitmapSampler, outBitmapTexCoords);\n"; + " vec4 bitmapColor = OETF(texture2D(bitmapSampler, outBitmapTexCoords));\n"; const char* gFS_Main_FetchBitmapNpot = - " vec4 bitmapColor = texture2D(bitmapSampler, wrap(outBitmapTexCoords));\n"; + " vec4 bitmapColor = OETF(texture2D(bitmapSampler, wrap(outBitmapTexCoords)));\n"; const char* gFS_Main_BlendShadersBG = " fragColor = blendShaders(gradientColor, bitmapColor)"; const char* gFS_Main_BlendShadersGB = @@ -649,71 +615,6 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti shader.appendFormat(gFS_Gamma_Preamble, Properties::textGamma, 1.0f / Properties::textGamma); } - // Optimization for common cases - if (!description.hasVertexAlpha - && !blendFramebuffer - && !description.hasColors - && description.colorOp == ProgramDescription::ColorFilterMode::None - && !description.hasDebugHighlight - && !description.hasRoundRectClip) { - bool fast = false; - - const bool noShader = !description.hasGradient && !description.hasBitmap; - const bool singleTexture = (description.hasTexture || description.hasExternalTexture) && - !description.hasAlpha8Texture && noShader; - const bool singleA8Texture = description.hasTexture && - description.hasAlpha8Texture && noShader; - const bool singleGradient = !description.hasTexture && !description.hasExternalTexture && - 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) { - if (description.hasGammaCorrection) { - shader.append(gFS_Fast_SingleA8Texture_ApplyGamma); - } else { - shader.append(gFS_Fast_SingleA8Texture); - } - } else { - if (description.hasGammaCorrection) { - shader.append(gFS_Fast_SingleModulateA8Texture_ApplyGamma); - } else { - shader.append(gFS_Fast_SingleModulateA8Texture); - } - } - fast = true; - } else if (singleGradient) { - shader.append(gFS_Gradient_Functions); - shader.append(gFS_Gradient_Preamble[mHasSRGB]); - if (!description.modulate) { - shader.append(gFS_Fast_SingleGradient[description.isSimpleGradient]); - } else { - shader.append(gFS_Fast_SingleModulateGradient[description.isSimpleGradient]); - } - fast = true; - } - - if (fast) { -#if DEBUG_PROGRAMS - PROGRAM_LOGD("*** Fast case:\n"); - PROGRAM_LOGD("*** Generated fragment shader:\n\n"); - printLongString(shader); -#endif - - return shader; - } - } - if (description.hasBitmap) { if (description.isShaderBitmapExternal) { shader.append(gFS_Uniforms_BitmapExternalSampler); @@ -736,6 +637,13 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti if (description.useShaderBasedWrap) { generateTextureWrap(shader, description.bitmapWrapS, description.bitmapWrapT); } + if (description.hasGradient || description.hasLinearTexture) { + shader.append(gFS_Transfer_Functions); + } + if (description.hasBitmap || ((description.hasTexture || description.hasExternalTexture) && + !description.hasAlpha8Texture)) { + shader.append(gFS_OETF[description.hasLinearTexture && !mHasSRGB]); + } if (description.hasGradient) { shader.append(gFS_Gradient_Functions); shader.append(gFS_Gradient_Preamble[mHasSRGB]); @@ -827,10 +735,10 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti // End the shader shader.append(gFS_Footer); -#if DEBUG_PROGRAMS +//#if DEBUG_PROGRAMS PROGRAM_LOGD("*** Generated fragment shader:\n\n"); printLongString(shader); -#endif +//#endif return shader; } diff --git a/libs/hwui/Texture.cpp b/libs/hwui/Texture.cpp index f6850a110286..50af9c8cd711 100644 --- a/libs/hwui/Texture.cpp +++ b/libs/hwui/Texture.cpp @@ -48,6 +48,10 @@ static int bytesPerPixel(GLint glFormat) { } } +bool Texture::isLinear() const { + return mInternalFormat == GL_RGBA16F; +} + void Texture::setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture, bool force) { if (force || wrapS != mWrapS || wrapT != mWrapT) { diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h index b8397ccade9c..ce9d4dc234a8 100644 --- a/libs/hwui/Texture.h +++ b/libs/hwui/Texture.h @@ -128,6 +128,11 @@ public: } /** + * Returns true if this texture uses a linear encoding format. + */ + bool isLinear() const; + + /** * Generation of the backing bitmap, */ uint32_t generation = 0; |