Skip to content

Commit

Permalink
display: Render screen-off fade animation in linear sRGB space
Browse files Browse the repository at this point in the history
The sRGB transfer function is a piecewise function with linear and gamma
2.4 parts, not involving cosine or other magic constants.

Fade colors in linear sRGB instead of non-linear sRGB + magic gamma to
minimize color distortion as the animation progresses.

Change-Id: I57db834f938cc63b7298af1c9dfe8c284dc6abe2
  • Loading branch information
kdrag0n committed Jun 7, 2022
1 parent 45341c8 commit 7234d99
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 17 deletions.
34 changes: 28 additions & 6 deletions core/res/res/raw/color_fade_frag.frag
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,34 @@
precision mediump float;
uniform samplerExternalOES texUnit;
uniform float opacity;
uniform float gamma;
varying vec2 UV;

void main()
{
vec4 color = texture2D(texUnit, UV);
vec3 rgb = pow(color.rgb * opacity, vec3(gamma));
gl_FragColor = vec4(rgb, 1.0);
vec3 mixBvec3(vec3 a, vec3 b, bvec3 sel) {
return vec3(
sel.x ? b.x : a.x,
sel.y ? b.y : a.y,
sel.z ? b.z : a.z
);
}

vec3 srgbTransfer(vec3 c) {
vec3 gamma = 1.055 * pow(c, vec3(1.0/2.4)) - 0.055;
vec3 linear = 12.92 * c;
bvec3 selectParts = lessThan(c, vec3(0.0031308));
return mixBvec3(gamma, linear, selectParts);
}

vec3 srgbTransferInv(vec3 c) {
vec3 gamma = pow((c + 0.055)/1.055, vec3(2.4));
vec3 linear = c / 12.92;
bvec3 selectParts = lessThan(c, vec3(0.04045));
return mixBvec3(gamma, linear, selectParts);
}

void main() {
vec3 inRgb = srgbTransferInv(texture2D(texUnit, UV).rgb);
vec3 fade = inRgb * opacity * opacity;
vec3 outRgb = srgbTransfer(fade);

gl_FragColor = vec4(outRgb, 1.0);
}
15 changes: 4 additions & 11 deletions services/core/java/com/android/server/display/ColorFade.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ final class ColorFade {
private final float mProjMatrix[] = new float[16];
private final int[] mGLBuffers = new int[2];
private int mTexCoordLoc, mVertexLoc, mTexUnitLoc, mProjMatrixLoc, mTexMatrixLoc;
private int mOpacityLoc, mGammaLoc;
private int mOpacityLoc;
private int mProgram;

// Vertex and corresponding texture coordinates.
Expand Down Expand Up @@ -288,7 +288,6 @@ private boolean initGLShaders(Context context) {
mTexMatrixLoc = GLES20.glGetUniformLocation(mProgram, "tex_matrix");

mOpacityLoc = GLES20.glGetUniformLocation(mProgram, "opacity");
mGammaLoc = GLES20.glGetUniformLocation(mProgram, "gamma");
mTexUnitLoc = GLES20.glGetUniformLocation(mProgram, "texUnit");

GLES20.glUseProgram(mProgram);
Expand Down Expand Up @@ -432,12 +431,7 @@ public boolean draw(float level) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

// Draw the frame.
double one_minus_level = 1 - level;
double cos = Math.cos(Math.PI * one_minus_level);
double sign = cos < 0 ? -1 : 1;
float opacity = (float) -Math.pow(one_minus_level, 2) + 1;
float gamma = (float) ((0.5d * sign * Math.pow(cos, 2) + 0.5d) * 0.9d + 0.1d);
drawFaded(opacity, 1.f / gamma);
drawFaded(level);
if (checkGlErrors("drawFrame")) {
return false;
}
Expand All @@ -449,9 +443,9 @@ public boolean draw(float level) {
return showSurface(1.0f);
}

private void drawFaded(float opacity, float gamma) {
private void drawFaded(float opacity) {
if (DEBUG) {
Slog.d(TAG, "drawFaded: opacity=" + opacity + ", gamma=" + gamma);
Slog.d(TAG, "drawFaded: opacity=" + opacity);
}
// Use shaders
GLES20.glUseProgram(mProgram);
Expand All @@ -460,7 +454,6 @@ private void drawFaded(float opacity, float gamma) {
GLES20.glUniformMatrix4fv(mProjMatrixLoc, 1, false, mProjMatrix, 0);
GLES20.glUniformMatrix4fv(mTexMatrixLoc, 1, false, mTexMatrix, 0);
GLES20.glUniform1f(mOpacityLoc, opacity);
GLES20.glUniform1f(mGammaLoc, gamma);

// Use textures
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
Expand Down

0 comments on commit 7234d99

Please sign in to comment.