1227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/* 2227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Copyright (C) 2011 The Android Open Source Project 3227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 4227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Licensed under the Apache License, Version 2.0 (the "License"); 5227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * you may not use this file except in compliance with the License. 6227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * You may obtain a copy of the License at 7227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 8227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * http://www.apache.org/licenses/LICENSE-2.0 9227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 10227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Unless required by applicable law or agreed to in writing, software 11227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * distributed under the License is distributed on an "AS IS" BASIS, 12227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * See the License for the specific language governing permissions and 14227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * limitations under the License. 15227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 16227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 17227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspackage androidx.media.filterfw; 18227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 19227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.graphics.Bitmap; 20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.opengl.GLES20; 21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.opengl.GLUtils; 22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.os.Looper; 23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.nio.ByteBuffer; 25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.nio.ByteOrder; 26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/** 28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * TODO: Make this package-private as RenderTarget and TextureSource should suffice as public 29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * facing OpenGL utilities. 30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @hide 31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspublic class GLToolbox { 33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static int textureNone() { 35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return 0; 36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static boolean isTexture(int texId) { 39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return GLES20.glIsTexture(texId); 40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static void deleteTexture(int texId) { 43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int[] textures = new int[] { texId }; 44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks assertNonUiThread("glDeleteTextures"); 45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glDeleteTextures(1, textures, 0); 46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkGlError("glDeleteTextures"); 47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static void deleteFbo(int fboId) { 50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int[] fbos = new int[] { fboId }; 51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks assertNonUiThread("glDeleteFramebuffers"); 52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glDeleteFramebuffers(1, fbos, 0); 53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkGlError("glDeleteFramebuffers"); 54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static int generateTexture() { 57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int[] textures = new int[1]; 58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glGenTextures(1, textures, 0); 59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkGlError("glGenTextures"); 60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return textures[0]; 61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static int generateFbo() { 64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int[] fbos = new int[1]; 65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glGenFramebuffers(1, fbos, 0); 66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkGlError("glGenFramebuffers"); 67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return fbos[0]; 68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static void readFbo(int fboId, ByteBuffer pixels, int width, int height) { 71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboId); 72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, pixels); 73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkGlError("glReadPixels"); 74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static void readTarget(RenderTarget target, ByteBuffer pixels, int width, int height) { 77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks target.focus(); 78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, pixels); 79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkGlError("glReadPixels"); 80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static int attachedTexture(int fboId) { 83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int[] params = new int[1]; 84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glGetFramebufferAttachmentParameteriv( 85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.GL_FRAMEBUFFER, 86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.GL_COLOR_ATTACHMENT0, 87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, 88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks params, 0); 89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkGlError("glGetFramebufferAttachmentParameteriv"); 90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return params[0]; 91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static void attachTextureToFbo(int texId, int fboId) { 94227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboId); 95227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, 96227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.GL_COLOR_ATTACHMENT0, 97227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.GL_TEXTURE_2D, 98227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks texId, 99227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 0); 100227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkGlError("glFramebufferTexture2D"); 101227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 102227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 103227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static void allocateTexturePixels(int texId, int target, int width, int height) { 104227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks setTexturePixels(texId, target, (ByteBuffer)null, width, height); 105227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 106227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 107227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static void setTexturePixels(int texId, int target, Bitmap bitmap) { 108227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glBindTexture(target, texId); 109227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLUtils.texImage2D(target, 0, bitmap, 0); 110227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkGlError("glTexImage2D"); 111227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks setDefaultTexParams(); 112227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 113227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 114227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static void setTexturePixels(int texId, int target, ByteBuffer pixels, 115227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int width, int height) { 116227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glBindTexture(target, texId); 117227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 118227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // For some devices, "pixels" being null causes system error. 119227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (pixels == null) { 120227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks pixels = ByteBuffer.allocateDirect(width * height * 4); 121227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 122227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glTexImage2D(target, 0, GLES20.GL_RGBA, width, height, 0, 123227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, pixels); 124227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkGlError("glTexImage2D"); 125227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks setDefaultTexParams(); 126227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 127227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 128227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static void setDefaultTexParams() { 129227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, 130227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 131227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, 132227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 133227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, 134227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 135227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, 136227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 137227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkGlError("glTexParameteri"); 138227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 139227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 140227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static int vboNone() { 141227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return 0; 142227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 143227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 144227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static int generateVbo() { 145227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int[] vbos = new int[1]; 146227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glGenBuffers(1, vbos, 0); 147227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkGlError("glGenBuffers"); 148227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return vbos[0]; 149227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 150227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 151227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static void setVboData(int vboId, ByteBuffer data) { 152227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId); 153227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, data.remaining(), data, GLES20.GL_STATIC_DRAW); 154227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkGlError("glBufferData"); 155227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 156227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 157227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static void setVboFloats(int vboId, float[] values) { 158227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int len = values.length * 4; 159227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ByteBuffer buffer = ByteBuffer.allocateDirect(len).order(ByteOrder.nativeOrder()); 160227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks setVboData(vboId, buffer); 161227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 162227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 163227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static boolean isVbo(int vboId) { 164227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return GLES20.glIsBuffer(vboId); 165227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 166227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 167227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static void deleteVbo(int vboId) { 168227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int[] buffers = new int[] { vboId }; 169227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glDeleteBuffers(1, buffers, 0); 170227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkGlError("glDeleteBuffers"); 171227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 172227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 173227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static void checkGlError(String operation) { 174227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int error; 175227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) { 176227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new RuntimeException("GL Operation '" + operation + "' caused error " 177227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + Integer.toHexString(error) + "!"); 178227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 179227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 180227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 181227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 182227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Make sure we are not operating in the UI thread. 183227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 184227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * It is often tricky to track down bugs that happen when issuing GL commands in the UI thread. 185227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * This is especially true when releasing GL resources. Often this will cause errors much later 186227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * on. Therefore we make sure we do not do these dangerous operations on the UI thread. 187227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 188227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static void assertNonUiThread(String operation) { 189227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (Looper.getMainLooper().getThread() == Thread.currentThread()) { 190227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new RuntimeException("Attempting to perform GL operation '" + operation 191227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + "' on UI thread!"); 192227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 193227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 194227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks} 195