blob: 29606347f00972baddf6ef8c40e485557285a0ac [file] [log] [blame]
Ahan Wu67e7f102019-01-14 20:38:14 +08001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.systemui.glwallpaper;
18
19import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;
20import static android.opengl.GLES20.glClear;
21import static android.opengl.GLES20.glClearColor;
22import static android.opengl.GLES20.glUniform1f;
23import static android.opengl.GLES20.glViewport;
24
25import android.app.WallpaperManager;
26import android.content.Context;
Ahan Wu0e174802019-07-23 20:41:52 +080027import android.content.res.Configuration;
Ahan Wu67e7f102019-01-14 20:38:14 +080028import android.graphics.Bitmap;
29import android.graphics.Rect;
Ahan Wu67e7f102019-01-14 20:38:14 +080030import android.util.Log;
Ahan Wuc8363352019-03-07 17:35:27 +080031import android.util.MathUtils;
Ahan Wufa42c512019-05-15 19:52:51 +080032import android.util.Size;
Ahan Wue16e1fa2019-05-29 18:39:33 +080033import android.view.DisplayInfo;
34import android.view.WindowManager;
Ahan Wu67e7f102019-01-14 20:38:14 +080035
Ahan Wu67e7f102019-01-14 20:38:14 +080036import com.android.systemui.R;
37
Ahan Wu76884242019-05-22 20:04:23 +080038import java.io.FileDescriptor;
39import java.io.PrintWriter;
40
Ahan Wu67e7f102019-01-14 20:38:14 +080041/**
42 * A GL renderer for image wallpaper.
43 */
Ahan Wufa42c512019-05-15 19:52:51 +080044public class ImageWallpaperRenderer implements GLWallpaperRenderer,
45 ImageRevealHelper.RevealStateListener {
Ahan Wu67e7f102019-01-14 20:38:14 +080046 private static final String TAG = ImageWallpaperRenderer.class.getSimpleName();
Ahan Wue16e1fa2019-05-29 18:39:33 +080047 private static final float SCALE_VIEWPORT_MIN = 1f;
48 private static final float SCALE_VIEWPORT_MAX = 1.1f;
Ahan Wu67e7f102019-01-14 20:38:14 +080049
50 private final WallpaperManager mWallpaperManager;
51 private final ImageGLProgram mProgram;
52 private final ImageGLWallpaper mWallpaper;
53 private final ImageProcessHelper mImageProcessHelper;
54 private final ImageRevealHelper mImageRevealHelper;
Ahan Wu67e7f102019-01-14 20:38:14 +080055
Ahan Wufa42c512019-05-15 19:52:51 +080056 private SurfaceProxy mProxy;
Ahan Wue16e1fa2019-05-29 18:39:33 +080057 private final Rect mScissor;
58 private final Rect mSurfaceSize = new Rect();
59 private final Rect mViewport = new Rect();
Ahan Wu48ebbd72019-03-12 20:59:13 +080060 private Bitmap mBitmap;
Ahan Wue16e1fa2019-05-29 18:39:33 +080061 private boolean mScissorMode;
62 private float mXOffset;
63 private float mYOffset;
Ahan Wu48ebbd72019-03-12 20:59:13 +080064
Ahan Wufa42c512019-05-15 19:52:51 +080065 public ImageWallpaperRenderer(Context context, SurfaceProxy proxy) {
Ahan Wu67e7f102019-01-14 20:38:14 +080066 mWallpaperManager = context.getSystemService(WallpaperManager.class);
67 if (mWallpaperManager == null) {
68 Log.w(TAG, "WallpaperManager not available");
69 }
70
Ahan Wue16e1fa2019-05-29 18:39:33 +080071 DisplayInfo displayInfo = new DisplayInfo();
72 WindowManager wm = context.getSystemService(WindowManager.class);
73 wm.getDefaultDisplay().getDisplayInfo(displayInfo);
Ahan Wu0e174802019-07-23 20:41:52 +080074
75 // We only do transition in portrait currently, b/137962047.
76 int orientation = context.getResources().getConfiguration().orientation;
77 if (orientation == Configuration.ORIENTATION_PORTRAIT) {
78 mScissor = new Rect(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
79 } else {
80 mScissor = new Rect(0, 0, displayInfo.logicalHeight, displayInfo.logicalWidth);
81 }
Ahan Wue16e1fa2019-05-29 18:39:33 +080082
Ahan Wufa42c512019-05-15 19:52:51 +080083 mProxy = proxy;
Ahan Wu67e7f102019-01-14 20:38:14 +080084 mProgram = new ImageGLProgram(context);
85 mWallpaper = new ImageGLWallpaper(mProgram);
86 mImageProcessHelper = new ImageProcessHelper();
87 mImageRevealHelper = new ImageRevealHelper(this);
Ahan Wu67e7f102019-01-14 20:38:14 +080088
Ahan Wufa42c512019-05-15 19:52:51 +080089 if (loadBitmap()) {
Ahan Wu330bc602019-04-25 15:04:39 +080090 // Compute threshold of the image, this is an async work.
91 mImageProcessHelper.start(mBitmap);
Ahan Wu67e7f102019-01-14 20:38:14 +080092 }
93 }
94
95 @Override
Ahan Wufa42c512019-05-15 19:52:51 +080096 public void onSurfaceCreated() {
Ahan Wu67e7f102019-01-14 20:38:14 +080097 glClearColor(0f, 0f, 0f, 1.0f);
98 mProgram.useGLProgram(
99 R.raw.image_wallpaper_vertex_shader, R.raw.image_wallpaper_fragment_shader);
Ahan Wufa42c512019-05-15 19:52:51 +0800100
101 if (!loadBitmap()) {
102 Log.w(TAG, "reload bitmap failed!");
103 }
104
Ahan Wu48ebbd72019-03-12 20:59:13 +0800105 mWallpaper.setup(mBitmap);
106 mBitmap = null;
Ahan Wu67e7f102019-01-14 20:38:14 +0800107 }
108
Ahan Wufa42c512019-05-15 19:52:51 +0800109 private boolean loadBitmap() {
110 if (mWallpaperManager != null && mBitmap == null) {
111 mBitmap = mWallpaperManager.getBitmap();
112 mWallpaperManager.forgetLoadedWallpaper();
113 if (mBitmap != null) {
Ahan Wuc6e84a12019-09-06 19:19:05 +0800114 float scale = (float) mScissor.height() / mBitmap.getHeight();
115 int surfaceHeight = Math.max(mScissor.height(), mBitmap.getHeight());
116 int surfaceWidth = scale > 1f
117 ? Math.round(mBitmap.getWidth() * scale)
118 : mBitmap.getWidth();
119 mSurfaceSize.set(0, 0, surfaceWidth, surfaceHeight);
Ahan Wufa42c512019-05-15 19:52:51 +0800120 }
Ahan Wu67e7f102019-01-14 20:38:14 +0800121 }
Ahan Wufa42c512019-05-15 19:52:51 +0800122 return mBitmap != null;
Ahan Wu67e7f102019-01-14 20:38:14 +0800123 }
124
125 @Override
Ahan Wufa42c512019-05-15 19:52:51 +0800126 public void onSurfaceChanged(int width, int height) {
127 glViewport(0, 0, width, height);
128 }
129
130 @Override
131 public void onDrawFrame() {
Ahan Wu330bc602019-04-25 15:04:39 +0800132 float threshold = mImageProcessHelper.getThreshold();
Ahan Wu67e7f102019-01-14 20:38:14 +0800133 float reveal = mImageRevealHelper.getReveal();
134
Ahan Wu67e7f102019-01-14 20:38:14 +0800135 glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_AOD2OPACITY), 1);
Ahan Wu330bc602019-04-25 15:04:39 +0800136 glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_PER85), threshold);
Ahan Wu67e7f102019-01-14 20:38:14 +0800137 glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_REVEAL), reveal);
138
Ahan Wue16e1fa2019-05-29 18:39:33 +0800139 glClear(GL_COLOR_BUFFER_BIT);
140 // We only need to scale viewport while doing transition.
141 if (mScissorMode) {
142 scaleViewport(reveal);
143 } else {
144 glViewport(0, 0, mSurfaceSize.width(), mSurfaceSize.height());
145 }
Ahan Wu67e7f102019-01-14 20:38:14 +0800146 mWallpaper.useTexture();
147 mWallpaper.draw();
148 }
149
Ahan Wufa42c512019-05-15 19:52:51 +0800150 @Override
151 public void updateAmbientMode(boolean inAmbientMode, long duration) {
152 mImageRevealHelper.updateAwake(!inAmbientMode, duration);
153 }
154
155 @Override
Ahan Wue16e1fa2019-05-29 18:39:33 +0800156 public void updateOffsets(float xOffset, float yOffset) {
157 mXOffset = xOffset;
158 mYOffset = yOffset;
159 int left = (int) ((mSurfaceSize.width() - mScissor.width()) * xOffset);
160 int right = left + mScissor.width();
161 mScissor.set(left, mScissor.top, right, mScissor.bottom);
162 }
163
164 @Override
Ahan Wufa42c512019-05-15 19:52:51 +0800165 public Size reportSurfaceSize() {
166 return new Size(mSurfaceSize.width(), mSurfaceSize.height());
167 }
168
169 @Override
170 public void finish() {
171 mProxy = null;
172 }
173
Ahan Wuc8363352019-03-07 17:35:27 +0800174 private void scaleViewport(float reveal) {
Ahan Wue16e1fa2019-05-29 18:39:33 +0800175 int left = mScissor.left;
176 int top = mScissor.top;
177 int width = mScissor.width();
178 int height = mScissor.height();
Ahan Wuc8363352019-03-07 17:35:27 +0800179 // Interpolation between SCALE_VIEWPORT_MAX and SCALE_VIEWPORT_MIN by reveal.
Ahan Wue16e1fa2019-05-29 18:39:33 +0800180 float vpScaled = MathUtils.lerp(SCALE_VIEWPORT_MIN, SCALE_VIEWPORT_MAX, reveal);
Ahan Wuc8363352019-03-07 17:35:27 +0800181 // Calculate the offset amount from the lower left corner.
Ahan Wue16e1fa2019-05-29 18:39:33 +0800182 float offset = (SCALE_VIEWPORT_MIN - vpScaled) / 2;
Ahan Wuc8363352019-03-07 17:35:27 +0800183 // Change the viewport.
Ahan Wue16e1fa2019-05-29 18:39:33 +0800184 mViewport.set((int) (left + width * offset), (int) (top + height * offset),
Ahan Wufa42c512019-05-15 19:52:51 +0800185 (int) (width * vpScaled), (int) (height * vpScaled));
Ahan Wue16e1fa2019-05-29 18:39:33 +0800186 glViewport(mViewport.left, mViewport.top, mViewport.right, mViewport.bottom);
Ahan Wu67e7f102019-01-14 20:38:14 +0800187 }
188
189 @Override
190 public void onRevealStateChanged() {
Ahan Wufa42c512019-05-15 19:52:51 +0800191 mProxy.requestRender();
Ahan Wu67e7f102019-01-14 20:38:14 +0800192 }
193
Ahan Wufa42c512019-05-15 19:52:51 +0800194 @Override
Ahan Wu0e174802019-07-23 20:41:52 +0800195 public void onRevealStart(boolean animate) {
196 if (animate) {
197 mScissorMode = true;
198 // Use current display area of texture.
199 mWallpaper.adjustTextureCoordinates(mSurfaceSize, mScissor, mXOffset, mYOffset);
200 }
Ahan Wufa42c512019-05-15 19:52:51 +0800201 mProxy.preRender();
202 }
203
204 @Override
205 public void onRevealEnd() {
Ahan Wu0e174802019-07-23 20:41:52 +0800206 if (mScissorMode) {
207 mScissorMode = false;
208 // reset texture coordinates to use full texture.
209 mWallpaper.adjustTextureCoordinates(null, null, 0, 0);
210 // We need draw full texture back before finishing render.
211 mProxy.requestRender();
212 }
Ahan Wufa42c512019-05-15 19:52:51 +0800213 mProxy.postRender();
Ahan Wu67e7f102019-01-14 20:38:14 +0800214 }
Ahan Wu76884242019-05-22 20:04:23 +0800215
216 @Override
217 public void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) {
218 out.print(prefix); out.print("mProxy="); out.print(mProxy);
219 out.print(prefix); out.print("mSurfaceSize="); out.print(mSurfaceSize);
Ahan Wue16e1fa2019-05-29 18:39:33 +0800220 out.print(prefix); out.print("mScissor="); out.print(mScissor);
221 out.print(prefix); out.print("mViewport="); out.print(mViewport);
222 out.print(prefix); out.print("mScissorMode="); out.print(mScissorMode);
223 out.print(prefix); out.print("mXOffset="); out.print(mXOffset);
224 out.print(prefix); out.print("mYOffset="); out.print(mYOffset);
Ahan Wu76884242019-05-22 20:04:23 +0800225 out.print(prefix); out.print("threshold="); out.print(mImageProcessHelper.getThreshold());
Ahan Wue16e1fa2019-05-29 18:39:33 +0800226 mWallpaper.dump(prefix, fd, out, args);
Ahan Wu76884242019-05-22 20:04:23 +0800227 }
Ahan Wu67e7f102019-01-14 20:38:14 +0800228}