Commit | Line | Data |
---|---|---|
d42e7319 JB |
1 | /* |
2 | * Copyright (c) 2012 Carsten Munk <carsten.munk@gmail.com> | |
3 | * | |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at | |
7 | * | |
8 | * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
15 | * | |
16 | */ | |
17 | ||
18 | /* EGL function pointers */ | |
19 | #define EGL_EGLEXT_PROTOTYPES | |
20 | #include <EGL/egl.h> | |
21 | #include <EGL/eglext.h> | |
22 | #include <GLES2/gl2.h> | |
23 | #include <GLES2/gl2ext.h> | |
24 | #include <dlfcn.h> | |
25 | #include <stddef.h> | |
26 | #include <stdlib.h> | |
27 | #include <malloc.h> | |
28 | #include "ws.h" | |
29 | #include "helper.h" | |
30 | #include <assert.h> | |
31 | ||
32 | ||
33 | #include <hybris/internal/binding.h> | |
34 | #include <string.h> | |
35 | ||
36 | #include <android/system/window.h> | |
37 | #include "logging.h" | |
38 | ||
39 | static void *_libegl = NULL; | |
40 | static void *_libgles = NULL; | |
41 | ||
42 | static EGLint (*_eglGetError)(void) = NULL; | |
43 | ||
44 | static EGLDisplay (*_eglGetDisplay)(EGLNativeDisplayType display_id) = NULL; | |
45 | static EGLBoolean (*_eglInitialize)(EGLDisplay dpy, EGLint *major, EGLint *minor) = NULL; | |
46 | static EGLBoolean (*_eglTerminate)(EGLDisplay dpy) = NULL; | |
47 | ||
48 | static const char * (*_eglQueryString)(EGLDisplay dpy, EGLint name) = NULL; | |
49 | ||
50 | static EGLBoolean (*_eglGetConfigs)(EGLDisplay dpy, EGLConfig *configs, | |
51 | EGLint config_size, EGLint *num_config) = NULL; | |
52 | static EGLBoolean (*_eglChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list, | |
53 | EGLConfig *configs, EGLint config_size, | |
54 | EGLint *num_config) = NULL; | |
55 | static EGLBoolean (*_eglGetConfigAttrib)(EGLDisplay dpy, EGLConfig config, | |
56 | EGLint attribute, EGLint *value) = NULL; | |
57 | ||
58 | static EGLSurface (*_eglCreateWindowSurface)(EGLDisplay dpy, EGLConfig config, | |
59 | EGLNativeWindowType win, | |
60 | const EGLint *attrib_list) = NULL; | |
61 | static EGLSurface (*_eglCreatePbufferSurface)(EGLDisplay dpy, EGLConfig config, | |
62 | const EGLint *attrib_list) = NULL; | |
63 | static EGLSurface (*_eglCreatePixmapSurface)(EGLDisplay dpy, EGLConfig config, | |
64 | EGLNativePixmapType pixmap, | |
65 | const EGLint *attrib_list) = NULL; | |
66 | static EGLBoolean (*_eglDestroySurface)(EGLDisplay dpy, EGLSurface surface) = NULL; | |
67 | static EGLBoolean (*_eglQuerySurface)(EGLDisplay dpy, EGLSurface surface, | |
68 | EGLint attribute, EGLint *value) = NULL; | |
69 | ||
70 | static EGLBoolean (*_eglBindAPI)(EGLenum api) = NULL; | |
71 | static EGLenum (*_eglQueryAPI)(void) = NULL; | |
72 | ||
73 | static EGLBoolean (*_eglWaitClient)(void) = NULL; | |
74 | ||
75 | static EGLBoolean (*_eglReleaseThread)(void) = NULL; | |
76 | ||
77 | static EGLSurface (*_eglCreatePbufferFromClientBuffer)( | |
78 | EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, | |
79 | EGLConfig config, const EGLint *attrib_list) = NULL; | |
80 | ||
81 | static EGLBoolean (*_eglSurfaceAttrib)(EGLDisplay dpy, EGLSurface surface, | |
82 | EGLint attribute, EGLint value) = NULL; | |
83 | static EGLBoolean (*_eglBindTexImage)(EGLDisplay dpy, EGLSurface surface, EGLint buffer) = NULL; | |
84 | static EGLBoolean (*_eglReleaseTexImage)(EGLDisplay dpy, EGLSurface surface, EGLint buffer) = NULL; | |
85 | ||
86 | ||
87 | static EGLBoolean (*_eglSwapInterval)(EGLDisplay dpy, EGLint interval) = NULL; | |
88 | ||
89 | ||
90 | static EGLContext (*_eglCreateContext)(EGLDisplay dpy, EGLConfig config, | |
91 | EGLContext share_context, | |
92 | const EGLint *attrib_list) = NULL; | |
93 | static EGLBoolean (*_eglDestroyContext)(EGLDisplay dpy, EGLContext ctx) = NULL; | |
94 | static EGLBoolean (*_eglMakeCurrent)(EGLDisplay dpy, EGLSurface draw, | |
95 | EGLSurface read, EGLContext ctx) = NULL; | |
96 | ||
97 | static EGLContext (*_eglGetCurrentContext)(void) = NULL; | |
98 | static EGLSurface (*_eglGetCurrentSurface)(EGLint readdraw) = NULL; | |
99 | static EGLDisplay (*_eglGetCurrentDisplay)(void) = NULL; | |
100 | static EGLBoolean (*_eglQueryContext)(EGLDisplay dpy, EGLContext ctx, | |
101 | EGLint attribute, EGLint *value) = NULL; | |
102 | ||
103 | static EGLBoolean (*_eglWaitGL)(void) = NULL; | |
104 | static EGLBoolean (*_eglWaitNative)(EGLint engine) = NULL; | |
105 | static EGLBoolean (*_eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface) = NULL; | |
106 | static EGLBoolean (*_eglCopyBuffers)(EGLDisplay dpy, EGLSurface surface, | |
107 | EGLNativePixmapType target) = NULL; | |
108 | ||
109 | ||
110 | static EGLImageKHR (*_eglCreateImageKHR)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) = NULL; | |
111 | static EGLBoolean (*_eglDestroyImageKHR) (EGLDisplay dpy, EGLImageKHR image) = NULL; | |
112 | ||
113 | static void (*_glEGLImageTargetTexture2DOES) (GLenum target, GLeglImageOES image) = NULL; | |
114 | ||
115 | static __eglMustCastToProperFunctionPointerType (*_eglGetProcAddress)(const char *procname) = NULL; | |
116 | ||
117 | static void _init_androidegl() | |
118 | { | |
119 | _libegl = (void *) android_dlopen(getenv("LIBEGL") ? getenv("LIBEGL") : "libEGL.so", RTLD_LAZY); | |
120 | _libgles = (void *) android_dlopen(getenv("LIBGLESV2") ? getenv("LIBGLESV2") : "libGLESv2.so", RTLD_LAZY); | |
121 | } | |
122 | ||
123 | #define EGL_DLSYM(fptr, sym) do { if (_libegl == NULL) { _init_androidegl(); }; if (*(fptr) == NULL) { *(fptr) = (void *) android_dlsym(_libegl, sym); } } while (0) | |
124 | #define GLESv2_DLSYM(fptr, sym) do { if (_libgles == NULL) { _init_androidegl(); }; if (*(fptr) == NULL) { *(fptr) = (void *) android_dlsym(_libgles, sym); } } while (0) | |
125 | ||
126 | EGLint eglGetError(void) | |
127 | { | |
128 | EGL_DLSYM(&_eglGetError, "eglGetError"); | |
129 | return (*_eglGetError)(); | |
130 | } | |
131 | ||
132 | struct _eglDisplayMapping { | |
133 | EGLNativeDisplayType ndt; | |
134 | EGLDisplay display; | |
135 | }; | |
136 | ||
137 | #define _EGL_MAX_DISPLAYS 100 | |
138 | ||
139 | struct _eglDisplayMapping *_displayMappings[_EGL_MAX_DISPLAYS]; | |
140 | ||
141 | void _addMapping(EGLNativeDisplayType display_id, EGLDisplay display) | |
142 | { | |
143 | int i; | |
144 | for (i = 0; i < _EGL_MAX_DISPLAYS; i++) | |
145 | { | |
146 | if (_displayMappings[i] == NULL) | |
147 | { | |
148 | _displayMappings[i] = (struct _eglDisplayMapping *) malloc(sizeof(struct _eglDisplayMapping)); | |
149 | _displayMappings[i]->ndt = display_id; | |
150 | _displayMappings[i]->display = display; | |
151 | return; | |
152 | } | |
153 | } | |
154 | } | |
155 | ||
156 | EGLNativeDisplayType _egldisplay2NDT(EGLDisplay display) | |
157 | { | |
158 | int i; | |
159 | for (i = 0; i < _EGL_MAX_DISPLAYS; i++) | |
160 | { | |
161 | if (_displayMappings[i]) | |
162 | { | |
163 | if (_displayMappings[i]->display == display) | |
164 | { | |
165 | return _displayMappings[i]->ndt; | |
166 | } | |
167 | ||
168 | } | |
169 | } | |
170 | return EGL_NO_DISPLAY; | |
171 | } | |
172 | ||
173 | EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id) | |
174 | { | |
175 | EGL_DLSYM(&_eglGetDisplay, "eglGetDisplay"); | |
176 | EGLNativeDisplayType real_display; | |
177 | ||
178 | if (!ws_IsValidDisplay(display_id)) | |
179 | { | |
180 | return EGL_NO_DISPLAY; | |
181 | } | |
182 | ||
183 | real_display = (*_eglGetDisplay)(EGL_DEFAULT_DISPLAY); | |
184 | if (real_display == EGL_NO_DISPLAY) | |
185 | { | |
186 | return EGL_NO_DISPLAY; | |
187 | } | |
188 | _addMapping(display_id, real_display); | |
189 | return real_display; | |
190 | } | |
191 | ||
192 | EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) | |
193 | { | |
194 | EGL_DLSYM(&_eglInitialize, "eglInitialize"); | |
195 | return (*_eglInitialize)(dpy, major, minor); | |
196 | } | |
197 | ||
198 | EGLBoolean eglTerminate(EGLDisplay dpy) | |
199 | { | |
200 | EGL_DLSYM(&_eglTerminate, "eglTerminate"); | |
201 | return (*_eglTerminate)(dpy); | |
202 | } | |
203 | ||
204 | const char * eglQueryString(EGLDisplay dpy, EGLint name) | |
205 | { | |
206 | EGL_DLSYM(&_eglQueryString, "eglQueryString"); | |
207 | return ws_eglQueryString(dpy, name, _eglQueryString); | |
208 | } | |
209 | ||
210 | EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, | |
211 | EGLint config_size, EGLint *num_config) | |
212 | { | |
213 | EGL_DLSYM(&_eglGetConfigs, "eglGetConfigs"); | |
214 | return (*_eglGetConfigs)(dpy, configs, config_size, num_config); | |
215 | } | |
216 | ||
217 | EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, | |
218 | EGLConfig *configs, EGLint config_size, | |
219 | EGLint *num_config) | |
220 | { | |
221 | EGL_DLSYM(&_eglChooseConfig, "eglChooseConfig"); | |
222 | return (*_eglChooseConfig)(dpy, attrib_list, | |
223 | configs, config_size, | |
224 | num_config); | |
225 | } | |
226 | ||
227 | EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, | |
228 | EGLint attribute, EGLint *value) | |
229 | { | |
230 | EGL_DLSYM(&_eglGetConfigAttrib, "eglGetConfigAttrib"); | |
231 | return (*_eglGetConfigAttrib)(dpy, config, | |
232 | attribute, value); | |
233 | } | |
234 | ||
235 | EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, | |
236 | EGLNativeWindowType win, | |
237 | const EGLint *attrib_list) | |
238 | { | |
239 | EGL_DLSYM(&_eglCreateWindowSurface, "eglCreateWindowSurface"); | |
240 | ||
241 | win = ws_CreateWindow(win, _egldisplay2NDT(dpy)); | |
242 | ||
243 | assert(((struct ANativeWindowBuffer *) win)->common.magic == ANDROID_NATIVE_WINDOW_MAGIC); | |
244 | ||
245 | EGLSurface result = (*_eglCreateWindowSurface)(dpy, config, win, attrib_list); | |
246 | egl_helper_push_mapping(result, win); | |
247 | return result; | |
248 | } | |
249 | ||
250 | EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, | |
251 | const EGLint *attrib_list) | |
252 | { | |
253 | EGL_DLSYM(&_eglCreatePbufferSurface, "eglCreatePbufferSurface"); | |
254 | return (*_eglCreatePbufferSurface)(dpy, config, attrib_list); | |
255 | } | |
256 | ||
257 | EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, | |
258 | EGLNativePixmapType pixmap, | |
259 | const EGLint *attrib_list) | |
260 | { | |
261 | EGL_DLSYM(&_eglCreatePixmapSurface, "eglCreatePixmapSurface"); | |
262 | return (*_eglCreatePixmapSurface)(dpy, config, pixmap, attrib_list); | |
263 | } | |
264 | ||
265 | EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) | |
266 | { | |
267 | EGL_DLSYM(&_eglDestroySurface, "eglDestroySurface"); | |
268 | EGLBoolean result = (*_eglDestroySurface)(dpy, surface); | |
269 | ||
270 | /** | |
271 | * If the surface was created via eglCreateWindowSurface, we must | |
272 | * notify the ws about surface destruction for clean-up. | |
273 | **/ | |
274 | if (egl_helper_has_mapping(surface)) { | |
275 | ws_DestroyWindow(egl_helper_pop_mapping(surface)); | |
276 | } | |
277 | ||
278 | return result; | |
279 | } | |
280 | ||
281 | EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface surface, | |
282 | EGLint attribute, EGLint *value) | |
283 | { | |
284 | EGL_DLSYM(&_eglQuerySurface, "eglQuerySurface"); | |
285 | return (*_eglQuerySurface)(dpy, surface, attribute, value); | |
286 | } | |
287 | ||
288 | ||
289 | EGLBoolean eglBindAPI(EGLenum api) | |
290 | { | |
291 | EGL_DLSYM(&_eglBindAPI, "eglBindAPI"); | |
292 | return (*_eglBindAPI)(api); | |
293 | } | |
294 | ||
295 | EGLenum eglQueryAPI(void) | |
296 | { | |
297 | EGL_DLSYM(&_eglQueryAPI, "eglQueryAPI"); | |
298 | return (*_eglQueryAPI)(); | |
299 | } | |
300 | ||
301 | EGLBoolean eglWaitClient(void) | |
302 | { | |
303 | EGL_DLSYM(&_eglWaitClient, "eglWaitClient"); | |
304 | return (*_eglWaitClient)(); | |
305 | } | |
306 | ||
307 | EGLBoolean eglReleaseThread(void) | |
308 | { | |
309 | EGL_DLSYM(&_eglReleaseThread, "eglReleaseThread"); | |
310 | return (*_eglReleaseThread)(); | |
311 | } | |
312 | ||
313 | EGLSurface eglCreatePbufferFromClientBuffer( | |
314 | EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, | |
315 | EGLConfig config, const EGLint *attrib_list) | |
316 | { | |
317 | EGL_DLSYM(&_eglCreatePbufferFromClientBuffer, "eglCreatePbufferFromClientBuffer"); | |
318 | return (*_eglCreatePbufferFromClientBuffer)(dpy, buftype, buffer, config, attrib_list); | |
319 | } | |
320 | ||
321 | EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, | |
322 | EGLint attribute, EGLint value) | |
323 | { | |
324 | EGL_DLSYM(&_eglSurfaceAttrib, "eglSurfaceAttrib"); | |
325 | return (*_eglSurfaceAttrib)(dpy, surface, attribute, value); | |
326 | } | |
327 | ||
328 | EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) | |
329 | { | |
330 | EGL_DLSYM(&_eglBindTexImage, "eglBindTexImage"); | |
331 | return (*_eglBindTexImage)(dpy, surface, buffer); | |
332 | } | |
333 | ||
334 | EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) | |
335 | { | |
336 | EGL_DLSYM(&_eglReleaseTexImage, "eglReleaseTexImage"); | |
337 | return (*_eglReleaseTexImage)(dpy, surface, buffer); | |
338 | } | |
339 | ||
340 | EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) | |
341 | { | |
342 | EGL_DLSYM(&_eglSwapInterval, "eglSwapInterval"); | |
343 | return (*_eglSwapInterval)(dpy, interval); | |
344 | } | |
345 | ||
346 | EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, | |
347 | EGLContext share_context, | |
348 | const EGLint *attrib_list) | |
349 | { | |
350 | EGL_DLSYM(&_eglCreateContext, "eglCreateContext"); | |
351 | return (*_eglCreateContext)(dpy, config, share_context, attrib_list); | |
352 | } | |
353 | ||
354 | EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) | |
355 | { | |
356 | EGL_DLSYM(&_eglDestroyContext, "eglDestroyContext"); | |
357 | return (*_eglDestroyContext)(dpy, ctx); | |
358 | } | |
359 | ||
360 | EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, | |
361 | EGLSurface read, EGLContext ctx) | |
362 | { | |
363 | EGL_DLSYM(&_eglMakeCurrent, "eglMakeCurrent"); | |
364 | return (*_eglMakeCurrent)(dpy, draw, read, ctx); | |
365 | } | |
366 | ||
367 | EGLContext eglGetCurrentContext(void) | |
368 | { | |
369 | EGL_DLSYM(&_eglGetCurrentContext, "eglGetCurrentContext"); | |
370 | return (*_eglGetCurrentContext)(); | |
371 | } | |
372 | ||
373 | EGLSurface eglGetCurrentSurface(EGLint readdraw) | |
374 | { | |
375 | EGL_DLSYM(&_eglGetCurrentSurface, "eglGetCurrentSurface"); | |
376 | return (*_eglGetCurrentSurface)(readdraw); | |
377 | } | |
378 | ||
379 | EGLDisplay eglGetCurrentDisplay(void) | |
380 | { | |
381 | EGL_DLSYM(&_eglGetCurrentDisplay, "eglGetCurrentDisplay"); | |
382 | return (*_eglGetCurrentDisplay)(); | |
383 | } | |
384 | ||
385 | EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, | |
386 | EGLint attribute, EGLint *value) | |
387 | { | |
388 | EGL_DLSYM(&_eglQueryContext, "eglQueryContext"); | |
389 | return (*_eglQueryContext)(dpy, ctx, attribute, value); | |
390 | } | |
391 | ||
392 | EGLBoolean eglWaitGL(void) | |
393 | { | |
394 | EGL_DLSYM(&_eglWaitGL, "eglWaitGL"); | |
395 | return (*_eglWaitGL)(); | |
396 | } | |
397 | ||
398 | EGLBoolean eglWaitNative(EGLint engine) | |
399 | { | |
400 | EGL_DLSYM(&_eglWaitNative, "eglWaitNative"); | |
401 | return (*_eglWaitNative)(engine); | |
402 | } | |
403 | ||
404 | EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) | |
405 | { | |
406 | EGLBoolean ret; | |
407 | HYBRIS_TRACE_BEGIN("hybris-egl", "eglSwapBuffers", ""); | |
408 | EGL_DLSYM(&_eglSwapBuffers, "eglSwapBuffers"); | |
409 | ret = (*_eglSwapBuffers)(dpy, surface); | |
410 | HYBRIS_TRACE_END("hybris-egl", "eglSwapBuffers", ""); | |
411 | return ret; | |
412 | } | |
413 | ||
414 | EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, | |
415 | EGLNativePixmapType target) | |
416 | { | |
417 | EGL_DLSYM(&_eglCopyBuffers, "eglCopyBuffers"); | |
418 | return (*_eglCopyBuffers)(dpy, surface, target); | |
419 | } | |
420 | ||
421 | static EGLImageKHR _my_eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) | |
422 | { | |
423 | EGL_DLSYM(&_eglCreateImageKHR, "eglCreateImageKHR"); | |
424 | EGLContext newctx = ctx; | |
425 | EGLenum newtarget = target; | |
426 | EGLClientBuffer newbuffer = buffer; | |
427 | const EGLint *newattrib_list = attrib_list; | |
428 | ||
429 | ws_passthroughImageKHR(&newctx, &newtarget, &newbuffer, &newattrib_list); | |
430 | return (*_eglCreateImageKHR)(dpy, newctx, newtarget, newbuffer, newattrib_list); | |
431 | } | |
432 | ||
433 | static void _my_glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) | |
434 | { | |
435 | GLESv2_DLSYM(&_glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES"); | |
436 | (*_glEGLImageTargetTexture2DOES)(target, image); | |
437 | return; | |
438 | } | |
439 | ||
440 | __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) | |
441 | { | |
442 | EGL_DLSYM(&_eglGetProcAddress, "eglGetProcAddress"); | |
443 | if (strcmp(procname, "eglCreateImageKHR") == 0) | |
444 | { | |
445 | return _my_eglCreateImageKHR; | |
446 | } | |
447 | else if (strcmp(procname, "glEGLImageTargetTexture2DOES") == 0) | |
448 | { | |
449 | return _my_glEGLImageTargetTexture2DOES; | |
450 | } | |
451 | __eglMustCastToProperFunctionPointerType ret = ws_eglGetProcAddress(procname); | |
452 | if (ret == NULL) | |
453 | return (*_eglGetProcAddress)(procname); | |
454 | else return ret; | |
455 | } | |
456 | ||
457 | EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image) | |
458 | { | |
459 | EGL_DLSYM(&_eglDestroyImageKHR, "eglDestroyImageKHR"); | |
460 | return (*_eglDestroyImageKHR)(dpy, image); | |
461 | } | |
462 | ||
463 | ||
464 | // vim:ts=4:sw=4:noexpandtab |