Commit dcdcb919 by huangdarwin Committed by bachinger

Transformer GL: Simplify GL program handling.

Relanding http://https://github.com/google/ExoPlayer/commit/9788750ddb23b2064dddf99d6e1ea491b2e45cea, with some changes
applied to improve primarily readability, naming,
and nullness checks.

PiperOrigin-RevId: 406101742
parent ad39f389
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
*/ */
package com.google.android.exoplayer2.gldemo; package com.google.android.exoplayer2.gldemo;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.Bitmap; import android.graphics.Bitmap;
...@@ -26,11 +28,11 @@ import android.opengl.GLES20; ...@@ -26,11 +28,11 @@ import android.opengl.GLES20;
import android.opengl.GLUtils; import android.opengl.GLUtils;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.GlUtil; import com.google.android.exoplayer2.util.GlUtil;
import java.io.IOException; import java.io.IOException;
import java.util.Locale; import java.util.Locale;
import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.opengles.GL10;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/** /**
* Video processor that demonstrates how to overlay a bitmap on video output using a GL shader. The * Video processor that demonstrates how to overlay a bitmap on video output using a GL shader. The
...@@ -49,7 +51,7 @@ import javax.microedition.khronos.opengles.GL10; ...@@ -49,7 +51,7 @@ import javax.microedition.khronos.opengles.GL10;
private final Bitmap logoBitmap; private final Bitmap logoBitmap;
private final Canvas overlayCanvas; private final Canvas overlayCanvas;
private int program; private GlUtil.@MonotonicNonNull Program program;
@Nullable private GlUtil.Attribute[] attributes; @Nullable private GlUtil.Attribute[] attributes;
@Nullable private GlUtil.Uniform[] uniforms; @Nullable private GlUtil.Uniform[] uniforms;
...@@ -77,27 +79,39 @@ import javax.microedition.khronos.opengles.GL10; ...@@ -77,27 +79,39 @@ import javax.microedition.khronos.opengles.GL10;
@Override @Override
public void initialize() { public void initialize() {
String vertexShaderCode;
String fragmentShaderCode;
try { try {
vertexShaderCode = GlUtil.loadAsset(context, "bitmap_overlay_video_processor_vertex.glsl"); program =
fragmentShaderCode = new GlUtil.Program(
GlUtil.loadAsset(context, "bitmap_overlay_video_processor_fragment.glsl"); context,
/* vertexShaderFilePath= */ "bitmap_overlay_video_processor_vertex.glsl",
/* fragmentShaderFilePath= */ "bitmap_overlay_video_processor_fragment.glsl");
} catch (IOException e) { } catch (IOException e) {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
program = GlUtil.compileProgram(vertexShaderCode, fragmentShaderCode); GlUtil.Attribute[] attributes = program.getAttributes();
GlUtil.Attribute[] attributes = GlUtil.getAttributes(program);
GlUtil.Uniform[] uniforms = GlUtil.getUniforms(program);
for (GlUtil.Attribute attribute : attributes) { for (GlUtil.Attribute attribute : attributes) {
if (attribute.name.equals("a_position")) { 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")) { } 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.attributes = attributes;
this.uniforms = uniforms; this.uniforms = program.getUniforms();
GLES20.glGenTextures(1, textures, 0); GLES20.glGenTextures(1, textures, 0);
GLES20.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); GLES20.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
GLES20.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST); GLES20.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
...@@ -126,9 +140,9 @@ import javax.microedition.khronos.opengles.GL10; ...@@ -126,9 +140,9 @@ import javax.microedition.khronos.opengles.GL10;
GlUtil.checkGlError(); GlUtil.checkGlError();
// Run the shader program. // Run the shader program.
GlUtil.Uniform[] uniforms = Assertions.checkNotNull(this.uniforms); GlUtil.Uniform[] uniforms = checkNotNull(this.uniforms);
GlUtil.Attribute[] attributes = Assertions.checkNotNull(this.attributes); GlUtil.Attribute[] attributes = checkNotNull(this.attributes);
GLES20.glUseProgram(program); checkNotNull(program).use();
for (GlUtil.Uniform uniform : uniforms) { for (GlUtil.Uniform uniform : uniforms) {
switch (uniform.name) { switch (uniform.name) {
case "tex_sampler_0": case "tex_sampler_0":
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
*/ */
package com.google.android.exoplayer2.video; package com.google.android.exoplayer2.video;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import android.content.Context; import android.content.Context;
import android.opengl.GLES20; import android.opengl.GLES20;
import android.opengl.GLSurfaceView; import android.opengl.GLSurfaceView;
...@@ -30,6 +32,7 @@ import javax.microedition.khronos.egl.EGLConfig; ...@@ -30,6 +32,7 @@ import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.opengles.GL10;
import org.checkerframework.checker.nullness.compatqual.NullableType; import org.checkerframework.checker.nullness.compatqual.NullableType;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
/** /**
* GLSurfaceView implementing {@link VideoDecoderOutputBufferRenderer} for rendering {@link * GLSurfaceView implementing {@link VideoDecoderOutputBufferRenderer} for rendering {@link
...@@ -141,7 +144,7 @@ public final class VideoDecoderGLSurfaceView extends GLSurfaceView ...@@ -141,7 +144,7 @@ public final class VideoDecoderGLSurfaceView extends GLSurfaceView
// glDrawArrays uses it. // glDrawArrays uses it.
private final FloatBuffer[] textureCoords; private final FloatBuffer[] textureCoords;
private int program; private GlUtil.@MonotonicNonNull Program program;
private int colorMatrixLocation; private int colorMatrixLocation;
// Accessed only from the GL thread. // Accessed only from the GL thread.
...@@ -162,9 +165,9 @@ public final class VideoDecoderGLSurfaceView extends GLSurfaceView ...@@ -162,9 +165,9 @@ public final class VideoDecoderGLSurfaceView extends GLSurfaceView
@Override @Override
public void onSurfaceCreated(GL10 unused, EGLConfig config) { public void onSurfaceCreated(GL10 unused, EGLConfig config) {
program = GlUtil.compileProgram(VERTEX_SHADER, FRAGMENT_SHADER); program = new GlUtil.Program(VERTEX_SHADER, FRAGMENT_SHADER);
GLES20.glUseProgram(program); program.use();
int posLocation = GLES20.glGetAttribLocation(program, "in_pos"); int posLocation = program.getAttribLocation("in_pos");
GLES20.glEnableVertexAttribArray(posLocation); GLES20.glEnableVertexAttribArray(posLocation);
GLES20.glVertexAttribPointer( GLES20.glVertexAttribPointer(
posLocation, posLocation,
...@@ -173,14 +176,14 @@ public final class VideoDecoderGLSurfaceView extends GLSurfaceView ...@@ -173,14 +176,14 @@ public final class VideoDecoderGLSurfaceView extends GLSurfaceView
/* normalized= */ false, /* normalized= */ false,
/* stride= */ 0, /* stride= */ 0,
TEXTURE_VERTICES); TEXTURE_VERTICES);
texLocations[0] = GLES20.glGetAttribLocation(program, "in_tc_y"); texLocations[0] = program.getAttribLocation("in_tc_y");
GLES20.glEnableVertexAttribArray(texLocations[0]); GLES20.glEnableVertexAttribArray(texLocations[0]);
texLocations[1] = GLES20.glGetAttribLocation(program, "in_tc_u"); texLocations[1] = program.getAttribLocation("in_tc_u");
GLES20.glEnableVertexAttribArray(texLocations[1]); GLES20.glEnableVertexAttribArray(texLocations[1]);
texLocations[2] = GLES20.glGetAttribLocation(program, "in_tc_v"); texLocations[2] = program.getAttribLocation("in_tc_v");
GLES20.glEnableVertexAttribArray(texLocations[2]); GLES20.glEnableVertexAttribArray(texLocations[2]);
GlUtil.checkGlError(); GlUtil.checkGlError();
colorMatrixLocation = GLES20.glGetUniformLocation(program, "mColorConversion"); colorMatrixLocation = program.getUniformLocation("mColorConversion");
GlUtil.checkGlError(); GlUtil.checkGlError();
setupTextures(); setupTextures();
GlUtil.checkGlError(); GlUtil.checkGlError();
...@@ -207,7 +210,7 @@ public final class VideoDecoderGLSurfaceView extends GLSurfaceView ...@@ -207,7 +210,7 @@ public final class VideoDecoderGLSurfaceView extends GLSurfaceView
renderedOutputBuffer = pendingOutputBuffer; renderedOutputBuffer = pendingOutputBuffer;
} }
VideoDecoderOutputBuffer outputBuffer = Assertions.checkNotNull(renderedOutputBuffer); VideoDecoderOutputBuffer outputBuffer = checkNotNull(renderedOutputBuffer);
// Set color matrix. Assume BT709 if the color space is unknown. // Set color matrix. Assume BT709 if the color space is unknown.
float[] colorConversion = kColorConversion709; float[] colorConversion = kColorConversion709;
...@@ -230,8 +233,8 @@ public final class VideoDecoderGLSurfaceView extends GLSurfaceView ...@@ -230,8 +233,8 @@ public final class VideoDecoderGLSurfaceView extends GLSurfaceView
colorConversion, colorConversion,
/* offset= */ 0); /* offset= */ 0);
int[] yuvStrides = Assertions.checkNotNull(outputBuffer.yuvStrides); int[] yuvStrides = checkNotNull(outputBuffer.yuvStrides);
ByteBuffer[] yuvPlanes = Assertions.checkNotNull(outputBuffer.yuvPlanes); ByteBuffer[] yuvPlanes = checkNotNull(outputBuffer.yuvPlanes);
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
int h = (i == 0) ? outputBuffer.height : (outputBuffer.height + 1) / 2; int h = (i == 0) ? outputBuffer.height : (outputBuffer.height + 1) / 2;
...@@ -294,10 +297,11 @@ public final class VideoDecoderGLSurfaceView extends GLSurfaceView ...@@ -294,10 +297,11 @@ public final class VideoDecoderGLSurfaceView extends GLSurfaceView
surfaceView.requestRender(); surfaceView.requestRender();
} }
@RequiresNonNull("program")
private void setupTextures() { private void setupTextures() {
GLES20.glGenTextures(3, yuvTextures, /* offset= */ 0); GLES20.glGenTextures(3, yuvTextures, /* offset= */ 0);
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
GLES20.glUniform1i(GLES20.glGetUniformLocation(program, TEXTURE_UNIFORMS[i]), i); GLES20.glUniform1i(program.getUniformLocation(TEXTURE_UNIFORMS[i]), i);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i); GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, yuvTextures[i]); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, yuvTextures[i]);
GLES20.glTexParameterf( GLES20.glTexParameterf(
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer2.video.spherical; 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 static com.google.android.exoplayer2.util.GlUtil.checkGlError;
import android.opengl.GLES11Ext; import android.opengl.GLES11Ext;
...@@ -92,9 +93,9 @@ import java.nio.FloatBuffer; ...@@ -92,9 +93,9 @@ import java.nio.FloatBuffer;
private int stereoMode; private int stereoMode;
@Nullable private MeshData leftMeshData; @Nullable private MeshData leftMeshData;
@Nullable private MeshData rightMeshData; @Nullable private MeshData rightMeshData;
@Nullable private GlUtil.Program program;
// Program related GL items. These are only valid if program != 0. // Program related GL items. These are only valid if program is non-null.
private int program;
private int mvpMatrixHandle; private int mvpMatrixHandle;
private int uTexMatrixHandle; private int uTexMatrixHandle;
private int positionHandle; private int positionHandle;
...@@ -119,12 +120,12 @@ import java.nio.FloatBuffer; ...@@ -119,12 +120,12 @@ import java.nio.FloatBuffer;
/** Initializes of the GL components. */ /** Initializes of the GL components. */
/* package */ void init() { /* package */ void init() {
program = GlUtil.compileProgram(VERTEX_SHADER_CODE, FRAGMENT_SHADER_CODE); program = new GlUtil.Program(VERTEX_SHADER_CODE, FRAGMENT_SHADER_CODE);
mvpMatrixHandle = GLES20.glGetUniformLocation(program, "uMvpMatrix"); mvpMatrixHandle = program.getUniformLocation("uMvpMatrix");
uTexMatrixHandle = GLES20.glGetUniformLocation(program, "uTexMatrix"); uTexMatrixHandle = program.getUniformLocation("uTexMatrix");
positionHandle = GLES20.glGetAttribLocation(program, "aPosition"); positionHandle = program.getAttribLocation("aPosition");
texCoordsHandle = GLES20.glGetAttribLocation(program, "aTexCoords"); texCoordsHandle = program.getAttribLocation("aTexCoords");
textureHandle = GLES20.glGetUniformLocation(program, "uTexture"); textureHandle = program.getUniformLocation("uTexture");
} }
/** /**
...@@ -143,7 +144,7 @@ import java.nio.FloatBuffer; ...@@ -143,7 +144,7 @@ import java.nio.FloatBuffer;
} }
// Configure shader. // Configure shader.
GLES20.glUseProgram(program); checkNotNull(program).use();
checkGlError(); checkGlError();
GLES20.glEnableVertexAttribArray(positionHandle); GLES20.glEnableVertexAttribArray(positionHandle);
...@@ -196,8 +197,9 @@ import java.nio.FloatBuffer; ...@@ -196,8 +197,9 @@ import java.nio.FloatBuffer;
/** Cleans up the GL resources. */ /** Cleans up the GL resources. */
/* package */ void shutdown() { /* package */ void shutdown() {
if (program != 0) { if (program != null) {
GLES20.glDeleteProgram(program); program.delete();
program = null;
} }
} }
......
...@@ -229,17 +229,19 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -229,17 +229,19 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
GlUtil.focusSurface( GlUtil.focusSurface(
eglDisplay, eglContext, eglSurface, decoderInputFormat.width, decoderInputFormat.height); eglDisplay, eglContext, eglSurface, decoderInputFormat.width, decoderInputFormat.height);
decoderTextureId = GlUtil.createExternalTexture(); decoderTextureId = GlUtil.createExternalTexture();
String vertexShaderCode; GlUtil.Program copyProgram;
String fragmentShaderCode;
try { try {
vertexShaderCode = GlUtil.loadAsset(context, "shaders/blit_vertex_shader.glsl"); copyProgram =
fragmentShaderCode = GlUtil.loadAsset(context, "shaders/copy_external_fragment_shader.glsl"); new GlUtil.Program(
context,
/* vertexShaderFilePath= */ "shaders/blit_vertex_shader.glsl",
/* fragmentShaderFilePath= */ "shaders/copy_external_fragment_shader.glsl");
} catch (IOException e) { } catch (IOException e) {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
int copyProgram = GlUtil.compileProgram(vertexShaderCode, fragmentShaderCode);
GLES20.glUseProgram(copyProgram); copyProgram.use();
GlUtil.Attribute[] copyAttributes = GlUtil.getAttributes(copyProgram); GlUtil.Attribute[] copyAttributes = copyProgram.getAttributes();
checkState(copyAttributes.length == 2, "Expected program to have two vertex attributes."); checkState(copyAttributes.length == 2, "Expected program to have two vertex attributes.");
for (GlUtil.Attribute copyAttribute : copyAttributes) { for (GlUtil.Attribute copyAttribute : copyAttributes) {
if (copyAttribute.name.equals("a_position")) { if (copyAttribute.name.equals("a_position")) {
...@@ -265,7 +267,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -265,7 +267,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
} }
copyAttribute.bind(); copyAttribute.bind();
} }
GlUtil.Uniform[] copyUniforms = GlUtil.getUniforms(copyProgram); GlUtil.Uniform[] copyUniforms = copyProgram.getUniforms();
checkState(copyUniforms.length == 2, "Expected program to have two uniforms."); checkState(copyUniforms.length == 2, "Expected program to have two uniforms.");
for (GlUtil.Uniform copyUniform : copyUniforms) { for (GlUtil.Uniform copyUniform : copyUniforms) {
if (copyUniform.name.equals("tex_sampler")) { if (copyUniform.name.equals("tex_sampler")) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment