1227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/* 2227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Copyright (C) 2012 The Android Open Source Project 3227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 4227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Licensed under the Apache License, Version 2.0 (the "License"); 5227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * you may not use this file except in compliance with the License. 6227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * You may obtain a copy of the License at 7227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 8227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * http://www.apache.org/licenses/LICENSE-2.0 9227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 10227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Unless required by applicable law or agreed to in writing, software 11227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * distributed under the License is distributed on an "AS IS" BASIS, 12227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * See the License for the specific language governing permissions and 14227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * limitations under the License. 15227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 16227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 17227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspackage androidx.media.filterfw; 18227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 19227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.graphics.RectF; 20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.opengl.GLES20; 21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.util.Log; 22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.geometry.Quad; 24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.nio.ByteBuffer; 26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.nio.ByteOrder; 27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.nio.FloatBuffer; 28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.Arrays; 29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.HashMap; 30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/** 32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Convenience class to perform GL shader operations on image data. 33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * <p> 34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The ImageShader class greatly simplifies the task of running GL shader language kernels over 35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Frame data buffers that contain RGBA image data. 36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * </p><p> 37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * TODO: More documentation 38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * </p> 39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspublic class ImageShader { 41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mProgram = 0; 43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private boolean mClearsOutput = false; 44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float[] mClearColor = { 0f, 0f, 0f, 0f }; 45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private boolean mBlendEnabled = false; 46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mSFactor = GLES20.GL_SRC_ALPHA; 47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mDFactor = GLES20.GL_ONE_MINUS_SRC_ALPHA; 48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mDrawMode = GLES20.GL_TRIANGLE_STRIP; 49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mVertexCount = 4; 50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mBaseTexUnit = GLES20.GL_TEXTURE0; 51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mClearBuffers = GLES20.GL_COLOR_BUFFER_BIT; 52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float[] mSourceCoords = new float[] { 0f, 0f, 1f, 0f, 0f, 1f, 1f, 1f }; 53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private float[] mTargetCoords = new float[] { -1f, -1f, 1f, -1f, -1f, 1f, 1f, 1f }; 54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private HashMap<String, ProgramUniform> mUniforms; 56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private HashMap<String, VertexAttribute> mAttributes = new HashMap<String, VertexAttribute>(); 57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final static int FLOAT_SIZE = 4; 59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final static String mDefaultVertexShader = 61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks "attribute vec4 a_position;\n" + 62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks "attribute vec2 a_texcoord;\n" + 63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks "varying vec2 v_texcoord;\n" + 64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks "void main() {\n" + 65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks " gl_Position = a_position;\n" + 66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks " v_texcoord = a_texcoord;\n" + 67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks "}\n"; 68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final static String mIdentityShader = 70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks "precision mediump float;\n" + 71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks "uniform sampler2D tex_sampler_0;\n" + 72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks "varying vec2 v_texcoord;\n" + 73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks "void main() {\n" + 74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks " gl_FragColor = texture2D(tex_sampler_0, v_texcoord);\n" + 75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks "}\n"; 76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static class VertexAttribute { 78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private String mName; 79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private boolean mIsConst; 80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mIndex; 81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private boolean mShouldNormalize; 82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mOffset; 83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mStride; 84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mComponents; 85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mType; 86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mVbo; 87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mLength; 88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private FloatBuffer mValues; 89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public VertexAttribute(String name, int index) { 91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mName = name; 92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mIndex = index; 93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mLength = -1; 94227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 95227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 96227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void set(boolean normalize, int stride, int components, int type, float[] values) { 97227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mIsConst = false; 98227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mShouldNormalize = normalize; 99227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mStride = stride; 100227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mComponents = components; 101227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mType = type; 102227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mVbo = 0; 103227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mLength != values.length){ 104227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks initBuffer(values); 105227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mLength = values.length; 106227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 107227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks copyValues(values); 108227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 109227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 110227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void set(boolean normalize, int offset, int stride, int components, int type, 111227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int vbo){ 112227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mIsConst = false; 113227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mShouldNormalize = normalize; 114227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mOffset = offset; 115227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mStride = stride; 116227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mComponents = components; 117227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mType = type; 118227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mVbo = vbo; 119227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mValues = null; 120227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 121227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 122227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public boolean push() { 123227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mIsConst) { 124227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks switch (mComponents) { 125227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case 1: 126227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glVertexAttrib1fv(mIndex, mValues); 127227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 128227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case 2: 129227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glVertexAttrib2fv(mIndex, mValues); 130227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 131227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case 3: 132227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glVertexAttrib3fv(mIndex, mValues); 133227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 134227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case 4: 135227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glVertexAttrib4fv(mIndex, mValues); 136227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 137227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks default: 138227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return false; 139227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 140227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glDisableVertexAttribArray(mIndex); 141227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 142227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mValues != null) { 143227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Note that we cannot do any size checking here, as the correct component 144227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // count depends on the drawing step. GL should catch such errors then, and 145227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // we will report them to the user. 146227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); 147227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glVertexAttribPointer(mIndex, 148227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mComponents, 149227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mType, 150227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mShouldNormalize, 151227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mStride, 152227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mValues); 153227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 154227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVbo); 155227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glVertexAttribPointer(mIndex, 156227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mComponents, 157227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mType, 158227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mShouldNormalize, 159227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mStride, 160227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mOffset); 161227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 162227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glEnableVertexAttribArray(mIndex); 163227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 164227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLToolbox.checkGlError("Set vertex-attribute values"); 165227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return true; 166227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 167227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 168227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 169227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public String toString() { 170227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mName; 171227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 172227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 173227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void initBuffer(float[] values) { 174227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mValues = ByteBuffer.allocateDirect(values.length * FLOAT_SIZE) 175227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .order(ByteOrder.nativeOrder()).asFloatBuffer(); 176227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 177227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 178227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void copyValues(float[] values) { 179227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mValues.put(values).position(0); 180227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 181227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 182227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 183227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 184227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static final class ProgramUniform { 185227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private String mName; 186227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mLocation; 187227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mType; 188227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mSize; 189227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 190227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public ProgramUniform(int program, int index) { 191227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int[] len = new int[1]; 192227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glGetProgramiv(program, GLES20.GL_ACTIVE_UNIFORM_MAX_LENGTH, len, 0); 193227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 194227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int[] type = new int[1]; 195227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int[] size = new int[1]; 196227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks byte[] name = new byte[len[0]]; 197227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int[] ignore = new int[1]; 198227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 199227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glGetActiveUniform(program, index, len[0], ignore, 0, size, 0, type, 0, name, 0); 200227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mName = new String(name, 0, strlen(name)); 201227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mLocation = GLES20.glGetUniformLocation(program, mName); 202227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mType = type[0]; 203227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mSize = size[0]; 204227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLToolbox.checkGlError("Initializing uniform"); 205227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 206227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 207227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public String getName() { 208227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mName; 209227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 210227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 211227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public int getType() { 212227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mType; 213227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 214227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 215227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public int getLocation() { 216227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mLocation; 217227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 218227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 219227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public int getSize() { 220227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mSize; 221227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 222227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 223227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 224227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public ImageShader(String fragmentShader) { 225227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mProgram = createProgram(mDefaultVertexShader, fragmentShader); 226227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks scanUniforms(); 227227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 228227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 229227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public ImageShader(String vertexShader, String fragmentShader) { 230227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mProgram = createProgram(vertexShader, fragmentShader); 231227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks scanUniforms(); 232227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 233227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 234227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static ImageShader createIdentity() { 235227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new ImageShader(mIdentityShader); 236227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 237227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 238227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static ImageShader createIdentity(String vertexShader) { 239227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new ImageShader(vertexShader, mIdentityShader); 240227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 241227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 242227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static void renderTextureToTarget(TextureSource texture, 243227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks RenderTarget target, 244227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int width, 245227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int height) { 246227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ImageShader shader = RenderTarget.currentTarget().getIdentityShader(); 247227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks shader.process(texture, target, width, height); 248227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 249227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 250227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void process(FrameImage2D input, FrameImage2D output) { 251227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks TextureSource texSource = input.lockTextureSource(); 252227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks RenderTarget renderTarget = output.lockRenderTarget(); 253227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks processMulti(new TextureSource[] { texSource }, 254227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks renderTarget, 255227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks output.getWidth(), 256227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks output.getHeight()); 257227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks input.unlock(); 258227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks output.unlock(); 259227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 260227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 261227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void processMulti(FrameImage2D[] inputs, FrameImage2D output) { 262227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks TextureSource[] texSources = new TextureSource[inputs.length]; 263227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (int i = 0; i < inputs.length; ++i) { 264227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks texSources[i] = inputs[i].lockTextureSource(); 265227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 266227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks RenderTarget renderTarget = output.lockRenderTarget(); 267227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks processMulti(texSources, 268227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks renderTarget, 269227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks output.getWidth(), 270227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks output.getHeight()); 271227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (FrameImage2D input : inputs) { 272227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks input.unlock(); 273227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 274227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks output.unlock(); 275227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 276227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 277227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void process(TextureSource texture, RenderTarget target, int width, int height) { 278227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks processMulti(new TextureSource[] { texture }, target, width, height); 279227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 280227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 281227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void processMulti(TextureSource[] sources, RenderTarget target, int width, int height) { 282227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLToolbox.checkGlError("Unknown Operation"); 283227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkExecutable(); 284227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkTexCount(sources.length); 285227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks focusTarget(target, width, height); 286227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks pushShaderState(); 287227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks bindInputTextures(sources); 288227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks render(); 289227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 290227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 291227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void processNoInput(FrameImage2D output) { 292227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks RenderTarget renderTarget = output.lockRenderTarget(); 293227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks processNoInput(renderTarget, output.getWidth(), output.getHeight()); 294227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks output.unlock(); 295227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 296227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 297227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void processNoInput(RenderTarget target, int width, int height) { 298227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks processMulti(new TextureSource[] {}, target, width, height); 299227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 300227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 301227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public int getUniformLocation(String name) { 302227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return getProgramUniform(name, true).getLocation(); 303227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 304227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 305227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public int getAttributeLocation(String name) { 306227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (name.equals(positionAttributeName()) || name.equals(texCoordAttributeName())) { 307227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Log.w("ImageShader", "Attempting to access internal attribute '" + name 308227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + "' directly!"); 309227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 310227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int loc = GLES20.glGetAttribLocation(mProgram, name); 311227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (loc < 0) { 312227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new RuntimeException("Unknown attribute '" + name + "' in shader program!"); 313227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 314227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return loc; 315227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 316227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 317227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setUniformValue(String uniformName, int value) { 318227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks useProgram(); 319227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int uniformHandle = getUniformLocation(uniformName); 320227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glUniform1i(uniformHandle, value); 321227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLToolbox.checkGlError("Set uniform value (" + uniformName + ")"); 322227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 323227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 324227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setUniformValue(String uniformName, float value) { 325227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks useProgram(); 326227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int uniformHandle = getUniformLocation(uniformName); 327227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glUniform1f(uniformHandle, value); 328227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLToolbox.checkGlError("Set uniform value (" + uniformName + ")"); 329227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 330227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 331227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setUniformValue(String uniformName, int[] values) { 332227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ProgramUniform uniform = getProgramUniform(uniformName, true); 333227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks useProgram(); 334227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int len = values.length; 335227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks switch (uniform.getType()) { 336227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case GLES20.GL_INT: 337227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkUniformAssignment(uniform, len, 1); 338227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glUniform1iv(uniform.getLocation(), len, values, 0); 339227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 340227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case GLES20.GL_INT_VEC2: 341227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkUniformAssignment(uniform, len, 2); 342227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glUniform2iv(uniform.getLocation(), len / 2, values, 0); 343227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 344227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case GLES20.GL_INT_VEC3: 345227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkUniformAssignment(uniform, len, 3); 346227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glUniform2iv(uniform.getLocation(), len / 3, values, 0); 347227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 348227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case GLES20.GL_INT_VEC4: 349227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkUniformAssignment(uniform, len, 4); 350227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glUniform2iv(uniform.getLocation(), len / 4, values, 0); 351227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 352227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks default: 353227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new RuntimeException("Cannot assign int-array to incompatible uniform type " 354227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + "for uniform '" + uniformName + "'!"); 355227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 356227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLToolbox.checkGlError("Set uniform value (" + uniformName + ")"); 357227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 358227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 359227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 360227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setUniformValue(String uniformName, float[] values) { 361227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ProgramUniform uniform = getProgramUniform(uniformName, true); 362227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks useProgram(); 363227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int len = values.length; 364227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks switch (uniform.getType()) { 365227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case GLES20.GL_FLOAT: 366227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkUniformAssignment(uniform, len, 1); 367227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glUniform1fv(uniform.getLocation(), len, values, 0); 368227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 369227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case GLES20.GL_FLOAT_VEC2: 370227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkUniformAssignment(uniform, len, 2); 371227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glUniform2fv(uniform.getLocation(), len / 2, values, 0); 372227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 373227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case GLES20.GL_FLOAT_VEC3: 374227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkUniformAssignment(uniform, len, 3); 375227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glUniform3fv(uniform.getLocation(), len / 3, values, 0); 376227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 377227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case GLES20.GL_FLOAT_VEC4: 378227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkUniformAssignment(uniform, len, 4); 379227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glUniform4fv(uniform.getLocation(), len / 4, values, 0); 380227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 381227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case GLES20.GL_FLOAT_MAT2: 382227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkUniformAssignment(uniform, len, 4); 383227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glUniformMatrix2fv(uniform.getLocation(), len / 4, false, values, 0); 384227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 385227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case GLES20.GL_FLOAT_MAT3: 386227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkUniformAssignment(uniform, len, 9); 387227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glUniformMatrix3fv(uniform.getLocation(), len / 9, false, values, 0); 388227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 389227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case GLES20.GL_FLOAT_MAT4: 390227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks checkUniformAssignment(uniform, len, 16); 391227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glUniformMatrix4fv(uniform.getLocation(), len / 16, false, values, 0); 392227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 393227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks default: 394227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new RuntimeException("Cannot assign float-array to incompatible uniform type " 395227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + "for uniform '" + uniformName + "'!"); 396227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 397227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLToolbox.checkGlError("Set uniform value (" + uniformName + ")"); 398227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 399227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 400227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setAttributeValues(String attributeName, float[] data, int components) { 401227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks VertexAttribute attr = getProgramAttribute(attributeName, true); 402227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks attr.set(false, FLOAT_SIZE * components, components, GLES20.GL_FLOAT, data); 403227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 404227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 405227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setAttributeValues(String attributeName, int vbo, int type, int components, 406227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int stride, int offset, boolean normalize) { 407227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks VertexAttribute attr = getProgramAttribute(attributeName, true); 408227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks attr.set(normalize, offset, stride, components, type, vbo); 409227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 410227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 411227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setSourceRect(float x, float y, float width, float height) { 412227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks setSourceCoords(new float[] { x, y, x + width, y, x, y + height, x + width, y + height }); 413227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 414227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 415227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setSourceRect(RectF rect) { 416227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks setSourceRect(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); 417227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 418227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 419227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setSourceQuad(Quad quad) { 420227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks setSourceCoords(new float[] { quad.topLeft().x, quad.topLeft().y, 421227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks quad.topRight().x, quad.topRight().y, 422227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks quad.bottomLeft().x, quad.bottomLeft().y, 423227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks quad.bottomRight().x, quad.bottomRight().y }); 424227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 425227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 426227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setSourceCoords(float[] coords) { 427227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (coords.length != 8) { 428227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("Expected 8 coordinates as source coordinates but " 429227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + "got " + coords.length + " coordinates!"); 430227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 431227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mSourceCoords = Arrays.copyOf(coords, 8); 432227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 433227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 434227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setSourceTransform(float[] matrix) { 435227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (matrix.length != 16) { 436227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("Expected 4x4 matrix for source transform!"); 437227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 438227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks setSourceCoords(new float[] { 439227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks matrix[12], 440227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks matrix[13], 441227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 442227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks matrix[0] + matrix[12], 443227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks matrix[1] + matrix[13], 444227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 445227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks matrix[4] + matrix[12], 446227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks matrix[5] + matrix[13], 447227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 448227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks matrix[0] + matrix[4] + matrix[12], 449227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks matrix[1] + matrix[5] + matrix[13], 450227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks }); 451227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 452227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 453227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setTargetRect(float x, float y, float width, float height) { 454227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks setTargetCoords(new float[] { x, y, 455227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks x + width, y, 456227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks x, y + height, 457227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks x + width, y + height }); 458227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 459227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 460227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setTargetRect(RectF rect) { 461227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks setTargetCoords(new float[] { rect.left, rect.top, 462227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks rect.right, rect.top, 463227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks rect.left, rect.bottom, 464227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks rect.right, rect.bottom }); 465227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 466227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 467227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setTargetQuad(Quad quad) { 468227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks setTargetCoords(new float[] { quad.topLeft().x, quad.topLeft().y, 469227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks quad.topRight().x, quad.topRight().y, 470227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks quad.bottomLeft().x, quad.bottomLeft().y, 471227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks quad.bottomRight().x, quad.bottomRight().y }); 472227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 473227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 474227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setTargetCoords(float[] coords) { 475227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (coords.length != 8) { 476227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("Expected 8 coordinates as target coordinates but " 477227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + "got " + coords.length + " coordinates!"); 478227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 479227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mTargetCoords = new float[8]; 480227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (int i = 0; i < 8; ++i) { 481227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mTargetCoords[i] = coords[i] * 2f - 1f; 482227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 483227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 484227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 485227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setTargetTransform(float[] matrix) { 486227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (matrix.length != 16) { 487227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("Expected 4x4 matrix for target transform!"); 488227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 489227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks setTargetCoords(new float[] { 490227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks matrix[12], 491227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks matrix[13], 492227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 493227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks matrix[0] + matrix[12], 494227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks matrix[1] + matrix[13], 495227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 496227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks matrix[4] + matrix[12], 497227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks matrix[5] + matrix[13], 498227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 499227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks matrix[0] + matrix[4] + matrix[12], 500227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks matrix[1] + matrix[5] + matrix[13], 501227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks }); 502227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 503227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 504227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setClearsOutput(boolean clears) { 505227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mClearsOutput = clears; 506227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 507227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 508227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public boolean getClearsOutput() { 509227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mClearsOutput; 510227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 511227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 512227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setClearColor(float[] rgba) { 513227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mClearColor = rgba; 514227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 515227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 516227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public float[] getClearColor() { 517227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mClearColor; 518227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 519227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 520227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setClearBufferMask(int bufferMask) { 521227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mClearBuffers = bufferMask; 522227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 523227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 524227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public int getClearBufferMask() { 525227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mClearBuffers; 526227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 527227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 528227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setBlendEnabled(boolean enable) { 529227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mBlendEnabled = enable; 530227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 531227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 532227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public boolean getBlendEnabled() { 533227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mBlendEnabled; 534227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 535227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 536227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setBlendFunc(int sFactor, int dFactor) { 537227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mSFactor = sFactor; 538227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mDFactor = dFactor; 539227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 540227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 541227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setDrawMode(int drawMode) { 542227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mDrawMode = drawMode; 543227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 544227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 545227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public int getDrawMode() { 546227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mDrawMode; 547227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 548227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 549227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setVertexCount(int count) { 550227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mVertexCount = count; 551227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 552227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 553227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public int getVertexCount() { 554227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mVertexCount; 555227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 556227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 557227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setBaseTextureUnit(int baseTexUnit) { 558227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mBaseTexUnit = baseTexUnit; 559227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 560227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 561227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public int baseTextureUnit() { 562227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mBaseTexUnit; 563227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 564227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 565227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public String texCoordAttributeName() { 566227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return "a_texcoord"; 567227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 568227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 569227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public String positionAttributeName() { 570227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return "a_position"; 571227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 572227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 573227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public String inputTextureUniformName(int index) { 574227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return "tex_sampler_" + index; 575227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 576227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 577227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static int maxTextureUnits() { 578227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return GLES20.GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS; 579227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 580227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 581227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 582227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks protected void finalize() throws Throwable { 583227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glDeleteProgram(mProgram); 584227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 585227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 586227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks protected void pushShaderState() { 587227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks useProgram(); 588227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks updateSourceCoordAttribute(); 589227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks updateTargetCoordAttribute(); 590227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks pushAttributes(); 591227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mClearsOutput) { 592227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glClearColor(mClearColor[0], mClearColor[1], mClearColor[2], mClearColor[3]); 593227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glClear(mClearBuffers); 594227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 595227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mBlendEnabled) { 596227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glEnable(GLES20.GL_BLEND); 597227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glBlendFunc(mSFactor, mDFactor); 598227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 599227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glDisable(GLES20.GL_BLEND); 600227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 601227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLToolbox.checkGlError("Set render variables"); 602227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 603227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 604227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void focusTarget(RenderTarget target, int width, int height) { 605227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks target.focus(); 606227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glViewport(0, 0, width, height); 607227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLToolbox.checkGlError("glViewport"); 608227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 609227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 610227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void bindInputTextures(TextureSource[] sources) { 611227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (int i = 0; i < sources.length; ++i) { 612227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Activate texture unit i 613227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glActiveTexture(baseTextureUnit() + i); 614227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 615227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Bind texture 616227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks sources[i].bind(); 617227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 618227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Assign the texture uniform in the shader to unit i 619227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int texUniform = GLES20.glGetUniformLocation(mProgram, inputTextureUniformName(i)); 620227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (texUniform >= 0) { 621227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glUniform1i(texUniform, i); 622227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 623227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new RuntimeException("Shader does not seem to support " + sources.length 624227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + " number of input textures! Missing uniform " + inputTextureUniformName(i) 625227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + "!"); 626227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 627227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLToolbox.checkGlError("Binding input texture " + i); 628227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 629227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 630227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 631227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void pushAttributes() { 632227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (VertexAttribute attr : mAttributes.values()) { 633227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (!attr.push()) { 634227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new RuntimeException("Unable to assign attribute value '" + attr + "'!"); 635227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 636227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 637227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLToolbox.checkGlError("Push Attributes"); 638227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 639227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 640227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void updateSourceCoordAttribute() { 641227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // If attribute does not exist, simply do nothing (may be custom shader). 642227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks VertexAttribute attr = getProgramAttribute(texCoordAttributeName(), false); 643227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // A non-null value of mSourceCoords indicates new values to be set. 644227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mSourceCoords != null && attr != null) { 645227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Upload new source coordinates to GPU 646227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks attr.set(false, FLOAT_SIZE * 2, 2, GLES20.GL_FLOAT, mSourceCoords); 647227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 648227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Do not set again (even if failed, to not cause endless attempts) 649227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mSourceCoords = null; 650227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 651227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 652227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void updateTargetCoordAttribute() { 653227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // If attribute does not exist, simply do nothing (may be custom shader). 654227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks VertexAttribute attr = getProgramAttribute(positionAttributeName(), false); 655227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // A non-null value of mTargetCoords indicates new values to be set. 656227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mTargetCoords != null && attr != null) { 657227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Upload new target coordinates to GPU 658227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks attr.set(false, FLOAT_SIZE * 2, 2, GLES20.GL_FLOAT, mTargetCoords); 659227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 660227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Do not set again (even if failed, to not cause endless attempts) 661227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mTargetCoords = null; 662227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 663227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 664227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void render() { 665227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glDrawArrays(mDrawMode, 0, mVertexCount); 666227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLToolbox.checkGlError("glDrawArrays"); 667227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 668227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 669227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void checkExecutable() { 670227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mProgram == 0) { 671227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new RuntimeException("Attempting to execute invalid shader-program!"); 672227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 673227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 674227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 675227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void useProgram() { 676227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glUseProgram(mProgram); 677227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLToolbox.checkGlError("glUseProgram"); 678227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 679227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 680227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static void checkTexCount(int count) { 681227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (count > maxTextureUnits()) { 682227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new RuntimeException("Number of textures passed (" + count + ") exceeds the " 683227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + "maximum number of allowed texture units (" + maxTextureUnits() + ")!"); 684227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 685227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 686227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 687227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static int loadShader(int shaderType, String source) { 688227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int shader = GLES20.glCreateShader(shaderType); 689227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (shader != 0) { 690227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glShaderSource(shader, source); 691227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glCompileShader(shader); 692227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int[] compiled = new int[1]; 693227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0); 694227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (compiled[0] == 0) { 695227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks String info = GLES20.glGetShaderInfoLog(shader); 696227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glDeleteShader(shader); 697227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks shader = 0; 698227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new RuntimeException("Could not compile shader " + shaderType + ":" + info); 699227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 700227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 701227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return shader; 702227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 703227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 704227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static int createProgram(String vertexSource, String fragmentSource) { 705227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource); 706227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (vertexShader == 0) { 707227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new RuntimeException("Could not create shader-program as vertex shader " 708227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + "could not be compiled!"); 709227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 710227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource); 711227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (pixelShader == 0) { 712227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new RuntimeException("Could not create shader-program as fragment shader " 713227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + "could not be compiled!"); 714227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 715227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 716227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int program = GLES20.glCreateProgram(); 717227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (program != 0) { 718227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glAttachShader(program, vertexShader); 719227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLToolbox.checkGlError("glAttachShader"); 720227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glAttachShader(program, pixelShader); 721227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLToolbox.checkGlError("glAttachShader"); 722227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glLinkProgram(program); 723227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int[] linkStatus = new int[1]; 724227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0); 725227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (linkStatus[0] != GLES20.GL_TRUE) { 726227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks String info = GLES20.glGetProgramInfoLog(program); 727227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glDeleteProgram(program); 728227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks program = 0; 729227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new RuntimeException("Could not link program: " + info); 730227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 731227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 732227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 733227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glDeleteShader(vertexShader); 734227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glDeleteShader(pixelShader); 735227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 736227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return program; 737227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 738227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 739227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void scanUniforms() { 740227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int uniformCount[] = new int [1]; 741227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks GLES20.glGetProgramiv(mProgram, GLES20.GL_ACTIVE_UNIFORMS, uniformCount, 0); 742227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (uniformCount[0] > 0) { 743227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mUniforms = new HashMap<String, ProgramUniform>(uniformCount[0]); 744227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (int i = 0; i < uniformCount[0]; ++i) { 745227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ProgramUniform uniform = new ProgramUniform(mProgram, i); 746227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mUniforms.put(uniform.getName(), uniform); 747227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 748227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 749227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 750227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 751227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private ProgramUniform getProgramUniform(String name, boolean required) { 752227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ProgramUniform result = mUniforms.get(name); 753227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (result == null && required) { 754227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("Unknown uniform '" + name + "'!"); 755227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 756227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return result; 757227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 758227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 759227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private VertexAttribute getProgramAttribute(String name, boolean required) { 760227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks VertexAttribute result = mAttributes.get(name); 761227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (result == null) { 762227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int handle = GLES20.glGetAttribLocation(mProgram, name); 763227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (handle >= 0) { 764227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks result = new VertexAttribute(name, handle); 765227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mAttributes.put(name, result); 766227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (required) { 767227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("Unknown attribute '" + name + "'!"); 768227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 769227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 770227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return result; 771227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 772227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 773227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void checkUniformAssignment(ProgramUniform uniform, int values, int components) { 774227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (values % components != 0) { 775227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new RuntimeException("Size mismatch: Attempting to assign values of size " 776227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + values + " to uniform '" + uniform.getName() + "' (must be multiple of " 777227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + components + ")!"); 778227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (uniform.getSize() != values / components) { 779227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new RuntimeException("Size mismatch: Cannot assign " + values + " values to " 780227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + "uniform '" + uniform.getName() + "'!"); 781227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 782227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 783227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 784227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static int strlen(byte[] strVal) { 785227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (int i = 0; i < strVal.length; ++i) { 786227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (strVal[i] == '\0') { 787227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return i; 788227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 789227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 790227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return strVal.length; 791227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 792227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks} 793227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 794