1104c45677660586026a7e74ef8c47d396403d50eMichael Jurka/* 2104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Copyright (C) 2012 The Android Open Source Project 3104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * 4104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Licensed under the Apache License, Version 2.0 (the "License"); 5104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * you may not use this file except in compliance with the License. 6104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * You may obtain a copy of the License at 7104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * 8104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * http://www.apache.org/licenses/LICENSE-2.0 9104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * 10104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Unless required by applicable law or agreed to in writing, software 11104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * distributed under the License is distributed on an "AS IS" BASIS, 12104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * See the License for the specific language governing permissions and 14104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * limitations under the License. 15104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 16104c45677660586026a7e74ef8c47d396403d50eMichael Jurkapackage com.android.gallery3d.glrenderer; 17104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 18104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.graphics.Bitmap; 19104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.graphics.Rect; 20104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.graphics.RectF; 21104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.opengl.GLES20; 22104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.opengl.GLUtils; 23104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.opengl.Matrix; 24104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.util.Log; 25104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 26104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport com.android.gallery3d.util.IntArray; 27104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 28104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.nio.Buffer; 29104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.nio.ByteBuffer; 30104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.nio.ByteOrder; 31104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.nio.FloatBuffer; 32104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.util.ArrayList; 33104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.util.Arrays; 34104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 35104c45677660586026a7e74ef8c47d396403d50eMichael Jurkapublic class GLES20Canvas implements GLCanvas { 36104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // ************** Constants ********************** 37104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final String TAG = GLES20Canvas.class.getSimpleName(); 38104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final int FLOAT_SIZE = Float.SIZE / Byte.SIZE; 39104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final float OPAQUE_ALPHA = 0.95f; 40104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 41104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final int COORDS_PER_VERTEX = 2; 42104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final int VERTEX_STRIDE = COORDS_PER_VERTEX * FLOAT_SIZE; 43104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 44104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final int COUNT_FILL_VERTEX = 4; 45104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final int COUNT_LINE_VERTEX = 2; 46104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final int COUNT_RECT_VERTEX = 4; 47104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final int OFFSET_FILL_RECT = 0; 48104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final int OFFSET_DRAW_LINE = OFFSET_FILL_RECT + COUNT_FILL_VERTEX; 49104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final int OFFSET_DRAW_RECT = OFFSET_DRAW_LINE + COUNT_LINE_VERTEX; 50104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 51104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final float[] BOX_COORDINATES = { 52104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 0, 0, // Fill rectangle 53104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 1, 0, 54104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 0, 1, 55104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 1, 1, 56104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 0, 0, // Draw line 57104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 1, 1, 58104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 0, 0, // Draw rectangle outline 59104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 0, 1, 60104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 1, 1, 61104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 1, 0, 62104c45677660586026a7e74ef8c47d396403d50eMichael Jurka }; 63104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 64104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final float[] BOUNDS_COORDINATES = { 65104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 0, 0, 0, 1, 66104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 1, 1, 0, 1, 67104c45677660586026a7e74ef8c47d396403d50eMichael Jurka }; 68104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 69104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final String POSITION_ATTRIBUTE = "aPosition"; 70104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final String COLOR_UNIFORM = "uColor"; 71104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final String MATRIX_UNIFORM = "uMatrix"; 72104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final String TEXTURE_MATRIX_UNIFORM = "uTextureMatrix"; 73104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final String TEXTURE_SAMPLER_UNIFORM = "uTextureSampler"; 74104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final String ALPHA_UNIFORM = "uAlpha"; 75104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final String TEXTURE_COORD_ATTRIBUTE = "aTextureCoordinate"; 76104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 77104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final String DRAW_VERTEX_SHADER = "" 78104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "uniform mat4 " + MATRIX_UNIFORM + ";\n" 79104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "attribute vec2 " + POSITION_ATTRIBUTE + ";\n" 80104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "void main() {\n" 81104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + " vec4 pos = vec4(" + POSITION_ATTRIBUTE + ", 0.0, 1.0);\n" 82104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + " gl_Position = " + MATRIX_UNIFORM + " * pos;\n" 83104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "}\n"; 84104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 85104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final String DRAW_FRAGMENT_SHADER = "" 86104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "precision mediump float;\n" 87104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "uniform vec4 " + COLOR_UNIFORM + ";\n" 88104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "void main() {\n" 89104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + " gl_FragColor = " + COLOR_UNIFORM + ";\n" 90104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "}\n"; 91104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 92104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final String TEXTURE_VERTEX_SHADER = "" 93104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "uniform mat4 " + MATRIX_UNIFORM + ";\n" 94104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "uniform mat4 " + TEXTURE_MATRIX_UNIFORM + ";\n" 95104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "attribute vec2 " + POSITION_ATTRIBUTE + ";\n" 96104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "varying vec2 vTextureCoord;\n" 97104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "void main() {\n" 98104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + " vec4 pos = vec4(" + POSITION_ATTRIBUTE + ", 0.0, 1.0);\n" 99104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + " gl_Position = " + MATRIX_UNIFORM + " * pos;\n" 100104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + " vTextureCoord = (" + TEXTURE_MATRIX_UNIFORM + " * pos).xy;\n" 101104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "}\n"; 102104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 103104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final String MESH_VERTEX_SHADER = "" 104104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "uniform mat4 " + MATRIX_UNIFORM + ";\n" 105104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "attribute vec2 " + POSITION_ATTRIBUTE + ";\n" 106104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "attribute vec2 " + TEXTURE_COORD_ATTRIBUTE + ";\n" 107104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "varying vec2 vTextureCoord;\n" 108104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "void main() {\n" 109104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + " vec4 pos = vec4(" + POSITION_ATTRIBUTE + ", 0.0, 1.0);\n" 110104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + " gl_Position = " + MATRIX_UNIFORM + " * pos;\n" 111104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + " vTextureCoord = " + TEXTURE_COORD_ATTRIBUTE + ";\n" 112104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "}\n"; 113104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 114104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final String TEXTURE_FRAGMENT_SHADER = "" 115104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "precision mediump float;\n" 116104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "varying vec2 vTextureCoord;\n" 117104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "uniform float " + ALPHA_UNIFORM + ";\n" 118104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "uniform sampler2D " + TEXTURE_SAMPLER_UNIFORM + ";\n" 119104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "void main() {\n" 120104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + " gl_FragColor = texture2D(" + TEXTURE_SAMPLER_UNIFORM + ", vTextureCoord);\n" 121104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + " gl_FragColor *= " + ALPHA_UNIFORM + ";\n" 122104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "}\n"; 123104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 124104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final String OES_TEXTURE_FRAGMENT_SHADER = "" 125104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "#extension GL_OES_EGL_image_external : require\n" 126104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "precision mediump float;\n" 127104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "varying vec2 vTextureCoord;\n" 128104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "uniform float " + ALPHA_UNIFORM + ";\n" 129104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "uniform samplerExternalOES " + TEXTURE_SAMPLER_UNIFORM + ";\n" 130104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "void main() {\n" 131104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + " gl_FragColor = texture2D(" + TEXTURE_SAMPLER_UNIFORM + ", vTextureCoord);\n" 132104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + " gl_FragColor *= " + ALPHA_UNIFORM + ";\n" 133104c45677660586026a7e74ef8c47d396403d50eMichael Jurka + "}\n"; 134104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 135104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final int INITIAL_RESTORE_STATE_SIZE = 8; 136104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final int MATRIX_SIZE = 16; 137104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 138104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // Keep track of restore state 139104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private float[] mMatrices = new float[INITIAL_RESTORE_STATE_SIZE * MATRIX_SIZE]; 140104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private float[] mAlphas = new float[INITIAL_RESTORE_STATE_SIZE]; 141104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private IntArray mSaveFlags = new IntArray(); 142104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 143104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private int mCurrentAlphaIndex = 0; 144104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private int mCurrentMatrixIndex = 0; 145104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 146104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // Viewport size 147104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private int mWidth; 148104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private int mHeight; 149104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 150104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // Projection matrix 151104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private float[] mProjectionMatrix = new float[MATRIX_SIZE]; 152104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 153104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // Screen size for when we aren't bound to a texture 154104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private int mScreenWidth; 155104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private int mScreenHeight; 156104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 157104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // GL programs 158104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private int mDrawProgram; 159104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private int mTextureProgram; 160104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private int mOesTextureProgram; 161104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private int mMeshProgram; 162104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 163104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // GL buffer containing BOX_COORDINATES 164104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private int mBoxCoordinates; 165104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 166104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // Handle indices -- common 167104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final int INDEX_POSITION = 0; 168104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final int INDEX_MATRIX = 1; 169104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 170104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // Handle indices -- draw 171104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final int INDEX_COLOR = 2; 172104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 173104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // Handle indices -- texture 174104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final int INDEX_TEXTURE_MATRIX = 2; 175104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final int INDEX_TEXTURE_SAMPLER = 3; 176104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final int INDEX_ALPHA = 4; 177104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 178104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // Handle indices -- mesh 179104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final int INDEX_TEXTURE_COORD = 2; 180104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 181104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private abstract static class ShaderParameter { 182104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public int handle; 183104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected final String mName; 184104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 185104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public ShaderParameter(String name) { 186104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mName = name; 187104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 188104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 189104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public abstract void loadHandle(int program); 190104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 191104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 192104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static class UniformShaderParameter extends ShaderParameter { 193104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public UniformShaderParameter(String name) { 194104c45677660586026a7e74ef8c47d396403d50eMichael Jurka super(name); 195104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 196104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 197104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 198104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void loadHandle(int program) { 199104c45677660586026a7e74ef8c47d396403d50eMichael Jurka handle = GLES20.glGetUniformLocation(program, mName); 200104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 201104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 202104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 203104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 204104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static class AttributeShaderParameter extends ShaderParameter { 205104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public AttributeShaderParameter(String name) { 206104c45677660586026a7e74ef8c47d396403d50eMichael Jurka super(name); 207104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 208104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 209104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 210104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void loadHandle(int program) { 211104c45677660586026a7e74ef8c47d396403d50eMichael Jurka handle = GLES20.glGetAttribLocation(program, mName); 212104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 213104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 214104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 215104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 216104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ShaderParameter[] mDrawParameters = { 217104c45677660586026a7e74ef8c47d396403d50eMichael Jurka new AttributeShaderParameter(POSITION_ATTRIBUTE), // INDEX_POSITION 218104c45677660586026a7e74ef8c47d396403d50eMichael Jurka new UniformShaderParameter(MATRIX_UNIFORM), // INDEX_MATRIX 219104c45677660586026a7e74ef8c47d396403d50eMichael Jurka new UniformShaderParameter(COLOR_UNIFORM), // INDEX_COLOR 220104c45677660586026a7e74ef8c47d396403d50eMichael Jurka }; 221104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ShaderParameter[] mTextureParameters = { 222104c45677660586026a7e74ef8c47d396403d50eMichael Jurka new AttributeShaderParameter(POSITION_ATTRIBUTE), // INDEX_POSITION 223104c45677660586026a7e74ef8c47d396403d50eMichael Jurka new UniformShaderParameter(MATRIX_UNIFORM), // INDEX_MATRIX 224104c45677660586026a7e74ef8c47d396403d50eMichael Jurka new UniformShaderParameter(TEXTURE_MATRIX_UNIFORM), // INDEX_TEXTURE_MATRIX 225104c45677660586026a7e74ef8c47d396403d50eMichael Jurka new UniformShaderParameter(TEXTURE_SAMPLER_UNIFORM), // INDEX_TEXTURE_SAMPLER 226104c45677660586026a7e74ef8c47d396403d50eMichael Jurka new UniformShaderParameter(ALPHA_UNIFORM), // INDEX_ALPHA 227104c45677660586026a7e74ef8c47d396403d50eMichael Jurka }; 228104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ShaderParameter[] mOesTextureParameters = { 229104c45677660586026a7e74ef8c47d396403d50eMichael Jurka new AttributeShaderParameter(POSITION_ATTRIBUTE), // INDEX_POSITION 230104c45677660586026a7e74ef8c47d396403d50eMichael Jurka new UniformShaderParameter(MATRIX_UNIFORM), // INDEX_MATRIX 231104c45677660586026a7e74ef8c47d396403d50eMichael Jurka new UniformShaderParameter(TEXTURE_MATRIX_UNIFORM), // INDEX_TEXTURE_MATRIX 232104c45677660586026a7e74ef8c47d396403d50eMichael Jurka new UniformShaderParameter(TEXTURE_SAMPLER_UNIFORM), // INDEX_TEXTURE_SAMPLER 233104c45677660586026a7e74ef8c47d396403d50eMichael Jurka new UniformShaderParameter(ALPHA_UNIFORM), // INDEX_ALPHA 234104c45677660586026a7e74ef8c47d396403d50eMichael Jurka }; 235104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ShaderParameter[] mMeshParameters = { 236104c45677660586026a7e74ef8c47d396403d50eMichael Jurka new AttributeShaderParameter(POSITION_ATTRIBUTE), // INDEX_POSITION 237104c45677660586026a7e74ef8c47d396403d50eMichael Jurka new UniformShaderParameter(MATRIX_UNIFORM), // INDEX_MATRIX 238104c45677660586026a7e74ef8c47d396403d50eMichael Jurka new AttributeShaderParameter(TEXTURE_COORD_ATTRIBUTE), // INDEX_TEXTURE_COORD 239104c45677660586026a7e74ef8c47d396403d50eMichael Jurka new UniformShaderParameter(TEXTURE_SAMPLER_UNIFORM), // INDEX_TEXTURE_SAMPLER 240104c45677660586026a7e74ef8c47d396403d50eMichael Jurka new UniformShaderParameter(ALPHA_UNIFORM), // INDEX_ALPHA 241104c45677660586026a7e74ef8c47d396403d50eMichael Jurka }; 242104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 243104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private final IntArray mUnboundTextures = new IntArray(); 244104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private final IntArray mDeleteBuffers = new IntArray(); 245104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 246104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // Keep track of statistics for debugging 247104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private int mCountDrawMesh = 0; 248104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private int mCountTextureRect = 0; 249104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private int mCountFillRect = 0; 250104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private int mCountDrawLine = 0; 251104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 252104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // Buffer for framebuffer IDs -- we keep track so we can switch the attached 253104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // texture. 254104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private int[] mFrameBuffer = new int[1]; 255104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 256104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // Bound textures. 257104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private ArrayList<RawTexture> mTargetTextures = new ArrayList<RawTexture>(); 258104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 259104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // Temporary variables used within calculations 260104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private final float[] mTempMatrix = new float[32]; 261104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private final float[] mTempColor = new float[4]; 262104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private final RectF mTempSourceRect = new RectF(); 263104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private final RectF mTempTargetRect = new RectF(); 264104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private final float[] mTempTextureMatrix = new float[MATRIX_SIZE]; 265104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private final int[] mTempIntArray = new int[1]; 266104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 267104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final GLId mGLId = new GLES20IdImpl(); 268104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 269104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public GLES20Canvas() { 270104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Matrix.setIdentityM(mTempTextureMatrix, 0); 271104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Matrix.setIdentityM(mMatrices, mCurrentMatrixIndex); 272104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mAlphas[mCurrentAlphaIndex] = 1f; 273104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTargetTextures.add(null); 274104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 275104c45677660586026a7e74ef8c47d396403d50eMichael Jurka FloatBuffer boxBuffer = createBuffer(BOX_COORDINATES); 276104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mBoxCoordinates = uploadBuffer(boxBuffer); 277104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 278104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int drawVertexShader = loadShader(GLES20.GL_VERTEX_SHADER, DRAW_VERTEX_SHADER); 279104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int textureVertexShader = loadShader(GLES20.GL_VERTEX_SHADER, TEXTURE_VERTEX_SHADER); 280104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int meshVertexShader = loadShader(GLES20.GL_VERTEX_SHADER, MESH_VERTEX_SHADER); 281104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int drawFragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, DRAW_FRAGMENT_SHADER); 282104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int textureFragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, TEXTURE_FRAGMENT_SHADER); 283104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int oesTextureFragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, 284104c45677660586026a7e74ef8c47d396403d50eMichael Jurka OES_TEXTURE_FRAGMENT_SHADER); 285104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 286104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mDrawProgram = assembleProgram(drawVertexShader, drawFragmentShader, mDrawParameters); 287104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTextureProgram = assembleProgram(textureVertexShader, textureFragmentShader, 288104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTextureParameters); 289104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mOesTextureProgram = assembleProgram(textureVertexShader, oesTextureFragmentShader, 290104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mOesTextureParameters); 291104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mMeshProgram = assembleProgram(meshVertexShader, textureFragmentShader, mMeshParameters); 292104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA); 293104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 294104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 295104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 296104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static FloatBuffer createBuffer(float[] values) { 297104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // First create an nio buffer, then create a VBO from it. 298104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int size = values.length * FLOAT_SIZE; 299104c45677660586026a7e74ef8c47d396403d50eMichael Jurka FloatBuffer buffer = ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder()) 300104c45677660586026a7e74ef8c47d396403d50eMichael Jurka .asFloatBuffer(); 301104c45677660586026a7e74ef8c47d396403d50eMichael Jurka buffer.put(values, 0, values.length).position(0); 302104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return buffer; 303104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 304104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 305104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private int assembleProgram(int vertexShader, int fragmentShader, ShaderParameter[] params) { 306104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int program = GLES20.glCreateProgram(); 307104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 308104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (program == 0) { 309104c45677660586026a7e74ef8c47d396403d50eMichael Jurka throw new RuntimeException("Cannot create GL program: " + GLES20.glGetError()); 310104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 311104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glAttachShader(program, vertexShader); 312104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 313104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glAttachShader(program, fragmentShader); 314104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 315104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glLinkProgram(program); 316104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 317104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int[] mLinkStatus = mTempIntArray; 318104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, mLinkStatus, 0); 319104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (mLinkStatus[0] != GLES20.GL_TRUE) { 320104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Log.e(TAG, "Could not link program: "); 321104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Log.e(TAG, GLES20.glGetProgramInfoLog(program)); 322104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glDeleteProgram(program); 323104c45677660586026a7e74ef8c47d396403d50eMichael Jurka program = 0; 324104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 325104c45677660586026a7e74ef8c47d396403d50eMichael Jurka for (int i = 0; i < params.length; i++) { 326104c45677660586026a7e74ef8c47d396403d50eMichael Jurka params[i].loadHandle(program); 327104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 328104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return program; 329104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 330104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 331104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static int loadShader(int type, String shaderCode) { 332104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // create a vertex shader type (GLES20.GL_VERTEX_SHADER) 333104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER) 334104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int shader = GLES20.glCreateShader(type); 335104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 336104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // add the source code to the shader and compile it 337104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glShaderSource(shader, shaderCode); 338104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 339104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glCompileShader(shader); 340104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 341104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 342104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return shader; 343104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 344104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 345104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 346104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void setSize(int width, int height) { 347104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mWidth = width; 348104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mHeight = height; 349104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glViewport(0, 0, mWidth, mHeight); 350104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 351104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Matrix.setIdentityM(mMatrices, mCurrentMatrixIndex); 352104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Matrix.orthoM(mProjectionMatrix, 0, 0, width, 0, height, -1, 1); 353104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (getTargetTexture() == null) { 354104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mScreenWidth = width; 355104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mScreenHeight = height; 356104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Matrix.translateM(mMatrices, mCurrentMatrixIndex, 0, height, 0); 357104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Matrix.scaleM(mMatrices, mCurrentMatrixIndex, 1, -1, 1); 358104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 359104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 360104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 361104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 362104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void clearBuffer() { 363104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glClearColor(0f, 0f, 0f, 1f); 364104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 365104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 366104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 367104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 368104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 369104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 370104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void clearBuffer(float[] argb) { 371104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glClearColor(argb[1], argb[2], argb[3], argb[0]); 372104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 373104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 374104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 375104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 376104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 377104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 378104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public float getAlpha() { 379104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return mAlphas[mCurrentAlphaIndex]; 380104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 381104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 382104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 383104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void setAlpha(float alpha) { 384104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mAlphas[mCurrentAlphaIndex] = alpha; 385104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 386104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 387104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 388104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void multiplyAlpha(float alpha) { 389104c45677660586026a7e74ef8c47d396403d50eMichael Jurka setAlpha(getAlpha() * alpha); 390104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 391104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 392104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 393104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void translate(float x, float y, float z) { 394104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Matrix.translateM(mMatrices, mCurrentMatrixIndex, x, y, z); 395104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 396104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 397104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // This is a faster version of translate(x, y, z) because 398104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // (1) we knows z = 0, (2) we inline the Matrix.translateM call, 399104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // (3) we unroll the loop 400104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 401104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void translate(float x, float y) { 402104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int index = mCurrentMatrixIndex; 403104c45677660586026a7e74ef8c47d396403d50eMichael Jurka float[] m = mMatrices; 404104c45677660586026a7e74ef8c47d396403d50eMichael Jurka m[index + 12] += m[index + 0] * x + m[index + 4] * y; 405104c45677660586026a7e74ef8c47d396403d50eMichael Jurka m[index + 13] += m[index + 1] * x + m[index + 5] * y; 406104c45677660586026a7e74ef8c47d396403d50eMichael Jurka m[index + 14] += m[index + 2] * x + m[index + 6] * y; 407104c45677660586026a7e74ef8c47d396403d50eMichael Jurka m[index + 15] += m[index + 3] * x + m[index + 7] * y; 408104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 409104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 410104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 411104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void scale(float sx, float sy, float sz) { 412104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Matrix.scaleM(mMatrices, mCurrentMatrixIndex, sx, sy, sz); 413104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 414104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 415104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 416104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void rotate(float angle, float x, float y, float z) { 417104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (angle == 0f) { 418104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return; 419104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 420104c45677660586026a7e74ef8c47d396403d50eMichael Jurka float[] temp = mTempMatrix; 421104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Matrix.setRotateM(temp, 0, angle, x, y, z); 422104c45677660586026a7e74ef8c47d396403d50eMichael Jurka float[] matrix = mMatrices; 423104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int index = mCurrentMatrixIndex; 424104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Matrix.multiplyMM(temp, MATRIX_SIZE, matrix, index, temp, 0); 425104c45677660586026a7e74ef8c47d396403d50eMichael Jurka System.arraycopy(temp, MATRIX_SIZE, matrix, index, MATRIX_SIZE); 426104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 427104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 428104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 429104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void multiplyMatrix(float[] matrix, int offset) { 430104c45677660586026a7e74ef8c47d396403d50eMichael Jurka float[] temp = mTempMatrix; 431104c45677660586026a7e74ef8c47d396403d50eMichael Jurka float[] currentMatrix = mMatrices; 432104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int index = mCurrentMatrixIndex; 433104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Matrix.multiplyMM(temp, 0, currentMatrix, index, matrix, offset); 434104c45677660586026a7e74ef8c47d396403d50eMichael Jurka System.arraycopy(temp, 0, currentMatrix, index, 16); 435104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 436104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 437104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 438104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void save() { 439104c45677660586026a7e74ef8c47d396403d50eMichael Jurka save(SAVE_FLAG_ALL); 440104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 441104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 442104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 443104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void save(int saveFlags) { 444104c45677660586026a7e74ef8c47d396403d50eMichael Jurka boolean saveAlpha = (saveFlags & SAVE_FLAG_ALPHA) == SAVE_FLAG_ALPHA; 445104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (saveAlpha) { 446104c45677660586026a7e74ef8c47d396403d50eMichael Jurka float currentAlpha = getAlpha(); 447104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mCurrentAlphaIndex++; 448104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (mAlphas.length <= mCurrentAlphaIndex) { 449104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mAlphas = Arrays.copyOf(mAlphas, mAlphas.length * 2); 450104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 451104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mAlphas[mCurrentAlphaIndex] = currentAlpha; 452104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 453104c45677660586026a7e74ef8c47d396403d50eMichael Jurka boolean saveMatrix = (saveFlags & SAVE_FLAG_MATRIX) == SAVE_FLAG_MATRIX; 454104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (saveMatrix) { 455104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int currentIndex = mCurrentMatrixIndex; 456104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mCurrentMatrixIndex += MATRIX_SIZE; 457104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (mMatrices.length <= mCurrentMatrixIndex) { 458104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mMatrices = Arrays.copyOf(mMatrices, mMatrices.length * 2); 459104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 460104c45677660586026a7e74ef8c47d396403d50eMichael Jurka System.arraycopy(mMatrices, currentIndex, mMatrices, mCurrentMatrixIndex, MATRIX_SIZE); 461104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 462104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mSaveFlags.add(saveFlags); 463104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 464104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 465104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 466104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void restore() { 467104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int restoreFlags = mSaveFlags.removeLast(); 468104c45677660586026a7e74ef8c47d396403d50eMichael Jurka boolean restoreAlpha = (restoreFlags & SAVE_FLAG_ALPHA) == SAVE_FLAG_ALPHA; 469104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (restoreAlpha) { 470104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mCurrentAlphaIndex--; 471104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 472104c45677660586026a7e74ef8c47d396403d50eMichael Jurka boolean restoreMatrix = (restoreFlags & SAVE_FLAG_MATRIX) == SAVE_FLAG_MATRIX; 473104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (restoreMatrix) { 474104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mCurrentMatrixIndex -= MATRIX_SIZE; 475104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 476104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 477104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 478104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 479104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void drawLine(float x1, float y1, float x2, float y2, GLPaint paint) { 480104c45677660586026a7e74ef8c47d396403d50eMichael Jurka draw(GLES20.GL_LINE_STRIP, OFFSET_DRAW_LINE, COUNT_LINE_VERTEX, x1, y1, x2 - x1, y2 - y1, 481104c45677660586026a7e74ef8c47d396403d50eMichael Jurka paint); 482104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mCountDrawLine++; 483104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 484104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 485104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 486104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void drawRect(float x, float y, float width, float height, GLPaint paint) { 487104c45677660586026a7e74ef8c47d396403d50eMichael Jurka draw(GLES20.GL_LINE_LOOP, OFFSET_DRAW_RECT, COUNT_RECT_VERTEX, x, y, width, height, paint); 488104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mCountDrawLine++; 489104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 490104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 491104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private void draw(int type, int offset, int count, float x, float y, float width, float height, 492104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLPaint paint) { 493104c45677660586026a7e74ef8c47d396403d50eMichael Jurka draw(type, offset, count, x, y, width, height, paint.getColor(), paint.getLineWidth()); 494104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 495104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 496104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private void draw(int type, int offset, int count, float x, float y, float width, float height, 497104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int color, float lineWidth) { 498104c45677660586026a7e74ef8c47d396403d50eMichael Jurka prepareDraw(offset, color, lineWidth); 499104c45677660586026a7e74ef8c47d396403d50eMichael Jurka draw(mDrawParameters, type, count, x, y, width, height); 500104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 501104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 502104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private void prepareDraw(int offset, int color, float lineWidth) { 503104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glUseProgram(mDrawProgram); 504104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 505104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (lineWidth > 0) { 506104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glLineWidth(lineWidth); 507104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 508104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 509104c45677660586026a7e74ef8c47d396403d50eMichael Jurka float[] colorArray = getColor(color); 510104c45677660586026a7e74ef8c47d396403d50eMichael Jurka boolean blendingEnabled = (colorArray[3] < 1f); 511104c45677660586026a7e74ef8c47d396403d50eMichael Jurka enableBlending(blendingEnabled); 512104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (blendingEnabled) { 513104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glBlendColor(colorArray[0], colorArray[1], colorArray[2], colorArray[3]); 514104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 515104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 516104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 517104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glUniform4fv(mDrawParameters[INDEX_COLOR].handle, 1, colorArray, 0); 518104c45677660586026a7e74ef8c47d396403d50eMichael Jurka setPosition(mDrawParameters, offset); 519104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 520104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 521104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 522104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private float[] getColor(int color) { 523104c45677660586026a7e74ef8c47d396403d50eMichael Jurka float alpha = ((color >>> 24) & 0xFF) / 255f * getAlpha(); 524104c45677660586026a7e74ef8c47d396403d50eMichael Jurka float red = ((color >>> 16) & 0xFF) / 255f * alpha; 525104c45677660586026a7e74ef8c47d396403d50eMichael Jurka float green = ((color >>> 8) & 0xFF) / 255f * alpha; 526104c45677660586026a7e74ef8c47d396403d50eMichael Jurka float blue = (color & 0xFF) / 255f * alpha; 527104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTempColor[0] = red; 528104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTempColor[1] = green; 529104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTempColor[2] = blue; 530104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTempColor[3] = alpha; 531104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return mTempColor; 532104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 533104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 534104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private void enableBlending(boolean enableBlending) { 535104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (enableBlending) { 536104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glEnable(GLES20.GL_BLEND); 537104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 538104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } else { 539104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glDisable(GLES20.GL_BLEND); 540104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 541104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 542104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 543104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 544104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private void setPosition(ShaderParameter[] params, int offset) { 545104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mBoxCoordinates); 546104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 547104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glVertexAttribPointer(params[INDEX_POSITION].handle, COORDS_PER_VERTEX, 548104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.GL_FLOAT, false, VERTEX_STRIDE, offset * VERTEX_STRIDE); 549104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 550104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); 551104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 552104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 553104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 554104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private void draw(ShaderParameter[] params, int type, int count, float x, float y, float width, 555104c45677660586026a7e74ef8c47d396403d50eMichael Jurka float height) { 556104c45677660586026a7e74ef8c47d396403d50eMichael Jurka setMatrix(params, x, y, width, height); 557104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int positionHandle = params[INDEX_POSITION].handle; 558104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glEnableVertexAttribArray(positionHandle); 559104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 560104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glDrawArrays(type, 0, count); 561104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 562104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glDisableVertexAttribArray(positionHandle); 563104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 564104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 565104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 566104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private void setMatrix(ShaderParameter[] params, float x, float y, float width, float height) { 567104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Matrix.translateM(mTempMatrix, 0, mMatrices, mCurrentMatrixIndex, x, y, 0f); 568104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Matrix.scaleM(mTempMatrix, 0, width, height, 1f); 569104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Matrix.multiplyMM(mTempMatrix, MATRIX_SIZE, mProjectionMatrix, 0, mTempMatrix, 0); 570104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glUniformMatrix4fv(params[INDEX_MATRIX].handle, 1, false, mTempMatrix, MATRIX_SIZE); 571104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 572104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 573104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 574104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 575104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void fillRect(float x, float y, float width, float height, int color) { 576104c45677660586026a7e74ef8c47d396403d50eMichael Jurka draw(GLES20.GL_TRIANGLE_STRIP, OFFSET_FILL_RECT, COUNT_FILL_VERTEX, x, y, width, height, 577104c45677660586026a7e74ef8c47d396403d50eMichael Jurka color, 0f); 578104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mCountFillRect++; 579104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 580104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 581104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 582104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void drawTexture(BasicTexture texture, int x, int y, int width, int height) { 583104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (width <= 0 || height <= 0) { 584104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return; 585104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 586104c45677660586026a7e74ef8c47d396403d50eMichael Jurka copyTextureCoordinates(texture, mTempSourceRect); 587104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTempTargetRect.set(x, y, x + width, y + height); 588104c45677660586026a7e74ef8c47d396403d50eMichael Jurka convertCoordinate(mTempSourceRect, mTempTargetRect, texture); 589104c45677660586026a7e74ef8c47d396403d50eMichael Jurka drawTextureRect(texture, mTempSourceRect, mTempTargetRect); 590104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 591104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 592104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static void copyTextureCoordinates(BasicTexture texture, RectF outRect) { 593104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int left = 0; 594104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int top = 0; 595104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int right = texture.getWidth(); 596104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int bottom = texture.getHeight(); 597104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (texture.hasBorder()) { 598104c45677660586026a7e74ef8c47d396403d50eMichael Jurka left = 1; 599104c45677660586026a7e74ef8c47d396403d50eMichael Jurka top = 1; 600104c45677660586026a7e74ef8c47d396403d50eMichael Jurka right -= 1; 601104c45677660586026a7e74ef8c47d396403d50eMichael Jurka bottom -= 1; 602104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 603104c45677660586026a7e74ef8c47d396403d50eMichael Jurka outRect.set(left, top, right, bottom); 604104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 605104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 606104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 607104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void drawTexture(BasicTexture texture, RectF source, RectF target) { 608104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (target.width() <= 0 || target.height() <= 0) { 609104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return; 610104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 611104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTempSourceRect.set(source); 612104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTempTargetRect.set(target); 613104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 614104c45677660586026a7e74ef8c47d396403d50eMichael Jurka convertCoordinate(mTempSourceRect, mTempTargetRect, texture); 615104c45677660586026a7e74ef8c47d396403d50eMichael Jurka drawTextureRect(texture, mTempSourceRect, mTempTargetRect); 616104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 617104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 618104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 619104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void drawTexture(BasicTexture texture, float[] textureTransform, int x, int y, int w, 620104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int h) { 621104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (w <= 0 || h <= 0) { 622104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return; 623104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 624104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTempTargetRect.set(x, y, x + w, y + h); 625104c45677660586026a7e74ef8c47d396403d50eMichael Jurka drawTextureRect(texture, textureTransform, mTempTargetRect); 626104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 627104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 628104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private void drawTextureRect(BasicTexture texture, RectF source, RectF target) { 629104c45677660586026a7e74ef8c47d396403d50eMichael Jurka setTextureMatrix(source); 630104c45677660586026a7e74ef8c47d396403d50eMichael Jurka drawTextureRect(texture, mTempTextureMatrix, target); 631104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 632104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 633104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private void setTextureMatrix(RectF source) { 634104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTempTextureMatrix[0] = source.width(); 635104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTempTextureMatrix[5] = source.height(); 636104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTempTextureMatrix[12] = source.left; 637104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTempTextureMatrix[13] = source.top; 638104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 639104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 640104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // This function changes the source coordinate to the texture coordinates. 641104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // It also clips the source and target coordinates if it is beyond the 642104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // bound of the texture. 643104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static void convertCoordinate(RectF source, RectF target, BasicTexture texture) { 644104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int width = texture.getWidth(); 645104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int height = texture.getHeight(); 646104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int texWidth = texture.getTextureWidth(); 647104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int texHeight = texture.getTextureHeight(); 648104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // Convert to texture coordinates 649104c45677660586026a7e74ef8c47d396403d50eMichael Jurka source.left /= texWidth; 650104c45677660586026a7e74ef8c47d396403d50eMichael Jurka source.right /= texWidth; 651104c45677660586026a7e74ef8c47d396403d50eMichael Jurka source.top /= texHeight; 652104c45677660586026a7e74ef8c47d396403d50eMichael Jurka source.bottom /= texHeight; 653104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 654104c45677660586026a7e74ef8c47d396403d50eMichael Jurka // Clip if the rendering range is beyond the bound of the texture. 655104c45677660586026a7e74ef8c47d396403d50eMichael Jurka float xBound = (float) width / texWidth; 656104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (source.right > xBound) { 657104c45677660586026a7e74ef8c47d396403d50eMichael Jurka target.right = target.left + target.width() * (xBound - source.left) / source.width(); 658104c45677660586026a7e74ef8c47d396403d50eMichael Jurka source.right = xBound; 659104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 660104c45677660586026a7e74ef8c47d396403d50eMichael Jurka float yBound = (float) height / texHeight; 661104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (source.bottom > yBound) { 662104c45677660586026a7e74ef8c47d396403d50eMichael Jurka target.bottom = target.top + target.height() * (yBound - source.top) / source.height(); 663104c45677660586026a7e74ef8c47d396403d50eMichael Jurka source.bottom = yBound; 664104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 665104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 666104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 667104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private void drawTextureRect(BasicTexture texture, float[] textureMatrix, RectF target) { 668104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ShaderParameter[] params = prepareTexture(texture); 669104c45677660586026a7e74ef8c47d396403d50eMichael Jurka setPosition(params, OFFSET_FILL_RECT); 670104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glUniformMatrix4fv(params[INDEX_TEXTURE_MATRIX].handle, 1, false, textureMatrix, 0); 671104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 672104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (texture.isFlippedVertically()) { 673104c45677660586026a7e74ef8c47d396403d50eMichael Jurka save(SAVE_FLAG_MATRIX); 674104c45677660586026a7e74ef8c47d396403d50eMichael Jurka translate(0, target.centerY()); 675104c45677660586026a7e74ef8c47d396403d50eMichael Jurka scale(1, -1, 1); 676104c45677660586026a7e74ef8c47d396403d50eMichael Jurka translate(0, -target.centerY()); 677104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 678104c45677660586026a7e74ef8c47d396403d50eMichael Jurka draw(params, GLES20.GL_TRIANGLE_STRIP, COUNT_FILL_VERTEX, target.left, target.top, 679104c45677660586026a7e74ef8c47d396403d50eMichael Jurka target.width(), target.height()); 680104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (texture.isFlippedVertically()) { 681104c45677660586026a7e74ef8c47d396403d50eMichael Jurka restore(); 682104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 683104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mCountTextureRect++; 684104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 685104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 686104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private ShaderParameter[] prepareTexture(BasicTexture texture) { 687104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ShaderParameter[] params; 688104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int program; 689104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (texture.getTarget() == GLES20.GL_TEXTURE_2D) { 690104c45677660586026a7e74ef8c47d396403d50eMichael Jurka params = mTextureParameters; 691104c45677660586026a7e74ef8c47d396403d50eMichael Jurka program = mTextureProgram; 692104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } else { 693104c45677660586026a7e74ef8c47d396403d50eMichael Jurka params = mOesTextureParameters; 694104c45677660586026a7e74ef8c47d396403d50eMichael Jurka program = mOesTextureProgram; 695104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 696104c45677660586026a7e74ef8c47d396403d50eMichael Jurka prepareTexture(texture, program, params); 697104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return params; 698104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 699104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 700104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private void prepareTexture(BasicTexture texture, int program, ShaderParameter[] params) { 701104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glUseProgram(program); 702104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 703104c45677660586026a7e74ef8c47d396403d50eMichael Jurka enableBlending(!texture.isOpaque() || getAlpha() < OPAQUE_ALPHA); 704104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 705104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 706104c45677660586026a7e74ef8c47d396403d50eMichael Jurka texture.onBind(this); 707104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glBindTexture(texture.getTarget(), texture.getId()); 708104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 709104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glUniform1i(params[INDEX_TEXTURE_SAMPLER].handle, 0); 710104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 711104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glUniform1f(params[INDEX_ALPHA].handle, getAlpha()); 712104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 713104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 714104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 715104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 716104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void drawMesh(BasicTexture texture, int x, int y, int xyBuffer, int uvBuffer, 717104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int indexBuffer, int indexCount) { 718104c45677660586026a7e74ef8c47d396403d50eMichael Jurka prepareTexture(texture, mMeshProgram, mMeshParameters); 719104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 720104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBuffer); 721104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 722104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 723104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, xyBuffer); 724104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 725104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int positionHandle = mMeshParameters[INDEX_POSITION].handle; 726104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 727104c45677660586026a7e74ef8c47d396403d50eMichael Jurka VERTEX_STRIDE, 0); 728104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 729104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 730104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, uvBuffer); 731104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 732104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int texCoordHandle = mMeshParameters[INDEX_TEXTURE_COORD].handle; 733104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glVertexAttribPointer(texCoordHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, 734104c45677660586026a7e74ef8c47d396403d50eMichael Jurka false, VERTEX_STRIDE, 0); 735104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 736104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); 737104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 738104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 739104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glEnableVertexAttribArray(positionHandle); 740104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 741104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glEnableVertexAttribArray(texCoordHandle); 742104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 743104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 744104c45677660586026a7e74ef8c47d396403d50eMichael Jurka setMatrix(mMeshParameters, x, y, 1, 1); 745104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, indexCount, GLES20.GL_UNSIGNED_BYTE, 0); 746104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 747104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 748104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glDisableVertexAttribArray(positionHandle); 749104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 750104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glDisableVertexAttribArray(texCoordHandle); 751104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 752104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); 753104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 754104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mCountDrawMesh++; 755104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 756104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 757104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 758104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void drawMixed(BasicTexture texture, int toColor, float ratio, int x, int y, int w, int h) { 759104c45677660586026a7e74ef8c47d396403d50eMichael Jurka copyTextureCoordinates(texture, mTempSourceRect); 760104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTempTargetRect.set(x, y, x + w, y + h); 761104c45677660586026a7e74ef8c47d396403d50eMichael Jurka drawMixed(texture, toColor, ratio, mTempSourceRect, mTempTargetRect); 762104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 763104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 764104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 765104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void drawMixed(BasicTexture texture, int toColor, float ratio, RectF source, RectF target) { 766104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (target.width() <= 0 || target.height() <= 0) { 767104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return; 768104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 769104c45677660586026a7e74ef8c47d396403d50eMichael Jurka save(SAVE_FLAG_ALPHA); 770104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 771104c45677660586026a7e74ef8c47d396403d50eMichael Jurka float currentAlpha = getAlpha(); 772104c45677660586026a7e74ef8c47d396403d50eMichael Jurka float cappedRatio = Math.min(1f, Math.max(0f, ratio)); 773104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 774104c45677660586026a7e74ef8c47d396403d50eMichael Jurka float textureAlpha = (1f - cappedRatio) * currentAlpha; 775104c45677660586026a7e74ef8c47d396403d50eMichael Jurka setAlpha(textureAlpha); 776104c45677660586026a7e74ef8c47d396403d50eMichael Jurka drawTexture(texture, source, target); 777104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 778104c45677660586026a7e74ef8c47d396403d50eMichael Jurka float colorAlpha = cappedRatio * currentAlpha; 779104c45677660586026a7e74ef8c47d396403d50eMichael Jurka setAlpha(colorAlpha); 780104c45677660586026a7e74ef8c47d396403d50eMichael Jurka fillRect(target.left, target.top, target.width(), target.height(), toColor); 781104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 782104c45677660586026a7e74ef8c47d396403d50eMichael Jurka restore(); 783104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 784104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 785104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 786104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public boolean unloadTexture(BasicTexture texture) { 787104c45677660586026a7e74ef8c47d396403d50eMichael Jurka boolean unload = texture.isLoaded(); 788104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (unload) { 789104c45677660586026a7e74ef8c47d396403d50eMichael Jurka synchronized (mUnboundTextures) { 790104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mUnboundTextures.add(texture.getId()); 791104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 792104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 793104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return unload; 794104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 795104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 796104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 797104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void deleteBuffer(int bufferId) { 798104c45677660586026a7e74ef8c47d396403d50eMichael Jurka synchronized (mUnboundTextures) { 799104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mDeleteBuffers.add(bufferId); 800104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 801104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 802104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 803104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 804104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void deleteRecycledResources() { 805104c45677660586026a7e74ef8c47d396403d50eMichael Jurka synchronized (mUnboundTextures) { 806104c45677660586026a7e74ef8c47d396403d50eMichael Jurka IntArray ids = mUnboundTextures; 807104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (mUnboundTextures.size() > 0) { 808104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mGLId.glDeleteTextures(null, ids.size(), ids.getInternalArray(), 0); 809104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ids.clear(); 810104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 811104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 812104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ids = mDeleteBuffers; 813104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (ids.size() > 0) { 814104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mGLId.glDeleteBuffers(null, ids.size(), ids.getInternalArray(), 0); 815104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ids.clear(); 816104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 817104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 818104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 819104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 820104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 821104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void dumpStatisticsAndClear() { 822104c45677660586026a7e74ef8c47d396403d50eMichael Jurka String line = String.format("MESH:%d, TEX_RECT:%d, FILL_RECT:%d, LINE:%d", mCountDrawMesh, 823104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mCountTextureRect, mCountFillRect, mCountDrawLine); 824104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mCountDrawMesh = 0; 825104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mCountTextureRect = 0; 826104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mCountFillRect = 0; 827104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mCountDrawLine = 0; 828104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Log.d(TAG, line); 829104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 830104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 831104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 832104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void endRenderTarget() { 833104c45677660586026a7e74ef8c47d396403d50eMichael Jurka RawTexture oldTexture = mTargetTextures.remove(mTargetTextures.size() - 1); 834104c45677660586026a7e74ef8c47d396403d50eMichael Jurka RawTexture texture = getTargetTexture(); 835104c45677660586026a7e74ef8c47d396403d50eMichael Jurka setRenderTarget(oldTexture, texture); 836104c45677660586026a7e74ef8c47d396403d50eMichael Jurka restore(); // restore matrix and alpha 837104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 838104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 839104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 840104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void beginRenderTarget(RawTexture texture) { 841104c45677660586026a7e74ef8c47d396403d50eMichael Jurka save(); // save matrix and alpha and blending 842104c45677660586026a7e74ef8c47d396403d50eMichael Jurka RawTexture oldTexture = getTargetTexture(); 843104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mTargetTextures.add(texture); 844104c45677660586026a7e74ef8c47d396403d50eMichael Jurka setRenderTarget(oldTexture, texture); 845104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 846104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 847104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private RawTexture getTargetTexture() { 848104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return mTargetTextures.get(mTargetTextures.size() - 1); 849104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 850104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 851104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private void setRenderTarget(BasicTexture oldTexture, RawTexture texture) { 852104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (oldTexture == null && texture != null) { 853104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glGenFramebuffers(1, mFrameBuffer, 0); 854104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 855104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffer[0]); 856104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 857104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } else if (oldTexture != null && texture == null) { 858104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 859104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 860104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glDeleteFramebuffers(1, mFrameBuffer, 0); 861104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 862104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 863104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 864104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (texture == null) { 865104c45677660586026a7e74ef8c47d396403d50eMichael Jurka setSize(mScreenWidth, mScreenHeight); 866104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } else { 867104c45677660586026a7e74ef8c47d396403d50eMichael Jurka setSize(texture.getWidth(), texture.getHeight()); 868104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 869104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (!texture.isLoaded()) { 870104c45677660586026a7e74ef8c47d396403d50eMichael Jurka texture.prepare(this); 871104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 872104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 873104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, 874104c45677660586026a7e74ef8c47d396403d50eMichael Jurka texture.getTarget(), texture.getId(), 0); 875104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 876104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 877104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkFramebufferStatus(); 878104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 879104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 880104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 881104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static void checkFramebufferStatus() { 882104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER); 883104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (status != GLES20.GL_FRAMEBUFFER_COMPLETE) { 884104c45677660586026a7e74ef8c47d396403d50eMichael Jurka String msg = ""; 885104c45677660586026a7e74ef8c47d396403d50eMichael Jurka switch (status) { 886104c45677660586026a7e74ef8c47d396403d50eMichael Jurka case GLES20.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: 887104c45677660586026a7e74ef8c47d396403d50eMichael Jurka msg = "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; 888104c45677660586026a7e74ef8c47d396403d50eMichael Jurka break; 889104c45677660586026a7e74ef8c47d396403d50eMichael Jurka case GLES20.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: 890104c45677660586026a7e74ef8c47d396403d50eMichael Jurka msg = "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"; 891104c45677660586026a7e74ef8c47d396403d50eMichael Jurka break; 892104c45677660586026a7e74ef8c47d396403d50eMichael Jurka case GLES20.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: 893104c45677660586026a7e74ef8c47d396403d50eMichael Jurka msg = "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; 894104c45677660586026a7e74ef8c47d396403d50eMichael Jurka break; 895104c45677660586026a7e74ef8c47d396403d50eMichael Jurka case GLES20.GL_FRAMEBUFFER_UNSUPPORTED: 896104c45677660586026a7e74ef8c47d396403d50eMichael Jurka msg = "GL_FRAMEBUFFER_UNSUPPORTED"; 897104c45677660586026a7e74ef8c47d396403d50eMichael Jurka break; 898104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 899104c45677660586026a7e74ef8c47d396403d50eMichael Jurka throw new RuntimeException(msg + ":" + Integer.toHexString(status)); 900104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 901104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 902104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 903104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 904104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void setTextureParameters(BasicTexture texture) { 905104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int target = texture.getTarget(); 906104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glBindTexture(target, texture.getId()); 907104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 908104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 909104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 910104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glTexParameterf(target, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 911104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glTexParameterf(target, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 912104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 913104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 914104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 915104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void initializeTextureSize(BasicTexture texture, int format, int type) { 916104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int target = texture.getTarget(); 917104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glBindTexture(target, texture.getId()); 918104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 919104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int width = texture.getTextureWidth(); 920104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int height = texture.getTextureHeight(); 921104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glTexImage2D(target, 0, format, width, height, 0, format, type, null); 922104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 923104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 924104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 925104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void initializeTexture(BasicTexture texture, Bitmap bitmap) { 926104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int target = texture.getTarget(); 927104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glBindTexture(target, texture.getId()); 928104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 929104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLUtils.texImage2D(target, 0, bitmap, 0); 930104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 931104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 932104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 933104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void texSubImage2D(BasicTexture texture, int xOffset, int yOffset, Bitmap bitmap, 934104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int format, int type) { 935104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int target = texture.getTarget(); 936104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glBindTexture(target, texture.getId()); 937104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 938104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLUtils.texSubImage2D(target, 0, xOffset, yOffset, bitmap, format, type); 939104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 940104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 941104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 942104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public int uploadBuffer(FloatBuffer buf) { 943104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return uploadBuffer(buf, FLOAT_SIZE); 944104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 945104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 946104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 947104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public int uploadBuffer(ByteBuffer buf) { 948104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return uploadBuffer(buf, 1); 949104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 950104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 951104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private int uploadBuffer(Buffer buffer, int elementSize) { 952104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mGLId.glGenBuffers(1, mTempIntArray, 0); 953104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 954104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int bufferId = mTempIntArray[0]; 955104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, bufferId); 956104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 957104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, buffer.capacity() * elementSize, buffer, 958104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.GL_STATIC_DRAW); 959104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 960104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return bufferId; 961104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 962104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 963104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public static void checkError() { 964104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int error = GLES20.glGetError(); 965104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (error != 0) { 966104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Throwable t = new Throwable(); 967104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Log.e(TAG, "GL error: " + error, t); 968104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 969104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 970104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 971104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @SuppressWarnings("unused") 972104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static void printMatrix(String message, float[] m, int offset) { 973104c45677660586026a7e74ef8c47d396403d50eMichael Jurka StringBuilder b = new StringBuilder(message); 974104c45677660586026a7e74ef8c47d396403d50eMichael Jurka for (int i = 0; i < MATRIX_SIZE; i++) { 975104c45677660586026a7e74ef8c47d396403d50eMichael Jurka b.append(' '); 976104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (i % 4 == 0) { 977104c45677660586026a7e74ef8c47d396403d50eMichael Jurka b.append('\n'); 978104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 979104c45677660586026a7e74ef8c47d396403d50eMichael Jurka b.append(m[offset + i]); 980104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 981104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Log.v(TAG, b.toString()); 982104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 983104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 984104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 985104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void recoverFromLightCycle() { 986104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glViewport(0, 0, mWidth, mHeight); 987104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glDisable(GLES20.GL_DEPTH_TEST); 988104c45677660586026a7e74ef8c47d396403d50eMichael Jurka GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA); 989104c45677660586026a7e74ef8c47d396403d50eMichael Jurka checkError(); 990104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 991104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 992104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 993104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public void getBounds(Rect bounds, int x, int y, int width, int height) { 994104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Matrix.translateM(mTempMatrix, 0, mMatrices, mCurrentMatrixIndex, x, y, 0f); 995104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Matrix.scaleM(mTempMatrix, 0, width, height, 1f); 996104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Matrix.multiplyMV(mTempMatrix, MATRIX_SIZE, mTempMatrix, 0, BOUNDS_COORDINATES, 0); 997104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Matrix.multiplyMV(mTempMatrix, MATRIX_SIZE + 4, mTempMatrix, 0, BOUNDS_COORDINATES, 4); 998104c45677660586026a7e74ef8c47d396403d50eMichael Jurka bounds.left = Math.round(mTempMatrix[MATRIX_SIZE]); 999104c45677660586026a7e74ef8c47d396403d50eMichael Jurka bounds.right = Math.round(mTempMatrix[MATRIX_SIZE + 4]); 1000104c45677660586026a7e74ef8c47d396403d50eMichael Jurka bounds.top = Math.round(mTempMatrix[MATRIX_SIZE + 1]); 1001104c45677660586026a7e74ef8c47d396403d50eMichael Jurka bounds.bottom = Math.round(mTempMatrix[MATRIX_SIZE + 5]); 1002104c45677660586026a7e74ef8c47d396403d50eMichael Jurka bounds.sort(); 1003104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 1004104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 1005104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 1006104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public GLId getGLId() { 1007104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return mGLId; 1008104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 1009104c45677660586026a7e74ef8c47d396403d50eMichael Jurka} 1010