diff options
5 files changed, 102 insertions, 8 deletions
diff --git a/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl b/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl index e4b6e0778664..e9c838999dda 100644 --- a/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl +++ b/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl @@ -1,11 +1,54 @@ precision mediump float; +#define GAMMA 2.2 +#define INV_GAMMA 1.0 / GAMMA // The actual wallpaper texture. uniform sampler2D uTexture; +uniform float uExposure; varying vec2 vTextureCoordinates; +// Following the Rec. ITU-R BT.709. +float relativeLuminance(vec3 color) { + return 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b; +} + +// Adjusts the exposure of some luminance value. +float relativeExposureCompensation(in float lum, in float ev) { + return lum * pow(2.0, ev); +} + +vec4 srgbToLinear(in vec4 color) { + vec4 linearColor = vec4(color); + linearColor.rgb = pow(linearColor.rgb, vec3(GAMMA)); + return linearColor; +} + +vec4 linearToSrgb(in vec4 color) { + vec4 srgbColor = vec4(color); + srgbColor.rgb = pow(srgbColor.rgb, vec3(INV_GAMMA)); + return srgbColor; +} + +/* + * Normalizes a value inside a range to a normalized range [0,1]. + */ +float normalizedRange(in float value, in float inMin, in float inMax) { + float valueClamped = clamp(value, inMin, inMax); + return (value - inMin) / (inMax - inMin); +} + void main() { - // gets the pixel value of the wallpaper for this uv coordinates on screen. - gl_FragColor = texture2D(uTexture, vTextureCoordinates); + // Gets the pixel value of the wallpaper for this uv coordinates on screen. + vec4 color = srgbToLinear(texture2D(uTexture, vTextureCoordinates)); + float lum = relativeLuminance(color.rgb); + + // Transform it using the S curve created by the smoothstep. This will increase the contrast. + lum = smoothstep(0., 1., lum) + 0.001; + + lum = relativeExposureCompensation(lum, mix(-15., 10., uExposure)); + lum = mix(clamp(lum, 0.0, 1.0), 1.0, normalizedRange(uExposure, 0.55, 1.0)); + color.rgb *= lum; + + gl_FragColor = linearToSrgb(color); }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java index 7966b388bc4f..8b68ae959ebf 100644 --- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java @@ -29,6 +29,7 @@ import android.util.ArraySet; import android.util.Log; import android.util.MathUtils; import android.util.Size; +import android.view.Choreographer; import android.view.SurfaceHolder; import android.view.WindowManager; @@ -37,6 +38,7 @@ import androidx.annotation.NonNull; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.glwallpaper.EglHelper; import com.android.systemui.glwallpaper.ImageWallpaperRenderer; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -53,10 +55,11 @@ public class ImageWallpaper extends WallpaperService { private static final String TAG = ImageWallpaper.class.getSimpleName(); // We delayed destroy render context that subsequent render requests have chance to cancel it. // This is to avoid destroying then recreating render context in a very short time. - private static final int DELAY_FINISH_RENDERING = 1000; + private static final int DELAY_FINISH_RENDERING = 3000; private static final @android.annotation.NonNull RectF LOCAL_COLOR_BOUNDS = new RectF(0, 0, 1, 1); private static final boolean DEBUG = false; + private final StatusBarStateController mStatusBarStateController; private final ArrayList<RectF> mLocalColorsToAdd = new ArrayList<>(); private final ArraySet<RectF> mColorAreas = new ArraySet<>(); private float mShift; @@ -66,8 +69,9 @@ public class ImageWallpaper extends WallpaperService { private Bitmap mMiniBitmap; @Inject - public ImageWallpaper() { + public ImageWallpaper(StatusBarStateController statusBarStateController) { super(); + mStatusBarStateController = statusBarStateController; } @Override @@ -90,7 +94,9 @@ public class ImageWallpaper extends WallpaperService { mMiniBitmap = null; } - class GLEngine extends Engine { + + class GLEngine extends Engine implements StatusBarStateController.StateListener, + Choreographer.FrameCallback { // Surface is rejected if size below a threshold on some devices (ie. 8px on elfin) // set min to 64 px (CTS covers this), please refer to ag/4867989 for detail. @VisibleForTesting @@ -101,11 +107,12 @@ public class ImageWallpaper extends WallpaperService { private ImageWallpaperRenderer mRenderer; private EglHelper mEglHelper; private final Runnable mFinishRenderingTask = this::finishRendering; - private boolean mNeedRedraw; private int mWidth = 1; private int mHeight = 1; private int mImgWidth = 1; private int mImgHeight = 1; + private volatile float mDozeAmount; + private volatile boolean mNewDozeValue = false; GLEngine() { } @@ -130,8 +137,14 @@ public class ImageWallpaper extends WallpaperService { mWidth = window.width(); mMiniBitmap = null; if (mWorker != null && mWorker.getThreadHandler() != null) { - mWorker.getThreadHandler().post(this::updateMiniBitmap); + mWorker.getThreadHandler().post(() -> { + updateMiniBitmap(); + Choreographer.getInstance().postFrameCallback(GLEngine.this); + }); } + + mDozeAmount = mStatusBarStateController.getDozeAmount(); + mStatusBarStateController.addCallback(this); } EglHelper getEglHelperInstance() { @@ -210,11 +223,14 @@ public class ImageWallpaper extends WallpaperService { public void onDestroy() { mMiniBitmap = null; mWorker.getThreadHandler().post(() -> { + Choreographer.getInstance().removeFrameCallback(this); mRenderer.finish(); mRenderer = null; mEglHelper.finish(); mEglHelper = null; }); + + mStatusBarStateController.removeCallback(this); } @Override @@ -323,9 +339,16 @@ public class ImageWallpaper extends WallpaperService { @Override public void onSurfaceRedrawNeeded(SurfaceHolder holder) { if (mWorker == null) return; + mDozeAmount = mStatusBarStateController.getDozeAmount(); mWorker.getThreadHandler().post(this::drawFrame); } + @Override + public void onDozeAmountChanged(float linear, float eased) { + mDozeAmount = linear; + mNewDozeValue = true; + } + private void drawFrame() { preRender(); requestRender(); @@ -381,6 +404,7 @@ public class ImageWallpaper extends WallpaperService { && frame.width() > 0 && frame.height() > 0; if (readyToRender) { + mRenderer.setExposureValue(1 - mDozeAmount); mRenderer.onDrawFrame(); if (!mEglHelper.swapBuffer()) { Log.e(TAG, "drawFrame failed!"); @@ -438,5 +462,14 @@ public class ImageWallpaper extends WallpaperService { mEglHelper.dump(prefix, fd, out, args); mRenderer.dump(prefix, fd, out, args); } + + @Override + public void doFrame(long frameTimeNanos) { + if (mNewDozeValue) { + drawFrame(); + mNewDozeValue = false; + } + Choreographer.getInstance().postFrameCallback(this); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java index 1a53c28c0fc5..58c41d582413 100644 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java @@ -29,6 +29,7 @@ import static android.opengl.GLES20.glDrawArrays; import static android.opengl.GLES20.glEnableVertexAttribArray; import static android.opengl.GLES20.glGenTextures; import static android.opengl.GLES20.glTexParameteri; +import static android.opengl.GLES20.glUniform1f; import static android.opengl.GLES20.glUniform1i; import static android.opengl.GLES20.glVertexAttribPointer; @@ -52,6 +53,7 @@ class ImageGLWallpaper { private static final String A_POSITION = "aPosition"; private static final String A_TEXTURE_COORDINATES = "aTextureCoordinates"; private static final String U_TEXTURE = "uTexture"; + private static final String U_EXPOSURE = "uExposure"; private static final int POSITION_COMPONENT_COUNT = 2; private static final int TEXTURE_COMPONENT_COUNT = 2; private static final int BYTES_PER_FLOAT = 4; @@ -83,6 +85,7 @@ class ImageGLWallpaper { private int mAttrPosition; private int mAttrTextureCoordinates; private int mUniTexture; + private int mUniExposure; private int mTextureId; ImageGLWallpaper(ImageGLProgram program) { @@ -125,6 +128,7 @@ class ImageGLWallpaper { private void setupUniforms() { mUniTexture = mProgram.getUniformHandle(U_TEXTURE); + mUniExposure = mProgram.getUniformHandle(U_EXPOSURE); } void draw() { @@ -171,6 +175,10 @@ class ImageGLWallpaper { glUniform1i(mUniTexture, 0); } + void setExposureValue(float exposureValue) { + glUniform1f(mUniExposure, exposureValue); + } + /** * Called to dump current state. * @param prefix prefix. diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java index 01a353ce8f1f..cdf88f3898bb 100644 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java +++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java @@ -46,6 +46,7 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer { private final ImageGLWallpaper mWallpaper; private final Rect mSurfaceSize = new Rect(); private final WallpaperTexture mTexture; + private float mExposureValue; public ImageWallpaperRenderer(Context context) { final WallpaperManager wpm = context.getSystemService(WallpaperManager.class); @@ -66,6 +67,13 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer { mTexture.use(c); } + /** + * @hide + */ + public void setExposureValue(float exposureValue) { + mExposureValue = exposureValue; + } + @Override public boolean isWcgContent() { return mTexture.isWcgContent(); @@ -94,6 +102,7 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer { public void onDrawFrame() { glClear(GL_COLOR_BUFFER_BIT); glViewport(0, 0, mSurfaceSize.width(), mSurfaceSize.height()); + mWallpaper.setExposureValue(mExposureValue); mWallpaper.useTexture(); mWallpaper.draw(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java b/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java index e1ddaada44cf..daa896cc6a8b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java @@ -41,6 +41,7 @@ import android.view.DisplayInfo; import android.view.SurfaceHolder; import com.android.systemui.glwallpaper.ImageWallpaperRenderer; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import org.junit.Before; import org.junit.Ignore; @@ -99,7 +100,7 @@ public class ImageWallpaperTest extends SysuiTestCase { } private ImageWallpaper createImageWallpaper() { - return new ImageWallpaper() { + return new ImageWallpaper(mock(StatusBarStateController.class)) { @Override public Engine onCreateEngine() { return new GLEngine(mHandler) { |