summaryrefslogtreecommitdiff
path: root/libs/hwui/ProgramCache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui/ProgramCache.cpp')
-rw-r--r--libs/hwui/ProgramCache.cpp51
1 files changed, 34 insertions, 17 deletions
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 71076791cf7f..42ef76296006 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -164,24 +164,39 @@ const char* gFS_Uniforms_HasRoundRectClip =
// 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)
-// We approximate the transfer functions with gamma 2.0 to avoid branches and pow()
// 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 =
- "\nfloat triangleNoise(const highp vec2 n) {\n"
- " highp vec2 p = fract(n * vec2(5.3987, 5.4421));\n"
- " p += dot(p.yx, p.xy + vec2(21.5351, 14.3137));\n"
- " highp float xy = p.x * p.y;\n"
- " return fract(xy * 95.4307) + fract(xy * 75.04961) - 1.0;\n"
- "}\n";
+const char* gFS_Gradient_Functions = R"__SHADER__(
+ float triangleNoise(const highp vec2 n) {
+ highp vec2 p = fract(n * vec2(5.3987, 5.4421));
+ p += dot(p.yx, p.xy + vec2(21.5351, 14.3137));
+ 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
"\nvec4 dither(const vec4 color) {\n"
" return vec4(color.rgb + (triangleNoise(gl_FragCoord.xy * screenSize.xy) / 255.0), color.a);\n"
"}\n"
"\nvec4 gammaMix(const vec4 a, const vec4 b, float v) {\n"
- " vec4 c = pow(mix(a, b, v), vec4(vec3(1.0 / 2.2), 1.0));\n"
- " return vec4(c.rgb * c.a, c.a);\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"
"}\n",
// sRGB framebuffer
"\nvec4 dither(const vec4 color) {\n"
@@ -200,13 +215,15 @@ const char* gFS_Gradient_Preamble[2] = {
// The gamma coefficient is chosen to thicken or thin the text accordingly
// The dot product used to compute the luminance could be approximated with
// a simple max(color.r, color.g, color.b)
-const char* gFS_Gamma_Preamble =
- "\n#define GAMMA (%.2f)\n"
- "#define GAMMA_INV (%.2f)\n"
- "\nfloat gamma(float a, const vec3 color) {\n"
- " float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722));\n"
- " return pow(a, luminance < 0.5 ? GAMMA_INV : GAMMA);\n"
- "}\n";
+const char* gFS_Gamma_Preamble = R"__SHADER__(
+ #define GAMMA (%.2f)
+ #define GAMMA_INV (%.2f)
+
+ float gamma(float a, const vec3 color) {
+ float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722));
+ return pow(a, luminance < 0.5 ? GAMMA_INV : GAMMA);
+ }
+)__SHADER__";
const char* gFS_Main =
"\nvoid main(void) {\n"