1 /* 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 17 package com.android.systemui.glwallpaper; 18 19 import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT; 20 import static android.opengl.GLES20.glClear; 21 import static android.opengl.GLES20.glClearColor; 22 import static android.opengl.GLES20.glViewport; 23 24 import android.app.WallpaperManager; 25 import android.content.Context; 26 import android.graphics.Bitmap; 27 import android.graphics.Rect; 28 import android.util.Log; 29 import android.util.Size; 30 31 import com.android.systemui.R; 32 33 import java.io.FileDescriptor; 34 import java.io.PrintWriter; 35 import java.util.concurrent.atomic.AtomicInteger; 36 import java.util.function.Consumer; 37 38 /** 39 * A GL renderer for image wallpaper. 40 */ 41 public class ImageWallpaperRenderer implements GLWallpaperRenderer { 42 private static final String TAG = ImageWallpaperRenderer.class.getSimpleName(); 43 private static final boolean DEBUG = false; 44 45 private final ImageGLProgram mProgram; 46 private final ImageGLWallpaper mWallpaper; 47 private final Rect mSurfaceSize = new Rect(); 48 private final WallpaperTexture mTexture; 49 ImageWallpaperRenderer(Context context)50 public ImageWallpaperRenderer(Context context) { 51 final WallpaperManager wpm = context.getSystemService(WallpaperManager.class); 52 if (wpm == null) { 53 Log.w(TAG, "WallpaperManager not available"); 54 } 55 56 mTexture = new WallpaperTexture(wpm); 57 mProgram = new ImageGLProgram(context); 58 mWallpaper = new ImageGLWallpaper(mProgram); 59 } 60 61 @Override isWcgContent()62 public boolean isWcgContent() { 63 return mTexture.isWcgContent(); 64 } 65 66 @Override onSurfaceCreated()67 public void onSurfaceCreated() { 68 glClearColor(0f, 0f, 0f, 1.0f); 69 mProgram.useGLProgram( 70 R.raw.image_wallpaper_vertex_shader, R.raw.image_wallpaper_fragment_shader); 71 72 mTexture.use(bitmap -> { 73 if (bitmap == null) { 74 Log.w(TAG, "reload texture failed!"); 75 } 76 mWallpaper.setup(bitmap); 77 }); 78 } 79 80 @Override onSurfaceChanged(int width, int height)81 public void onSurfaceChanged(int width, int height) { 82 glViewport(0, 0, width, height); 83 } 84 85 @Override onDrawFrame()86 public void onDrawFrame() { 87 glClear(GL_COLOR_BUFFER_BIT); 88 glViewport(0, 0, mSurfaceSize.width(), mSurfaceSize.height()); 89 mWallpaper.useTexture(); 90 mWallpaper.draw(); 91 } 92 93 @Override reportSurfaceSize()94 public Size reportSurfaceSize() { 95 mTexture.use(null /* consumer */); 96 mSurfaceSize.set(mTexture.getTextureDimensions()); 97 return new Size(mSurfaceSize.width(), mSurfaceSize.height()); 98 } 99 100 @Override finish()101 public void finish() { 102 } 103 104 @Override dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args)105 public void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) { 106 out.print(prefix); out.print("mSurfaceSize="); out.print(mSurfaceSize); 107 out.print(prefix); out.print("mWcgContent="); out.print(isWcgContent()); 108 mWallpaper.dump(prefix, fd, out, args); 109 } 110 111 static class WallpaperTexture { 112 private final AtomicInteger mRefCount; 113 private final Rect mDimensions; 114 private final WallpaperManager mWallpaperManager; 115 private Bitmap mBitmap; 116 private boolean mWcgContent; 117 WallpaperTexture(WallpaperManager wallpaperManager)118 private WallpaperTexture(WallpaperManager wallpaperManager) { 119 mWallpaperManager = wallpaperManager; 120 mRefCount = new AtomicInteger(); 121 mDimensions = new Rect(); 122 } 123 use(Consumer<Bitmap> consumer)124 public void use(Consumer<Bitmap> consumer) { 125 mRefCount.incrementAndGet(); 126 synchronized (mRefCount) { 127 if (mBitmap == null) { 128 mBitmap = mWallpaperManager.getBitmap(false /* hardware */); 129 mWcgContent = mWallpaperManager.wallpaperSupportsWcg( 130 WallpaperManager.FLAG_SYSTEM); 131 mWallpaperManager.forgetLoadedWallpaper(); 132 if (mBitmap != null) { 133 mDimensions.set(0, 0, mBitmap.getWidth(), mBitmap.getHeight()); 134 } else { 135 Log.w(TAG, "Can't get bitmap"); 136 } 137 } 138 } 139 if (consumer != null) { 140 consumer.accept(mBitmap); 141 } 142 synchronized (mRefCount) { 143 final int count = mRefCount.decrementAndGet(); 144 if (count == 0 && mBitmap != null) { 145 if (DEBUG) { 146 Log.v(TAG, "WallpaperTexture: release 0x" + getHash() 147 + ", refCount=" + count); 148 } 149 mBitmap.recycle(); 150 mBitmap = null; 151 } 152 } 153 } 154 isWcgContent()155 private boolean isWcgContent() { 156 return mWcgContent; 157 } 158 getHash()159 private String getHash() { 160 return mBitmap != null ? Integer.toHexString(mBitmap.hashCode()) : "null"; 161 } 162 getTextureDimensions()163 private Rect getTextureDimensions() { 164 return mDimensions; 165 } 166 167 @Override toString()168 public String toString() { 169 return "{" + getHash() + ", " + mRefCount.get() + "}"; 170 } 171 } 172 } 173