blob: 21711fb1890c3670912801e1d8841a7649607137 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.glwallpaper;
import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;
import static android.opengl.GLES20.glClear;
import static android.opengl.GLES20.glClearColor;
import static android.opengl.GLES20.glUniform1f;
import static android.opengl.GLES20.glViewport;
import android.app.WallpaperManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.util.Log;
import android.util.MathUtils;
import android.util.Size;
import com.android.systemui.R;
import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
* A GL renderer for image wallpaper.
*/
public class ImageWallpaperRenderer implements GLWallpaperRenderer,
ImageRevealHelper.RevealStateListener {
private static final String TAG = ImageWallpaperRenderer.class.getSimpleName();
private static final float SCALE_VIEWPORT_MIN = 0.98f;
private static final float SCALE_VIEWPORT_MAX = 1f;
private final WallpaperManager mWallpaperManager;
private final ImageGLProgram mProgram;
private final ImageGLWallpaper mWallpaper;
private final ImageProcessHelper mImageProcessHelper;
private final ImageRevealHelper mImageRevealHelper;
private SurfaceProxy mProxy;
private Rect mSurfaceSize;
private Bitmap mBitmap;
public ImageWallpaperRenderer(Context context, SurfaceProxy proxy) {
mWallpaperManager = context.getSystemService(WallpaperManager.class);
if (mWallpaperManager == null) {
Log.w(TAG, "WallpaperManager not available");
}
mProxy = proxy;
mProgram = new ImageGLProgram(context);
mWallpaper = new ImageGLWallpaper(mProgram);
mImageProcessHelper = new ImageProcessHelper();
mImageRevealHelper = new ImageRevealHelper(this);
if (loadBitmap()) {
// Compute threshold of the image, this is an async work.
mImageProcessHelper.start(mBitmap);
}
}
@Override
public void onSurfaceCreated() {
glClearColor(0f, 0f, 0f, 1.0f);
mProgram.useGLProgram(
R.raw.image_wallpaper_vertex_shader, R.raw.image_wallpaper_fragment_shader);
if (!loadBitmap()) {
Log.w(TAG, "reload bitmap failed!");
}
mWallpaper.setup(mBitmap);
mBitmap = null;
}
private boolean loadBitmap() {
if (mWallpaperManager != null && mBitmap == null) {
mBitmap = mWallpaperManager.getBitmap();
mWallpaperManager.forgetLoadedWallpaper();
if (mBitmap != null) {
mSurfaceSize = new Rect(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
}
}
return mBitmap != null;
}
@Override
public void onSurfaceChanged(int width, int height) {
glViewport(0, 0, width, height);
}
@Override
public void onDrawFrame() {
float threshold = mImageProcessHelper.getThreshold();
float reveal = mImageRevealHelper.getReveal();
glClear(GL_COLOR_BUFFER_BIT);
glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_AOD2OPACITY), 1);
glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_PER85), threshold);
glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_REVEAL), reveal);
scaleViewport(reveal);
mWallpaper.useTexture();
mWallpaper.draw();
}
@Override
public void updateAmbientMode(boolean inAmbientMode, long duration) {
mImageRevealHelper.updateAwake(!inAmbientMode, duration);
}
@Override
public Size reportSurfaceSize() {
return new Size(mSurfaceSize.width(), mSurfaceSize.height());
}
@Override
public void finish() {
mProxy = null;
}
private void scaleViewport(float reveal) {
int width = mSurfaceSize.width();
int height = mSurfaceSize.height();
// Interpolation between SCALE_VIEWPORT_MAX and SCALE_VIEWPORT_MIN by reveal.
float vpScaled = MathUtils.lerp(SCALE_VIEWPORT_MAX, SCALE_VIEWPORT_MIN, reveal);
// Calculate the offset amount from the lower left corner.
float offset = (SCALE_VIEWPORT_MAX - vpScaled) / 2;
// Change the viewport.
glViewport((int) (width * offset), (int) (height * offset),
(int) (width * vpScaled), (int) (height * vpScaled));
}
@Override
public void onRevealStateChanged() {
mProxy.requestRender();
}
@Override
public void onRevealStart() {
mProxy.preRender();
}
@Override
public void onRevealEnd() {
mProxy.postRender();
}
@Override
public void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) {
out.print(prefix); out.print("mProxy="); out.print(mProxy);
out.print(prefix); out.print("mSurfaceSize="); out.print(mSurfaceSize);
out.print(prefix); out.print("threshold="); out.print(mImageProcessHelper.getThreshold());
}
}