OSDN Git Service

Merge "Adding 3 additional notification sounds Bug: 5416299" into ics-factoryrom
[android-x86/frameworks-native.git] / opengl / libs / EGL / eglApi.cpp
1 /* 
2  ** Copyright 2007, The Android Open Source Project
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 #include <ctype.h>
18 #include <stdlib.h>
19 #include <string.h>
20
21 #include <hardware/gralloc.h>
22 #include <system/window.h>
23
24 #include <EGL/egl.h>
25 #include <EGL/eglext.h>
26 #include <GLES/gl.h>
27 #include <GLES/glext.h>
28
29 #include <cutils/log.h>
30 #include <cutils/atomic.h>
31 #include <cutils/properties.h>
32 #include <cutils/memory.h>
33
34 #include <utils/KeyedVector.h>
35 #include <utils/SortedVector.h>
36 #include <utils/String8.h>
37
38 #include "egl_impl.h"
39 #include "egl_tls.h"
40 #include "glesv2dbg.h"
41 #include "hooks.h"
42
43 #include "egl_display.h"
44 #include "egl_impl.h"
45 #include "egl_object.h"
46 #include "egl_tls.h"
47
48 using namespace android;
49
50 // ----------------------------------------------------------------------------
51
52 static char const * const sVendorString     = "Android";
53 static char const * const sVersionString    = "1.4 Android META-EGL";
54 static char const * const sClientApiString  = "OpenGL ES";
55 static char const * const sExtensionString  =
56         "EGL_KHR_image "
57         "EGL_KHR_image_base "
58         "EGL_KHR_image_pixmap "
59         "EGL_KHR_gl_texture_2D_image "
60         "EGL_KHR_gl_texture_cubemap_image "
61         "EGL_KHR_gl_renderbuffer_image "
62         "EGL_KHR_fence_sync "
63         "EGL_ANDROID_image_native_buffer "
64         "EGL_ANDROID_swap_rectangle "
65         "EGL_NV_system_time "
66         ;
67
68 struct extention_map_t {
69     const char* name;
70     __eglMustCastToProperFunctionPointerType address;
71 };
72
73 static const extention_map_t sExtentionMap[] = {
74     { "eglLockSurfaceKHR",
75             (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
76     { "eglUnlockSurfaceKHR",
77             (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
78     { "eglCreateImageKHR",
79             (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
80     { "eglDestroyImageKHR",
81             (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
82     { "eglSetSwapRectangleANDROID",
83             (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
84     { "eglGetSystemTimeFrequencyNV",
85             (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
86     { "eglGetSystemTimeNV",
87             (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
88 };
89
90 // accesses protected by sExtensionMapMutex
91 static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
92 static int sGLExtentionSlot = 0;
93 static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
94
95 static void(*findProcAddress(const char* name,
96         const extention_map_t* map, size_t n))() {
97     for (uint32_t i=0 ; i<n ; i++) {
98         if (!strcmp(name, map[i].name)) {
99             return map[i].address;
100         }
101     }
102     return NULL;
103 }
104
105 // ----------------------------------------------------------------------------
106
107 template<typename T>
108 static __attribute__((noinline))
109 int binarySearch(T const sortedArray[], int first, int last, T key) {
110     while (first <= last) {
111         int mid = (first + last) / 2;
112         if (sortedArray[mid] < key) {
113             first = mid + 1;
114         } else if (key < sortedArray[mid]) {
115             last = mid - 1;
116         } else {
117             return mid;
118         }
119     }
120     return -1;
121 }
122
123 // ----------------------------------------------------------------------------
124
125 namespace android {
126 extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
127 extern EGLBoolean egl_init_drivers();
128 extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
129 extern int gEGLDebugLevel;
130 extern gl_hooks_t gHooksTrace;
131 extern gl_hooks_t gHooksDebug;
132 } // namespace android;
133
134 // ----------------------------------------------------------------------------
135
136 static inline void clearError() { egl_tls_t::clearError(); }
137 static inline EGLContext getContext() { return egl_tls_t::getContext(); }
138
139 // ----------------------------------------------------------------------------
140
141 EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
142 {
143     clearError();
144
145     uint32_t index = uint32_t(display);
146     if (index >= NUM_DISPLAYS) {
147         return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
148     }
149
150     if (egl_init_drivers() == EGL_FALSE) {
151         return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
152     }
153
154     EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
155     return dpy;
156 }
157
158 // ----------------------------------------------------------------------------
159 // Initialization
160 // ----------------------------------------------------------------------------
161
162 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
163 {
164     clearError();
165
166     egl_display_t * const dp = get_display(dpy);
167     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
168
169     EGLBoolean res = dp->initialize(major, minor);
170
171     return res;
172 }
173
174 EGLBoolean eglTerminate(EGLDisplay dpy)
175 {
176     // NOTE: don't unload the drivers b/c some APIs can be called
177     // after eglTerminate() has been called. eglTerminate() only
178     // terminates an EGLDisplay, not a EGL itself.
179
180     clearError();
181
182     egl_display_t* const dp = get_display(dpy);
183     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
184
185     EGLBoolean res = dp->terminate();
186     
187     return res;
188 }
189
190 // ----------------------------------------------------------------------------
191 // configuration
192 // ----------------------------------------------------------------------------
193
194 EGLBoolean eglGetConfigs(   EGLDisplay dpy,
195                             EGLConfig *configs,
196                             EGLint config_size, EGLint *num_config)
197 {
198     clearError();
199
200     egl_display_t const * const dp = validate_display(dpy);
201     if (!dp) return EGL_FALSE;
202
203     GLint numConfigs = dp->numTotalConfigs;
204     if (!configs) {
205         *num_config = numConfigs;
206         return EGL_TRUE;
207     }
208
209     GLint n = 0;
210     for (intptr_t i=0 ; i<dp->numTotalConfigs && config_size ; i++) {
211         *configs++ = EGLConfig(i);
212         config_size--;
213         n++;
214     }
215     
216     *num_config = n;
217     return EGL_TRUE;
218 }
219
220 EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
221                             EGLConfig *configs, EGLint config_size,
222                             EGLint *num_config)
223 {
224     clearError();
225
226     egl_display_t const * const dp = validate_display(dpy);
227     if (!dp) return EGL_FALSE;
228
229     if (num_config==0) {
230         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
231     }
232
233     EGLint n;
234     EGLBoolean res = EGL_FALSE;
235     *num_config = 0;
236
237     
238     // It is unfortunate, but we need to remap the EGL_CONFIG_IDs, 
239     // to do this, we have to go through the attrib_list array once
240     // to figure out both its size and if it contains an EGL_CONFIG_ID
241     // key. If so, the full array is copied and patched.
242     // NOTE: we assume that there can be only one occurrence
243     // of EGL_CONFIG_ID.
244     
245     EGLint patch_index = -1;
246     GLint attr;
247     size_t size = 0;
248     if (attrib_list) {
249         while ((attr=attrib_list[size]) != EGL_NONE) {
250             if (attr == EGL_CONFIG_ID)
251                 patch_index = size;
252             size += 2;
253         }
254     }
255     if (patch_index >= 0) {
256         size += 2; // we need copy the sentinel as well
257         EGLint* new_list = (EGLint*)malloc(size*sizeof(EGLint));
258         if (new_list == 0)
259             return setError(EGL_BAD_ALLOC, EGL_FALSE);
260         memcpy(new_list, attrib_list, size*sizeof(EGLint));
261
262         // patch the requested EGL_CONFIG_ID
263         bool found = false;
264         EGLConfig ourConfig(0);
265         EGLint& configId(new_list[patch_index+1]);
266         for (intptr_t i=0 ; i<dp->numTotalConfigs ; i++) {
267             if (dp->configs[i].configId == configId) {
268                 ourConfig = EGLConfig(i);
269                 configId = dp->configs[i].implConfigId;
270                 found = true;
271                 break;
272             }
273         }
274
275         egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(ourConfig)].impl];
276         if (found && cnx->dso) {
277             // and switch to the new list
278             attrib_list = const_cast<const EGLint *>(new_list);
279
280             // At this point, the only configuration that can match is
281             // dp->configs[i][index], however, we don't know if it would be
282             // rejected because of the other attributes, so we do have to call
283             // cnx->egl.eglChooseConfig() -- but we don't have to loop
284             // through all the EGLimpl[].
285             // We also know we can only get a single config back, and we know
286             // which one.
287
288             res = cnx->egl.eglChooseConfig(
289                     dp->disp[ dp->configs[intptr_t(ourConfig)].impl ].dpy,
290                     attrib_list, configs, config_size, &n);
291             if (res && n>0) {
292                 // n has to be 0 or 1, by construction, and we already know
293                 // which config it will return (since there can be only one).
294                 if (configs) {
295                     configs[0] = ourConfig;
296                 }
297                 *num_config = 1;
298             }
299         }
300
301         free(const_cast<EGLint *>(attrib_list));
302         return res;
303     }
304
305
306     for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
307         egl_connection_t* const cnx = &gEGLImpl[i];
308         if (cnx->dso) {
309             if (cnx->egl.eglChooseConfig(
310                     dp->disp[i].dpy, attrib_list, configs, config_size, &n)) {
311                 if (configs) {
312                     // now we need to convert these client EGLConfig to our
313                     // internal EGLConfig format.
314                     // This is done in O(n Log(n)) time.
315                     for (int j=0 ; j<n ; j++) {
316                         egl_config_t key(i, configs[j]);
317                         intptr_t index = binarySearch<egl_config_t>(
318                                 dp->configs, 0, dp->numTotalConfigs, key);
319                         if (index >= 0) {
320                             configs[j] = EGLConfig(index);
321                         } else {
322                             return setError(EGL_BAD_CONFIG, EGL_FALSE);
323                         }
324                     }
325                     configs += n;
326                     config_size -= n;
327                 }
328                 *num_config += n;
329                 res = EGL_TRUE;
330             }
331         }
332     }
333     return res;
334 }
335
336 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
337         EGLint attribute, EGLint *value)
338 {
339     clearError();
340
341     egl_display_t const* dp = 0;
342     egl_connection_t* cnx = validate_display_config(dpy, config, dp);
343     if (!cnx) return EGL_FALSE;
344     
345     if (attribute == EGL_CONFIG_ID) {
346         *value = dp->configs[intptr_t(config)].configId;
347         return EGL_TRUE;
348     }
349     return cnx->egl.eglGetConfigAttrib(
350             dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
351             dp->configs[intptr_t(config)].config, attribute, value);
352 }
353
354 // ----------------------------------------------------------------------------
355 // surfaces
356 // ----------------------------------------------------------------------------
357
358 EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
359                                     NativeWindowType window,
360                                     const EGLint *attrib_list)
361 {
362     clearError();
363
364     egl_display_t const* dp = 0;
365     egl_connection_t* cnx = validate_display_config(dpy, config, dp);
366     if (cnx) {
367         EGLDisplay iDpy = dp->disp[ dp->configs[intptr_t(config)].impl ].dpy;
368         EGLConfig iConfig = dp->configs[intptr_t(config)].config;
369         EGLint format;
370
371         if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) {
372             LOGE("EGLNativeWindowType %p already connected to another API",
373                     window);
374             return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
375         }
376
377         // set the native window's buffers format to match this config
378         if (cnx->egl.eglGetConfigAttrib(iDpy,
379                 iConfig, EGL_NATIVE_VISUAL_ID, &format)) {
380             if (format != 0) {
381                 int err = native_window_set_buffers_format(window, format);
382                 if (err != 0) {
383                     LOGE("error setting native window pixel format: %s (%d)",
384                             strerror(-err), err);
385                     native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
386                     return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
387                 }
388             }
389         }
390
391         EGLSurface surface = cnx->egl.eglCreateWindowSurface(
392                 iDpy, iConfig, window, attrib_list);
393         if (surface != EGL_NO_SURFACE) {
394             egl_surface_t* s = new egl_surface_t(dpy, config, window, surface,
395                     dp->configs[intptr_t(config)].impl, cnx);
396             return s;
397         }
398
399         // EGLSurface creation failed
400         native_window_set_buffers_format(window, 0);
401         native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
402     }
403     return EGL_NO_SURFACE;
404 }
405
406 EGLSurface eglCreatePixmapSurface(  EGLDisplay dpy, EGLConfig config,
407                                     NativePixmapType pixmap,
408                                     const EGLint *attrib_list)
409 {
410     clearError();
411
412     egl_display_t const* dp = 0;
413     egl_connection_t* cnx = validate_display_config(dpy, config, dp);
414     if (cnx) {
415         EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
416                 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
417                 dp->configs[intptr_t(config)].config, pixmap, attrib_list);
418         if (surface != EGL_NO_SURFACE) {
419             egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
420                     dp->configs[intptr_t(config)].impl, cnx);
421             return s;
422         }
423     }
424     return EGL_NO_SURFACE;
425 }
426
427 EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
428                                     const EGLint *attrib_list)
429 {
430     clearError();
431
432     egl_display_t const* dp = 0;
433     egl_connection_t* cnx = validate_display_config(dpy, config, dp);
434     if (cnx) {
435         EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
436                 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
437                 dp->configs[intptr_t(config)].config, attrib_list);
438         if (surface != EGL_NO_SURFACE) {
439             egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
440                     dp->configs[intptr_t(config)].impl, cnx);
441             return s;
442         }
443     }
444     return EGL_NO_SURFACE;
445 }
446                                     
447 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
448 {
449     clearError();
450
451     egl_display_t const * const dp = validate_display(dpy);
452     if (!dp) return EGL_FALSE;
453
454     SurfaceRef _s(surface);
455     if (!_s.get())
456         return setError(EGL_BAD_SURFACE, EGL_FALSE);
457
458     egl_surface_t * const s = get_surface(surface);
459     EGLBoolean result = s->cnx->egl.eglDestroySurface(
460             dp->disp[s->impl].dpy, s->surface);
461     if (result == EGL_TRUE) {
462         _s.terminate();
463     }
464     return result;
465 }
466
467 EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
468                             EGLint attribute, EGLint *value)
469 {
470     clearError();
471
472     egl_display_t const * const dp = validate_display(dpy);
473     if (!dp) return EGL_FALSE;
474
475     SurfaceRef _s(surface);
476     if (!_s.get())
477         return setError(EGL_BAD_SURFACE, EGL_FALSE);
478
479     egl_surface_t const * const s = get_surface(surface);
480     EGLBoolean result(EGL_TRUE);
481     if (attribute == EGL_CONFIG_ID) {
482         // We need to remap EGL_CONFIG_IDs
483         *value = dp->configs[intptr_t(s->config)].configId;
484     } else {
485         result = s->cnx->egl.eglQuerySurface(
486                 dp->disp[s->impl].dpy, s->surface, attribute, value);
487     }
488
489     return result;
490 }
491
492 // ----------------------------------------------------------------------------
493 // Contexts
494 // ----------------------------------------------------------------------------
495
496 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
497                             EGLContext share_list, const EGLint *attrib_list)
498 {
499     clearError();
500
501     egl_display_t const* dp = 0;
502     egl_connection_t* cnx = validate_display_config(dpy, config, dp);
503     if (cnx) {
504         if (share_list != EGL_NO_CONTEXT) {
505             egl_context_t* const c = get_context(share_list);
506             share_list = c->context;
507         }
508         EGLContext context = cnx->egl.eglCreateContext(
509                 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
510                 dp->configs[intptr_t(config)].config,
511                 share_list, attrib_list);
512         if (context != EGL_NO_CONTEXT) {
513             // figure out if it's a GLESv1 or GLESv2
514             int version = 0;
515             if (attrib_list) {
516                 while (*attrib_list != EGL_NONE) {
517                     GLint attr = *attrib_list++;
518                     GLint value = *attrib_list++;
519                     if (attr == EGL_CONTEXT_CLIENT_VERSION) {
520                         if (value == 1) {
521                             version = GLESv1_INDEX;
522                         } else if (value == 2) {
523                             version = GLESv2_INDEX;
524                         }
525                     }
526                 };
527             }
528             egl_context_t* c = new egl_context_t(dpy, context, config,
529                     dp->configs[intptr_t(config)].impl, cnx, version);
530             return c;
531         }
532     }
533     return EGL_NO_CONTEXT;
534 }
535
536 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
537 {
538     clearError();
539
540     egl_display_t const * const dp = validate_display(dpy);
541     if (!dp)
542         return EGL_FALSE;
543
544     ContextRef _c(ctx);
545     if (!_c.get())
546         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
547     
548     egl_context_t * const c = get_context(ctx);
549     EGLBoolean result = c->cnx->egl.eglDestroyContext(
550             dp->disp[c->impl].dpy, c->context);
551     if (result == EGL_TRUE) {
552         _c.terminate();
553     }
554     return result;
555 }
556
557 static void loseCurrent(egl_context_t * cur_c)
558 {
559     if (cur_c) {
560         egl_surface_t * cur_r = get_surface(cur_c->read);
561         egl_surface_t * cur_d = get_surface(cur_c->draw);
562
563         // by construction, these are either 0 or valid (possibly terminated)
564         // it should be impossible for these to be invalid
565         ContextRef _cur_c(cur_c);
566         SurfaceRef _cur_r(cur_r);
567         SurfaceRef _cur_d(cur_d);
568
569         cur_c->read = NULL;
570         cur_c->draw = NULL;
571
572         _cur_c.release();
573         _cur_r.release();
574         _cur_d.release();
575     }
576 }
577
578 EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
579                             EGLSurface read, EGLContext ctx)
580 {
581     clearError();
582
583     egl_display_t const * const dp = get_display(dpy);
584     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
585
586     // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
587     // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
588     // a valid but uninitialized display.
589     if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
590          (draw != EGL_NO_SURFACE) ) {
591         if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
592     }
593
594     // get a reference to the object passed in
595     ContextRef _c(ctx);
596     SurfaceRef _d(draw);
597     SurfaceRef _r(read);
598
599     // validate the context (if not EGL_NO_CONTEXT)
600     if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
601         // EGL_NO_CONTEXT is valid
602         return EGL_FALSE;
603     }
604
605     // these are the underlying implementation's object
606     EGLContext impl_ctx  = EGL_NO_CONTEXT;
607     EGLSurface impl_draw = EGL_NO_SURFACE;
608     EGLSurface impl_read = EGL_NO_SURFACE;
609
610     // these are our objects structs passed in
611     egl_context_t       * c = NULL;
612     egl_surface_t const * d = NULL;
613     egl_surface_t const * r = NULL;
614
615     // these are the current objects structs
616     egl_context_t * cur_c = get_context(getContext());
617     
618     if (ctx != EGL_NO_CONTEXT) {
619         c = get_context(ctx);
620         impl_ctx = c->context;
621     } else {
622         // no context given, use the implementation of the current context
623         if (cur_c == NULL) {
624             // no current context
625             if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
626                 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
627                 return setError(EGL_BAD_MATCH, EGL_FALSE);
628             }
629             // not an error, there is just no current context.
630             return EGL_TRUE;
631         }
632     }
633
634     // retrieve the underlying implementation's draw EGLSurface
635     if (draw != EGL_NO_SURFACE) {
636         d = get_surface(draw);
637         // make sure the EGLContext and EGLSurface passed in are for
638         // the same driver
639         if (c && d->impl != c->impl)
640             return setError(EGL_BAD_MATCH, EGL_FALSE);
641         impl_draw = d->surface;
642     }
643
644     // retrieve the underlying implementation's read EGLSurface
645     if (read != EGL_NO_SURFACE) {
646         r = get_surface(read);
647         // make sure the EGLContext and EGLSurface passed in are for
648         // the same driver
649         if (c && r->impl != c->impl)
650             return setError(EGL_BAD_MATCH, EGL_FALSE);
651         impl_read = r->surface;
652     }
653
654     EGLBoolean result;
655
656     if (c) {
657         result = c->cnx->egl.eglMakeCurrent(
658                 dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
659     } else {
660         result = cur_c->cnx->egl.eglMakeCurrent(
661                 dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
662     }
663
664     if (result == EGL_TRUE) {
665
666         loseCurrent(cur_c);
667
668         if (ctx != EGL_NO_CONTEXT) {
669             setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
670             egl_tls_t::setContext(ctx);
671             if (gEGLDebugLevel > 0) {
672                 CreateDbgContext(c->version, c->cnx->hooks[c->version]);
673             }
674             _c.acquire();
675             _r.acquire();
676             _d.acquire();
677             c->read = read;
678             c->draw = draw;
679         } else {
680             setGLHooksThreadSpecific(&gHooksNoContext);
681             egl_tls_t::setContext(EGL_NO_CONTEXT);
682         }
683     } else {
684         // this will LOGE the error
685         result = setError(c->cnx->egl.eglGetError(), EGL_FALSE);
686     }
687     return result;
688 }
689
690
691 EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
692                             EGLint attribute, EGLint *value)
693 {
694     clearError();
695
696     egl_display_t const * const dp = validate_display(dpy);
697     if (!dp) return EGL_FALSE;
698
699     ContextRef _c(ctx);
700     if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
701
702     egl_context_t * const c = get_context(ctx);
703
704     EGLBoolean result(EGL_TRUE);
705     if (attribute == EGL_CONFIG_ID) {
706         *value = dp->configs[intptr_t(c->config)].configId;
707     } else {
708         // We need to remap EGL_CONFIG_IDs
709         result = c->cnx->egl.eglQueryContext(
710                 dp->disp[c->impl].dpy, c->context, attribute, value);
711     }
712
713     return result;
714 }
715
716 EGLContext eglGetCurrentContext(void)
717 {
718     // could be called before eglInitialize(), but we wouldn't have a context
719     // then, and this function would correctly return EGL_NO_CONTEXT.
720
721     clearError();
722
723     EGLContext ctx = getContext();
724     return ctx;
725 }
726
727 EGLSurface eglGetCurrentSurface(EGLint readdraw)
728 {
729     // could be called before eglInitialize(), but we wouldn't have a context
730     // then, and this function would correctly return EGL_NO_SURFACE.
731
732     clearError();
733
734     EGLContext ctx = getContext();
735     if (ctx) {
736         egl_context_t const * const c = get_context(ctx);
737         if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
738         switch (readdraw) {
739             case EGL_READ: return c->read;
740             case EGL_DRAW: return c->draw;            
741             default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
742         }
743     }
744     return EGL_NO_SURFACE;
745 }
746
747 EGLDisplay eglGetCurrentDisplay(void)
748 {
749     // could be called before eglInitialize(), but we wouldn't have a context
750     // then, and this function would correctly return EGL_NO_DISPLAY.
751
752     clearError();
753
754     EGLContext ctx = getContext();
755     if (ctx) {
756         egl_context_t const * const c = get_context(ctx);
757         if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
758         return c->dpy;
759     }
760     return EGL_NO_DISPLAY;
761 }
762
763 EGLBoolean eglWaitGL(void)
764 {
765     // could be called before eglInitialize(), but we wouldn't have a context
766     // then, and this function would return GL_TRUE, which isn't wrong.
767
768     clearError();
769
770     EGLBoolean res = EGL_TRUE;
771     EGLContext ctx = getContext();
772     if (ctx) {
773         egl_context_t const * const c = get_context(ctx);
774         if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
775         if (uint32_t(c->impl)>=2)
776             return setError(EGL_BAD_CONTEXT, EGL_FALSE);
777         egl_connection_t* const cnx = &gEGLImpl[c->impl];
778         if (!cnx->dso) 
779             return setError(EGL_BAD_CONTEXT, EGL_FALSE);
780         res = cnx->egl.eglWaitGL();
781     }
782     return res;
783 }
784
785 EGLBoolean eglWaitNative(EGLint engine)
786 {
787     // could be called before eglInitialize(), but we wouldn't have a context
788     // then, and this function would return GL_TRUE, which isn't wrong.
789
790     clearError();
791
792     EGLBoolean res = EGL_TRUE;
793     EGLContext ctx = getContext();
794     if (ctx) {
795         egl_context_t const * const c = get_context(ctx);
796         if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
797         if (uint32_t(c->impl)>=2)
798             return setError(EGL_BAD_CONTEXT, EGL_FALSE);
799         egl_connection_t* const cnx = &gEGLImpl[c->impl];
800         if (!cnx->dso) 
801             return setError(EGL_BAD_CONTEXT, EGL_FALSE);
802         res = cnx->egl.eglWaitNative(engine);
803     }
804     return res;
805 }
806
807 EGLint eglGetError(void)
808 {
809     EGLint result = EGL_SUCCESS;
810     EGLint err;
811     for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
812         err = EGL_SUCCESS;
813         egl_connection_t* const cnx = &gEGLImpl[i];
814         if (cnx->dso)
815             err = cnx->egl.eglGetError();
816         if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
817             result = err;
818     }
819     err = egl_tls_t::getError();
820     if (result == EGL_SUCCESS)
821         result = err;
822     return result;
823 }
824
825 // Note: Similar implementations of these functions also exist in
826 // gl2.cpp and gl.cpp, and are used by applications that call the
827 // exported entry points directly.
828 typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
829 typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
830
831 static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL;
832 static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL;
833
834 static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image)
835 {
836     GLeglImageOES implImage =
837         (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
838     glEGLImageTargetTexture2DOES_impl(target, implImage);
839 }
840
841 static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image)
842 {
843     GLeglImageOES implImage =
844         (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
845     glEGLImageTargetRenderbufferStorageOES_impl(target, implImage);
846 }
847
848 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
849 {
850     // eglGetProcAddress() could be the very first function called
851     // in which case we must make sure we've initialized ourselves, this
852     // happens the first time egl_get_display() is called.
853
854     clearError();
855
856     if (egl_init_drivers() == EGL_FALSE) {
857         setError(EGL_BAD_PARAMETER, NULL);
858         return  NULL;
859     }
860
861     __eglMustCastToProperFunctionPointerType addr;
862     addr = findProcAddress(procname, sExtentionMap, NELEM(sExtentionMap));
863     if (addr) return addr;
864
865     // this protects accesses to sGLExtentionMap and sGLExtentionSlot
866     pthread_mutex_lock(&sExtensionMapMutex);
867
868         /*
869          * Since eglGetProcAddress() is not associated to anything, it needs
870          * to return a function pointer that "works" regardless of what
871          * the current context is.
872          *
873          * For this reason, we return a "forwarder", a small stub that takes
874          * care of calling the function associated with the context
875          * currently bound.
876          *
877          * We first look for extensions we've already resolved, if we're seeing
878          * this extension for the first time, we go through all our
879          * implementations and call eglGetProcAddress() and record the
880          * result in the appropriate implementation hooks and return the
881          * address of the forwarder corresponding to that hook set.
882          *
883          */
884
885         const String8 name(procname);
886         addr = sGLExtentionMap.valueFor(name);
887         const int slot = sGLExtentionSlot;
888
889         LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
890                 "no more slots for eglGetProcAddress(\"%s\")",
891                 procname);
892
893         if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
894             bool found = false;
895             for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
896                 egl_connection_t* const cnx = &gEGLImpl[i];
897                 if (cnx->dso && cnx->egl.eglGetProcAddress) {
898                     found = true;
899                     // Extensions are independent of the bound context
900                     cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
901                     cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
902 #if EGL_TRACE
903                     gHooksDebug.ext.extensions[slot] = gHooksTrace.ext.extensions[slot] =
904 #endif
905                             cnx->egl.eglGetProcAddress(procname);
906                 }
907             }
908             if (found) {
909                 addr = gExtensionForwarders[slot];
910
911                 if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) {
912                     glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr;
913                     addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper;
914                 }
915                 if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) {
916                     glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr;
917                     addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper;
918                 }
919
920                 sGLExtentionMap.add(name, addr);
921                 sGLExtentionSlot++;
922             }
923         }
924
925     pthread_mutex_unlock(&sExtensionMapMutex);
926     return addr;
927 }
928
929 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
930 {
931     EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw);
932     if (gEGLDebugLevel > 0)
933         Debug_eglSwapBuffers(dpy, draw);
934
935     clearError();
936
937     egl_display_t const * const dp = validate_display(dpy);
938     if (!dp) return EGL_FALSE;
939
940     SurfaceRef _s(draw);
941     if (!_s.get())
942         return setError(EGL_BAD_SURFACE, EGL_FALSE);
943
944     egl_surface_t const * const s = get_surface(draw);
945     return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
946 }
947
948 EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface surface,
949                             NativePixmapType target)
950 {
951     clearError();
952
953     egl_display_t const * const dp = validate_display(dpy);
954     if (!dp) return EGL_FALSE;
955
956     SurfaceRef _s(surface);
957     if (!_s.get())
958         return setError(EGL_BAD_SURFACE, EGL_FALSE);
959
960     egl_surface_t const * const s = get_surface(surface);
961     return s->cnx->egl.eglCopyBuffers(
962             dp->disp[s->impl].dpy, s->surface, target);
963 }
964
965 const char* eglQueryString(EGLDisplay dpy, EGLint name)
966 {
967     clearError();
968
969     egl_display_t const * const dp = validate_display(dpy);
970     if (!dp) return (const char *) NULL;
971
972     switch (name) {
973         case EGL_VENDOR:
974             return sVendorString;
975         case EGL_VERSION:
976             return sVersionString;
977         case EGL_EXTENSIONS:
978             return sExtensionString;
979         case EGL_CLIENT_APIS:
980             return sClientApiString;
981     }
982     return setError(EGL_BAD_PARAMETER, (const char *)0);
983 }
984
985
986 // ----------------------------------------------------------------------------
987 // EGL 1.1
988 // ----------------------------------------------------------------------------
989
990 EGLBoolean eglSurfaceAttrib(
991         EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
992 {
993     clearError();
994
995     egl_display_t const * const dp = validate_display(dpy);
996     if (!dp) return EGL_FALSE;
997
998     SurfaceRef _s(surface);
999     if (!_s.get())
1000         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1001
1002     egl_surface_t const * const s = get_surface(surface);
1003     if (s->cnx->egl.eglSurfaceAttrib) {
1004         return s->cnx->egl.eglSurfaceAttrib(
1005                 dp->disp[s->impl].dpy, s->surface, attribute, value);
1006     }
1007     return setError(EGL_BAD_SURFACE, EGL_FALSE);
1008 }
1009
1010 EGLBoolean eglBindTexImage(
1011         EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1012 {
1013     clearError();
1014
1015     egl_display_t const * const dp = validate_display(dpy);
1016     if (!dp) return EGL_FALSE;
1017
1018     SurfaceRef _s(surface);
1019     if (!_s.get())
1020         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1021
1022     egl_surface_t const * const s = get_surface(surface);
1023     if (s->cnx->egl.eglBindTexImage) {
1024         return s->cnx->egl.eglBindTexImage(
1025                 dp->disp[s->impl].dpy, s->surface, buffer);
1026     }
1027     return setError(EGL_BAD_SURFACE, EGL_FALSE);
1028 }
1029
1030 EGLBoolean eglReleaseTexImage(
1031         EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1032 {
1033     clearError();
1034
1035     egl_display_t const * const dp = validate_display(dpy);
1036     if (!dp) return EGL_FALSE;
1037
1038     SurfaceRef _s(surface);
1039     if (!_s.get())
1040         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1041
1042     egl_surface_t const * const s = get_surface(surface);
1043     if (s->cnx->egl.eglReleaseTexImage) {
1044         return s->cnx->egl.eglReleaseTexImage(
1045                 dp->disp[s->impl].dpy, s->surface, buffer);
1046     }
1047     return setError(EGL_BAD_SURFACE, EGL_FALSE);
1048 }
1049
1050 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1051 {
1052     clearError();
1053
1054     egl_display_t const * const dp = validate_display(dpy);
1055     if (!dp) return EGL_FALSE;
1056
1057     EGLBoolean res = EGL_TRUE;
1058     for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1059         egl_connection_t* const cnx = &gEGLImpl[i];
1060         if (cnx->dso) {
1061             if (cnx->egl.eglSwapInterval) {
1062                 if (cnx->egl.eglSwapInterval(
1063                         dp->disp[i].dpy, interval) == EGL_FALSE) {
1064                     res = EGL_FALSE;
1065                 }
1066             }
1067         }
1068     }
1069     return res;
1070 }
1071
1072
1073 // ----------------------------------------------------------------------------
1074 // EGL 1.2
1075 // ----------------------------------------------------------------------------
1076
1077 EGLBoolean eglWaitClient(void)
1078 {
1079     clearError();
1080
1081     // could be called before eglInitialize(), but we wouldn't have a context
1082     // then, and this function would return GL_TRUE, which isn't wrong.
1083     EGLBoolean res = EGL_TRUE;
1084     EGLContext ctx = getContext();
1085     if (ctx) {
1086         egl_context_t const * const c = get_context(ctx);
1087         if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1088         if (uint32_t(c->impl)>=2)
1089             return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1090         egl_connection_t* const cnx = &gEGLImpl[c->impl];
1091         if (!cnx->dso) 
1092             return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1093         if (cnx->egl.eglWaitClient) {
1094             res = cnx->egl.eglWaitClient();
1095         } else {
1096             res = cnx->egl.eglWaitGL();
1097         }
1098     }
1099     return res;
1100 }
1101
1102 EGLBoolean eglBindAPI(EGLenum api)
1103 {
1104     clearError();
1105
1106     if (egl_init_drivers() == EGL_FALSE) {
1107         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1108     }
1109
1110     // bind this API on all EGLs
1111     EGLBoolean res = EGL_TRUE;
1112     for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1113         egl_connection_t* const cnx = &gEGLImpl[i];
1114         if (cnx->dso) {
1115             if (cnx->egl.eglBindAPI) {
1116                 if (cnx->egl.eglBindAPI(api) == EGL_FALSE) {
1117                     res = EGL_FALSE;
1118                 }
1119             }
1120         }
1121     }
1122     return res;
1123 }
1124
1125 EGLenum eglQueryAPI(void)
1126 {
1127     clearError();
1128
1129     if (egl_init_drivers() == EGL_FALSE) {
1130         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1131     }
1132
1133     for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1134         egl_connection_t* const cnx = &gEGLImpl[i];
1135         if (cnx->dso) {
1136             if (cnx->egl.eglQueryAPI) {
1137                 // the first one we find is okay, because they all
1138                 // should be the same
1139                 return cnx->egl.eglQueryAPI();
1140             }
1141         }
1142     }
1143     // or, it can only be OpenGL ES
1144     return EGL_OPENGL_ES_API;
1145 }
1146
1147 EGLBoolean eglReleaseThread(void)
1148 {
1149     clearError();
1150
1151     // If there is context bound to the thread, release it
1152     loseCurrent(get_context(getContext()));
1153
1154     for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1155         egl_connection_t* const cnx = &gEGLImpl[i];
1156         if (cnx->dso) {
1157             if (cnx->egl.eglReleaseThread) {
1158                 cnx->egl.eglReleaseThread();
1159             }
1160         }
1161     }
1162     egl_tls_t::clearTLS();
1163     dbgReleaseThread();
1164     return EGL_TRUE;
1165 }
1166
1167 EGLSurface eglCreatePbufferFromClientBuffer(
1168           EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1169           EGLConfig config, const EGLint *attrib_list)
1170 {
1171     clearError();
1172
1173     egl_display_t const* dp = 0;
1174     egl_connection_t* cnx = validate_display_config(dpy, config, dp);
1175     if (!cnx) return EGL_FALSE;
1176     if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1177         return cnx->egl.eglCreatePbufferFromClientBuffer(
1178                 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1179                 buftype, buffer,
1180                 dp->configs[intptr_t(config)].config, attrib_list);
1181     }
1182     return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1183 }
1184
1185 // ----------------------------------------------------------------------------
1186 // EGL_EGLEXT_VERSION 3
1187 // ----------------------------------------------------------------------------
1188
1189 EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1190         const EGLint *attrib_list)
1191 {
1192     clearError();
1193
1194     egl_display_t const * const dp = validate_display(dpy);
1195     if (!dp) return EGL_FALSE;
1196
1197     SurfaceRef _s(surface);
1198     if (!_s.get())
1199         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1200
1201     egl_surface_t const * const s = get_surface(surface);
1202     if (s->cnx->egl.eglLockSurfaceKHR) {
1203         return s->cnx->egl.eglLockSurfaceKHR(
1204                 dp->disp[s->impl].dpy, s->surface, attrib_list);
1205     }
1206     return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1207 }
1208
1209 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1210 {
1211     clearError();
1212
1213     egl_display_t const * const dp = validate_display(dpy);
1214     if (!dp) return EGL_FALSE;
1215
1216     SurfaceRef _s(surface);
1217     if (!_s.get())
1218         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1219
1220     egl_surface_t const * const s = get_surface(surface);
1221     if (s->cnx->egl.eglUnlockSurfaceKHR) {
1222         return s->cnx->egl.eglUnlockSurfaceKHR(
1223                 dp->disp[s->impl].dpy, s->surface);
1224     }
1225     return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1226 }
1227
1228 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1229         EGLClientBuffer buffer, const EGLint *attrib_list)
1230 {
1231     clearError();
1232
1233     egl_display_t const * const dp = validate_display(dpy);
1234     if (!dp) return EGL_NO_IMAGE_KHR;
1235
1236     if (ctx != EGL_NO_CONTEXT) {
1237         ContextRef _c(ctx);
1238         if (!_c.get())
1239             return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1240         egl_context_t * const c = get_context(ctx);
1241         // since we have an EGLContext, we know which implementation to use
1242         EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
1243                 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
1244         if (image == EGL_NO_IMAGE_KHR)
1245             return image;
1246             
1247         egl_image_t* result = new egl_image_t(dpy, ctx);
1248         result->images[c->impl] = image;
1249         return (EGLImageKHR)result;
1250     } else {
1251         // EGL_NO_CONTEXT is a valid parameter
1252
1253         /* Since we don't have a way to know which implementation to call,
1254          * we're calling all of them. If at least one of the implementation
1255          * succeeded, this is a success.
1256          */
1257
1258         EGLint currentError = eglGetError();
1259
1260         EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS];
1261         bool success = false;
1262         for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1263             egl_connection_t* const cnx = &gEGLImpl[i];
1264             implImages[i] = EGL_NO_IMAGE_KHR;
1265             if (cnx->dso) {
1266                 if (cnx->egl.eglCreateImageKHR) {
1267                     implImages[i] = cnx->egl.eglCreateImageKHR(
1268                             dp->disp[i].dpy, ctx, target, buffer, attrib_list);
1269                     if (implImages[i] != EGL_NO_IMAGE_KHR) {
1270                         success = true;
1271                     }
1272                 }
1273             }
1274         }
1275
1276         if (!success) {
1277             // failure, if there was an error when we entered this function,
1278             // the error flag must not be updated.
1279             // Otherwise, the error is whatever happened in the implementation
1280             // that faulted.
1281             if (currentError != EGL_SUCCESS) {
1282                 setError(currentError, EGL_NO_IMAGE_KHR);
1283             }
1284             return EGL_NO_IMAGE_KHR;
1285         } else {
1286             // In case of success, we need to clear all error flags
1287             // (especially those caused by the implementation that didn't
1288             // succeed). TODO: we could avoid this if we knew this was
1289             // a "full" success (all implementation succeeded).
1290             eglGetError();
1291         }
1292
1293         egl_image_t* result = new egl_image_t(dpy, ctx);
1294         memcpy(result->images, implImages, sizeof(implImages));
1295         return (EGLImageKHR)result;
1296     }
1297 }
1298
1299 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1300 {
1301     clearError();
1302
1303     egl_display_t const * const dp = validate_display(dpy);
1304     if (!dp) return EGL_FALSE;
1305
1306     ImageRef _i(img);
1307     if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1308
1309     egl_image_t* image = get_image(img);
1310     bool success = false;
1311     for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1312         egl_connection_t* const cnx = &gEGLImpl[i];
1313         if (image->images[i] != EGL_NO_IMAGE_KHR) {
1314             if (cnx->dso) {
1315                 if (cnx->egl.eglDestroyImageKHR) {
1316                     if (cnx->egl.eglDestroyImageKHR(
1317                             dp->disp[i].dpy, image->images[i])) {
1318                         success = true;
1319                     }
1320                 }
1321             }
1322         }
1323     }
1324     if (!success)
1325         return EGL_FALSE;
1326
1327     _i.terminate();
1328
1329     return EGL_TRUE;
1330 }
1331
1332 // ----------------------------------------------------------------------------
1333 // EGL_EGLEXT_VERSION 5
1334 // ----------------------------------------------------------------------------
1335
1336
1337 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1338 {
1339     clearError();
1340
1341     egl_display_t const * const dp = validate_display(dpy);
1342     if (!dp) return EGL_NO_SYNC_KHR;
1343
1344     EGLContext ctx = eglGetCurrentContext();
1345     ContextRef _c(ctx);
1346     if (!_c.get())
1347         return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR);
1348
1349     egl_context_t * const c = get_context(ctx);
1350     EGLSyncKHR result = EGL_NO_SYNC_KHR;
1351     if (c->cnx->egl.eglCreateSyncKHR) {
1352         EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR(
1353                 dp->disp[c->impl].dpy, type, attrib_list);
1354         if (sync == EGL_NO_SYNC_KHR)
1355             return sync;
1356         result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync);
1357     }
1358     return (EGLSyncKHR)result;
1359 }
1360
1361 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1362 {
1363     clearError();
1364
1365     egl_display_t const * const dp = validate_display(dpy);
1366     if (!dp) return EGL_FALSE;
1367
1368     SyncRef _s(sync);
1369     if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1370     egl_sync_t* syncObject = get_sync(sync);
1371
1372     EGLContext ctx = syncObject->context;
1373     ContextRef _c(ctx);
1374     if (!_c.get())
1375         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1376
1377     EGLBoolean result = EGL_FALSE;
1378     egl_context_t * const c = get_context(ctx);
1379     if (c->cnx->egl.eglDestroySyncKHR) {
1380         result = c->cnx->egl.eglDestroySyncKHR(
1381                 dp->disp[c->impl].dpy, syncObject->sync);
1382         if (result)
1383             _s.terminate();
1384     }
1385     return result;
1386 }
1387
1388 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
1389 {
1390     clearError();
1391
1392     egl_display_t const * const dp = validate_display(dpy);
1393     if (!dp) return EGL_FALSE;
1394
1395     SyncRef _s(sync);
1396     if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1397     egl_sync_t* syncObject = get_sync(sync);
1398
1399     EGLContext ctx = syncObject->context;
1400     ContextRef _c(ctx);
1401     if (!_c.get())
1402         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1403
1404     egl_context_t * const c = get_context(ctx);
1405     if (c->cnx->egl.eglClientWaitSyncKHR) {
1406         return c->cnx->egl.eglClientWaitSyncKHR(
1407                 dp->disp[c->impl].dpy, syncObject->sync, flags, timeout);
1408     }
1409
1410     return EGL_FALSE;
1411 }
1412
1413 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
1414 {
1415     clearError();
1416
1417     egl_display_t const * const dp = validate_display(dpy);
1418     if (!dp) return EGL_FALSE;
1419
1420     SyncRef _s(sync);
1421     if (!_s.get())
1422         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1423
1424     egl_sync_t* syncObject = get_sync(sync);
1425     EGLContext ctx = syncObject->context;
1426     ContextRef _c(ctx);
1427     if (!_c.get())
1428         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1429
1430     egl_context_t * const c = get_context(ctx);
1431     if (c->cnx->egl.eglGetSyncAttribKHR) {
1432         return c->cnx->egl.eglGetSyncAttribKHR(
1433                 dp->disp[c->impl].dpy, syncObject->sync, attribute, value);
1434     }
1435
1436     return EGL_FALSE;
1437 }
1438
1439 // ----------------------------------------------------------------------------
1440 // ANDROID extensions
1441 // ----------------------------------------------------------------------------
1442
1443 EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
1444         EGLint left, EGLint top, EGLint width, EGLint height)
1445 {
1446     clearError();
1447
1448     egl_display_t const * const dp = validate_display(dpy);
1449     if (!dp) return EGL_FALSE;
1450
1451     SurfaceRef _s(draw);
1452     if (!_s.get())
1453         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1454
1455     egl_surface_t const * const s = get_surface(draw);
1456     if (s->cnx->egl.eglSetSwapRectangleANDROID) {
1457         return s->cnx->egl.eglSetSwapRectangleANDROID(
1458                 dp->disp[s->impl].dpy, s->surface, left, top, width, height);
1459     }
1460     return setError(EGL_BAD_DISPLAY, NULL);
1461 }
1462
1463 // ----------------------------------------------------------------------------
1464 // NVIDIA extensions
1465 // ----------------------------------------------------------------------------
1466 EGLuint64NV eglGetSystemTimeFrequencyNV()
1467 {
1468     clearError();
1469
1470     if (egl_init_drivers() == EGL_FALSE) {
1471         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1472     }
1473
1474     EGLuint64NV ret = 0;
1475     egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE];
1476
1477     if (cnx->dso) {
1478         if (cnx->egl.eglGetSystemTimeFrequencyNV) {
1479             return cnx->egl.eglGetSystemTimeFrequencyNV();
1480         }
1481     }
1482
1483     return setError(EGL_BAD_DISPLAY, 0);;
1484 }
1485
1486 EGLuint64NV eglGetSystemTimeNV()
1487 {
1488     clearError();
1489
1490     if (egl_init_drivers() == EGL_FALSE) {
1491         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1492     }
1493
1494     EGLuint64NV ret = 0;
1495     egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE];
1496
1497     if (cnx->dso) {
1498         if (cnx->egl.eglGetSystemTimeNV) {
1499             return cnx->egl.eglGetSystemTimeNV();
1500         }
1501     }
1502
1503     return setError(EGL_BAD_DISPLAY, 0);;
1504 }