blob: be6f7bfe25870cffebefc07783280c8971a506cb [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 Wu3573cdd2019-10-04 11:59:10 +080049 private static final boolean DEBUG = true;
Ahan Wu67e7f102019-01-14 20:38:14 +080050
51 private final WallpaperManager mWallpaperManager;
52 private final ImageGLProgram mProgram;
53 private final ImageGLWallpaper mWallpaper;
54 private final ImageProcessHelper mImageProcessHelper;
55 private final ImageRevealHelper mImageRevealHelper;
Ahan Wu67e7f102019-01-14 20:38:14 +080056
Ahan Wufa42c512019-05-15 19:52:51 +080057 private SurfaceProxy mProxy;
Ahan Wue16e1fa2019-05-29 18:39:33 +080058 private final Rect mScissor;
59 private final Rect mSurfaceSize = new Rect();
60 private final Rect mViewport = new Rect();
Ahan Wu48ebbd72019-03-12 20:59:13 +080061 private Bitmap mBitmap;
Ahan Wue16e1fa2019-05-29 18:39:33 +080062 private boolean mScissorMode;
63 private float mXOffset;
64 private float mYOffset;
Ahan Wu48ebbd72019-03-12 20:59:13 +080065
Ahan Wufa42c512019-05-15 19:52:51 +080066 public ImageWallpaperRenderer(Context context, SurfaceProxy proxy) {
Ahan Wu67e7f102019-01-14 20:38:14 +080067 mWallpaperManager = context.getSystemService(WallpaperManager.class);
68 if (mWallpaperManager == null) {
69 Log.w(TAG, "WallpaperManager not available");
70 }
71
Ahan Wue16e1fa2019-05-29 18:39:33 +080072 DisplayInfo displayInfo = new DisplayInfo();
73 WindowManager wm = context.getSystemService(WindowManager.class);
74 wm.getDefaultDisplay().getDisplayInfo(displayInfo);
Ahan Wu0e174802019-07-23 20:41:52 +080075
76 // We only do transition in portrait currently, b/137962047.
77 int orientation = context.getResources().getConfiguration().orientation;
78 if (orientation == Configuration.ORIENTATION_PORTRAIT) {
79 mScissor = new Rect(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
80 } else {
81 mScissor = new Rect(0, 0, displayInfo.logicalHeight, displayInfo.logicalWidth);
82 }
Ahan Wue16e1fa2019-05-29 18:39:33 +080083
Ahan Wufa42c512019-05-15 19:52:51 +080084 mProxy = proxy;
Ahan Wu67e7f102019-01-14 20:38:14 +080085 mProgram = new ImageGLProgram(context);
86 mWallpaper = new ImageGLWallpaper(mProgram);
87 mImageProcessHelper = new ImageProcessHelper();
88 mImageRevealHelper = new ImageRevealHelper(this);
Ahan Wu67e7f102019-01-14 20:38:14 +080089
Ahan Wufa42c512019-05-15 19:52:51 +080090 if (loadBitmap()) {
Ahan Wu330bc602019-04-25 15:04:39 +080091 // Compute threshold of the image, this is an async work.
92 mImageProcessHelper.start(mBitmap);
Ahan Wu67e7f102019-01-14 20:38:14 +080093 }
94 }
95
96 @Override
Ahan Wufa42c512019-05-15 19:52:51 +080097 public void onSurfaceCreated() {
Ahan Wu67e7f102019-01-14 20:38:14 +080098 glClearColor(0f, 0f, 0f, 1.0f);
99 mProgram.useGLProgram(
100 R.raw.image_wallpaper_vertex_shader, R.raw.image_wallpaper_fragment_shader);
Ahan Wufa42c512019-05-15 19:52:51 +0800101
102 if (!loadBitmap()) {
103 Log.w(TAG, "reload bitmap failed!");
104 }
105
Ahan Wu48ebbd72019-03-12 20:59:13 +0800106 mWallpaper.setup(mBitmap);
107 mBitmap = null;
Ahan Wu67e7f102019-01-14 20:38:14 +0800108 }
109
Ahan Wufa42c512019-05-15 19:52:51 +0800110 private boolean loadBitmap() {
Ahan Wu3573cdd2019-10-04 11:59:10 +0800111 if (DEBUG) {
112 Log.d(TAG, "loadBitmap: mBitmap=" + mBitmap);
113 }
Ahan Wufa42c512019-05-15 19:52:51 +0800114 if (mWallpaperManager != null && mBitmap == null) {
115 mBitmap = mWallpaperManager.getBitmap();
116 mWallpaperManager.forgetLoadedWallpaper();
117 if (mBitmap != null) {
Ahan Wuc6e84a12019-09-06 19:19:05 +0800118 float scale = (float) mScissor.height() / mBitmap.getHeight();
119 int surfaceHeight = Math.max(mScissor.height(), mBitmap.getHeight());
120 int surfaceWidth = scale > 1f
121 ? Math.round(mBitmap.getWidth() * scale)
122 : mBitmap.getWidth();
123 mSurfaceSize.set(0, 0, surfaceWidth, surfaceHeight);
Ahan Wufa42c512019-05-15 19:52:51 +0800124 }
Ahan Wu67e7f102019-01-14 20:38:14 +0800125 }
Ahan Wu3573cdd2019-10-04 11:59:10 +0800126 if (DEBUG) {
127 Log.d(TAG, "loadBitmap done, surface size=" + mSurfaceSize);
128 }
Ahan Wufa42c512019-05-15 19:52:51 +0800129 return mBitmap != null;
Ahan Wu67e7f102019-01-14 20:38:14 +0800130 }
131
132 @Override
Ahan Wufa42c512019-05-15 19:52:51 +0800133 public void onSurfaceChanged(int width, int height) {
134 glViewport(0, 0, width, height);
135 }
136
137 @Override
138 public void onDrawFrame() {
Ahan Wu330bc602019-04-25 15:04:39 +0800139 float threshold = mImageProcessHelper.getThreshold();
Ahan Wu67e7f102019-01-14 20:38:14 +0800140 float reveal = mImageRevealHelper.getReveal();
141
Ahan Wu67e7f102019-01-14 20:38:14 +0800142 glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_AOD2OPACITY), 1);
Ahan Wu330bc602019-04-25 15:04:39 +0800143 glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_PER85), threshold);
Ahan Wu67e7f102019-01-14 20:38:14 +0800144 glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_REVEAL), reveal);
145
Ahan Wue16e1fa2019-05-29 18:39:33 +0800146 glClear(GL_COLOR_BUFFER_BIT);
147 // We only need to scale viewport while doing transition.
148 if (mScissorMode) {
149 scaleViewport(reveal);
150 } else {
151 glViewport(0, 0, mSurfaceSize.width(), mSurfaceSize.height());
152 }
Ahan Wu67e7f102019-01-14 20:38:14 +0800153 mWallpaper.useTexture();
154 mWallpaper.draw();
155 }
156
Ahan Wufa42c512019-05-15 19:52:51 +0800157 @Override
158 public void updateAmbientMode(boolean inAmbientMode, long duration) {
159 mImageRevealHelper.updateAwake(!inAmbientMode, duration);
160 }
161
162 @Override
Ahan Wue16e1fa2019-05-29 18:39:33 +0800163 public void updateOffsets(float xOffset, float yOffset) {
164 mXOffset = xOffset;
165 mYOffset = yOffset;
166 int left = (int) ((mSurfaceSize.width() - mScissor.width()) * xOffset);
167 int right = left + mScissor.width();
168 mScissor.set(left, mScissor.top, right, mScissor.bottom);
169 }
170
171 @Override
Ahan Wufa42c512019-05-15 19:52:51 +0800172 public Size reportSurfaceSize() {
173 return new Size(mSurfaceSize.width(), mSurfaceSize.height());
174 }
175
176 @Override
177 public void finish() {
178 mProxy = null;
179 }
180
Ahan Wuc8363352019-03-07 17:35:27 +0800181 private void scaleViewport(float reveal) {
Ahan Wue16e1fa2019-05-29 18:39:33 +0800182 int left = mScissor.left;
183 int top = mScissor.top;
184 int width = mScissor.width();
185 int height = mScissor.height();
Ahan Wuc8363352019-03-07 17:35:27 +0800186 // Interpolation between SCALE_VIEWPORT_MAX and SCALE_VIEWPORT_MIN by reveal.
Ahan Wue16e1fa2019-05-29 18:39:33 +0800187 float vpScaled = MathUtils.lerp(SCALE_VIEWPORT_MIN, SCALE_VIEWPORT_MAX, reveal);
Ahan Wuc8363352019-03-07 17:35:27 +0800188 // Calculate the offset amount from the lower left corner.
Ahan Wue16e1fa2019-05-29 18:39:33 +0800189 float offset = (SCALE_VIEWPORT_MIN - vpScaled) / 2;
Ahan Wuc8363352019-03-07 17:35:27 +0800190 // Change the viewport.
Ahan Wue16e1fa2019-05-29 18:39:33 +0800191 mViewport.set((int) (left + width * offset), (int) (top + height * offset),
Ahan Wufa42c512019-05-15 19:52:51 +0800192 (int) (width * vpScaled), (int) (height * vpScaled));
Ahan Wue16e1fa2019-05-29 18:39:33 +0800193 glViewport(mViewport.left, mViewport.top, mViewport.right, mViewport.bottom);
Ahan Wu67e7f102019-01-14 20:38:14 +0800194 }
195
196 @Override
197 public void onRevealStateChanged() {
Ahan Wufa42c512019-05-15 19:52:51 +0800198 mProxy.requestRender();
Ahan Wu67e7f102019-01-14 20:38:14 +0800199 }
200
Ahan Wufa42c512019-05-15 19:52:51 +0800201 @Override
Ahan Wu0e174802019-07-23 20:41:52 +0800202 public void onRevealStart(boolean animate) {
Ahan Wu3573cdd2019-10-04 11:59:10 +0800203 if (DEBUG) {
204 Log.v(TAG, "onRevealStart: start, anim=" + animate);
205 }
206
Ahan Wu0e174802019-07-23 20:41:52 +0800207 if (animate) {
208 mScissorMode = true;
209 // Use current display area of texture.
210 mWallpaper.adjustTextureCoordinates(mSurfaceSize, mScissor, mXOffset, mYOffset);
211 }
Ahan Wufa42c512019-05-15 19:52:51 +0800212 mProxy.preRender();
Ahan Wu3573cdd2019-10-04 11:59:10 +0800213
214 if (DEBUG) {
215 Log.v(TAG, "onRevealStart: done");
216 }
Ahan Wufa42c512019-05-15 19:52:51 +0800217 }
218
219 @Override
220 public void onRevealEnd() {
Ahan Wu3573cdd2019-10-04 11:59:10 +0800221 if (DEBUG) {
222 Log.v(TAG, "onRevealEnd: start, mScissorMode=" + mScissorMode);
223 }
224
Ahan Wu0e174802019-07-23 20:41:52 +0800225 if (mScissorMode) {
226 mScissorMode = false;
227 // reset texture coordinates to use full texture.
228 mWallpaper.adjustTextureCoordinates(null, null, 0, 0);
229 // We need draw full texture back before finishing render.
230 mProxy.requestRender();
231 }
Ahan Wufa42c512019-05-15 19:52:51 +0800232 mProxy.postRender();
Ahan Wu3573cdd2019-10-04 11:59:10 +0800233
234 if (DEBUG) {
235 Log.v(TAG, "onRevealEnd: done");
236 }
Ahan Wu67e7f102019-01-14 20:38:14 +0800237 }
Ahan Wu76884242019-05-22 20:04:23 +0800238
239 @Override
240 public void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) {
241 out.print(prefix); out.print("mProxy="); out.print(mProxy);
242 out.print(prefix); out.print("mSurfaceSize="); out.print(mSurfaceSize);
Ahan Wue16e1fa2019-05-29 18:39:33 +0800243 out.print(prefix); out.print("mScissor="); out.print(mScissor);
244 out.print(prefix); out.print("mViewport="); out.print(mViewport);
245 out.print(prefix); out.print("mScissorMode="); out.print(mScissorMode);
246 out.print(prefix); out.print("mXOffset="); out.print(mXOffset);
247 out.print(prefix); out.print("mYOffset="); out.print(mYOffset);
Ahan Wu76884242019-05-22 20:04:23 +0800248 out.print(prefix); out.print("threshold="); out.print(mImageProcessHelper.getThreshold());
Ahan Wu3573cdd2019-10-04 11:59:10 +0800249 out.print(prefix); out.print("mReveal="); out.print(mImageRevealHelper.getReveal());
Ahan Wue16e1fa2019-05-29 18:39:33 +0800250 mWallpaper.dump(prefix, fd, out, args);
Ahan Wu76884242019-05-22 20:04:23 +0800251 }
Ahan Wu67e7f102019-01-14 20:38:14 +0800252}