From 3eda590c875ac07f4ec16c09f5f68322f2890715 Mon Sep 17 00:00:00 2001 From: claincly Date: Tue, 5 Oct 2021 14:34:04 +0100 Subject: [PATCH] Rollback of https://github.com/google/ExoPlayer/commit/9788750ddb23b2064dddf99d6e1ea491b2e45cea *** Original commit *** Simplify GL program handling. *** PiperOrigin-RevId: 400970170 --- .../gldemo/BitmapOverlayVideoProcessor.java | 45 +-- .../android/exoplayer2/util/GlUtil.java | 289 ++++++++---------- .../video/VideoDecoderGLSurfaceView.java | 20 +- .../video/spherical/ProjectionRenderer.java | 23 +- .../TransformerTranscodingVideoRenderer.java | 20 +- 5 files changed, 168 insertions(+), 229 deletions(-) diff --git a/demos/gl/src/main/java/com/google/android/exoplayer2/gldemo/BitmapOverlayVideoProcessor.java b/demos/gl/src/main/java/com/google/android/exoplayer2/gldemo/BitmapOverlayVideoProcessor.java index cbc2bfe30c..13e2a60684 100644 --- a/demos/gl/src/main/java/com/google/android/exoplayer2/gldemo/BitmapOverlayVideoProcessor.java +++ b/demos/gl/src/main/java/com/google/android/exoplayer2/gldemo/BitmapOverlayVideoProcessor.java @@ -15,8 +15,6 @@ */ package com.google.android.exoplayer2.gldemo; -import static com.google.android.exoplayer2.util.Assertions.checkNotNull; - import android.content.Context; import android.content.pm.PackageManager; import android.graphics.Bitmap; @@ -28,6 +26,7 @@ import android.opengl.GLES20; import android.opengl.GLUtils; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.GlUtil; import java.io.IOException; import java.util.Locale; @@ -50,7 +49,7 @@ import javax.microedition.khronos.opengles.GL10; private final Bitmap logoBitmap; private final Canvas overlayCanvas; - @Nullable private GlUtil.Program program; + private int program; @Nullable private GlUtil.Attribute[] attributes; @Nullable private GlUtil.Uniform[] uniforms; @@ -78,40 +77,27 @@ import javax.microedition.khronos.opengles.GL10; @Override public void initialize() { + String vertexShaderCode; + String fragmentShaderCode; try { - program = - new GlUtil.Program( - context, - /* vertexShaderFilePath= */ "bitmap_overlay_video_processor_vertex.glsl", - /* fragmentShaderFilePath= */ "bitmap_overlay_video_processor_fragment.glsl"); + vertexShaderCode = GlUtil.loadAsset(context, "bitmap_overlay_video_processor_vertex.glsl"); + fragmentShaderCode = + GlUtil.loadAsset(context, "bitmap_overlay_video_processor_fragment.glsl"); } catch (IOException e) { throw new IllegalStateException(e); } - program.use(); - GlUtil.Attribute[] attributes = program.getAttributes(); + program = GlUtil.compileProgram(vertexShaderCode, fragmentShaderCode); + GlUtil.Attribute[] attributes = GlUtil.getAttributes(program); + GlUtil.Uniform[] uniforms = GlUtil.getUniforms(program); for (GlUtil.Attribute attribute : attributes) { if (attribute.name.equals("a_position")) { - attribute.setBuffer( - new float[] { - -1, -1, 0, 1, - 1, -1, 0, 1, - -1, 1, 0, 1, - 1, 1, 0, 1 - }, - 4); + attribute.setBuffer(new float[] {-1, -1, 0, 1, 1, -1, 0, 1, -1, 1, 0, 1, 1, 1, 0, 1}, 4); } else if (attribute.name.equals("a_texcoord")) { - attribute.setBuffer( - new float[] { - 0, 0, 0, 1, - 1, 0, 0, 1, - 0, 1, 0, 1, - 1, 1, 0, 1 - }, - 4); + attribute.setBuffer(new float[] {0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1}, 4); } } this.attributes = attributes; - this.uniforms = checkNotNull(program).getUniforms(); + this.uniforms = uniforms; GLES20.glGenTextures(1, textures, 0); GLES20.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); GLES20.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST); @@ -140,8 +126,9 @@ import javax.microedition.khronos.opengles.GL10; GlUtil.checkGlError(); // Run the shader program. - GlUtil.Uniform[] uniforms = checkNotNull(this.uniforms); - GlUtil.Attribute[] attributes = checkNotNull(this.attributes); + GlUtil.Uniform[] uniforms = Assertions.checkNotNull(this.uniforms); + GlUtil.Attribute[] attributes = Assertions.checkNotNull(this.attributes); + GLES20.glUseProgram(program); for (GlUtil.Uniform uniform : uniforms) { switch (uniform.name) { case "tex_sampler_0": diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/GlUtil.java b/library/common/src/main/java/com/google/android/exoplayer2/util/GlUtil.java index a46e6ca21c..a0643ad393 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/GlUtil.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/GlUtil.java @@ -54,160 +54,6 @@ public final class GlUtil { /** Thrown when the required EGL version is not supported by the device. */ public static final class UnsupportedEglVersionException extends Exception {} - /** GL program. */ - public static final class Program { - /** The identifier of a compiled and linked GLSL shader program. */ - private final int programId; - - /** - * Compiles a GL shader program from vertex and fragment shader code. - * - * @param vertexShaderCode GLES20 vertex shader program. - * @param fragmentShaderCode GLES20 fragment shader program. - */ - public Program(String vertexShaderCode, String fragmentShaderCode) { - programId = GLES20.glCreateProgram(); - checkGlError(); - - // Add the vertex and fragment shaders. - addShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode); - addShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); - - // Link and check for errors. - GLES20.glLinkProgram(programId); - int[] linkStatus = new int[] {GLES20.GL_FALSE}; - GLES20.glGetProgramiv(programId, GLES20.GL_LINK_STATUS, linkStatus, 0); - if (linkStatus[0] != GLES20.GL_TRUE) { - throwGlException( - "Unable to link shader program: \n" + GLES20.glGetProgramInfoLog(programId)); - } - checkGlError(); - } - - /** - * Compiles a GL shader program from vertex and fragment shader code. - * - * @param context The {@link Context}. - * @param vertexShaderFilePath The path to a GLES20 vertex shader program. - * @param fragmentShaderFilePath The path to a fragment shader program. - * @throws IOException When failing to read the shader files. - */ - public Program(Context context, String vertexShaderFilePath, String fragmentShaderFilePath) - throws IOException { - this(loadAsset(context, vertexShaderFilePath), loadAsset(context, fragmentShaderFilePath)); - } - - /** - * Compiles a GL shader program from vertex and fragment shader code. - * - * @param vertexShaderCode GLES20 vertex shader program as arrays of strings. Strings are joined - * by adding a new line character in between each of them. - * @param fragmentShaderCode GLES20 fragment shader program as arrays of strings. Strings are - * joined by adding a new line character in between each of them. - */ - public Program(String[] vertexShaderCode, String[] fragmentShaderCode) { - this(TextUtils.join("\n", vertexShaderCode), TextUtils.join("\n", fragmentShaderCode)); - } - - /** Uses the program. */ - public void use() { - GLES20.glUseProgram(programId); - } - - /** Deletes the program. Deleted programs cannot be used again. */ - public void delete() { - GLES20.glDeleteProgram(programId); - } - - /** Returns the location of an {@link Attribute}. */ - public int glGetAttribLocation(String attributeName) { - return GLES20.glGetAttribLocation(programId, attributeName); - } - - /** Returns the location of a {@link Uniform}. */ - public int glGetUniformLocation(String uniformName) { - return GLES20.glGetUniformLocation(programId, uniformName); - } - - /** Returns the program's {@link Attribute}s. */ - public Attribute[] getAttributes() { - int[] attributeCount = new int[1]; - GLES20.glGetProgramiv(programId, GLES20.GL_ACTIVE_ATTRIBUTES, attributeCount, 0); - if (attributeCount[0] != 2) { - throw new IllegalStateException("Expected two attributes."); - } - - Attribute[] attributes = new Attribute[attributeCount[0]]; - for (int i = 0; i < attributeCount[0]; i++) { - attributes[i] = createAttribute(i); - } - return attributes; - } - - /** Returns the program's {@link Uniform}s. */ - public Uniform[] getUniforms() { - int[] uniformCount = new int[1]; - GLES20.glGetProgramiv(programId, GLES20.GL_ACTIVE_UNIFORMS, uniformCount, 0); - - Uniform[] uniforms = new Uniform[uniformCount[0]]; - for (int i = 0; i < uniformCount[0]; i++) { - uniforms[i] = createUniform(i); - } - - return uniforms; - } - - private Uniform createUniform(int index) { - int[] length = new int[1]; - GLES20.glGetProgramiv(programId, GLES20.GL_ACTIVE_UNIFORM_MAX_LENGTH, length, 0); - - int[] type = new int[1]; - int[] size = new int[1]; - byte[] name = new byte[length[0]]; - int[] ignore = new int[1]; - - GLES20.glGetActiveUniform(programId, index, length[0], ignore, 0, size, 0, type, 0, name, 0); - String nameString = new String(name, 0, strlen(name)); - int location = glGetAttribLocation(nameString); - int typeInt = type[0]; - - return new Uniform(nameString, location, typeInt); - } - - private Attribute createAttribute(int index) { - int[] length = new int[1]; - GLES20.glGetProgramiv(programId, GLES20.GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, length, 0); - - int[] type = new int[1]; - int[] size = new int[1]; - byte[] nameBytes = new byte[length[0]]; - int[] ignore = new int[1]; - - GLES20.glGetActiveAttrib( - programId, index, length[0], ignore, 0, size, 0, type, 0, nameBytes, 0); - String name = new String(nameBytes, 0, strlen(nameBytes)); - int location = glGetAttribLocation(name); - - return new Attribute(name, index, location); - } - - private void addShader(int type, String shaderCode) { - int shader = GLES20.glCreateShader(type); - GLES20.glShaderSource(shader, shaderCode); - GLES20.glCompileShader(shader); - - int[] result = new int[] {GLES20.GL_FALSE}; - GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, result, 0); - if (result[0] != GLES20.GL_TRUE) { - throwGlException(GLES20.glGetShaderInfoLog(shader) + ", source: " + shaderCode); - } - - GLES20.glAttachShader(programId, shader); - GLES20.glDeleteShader(shader); - checkGlError(); - } - } - /** * GL attribute, which can be attached to a buffer with {@link Attribute#setBuffer(float[], int)}. */ @@ -222,11 +68,26 @@ public final class GlUtil { @Nullable private Buffer buffer; private int size; - /** Creates a new GL attribute. */ - public Attribute(String name, int index, int location) { - this.name = name; + /** + * Creates a new GL attribute. + * + * @param program The identifier of a compiled and linked GLSL shader program. + * @param index The index of the attribute. After this instance has been constructed, the name + * of the attribute is available via the {@link #name} field. + */ + public Attribute(int program, int index) { + int[] len = new int[1]; + GLES20.glGetProgramiv(program, GLES20.GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, len, 0); + + int[] type = new int[1]; + int[] size = new int[1]; + byte[] nameBytes = new byte[len[0]]; + int[] ignore = new int[1]; + + GLES20.glGetActiveAttrib(program, index, len[0], ignore, 0, size, 0, type, 0, nameBytes, 0); + name = new String(nameBytes, 0, strlen(nameBytes)); + location = GLES20.glGetAttribLocation(program, name); this.index = index; - this.location = location; } /** @@ -276,12 +137,28 @@ public final class GlUtil { private int texId; private int unit; - /** Creates a new GL uniform. */ - public Uniform(String name, int location, int type) { - this.name = name; - this.location = location; - this.type = type; - this.value = new float[16]; + /** + * Creates a new GL uniform. + * + * @param program The identifier of a compiled and linked GLSL shader program. + * @param index The index of the uniform. After this instance has been constructed, the name of + * the uniform is available via the {@link #name} field. + */ + public Uniform(int program, int index) { + int[] len = new int[1]; + GLES20.glGetProgramiv(program, GLES20.GL_ACTIVE_UNIFORM_MAX_LENGTH, len, 0); + + int[] type = new int[1]; + int[] size = new int[1]; + byte[] name = new byte[len[0]]; + int[] ignore = new int[1]; + + GLES20.glGetActiveUniform(program, index, len[0], ignore, 0, size, 0, type, 0, name, 0); + this.name = new String(name, 0, strlen(name)); + location = GLES20.glGetUniformLocation(program, this.name); + this.type = type[0]; + + value = new float[16]; } /** @@ -455,6 +332,74 @@ public final class GlUtil { Api17.focusSurface(eglDisplay, eglContext, surface, width, height); } + /** + * Builds a GL shader program from vertex and fragment shader code. + * + * @param vertexCode GLES20 vertex shader program as arrays of strings. Strings are joined by + * adding a new line character in between each of them. + * @param fragmentCode GLES20 fragment shader program as arrays of strings. Strings are joined by + * adding a new line character in between each of them. + * @return GLES20 program id. + */ + public static int compileProgram(String[] vertexCode, String[] fragmentCode) { + return compileProgram(TextUtils.join("\n", vertexCode), TextUtils.join("\n", fragmentCode)); + } + + /** + * Builds a GL shader program from vertex and fragment shader code. + * + * @param vertexCode GLES20 vertex shader program. + * @param fragmentCode GLES20 fragment shader program. + * @return GLES20 program id. + */ + public static int compileProgram(String vertexCode, String fragmentCode) { + int program = GLES20.glCreateProgram(); + checkGlError(); + + // Add the vertex and fragment shaders. + addShader(GLES20.GL_VERTEX_SHADER, vertexCode, program); + addShader(GLES20.GL_FRAGMENT_SHADER, fragmentCode, program); + + // Link and check for errors. + GLES20.glLinkProgram(program); + int[] linkStatus = new int[] {GLES20.GL_FALSE}; + GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0); + if (linkStatus[0] != GLES20.GL_TRUE) { + throwGlException("Unable to link shader program: \n" + GLES20.glGetProgramInfoLog(program)); + } + checkGlError(); + + return program; + } + + /** Returns the {@link Attribute}s in the specified {@code program}. */ + public static Attribute[] getAttributes(int program) { + int[] attributeCount = new int[1]; + GLES20.glGetProgramiv(program, GLES20.GL_ACTIVE_ATTRIBUTES, attributeCount, 0); + if (attributeCount[0] != 2) { + throw new IllegalStateException("Expected two attributes."); + } + + Attribute[] attributes = new Attribute[attributeCount[0]]; + for (int i = 0; i < attributeCount[0]; i++) { + attributes[i] = new Attribute(program, i); + } + return attributes; + } + + /** Returns the {@link Uniform}s in the specified {@code program}. */ + public static Uniform[] getUniforms(int program) { + int[] uniformCount = new int[1]; + GLES20.glGetProgramiv(program, GLES20.GL_ACTIVE_UNIFORMS, uniformCount, 0); + + Uniform[] uniforms = new Uniform[uniformCount[0]]; + for (int i = 0; i < uniformCount[0]; i++) { + uniforms[i] = new Uniform(program, i); + } + + return uniforms; + } + /** * Deletes a GL texture. * @@ -533,6 +478,22 @@ public final class GlUtil { return texId[0]; } + private static void addShader(int type, String source, int program) { + int shader = GLES20.glCreateShader(type); + GLES20.glShaderSource(shader, source); + GLES20.glCompileShader(shader); + + int[] result = new int[] {GLES20.GL_FALSE}; + GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, result, 0); + if (result[0] != GLES20.GL_TRUE) { + throwGlException(GLES20.glGetShaderInfoLog(shader) + ", source: " + source); + } + + GLES20.glAttachShader(program, shader); + GLES20.glDeleteShader(shader); + checkGlError(); + } + private static void throwGlException(String errorMsg) { Log.e(TAG, errorMsg); if (glAssertionsEnabled) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/VideoDecoderGLSurfaceView.java b/library/core/src/main/java/com/google/android/exoplayer2/video/VideoDecoderGLSurfaceView.java index 756f5ed7ee..f47a76760f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/VideoDecoderGLSurfaceView.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/VideoDecoderGLSurfaceView.java @@ -15,8 +15,6 @@ */ package com.google.android.exoplayer2.video; -import static com.google.android.exoplayer2.util.Assertions.checkNotNull; - import android.content.Context; import android.opengl.GLES20; import android.opengl.GLSurfaceView; @@ -142,7 +140,7 @@ public final class VideoDecoderGLSurfaceView extends GLSurfaceView // glDrawArrays uses it. private final FloatBuffer[] textureCoords; - @Nullable private GlUtil.Program program; + private int program; private int colorMatrixLocation; // Accessed only from the GL thread. @@ -163,9 +161,9 @@ public final class VideoDecoderGLSurfaceView extends GLSurfaceView @Override public void onSurfaceCreated(GL10 unused, EGLConfig config) { - program = new GlUtil.Program(VERTEX_SHADER, FRAGMENT_SHADER); - program.use(); - int posLocation = program.glGetAttribLocation("in_pos"); + program = GlUtil.compileProgram(VERTEX_SHADER, FRAGMENT_SHADER); + GLES20.glUseProgram(program); + int posLocation = GLES20.glGetAttribLocation(program, "in_pos"); GLES20.glEnableVertexAttribArray(posLocation); GLES20.glVertexAttribPointer( posLocation, @@ -174,14 +172,14 @@ public final class VideoDecoderGLSurfaceView extends GLSurfaceView /* normalized= */ false, /* stride= */ 0, TEXTURE_VERTICES); - texLocations[0] = checkNotNull(program).glGetAttribLocation("in_tc_y"); + texLocations[0] = GLES20.glGetAttribLocation(program, "in_tc_y"); GLES20.glEnableVertexAttribArray(texLocations[0]); - texLocations[1] = checkNotNull(program).glGetAttribLocation("in_tc_u"); + texLocations[1] = GLES20.glGetAttribLocation(program, "in_tc_u"); GLES20.glEnableVertexAttribArray(texLocations[1]); - texLocations[2] = checkNotNull(program).glGetAttribLocation("in_tc_v"); + texLocations[2] = GLES20.glGetAttribLocation(program, "in_tc_v"); GLES20.glEnableVertexAttribArray(texLocations[2]); GlUtil.checkGlError(); - colorMatrixLocation = checkNotNull(program).glGetUniformLocation("mColorConversion"); + colorMatrixLocation = GLES20.glGetUniformLocation(program, "mColorConversion"); GlUtil.checkGlError(); setupTextures(); GlUtil.checkGlError(); @@ -298,7 +296,7 @@ public final class VideoDecoderGLSurfaceView extends GLSurfaceView private void setupTextures() { GLES20.glGenTextures(3, yuvTextures, /* offset= */ 0); for (int i = 0; i < 3; i++) { - GLES20.glUniform1i(checkNotNull(program).glGetUniformLocation(TEXTURE_UNIFORMS[i]), i); + GLES20.glUniform1i(GLES20.glGetUniformLocation(program, TEXTURE_UNIFORMS[i]), i); GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, yuvTextures[i]); GLES20.glTexParameterf( diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/spherical/ProjectionRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/video/spherical/ProjectionRenderer.java index 8f59f53718..4ba5dcca08 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/spherical/ProjectionRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/spherical/ProjectionRenderer.java @@ -15,7 +15,6 @@ */ package com.google.android.exoplayer2.video.spherical; -import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static com.google.android.exoplayer2.util.GlUtil.checkGlError; import android.opengl.GLES11Ext; @@ -91,12 +90,11 @@ import java.nio.FloatBuffer; }; private int stereoMode; - - @Nullable private GlUtil.Program program; @Nullable private MeshData leftMeshData; @Nullable private MeshData rightMeshData; // Program related GL items. These are only valid if program != 0. + private int program; private int mvpMatrixHandle; private int uTexMatrixHandle; private int positionHandle; @@ -121,12 +119,12 @@ import java.nio.FloatBuffer; /** Initializes of the GL components. */ /* package */ void init() { - program = new GlUtil.Program(VERTEX_SHADER_CODE, FRAGMENT_SHADER_CODE); - mvpMatrixHandle = program.glGetUniformLocation("uMvpMatrix"); - uTexMatrixHandle = program.glGetUniformLocation("uTexMatrix"); - positionHandle = program.glGetAttribLocation("aPosition"); - texCoordsHandle = program.glGetAttribLocation("aTexCoords"); - textureHandle = program.glGetUniformLocation("uTexture"); + program = GlUtil.compileProgram(VERTEX_SHADER_CODE, FRAGMENT_SHADER_CODE); + mvpMatrixHandle = GLES20.glGetUniformLocation(program, "uMvpMatrix"); + uTexMatrixHandle = GLES20.glGetUniformLocation(program, "uTexMatrix"); + positionHandle = GLES20.glGetAttribLocation(program, "aPosition"); + texCoordsHandle = GLES20.glGetAttribLocation(program, "aTexCoords"); + textureHandle = GLES20.glGetUniformLocation(program, "uTexture"); } /** @@ -145,7 +143,7 @@ import java.nio.FloatBuffer; } // Configure shader. - checkNotNull(program).use(); + GLES20.glUseProgram(program); checkGlError(); GLES20.glEnableVertexAttribArray(positionHandle); @@ -198,9 +196,8 @@ import java.nio.FloatBuffer; /** Cleans up the GL resources. */ /* package */ void shutdown() { - if (program != null) { - program.delete(); - program = null; + if (program != 0) { + GLES20.glDeleteProgram(program); } } diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerTranscodingVideoRenderer.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerTranscodingVideoRenderer.java index 8064927f00..88e04a0b70 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerTranscodingVideoRenderer.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerTranscodingVideoRenderer.java @@ -186,7 +186,6 @@ import java.nio.ByteBuffer; } eglSurface = GlUtil.getEglSurface(eglDisplay, checkNotNull(checkNotNull(encoder).getInputSurface())); - GlUtil.focusSurface( eglDisplay, eglContext, @@ -194,20 +193,17 @@ import java.nio.ByteBuffer; encoderConfigurationOutputFormat.width, encoderConfigurationOutputFormat.height); decoderTextureId = GlUtil.createExternalTexture(); - - GlUtil.Program copyProgram; + String vertexShaderCode; + String fragmentShaderCode; try { - copyProgram = - new GlUtil.Program( - context, - /* vertexShaderFilePath= */ "shaders/blit_vertex_shader.glsl", - /* fragmentShaderFilePath= */ "shaders/copy_external_fragment_shader.glsl"); + vertexShaderCode = GlUtil.loadAsset(context, "shaders/blit_vertex_shader.glsl"); + fragmentShaderCode = GlUtil.loadAsset(context, "shaders/copy_external_fragment_shader.glsl"); } catch (IOException e) { throw new IllegalStateException(e); } - - copyProgram.use(); - GlUtil.Attribute[] copyAttributes = copyProgram.getAttributes(); + int copyProgram = GlUtil.compileProgram(vertexShaderCode, fragmentShaderCode); + GLES20.glUseProgram(copyProgram); + GlUtil.Attribute[] copyAttributes = GlUtil.getAttributes(copyProgram); checkState(copyAttributes.length == 2, "Expected program to have two vertex attributes."); for (GlUtil.Attribute copyAttribute : copyAttributes) { if (copyAttribute.name.equals("a_position")) { @@ -233,7 +229,7 @@ import java.nio.ByteBuffer; } copyAttribute.bind(); } - GlUtil.Uniform[] copyUniforms = copyProgram.getUniforms(); + GlUtil.Uniform[] copyUniforms = GlUtil.getUniforms(copyProgram); checkState(copyUniforms.length == 2, "Expected program to have two uniforms."); for (GlUtil.Uniform copyUniform : copyUniforms) { if (copyUniform.name.equals("tex_sampler")) {