blob: 15dfc45a270e4b0ab518beb35f0404ee51ce7a47 [file] [log] [blame]
Magnus Jedvert80cf97c2015-06-11 10:08:59 +02001/*
kjellanderb24317b2016-02-10 07:54:43 -08002 * Copyright 2015 The WebRTC project authors. All Rights Reserved.
Magnus Jedvert80cf97c2015-06-11 10:08:59 +02003 *
kjellanderb24317b2016-02-10 07:54:43 -08004 * 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.
Magnus Jedvert80cf97c2015-06-11 10:08:59 +02009 */
10
11package org.webrtc;
12
13import android.opengl.GLES20;
Jiayang Liu5975b3c2015-09-16 13:40:53 -070014
magjed59a677a2015-06-24 03:59:37 -070015import java.nio.FloatBuffer;
16
Magnus Jedvert80cf97c2015-06-11 10:08:59 +020017// Helper class for handling OpenGL shaders and shader programs.
18public class GlShader {
19 private static final String TAG = "GlShader";
20
21 private static int compileShader(int shaderType, String source) {
magjed347c0bb2016-02-18 03:47:44 -080022 final int shader = GLES20.glCreateShader(shaderType);
23 if (shader == 0) {
24 throw new RuntimeException("glCreateShader() failed. GLES20 error: " + GLES20.glGetError());
25 }
Magnus Jedvert80cf97c2015-06-11 10:08:59 +020026 GLES20.glShaderSource(shader, source);
27 GLES20.glCompileShader(shader);
sakalb6760f92016-09-29 04:12:44 -070028 int[] compileStatus = new int[] {GLES20.GL_FALSE};
magjed347c0bb2016-02-18 03:47:44 -080029 GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
30 if (compileStatus[0] != GLES20.GL_TRUE) {
sakalb6760f92016-09-29 04:12:44 -070031 Logging.e(
32 TAG, "Could not compile shader " + shaderType + ":" + GLES20.glGetShaderInfoLog(shader));
Magnus Jedvert80cf97c2015-06-11 10:08:59 +020033 throw new RuntimeException(GLES20.glGetShaderInfoLog(shader));
34 }
35 GlUtil.checkNoGLES2Error("compileShader");
36 return shader;
37 }
38
Magnus Jedvert80cf97c2015-06-11 10:08:59 +020039 private int program;
40
41 public GlShader(String vertexSource, String fragmentSource) {
magjed347c0bb2016-02-18 03:47:44 -080042 final int vertexShader = compileShader(GLES20.GL_VERTEX_SHADER, vertexSource);
43 final int fragmentShader = compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
Magnus Jedvert80cf97c2015-06-11 10:08:59 +020044 program = GLES20.glCreateProgram();
45 if (program == 0) {
magjed347c0bb2016-02-18 03:47:44 -080046 throw new RuntimeException("glCreateProgram() failed. GLES20 error: " + GLES20.glGetError());
Magnus Jedvert80cf97c2015-06-11 10:08:59 +020047 }
48 GLES20.glAttachShader(program, vertexShader);
49 GLES20.glAttachShader(program, fragmentShader);
50 GLES20.glLinkProgram(program);
sakalb6760f92016-09-29 04:12:44 -070051 int[] linkStatus = new int[] {GLES20.GL_FALSE};
Magnus Jedvert80cf97c2015-06-11 10:08:59 +020052 GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
53 if (linkStatus[0] != GLES20.GL_TRUE) {
sakalb6760f92016-09-29 04:12:44 -070054 Logging.e(TAG, "Could not link program: " + GLES20.glGetProgramInfoLog(program));
Magnus Jedvert80cf97c2015-06-11 10:08:59 +020055 throw new RuntimeException(GLES20.glGetProgramInfoLog(program));
56 }
magjed347c0bb2016-02-18 03:47:44 -080057 // 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);
Magnus Jedvert80cf97c2015-06-11 10:08:59 +020066 GlUtil.checkNoGLES2Error("Creating GlShader");
67 }
68
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
magjed59a677a2015-06-24 03:59:37 -070080 /**
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 */
84 public void setVertexAttribArray(String label, int dimension, FloatBuffer buffer) {
85 if (program == -1) {
86 throw new RuntimeException("The program has been released");
87 }
88 int location = getAttribLocation(label);
89 GLES20.glEnableVertexAttribArray(location);
90 GLES20.glVertexAttribPointer(location, dimension, GLES20.GL_FLOAT, false, 0, buffer);
91 GlUtil.checkNoGLES2Error("setVertexAttribArray");
92 }
93
Magnus Jedvert80cf97c2015-06-11 10:08:59 +020094 public int getUniformLocation(String label) {
95 if (program == -1) {
96 throw new RuntimeException("The program has been released");
97 }
98 int location = GLES20.glGetUniformLocation(program, label);
99 if (location < 0) {
100 throw new RuntimeException("Could not locate uniform '" + label + "' in program");
101 }
102 return location;
103 }
104
105 public void useProgram() {
106 if (program == -1) {
107 throw new RuntimeException("The program has been released");
108 }
109 GLES20.glUseProgram(program);
110 GlUtil.checkNoGLES2Error("glUseProgram");
111 }
112
113 public void release() {
Jiayang Liu5975b3c2015-09-16 13:40:53 -0700114 Logging.d(TAG, "Deleting shader.");
Magnus Jedvert80cf97c2015-06-11 10:08:59 +0200115 // Delete program, automatically detaching any shaders from it.
116 if (program != -1) {
117 GLES20.glDeleteProgram(program);
118 program = -1;
119 }
120 }
121}