Imported Upstream version 0.1.0+git20131207+e452e83
[deb_libhybris.git] / hybris / egl / egl.c
CommitLineData
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
39static void *_libegl = NULL;
40static void *_libgles = NULL;
41
42static EGLint (*_eglGetError)(void) = NULL;
43
44static EGLDisplay (*_eglGetDisplay)(EGLNativeDisplayType display_id) = NULL;
45static EGLBoolean (*_eglInitialize)(EGLDisplay dpy, EGLint *major, EGLint *minor) = NULL;
46static EGLBoolean (*_eglTerminate)(EGLDisplay dpy) = NULL;
47
48static const char * (*_eglQueryString)(EGLDisplay dpy, EGLint name) = NULL;
49
50static EGLBoolean (*_eglGetConfigs)(EGLDisplay dpy, EGLConfig *configs,
51 EGLint config_size, EGLint *num_config) = NULL;
52static EGLBoolean (*_eglChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list,
53 EGLConfig *configs, EGLint config_size,
54 EGLint *num_config) = NULL;
55static EGLBoolean (*_eglGetConfigAttrib)(EGLDisplay dpy, EGLConfig config,
56 EGLint attribute, EGLint *value) = NULL;
57
58static EGLSurface (*_eglCreateWindowSurface)(EGLDisplay dpy, EGLConfig config,
59 EGLNativeWindowType win,
60 const EGLint *attrib_list) = NULL;
61static EGLSurface (*_eglCreatePbufferSurface)(EGLDisplay dpy, EGLConfig config,
62 const EGLint *attrib_list) = NULL;
63static EGLSurface (*_eglCreatePixmapSurface)(EGLDisplay dpy, EGLConfig config,
64 EGLNativePixmapType pixmap,
65 const EGLint *attrib_list) = NULL;
66static EGLBoolean (*_eglDestroySurface)(EGLDisplay dpy, EGLSurface surface) = NULL;
67static EGLBoolean (*_eglQuerySurface)(EGLDisplay dpy, EGLSurface surface,
68 EGLint attribute, EGLint *value) = NULL;
69
70static EGLBoolean (*_eglBindAPI)(EGLenum api) = NULL;
71static EGLenum (*_eglQueryAPI)(void) = NULL;
72
73static EGLBoolean (*_eglWaitClient)(void) = NULL;
74
75static EGLBoolean (*_eglReleaseThread)(void) = NULL;
76
77static EGLSurface (*_eglCreatePbufferFromClientBuffer)(
78 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
79 EGLConfig config, const EGLint *attrib_list) = NULL;
80
81static EGLBoolean (*_eglSurfaceAttrib)(EGLDisplay dpy, EGLSurface surface,
82 EGLint attribute, EGLint value) = NULL;
83static EGLBoolean (*_eglBindTexImage)(EGLDisplay dpy, EGLSurface surface, EGLint buffer) = NULL;
84static EGLBoolean (*_eglReleaseTexImage)(EGLDisplay dpy, EGLSurface surface, EGLint buffer) = NULL;
85
86
87static EGLBoolean (*_eglSwapInterval)(EGLDisplay dpy, EGLint interval) = NULL;
88
89
90static EGLContext (*_eglCreateContext)(EGLDisplay dpy, EGLConfig config,
91 EGLContext share_context,
92 const EGLint *attrib_list) = NULL;
93static EGLBoolean (*_eglDestroyContext)(EGLDisplay dpy, EGLContext ctx) = NULL;
94static EGLBoolean (*_eglMakeCurrent)(EGLDisplay dpy, EGLSurface draw,
95 EGLSurface read, EGLContext ctx) = NULL;
96
97static EGLContext (*_eglGetCurrentContext)(void) = NULL;
98static EGLSurface (*_eglGetCurrentSurface)(EGLint readdraw) = NULL;
99static EGLDisplay (*_eglGetCurrentDisplay)(void) = NULL;
100static EGLBoolean (*_eglQueryContext)(EGLDisplay dpy, EGLContext ctx,
101 EGLint attribute, EGLint *value) = NULL;
102
103static EGLBoolean (*_eglWaitGL)(void) = NULL;
104static EGLBoolean (*_eglWaitNative)(EGLint engine) = NULL;
105static EGLBoolean (*_eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface) = NULL;
106static EGLBoolean (*_eglCopyBuffers)(EGLDisplay dpy, EGLSurface surface,
107 EGLNativePixmapType target) = NULL;
108
109
110static EGLImageKHR (*_eglCreateImageKHR)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) = NULL;
111static EGLBoolean (*_eglDestroyImageKHR) (EGLDisplay dpy, EGLImageKHR image) = NULL;
112
113static void (*_glEGLImageTargetTexture2DOES) (GLenum target, GLeglImageOES image) = NULL;
114
115static __eglMustCastToProperFunctionPointerType (*_eglGetProcAddress)(const char *procname) = NULL;
116
117static 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
126EGLint eglGetError(void)
127{
128 EGL_DLSYM(&_eglGetError, "eglGetError");
129 return (*_eglGetError)();
130}
131
132struct _eglDisplayMapping {
133 EGLNativeDisplayType ndt;
134 EGLDisplay display;
135};
136
137#define _EGL_MAX_DISPLAYS 100
138
139struct _eglDisplayMapping *_displayMappings[_EGL_MAX_DISPLAYS];
140
141void _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
156EGLNativeDisplayType _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
173EGLDisplay 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
192EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
193{
194 EGL_DLSYM(&_eglInitialize, "eglInitialize");
195 return (*_eglInitialize)(dpy, major, minor);
196}
197
198EGLBoolean eglTerminate(EGLDisplay dpy)
199{
200 EGL_DLSYM(&_eglTerminate, "eglTerminate");
201 return (*_eglTerminate)(dpy);
202}
203
204const char * eglQueryString(EGLDisplay dpy, EGLint name)
205{
206 EGL_DLSYM(&_eglQueryString, "eglQueryString");
207 return ws_eglQueryString(dpy, name, _eglQueryString);
208}
209
210EGLBoolean 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
217EGLBoolean 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
227EGLBoolean 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
235EGLSurface 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
250EGLSurface 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
257EGLSurface 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
265EGLBoolean 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
281EGLBoolean 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
289EGLBoolean eglBindAPI(EGLenum api)
290{
291 EGL_DLSYM(&_eglBindAPI, "eglBindAPI");
292 return (*_eglBindAPI)(api);
293}
294
295EGLenum eglQueryAPI(void)
296{
297 EGL_DLSYM(&_eglQueryAPI, "eglQueryAPI");
298 return (*_eglQueryAPI)();
299}
300
301EGLBoolean eglWaitClient(void)
302{
303 EGL_DLSYM(&_eglWaitClient, "eglWaitClient");
304 return (*_eglWaitClient)();
305}
306
307EGLBoolean eglReleaseThread(void)
308{
309 EGL_DLSYM(&_eglReleaseThread, "eglReleaseThread");
310 return (*_eglReleaseThread)();
311}
312
313EGLSurface 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
321EGLBoolean 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
328EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
329{
330 EGL_DLSYM(&_eglBindTexImage, "eglBindTexImage");
331 return (*_eglBindTexImage)(dpy, surface, buffer);
332}
333
334EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
335{
336 EGL_DLSYM(&_eglReleaseTexImage, "eglReleaseTexImage");
337 return (*_eglReleaseTexImage)(dpy, surface, buffer);
338}
339
340EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
341{
342 EGL_DLSYM(&_eglSwapInterval, "eglSwapInterval");
343 return (*_eglSwapInterval)(dpy, interval);
344}
345
346EGLContext 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
354EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
355{
356 EGL_DLSYM(&_eglDestroyContext, "eglDestroyContext");
357 return (*_eglDestroyContext)(dpy, ctx);
358}
359
360EGLBoolean 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
367EGLContext eglGetCurrentContext(void)
368{
369 EGL_DLSYM(&_eglGetCurrentContext, "eglGetCurrentContext");
370 return (*_eglGetCurrentContext)();
371}
372
373EGLSurface eglGetCurrentSurface(EGLint readdraw)
374{
375 EGL_DLSYM(&_eglGetCurrentSurface, "eglGetCurrentSurface");
376 return (*_eglGetCurrentSurface)(readdraw);
377}
378
379EGLDisplay eglGetCurrentDisplay(void)
380{
381 EGL_DLSYM(&_eglGetCurrentDisplay, "eglGetCurrentDisplay");
382 return (*_eglGetCurrentDisplay)();
383}
384
385EGLBoolean 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
392EGLBoolean eglWaitGL(void)
393{
394 EGL_DLSYM(&_eglWaitGL, "eglWaitGL");
395 return (*_eglWaitGL)();
396}
397
398EGLBoolean eglWaitNative(EGLint engine)
399{
400 EGL_DLSYM(&_eglWaitNative, "eglWaitNative");
401 return (*_eglWaitNative)(engine);
402}
403
404EGLBoolean 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
414EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface,
415 EGLNativePixmapType target)
416{
417 EGL_DLSYM(&_eglCopyBuffers, "eglCopyBuffers");
418 return (*_eglCopyBuffers)(dpy, surface, target);
419}
420
421static 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
433static 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
457EGLBoolean 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