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 10 matching lines...) Expand all Loading... | |
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.SurfaceTexture; | 30 import android.graphics.SurfaceTexture; |
31 import android.opengl.EGL14; | |
32 import android.opengl.EGLConfig; | |
33 import android.opengl.EGLContext; | |
34 import android.opengl.EGLDisplay; | |
35 import android.opengl.EGLSurface; | |
36 import android.view.Surface; | 31 import android.view.Surface; |
37 | 32 |
38 import org.webrtc.Logging; | 33 import org.webrtc.Logging; |
39 | 34 |
35 import javax.microedition.khronos.egl.EGL10; | |
36 import javax.microedition.khronos.egl.EGLConfig; | |
37 import javax.microedition.khronos.egl.EGLContext; | |
38 import javax.microedition.khronos.egl.EGLDisplay; | |
39 import javax.microedition.khronos.egl.EGLSurface; | |
40 | |
40 /** | 41 /** |
41 * Holds EGL state and utility methods for handling an EGLContext, an EGLDisplay , and an EGLSurface. | 42 * Holds EGL state and utility methods for handling an EGLContext, an EGLDisplay , and an EGLSurface. |
42 */ | 43 */ |
43 public final class EglBase { | 44 public final class EglBase { |
44 private static final String TAG = "EglBase"; | 45 private static final String TAG = "EglBase"; |
45 private static final int EGL14_SDK_VERSION = android.os.Build.VERSION_CODES.JE LLY_BEAN_MR1; | 46 private static final int EGL_OPENGL_ES2_BIT = 4; |
perkj_webrtc
2015/10/21 15:26:57
Document what this is and and why it is hardcoded
magjed_webrtc
2015/10/21 21:54:35
Done.
| |
46 private static final int CURRENT_SDK_VERSION = android.os.Build.VERSION.SDK_IN T; | 47 private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; |
perkj_webrtc
2015/10/21 15:26:57
Dito
magjed_webrtc
2015/10/21 21:54:35
Done.
| |
47 // Android-specific extension. | 48 // Android-specific extension. |
48 private static final int EGL_RECORDABLE_ANDROID = 0x3142; | 49 private static final int EGL_RECORDABLE_ANDROID = 0x3142; |
49 | 50 |
51 private final EGL10 egl; | |
50 private EGLContext eglContext; | 52 private EGLContext eglContext; |
51 private ConfigType configType; | 53 private ConfigType configType; |
52 private EGLConfig eglConfig; | 54 private EGLConfig eglConfig; |
53 private EGLDisplay eglDisplay; | 55 private EGLDisplay eglDisplay; |
54 private EGLSurface eglSurface = EGL14.EGL_NO_SURFACE; | 56 private EGLSurface eglSurface = EGL10.EGL_NO_SURFACE; |
55 | |
56 public static boolean isEGL14Supported() { | |
57 Logging.d(TAG, "SDK version: " + CURRENT_SDK_VERSION); | |
58 return (CURRENT_SDK_VERSION >= EGL14_SDK_VERSION); | |
59 } | |
60 | 57 |
61 // EGLConfig constructor type. Influences eglChooseConfig arguments. | 58 // EGLConfig constructor type. Influences eglChooseConfig arguments. |
62 public static enum ConfigType { | 59 public static enum ConfigType { |
63 // No special parameters. | 60 // No special parameters. |
64 PLAIN, | 61 PLAIN, |
65 // Configures with EGL_SURFACE_TYPE = EGL_PBUFFER_BIT. | 62 // Configures with EGL_SURFACE_TYPE = EGL_PBUFFER_BIT. |
66 PIXEL_BUFFER, | 63 PIXEL_BUFFER, |
67 // Configures with EGL_RECORDABLE_ANDROID = 1. | 64 // Configures with EGL_RECORDABLE_ANDROID = 1. |
68 // Discourages EGL from using pixel formats that cannot efficiently be | 65 // Discourages EGL from using pixel formats that cannot efficiently be |
69 // converted to something usable by the video encoder. | 66 // converted to something usable by the video encoder. |
70 RECORDABLE | 67 RECORDABLE |
71 } | 68 } |
72 | 69 |
73 // Create root context without any EGLSurface or parent EGLContext. This can b e used for branching | 70 // Create root context without any EGLSurface or parent EGLContext. This can b e used for branching |
74 // new contexts that share data. | 71 // new contexts that share data. |
75 public EglBase() { | 72 public EglBase() { |
76 this(EGL14.EGL_NO_CONTEXT, ConfigType.PLAIN); | 73 this(EGL10.EGL_NO_CONTEXT, ConfigType.PLAIN); |
77 } | 74 } |
78 | 75 |
79 // Create a new context with the specified config type, sharing data with shar edContext. | 76 // Create a new context with the specified config type, sharing data with shar edContext. |
80 public EglBase(EGLContext sharedContext, ConfigType configType) { | 77 public EglBase(EGLContext sharedContext, ConfigType configType) { |
78 this.egl = (EGL10) EGLContext.getEGL(); | |
81 this.configType = configType; | 79 this.configType = configType; |
82 eglDisplay = getEglDisplay(); | 80 eglDisplay = getEglDisplay(); |
83 eglConfig = getEglConfig(eglDisplay, configType); | 81 eglConfig = getEglConfig(eglDisplay, configType); |
84 eglContext = createEglContext(sharedContext, eglDisplay, eglConfig); | 82 eglContext = createEglContext(sharedContext, eglDisplay, eglConfig); |
85 } | 83 } |
86 | 84 |
87 // Create EGLSurface from the Android Surface. | 85 // Create EGLSurface from the Android Surface. |
88 public void createSurface(Surface surface) { | 86 public void createSurface(Surface surface) { |
89 createSurfaceInternal(surface); | 87 createSurfaceInternal(surface); |
90 } | 88 } |
91 | 89 |
92 // Create EGLSurface from the Android SurfaceTexture. | 90 // Create EGLSurface from the Android SurfaceTexture. |
93 public void createSurface(SurfaceTexture surfaceTexture) { | 91 public void createSurface(SurfaceTexture surfaceTexture) { |
94 createSurfaceInternal(surfaceTexture); | 92 createSurfaceInternal(surfaceTexture); |
95 } | 93 } |
96 | 94 |
97 // Create EGLSurface from either Surface or SurfaceTexture. | 95 // Create EGLSurface from either Surface or SurfaceTexture. |
98 private void createSurfaceInternal(Object surface) { | 96 private void createSurfaceInternal(Object surface) { |
99 if (!(surface instanceof Surface) && !(surface instanceof SurfaceTexture)) { | 97 if (!(surface instanceof Surface) && !(surface instanceof SurfaceTexture)) { |
100 throw new IllegalStateException("Input must be either a Surface or Surface Texture"); | 98 throw new IllegalStateException("Input must be either a Surface or Surface Texture"); |
101 } | 99 } |
102 checkIsNotReleased(); | 100 checkIsNotReleased(); |
103 if (configType == ConfigType.PIXEL_BUFFER) { | 101 if (configType == ConfigType.PIXEL_BUFFER) { |
104 Logging.w(TAG, "This EGL context is configured for PIXEL_BUFFER, but uses regular Surface"); | 102 Logging.w(TAG, "This EGL context is configured for PIXEL_BUFFER, but uses regular Surface"); |
105 } | 103 } |
106 if (eglSurface != EGL14.EGL_NO_SURFACE) { | 104 if (eglSurface != EGL10.EGL_NO_SURFACE) { |
107 throw new RuntimeException("Already has an EGLSurface"); | 105 throw new RuntimeException("Already has an EGLSurface"); |
108 } | 106 } |
109 int[] surfaceAttribs = {EGL14.EGL_NONE}; | 107 int[] surfaceAttribs = {EGL10.EGL_NONE}; |
110 eglSurface = EGL14.eglCreateWindowSurface(eglDisplay, eglConfig, surface, su rfaceAttribs, 0); | 108 eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig, surface, surf aceAttribs); |
111 if (eglSurface == EGL14.EGL_NO_SURFACE) { | 109 if (eglSurface == EGL10.EGL_NO_SURFACE) { |
112 throw new RuntimeException("Failed to create window surface"); | 110 throw new RuntimeException("Failed to create window surface"); |
113 } | 111 } |
114 } | 112 } |
115 | 113 |
116 // Create dummy 1x1 pixel buffer surface so the context can be made current. | 114 // Create dummy 1x1 pixel buffer surface so the context can be made current. |
117 public void createDummyPbufferSurface() { | 115 public void createDummyPbufferSurface() { |
118 createPbufferSurface(1, 1); | 116 createPbufferSurface(1, 1); |
119 } | 117 } |
120 | 118 |
121 public void createPbufferSurface(int width, int height) { | 119 public void createPbufferSurface(int width, int height) { |
122 checkIsNotReleased(); | 120 checkIsNotReleased(); |
123 if (configType != ConfigType.PIXEL_BUFFER) { | 121 if (configType != ConfigType.PIXEL_BUFFER) { |
124 throw new RuntimeException( | 122 throw new RuntimeException( |
125 "This EGL context is not configured to use a pixel buffer: " + configT ype); | 123 "This EGL context is not configured to use a pixel buffer: " + configT ype); |
126 } | 124 } |
127 if (eglSurface != EGL14.EGL_NO_SURFACE) { | 125 if (eglSurface != EGL10.EGL_NO_SURFACE) { |
128 throw new RuntimeException("Already has an EGLSurface"); | 126 throw new RuntimeException("Already has an EGLSurface"); |
129 } | 127 } |
130 int[] surfaceAttribs = {EGL14.EGL_WIDTH, width, EGL14.EGL_HEIGHT, height, EG L14.EGL_NONE}; | 128 int[] surfaceAttribs = {EGL10.EGL_WIDTH, width, EGL10.EGL_HEIGHT, height, EG L10.EGL_NONE}; |
131 eglSurface = EGL14.eglCreatePbufferSurface(eglDisplay, eglConfig, surfaceAtt ribs, 0); | 129 eglSurface = egl.eglCreatePbufferSurface(eglDisplay, eglConfig, surfaceAttri bs); |
132 if (eglSurface == EGL14.EGL_NO_SURFACE) { | 130 if (eglSurface == EGL10.EGL_NO_SURFACE) { |
133 throw new RuntimeException("Failed to create pixel buffer surface"); | 131 throw new RuntimeException("Failed to create pixel buffer surface"); |
134 } | 132 } |
135 } | 133 } |
136 | 134 |
137 public EGLContext getContext() { | 135 public EGLContext getContext() { |
138 return eglContext; | 136 return eglContext; |
139 } | 137 } |
140 | 138 |
141 public boolean hasSurface() { | 139 public boolean hasSurface() { |
142 return eglSurface != EGL14.EGL_NO_SURFACE; | 140 return eglSurface != EGL10.EGL_NO_SURFACE; |
143 } | 141 } |
144 | 142 |
145 public int surfaceWidth() { | 143 public int surfaceWidth() { |
146 final int widthArray[] = new int[1]; | 144 final int widthArray[] = new int[1]; |
147 EGL14.eglQuerySurface(eglDisplay, eglSurface, EGL14.EGL_WIDTH, widthArray, 0 ); | 145 egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_WIDTH, widthArray); |
148 return widthArray[0]; | 146 return widthArray[0]; |
149 } | 147 } |
150 | 148 |
151 public int surfaceHeight() { | 149 public int surfaceHeight() { |
152 final int heightArray[] = new int[1]; | 150 final int heightArray[] = new int[1]; |
153 EGL14.eglQuerySurface(eglDisplay, eglSurface, EGL14.EGL_HEIGHT, heightArray, 0); | 151 egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_HEIGHT, heightArray); |
154 return heightArray[0]; | 152 return heightArray[0]; |
155 } | 153 } |
156 | 154 |
157 public void releaseSurface() { | 155 public void releaseSurface() { |
158 if (eglSurface != EGL14.EGL_NO_SURFACE) { | 156 if (eglSurface != EGL10.EGL_NO_SURFACE) { |
159 EGL14.eglDestroySurface(eglDisplay, eglSurface); | 157 egl.eglDestroySurface(eglDisplay, eglSurface); |
160 eglSurface = EGL14.EGL_NO_SURFACE; | 158 eglSurface = EGL10.EGL_NO_SURFACE; |
161 } | 159 } |
162 } | 160 } |
163 | 161 |
164 private void checkIsNotReleased() { | 162 private void checkIsNotReleased() { |
165 if (eglDisplay == EGL14.EGL_NO_DISPLAY || eglContext == EGL14.EGL_NO_CONTEXT | 163 if (eglDisplay == EGL10.EGL_NO_DISPLAY || eglContext == EGL10.EGL_NO_CONTEXT |
166 || eglConfig == null) { | 164 || eglConfig == null) { |
167 throw new RuntimeException("This object has been released"); | 165 throw new RuntimeException("This object has been released"); |
168 } | 166 } |
169 } | 167 } |
170 | 168 |
171 public void release() { | 169 public void release() { |
172 checkIsNotReleased(); | 170 checkIsNotReleased(); |
173 releaseSurface(); | 171 releaseSurface(); |
174 detachCurrent(); | 172 detachCurrent(); |
175 EGL14.eglDestroyContext(eglDisplay, eglContext); | 173 egl.eglDestroyContext(eglDisplay, eglContext); |
176 EGL14.eglReleaseThread(); | 174 egl.eglTerminate(eglDisplay); |
177 EGL14.eglTerminate(eglDisplay); | 175 eglContext = EGL10.EGL_NO_CONTEXT; |
178 eglContext = EGL14.EGL_NO_CONTEXT; | 176 eglDisplay = EGL10.EGL_NO_DISPLAY; |
179 eglDisplay = EGL14.EGL_NO_DISPLAY; | |
180 eglConfig = null; | 177 eglConfig = null; |
181 } | 178 } |
182 | 179 |
183 public void makeCurrent() { | 180 public void makeCurrent() { |
184 checkIsNotReleased(); | 181 checkIsNotReleased(); |
185 if (eglSurface == EGL14.EGL_NO_SURFACE) { | 182 if (eglSurface == EGL10.EGL_NO_SURFACE) { |
186 throw new RuntimeException("No EGLSurface - can't make current"); | 183 throw new RuntimeException("No EGLSurface - can't make current"); |
187 } | 184 } |
188 if (!EGL14.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) { | 185 if (!egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) { |
189 throw new RuntimeException("eglMakeCurrent failed"); | 186 throw new RuntimeException("eglMakeCurrent failed"); |
190 } | 187 } |
191 } | 188 } |
192 | 189 |
193 // Detach the current EGL context, so that it can be made current on another t hread. | 190 // Detach the current EGL context, so that it can be made current on another t hread. |
194 public void detachCurrent() { | 191 public void detachCurrent() { |
195 if (!EGL14.eglMakeCurrent( | 192 if (!egl.eglMakeCurrent( |
196 eglDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CON TEXT)) { | 193 eglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CON TEXT)) { |
197 throw new RuntimeException("eglMakeCurrent failed"); | 194 throw new RuntimeException("eglMakeCurrent failed"); |
198 } | 195 } |
199 } | 196 } |
200 | 197 |
201 public void swapBuffers() { | 198 public void swapBuffers() { |
202 checkIsNotReleased(); | 199 checkIsNotReleased(); |
203 if (eglSurface == EGL14.EGL_NO_SURFACE) { | 200 if (eglSurface == EGL10.EGL_NO_SURFACE) { |
204 throw new RuntimeException("No EGLSurface - can't swap buffers"); | 201 throw new RuntimeException("No EGLSurface - can't swap buffers"); |
205 } | 202 } |
206 EGL14.eglSwapBuffers(eglDisplay, eglSurface); | 203 egl.eglSwapBuffers(eglDisplay, eglSurface); |
207 } | 204 } |
208 | 205 |
209 // Return an EGLDisplay, or die trying. | 206 // Return an EGLDisplay, or die trying. |
210 private static EGLDisplay getEglDisplay() { | 207 private EGLDisplay getEglDisplay() { |
211 EGLDisplay eglDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY); | 208 EGLDisplay eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); |
212 if (eglDisplay == EGL14.EGL_NO_DISPLAY) { | 209 if (eglDisplay == EGL10.EGL_NO_DISPLAY) { |
213 throw new RuntimeException("Unable to get EGL14 display"); | 210 throw new RuntimeException("Unable to get EGL10 display"); |
214 } | 211 } |
215 int[] version = new int[2]; | 212 int[] version = new int[2]; |
216 if (!EGL14.eglInitialize(eglDisplay, version, 0, version, 1)) { | 213 if (!egl.eglInitialize(eglDisplay, version)) { |
217 throw new RuntimeException("Unable to initialize EGL14"); | 214 throw new RuntimeException("Unable to initialize EGL10"); |
218 } | 215 } |
219 return eglDisplay; | 216 return eglDisplay; |
220 } | 217 } |
221 | 218 |
222 // Return an EGLConfig, or die trying. | 219 // Return an EGLConfig, or die trying. |
223 private static EGLConfig getEglConfig(EGLDisplay eglDisplay, ConfigType config Type) { | 220 private EGLConfig getEglConfig(EGLDisplay eglDisplay, ConfigType configType) { |
224 // Always RGB888, GLES2. | 221 // Always RGB888, GLES2. |
225 int[] configAttributes = { | 222 int[] configAttributes = { |
226 EGL14.EGL_RED_SIZE, 8, | 223 EGL10.EGL_RED_SIZE, 8, |
227 EGL14.EGL_GREEN_SIZE, 8, | 224 EGL10.EGL_GREEN_SIZE, 8, |
228 EGL14.EGL_BLUE_SIZE, 8, | 225 EGL10.EGL_BLUE_SIZE, 8, |
229 EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT, | 226 EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, |
230 EGL14.EGL_NONE, 0, // Allocate dummy fields for specific options. | 227 EGL10.EGL_NONE, 0, // Allocate dummy fields for specific options. |
231 EGL14.EGL_NONE | 228 EGL10.EGL_NONE |
232 }; | 229 }; |
233 | 230 |
234 // Fill in dummy fields based on configType. | 231 // Fill in dummy fields based on configType. |
235 switch (configType) { | 232 switch (configType) { |
236 case PLAIN: | 233 case PLAIN: |
237 break; | 234 break; |
238 case PIXEL_BUFFER: | 235 case PIXEL_BUFFER: |
239 configAttributes[configAttributes.length - 3] = EGL14.EGL_SURFACE_TYPE; | 236 configAttributes[configAttributes.length - 3] = EGL10.EGL_SURFACE_TYPE; |
240 configAttributes[configAttributes.length - 2] = EGL14.EGL_PBUFFER_BIT; | 237 configAttributes[configAttributes.length - 2] = EGL10.EGL_PBUFFER_BIT; |
241 break; | 238 break; |
242 case RECORDABLE: | 239 case RECORDABLE: |
243 configAttributes[configAttributes.length - 3] = EGL_RECORDABLE_ANDROID; | 240 configAttributes[configAttributes.length - 3] = EGL_RECORDABLE_ANDROID; |
244 configAttributes[configAttributes.length - 2] = 1; | 241 configAttributes[configAttributes.length - 2] = 1; |
245 break; | 242 break; |
246 default: | 243 default: |
247 throw new IllegalArgumentException(); | 244 throw new IllegalArgumentException(); |
248 } | 245 } |
249 | 246 |
250 EGLConfig[] configs = new EGLConfig[1]; | 247 EGLConfig[] configs = new EGLConfig[1]; |
251 int[] numConfigs = new int[1]; | 248 int[] numConfigs = new int[1]; |
252 if (!EGL14.eglChooseConfig( | 249 if (!egl.eglChooseConfig( |
253 eglDisplay, configAttributes, 0, configs, 0, configs.length, numConfigs, 0)) { | 250 eglDisplay, configAttributes, configs, configs.length, numConfigs)) { |
254 throw new RuntimeException("Unable to find RGB888 " + configType + " EGL c onfig"); | 251 throw new RuntimeException("Unable to find RGB888 " + configType + " EGL c onfig"); |
255 } | 252 } |
256 return configs[0]; | 253 return configs[0]; |
257 } | 254 } |
258 | 255 |
259 // Return an EGLConfig, or die trying. | 256 // Return an EGLConfig, or die trying. |
260 private static EGLContext createEglContext( | 257 private EGLContext createEglContext( |
261 EGLContext sharedContext, EGLDisplay eglDisplay, EGLConfig eglConfig) { | 258 EGLContext sharedContext, EGLDisplay eglDisplay, EGLConfig eglConfig) { |
262 int[] contextAttributes = {EGL14.EGL_CONTEXT_CLIENT_VERSION, 2, EGL14.EGL_NO NE}; | 259 int[] contextAttributes = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE}; |
263 EGLContext eglContext = | 260 EGLContext eglContext = |
264 EGL14.eglCreateContext(eglDisplay, eglConfig, sharedContext, contextAttr ibutes, 0); | 261 egl.eglCreateContext(eglDisplay, eglConfig, sharedContext, contextAttrib utes); |
265 if (eglContext == EGL14.EGL_NO_CONTEXT) { | 262 if (eglContext == EGL10.EGL_NO_CONTEXT) { |
266 throw new RuntimeException("Failed to create EGL context"); | 263 throw new RuntimeException("Failed to create EGL context"); |
267 } | 264 } |
268 return eglContext; | 265 return eglContext; |
269 } | 266 } |
270 } | 267 } |
OLD | NEW |