Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(233)

Side by Side Diff: talk/app/webrtc/java/android/org/webrtc/GlRectDrawer.java

Issue 1520243003: Android: Refactor renderers to allow apps to inject custom shaders (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Address Nisses comments Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * libjingle 2 * libjingle
3 * Copyright 2015 Google Inc. 3 * Copyright 2015 Google Inc.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright notice, 8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer. 9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, 10 * 2. Redistributions in binary form must reproduce the above copyright notice,
(...skipping 22 matching lines...) Expand all
33 import org.webrtc.GlShader; 33 import org.webrtc.GlShader;
34 import org.webrtc.GlUtil; 34 import org.webrtc.GlUtil;
35 35
36 import java.nio.ByteBuffer; 36 import java.nio.ByteBuffer;
37 import java.nio.FloatBuffer; 37 import java.nio.FloatBuffer;
38 import java.util.Arrays; 38 import java.util.Arrays;
39 import java.util.IdentityHashMap; 39 import java.util.IdentityHashMap;
40 import java.util.Map; 40 import java.util.Map;
41 41
42 /** 42 /**
43 * Helper class to draw a quad that covers the entire viewport. Rotation, mirror , and cropping is 43 * Helper class to draw an opaque quad on the target viewport location. Rotation , mirror, and
44 * specified using a 4x4 texture coordinate transform matrix. The frame input ca n either be an OES 44 * cropping is specified using a 4x4 texture coordinate transform matrix. The fr ame input can either
45 * texture or YUV textures in I420 format. The GL state must be preserved betwee n draw calls, this 45 * be an OES texture or YUV textures in I420 format. The GL state must be preser ved between draw
46 * is intentional to maximize performance. The function release() must be called manually to free 46 * calls, this is intentional to maximize performance. The function release() mu st be called
47 * the resources held by this object. 47 * manually to free the resources held by this object.
48 */ 48 */
49 public class GlRectDrawer { 49 public class GlRectDrawer implements RendererCommon.GlDrawer {
50 // Simple vertex shader, used for both YUV and OES. 50 // Simple vertex shader, used for both YUV and OES.
51 private static final String VERTEX_SHADER_STRING = 51 private static final String VERTEX_SHADER_STRING =
52 "varying vec2 interp_tc;\n" 52 "varying vec2 interp_tc;\n"
53 + "attribute vec4 in_pos;\n" 53 + "attribute vec4 in_pos;\n"
54 + "attribute vec4 in_tc;\n" 54 + "attribute vec4 in_tc;\n"
55 + "\n" 55 + "\n"
56 + "uniform mat4 texMatrix;\n" 56 + "uniform mat4 texMatrix;\n"
57 + "\n" 57 + "\n"
58 + "void main() {\n" 58 + "void main() {\n"
59 + " gl_Position = in_pos;\n" 59 + " gl_Position = in_pos;\n"
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 111
112 // Texture coordinates - (0, 0) is bottom-left and (1, 1) is top-right. 112 // Texture coordinates - (0, 0) is bottom-left and (1, 1) is top-right.
113 private static final FloatBuffer FULL_RECTANGLE_TEX_BUF = 113 private static final FloatBuffer FULL_RECTANGLE_TEX_BUF =
114 GlUtil.createFloatBuffer(new float[] { 114 GlUtil.createFloatBuffer(new float[] {
115 0.0f, 0.0f, // Bottom left. 115 0.0f, 0.0f, // Bottom left.
116 1.0f, 0.0f, // Bottom right. 116 1.0f, 0.0f, // Bottom right.
117 0.0f, 1.0f, // Top left. 117 0.0f, 1.0f, // Top left.
118 1.0f, 1.0f // Top right. 118 1.0f, 1.0f // Top right.
119 }); 119 });
120 120
121 // The keys are one of the fragments shaders above. 121 private static class Shader {
122 private final Map<String, GlShader> shaders = new IdentityHashMap<String, GlSh ader>(); 122 public final GlShader glShader;
123 private GlShader currentShader; 123 public final int texMatrixLocation;
124 private float[] currentTexMatrix;
125 private int texMatrixLocation;
126 // Intermediate copy buffer for uploading yuv frames that are not packed, i.e. stride > width.
127 // TODO(magjed): Investigate when GL_UNPACK_ROW_LENGTH is available, or make a custom shader that
128 // handles stride and compare performance with intermediate copy.
129 private ByteBuffer copyBuffer;
130 124
131 /** 125 public Shader(String fragmentShader) {
132 * Upload |planes| into |outputYuvTextures|, taking stride into consideration. |outputYuvTextures| 126 this.glShader = new GlShader(VERTEX_SHADER_STRING, fragmentShader);
133 * must have been generated in advance. 127 this.texMatrixLocation = glShader.getUniformLocation("texMatrix");
134 */
135 public void uploadYuvData(
136 int[] outputYuvTextures, int width, int height, int[] strides, ByteBuffer[ ] planes) {
137 // Make a first pass to see if we need a temporary copy buffer.
138 int copyCapacityNeeded = 0;
139 for (int i = 0; i < 3; ++i) {
140 final int planeWidth = (i == 0) ? width : width / 2;
141 final int planeHeight = (i == 0) ? height : height / 2;
142 if (strides[i] > planeWidth) {
143 copyCapacityNeeded = Math.max(copyCapacityNeeded, planeWidth * planeHeig ht);
144 }
145 }
146 // Allocate copy buffer if necessary.
147 if (copyCapacityNeeded > 0
148 && (copyBuffer == null || copyBuffer.capacity() < copyCapacityNeeded)) {
149 copyBuffer = ByteBuffer.allocateDirect(copyCapacityNeeded);
150 }
151 // Upload each plane.
152 for (int i = 0; i < 3; ++i) {
153 GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i);
154 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, outputYuvTextures[i]);
155 final int planeWidth = (i == 0) ? width : width / 2;
156 final int planeHeight = (i == 0) ? height : height / 2;
157 // GLES only accepts packed data, i.e. stride == planeWidth.
158 final ByteBuffer packedByteBuffer;
159 if (strides[i] == planeWidth) {
160 // Input is packed already.
161 packedByteBuffer = planes[i];
162 } else {
163 VideoRenderer.nativeCopyPlane(
164 planes[i], planeWidth, planeHeight, strides[i], copyBuffer, planeWid th);
165 packedByteBuffer = copyBuffer;
166 }
167 GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, planeWid th, planeHeight, 0,
168 GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, packedByteBuffer);
169 } 128 }
170 } 129 }
171 130
131 // The keys are one of the fragments shaders above.
132 private final Map<String, Shader> shaders = new IdentityHashMap<String, Shader >();
133
172 /** 134 /**
173 * Draw an OES texture frame with specified texture transformation matrix. Req uired resources are 135 * Draw an OES texture frame with specified texture transformation matrix. Req uired resources are
174 * allocated at the first call to this function. 136 * allocated at the first call to this function.
175 */ 137 */
176 public void drawOes(int oesTextureId, float[] texMatrix) { 138 @Override
177 prepareShader(OES_FRAGMENT_SHADER_STRING); 139 public void drawOes(int oesTextureId, float[] texMatrix, int x, int y, int wid th, int height) {
140 prepareShader(OES_FRAGMENT_SHADER_STRING, texMatrix);
141 GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
178 // updateTexImage() may be called from another thread in another EGL context , so we need to 142 // updateTexImage() may be called from another thread in another EGL context , so we need to
179 // bind/unbind the texture in each draw call so that GLES understads it's a new texture. 143 // bind/unbind the texture in each draw call so that GLES understads it's a new texture.
180 GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, oesTextureId); 144 GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, oesTextureId);
181 drawRectangle(texMatrix); 145 drawRectangle(x, y, width, height);
182 GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0); 146 GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0);
183 } 147 }
184 148
185 /** 149 /**
186 * Draw a RGB(A) texture frame with specified texture transformation matrix. R equired resources 150 * Draw a RGB(A) texture frame with specified texture transformation matrix. R equired resources
187 * are allocated at the first call to this function. 151 * are allocated at the first call to this function.
188 */ 152 */
189 public void drawRgb(int textureId, float[] texMatrix) { 153 @Override
190 prepareShader(RGB_FRAGMENT_SHADER_STRING); 154 public void drawRgb(int textureId, float[] texMatrix, int x, int y, int width, int height) {
155 prepareShader(RGB_FRAGMENT_SHADER_STRING, texMatrix);
156 GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
191 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId); 157 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
192 drawRectangle(texMatrix); 158 drawRectangle(x, y, width, height);
193 // Unbind the texture as a precaution. 159 // Unbind the texture as a precaution.
194 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); 160 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
195 } 161 }
196 162
197 /** 163 /**
198 * Draw a YUV frame with specified texture transformation matrix. Required res ources are 164 * Draw a YUV frame with specified texture transformation matrix. Required res ources are
199 * allocated at the first call to this function. 165 * allocated at the first call to this function.
200 */ 166 */
201 public void drawYuv(int[] yuvTextures, float[] texMatrix) { 167 @Override
202 prepareShader(YUV_FRAGMENT_SHADER_STRING); 168 public void drawYuv(int[] yuvTextures, float[] texMatrix, int x, int y, int wi dth, int height) {
169 prepareShader(YUV_FRAGMENT_SHADER_STRING, texMatrix);
203 // Bind the textures. 170 // Bind the textures.
204 for (int i = 0; i < 3; ++i) { 171 for (int i = 0; i < 3; ++i) {
205 GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i); 172 GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i);
206 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, yuvTextures[i]); 173 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, yuvTextures[i]);
207 } 174 }
208 drawRectangle(texMatrix); 175 drawRectangle(x, y, width, height);
209 // Unbind the textures as a precaution.. 176 // Unbind the textures as a precaution..
210 for (int i = 0; i < 3; ++i) { 177 for (int i = 0; i < 3; ++i) {
211 GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i); 178 GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i);
212 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); 179 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
213 } 180 }
214 } 181 }
215 182
216 private void drawRectangle(float[] texMatrix) { 183 private void drawRectangle(int x, int y, int width, int height) {
217 // Try avoid uploading the texture if possible.
218 if (!Arrays.equals(currentTexMatrix, texMatrix)) {
219 currentTexMatrix = texMatrix.clone();
220 // Copy the texture transformation matrix over.
221 GLES20.glUniformMatrix4fv(texMatrixLocation, 1, false, texMatrix, 0);
222 }
223 // Draw quad. 184 // Draw quad.
185 GLES20.glViewport(x, y, width, height);
224 GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); 186 GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
225 } 187 }
226 188
227 private void prepareShader(String fragmentShader) { 189 private void prepareShader(String fragmentShader, float[] texMatrix) {
228 // Lazy allocation. 190 final Shader shader;
229 if (!shaders.containsKey(fragmentShader)) { 191 if (shaders.containsKey(fragmentShader)) {
230 final GlShader shader = new GlShader(VERTEX_SHADER_STRING, fragmentShader) ; 192 shader = shaders.get(fragmentShader);
193 } else {
194 // Lazy allocation.
195 shader = new Shader(fragmentShader);
231 shaders.put(fragmentShader, shader); 196 shaders.put(fragmentShader, shader);
232 shader.useProgram(); 197 shader.glShader.useProgram();
233 // Initialize fragment shader uniform values. 198 // Initialize fragment shader uniform values.
234 if (fragmentShader == YUV_FRAGMENT_SHADER_STRING) { 199 if (fragmentShader == YUV_FRAGMENT_SHADER_STRING) {
235 GLES20.glUniform1i(shader.getUniformLocation("y_tex"), 0); 200 GLES20.glUniform1i(shader.glShader.getUniformLocation("y_tex"), 0);
236 GLES20.glUniform1i(shader.getUniformLocation("u_tex"), 1); 201 GLES20.glUniform1i(shader.glShader.getUniformLocation("u_tex"), 1);
237 GLES20.glUniform1i(shader.getUniformLocation("v_tex"), 2); 202 GLES20.glUniform1i(shader.glShader.getUniformLocation("v_tex"), 2);
238 } else if (fragmentShader == RGB_FRAGMENT_SHADER_STRING) { 203 } else if (fragmentShader == RGB_FRAGMENT_SHADER_STRING) {
239 GLES20.glUniform1i(shader.getUniformLocation("rgb_tex"), 0); 204 GLES20.glUniform1i(shader.glShader.getUniformLocation("rgb_tex"), 0);
240 } else if (fragmentShader == OES_FRAGMENT_SHADER_STRING) { 205 } else if (fragmentShader == OES_FRAGMENT_SHADER_STRING) {
241 GLES20.glUniform1i(shader.getUniformLocation("oes_tex"), 0); 206 GLES20.glUniform1i(shader.glShader.getUniformLocation("oes_tex"), 0);
242 } else { 207 } else {
243 throw new IllegalStateException("Unknown fragment shader: " + fragmentSh ader); 208 throw new IllegalStateException("Unknown fragment shader: " + fragmentSh ader);
244 } 209 }
245 GlUtil.checkNoGLES2Error("Initialize fragment shader uniform values."); 210 GlUtil.checkNoGLES2Error("Initialize fragment shader uniform values.");
246 // Initialize vertex shader attributes. 211 // Initialize vertex shader attributes.
247 shader.setVertexAttribArray("in_pos", 2, FULL_RECTANGLE_BUF); 212 shader.glShader.setVertexAttribArray("in_pos", 2, FULL_RECTANGLE_BUF);
248 shader.setVertexAttribArray("in_tc", 2, FULL_RECTANGLE_TEX_BUF); 213 shader.glShader.setVertexAttribArray("in_tc", 2, FULL_RECTANGLE_TEX_BUF);
249 } 214 }
250 215 shader.glShader.useProgram();
251 // Update GLES state if shader is not already current. 216 // Copy the texture transformation matrix over.
252 final GlShader shader = shaders.get(fragmentShader); 217 GLES20.glUniformMatrix4fv(shader.texMatrixLocation, 1, false, texMatrix, 0);
253 if (currentShader != shader) {
254 currentShader = shader;
255 shader.useProgram();
256 GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
257 currentTexMatrix = null;
258 texMatrixLocation = shader.getUniformLocation("texMatrix");
259 }
260 } 218 }
261 219
262 /** 220 /**
263 * Release all GLES resources. This needs to be done manually, otherwise the r esources are leaked. 221 * Release all GLES resources. This needs to be done manually, otherwise the r esources are leaked.
264 */ 222 */
223 @Override
265 public void release() { 224 public void release() {
266 for (GlShader shader : shaders.values()) { 225 for (Shader shader : shaders.values()) {
267 shader.release(); 226 shader.glShader.release();
268 } 227 }
269 shaders.clear(); 228 shaders.clear();
270 copyBuffer = null;
271 } 229 }
272 } 230 }
OLDNEW
« no previous file with comments | « talk/app/webrtc/java/android/org/webrtc/EglBase.java ('k') | talk/app/webrtc/java/android/org/webrtc/RendererCommon.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698