blob: 1a0356c4446d66264a37ebd51f52fe281bbabb7d [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.glViewport;
import android.app.WallpaperManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.util.Log;
import android.util.Size;
import com.android.systemui.R;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
/**
* A GL renderer for image wallpaper.
*/
public class ImageWallpaperRenderer implements GLWallpaperRenderer {
private static final String TAG = ImageWallpaperRenderer.class.getSimpleName();
private static final boolean DEBUG = false;
private final ImageGLProgram mProgram;
private final ImageGLWallpaper mWallpaper;
private final Rect mSurfaceSize = new Rect();
private final WallpaperTexture mTexture;
public ImageWallpaperRenderer(Context context) {
final WallpaperManager wpm = context.getSystemService(WallpaperManager.class);
if (wpm == null) {
Log.w(TAG, "WallpaperManager not available");
}
mTexture = new WallpaperTexture(wpm);
mProgram = new ImageGLProgram(context);
mWallpaper = new ImageGLWallpaper(mProgram);
}
@Override
public boolean isWcgContent() {
return mTexture.isWcgContent();
}
@Override
public void onSurfaceCreated() {
glClearColor(0f, 0f, 0f, 1.0f);
mProgram.useGLProgram(
R.raw.image_wallpaper_vertex_shader, R.raw.image_wallpaper_fragment_shader);
mTexture.use(bitmap -> {
if (bitmap == null) {
Log.w(TAG, "reload texture failed!");
}
mWallpaper.setup(bitmap);
});
}
@Override
public void onSurfaceChanged(int width, int height) {
glViewport(0, 0, width, height);
}
@Override
public void onDrawFrame() {
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, mSurfaceSize.width(), mSurfaceSize.height());
mWallpaper.useTexture();
mWallpaper.draw();
}
@Override
public Size reportSurfaceSize() {
mTexture.use(null /* consumer */);
mSurfaceSize.set(mTexture.getTextureDimensions());
return new Size(mSurfaceSize.width(), mSurfaceSize.height());
}
@Override
public void finish() {
}
@Override
public void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) {
out.print(prefix); out.print("mSurfaceSize="); out.print(mSurfaceSize);
out.print(prefix); out.print("mWcgContent="); out.print(isWcgContent());
mWallpaper.dump(prefix, fd, out, args);
}
static class WallpaperTexture {
private final AtomicInteger mRefCount;
private final Rect mDimensions;
private final WallpaperManager mWallpaperManager;
private Bitmap mBitmap;
private boolean mWcgContent;
private WallpaperTexture(WallpaperManager wallpaperManager) {
mWallpaperManager = wallpaperManager;
mRefCount = new AtomicInteger();
mDimensions = new Rect();
}
public void use(Consumer<Bitmap> consumer) {
mRefCount.incrementAndGet();
synchronized (mRefCount) {
if (mBitmap == null) {
mBitmap = mWallpaperManager.getBitmap(false /* hardware */);
mWcgContent = mWallpaperManager.wallpaperSupportsWcg(
WallpaperManager.FLAG_SYSTEM);
mWallpaperManager.forgetLoadedWallpaper();
if (mBitmap != null) {
mDimensions.set(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
} else {
Log.w(TAG, "Can't get bitmap");
}
}
}
if (consumer != null) {
consumer.accept(mBitmap);
}
synchronized (mRefCount) {
final int count = mRefCount.decrementAndGet();
if (count == 0 && mBitmap != null) {
if (DEBUG) {
Log.v(TAG, "WallpaperTexture: release 0x" + getHash()
+ ", refCount=" + count);
}
mBitmap.recycle();
mBitmap = null;
}
}
}
private boolean isWcgContent() {
return mWcgContent;
}
private String getHash() {
return mBitmap != null ? Integer.toHexString(mBitmap.hashCode()) : "null";
}
private Rect getTextureDimensions() {
return mDimensions;
}
@Override
public String toString() {
return "{" + getHash() + ", " + mRefCount.get() + "}";
}
}
}