Imported Upstream version 0.1.0+git20131207+e452e83
[deb_libhybris.git] / hybris / egl / egl.c
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