color blindness enhancement
This is an attempt at improving the experience of
users with color vision impairement.
At this time this feature can only be enabled for
debugging:
adb shell service call SurfaceFlinger 1014 i32 PARAM
with PARAM:
0 : disabled
1 : protanomaly/protanopia simulation
2 : deuteranomaly/deuteranopia simulation
3 : tritanopia/tritanomaly simulation
11, 12, 13: same as above w/ attempted correction/enhancement
The enhancement algorithm tries to spread the "error"
such that tones that would otherwise appear similar can be
distinguished.
Bug: 9465644
Change-Id: I860f7eed0cb81f54ef9cf24ad78155b6395ade48
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index 62d2eab..09b0ddc 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -96,7 +96,9 @@
.set(Key::BLEND_MASK,
description.mPremultipliedAlpha ? Key::BLEND_PREMULT : Key::BLEND_NORMAL)
.set(Key::OPACITY_MASK,
- description.mOpaque ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT);
+ description.mOpaque ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT)
+ .set(Key::COLOR_MATRIX_MASK,
+ description.mColorMatrixEnabled ? Key::COLOR_MATRIX_ON : Key::COLOR_MATRIX_OFF);
return needs;
}
@@ -139,6 +141,9 @@
if (needs.hasPlaneAlpha()) {
fs << "uniform float alphaPlane;";
}
+ if (needs.hasColorMatrix()) {
+ fs << "uniform mat4 colorMatrix;";
+ }
fs << "void main(void) {" << indent;
if (needs.isTexturing()) {
fs << "gl_FragColor = texture2D(sampler, outTexCoords);";
@@ -157,6 +162,21 @@
fs << "gl_FragColor.a *= alphaPlane;";
}
}
+
+ if (needs.hasColorMatrix()) {
+ if (!needs.isOpaque() && needs.isPremultiplied()) {
+ // un-premultiply if needed before linearization
+ fs << "gl_FragColor.rgb = gl_FragColor.rgb/gl_FragColor.a;";
+ }
+ fs << "gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(2.2));";
+ fs << "gl_FragColor = colorMatrix*gl_FragColor;";
+ fs << "gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(1.0 / 2.2));";
+ if (!needs.isOpaque() && needs.isPremultiplied()) {
+ // and re-premultiply if needed after gamma correction
+ fs << "gl_FragColor.rgb = gl_FragColor.rgb*gl_FragColor.a;";
+ }
+ }
+
fs << dedent << "}";
return fs.getString();
}