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, |
11 * this list of conditions and the following disclaimer in the documentation | 11 * this list of conditions and the following disclaimer in the documentation |
12 * and/or other materials provided with the distribution. | 12 * and/or other materials provided with the distribution. |
13 * 3. The name of the author may not be used to endorse or promote products | 13 * 3. The name of the author may not be used to endorse or promote products |
14 * derived from this software without specific prior written permission. | 14 * derived from this software without specific prior written permission. |
15 * | 15 * |
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED | 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 */ | 26 */ |
27 | 27 |
28 package org.webrtc; | 28 package org.webrtc; |
29 | 29 |
30 import android.graphics.Canvas; | |
31 import android.graphics.SurfaceTexture; | 30 import android.graphics.SurfaceTexture; |
32 import android.graphics.Rect; | |
33 import android.view.Surface; | 31 import android.view.Surface; |
34 import android.view.SurfaceHolder; | |
35 | |
36 import org.webrtc.Logging; | |
37 import org.webrtc.EglBase.Context; | |
38 | 32 |
39 import javax.microedition.khronos.egl.EGL10; | 33 import javax.microedition.khronos.egl.EGL10; |
40 import javax.microedition.khronos.egl.EGLConfig; | 34 |
41 import javax.microedition.khronos.egl.EGLContext; | |
42 import javax.microedition.khronos.egl.EGLDisplay; | |
43 import javax.microedition.khronos.egl.EGLSurface; | |
44 | 35 |
45 /** | 36 /** |
46 * Holds EGL state and utility methods for handling an egl 1.0 EGLContext, an EG
LDisplay, | 37 * Holds EGL state and utility methods for handling an egl 1.0 EGLContext, an EG
LDisplay, |
47 * and an EGLSurface. | 38 * and an EGLSurface. |
48 */ | 39 */ |
49 public class EglBase { | 40 public abstract class EglBase { |
50 private static final String TAG = "EglBase"; | 41 // EGL wrapper for an actual EGLContext. |
| 42 public static class Context { |
| 43 } |
| 44 |
51 // These constants are taken from EGL14.EGL_OPENGL_ES2_BIT and EGL14.EGL_CONTE
XT_CLIENT_VERSION. | 45 // 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 | 46 // https://android.googlesource.com/platform/frameworks/base/+/master/opengl/j
ava/android/opengl/EGL14.java |
53 // This is similar to how GlSurfaceView does: | 47 // 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 | 48 // 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; | 49 private static final int EGL_OPENGL_ES2_BIT = 4; |
56 private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; | |
57 // Android-specific extension. | 50 // Android-specific extension. |
58 private static final int EGL_RECORDABLE_ANDROID = 0x3142; | 51 private static final int EGL_RECORDABLE_ANDROID = 0x3142; |
59 | 52 |
60 private final EGL10 egl; | |
61 private EGLContext eglContext; | |
62 private EGLConfig eglConfig; | |
63 private EGLDisplay eglDisplay; | |
64 private EGLSurface eglSurface = EGL10.EGL_NO_SURFACE; | |
65 | |
66 // EGL wrapper for an actual EGLContext. | |
67 public static class Context { | |
68 private final EGLContext eglContext; | |
69 | |
70 public Context(EGLContext eglContext) { | |
71 this.eglContext = eglContext; | |
72 } | |
73 } | |
74 | |
75 public static final int[] CONFIG_PLAIN = { | 53 public static final int[] CONFIG_PLAIN = { |
76 EGL10.EGL_RED_SIZE, 8, | 54 EGL10.EGL_RED_SIZE, 8, |
77 EGL10.EGL_GREEN_SIZE, 8, | 55 EGL10.EGL_GREEN_SIZE, 8, |
78 EGL10.EGL_BLUE_SIZE, 8, | 56 EGL10.EGL_BLUE_SIZE, 8, |
79 EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, | 57 EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, |
80 EGL10.EGL_NONE | 58 EGL10.EGL_NONE |
81 }; | 59 }; |
82 public static final int[] CONFIG_PIXEL_BUFFER = { | 60 public static final int[] CONFIG_PIXEL_BUFFER = { |
83 EGL10.EGL_RED_SIZE, 8, | 61 EGL10.EGL_RED_SIZE, 8, |
84 EGL10.EGL_GREEN_SIZE, 8, | 62 EGL10.EGL_GREEN_SIZE, 8, |
(...skipping 19 matching lines...) Expand all Loading... |
104 EGL_RECORDABLE_ANDROID, 1, | 82 EGL_RECORDABLE_ANDROID, 1, |
105 EGL10.EGL_NONE | 83 EGL10.EGL_NONE |
106 }; | 84 }; |
107 | 85 |
108 // Create a new context with the specified config attributes, sharing data wit
h sharedContext. | 86 // Create a new context with the specified config attributes, sharing data wit
h sharedContext. |
109 // |sharedContext| can be null. | 87 // |sharedContext| can be null. |
110 public static EglBase create(Context sharedContext, int[] configAttributes) { | 88 public static EglBase create(Context sharedContext, int[] configAttributes) { |
111 return (EglBase14.isEGL14Supported() | 89 return (EglBase14.isEGL14Supported() |
112 && (sharedContext == null || sharedContext instanceof EglBase14.Context)
) | 90 && (sharedContext == null || sharedContext instanceof EglBase14.Context)
) |
113 ? new EglBase14((EglBase14.Context) sharedContext, configAttributes) | 91 ? new EglBase14((EglBase14.Context) sharedContext, configAttributes) |
114 : new EglBase(sharedContext, configAttributes); | 92 : new EglBase10((EglBase10.Context) sharedContext, configAttributes)
; |
115 } | 93 } |
116 | 94 |
117 public static EglBase create() { | 95 public static EglBase create() { |
118 return create(null, CONFIG_PLAIN); | 96 return create(null, CONFIG_PLAIN); |
119 } | 97 } |
120 | 98 |
121 //Create root context without any EGLSurface or parent EGLContext. This can be
used for branching | 99 public abstract void createSurface(Surface surface); |
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. | |
140 EglBase(Context sharedContext, int[] configAttributes) { | |
141 this.egl = (EGL10) EGLContext.getEGL(); | |
142 eglDisplay = getEglDisplay(); | |
143 eglConfig = getEglConfig(eglDisplay, configAttributes); | |
144 eglContext = createEglContext(sharedContext, eglDisplay, eglConfig); | |
145 } | |
146 | |
147 // TODO(perkj): This is a hacky ctor used to allow us to create an EGLBase14.
Remove this and | |
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) { | |
155 /** | |
156 * 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 | |
158 * SurfaceHolder.getSurface(), so we'll do that. No other methods are releva
nt. | |
159 */ | |
160 class FakeSurfaceHolder implements SurfaceHolder { | |
161 private final Surface surface; | |
162 | |
163 FakeSurfaceHolder(Surface surface) { | |
164 this.surface = surface; | |
165 } | |
166 | |
167 @Override | |
168 public void addCallback(Callback callback) {} | |
169 | |
170 @Override | |
171 public void removeCallback(Callback callback) {} | |
172 | |
173 @Override | |
174 public boolean isCreating() { | |
175 return false; | |
176 } | |
177 | |
178 @Deprecated | |
179 @Override | |
180 public void setType(int i) {} | |
181 | |
182 @Override | |
183 public void setFixedSize(int i, int i2) {} | |
184 | |
185 @Override | |
186 public void setSizeFromLayout() {} | |
187 | |
188 @Override | |
189 public void setFormat(int i) {} | |
190 | |
191 @Override | |
192 public void setKeepScreenOn(boolean b) {} | |
193 | |
194 @Override | |
195 public Canvas lockCanvas() { | |
196 return null; | |
197 } | |
198 | |
199 @Override | |
200 public Canvas lockCanvas(Rect rect) { | |
201 return null; | |
202 } | |
203 | |
204 @Override | |
205 public void unlockCanvasAndPost(Canvas canvas) {} | |
206 | |
207 @Override | |
208 public Rect getSurfaceFrame() { | |
209 return null; | |
210 } | |
211 | |
212 @Override | |
213 public Surface getSurface() { | |
214 return surface; | |
215 } | |
216 } | |
217 | |
218 createSurfaceInternal(new FakeSurfaceHolder(surface)); | |
219 } | |
220 | 100 |
221 // Create EGLSurface from the Android SurfaceTexture. | 101 // Create EGLSurface from the Android SurfaceTexture. |
222 public void createSurface(SurfaceTexture surfaceTexture) { | 102 public abstract void createSurface(SurfaceTexture surfaceTexture); |
223 createSurfaceInternal(surfaceTexture); | |
224 } | |
225 | |
226 // Create EGLSurface from either a SurfaceHolder or a SurfaceTexture. | |
227 private void createSurfaceInternal(Object nativeWindow) { | |
228 if (!(nativeWindow instanceof SurfaceHolder) && !(nativeWindow instanceof Su
rfaceTexture)) { | |
229 throw new IllegalStateException("Input must be either a SurfaceHolder or S
urfaceTexture"); | |
230 } | |
231 checkIsNotReleased(); | |
232 if (eglSurface != EGL10.EGL_NO_SURFACE) { | |
233 throw new RuntimeException("Already has an EGLSurface"); | |
234 } | |
235 int[] surfaceAttribs = {EGL10.EGL_NONE}; | |
236 eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig, nativeWindow,
surfaceAttribs); | |
237 if (eglSurface == EGL10.EGL_NO_SURFACE) { | |
238 throw new RuntimeException("Failed to create window surface"); | |
239 } | |
240 } | |
241 | 103 |
242 // Create dummy 1x1 pixel buffer surface so the context can be made current. | 104 // Create dummy 1x1 pixel buffer surface so the context can be made current. |
243 public void createDummyPbufferSurface() { | 105 public abstract void createDummyPbufferSurface(); |
244 createPbufferSurface(1, 1); | |
245 } | |
246 | 106 |
247 public void createPbufferSurface(int width, int height) { | 107 public abstract void createPbufferSurface(int width, int height); |
248 checkIsNotReleased(); | |
249 if (eglSurface != EGL10.EGL_NO_SURFACE) { | |
250 throw new RuntimeException("Already has an EGLSurface"); | |
251 } | |
252 int[] surfaceAttribs = {EGL10.EGL_WIDTH, width, EGL10.EGL_HEIGHT, height, EG
L10.EGL_NONE}; | |
253 eglSurface = egl.eglCreatePbufferSurface(eglDisplay, eglConfig, surfaceAttri
bs); | |
254 if (eglSurface == EGL10.EGL_NO_SURFACE) { | |
255 throw new RuntimeException("Failed to create pixel buffer surface"); | |
256 } | |
257 } | |
258 | 108 |
259 public Context getEglBaseContext() { | 109 public abstract Context getEglBaseContext(); |
260 return new Context(eglContext); | |
261 } | |
262 | 110 |
263 public boolean hasSurface() { | 111 public abstract boolean hasSurface(); |
264 return eglSurface != EGL10.EGL_NO_SURFACE; | |
265 } | |
266 | 112 |
267 public int surfaceWidth() { | 113 public abstract int surfaceWidth(); |
268 final int widthArray[] = new int[1]; | |
269 egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_WIDTH, widthArray); | |
270 return widthArray[0]; | |
271 } | |
272 | 114 |
273 public int surfaceHeight() { | 115 public abstract int surfaceHeight(); |
274 final int heightArray[] = new int[1]; | |
275 egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_HEIGHT, heightArray); | |
276 return heightArray[0]; | |
277 } | |
278 | 116 |
279 public void releaseSurface() { | 117 public abstract void releaseSurface(); |
280 if (eglSurface != EGL10.EGL_NO_SURFACE) { | |
281 egl.eglDestroySurface(eglDisplay, eglSurface); | |
282 eglSurface = EGL10.EGL_NO_SURFACE; | |
283 } | |
284 } | |
285 | 118 |
286 private void checkIsNotReleased() { | 119 public abstract void release(); |
287 if (eglDisplay == EGL10.EGL_NO_DISPLAY || eglContext == EGL10.EGL_NO_CONTEXT | |
288 || eglConfig == null) { | |
289 throw new RuntimeException("This object has been released"); | |
290 } | |
291 } | |
292 | 120 |
293 public void release() { | 121 public abstract void makeCurrent(); |
294 checkIsNotReleased(); | |
295 releaseSurface(); | |
296 detachCurrent(); | |
297 egl.eglDestroyContext(eglDisplay, eglContext); | |
298 egl.eglTerminate(eglDisplay); | |
299 eglContext = EGL10.EGL_NO_CONTEXT; | |
300 eglDisplay = EGL10.EGL_NO_DISPLAY; | |
301 eglConfig = null; | |
302 } | |
303 | |
304 public void makeCurrent() { | |
305 checkIsNotReleased(); | |
306 if (eglSurface == EGL10.EGL_NO_SURFACE) { | |
307 throw new RuntimeException("No EGLSurface - can't make current"); | |
308 } | |
309 if (!egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) { | |
310 throw new RuntimeException("eglMakeCurrent failed"); | |
311 } | |
312 } | |
313 | 122 |
314 // Detach the current EGL context, so that it can be made current on another t
hread. | 123 // Detach the current EGL context, so that it can be made current on another t
hread. |
315 public void detachCurrent() { | 124 public abstract void detachCurrent(); |
316 if (!egl.eglMakeCurrent( | |
317 eglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CON
TEXT)) { | |
318 throw new RuntimeException("eglMakeCurrent failed"); | |
319 } | |
320 } | |
321 | 125 |
322 public void swapBuffers() { | 126 public abstract void swapBuffers(); |
323 checkIsNotReleased(); | |
324 if (eglSurface == EGL10.EGL_NO_SURFACE) { | |
325 throw new RuntimeException("No EGLSurface - can't swap buffers"); | |
326 } | |
327 egl.eglSwapBuffers(eglDisplay, eglSurface); | |
328 } | |
329 | |
330 // Return an EGLDisplay, or die trying. | |
331 private EGLDisplay getEglDisplay() { | |
332 EGLDisplay eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); | |
333 if (eglDisplay == EGL10.EGL_NO_DISPLAY) { | |
334 throw new RuntimeException("Unable to get EGL10 display"); | |
335 } | |
336 int[] version = new int[2]; | |
337 if (!egl.eglInitialize(eglDisplay, version)) { | |
338 throw new RuntimeException("Unable to initialize EGL10"); | |
339 } | |
340 return eglDisplay; | |
341 } | |
342 | |
343 // Return an EGLConfig, or die trying. | |
344 private EGLConfig getEglConfig(EGLDisplay eglDisplay, int[] configAttributes)
{ | |
345 EGLConfig[] configs = new EGLConfig[1]; | |
346 int[] numConfigs = new int[1]; | |
347 if (!egl.eglChooseConfig( | |
348 eglDisplay, configAttributes, configs, configs.length, numConfigs)) { | |
349 throw new RuntimeException("Unable to find any matching EGL config"); | |
350 } | |
351 return configs[0]; | |
352 } | |
353 | |
354 // Return an EGLConfig, or die trying. | |
355 private EGLContext createEglContext( | |
356 Context sharedContext, EGLDisplay eglDisplay, EGLConfig eglConfig) { | |
357 int[] contextAttributes = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE}; | |
358 EGLContext rootContext = | |
359 sharedContext == null ? EGL10.EGL_NO_CONTEXT : sharedContext.eglContext; | |
360 EGLContext eglContext = | |
361 egl.eglCreateContext(eglDisplay, eglConfig, rootContext, contextAttribut
es); | |
362 if (eglContext == EGL10.EGL_NO_CONTEXT) { | |
363 throw new RuntimeException("Failed to create EGL context"); | |
364 } | |
365 return eglContext; | |
366 } | |
367 } | 127 } |
OLD | NEW |