• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright 2015 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 package org.webrtc;
12 
13 import android.opengl.GLES20;
14 
15 import java.nio.FloatBuffer;
16 
17 // Helper class for handling OpenGL shaders and shader programs.
18 public class GlShader {
19   private static final String TAG = "GlShader";
20 
compileShader(int shaderType, String source)21   private static int compileShader(int shaderType, String source) {
22     final int shader = GLES20.glCreateShader(shaderType);
23     if (shader == 0) {
24       throw new RuntimeException("glCreateShader() failed. GLES20 error: " + GLES20.glGetError());
25     }
26     GLES20.glShaderSource(shader, source);
27     GLES20.glCompileShader(shader);
28     int[] compileStatus = new int[] {GLES20.GL_FALSE};
29     GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
30     if (compileStatus[0] != GLES20.GL_TRUE) {
31       Logging.e(
32           TAG, "Compile error " + GLES20.glGetShaderInfoLog(shader) + " in shader:\n" + source);
33       throw new RuntimeException(GLES20.glGetShaderInfoLog(shader));
34     }
35     GlUtil.checkNoGLES2Error("compileShader");
36     return shader;
37   }
38 
39   private int program;
40 
GlShader(String vertexSource, String fragmentSource)41   public GlShader(String vertexSource, String fragmentSource) {
42     final int vertexShader = compileShader(GLES20.GL_VERTEX_SHADER, vertexSource);
43     final int fragmentShader = compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
44     program = GLES20.glCreateProgram();
45     if (program == 0) {
46       throw new RuntimeException("glCreateProgram() failed. GLES20 error: " + GLES20.glGetError());
47     }
48     GLES20.glAttachShader(program, vertexShader);
49     GLES20.glAttachShader(program, fragmentShader);
50     GLES20.glLinkProgram(program);
51     int[] linkStatus = new int[] {GLES20.GL_FALSE};
52     GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
53     if (linkStatus[0] != GLES20.GL_TRUE) {
54       Logging.e(TAG, "Could not link program: " + GLES20.glGetProgramInfoLog(program));
55       throw new RuntimeException(GLES20.glGetProgramInfoLog(program));
56     }
57     // According to the documentation of glLinkProgram():
58     // "After the link operation, applications are free to modify attached shader objects, compile
59     // attached shader objects, detach shader objects, delete shader objects, and attach additional
60     // shader objects. None of these operations affects the information log or the program that is
61     // part of the program object."
62     // But in practice, detaching shaders from the program seems to break some devices. Deleting the
63     // shaders are fine however - it will delete them when they are no longer attached to a program.
64     GLES20.glDeleteShader(vertexShader);
65     GLES20.glDeleteShader(fragmentShader);
66     GlUtil.checkNoGLES2Error("Creating GlShader");
67   }
68 
getAttribLocation(String label)69   public int getAttribLocation(String label) {
70     if (program == -1) {
71       throw new RuntimeException("The program has been released");
72     }
73     int location = GLES20.glGetAttribLocation(program, label);
74     if (location < 0) {
75       throw new RuntimeException("Could not locate '" + label + "' in program");
76     }
77     return location;
78   }
79 
80   /**
81    * Enable and upload a vertex array for attribute `label`. The vertex data is specified in
82    * `buffer` with `dimension` number of components per vertex.
83    */
setVertexAttribArray(String label, int dimension, FloatBuffer buffer)84   public void setVertexAttribArray(String label, int dimension, FloatBuffer buffer) {
85     setVertexAttribArray(label, dimension, 0 /* stride */, buffer);
86   }
87 
88   /**
89    * Enable and upload a vertex array for attribute `label`. The vertex data is specified in
90    * `buffer` with `dimension` number of components per vertex and specified `stride`.
91    */
setVertexAttribArray(String label, int dimension, int stride, FloatBuffer buffer)92   public void setVertexAttribArray(String label, int dimension, int stride, FloatBuffer buffer) {
93     if (program == -1) {
94       throw new RuntimeException("The program has been released");
95     }
96     int location = getAttribLocation(label);
97     GLES20.glEnableVertexAttribArray(location);
98     GLES20.glVertexAttribPointer(location, dimension, GLES20.GL_FLOAT, false, stride, buffer);
99     GlUtil.checkNoGLES2Error("setVertexAttribArray");
100   }
101 
getUniformLocation(String label)102   public int getUniformLocation(String label) {
103     if (program == -1) {
104       throw new RuntimeException("The program has been released");
105     }
106     int location = GLES20.glGetUniformLocation(program, label);
107     if (location < 0) {
108       throw new RuntimeException("Could not locate uniform '" + label + "' in program");
109     }
110     return location;
111   }
112 
useProgram()113   public void useProgram() {
114     if (program == -1) {
115       throw new RuntimeException("The program has been released");
116     }
117     synchronized (EglBase.lock) {
118       GLES20.glUseProgram(program);
119     }
120     GlUtil.checkNoGLES2Error("glUseProgram");
121   }
122 
release()123   public void release() {
124     Logging.d(TAG, "Deleting shader.");
125     // Delete program, automatically detaching any shaders from it.
126     if (program != -1) {
127       GLES20.glDeleteProgram(program);
128       program = -1;
129     }
130   }
131 }
132