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