OLD | NEW |
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 15 matching lines...) Expand all Loading... |
26 */ | 26 */ |
27 | 27 |
28 package org.webrtc; | 28 package org.webrtc; |
29 | 29 |
30 import android.graphics.Canvas; | 30 import android.graphics.Canvas; |
31 import android.graphics.SurfaceTexture; | 31 import android.graphics.SurfaceTexture; |
32 import android.graphics.Rect; | 32 import android.graphics.Rect; |
33 import android.view.Surface; | 33 import android.view.Surface; |
34 import android.view.SurfaceHolder; | 34 import android.view.SurfaceHolder; |
35 | 35 |
36 import org.webrtc.Logging; | |
37 import org.webrtc.EglBase.Context; | |
38 | |
39 import javax.microedition.khronos.egl.EGL10; | 36 import javax.microedition.khronos.egl.EGL10; |
40 import javax.microedition.khronos.egl.EGLConfig; | 37 import javax.microedition.khronos.egl.EGLConfig; |
41 import javax.microedition.khronos.egl.EGLContext; | 38 import javax.microedition.khronos.egl.EGLContext; |
42 import javax.microedition.khronos.egl.EGLDisplay; | 39 import javax.microedition.khronos.egl.EGLDisplay; |
43 import javax.microedition.khronos.egl.EGLSurface; | 40 import javax.microedition.khronos.egl.EGLSurface; |
44 | 41 |
45 /** | 42 /** |
46 * Holds EGL state and utility methods for handling an egl 1.0 EGLContext, an EG
LDisplay, | 43 * Holds EGL state and utility methods for handling an egl 1.0 EGLContext, an EG
LDisplay, |
47 * and an EGLSurface. | 44 * and an EGLSurface. |
48 */ | 45 */ |
49 public class EglBase { | 46 final class EglBase10 extends EglBase { |
50 private static final String TAG = "EglBase"; | 47 // This constant is taken from EGL14.EGL_CONTEXT_CLIENT_VERSION. |
51 // These constants are taken from EGL14.EGL_OPENGL_ES2_BIT and EGL14.EGL_CONTE
XT_CLIENT_VERSION. | |
52 // https://android.googlesource.com/platform/frameworks/base/+/master/opengl/j
ava/android/opengl/EGL14.java | |
53 // This is similar to how GlSurfaceView does: | |
54 // http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.androi
d/android/5.1.1_r1/android/opengl/GLSurfaceView.java#760 | |
55 private static final int EGL_OPENGL_ES2_BIT = 4; | |
56 private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; | 48 private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; |
57 // Android-specific extension. | |
58 private static final int EGL_RECORDABLE_ANDROID = 0x3142; | |
59 | 49 |
60 private final EGL10 egl; | 50 private final EGL10 egl; |
61 private EGLContext eglContext; | 51 private EGLContext eglContext; |
62 private EGLConfig eglConfig; | 52 private EGLConfig eglConfig; |
63 private EGLDisplay eglDisplay; | 53 private EGLDisplay eglDisplay; |
64 private EGLSurface eglSurface = EGL10.EGL_NO_SURFACE; | 54 private EGLSurface eglSurface = EGL10.EGL_NO_SURFACE; |
65 | 55 |
66 // EGL wrapper for an actual EGLContext. | 56 // EGL wrapper for an actual EGLContext. |
67 public static class Context { | 57 public static class Context extends EglBase.Context { |
68 private final EGLContext eglContext; | 58 private final EGLContext eglContext; |
69 | 59 |
70 public Context(EGLContext eglContext) { | 60 public Context(EGLContext eglContext) { |
71 this.eglContext = eglContext; | 61 this.eglContext = eglContext; |
72 } | 62 } |
73 } | 63 } |
74 | 64 |
75 public static final int[] CONFIG_PLAIN = { | |
76 EGL10.EGL_RED_SIZE, 8, | |
77 EGL10.EGL_GREEN_SIZE, 8, | |
78 EGL10.EGL_BLUE_SIZE, 8, | |
79 EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, | |
80 EGL10.EGL_NONE | |
81 }; | |
82 public static final int[] CONFIG_PIXEL_BUFFER = { | |
83 EGL10.EGL_RED_SIZE, 8, | |
84 EGL10.EGL_GREEN_SIZE, 8, | |
85 EGL10.EGL_BLUE_SIZE, 8, | |
86 EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, | |
87 EGL10.EGL_SURFACE_TYPE, EGL10.EGL_PBUFFER_BIT, | |
88 EGL10.EGL_NONE | |
89 }; | |
90 public static final int[] CONFIG_PIXEL_RGBA_BUFFER = { | |
91 EGL10.EGL_RED_SIZE, 8, | |
92 EGL10.EGL_GREEN_SIZE, 8, | |
93 EGL10.EGL_BLUE_SIZE, 8, | |
94 EGL10.EGL_ALPHA_SIZE, 8, | |
95 EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, | |
96 EGL10.EGL_SURFACE_TYPE, EGL10.EGL_PBUFFER_BIT, | |
97 EGL10.EGL_NONE | |
98 }; | |
99 public static final int[] CONFIG_RECORDABLE = { | |
100 EGL10.EGL_RED_SIZE, 8, | |
101 EGL10.EGL_GREEN_SIZE, 8, | |
102 EGL10.EGL_BLUE_SIZE, 8, | |
103 EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, | |
104 EGL_RECORDABLE_ANDROID, 1, | |
105 EGL10.EGL_NONE | |
106 }; | |
107 | |
108 // Create a new context with the specified config attributes, sharing data wit
h sharedContext. | |
109 // |sharedContext| can be null. | |
110 public static EglBase create(Context sharedContext, int[] configAttributes) { | |
111 return (EglBase14.isEGL14Supported() | |
112 && (sharedContext == null || sharedContext instanceof EglBase14.Context)
) | |
113 ? new EglBase14((EglBase14.Context) sharedContext, configAttributes) | |
114 : new EglBase(sharedContext, configAttributes); | |
115 } | |
116 | |
117 public static EglBase create() { | |
118 return create(null, CONFIG_PLAIN); | |
119 } | |
120 | |
121 //Create root context without any EGLSurface or parent EGLContext. This can be
used for branching | |
122 // new contexts that share data. | |
123 @Deprecated | |
124 public EglBase() { | |
125 this((Context) null, CONFIG_PLAIN); | |
126 } | |
127 | |
128 @Deprecated | |
129 public EglBase(EGLContext sharedContext, int[] configAttributes) { | |
130 this(new Context(sharedContext), configAttributes); | |
131 Logging.d(TAG, "EglBase created"); | |
132 } | |
133 | |
134 @Deprecated | |
135 public EGLContext getContext() { | |
136 return eglContext; | |
137 } | |
138 | |
139 // Create a new context with the specified config type, sharing data with shar
edContext. | 65 // Create a new context with the specified config type, sharing data with shar
edContext. |
140 EglBase(Context sharedContext, int[] configAttributes) { | 66 EglBase10(Context sharedContext, int[] configAttributes) { |
141 this.egl = (EGL10) EGLContext.getEGL(); | 67 this.egl = (EGL10) EGLContext.getEGL(); |
142 eglDisplay = getEglDisplay(); | 68 eglDisplay = getEglDisplay(); |
143 eglConfig = getEglConfig(eglDisplay, configAttributes); | 69 eglConfig = getEglConfig(eglDisplay, configAttributes); |
144 eglContext = createEglContext(sharedContext, eglDisplay, eglConfig); | 70 eglContext = createEglContext(sharedContext, eglDisplay, eglConfig); |
145 } | 71 } |
146 | 72 |
147 // TODO(perkj): This is a hacky ctor used to allow us to create an EGLBase14.
Remove this and | 73 @Override |
148 // make EglBase an abstract class once all applications have started using the
create factory | |
149 // method. | |
150 protected EglBase(boolean dummy) { | |
151 this.egl = null; | |
152 } | |
153 | |
154 public void createSurface(Surface surface) { | 74 public void createSurface(Surface surface) { |
155 /** | 75 /** |
156 * We have to wrap Surface in a SurfaceHolder because for some reason eglCre
ateWindowSurface | 76 * We have to wrap Surface in a SurfaceHolder because for some reason eglCre
ateWindowSurface |
157 * couldn't actually take a Surface object until API 17. Older versions fort
unately just call | 77 * couldn't actually take a Surface object until API 17. Older versions fort
unately just call |
158 * SurfaceHolder.getSurface(), so we'll do that. No other methods are releva
nt. | 78 * SurfaceHolder.getSurface(), so we'll do that. No other methods are releva
nt. |
159 */ | 79 */ |
160 class FakeSurfaceHolder implements SurfaceHolder { | 80 class FakeSurfaceHolder implements SurfaceHolder { |
161 private final Surface surface; | 81 private final Surface surface; |
162 | 82 |
163 FakeSurfaceHolder(Surface surface) { | 83 FakeSurfaceHolder(Surface surface) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 @Override | 132 @Override |
213 public Surface getSurface() { | 133 public Surface getSurface() { |
214 return surface; | 134 return surface; |
215 } | 135 } |
216 } | 136 } |
217 | 137 |
218 createSurfaceInternal(new FakeSurfaceHolder(surface)); | 138 createSurfaceInternal(new FakeSurfaceHolder(surface)); |
219 } | 139 } |
220 | 140 |
221 // Create EGLSurface from the Android SurfaceTexture. | 141 // Create EGLSurface from the Android SurfaceTexture. |
| 142 @Override |
222 public void createSurface(SurfaceTexture surfaceTexture) { | 143 public void createSurface(SurfaceTexture surfaceTexture) { |
223 createSurfaceInternal(surfaceTexture); | 144 createSurfaceInternal(surfaceTexture); |
224 } | 145 } |
225 | 146 |
226 // Create EGLSurface from either a SurfaceHolder or a SurfaceTexture. | 147 // Create EGLSurface from either a SurfaceHolder or a SurfaceTexture. |
227 private void createSurfaceInternal(Object nativeWindow) { | 148 private void createSurfaceInternal(Object nativeWindow) { |
228 if (!(nativeWindow instanceof SurfaceHolder) && !(nativeWindow instanceof Su
rfaceTexture)) { | 149 if (!(nativeWindow instanceof SurfaceHolder) && !(nativeWindow instanceof Su
rfaceTexture)) { |
229 throw new IllegalStateException("Input must be either a SurfaceHolder or S
urfaceTexture"); | 150 throw new IllegalStateException("Input must be either a SurfaceHolder or S
urfaceTexture"); |
230 } | 151 } |
231 checkIsNotReleased(); | 152 checkIsNotReleased(); |
232 if (eglSurface != EGL10.EGL_NO_SURFACE) { | 153 if (eglSurface != EGL10.EGL_NO_SURFACE) { |
233 throw new RuntimeException("Already has an EGLSurface"); | 154 throw new RuntimeException("Already has an EGLSurface"); |
234 } | 155 } |
235 int[] surfaceAttribs = {EGL10.EGL_NONE}; | 156 int[] surfaceAttribs = {EGL10.EGL_NONE}; |
236 eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig, nativeWindow,
surfaceAttribs); | 157 eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig, nativeWindow,
surfaceAttribs); |
237 if (eglSurface == EGL10.EGL_NO_SURFACE) { | 158 if (eglSurface == EGL10.EGL_NO_SURFACE) { |
238 throw new RuntimeException("Failed to create window surface"); | 159 throw new RuntimeException("Failed to create window surface"); |
239 } | 160 } |
240 } | 161 } |
241 | 162 |
242 // Create dummy 1x1 pixel buffer surface so the context can be made current. | 163 // Create dummy 1x1 pixel buffer surface so the context can be made current. |
| 164 @Override |
243 public void createDummyPbufferSurface() { | 165 public void createDummyPbufferSurface() { |
244 createPbufferSurface(1, 1); | 166 createPbufferSurface(1, 1); |
245 } | 167 } |
246 | 168 |
| 169 @Override |
247 public void createPbufferSurface(int width, int height) { | 170 public void createPbufferSurface(int width, int height) { |
248 checkIsNotReleased(); | 171 checkIsNotReleased(); |
249 if (eglSurface != EGL10.EGL_NO_SURFACE) { | 172 if (eglSurface != EGL10.EGL_NO_SURFACE) { |
250 throw new RuntimeException("Already has an EGLSurface"); | 173 throw new RuntimeException("Already has an EGLSurface"); |
251 } | 174 } |
252 int[] surfaceAttribs = {EGL10.EGL_WIDTH, width, EGL10.EGL_HEIGHT, height, EG
L10.EGL_NONE}; | 175 int[] surfaceAttribs = {EGL10.EGL_WIDTH, width, EGL10.EGL_HEIGHT, height, EG
L10.EGL_NONE}; |
253 eglSurface = egl.eglCreatePbufferSurface(eglDisplay, eglConfig, surfaceAttri
bs); | 176 eglSurface = egl.eglCreatePbufferSurface(eglDisplay, eglConfig, surfaceAttri
bs); |
254 if (eglSurface == EGL10.EGL_NO_SURFACE) { | 177 if (eglSurface == EGL10.EGL_NO_SURFACE) { |
255 throw new RuntimeException("Failed to create pixel buffer surface"); | 178 throw new RuntimeException("Failed to create pixel buffer surface"); |
256 } | 179 } |
257 } | 180 } |
258 | 181 |
259 public Context getEglBaseContext() { | 182 @Override |
260 return new Context(eglContext); | 183 public org.webrtc.EglBase.Context getEglBaseContext() { |
| 184 return new EglBase10.Context(eglContext); |
261 } | 185 } |
262 | 186 |
| 187 @Override |
263 public boolean hasSurface() { | 188 public boolean hasSurface() { |
264 return eglSurface != EGL10.EGL_NO_SURFACE; | 189 return eglSurface != EGL10.EGL_NO_SURFACE; |
265 } | 190 } |
266 | 191 |
| 192 @Override |
267 public int surfaceWidth() { | 193 public int surfaceWidth() { |
268 final int widthArray[] = new int[1]; | 194 final int widthArray[] = new int[1]; |
269 egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_WIDTH, widthArray); | 195 egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_WIDTH, widthArray); |
270 return widthArray[0]; | 196 return widthArray[0]; |
271 } | 197 } |
272 | 198 |
| 199 @Override |
273 public int surfaceHeight() { | 200 public int surfaceHeight() { |
274 final int heightArray[] = new int[1]; | 201 final int heightArray[] = new int[1]; |
275 egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_HEIGHT, heightArray); | 202 egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_HEIGHT, heightArray); |
276 return heightArray[0]; | 203 return heightArray[0]; |
277 } | 204 } |
278 | 205 |
| 206 @Override |
279 public void releaseSurface() { | 207 public void releaseSurface() { |
280 if (eglSurface != EGL10.EGL_NO_SURFACE) { | 208 if (eglSurface != EGL10.EGL_NO_SURFACE) { |
281 egl.eglDestroySurface(eglDisplay, eglSurface); | 209 egl.eglDestroySurface(eglDisplay, eglSurface); |
282 eglSurface = EGL10.EGL_NO_SURFACE; | 210 eglSurface = EGL10.EGL_NO_SURFACE; |
283 } | 211 } |
284 } | 212 } |
285 | 213 |
286 private void checkIsNotReleased() { | 214 private void checkIsNotReleased() { |
287 if (eglDisplay == EGL10.EGL_NO_DISPLAY || eglContext == EGL10.EGL_NO_CONTEXT | 215 if (eglDisplay == EGL10.EGL_NO_DISPLAY || eglContext == EGL10.EGL_NO_CONTEXT |
288 || eglConfig == null) { | 216 || eglConfig == null) { |
289 throw new RuntimeException("This object has been released"); | 217 throw new RuntimeException("This object has been released"); |
290 } | 218 } |
291 } | 219 } |
292 | 220 |
| 221 @Override |
293 public void release() { | 222 public void release() { |
294 checkIsNotReleased(); | 223 checkIsNotReleased(); |
295 releaseSurface(); | 224 releaseSurface(); |
296 detachCurrent(); | 225 detachCurrent(); |
297 egl.eglDestroyContext(eglDisplay, eglContext); | 226 egl.eglDestroyContext(eglDisplay, eglContext); |
298 egl.eglTerminate(eglDisplay); | 227 egl.eglTerminate(eglDisplay); |
299 eglContext = EGL10.EGL_NO_CONTEXT; | 228 eglContext = EGL10.EGL_NO_CONTEXT; |
300 eglDisplay = EGL10.EGL_NO_DISPLAY; | 229 eglDisplay = EGL10.EGL_NO_DISPLAY; |
301 eglConfig = null; | 230 eglConfig = null; |
302 } | 231 } |
303 | 232 |
| 233 @Override |
304 public void makeCurrent() { | 234 public void makeCurrent() { |
305 checkIsNotReleased(); | 235 checkIsNotReleased(); |
306 if (eglSurface == EGL10.EGL_NO_SURFACE) { | 236 if (eglSurface == EGL10.EGL_NO_SURFACE) { |
307 throw new RuntimeException("No EGLSurface - can't make current"); | 237 throw new RuntimeException("No EGLSurface - can't make current"); |
308 } | 238 } |
309 if (!egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) { | 239 if (!egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) { |
310 throw new RuntimeException("eglMakeCurrent failed"); | 240 throw new RuntimeException("eglMakeCurrent failed"); |
311 } | 241 } |
312 } | 242 } |
313 | 243 |
314 // Detach the current EGL context, so that it can be made current on another t
hread. | 244 // Detach the current EGL context, so that it can be made current on another t
hread. |
| 245 @Override |
315 public void detachCurrent() { | 246 public void detachCurrent() { |
316 if (!egl.eglMakeCurrent( | 247 if (!egl.eglMakeCurrent( |
317 eglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CON
TEXT)) { | 248 eglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CON
TEXT)) { |
318 throw new RuntimeException("eglMakeCurrent failed"); | 249 throw new RuntimeException("eglMakeCurrent failed"); |
319 } | 250 } |
320 } | 251 } |
321 | 252 |
| 253 @Override |
322 public void swapBuffers() { | 254 public void swapBuffers() { |
323 checkIsNotReleased(); | 255 checkIsNotReleased(); |
324 if (eglSurface == EGL10.EGL_NO_SURFACE) { | 256 if (eglSurface == EGL10.EGL_NO_SURFACE) { |
325 throw new RuntimeException("No EGLSurface - can't swap buffers"); | 257 throw new RuntimeException("No EGLSurface - can't swap buffers"); |
326 } | 258 } |
327 egl.eglSwapBuffers(eglDisplay, eglSurface); | 259 egl.eglSwapBuffers(eglDisplay, eglSurface); |
328 } | 260 } |
329 | 261 |
330 // Return an EGLDisplay, or die trying. | 262 // Return an EGLDisplay, or die trying. |
331 private EGLDisplay getEglDisplay() { | 263 private EGLDisplay getEglDisplay() { |
(...skipping 26 matching lines...) Expand all Loading... |
358 EGLContext rootContext = | 290 EGLContext rootContext = |
359 sharedContext == null ? EGL10.EGL_NO_CONTEXT : sharedContext.eglContext; | 291 sharedContext == null ? EGL10.EGL_NO_CONTEXT : sharedContext.eglContext; |
360 EGLContext eglContext = | 292 EGLContext eglContext = |
361 egl.eglCreateContext(eglDisplay, eglConfig, rootContext, contextAttribut
es); | 293 egl.eglCreateContext(eglDisplay, eglConfig, rootContext, contextAttribut
es); |
362 if (eglContext == EGL10.EGL_NO_CONTEXT) { | 294 if (eglContext == EGL10.EGL_NO_CONTEXT) { |
363 throw new RuntimeException("Failed to create EGL context"); | 295 throw new RuntimeException("Failed to create EGL context"); |
364 } | 296 } |
365 return eglContext; | 297 return eglContext; |
366 } | 298 } |
367 } | 299 } |
OLD | NEW |