| /* |
| * 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() + "}"; |
| } |
| } |
| } |