1e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka/* 2e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Copyright (C) 2012 The Android Open Source Project 3e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * 4e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Licensed under the Apache License, Version 2.0 (the "License"); 5e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * you may not use this file except in compliance with the License. 6e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * You may obtain a copy of the License at 7e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * 8e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * http://www.apache.org/licenses/LICENSE-2.0 9e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * 10e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Unless required by applicable law or agreed to in writing, software 11e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * distributed under the License is distributed on an "AS IS" BASIS, 12e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * See the License for the specific language governing permissions and 14e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * limitations under the License. 15e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 16e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkapackage com.android.gallery3d.glrenderer; 17e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 18e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.graphics.Bitmap; 19e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.graphics.Rect; 20e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.graphics.RectF; 21e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.opengl.GLES20; 22e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.opengl.GLUtils; 23e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.opengl.Matrix; 24e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.util.Log; 25e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 26e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport com.android.gallery3d.util.IntArray; 27e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 28e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport java.nio.Buffer; 29e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport java.nio.ByteBuffer; 30e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport java.nio.ByteOrder; 31e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport java.nio.FloatBuffer; 32e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport java.util.ArrayList; 33e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport java.util.Arrays; 34e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 35e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkapublic class GLES20Canvas implements GLCanvas { 36e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // ************** Constants ********************** 37e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final String TAG = GLES20Canvas.class.getSimpleName(); 38e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final int FLOAT_SIZE = Float.SIZE / Byte.SIZE; 39e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final float OPAQUE_ALPHA = 0.95f; 40e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 41e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final int COORDS_PER_VERTEX = 2; 42e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final int VERTEX_STRIDE = COORDS_PER_VERTEX * FLOAT_SIZE; 43e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 44e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final int COUNT_FILL_VERTEX = 4; 45e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final int COUNT_LINE_VERTEX = 2; 46e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final int COUNT_RECT_VERTEX = 4; 47e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final int OFFSET_FILL_RECT = 0; 48e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final int OFFSET_DRAW_LINE = OFFSET_FILL_RECT + COUNT_FILL_VERTEX; 49e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final int OFFSET_DRAW_RECT = OFFSET_DRAW_LINE + COUNT_LINE_VERTEX; 50e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 51e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final float[] BOX_COORDINATES = { 52e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 0, 0, // Fill rectangle 53e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 1, 0, 54e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 0, 1, 55e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 1, 1, 56e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 0, 0, // Draw line 57e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 1, 1, 58e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 0, 0, // Draw rectangle outline 59e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 0, 1, 60e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 1, 1, 61e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 1, 0, 62e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka }; 63e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 64e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final float[] BOUNDS_COORDINATES = { 65e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 0, 0, 0, 1, 66e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 1, 1, 0, 1, 67e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka }; 68e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 69e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final String POSITION_ATTRIBUTE = "aPosition"; 70e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final String COLOR_UNIFORM = "uColor"; 71e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final String MATRIX_UNIFORM = "uMatrix"; 72e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final String TEXTURE_MATRIX_UNIFORM = "uTextureMatrix"; 73e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final String TEXTURE_SAMPLER_UNIFORM = "uTextureSampler"; 74e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final String ALPHA_UNIFORM = "uAlpha"; 75e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final String TEXTURE_COORD_ATTRIBUTE = "aTextureCoordinate"; 76e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 77e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final String DRAW_VERTEX_SHADER = "" 78e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "uniform mat4 " + MATRIX_UNIFORM + ";\n" 79e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "attribute vec2 " + POSITION_ATTRIBUTE + ";\n" 80e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "void main() {\n" 81e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + " vec4 pos = vec4(" + POSITION_ATTRIBUTE + ", 0.0, 1.0);\n" 82e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + " gl_Position = " + MATRIX_UNIFORM + " * pos;\n" 83e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "}\n"; 84e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 85e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final String DRAW_FRAGMENT_SHADER = "" 86e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "precision mediump float;\n" 87e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "uniform vec4 " + COLOR_UNIFORM + ";\n" 88e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "void main() {\n" 89e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + " gl_FragColor = " + COLOR_UNIFORM + ";\n" 90e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "}\n"; 91e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 92e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final String TEXTURE_VERTEX_SHADER = "" 93e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "uniform mat4 " + MATRIX_UNIFORM + ";\n" 94e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "uniform mat4 " + TEXTURE_MATRIX_UNIFORM + ";\n" 95e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "attribute vec2 " + POSITION_ATTRIBUTE + ";\n" 96e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "varying vec2 vTextureCoord;\n" 97e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "void main() {\n" 98e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + " vec4 pos = vec4(" + POSITION_ATTRIBUTE + ", 0.0, 1.0);\n" 99e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + " gl_Position = " + MATRIX_UNIFORM + " * pos;\n" 100e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + " vTextureCoord = (" + TEXTURE_MATRIX_UNIFORM + " * pos).xy;\n" 101e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "}\n"; 102e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 103e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final String MESH_VERTEX_SHADER = "" 104e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "uniform mat4 " + MATRIX_UNIFORM + ";\n" 105e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "attribute vec2 " + POSITION_ATTRIBUTE + ";\n" 106e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "attribute vec2 " + TEXTURE_COORD_ATTRIBUTE + ";\n" 107e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "varying vec2 vTextureCoord;\n" 108e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "void main() {\n" 109e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + " vec4 pos = vec4(" + POSITION_ATTRIBUTE + ", 0.0, 1.0);\n" 110e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + " gl_Position = " + MATRIX_UNIFORM + " * pos;\n" 111e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + " vTextureCoord = " + TEXTURE_COORD_ATTRIBUTE + ";\n" 112e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "}\n"; 113e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 114e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final String TEXTURE_FRAGMENT_SHADER = "" 115e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "precision mediump float;\n" 116e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "varying vec2 vTextureCoord;\n" 117e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "uniform float " + ALPHA_UNIFORM + ";\n" 118e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "uniform sampler2D " + TEXTURE_SAMPLER_UNIFORM + ";\n" 119e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "void main() {\n" 120e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + " gl_FragColor = texture2D(" + TEXTURE_SAMPLER_UNIFORM + ", vTextureCoord);\n" 121e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + " gl_FragColor *= " + ALPHA_UNIFORM + ";\n" 122e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "}\n"; 123e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 124e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final String OES_TEXTURE_FRAGMENT_SHADER = "" 125e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "#extension GL_OES_EGL_image_external : require\n" 126e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "precision mediump float;\n" 127e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "varying vec2 vTextureCoord;\n" 128e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "uniform float " + ALPHA_UNIFORM + ";\n" 129e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "uniform samplerExternalOES " + TEXTURE_SAMPLER_UNIFORM + ";\n" 130e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "void main() {\n" 131e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + " gl_FragColor = texture2D(" + TEXTURE_SAMPLER_UNIFORM + ", vTextureCoord);\n" 132e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + " gl_FragColor *= " + ALPHA_UNIFORM + ";\n" 133e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka + "}\n"; 134e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 135e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final int INITIAL_RESTORE_STATE_SIZE = 8; 136e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final int MATRIX_SIZE = 16; 137e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 138e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Keep track of restore state 139e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private float[] mMatrices = new float[INITIAL_RESTORE_STATE_SIZE * MATRIX_SIZE]; 140e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private float[] mAlphas = new float[INITIAL_RESTORE_STATE_SIZE]; 141e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private IntArray mSaveFlags = new IntArray(); 142e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 143e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private int mCurrentAlphaIndex = 0; 144e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private int mCurrentMatrixIndex = 0; 145e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 146e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Viewport size 147e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private int mWidth; 148e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private int mHeight; 149e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 150e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Projection matrix 151e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private float[] mProjectionMatrix = new float[MATRIX_SIZE]; 152e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 153e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Screen size for when we aren't bound to a texture 154e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private int mScreenWidth; 155e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private int mScreenHeight; 156e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 157e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // GL programs 158e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private int mDrawProgram; 159e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private int mTextureProgram; 160e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private int mOesTextureProgram; 161e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private int mMeshProgram; 162e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 163e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // GL buffer containing BOX_COORDINATES 164e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private int mBoxCoordinates; 165e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 166e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Handle indices -- common 167e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final int INDEX_POSITION = 0; 168e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final int INDEX_MATRIX = 1; 169e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 170e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Handle indices -- draw 171e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final int INDEX_COLOR = 2; 172e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 173e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Handle indices -- texture 174e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final int INDEX_TEXTURE_MATRIX = 2; 175e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final int INDEX_TEXTURE_SAMPLER = 3; 176e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final int INDEX_ALPHA = 4; 177e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 178e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Handle indices -- mesh 179e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final int INDEX_TEXTURE_COORD = 2; 180e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 181e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private abstract static class ShaderParameter { 182e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public int handle; 183e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected final String mName; 184e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 185e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public ShaderParameter(String name) { 186e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mName = name; 187e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 188e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 189e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public abstract void loadHandle(int program); 190e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 191e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 192e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static class UniformShaderParameter extends ShaderParameter { 193e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public UniformShaderParameter(String name) { 194e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka super(name); 195e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 196e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 197e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 198e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void loadHandle(int program) { 199e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka handle = GLES20.glGetUniformLocation(program, mName); 200e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 201e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 202e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 203e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 204e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static class AttributeShaderParameter extends ShaderParameter { 205e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public AttributeShaderParameter(String name) { 206e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka super(name); 207e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 208e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 209e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 210e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void loadHandle(int program) { 211e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka handle = GLES20.glGetAttribLocation(program, mName); 212e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 213e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 214e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 215e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 216e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ShaderParameter[] mDrawParameters = { 217e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka new AttributeShaderParameter(POSITION_ATTRIBUTE), // INDEX_POSITION 218e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka new UniformShaderParameter(MATRIX_UNIFORM), // INDEX_MATRIX 219e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka new UniformShaderParameter(COLOR_UNIFORM), // INDEX_COLOR 220e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka }; 221e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ShaderParameter[] mTextureParameters = { 222e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka new AttributeShaderParameter(POSITION_ATTRIBUTE), // INDEX_POSITION 223e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka new UniformShaderParameter(MATRIX_UNIFORM), // INDEX_MATRIX 224e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka new UniformShaderParameter(TEXTURE_MATRIX_UNIFORM), // INDEX_TEXTURE_MATRIX 225e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka new UniformShaderParameter(TEXTURE_SAMPLER_UNIFORM), // INDEX_TEXTURE_SAMPLER 226e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka new UniformShaderParameter(ALPHA_UNIFORM), // INDEX_ALPHA 227e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka }; 228e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ShaderParameter[] mOesTextureParameters = { 229e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka new AttributeShaderParameter(POSITION_ATTRIBUTE), // INDEX_POSITION 230e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka new UniformShaderParameter(MATRIX_UNIFORM), // INDEX_MATRIX 231e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka new UniformShaderParameter(TEXTURE_MATRIX_UNIFORM), // INDEX_TEXTURE_MATRIX 232e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka new UniformShaderParameter(TEXTURE_SAMPLER_UNIFORM), // INDEX_TEXTURE_SAMPLER 233e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka new UniformShaderParameter(ALPHA_UNIFORM), // INDEX_ALPHA 234e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka }; 235e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ShaderParameter[] mMeshParameters = { 236e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka new AttributeShaderParameter(POSITION_ATTRIBUTE), // INDEX_POSITION 237e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka new UniformShaderParameter(MATRIX_UNIFORM), // INDEX_MATRIX 238e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka new AttributeShaderParameter(TEXTURE_COORD_ATTRIBUTE), // INDEX_TEXTURE_COORD 239e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka new UniformShaderParameter(TEXTURE_SAMPLER_UNIFORM), // INDEX_TEXTURE_SAMPLER 240e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka new UniformShaderParameter(ALPHA_UNIFORM), // INDEX_ALPHA 241e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka }; 242e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 243e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private final IntArray mUnboundTextures = new IntArray(); 244e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private final IntArray mDeleteBuffers = new IntArray(); 245e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 246e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Keep track of statistics for debugging 247e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private int mCountDrawMesh = 0; 248e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private int mCountTextureRect = 0; 249e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private int mCountFillRect = 0; 250e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private int mCountDrawLine = 0; 251e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 252e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Buffer for framebuffer IDs -- we keep track so we can switch the attached 253e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // texture. 254e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private int[] mFrameBuffer = new int[1]; 255e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 256e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Bound textures. 257e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private ArrayList<RawTexture> mTargetTextures = new ArrayList<RawTexture>(); 258e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 259e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Temporary variables used within calculations 260e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private final float[] mTempMatrix = new float[32]; 261e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private final float[] mTempColor = new float[4]; 262e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private final RectF mTempSourceRect = new RectF(); 263e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private final RectF mTempTargetRect = new RectF(); 264e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private final float[] mTempTextureMatrix = new float[MATRIX_SIZE]; 265e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private final int[] mTempIntArray = new int[1]; 266e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 267e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final GLId mGLId = new GLES20IdImpl(); 268e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 269e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public GLES20Canvas() { 270e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Matrix.setIdentityM(mTempTextureMatrix, 0); 271e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Matrix.setIdentityM(mMatrices, mCurrentMatrixIndex); 272e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mAlphas[mCurrentAlphaIndex] = 1f; 273e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mTargetTextures.add(null); 274e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 275e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka FloatBuffer boxBuffer = createBuffer(BOX_COORDINATES); 276e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mBoxCoordinates = uploadBuffer(boxBuffer); 277e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 278e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int drawVertexShader = loadShader(GLES20.GL_VERTEX_SHADER, DRAW_VERTEX_SHADER); 279e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int textureVertexShader = loadShader(GLES20.GL_VERTEX_SHADER, TEXTURE_VERTEX_SHADER); 280e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int meshVertexShader = loadShader(GLES20.GL_VERTEX_SHADER, MESH_VERTEX_SHADER); 281e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int drawFragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, DRAW_FRAGMENT_SHADER); 282e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int textureFragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, TEXTURE_FRAGMENT_SHADER); 283e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int oesTextureFragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, 284e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka OES_TEXTURE_FRAGMENT_SHADER); 285e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 286e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mDrawProgram = assembleProgram(drawVertexShader, drawFragmentShader, mDrawParameters); 287e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mTextureProgram = assembleProgram(textureVertexShader, textureFragmentShader, 288e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mTextureParameters); 289e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mOesTextureProgram = assembleProgram(textureVertexShader, oesTextureFragmentShader, 290e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mOesTextureParameters); 291e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mMeshProgram = assembleProgram(meshVertexShader, textureFragmentShader, mMeshParameters); 292e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA); 293e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 294e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 295e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 296e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static FloatBuffer createBuffer(float[] values) { 297e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // First create an nio buffer, then create a VBO from it. 298e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int size = values.length * FLOAT_SIZE; 299e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka FloatBuffer buffer = ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder()) 300e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka .asFloatBuffer(); 301e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka buffer.put(values, 0, values.length).position(0); 302e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return buffer; 303e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 304e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 305e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private int assembleProgram(int vertexShader, int fragmentShader, ShaderParameter[] params) { 306e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int program = GLES20.glCreateProgram(); 307e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 308e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (program == 0) { 309e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka throw new RuntimeException("Cannot create GL program: " + GLES20.glGetError()); 310e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 311e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glAttachShader(program, vertexShader); 312e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 313e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glAttachShader(program, fragmentShader); 314e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 315e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glLinkProgram(program); 316e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 317e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int[] mLinkStatus = mTempIntArray; 318e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, mLinkStatus, 0); 319e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (mLinkStatus[0] != GLES20.GL_TRUE) { 320e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Log.e(TAG, "Could not link program: "); 321e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Log.e(TAG, GLES20.glGetProgramInfoLog(program)); 322e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glDeleteProgram(program); 323e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka program = 0; 324e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 325e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka for (int i = 0; i < params.length; i++) { 326e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka params[i].loadHandle(program); 327e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 328e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return program; 329e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 330e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 331e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static int loadShader(int type, String shaderCode) { 332e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // create a vertex shader type (GLES20.GL_VERTEX_SHADER) 333e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER) 334e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int shader = GLES20.glCreateShader(type); 335e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 336e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // add the source code to the shader and compile it 337e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glShaderSource(shader, shaderCode); 338e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 339e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glCompileShader(shader); 340e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 341e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 342e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return shader; 343e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 344e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 345e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 346e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void setSize(int width, int height) { 347e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mWidth = width; 348e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mHeight = height; 349e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glViewport(0, 0, mWidth, mHeight); 350e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 351e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Matrix.setIdentityM(mMatrices, mCurrentMatrixIndex); 352e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Matrix.orthoM(mProjectionMatrix, 0, 0, width, 0, height, -1, 1); 353e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (getTargetTexture() == null) { 354e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mScreenWidth = width; 355e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mScreenHeight = height; 356e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Matrix.translateM(mMatrices, mCurrentMatrixIndex, 0, height, 0); 357e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Matrix.scaleM(mMatrices, mCurrentMatrixIndex, 1, -1, 1); 358e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 359e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 360e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 361e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 362e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void clearBuffer() { 363e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glClearColor(0f, 0f, 0f, 1f); 364e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 365e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 366e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 367e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 368e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 369e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 370e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void clearBuffer(float[] argb) { 371e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glClearColor(argb[1], argb[2], argb[3], argb[0]); 372e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 373e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 374e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 375e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 376e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 377e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 378e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public float getAlpha() { 379e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return mAlphas[mCurrentAlphaIndex]; 380e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 381e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 382e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 383e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void setAlpha(float alpha) { 384e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mAlphas[mCurrentAlphaIndex] = alpha; 385e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 386e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 387e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 388e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void multiplyAlpha(float alpha) { 389e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka setAlpha(getAlpha() * alpha); 390e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 391e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 392e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 393e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void translate(float x, float y, float z) { 394e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Matrix.translateM(mMatrices, mCurrentMatrixIndex, x, y, z); 395e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 396e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 397e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // This is a faster version of translate(x, y, z) because 398e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // (1) we knows z = 0, (2) we inline the Matrix.translateM call, 399e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // (3) we unroll the loop 400e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 401e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void translate(float x, float y) { 402e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int index = mCurrentMatrixIndex; 403e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka float[] m = mMatrices; 404e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka m[index + 12] += m[index + 0] * x + m[index + 4] * y; 405e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka m[index + 13] += m[index + 1] * x + m[index + 5] * y; 406e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka m[index + 14] += m[index + 2] * x + m[index + 6] * y; 407e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka m[index + 15] += m[index + 3] * x + m[index + 7] * y; 408e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 409e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 410e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 411e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void scale(float sx, float sy, float sz) { 412e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Matrix.scaleM(mMatrices, mCurrentMatrixIndex, sx, sy, sz); 413e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 414e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 415e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 416e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void rotate(float angle, float x, float y, float z) { 417e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (angle == 0f) { 418e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return; 419e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 420e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka float[] temp = mTempMatrix; 421e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Matrix.setRotateM(temp, 0, angle, x, y, z); 422e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka float[] matrix = mMatrices; 423e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int index = mCurrentMatrixIndex; 424e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Matrix.multiplyMM(temp, MATRIX_SIZE, matrix, index, temp, 0); 425e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka System.arraycopy(temp, MATRIX_SIZE, matrix, index, MATRIX_SIZE); 426e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 427e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 428e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 429e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void multiplyMatrix(float[] matrix, int offset) { 430e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka float[] temp = mTempMatrix; 431e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka float[] currentMatrix = mMatrices; 432e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int index = mCurrentMatrixIndex; 433e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Matrix.multiplyMM(temp, 0, currentMatrix, index, matrix, offset); 434e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka System.arraycopy(temp, 0, currentMatrix, index, 16); 435e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 436e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 437e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 438e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void save() { 439e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka save(SAVE_FLAG_ALL); 440e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 441e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 442e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 443e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void save(int saveFlags) { 444e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka boolean saveAlpha = (saveFlags & SAVE_FLAG_ALPHA) == SAVE_FLAG_ALPHA; 445e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (saveAlpha) { 446e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka float currentAlpha = getAlpha(); 447e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mCurrentAlphaIndex++; 448e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (mAlphas.length <= mCurrentAlphaIndex) { 449e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mAlphas = Arrays.copyOf(mAlphas, mAlphas.length * 2); 450e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 451e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mAlphas[mCurrentAlphaIndex] = currentAlpha; 452e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 453e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka boolean saveMatrix = (saveFlags & SAVE_FLAG_MATRIX) == SAVE_FLAG_MATRIX; 454e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (saveMatrix) { 455e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int currentIndex = mCurrentMatrixIndex; 456e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mCurrentMatrixIndex += MATRIX_SIZE; 457e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (mMatrices.length <= mCurrentMatrixIndex) { 458e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mMatrices = Arrays.copyOf(mMatrices, mMatrices.length * 2); 459e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 460e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka System.arraycopy(mMatrices, currentIndex, mMatrices, mCurrentMatrixIndex, MATRIX_SIZE); 461e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 462e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mSaveFlags.add(saveFlags); 463e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 464e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 465e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 466e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void restore() { 467e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int restoreFlags = mSaveFlags.removeLast(); 468e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka boolean restoreAlpha = (restoreFlags & SAVE_FLAG_ALPHA) == SAVE_FLAG_ALPHA; 469e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (restoreAlpha) { 470e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mCurrentAlphaIndex--; 471e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 472e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka boolean restoreMatrix = (restoreFlags & SAVE_FLAG_MATRIX) == SAVE_FLAG_MATRIX; 473e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (restoreMatrix) { 474e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mCurrentMatrixIndex -= MATRIX_SIZE; 475e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 476e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 477e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 478e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 479e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void drawLine(float x1, float y1, float x2, float y2, GLPaint paint) { 480e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka draw(GLES20.GL_LINE_STRIP, OFFSET_DRAW_LINE, COUNT_LINE_VERTEX, x1, y1, x2 - x1, y2 - y1, 481e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka paint); 482e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mCountDrawLine++; 483e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 484e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 485e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 486e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void drawRect(float x, float y, float width, float height, GLPaint paint) { 487e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka draw(GLES20.GL_LINE_LOOP, OFFSET_DRAW_RECT, COUNT_RECT_VERTEX, x, y, width, height, paint); 488e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mCountDrawLine++; 489e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 490e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 491e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private void draw(int type, int offset, int count, float x, float y, float width, float height, 492e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLPaint paint) { 493e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka draw(type, offset, count, x, y, width, height, paint.getColor(), paint.getLineWidth()); 494e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 495e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 496e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private void draw(int type, int offset, int count, float x, float y, float width, float height, 497e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int color, float lineWidth) { 498e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka prepareDraw(offset, color, lineWidth); 499e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka draw(mDrawParameters, type, count, x, y, width, height); 500e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 501e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 502e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private void prepareDraw(int offset, int color, float lineWidth) { 503e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glUseProgram(mDrawProgram); 504e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 505e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (lineWidth > 0) { 506e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glLineWidth(lineWidth); 507e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 508e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 509e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka float[] colorArray = getColor(color); 510e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka boolean blendingEnabled = (colorArray[3] < 1f); 511e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka enableBlending(blendingEnabled); 512e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (blendingEnabled) { 513e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glBlendColor(colorArray[0], colorArray[1], colorArray[2], colorArray[3]); 514e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 515e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 516e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 517e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glUniform4fv(mDrawParameters[INDEX_COLOR].handle, 1, colorArray, 0); 518e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka setPosition(mDrawParameters, offset); 519e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 520e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 521e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 522e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private float[] getColor(int color) { 523e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka float alpha = ((color >>> 24) & 0xFF) / 255f * getAlpha(); 524e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka float red = ((color >>> 16) & 0xFF) / 255f * alpha; 525e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka float green = ((color >>> 8) & 0xFF) / 255f * alpha; 526e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka float blue = (color & 0xFF) / 255f * alpha; 527e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mTempColor[0] = red; 528e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mTempColor[1] = green; 529e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mTempColor[2] = blue; 530e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mTempColor[3] = alpha; 531e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return mTempColor; 532e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 533e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 534e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private void enableBlending(boolean enableBlending) { 535e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (enableBlending) { 536e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glEnable(GLES20.GL_BLEND); 537e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 538e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else { 539e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glDisable(GLES20.GL_BLEND); 540e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 541e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 542e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 543e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 544e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private void setPosition(ShaderParameter[] params, int offset) { 545e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mBoxCoordinates); 546e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 547e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glVertexAttribPointer(params[INDEX_POSITION].handle, COORDS_PER_VERTEX, 548e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.GL_FLOAT, false, VERTEX_STRIDE, offset * VERTEX_STRIDE); 549e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 550e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); 551e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 552e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 553e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 554e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private void draw(ShaderParameter[] params, int type, int count, float x, float y, float width, 555e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka float height) { 556e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka setMatrix(params, x, y, width, height); 557e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int positionHandle = params[INDEX_POSITION].handle; 558e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glEnableVertexAttribArray(positionHandle); 559e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 560e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glDrawArrays(type, 0, count); 561e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 562e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glDisableVertexAttribArray(positionHandle); 563e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 564e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 565e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 566e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private void setMatrix(ShaderParameter[] params, float x, float y, float width, float height) { 567e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Matrix.translateM(mTempMatrix, 0, mMatrices, mCurrentMatrixIndex, x, y, 0f); 568e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Matrix.scaleM(mTempMatrix, 0, width, height, 1f); 569e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Matrix.multiplyMM(mTempMatrix, MATRIX_SIZE, mProjectionMatrix, 0, mTempMatrix, 0); 570e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glUniformMatrix4fv(params[INDEX_MATRIX].handle, 1, false, mTempMatrix, MATRIX_SIZE); 571e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 572e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 573e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 574e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 575e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void fillRect(float x, float y, float width, float height, int color) { 576e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka draw(GLES20.GL_TRIANGLE_STRIP, OFFSET_FILL_RECT, COUNT_FILL_VERTEX, x, y, width, height, 577e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka color, 0f); 578e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mCountFillRect++; 579e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 580e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 581e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 582e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void drawTexture(BasicTexture texture, int x, int y, int width, int height) { 583e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (width <= 0 || height <= 0) { 584e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return; 585e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 586e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka copyTextureCoordinates(texture, mTempSourceRect); 587e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mTempTargetRect.set(x, y, x + width, y + height); 588e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka convertCoordinate(mTempSourceRect, mTempTargetRect, texture); 589e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka drawTextureRect(texture, mTempSourceRect, mTempTargetRect); 590e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 591e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 592e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static void copyTextureCoordinates(BasicTexture texture, RectF outRect) { 593e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int left = 0; 594e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int top = 0; 595e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int right = texture.getWidth(); 596e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int bottom = texture.getHeight(); 597e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (texture.hasBorder()) { 598e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka left = 1; 599e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka top = 1; 600e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka right -= 1; 601e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka bottom -= 1; 602e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 603e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka outRect.set(left, top, right, bottom); 604e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 605e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 606e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 607e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void drawTexture(BasicTexture texture, RectF source, RectF target) { 608e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (target.width() <= 0 || target.height() <= 0) { 609e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return; 610e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 611e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mTempSourceRect.set(source); 612e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mTempTargetRect.set(target); 613e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 614e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka convertCoordinate(mTempSourceRect, mTempTargetRect, texture); 615e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka drawTextureRect(texture, mTempSourceRect, mTempTargetRect); 616e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 617e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 618e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 619e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void drawTexture(BasicTexture texture, float[] textureTransform, int x, int y, int w, 620e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int h) { 621e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (w <= 0 || h <= 0) { 622e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return; 623e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 624e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mTempTargetRect.set(x, y, x + w, y + h); 625e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka drawTextureRect(texture, textureTransform, mTempTargetRect); 626e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 627e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 628e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private void drawTextureRect(BasicTexture texture, RectF source, RectF target) { 629e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka setTextureMatrix(source); 630e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka drawTextureRect(texture, mTempTextureMatrix, target); 631e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 632e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 633e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private void setTextureMatrix(RectF source) { 634e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mTempTextureMatrix[0] = source.width(); 635e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mTempTextureMatrix[5] = source.height(); 636e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mTempTextureMatrix[12] = source.left; 637e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mTempTextureMatrix[13] = source.top; 638e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 639e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 640e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // This function changes the source coordinate to the texture coordinates. 641e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // It also clips the source and target coordinates if it is beyond the 642e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // bound of the texture. 643e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static void convertCoordinate(RectF source, RectF target, BasicTexture texture) { 644e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int width = texture.getWidth(); 645e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int height = texture.getHeight(); 646e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int texWidth = texture.getTextureWidth(); 647e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int texHeight = texture.getTextureHeight(); 648e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Convert to texture coordinates 649e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka source.left /= texWidth; 650e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka source.right /= texWidth; 651e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka source.top /= texHeight; 652e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka source.bottom /= texHeight; 653e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 654e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka // Clip if the rendering range is beyond the bound of the texture. 655e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka float xBound = (float) width / texWidth; 656e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (source.right > xBound) { 657e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka target.right = target.left + target.width() * (xBound - source.left) / source.width(); 658e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka source.right = xBound; 659e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 660e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka float yBound = (float) height / texHeight; 661e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (source.bottom > yBound) { 662e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka target.bottom = target.top + target.height() * (yBound - source.top) / source.height(); 663e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka source.bottom = yBound; 664e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 665e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 666e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 667e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private void drawTextureRect(BasicTexture texture, float[] textureMatrix, RectF target) { 668e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ShaderParameter[] params = prepareTexture(texture); 669e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka setPosition(params, OFFSET_FILL_RECT); 670e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glUniformMatrix4fv(params[INDEX_TEXTURE_MATRIX].handle, 1, false, textureMatrix, 0); 671e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 672e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (texture.isFlippedVertically()) { 673e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka save(SAVE_FLAG_MATRIX); 674e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka translate(0, target.centerY()); 675e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka scale(1, -1, 1); 676e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka translate(0, -target.centerY()); 677e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 678e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka draw(params, GLES20.GL_TRIANGLE_STRIP, COUNT_FILL_VERTEX, target.left, target.top, 679e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka target.width(), target.height()); 680e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (texture.isFlippedVertically()) { 681e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka restore(); 682e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 683e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mCountTextureRect++; 684e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 685e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 686e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private ShaderParameter[] prepareTexture(BasicTexture texture) { 687e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ShaderParameter[] params; 688e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int program; 689e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (texture.getTarget() == GLES20.GL_TEXTURE_2D) { 690e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka params = mTextureParameters; 691e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka program = mTextureProgram; 692e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else { 693e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka params = mOesTextureParameters; 694e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka program = mOesTextureProgram; 695e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 696e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka prepareTexture(texture, program, params); 697e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return params; 698e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 699e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 700e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private void prepareTexture(BasicTexture texture, int program, ShaderParameter[] params) { 701e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glUseProgram(program); 702e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 703e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka enableBlending(!texture.isOpaque() || getAlpha() < OPAQUE_ALPHA); 704e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 705e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 706e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka texture.onBind(this); 707e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glBindTexture(texture.getTarget(), texture.getId()); 708e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 709e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glUniform1i(params[INDEX_TEXTURE_SAMPLER].handle, 0); 710e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 711e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glUniform1f(params[INDEX_ALPHA].handle, getAlpha()); 712e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 713e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 714e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 715e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 716e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void drawMesh(BasicTexture texture, int x, int y, int xyBuffer, int uvBuffer, 717e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int indexBuffer, int indexCount) { 718e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka prepareTexture(texture, mMeshProgram, mMeshParameters); 719e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 720e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBuffer); 721e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 722e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 723e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, xyBuffer); 724e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 725e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int positionHandle = mMeshParameters[INDEX_POSITION].handle; 726e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 727e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka VERTEX_STRIDE, 0); 728e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 729e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 730e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, uvBuffer); 731e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 732e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int texCoordHandle = mMeshParameters[INDEX_TEXTURE_COORD].handle; 733e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glVertexAttribPointer(texCoordHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, 734e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka false, VERTEX_STRIDE, 0); 735e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 736e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); 737e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 738e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 739e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glEnableVertexAttribArray(positionHandle); 740e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 741e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glEnableVertexAttribArray(texCoordHandle); 742e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 743e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 744e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka setMatrix(mMeshParameters, x, y, 1, 1); 745e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, indexCount, GLES20.GL_UNSIGNED_BYTE, 0); 746e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 747e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 748e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glDisableVertexAttribArray(positionHandle); 749e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 750e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glDisableVertexAttribArray(texCoordHandle); 751e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 752e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); 753e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 754e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mCountDrawMesh++; 755e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 756e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 757e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 758e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void drawMixed(BasicTexture texture, int toColor, float ratio, int x, int y, int w, int h) { 759e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka copyTextureCoordinates(texture, mTempSourceRect); 760e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mTempTargetRect.set(x, y, x + w, y + h); 761e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka drawMixed(texture, toColor, ratio, mTempSourceRect, mTempTargetRect); 762e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 763e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 764e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 765e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void drawMixed(BasicTexture texture, int toColor, float ratio, RectF source, RectF target) { 766e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (target.width() <= 0 || target.height() <= 0) { 767e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return; 768e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 769e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka save(SAVE_FLAG_ALPHA); 770e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 771e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka float currentAlpha = getAlpha(); 772e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka float cappedRatio = Math.min(1f, Math.max(0f, ratio)); 773e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 774e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka float textureAlpha = (1f - cappedRatio) * currentAlpha; 775e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka setAlpha(textureAlpha); 776e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka drawTexture(texture, source, target); 777e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 778e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka float colorAlpha = cappedRatio * currentAlpha; 779e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka setAlpha(colorAlpha); 780e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka fillRect(target.left, target.top, target.width(), target.height(), toColor); 781e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 782e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka restore(); 783e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 784e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 785e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 786e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public boolean unloadTexture(BasicTexture texture) { 787e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka boolean unload = texture.isLoaded(); 788e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (unload) { 789e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka synchronized (mUnboundTextures) { 790e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mUnboundTextures.add(texture.getId()); 791e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 792e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 793e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return unload; 794e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 795e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 796e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 797e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void deleteBuffer(int bufferId) { 798e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka synchronized (mUnboundTextures) { 799e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mDeleteBuffers.add(bufferId); 800e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 801e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 802e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 803e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 804e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void deleteRecycledResources() { 805e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka synchronized (mUnboundTextures) { 806e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka IntArray ids = mUnboundTextures; 807e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (mUnboundTextures.size() > 0) { 808e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mGLId.glDeleteTextures(null, ids.size(), ids.getInternalArray(), 0); 809e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ids.clear(); 810e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 811e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 812e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ids = mDeleteBuffers; 813e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (ids.size() > 0) { 814e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mGLId.glDeleteBuffers(null, ids.size(), ids.getInternalArray(), 0); 815e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ids.clear(); 816e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 817e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 818e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 819e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 820e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 821e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void dumpStatisticsAndClear() { 822e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka String line = String.format("MESH:%d, TEX_RECT:%d, FILL_RECT:%d, LINE:%d", mCountDrawMesh, 823e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mCountTextureRect, mCountFillRect, mCountDrawLine); 824e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mCountDrawMesh = 0; 825e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mCountTextureRect = 0; 826e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mCountFillRect = 0; 827e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mCountDrawLine = 0; 828e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Log.d(TAG, line); 829e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 830e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 831e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 832e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void endRenderTarget() { 833e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka RawTexture oldTexture = mTargetTextures.remove(mTargetTextures.size() - 1); 834e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka RawTexture texture = getTargetTexture(); 835e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka setRenderTarget(oldTexture, texture); 836e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka restore(); // restore matrix and alpha 837e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 838e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 839e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 840e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void beginRenderTarget(RawTexture texture) { 841e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka save(); // save matrix and alpha and blending 842e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka RawTexture oldTexture = getTargetTexture(); 843e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mTargetTextures.add(texture); 844e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka setRenderTarget(oldTexture, texture); 845e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 846e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 847e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private RawTexture getTargetTexture() { 848e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return mTargetTextures.get(mTargetTextures.size() - 1); 849e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 850e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 851e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private void setRenderTarget(BasicTexture oldTexture, RawTexture texture) { 852e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (oldTexture == null && texture != null) { 853e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glGenFramebuffers(1, mFrameBuffer, 0); 854e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 855e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffer[0]); 856e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 857e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else if (oldTexture != null && texture == null) { 858e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 859e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 860e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glDeleteFramebuffers(1, mFrameBuffer, 0); 861e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 862e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 863e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 864e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (texture == null) { 865e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka setSize(mScreenWidth, mScreenHeight); 866e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else { 867e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka setSize(texture.getWidth(), texture.getHeight()); 868e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 869e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (!texture.isLoaded()) { 870e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka texture.prepare(this); 871e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 872e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 873e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, 874e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka texture.getTarget(), texture.getId(), 0); 875e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 876e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 877e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkFramebufferStatus(); 878e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 879e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 880e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 881e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static void checkFramebufferStatus() { 882e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER); 883e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (status != GLES20.GL_FRAMEBUFFER_COMPLETE) { 884e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka String msg = ""; 885e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka switch (status) { 886e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka case GLES20.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: 887e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka msg = "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; 888e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka break; 889e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka case GLES20.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: 890e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka msg = "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"; 891e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka break; 892e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka case GLES20.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: 893e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka msg = "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; 894e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka break; 895e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka case GLES20.GL_FRAMEBUFFER_UNSUPPORTED: 896e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka msg = "GL_FRAMEBUFFER_UNSUPPORTED"; 897e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka break; 898e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 899e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka throw new RuntimeException(msg + ":" + Integer.toHexString(status)); 900e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 901e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 902e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 903e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 904e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void setTextureParameters(BasicTexture texture) { 905e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int target = texture.getTarget(); 906e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glBindTexture(target, texture.getId()); 907e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 908e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 909e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 910e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glTexParameterf(target, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 911e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glTexParameterf(target, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 912e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 913e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 914e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 915e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void initializeTextureSize(BasicTexture texture, int format, int type) { 916e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int target = texture.getTarget(); 917e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glBindTexture(target, texture.getId()); 918e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 919e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int width = texture.getTextureWidth(); 920e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int height = texture.getTextureHeight(); 921e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glTexImage2D(target, 0, format, width, height, 0, format, type, null); 922e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 923e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 924e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 925e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void initializeTexture(BasicTexture texture, Bitmap bitmap) { 926e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int target = texture.getTarget(); 927e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glBindTexture(target, texture.getId()); 928e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 929e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLUtils.texImage2D(target, 0, bitmap, 0); 930e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 931e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 932e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 933e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void texSubImage2D(BasicTexture texture, int xOffset, int yOffset, Bitmap bitmap, 934e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int format, int type) { 935e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int target = texture.getTarget(); 936e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glBindTexture(target, texture.getId()); 937e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 938e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLUtils.texSubImage2D(target, 0, xOffset, yOffset, bitmap, format, type); 939e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 940e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 941e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 942e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public int uploadBuffer(FloatBuffer buf) { 943e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return uploadBuffer(buf, FLOAT_SIZE); 944e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 945e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 946e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 947e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public int uploadBuffer(ByteBuffer buf) { 948e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return uploadBuffer(buf, 1); 949e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 950e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 951e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private int uploadBuffer(Buffer buffer, int elementSize) { 952e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mGLId.glGenBuffers(1, mTempIntArray, 0); 953e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 954e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int bufferId = mTempIntArray[0]; 955e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, bufferId); 956e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 957e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, buffer.capacity() * elementSize, buffer, 958e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.GL_STATIC_DRAW); 959e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 960e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return bufferId; 961e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 962e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 963e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public static void checkError() { 964e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int error = GLES20.glGetError(); 965e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (error != 0) { 966e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Throwable t = new Throwable(); 967e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Log.e(TAG, "GL error: " + error, t); 968e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 969e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 970e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 971e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @SuppressWarnings("unused") 972e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static void printMatrix(String message, float[] m, int offset) { 973e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka StringBuilder b = new StringBuilder(message); 974e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka for (int i = 0; i < MATRIX_SIZE; i++) { 975e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka b.append(' '); 976e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (i % 4 == 0) { 977e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka b.append('\n'); 978e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 979e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka b.append(m[offset + i]); 980e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 981e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Log.v(TAG, b.toString()); 982e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 983e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 984e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 985e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void recoverFromLightCycle() { 986e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glViewport(0, 0, mWidth, mHeight); 987e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glDisable(GLES20.GL_DEPTH_TEST); 988e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA); 989e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka checkError(); 990e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 991e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 992e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 993e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public void getBounds(Rect bounds, int x, int y, int width, int height) { 994e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Matrix.translateM(mTempMatrix, 0, mMatrices, mCurrentMatrixIndex, x, y, 0f); 995e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Matrix.scaleM(mTempMatrix, 0, width, height, 1f); 996e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Matrix.multiplyMV(mTempMatrix, MATRIX_SIZE, mTempMatrix, 0, BOUNDS_COORDINATES, 0); 997e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Matrix.multiplyMV(mTempMatrix, MATRIX_SIZE + 4, mTempMatrix, 0, BOUNDS_COORDINATES, 4); 998e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka bounds.left = Math.round(mTempMatrix[MATRIX_SIZE]); 999e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka bounds.right = Math.round(mTempMatrix[MATRIX_SIZE + 4]); 1000e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka bounds.top = Math.round(mTempMatrix[MATRIX_SIZE + 1]); 1001e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka bounds.bottom = Math.round(mTempMatrix[MATRIX_SIZE + 5]); 1002e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka bounds.sort(); 1003e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 1004e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 1005e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 1006e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public GLId getGLId() { 1007e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return mGLId; 1008e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 1009e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka} 1010