1 /* 2 * libjingle 3 * Copyright 2015 Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 package org.webrtc; 29 30 import android.opengl.GLES20; 31 32 import org.webrtc.Logging; 33 34 import java.nio.FloatBuffer; 35 36 // Helper class for handling OpenGL shaders and shader programs. 37 public class GlShader { 38 private static final String TAG = "GlShader"; 39 compileShader(int shaderType, String source)40 private static int compileShader(int shaderType, String source) { 41 int[] result = new int[] { 42 GLES20.GL_FALSE 43 }; 44 int shader = GLES20.glCreateShader(shaderType); 45 GLES20.glShaderSource(shader, source); 46 GLES20.glCompileShader(shader); 47 GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, result, 0); 48 if (result[0] != GLES20.GL_TRUE) { 49 Logging.e(TAG, "Could not compile shader " + shaderType + ":" + 50 GLES20.glGetShaderInfoLog(shader)); 51 throw new RuntimeException(GLES20.glGetShaderInfoLog(shader)); 52 } 53 GlUtil.checkNoGLES2Error("compileShader"); 54 return shader; 55 } 56 57 private int vertexShader; 58 private int fragmentShader; 59 private int program; 60 GlShader(String vertexSource, String fragmentSource)61 public GlShader(String vertexSource, String fragmentSource) { 62 vertexShader = compileShader(GLES20.GL_VERTEX_SHADER, vertexSource); 63 fragmentShader = compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource); 64 program = GLES20.glCreateProgram(); 65 if (program == 0) { 66 throw new RuntimeException("Could not create program"); 67 } 68 GLES20.glAttachShader(program, vertexShader); 69 GLES20.glAttachShader(program, fragmentShader); 70 GLES20.glLinkProgram(program); 71 int[] linkStatus = new int[] { 72 GLES20.GL_FALSE 73 }; 74 GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0); 75 if (linkStatus[0] != GLES20.GL_TRUE) { 76 Logging.e(TAG, "Could not link program: " + 77 GLES20.glGetProgramInfoLog(program)); 78 throw new RuntimeException(GLES20.glGetProgramInfoLog(program)); 79 } 80 GlUtil.checkNoGLES2Error("Creating GlShader"); 81 } 82 getAttribLocation(String label)83 public int getAttribLocation(String label) { 84 if (program == -1) { 85 throw new RuntimeException("The program has been released"); 86 } 87 int location = GLES20.glGetAttribLocation(program, label); 88 if (location < 0) { 89 throw new RuntimeException("Could not locate '" + label + "' in program"); 90 } 91 return location; 92 } 93 94 /** 95 * Enable and upload a vertex array for attribute |label|. The vertex data is specified in 96 * |buffer| with |dimension| number of components per vertex. 97 */ setVertexAttribArray(String label, int dimension, FloatBuffer buffer)98 public void setVertexAttribArray(String label, int dimension, FloatBuffer buffer) { 99 if (program == -1) { 100 throw new RuntimeException("The program has been released"); 101 } 102 int location = getAttribLocation(label); 103 GLES20.glEnableVertexAttribArray(location); 104 GLES20.glVertexAttribPointer(location, dimension, GLES20.GL_FLOAT, false, 0, buffer); 105 GlUtil.checkNoGLES2Error("setVertexAttribArray"); 106 } 107 getUniformLocation(String label)108 public int getUniformLocation(String label) { 109 if (program == -1) { 110 throw new RuntimeException("The program has been released"); 111 } 112 int location = GLES20.glGetUniformLocation(program, label); 113 if (location < 0) { 114 throw new RuntimeException("Could not locate uniform '" + label + "' in program"); 115 } 116 return location; 117 } 118 useProgram()119 public void useProgram() { 120 if (program == -1) { 121 throw new RuntimeException("The program has been released"); 122 } 123 GLES20.glUseProgram(program); 124 GlUtil.checkNoGLES2Error("glUseProgram"); 125 } 126 release()127 public void release() { 128 Logging.d(TAG, "Deleting shader."); 129 // Flag shaders for deletion (does not delete until no longer attached to a program). 130 if (vertexShader != -1) { 131 GLES20.glDeleteShader(vertexShader); 132 vertexShader = -1; 133 } 134 if (fragmentShader != -1) { 135 GLES20.glDeleteShader(fragmentShader); 136 fragmentShader = -1; 137 } 138 // Delete program, automatically detaching any shaders from it. 139 if (program != -1) { 140 GLES20.glDeleteProgram(program); 141 program = -1; 142 } 143 } 144 } 145