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_FLOAT; 20 import static android.opengl.GLES20.GL_LINEAR; 21 import static android.opengl.GLES20.GL_TEXTURE0; 22 import static android.opengl.GLES20.GL_TEXTURE_2D; 23 import static android.opengl.GLES20.GL_TEXTURE_MAG_FILTER; 24 import static android.opengl.GLES20.GL_TEXTURE_MIN_FILTER; 25 import static android.opengl.GLES20.GL_TRIANGLES; 26 import static android.opengl.GLES20.glActiveTexture; 27 import static android.opengl.GLES20.glBindTexture; 28 import static android.opengl.GLES20.glDrawArrays; 29 import static android.opengl.GLES20.glEnableVertexAttribArray; 30 import static android.opengl.GLES20.glGenTextures; 31 import static android.opengl.GLES20.glTexParameteri; 32 import static android.opengl.GLES20.glUniform1i; 33 import static android.opengl.GLES20.glVertexAttribPointer; 34 35 import android.graphics.Bitmap; 36 import android.opengl.GLUtils; 37 import android.util.Log; 38 39 import java.io.FileDescriptor; 40 import java.io.PrintWriter; 41 import java.nio.ByteBuffer; 42 import java.nio.ByteOrder; 43 import java.nio.FloatBuffer; 44 45 /** 46 * This class takes charge of the geometry data like vertices and texture coordinates. 47 * It delivers these data to opengl runtime and triggers draw calls if necessary. 48 */ 49 class ImageGLWallpaper { 50 private static final String TAG = ImageGLWallpaper.class.getSimpleName(); 51 52 private static final String A_POSITION = "aPosition"; 53 private static final String A_TEXTURE_COORDINATES = "aTextureCoordinates"; 54 private static final String U_TEXTURE = "uTexture"; 55 private static final int POSITION_COMPONENT_COUNT = 2; 56 private static final int TEXTURE_COMPONENT_COUNT = 2; 57 private static final int BYTES_PER_FLOAT = 4; 58 59 // Vertices to define the square with 2 triangles. 60 private static final float[] VERTICES = { 61 -1.0f, -1.0f, 62 +1.0f, -1.0f, 63 +1.0f, +1.0f, 64 +1.0f, +1.0f, 65 -1.0f, +1.0f, 66 -1.0f, -1.0f 67 }; 68 69 // Texture coordinates that maps to vertices. 70 private static final float[] TEXTURES = { 71 0f, 1f, 72 1f, 1f, 73 1f, 0f, 74 1f, 0f, 75 0f, 0f, 76 0f, 1f 77 }; 78 79 private final FloatBuffer mVertexBuffer; 80 private final FloatBuffer mTextureBuffer; 81 private final ImageGLProgram mProgram; 82 83 private int mAttrPosition; 84 private int mAttrTextureCoordinates; 85 private int mUniTexture; 86 private int mTextureId; 87 ImageGLWallpaper(ImageGLProgram program)88 ImageGLWallpaper(ImageGLProgram program) { 89 mProgram = program; 90 91 // Create an float array in opengles runtime (native) and put vertex data. 92 mVertexBuffer = ByteBuffer.allocateDirect(VERTICES.length * BYTES_PER_FLOAT) 93 .order(ByteOrder.nativeOrder()) 94 .asFloatBuffer(); 95 mVertexBuffer.put(VERTICES); 96 mVertexBuffer.position(0); 97 98 // Create an float array in opengles runtime (native) and put texture data. 99 mTextureBuffer = ByteBuffer.allocateDirect(TEXTURES.length * BYTES_PER_FLOAT) 100 .order(ByteOrder.nativeOrder()) 101 .asFloatBuffer(); 102 mTextureBuffer.put(TEXTURES); 103 mTextureBuffer.position(0); 104 } 105 setup(Bitmap bitmap)106 void setup(Bitmap bitmap) { 107 setupAttributes(); 108 setupUniforms(); 109 setupTexture(bitmap); 110 } 111 setupAttributes()112 private void setupAttributes() { 113 mAttrPosition = mProgram.getAttributeHandle(A_POSITION); 114 mVertexBuffer.position(0); 115 glVertexAttribPointer(mAttrPosition, POSITION_COMPONENT_COUNT, GL_FLOAT, 116 false, 0, mVertexBuffer); 117 glEnableVertexAttribArray(mAttrPosition); 118 119 mAttrTextureCoordinates = mProgram.getAttributeHandle(A_TEXTURE_COORDINATES); 120 mTextureBuffer.position(0); 121 glVertexAttribPointer(mAttrTextureCoordinates, TEXTURE_COMPONENT_COUNT, GL_FLOAT, 122 false, 0, mTextureBuffer); 123 glEnableVertexAttribArray(mAttrTextureCoordinates); 124 } 125 setupUniforms()126 private void setupUniforms() { 127 mUniTexture = mProgram.getUniformHandle(U_TEXTURE); 128 } 129 draw()130 void draw() { 131 glDrawArrays(GL_TRIANGLES, 0, VERTICES.length / 2); 132 } 133 setupTexture(Bitmap bitmap)134 private void setupTexture(Bitmap bitmap) { 135 final int[] tids = new int[1]; 136 137 if (bitmap == null || bitmap.isRecycled()) { 138 Log.w(TAG, "setupTexture: invalid bitmap"); 139 return; 140 } 141 142 // Generate one texture object and store the id in tids[0]. 143 glGenTextures(1, tids, 0); 144 if (tids[0] == 0) { 145 Log.w(TAG, "setupTexture: glGenTextures() failed"); 146 return; 147 } 148 149 try { 150 // Bind a named texture to a target. 151 glBindTexture(GL_TEXTURE_2D, tids[0]); 152 // Load the bitmap data and copy it over into the texture object 153 // that is currently bound. 154 GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0); 155 // Use bilinear texture filtering when minification. 156 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 157 // Use bilinear texture filtering when magnification. 158 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 159 mTextureId = tids[0]; 160 } catch (IllegalArgumentException e) { 161 Log.w(TAG, "Failed uploading texture: " + e.getLocalizedMessage()); 162 } 163 } 164 useTexture()165 void useTexture() { 166 // Set the active texture unit to texture unit 0. 167 glActiveTexture(GL_TEXTURE0); 168 // Bind the texture to this unit. 169 glBindTexture(GL_TEXTURE_2D, mTextureId); 170 // Let the texture sampler in fragment shader to read form this texture unit. 171 glUniform1i(mUniTexture, 0); 172 } 173 174 /** 175 * Called to dump current state. 176 * @param prefix prefix. 177 * @param fd fd. 178 * @param out out. 179 * @param args args. 180 */ dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args)181 public void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) { 182 } 183 } 184