egl.cpp revision 8063c3ab04c922ef7c9bc3984a75503598001fd9
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#include <errno.h>
21#include <dlfcn.h>
22
23#include <sys/ioctl.h>
24
25#if HAVE_ANDROID_OS
26#include <linux/android_pmem.h>
27#endif
28
29#include <EGL/egl.h>
30#include <EGL/eglext.h>
31#include <GLES/gl.h>
32#include <GLES/glext.h>
33
34#include <cutils/log.h>
35#include <cutils/atomic.h>
36#include <cutils/properties.h>
37#include <cutils/memory.h>
38
39#include <utils/SortedVector.h>
40
41#include "hooks.h"
42#include "egl_impl.h"
43#include "Loader.h"
44
45#define MAKE_CONFIG(_impl, _index)  ((EGLConfig)(((_impl)<<24) | (_index)))
46#define setError(_e, _r) setErrorEtc(__FUNCTION__, __LINE__, _e, _r)
47
48// ----------------------------------------------------------------------------
49namespace android {
50// ----------------------------------------------------------------------------
51
52#define VERSION_MAJOR 1
53#define VERSION_MINOR 4
54static char const * const gVendorString     = "Android";
55static char const * const gVersionString    = "1.4 Android META-EGL";
56static char const * const gClientApiString  = "OpenGL ES";
57static char const * const gExtensionString  =
58        "EGL_KHR_image "
59        "EGL_KHR_image_base "
60        "EGL_KHR_image_pixmap "
61        "EGL_ANDROID_image_native_buffer "
62        "EGL_ANDROID_swap_rectangle "
63        "EGL_ANDROID_get_render_buffer "
64        ;
65
66// ----------------------------------------------------------------------------
67
68class egl_object_t {
69    static SortedVector<egl_object_t*> sObjects;
70    static Mutex sLock;
71
72            volatile int32_t  terminated;
73    mutable volatile int32_t  count;
74
75public:
76    egl_object_t() : terminated(0), count(1) {
77        Mutex::Autolock _l(sLock);
78        sObjects.add(this);
79    }
80
81    inline bool isAlive() const { return !terminated; }
82
83private:
84    bool get() {
85        Mutex::Autolock _l(sLock);
86        if (egl_object_t::sObjects.indexOf(this) >= 0) {
87            android_atomic_inc(&count);
88            return true;
89        }
90        return false;
91    }
92
93    bool put() {
94        Mutex::Autolock _l(sLock);
95        if (android_atomic_dec(&count) == 1) {
96            sObjects.remove(this);
97            return true;
98        }
99        return false;
100    }
101
102public:
103    template <typename N, typename T>
104    struct LocalRef {
105        N* ref;
106        LocalRef(T o) : ref(0) {
107            N* native = reinterpret_cast<N*>(o);
108            if (o && native->get()) {
109                ref = native;
110            }
111        }
112        ~LocalRef() {
113            if (ref && ref->put()) {
114                delete ref;
115            }
116        }
117        inline N* get() {
118            return ref;
119        }
120        void acquire() const {
121            if (ref) {
122                android_atomic_inc(&ref->count);
123            }
124        }
125        void release() const {
126            if (ref) {
127                int32_t c = android_atomic_dec(&ref->count);
128                // ref->count cannot be 1 prior atomic_dec because we have
129                // a reference, and if we have one, it means there was
130                // already one before us.
131                LOGE_IF(c==1, "refcount is now 0 in release()");
132            }
133        }
134        void terminate() {
135            if (ref) {
136                ref->terminated = 1;
137                release();
138            }
139        }
140    };
141};
142
143SortedVector<egl_object_t*> egl_object_t::sObjects;
144Mutex egl_object_t::sLock;
145
146struct egl_display_t {
147    enum { NOT_INITIALIZED, INITIALIZED, TERMINATED };
148
149    struct strings_t {
150        char const * vendor;
151        char const * version;
152        char const * clientApi;
153        char const * extensions;
154    };
155
156    struct DisplayImpl {
157        DisplayImpl() : dpy(EGL_NO_DISPLAY), config(0),
158                        state(NOT_INITIALIZED), numConfigs(0) { }
159        EGLDisplay  dpy;
160        EGLConfig*  config;
161        EGLint      state;
162        EGLint      numConfigs;
163        strings_t   queryString;
164    };
165
166    uint32_t    magic;
167    DisplayImpl disp[IMPL_NUM_IMPLEMENTATIONS];
168    EGLint      numTotalConfigs;
169    volatile int32_t refs;
170
171    egl_display_t() : magic('_dpy'), numTotalConfigs(0) { }
172    ~egl_display_t() { magic = 0; }
173    inline bool isValid() const { return magic == '_dpy'; }
174    inline bool isAlive() const { return isValid(); }
175};
176
177struct egl_surface_t : public egl_object_t
178{
179    typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
180
181    egl_surface_t(EGLDisplay dpy, EGLSurface surface,
182            int impl, egl_connection_t const* cnx)
183    : dpy(dpy), surface(surface), impl(impl), cnx(cnx) {
184    }
185    ~egl_surface_t() {
186    }
187    EGLDisplay                  dpy;
188    EGLSurface                  surface;
189    int                         impl;
190    egl_connection_t const*     cnx;
191};
192
193struct egl_context_t : public egl_object_t
194{
195    typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
196
197    egl_context_t(EGLDisplay dpy, EGLContext context,
198            int impl, egl_connection_t const* cnx, int version)
199    : dpy(dpy), context(context), read(0), draw(0), impl(impl), cnx(cnx),
200      version(version)
201    {
202    }
203    EGLDisplay                  dpy;
204    EGLContext                  context;
205    EGLSurface                  read;
206    EGLSurface                  draw;
207    int                         impl;
208    egl_connection_t const*     cnx;
209    int                         version;
210};
211
212struct egl_image_t : public egl_object_t
213{
214    typedef egl_object_t::LocalRef<egl_image_t, EGLImageKHR> Ref;
215
216    egl_image_t(EGLDisplay dpy, EGLContext context)
217        : dpy(dpy), context(context)
218    {
219        memset(images, 0, sizeof(images));
220    }
221    EGLDisplay dpy;
222    EGLConfig context;
223    EGLImageKHR images[IMPL_NUM_IMPLEMENTATIONS];
224};
225
226typedef egl_surface_t::Ref  SurfaceRef;
227typedef egl_context_t::Ref  ContextRef;
228typedef egl_image_t::Ref    ImageRef;
229
230struct tls_t
231{
232    tls_t() : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(EGL_TRUE) { }
233    EGLint      error;
234    EGLContext  ctx;
235    EGLBoolean  logCallWithNoContext;
236};
237
238
239// ----------------------------------------------------------------------------
240
241egl_connection_t gEGLImpl[IMPL_NUM_IMPLEMENTATIONS];
242static egl_display_t gDisplay[NUM_DISPLAYS];
243static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER;
244static pthread_key_t gEGLThreadLocalStorageKey = -1;
245
246// ----------------------------------------------------------------------------
247
248EGLAPI gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS];
249EGLAPI gl_hooks_t gHooksNoContext;
250EGLAPI pthread_key_t gGLWrapperKey = -1;
251
252// ----------------------------------------------------------------------------
253
254static __attribute__((noinline))
255const char *egl_strerror(EGLint err)
256{
257    switch (err){
258        case EGL_SUCCESS:               return "EGL_SUCCESS";
259        case EGL_NOT_INITIALIZED:       return "EGL_NOT_INITIALIZED";
260        case EGL_BAD_ACCESS:            return "EGL_BAD_ACCESS";
261        case EGL_BAD_ALLOC:             return "EGL_BAD_ALLOC";
262        case EGL_BAD_ATTRIBUTE:         return "EGL_BAD_ATTRIBUTE";
263        case EGL_BAD_CONFIG:            return "EGL_BAD_CONFIG";
264        case EGL_BAD_CONTEXT:           return "EGL_BAD_CONTEXT";
265        case EGL_BAD_CURRENT_SURFACE:   return "EGL_BAD_CURRENT_SURFACE";
266        case EGL_BAD_DISPLAY:           return "EGL_BAD_DISPLAY";
267        case EGL_BAD_MATCH:             return "EGL_BAD_MATCH";
268        case EGL_BAD_NATIVE_PIXMAP:     return "EGL_BAD_NATIVE_PIXMAP";
269        case EGL_BAD_NATIVE_WINDOW:     return "EGL_BAD_NATIVE_WINDOW";
270        case EGL_BAD_PARAMETER:         return "EGL_BAD_PARAMETER";
271        case EGL_BAD_SURFACE:           return "EGL_BAD_SURFACE";
272        case EGL_CONTEXT_LOST:          return "EGL_CONTEXT_LOST";
273        default: return "UNKNOWN";
274    }
275}
276
277static __attribute__((noinline))
278void clearTLS() {
279    if (gEGLThreadLocalStorageKey != -1) {
280        tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
281        if (tls) {
282            delete tls;
283            pthread_setspecific(gEGLThreadLocalStorageKey, 0);
284        }
285    }
286}
287
288static tls_t* getTLS()
289{
290    tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
291    if (tls == 0) {
292        tls = new tls_t;
293        pthread_setspecific(gEGLThreadLocalStorageKey, tls);
294    }
295    return tls;
296}
297
298template<typename T>
299static __attribute__((noinline))
300T setErrorEtc(const char* caller, int line, EGLint error, T returnValue) {
301    if (gEGLThreadLocalStorageKey == -1) {
302        pthread_mutex_lock(&gThreadLocalStorageKeyMutex);
303        if (gEGLThreadLocalStorageKey == -1)
304            pthread_key_create(&gEGLThreadLocalStorageKey, NULL);
305        pthread_mutex_unlock(&gThreadLocalStorageKeyMutex);
306    }
307    tls_t* tls = getTLS();
308    if (tls->error != error) {
309        LOGE("%s:%d error %x (%s)", caller, line, error, egl_strerror(error));
310        tls->error = error;
311    }
312    return returnValue;
313}
314
315static __attribute__((noinline))
316GLint getError() {
317    if (gEGLThreadLocalStorageKey == -1)
318        return EGL_SUCCESS;
319    tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
320    if (!tls) return EGL_SUCCESS;
321    GLint error = tls->error;
322    tls->error = EGL_SUCCESS;
323    return error;
324}
325
326static __attribute__((noinline))
327void setContext(EGLContext ctx) {
328    if (gEGLThreadLocalStorageKey == -1) {
329        pthread_mutex_lock(&gThreadLocalStorageKeyMutex);
330        if (gEGLThreadLocalStorageKey == -1)
331            pthread_key_create(&gEGLThreadLocalStorageKey, NULL);
332        pthread_mutex_unlock(&gThreadLocalStorageKeyMutex);
333    }
334    tls_t* tls = getTLS();
335    tls->ctx = ctx;
336}
337
338static __attribute__((noinline))
339EGLContext getContext() {
340    if (gEGLThreadLocalStorageKey == -1)
341        return EGL_NO_CONTEXT;
342    tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
343    if (!tls) return EGL_NO_CONTEXT;
344    return tls->ctx;
345}
346
347/*****************************************************************************/
348
349template<typename T>
350static __attribute__((noinline))
351int binarySearch(
352        T const sortedArray[], int first, int last, T key)
353{
354    while (first <= last) {
355        int mid = (first + last) / 2;
356        if (key > sortedArray[mid]) {
357            first = mid + 1;
358        } else if (key < sortedArray[mid]) {
359            last = mid - 1;
360        } else {
361            return mid;
362        }
363    }
364    return -1;
365}
366
367static EGLint configToUniqueId(egl_display_t const* dp, int i, int index)
368{
369    // NOTE: this mapping works only if we have no more than two EGLimpl
370    return (i>0 ? dp->disp[0].numConfigs : 0) + index;
371}
372
373static void uniqueIdToConfig(egl_display_t const* dp, EGLint configId,
374        int& i, int& index)
375{
376    // NOTE: this mapping works only if we have no more than two EGLimpl
377    size_t numConfigs = dp->disp[0].numConfigs;
378    i = configId / numConfigs;
379    index = configId % numConfigs;
380}
381
382static int cmp_configs(const void* a, const void *b)
383{
384    EGLConfig c0 = *(EGLConfig const *)a;
385    EGLConfig c1 = *(EGLConfig const *)b;
386    return c0<c1 ? -1 : (c0>c1 ? 1 : 0);
387}
388
389struct extention_map_t {
390    const char* name;
391    __eglMustCastToProperFunctionPointerType address;
392};
393
394static const extention_map_t gExtentionMap[] = {
395    { "eglLockSurfaceKHR",
396            (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
397    { "eglUnlockSurfaceKHR",
398            (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
399    { "eglCreateImageKHR",
400            (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
401    { "eglDestroyImageKHR",
402            (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
403    { "eglSetSwapRectangleANDROID",
404            (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
405    { "eglGetRenderBufferANDROID",
406            (__eglMustCastToProperFunctionPointerType)&eglGetRenderBufferANDROID },
407};
408
409static extention_map_t gGLExtentionMap[MAX_NUMBER_OF_GL_EXTENSIONS];
410
411static void(*findProcAddress(const char* name,
412        const extention_map_t* map, size_t n))()
413{
414    for (uint32_t i=0 ; i<n ; i++) {
415        if (!strcmp(name, map[i].name)) {
416            return map[i].address;
417        }
418    }
419    return NULL;
420}
421
422// ----------------------------------------------------------------------------
423
424static void gl_no_context() {
425    tls_t* tls = getTLS();
426    if (tls->logCallWithNoContext == EGL_TRUE) {
427        tls->logCallWithNoContext = EGL_FALSE;
428        LOGE("call to OpenGL ES API with no current context "
429             "(logged once per thread)");
430    }
431}
432
433static void early_egl_init(void)
434{
435#if !USE_FAST_TLS_KEY
436    pthread_key_create(&gGLWrapperKey, NULL);
437#endif
438    uint32_t addr = (uint32_t)((void*)gl_no_context);
439    android_memset32(
440            (uint32_t*)(void*)&gHooksNoContext,
441            addr,
442            sizeof(gHooksNoContext));
443    setGlThreadSpecific(&gHooksNoContext);
444}
445
446static pthread_once_t once_control = PTHREAD_ONCE_INIT;
447static int sEarlyInitState = pthread_once(&once_control, &early_egl_init);
448
449
450static inline
451egl_display_t* get_display(EGLDisplay dpy)
452{
453    uintptr_t index = uintptr_t(dpy)-1U;
454    return (index >= NUM_DISPLAYS) ? NULL : &gDisplay[index];
455}
456
457template<typename NATIVE, typename EGL>
458static inline NATIVE* egl_to_native_cast(EGL arg) {
459    return reinterpret_cast<NATIVE*>(arg);
460}
461
462static inline
463egl_surface_t* get_surface(EGLSurface surface) {
464    return egl_to_native_cast<egl_surface_t>(surface);
465}
466
467static inline
468egl_context_t* get_context(EGLContext context) {
469    return egl_to_native_cast<egl_context_t>(context);
470}
471
472static inline
473egl_image_t* get_image(EGLImageKHR image) {
474    return egl_to_native_cast<egl_image_t>(image);
475}
476
477static egl_connection_t* validate_display_config(
478        EGLDisplay dpy, EGLConfig config,
479        egl_display_t const*& dp, int& impl, int& index)
480{
481    dp = get_display(dpy);
482    if (!dp) return setError(EGL_BAD_DISPLAY, (egl_connection_t*)NULL);
483
484    impl = uintptr_t(config)>>24;
485    if (uint32_t(impl) >= IMPL_NUM_IMPLEMENTATIONS) {
486        return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
487    }
488    index = uintptr_t(config) & 0xFFFFFF;
489    if (index >= dp->disp[impl].numConfigs) {
490        return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
491    }
492    egl_connection_t* const cnx = &gEGLImpl[impl];
493    if (cnx->dso == 0) {
494        return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
495    }
496    return cnx;
497}
498
499static EGLBoolean validate_display_context(EGLDisplay dpy, EGLContext ctx)
500{
501    if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS)
502        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
503    if (!get_display(dpy)->isAlive())
504        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
505    if (!get_context(ctx)->isAlive())
506        return setError(EGL_BAD_CONTEXT, EGL_FALSE);
507    return EGL_TRUE;
508}
509
510static EGLBoolean validate_display_surface(EGLDisplay dpy, EGLSurface surface)
511{
512    if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS)
513        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
514    if (!get_display(dpy)->isAlive())
515        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
516    if (!get_surface(surface)->isAlive())
517        return setError(EGL_BAD_SURFACE, EGL_FALSE);
518    return EGL_TRUE;
519}
520
521EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image)
522{
523    ImageRef _i(image);
524    if (!_i.get()) return EGL_NO_IMAGE_KHR;
525
526    EGLContext context = getContext();
527    if (context == EGL_NO_CONTEXT || image == EGL_NO_IMAGE_KHR)
528        return EGL_NO_IMAGE_KHR;
529
530    egl_context_t const * const c = get_context(context);
531    if (!c->isAlive())
532        return EGL_NO_IMAGE_KHR;
533
534    egl_image_t const * const i = get_image(image);
535    return i->images[c->impl];
536}
537
538// ----------------------------------------------------------------------------
539
540// this mutex protects:
541//    d->disp[]
542//    egl_init_drivers_locked()
543//
544static pthread_mutex_t gInitDriverMutex = PTHREAD_MUTEX_INITIALIZER;
545
546EGLBoolean egl_init_drivers_locked()
547{
548    if (sEarlyInitState) {
549        // initialized by static ctor. should be set here.
550        return EGL_FALSE;
551    }
552
553    // get our driver loader
554    Loader& loader(Loader::getInstance());
555
556    // dynamically load all our EGL implementations for all displays
557    // and retrieve the corresponding EGLDisplay
558    // if that fails, don't use this driver.
559    // TODO: currently we only deal with EGL_DEFAULT_DISPLAY
560    egl_connection_t* cnx;
561    egl_display_t* d = &gDisplay[0];
562
563    cnx = &gEGLImpl[IMPL_SOFTWARE];
564    if (cnx->dso == 0) {
565        cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_SOFTWARE];
566        cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_SOFTWARE];
567        cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 0, cnx);
568        if (cnx->dso) {
569            EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
570            LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for software EGL!");
571            d->disp[IMPL_SOFTWARE].dpy = dpy;
572            if (dpy == EGL_NO_DISPLAY) {
573                loader.close(cnx->dso);
574                cnx->dso = NULL;
575            }
576        }
577    }
578
579    cnx = &gEGLImpl[IMPL_HARDWARE];
580    if (cnx->dso == 0) {
581        char value[PROPERTY_VALUE_MAX];
582        property_get("debug.egl.hw", value, "1");
583        if (atoi(value) != 0) {
584            cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_HARDWARE];
585            cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_HARDWARE];
586            cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 1, cnx);
587            if (cnx->dso) {
588                EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
589                LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for hardware EGL!");
590                d->disp[IMPL_HARDWARE].dpy = dpy;
591                if (dpy == EGL_NO_DISPLAY) {
592                    loader.close(cnx->dso);
593                    cnx->dso = NULL;
594                }
595            }
596        } else {
597            LOGD("3D hardware acceleration is disabled");
598        }
599    }
600
601    if (!gEGLImpl[IMPL_SOFTWARE].dso && !gEGLImpl[IMPL_HARDWARE].dso) {
602        return EGL_FALSE;
603    }
604
605    return EGL_TRUE;
606}
607
608EGLBoolean egl_init_drivers()
609{
610    EGLBoolean res;
611    pthread_mutex_lock(&gInitDriverMutex);
612    res = egl_init_drivers_locked();
613    pthread_mutex_unlock(&gInitDriverMutex);
614    return res;
615}
616
617// ----------------------------------------------------------------------------
618}; // namespace android
619// ----------------------------------------------------------------------------
620
621using namespace android;
622
623EGLDisplay eglGetDisplay(NativeDisplayType display)
624{
625    uint32_t index = uint32_t(display);
626    if (index >= NUM_DISPLAYS) {
627        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
628    }
629
630    if (egl_init_drivers() == EGL_FALSE) {
631        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
632    }
633
634    EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU);
635    return dpy;
636}
637
638// ----------------------------------------------------------------------------
639// Initialization
640// ----------------------------------------------------------------------------
641
642EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
643{
644    egl_display_t * const dp = get_display(dpy);
645    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
646
647    if (android_atomic_inc(&dp->refs) > 0) {
648        if (major != NULL) *major = VERSION_MAJOR;
649        if (minor != NULL) *minor = VERSION_MINOR;
650        return EGL_TRUE;
651    }
652
653    setGlThreadSpecific(&gHooksNoContext);
654
655    // initialize each EGL and
656    // build our own extension string first, based on the extension we know
657    // and the extension supported by our client implementation
658    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
659        egl_connection_t* const cnx = &gEGLImpl[i];
660        cnx->major = -1;
661        cnx->minor = -1;
662        if (!cnx->dso)
663            continue;
664
665#if defined(ADRENO130)
666#warning "Adreno-130 eglInitialize() workaround"
667        /*
668         * The ADRENO 130 driver returns a different EGLDisplay each time
669         * eglGetDisplay() is called, but also makes the EGLDisplay invalid
670         * after eglTerminate() has been called, so that eglInitialize()
671         * cannot be called again. Therefore, we need to make sure to call
672         * eglGetDisplay() before calling eglInitialize();
673         */
674        if (i == IMPL_HARDWARE) {
675            dp->disp[i].dpy =
676                cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
677        }
678#endif
679
680
681        EGLDisplay idpy = dp->disp[i].dpy;
682        if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
683            //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p",
684            //        i, idpy, cnx->major, cnx->minor, cnx);
685
686            // display is now initialized
687            dp->disp[i].state = egl_display_t::INITIALIZED;
688
689            // get the query-strings for this display for each implementation
690            dp->disp[i].queryString.vendor =
691                cnx->egl.eglQueryString(idpy, EGL_VENDOR);
692            dp->disp[i].queryString.version =
693                cnx->egl.eglQueryString(idpy, EGL_VERSION);
694            dp->disp[i].queryString.extensions =
695                    cnx->egl.eglQueryString(idpy, EGL_EXTENSIONS);
696            dp->disp[i].queryString.clientApi =
697                cnx->egl.eglQueryString(idpy, EGL_CLIENT_APIS);
698
699        } else {
700            LOGW("%d: eglInitialize(%p) failed (%s)", i, idpy,
701                    egl_strerror(cnx->egl.eglGetError()));
702        }
703    }
704
705    EGLBoolean res = EGL_FALSE;
706    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
707        egl_connection_t* const cnx = &gEGLImpl[i];
708        if (cnx->dso && cnx->major>=0 && cnx->minor>=0) {
709            EGLint n;
710            if (cnx->egl.eglGetConfigs(dp->disp[i].dpy, 0, 0, &n)) {
711                dp->disp[i].config = (EGLConfig*)malloc(sizeof(EGLConfig)*n);
712                if (dp->disp[i].config) {
713                    if (cnx->egl.eglGetConfigs(
714                            dp->disp[i].dpy, dp->disp[i].config, n,
715                            &dp->disp[i].numConfigs))
716                    {
717                        // sort the configurations so we can do binary searches
718                        qsort(  dp->disp[i].config,
719                                dp->disp[i].numConfigs,
720                                sizeof(EGLConfig), cmp_configs);
721
722                        dp->numTotalConfigs += n;
723                        res = EGL_TRUE;
724                    }
725                }
726            }
727        }
728    }
729
730    if (res == EGL_TRUE) {
731        if (major != NULL) *major = VERSION_MAJOR;
732        if (minor != NULL) *minor = VERSION_MINOR;
733        return EGL_TRUE;
734    }
735    return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
736}
737
738EGLBoolean eglTerminate(EGLDisplay dpy)
739{
740    // NOTE: don't unload the drivers b/c some APIs can be called
741    // after eglTerminate() has been called. eglTerminate() only
742    // terminates an EGLDisplay, not a EGL itself.
743
744    egl_display_t* const dp = get_display(dpy);
745    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
746    if (android_atomic_dec(&dp->refs) != 1)
747        return EGL_TRUE;
748
749    EGLBoolean res = EGL_FALSE;
750    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
751        egl_connection_t* const cnx = &gEGLImpl[i];
752        if (cnx->dso && dp->disp[i].state == egl_display_t::INITIALIZED) {
753            if (cnx->egl.eglTerminate(dp->disp[i].dpy) == EGL_FALSE) {
754                LOGW("%d: eglTerminate(%p) failed (%s)", i, dp->disp[i].dpy,
755                        egl_strerror(cnx->egl.eglGetError()));
756            }
757            // REVISIT: it's unclear what to do if eglTerminate() fails
758            free(dp->disp[i].config);
759
760            dp->disp[i].numConfigs = 0;
761            dp->disp[i].config = 0;
762            dp->disp[i].state = egl_display_t::TERMINATED;
763
764            res = EGL_TRUE;
765        }
766    }
767
768    // TODO: all egl_object_t should be marked for termination
769
770    dp->numTotalConfigs = 0;
771    clearTLS();
772    return res;
773}
774
775// ----------------------------------------------------------------------------
776// configuration
777// ----------------------------------------------------------------------------
778
779EGLBoolean eglGetConfigs(   EGLDisplay dpy,
780                            EGLConfig *configs,
781                            EGLint config_size, EGLint *num_config)
782{
783    egl_display_t const * const dp = get_display(dpy);
784    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
785
786    GLint numConfigs = dp->numTotalConfigs;
787    if (!configs) {
788        *num_config = numConfigs;
789        return EGL_TRUE;
790    }
791    GLint n = 0;
792    for (int j=0 ; j<IMPL_NUM_IMPLEMENTATIONS ; j++) {
793        for (int i=0 ; i<dp->disp[j].numConfigs && config_size ; i++) {
794            *configs++ = MAKE_CONFIG(j, i);
795            config_size--;
796            n++;
797        }
798    }
799
800    *num_config = n;
801    return EGL_TRUE;
802}
803
804EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
805                            EGLConfig *configs, EGLint config_size,
806                            EGLint *num_config)
807{
808    egl_display_t const * const dp = get_display(dpy);
809    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
810
811    if (num_config==0) {
812        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
813    }
814
815    EGLint n;
816    EGLBoolean res = EGL_FALSE;
817    *num_config = 0;
818
819
820    // It is unfortunate, but we need to remap the EGL_CONFIG_IDs,
821    // to do  this, we have to go through the attrib_list array once
822    // to figure out both its size and if it contains an EGL_CONFIG_ID
823    // key. If so, the full array is copied and patched.
824    // NOTE: we assume that there can be only one occurrence
825    // of EGL_CONFIG_ID.
826
827    EGLint patch_index = -1;
828    GLint attr;
829    size_t size = 0;
830    while ((attr=attrib_list[size]) != EGL_NONE) {
831        if (attr == EGL_CONFIG_ID)
832            patch_index = size;
833        size += 2;
834    }
835    if (patch_index >= 0) {
836        size += 2; // we need copy the sentinel as well
837        EGLint* new_list = (EGLint*)malloc(size*sizeof(EGLint));
838        if (new_list == 0)
839            return setError(EGL_BAD_ALLOC, EGL_FALSE);
840        memcpy(new_list, attrib_list, size*sizeof(EGLint));
841
842        // patch the requested EGL_CONFIG_ID
843        int i, index;
844        EGLint& configId(new_list[patch_index+1]);
845        uniqueIdToConfig(dp, configId, i, index);
846
847        egl_connection_t* const cnx = &gEGLImpl[i];
848        if (cnx->dso) {
849            cnx->egl.eglGetConfigAttrib(
850                    dp->disp[i].dpy, dp->disp[i].config[index],
851                    EGL_CONFIG_ID, &configId);
852
853            // and switch to the new list
854            attrib_list = const_cast<const EGLint *>(new_list);
855
856            // At this point, the only configuration that can match is
857            // dp->configs[i][index], however, we don't know if it would be
858            // rejected because of the other attributes, so we do have to call
859            // cnx->egl.eglChooseConfig() -- but we don't have to loop
860            // through all the EGLimpl[].
861            // We also know we can only get a single config back, and we know
862            // which one.
863
864            res = cnx->egl.eglChooseConfig(
865                    dp->disp[i].dpy, attrib_list, configs, config_size, &n);
866            if (res && n>0) {
867                // n has to be 0 or 1, by construction, and we already know
868                // which config it will return (since there can be only one).
869                if (configs) {
870                    configs[0] = MAKE_CONFIG(i, index);
871                }
872                *num_config = 1;
873            }
874        }
875
876        free(const_cast<EGLint *>(attrib_list));
877        return res;
878    }
879
880    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
881        egl_connection_t* const cnx = &gEGLImpl[i];
882        if (cnx->dso) {
883            if (cnx->egl.eglChooseConfig(
884                    dp->disp[i].dpy, attrib_list, configs, config_size, &n)) {
885                if (configs) {
886                    // now we need to convert these client EGLConfig to our
887                    // internal EGLConfig format. This is done in O(n log n).
888                    for (int j=0 ; j<n ; j++) {
889                        int index = binarySearch<EGLConfig>(
890                                dp->disp[i].config, 0,
891                                dp->disp[i].numConfigs-1, configs[j]);
892                        if (index >= 0) {
893                            if (configs) {
894                                configs[j] = MAKE_CONFIG(i, index);
895                            }
896                        } else {
897                            return setError(EGL_BAD_CONFIG, EGL_FALSE);
898                        }
899                    }
900                    configs += n;
901                    config_size -= n;
902                }
903                *num_config += n;
904                res = EGL_TRUE;
905            }
906        }
907    }
908    return res;
909}
910
911EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
912        EGLint attribute, EGLint *value)
913{
914    egl_display_t const* dp = 0;
915    int i=0, index=0;
916    egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
917    if (!cnx) return EGL_FALSE;
918
919    if (attribute == EGL_CONFIG_ID) {
920        // EGL_CONFIG_IDs must be unique, just use the order of the selected
921        // EGLConfig.
922        *value = configToUniqueId(dp, i, index);
923        return EGL_TRUE;
924    }
925    return cnx->egl.eglGetConfigAttrib(
926            dp->disp[i].dpy, dp->disp[i].config[index], attribute, value);
927}
928
929// ----------------------------------------------------------------------------
930// surfaces
931// ----------------------------------------------------------------------------
932
933EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
934                                    NativeWindowType window,
935                                    const EGLint *attrib_list)
936{
937    egl_display_t const* dp = 0;
938    int i=0, index=0;
939    egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
940    if (cnx) {
941        EGLSurface surface = cnx->egl.eglCreateWindowSurface(
942                dp->disp[i].dpy, dp->disp[i].config[index], window, attrib_list);
943        if (surface != EGL_NO_SURFACE) {
944            egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
945            return s;
946        }
947    }
948    return EGL_NO_SURFACE;
949}
950
951EGLSurface eglCreatePixmapSurface(  EGLDisplay dpy, EGLConfig config,
952                                    NativePixmapType pixmap,
953                                    const EGLint *attrib_list)
954{
955    egl_display_t const* dp = 0;
956    int i=0, index=0;
957    egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
958    if (cnx) {
959        EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
960                dp->disp[i].dpy, dp->disp[i].config[index], pixmap, attrib_list);
961        if (surface != EGL_NO_SURFACE) {
962            egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
963            return s;
964        }
965    }
966    return EGL_NO_SURFACE;
967}
968
969EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
970                                    const EGLint *attrib_list)
971{
972    egl_display_t const* dp = 0;
973    int i=0, index=0;
974    egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
975    if (cnx) {
976        EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
977                dp->disp[i].dpy, dp->disp[i].config[index], attrib_list);
978        if (surface != EGL_NO_SURFACE) {
979            egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
980            return s;
981        }
982    }
983    return EGL_NO_SURFACE;
984}
985
986EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
987{
988    SurfaceRef _s(surface);
989    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
990
991    if (!validate_display_surface(dpy, surface))
992        return EGL_FALSE;
993    egl_display_t const * const dp = get_display(dpy);
994
995    egl_surface_t * const s = get_surface(surface);
996    EGLBoolean result = s->cnx->egl.eglDestroySurface(
997            dp->disp[s->impl].dpy, s->surface);
998    if (result == EGL_TRUE) {
999        _s.terminate();
1000    }
1001    return result;
1002}
1003
1004EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
1005                            EGLint attribute, EGLint *value)
1006{
1007    SurfaceRef _s(surface);
1008    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1009
1010    if (!validate_display_surface(dpy, surface))
1011        return EGL_FALSE;
1012    egl_display_t const * const dp = get_display(dpy);
1013    egl_surface_t const * const s = get_surface(surface);
1014
1015    return s->cnx->egl.eglQuerySurface(
1016            dp->disp[s->impl].dpy, s->surface, attribute, value);
1017}
1018
1019// ----------------------------------------------------------------------------
1020// contextes
1021// ----------------------------------------------------------------------------
1022
1023EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
1024                            EGLContext share_list, const EGLint *attrib_list)
1025{
1026    egl_display_t const* dp = 0;
1027    int i=0, index=0;
1028    egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
1029    if (cnx) {
1030        EGLContext context = cnx->egl.eglCreateContext(
1031                dp->disp[i].dpy, dp->disp[i].config[index],
1032                share_list, attrib_list);
1033        if (context != EGL_NO_CONTEXT) {
1034            // figure out if it's a GLESv1 or GLESv2
1035            int version = 0;
1036            if (attrib_list) {
1037                while (*attrib_list != EGL_NONE) {
1038                    GLint attr = *attrib_list++;
1039                    GLint value = *attrib_list++;
1040                    if (attr == EGL_CONTEXT_CLIENT_VERSION) {
1041                        if (value == 1) {
1042                            version = GLESv1_INDEX;
1043                        } else if (value == 2) {
1044                            version = GLESv2_INDEX;
1045                        }
1046                    }
1047                };
1048            }
1049            egl_context_t* c = new egl_context_t(dpy, context, i, cnx, version);
1050            return c;
1051        }
1052    }
1053    return EGL_NO_CONTEXT;
1054}
1055
1056EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1057{
1058    ContextRef _c(ctx);
1059    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1060
1061    if (!validate_display_context(dpy, ctx))
1062        return EGL_FALSE;
1063    egl_display_t const * const dp = get_display(dpy);
1064    egl_context_t * const c = get_context(ctx);
1065    EGLBoolean result = c->cnx->egl.eglDestroyContext(
1066            dp->disp[c->impl].dpy, c->context);
1067    if (result == EGL_TRUE) {
1068        _c.terminate();
1069    }
1070    return result;
1071}
1072
1073EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
1074                            EGLSurface read, EGLContext ctx)
1075{
1076    // get a reference to the object passed in
1077    ContextRef _c(ctx);
1078    SurfaceRef _d(draw);
1079    SurfaceRef _r(read);
1080
1081    // validate the display and the context (if not EGL_NO_CONTEXT)
1082    egl_display_t const * const dp = get_display(dpy);
1083    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1084    if ((ctx != EGL_NO_CONTEXT) && (!validate_display_context(dpy, ctx))) {
1085        // EGL_NO_CONTEXT is valid
1086        return EGL_FALSE;
1087    }
1088
1089    // these are the underlying implementation's object
1090    EGLContext impl_ctx  = EGL_NO_CONTEXT;
1091    EGLSurface impl_draw = EGL_NO_SURFACE;
1092    EGLSurface impl_read = EGL_NO_SURFACE;
1093
1094    // these are our objects structs passed in
1095    egl_context_t       * c = NULL;
1096    egl_surface_t const * d = NULL;
1097    egl_surface_t const * r = NULL;
1098
1099    // these are the current objects structs
1100    egl_context_t * cur_c = get_context(getContext());
1101    egl_surface_t * cur_r = NULL;
1102    egl_surface_t * cur_d = NULL;
1103
1104    if (ctx != EGL_NO_CONTEXT) {
1105        c = get_context(ctx);
1106        cur_r = get_surface(c->read);
1107        cur_d = get_surface(c->draw);
1108        impl_ctx = c->context;
1109    } else {
1110        // no context given, use the implementation of the current context
1111        if (cur_c == NULL) {
1112            // no current context
1113            if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
1114                // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
1115                return setError(EGL_BAD_MATCH, EGL_FALSE);
1116            }
1117            // not an error, there is just no current context.
1118            return EGL_TRUE;
1119        }
1120    }
1121
1122    // retrieve the underlying implementation's draw EGLSurface
1123    if (draw != EGL_NO_SURFACE) {
1124        d = get_surface(draw);
1125        // make sure the EGLContext and EGLSurface passed in are for
1126        // the same driver
1127        if (c && d->impl != c->impl)
1128            return setError(EGL_BAD_MATCH, EGL_FALSE);
1129        impl_draw = d->surface;
1130    }
1131
1132    // retrieve the underlying implementation's read EGLSurface
1133    if (read != EGL_NO_SURFACE) {
1134        r = get_surface(read);
1135        // make sure the EGLContext and EGLSurface passed in are for
1136        // the same driver
1137        if (c && r->impl != c->impl)
1138            return setError(EGL_BAD_MATCH, EGL_FALSE);
1139        impl_read = r->surface;
1140    }
1141
1142    EGLBoolean result;
1143
1144    if (c) {
1145        result = c->cnx->egl.eglMakeCurrent(
1146                dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
1147    } else {
1148        result = cur_c->cnx->egl.eglMakeCurrent(
1149                dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
1150    }
1151
1152    if (result == EGL_TRUE) {
1153        // by construction, these are either 0 or valid (possibly terminated)
1154        // it should be impossible for these to be invalid
1155        ContextRef _cur_c(cur_c);
1156        SurfaceRef _cur_r(cur_r);
1157        SurfaceRef _cur_d(cur_d);
1158
1159        // cur_c has to be valid here (but could be terminated)
1160        if (ctx != EGL_NO_CONTEXT) {
1161            setGlThreadSpecific(c->cnx->hooks[c->version]);
1162            setContext(ctx);
1163            _c.acquire();
1164        } else {
1165            setGlThreadSpecific(&gHooksNoContext);
1166            setContext(EGL_NO_CONTEXT);
1167        }
1168        _cur_c.release();
1169
1170        _r.acquire();
1171        _cur_r.release();
1172        if (c) c->read = read;
1173
1174        _d.acquire();
1175        _cur_d.release();
1176        if (c) c->draw = draw;
1177    }
1178    return result;
1179}
1180
1181
1182EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
1183                            EGLint attribute, EGLint *value)
1184{
1185    ContextRef _c(ctx);
1186    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1187
1188    if (!validate_display_context(dpy, ctx))
1189        return EGL_FALSE;
1190
1191    egl_display_t const * const dp = get_display(dpy);
1192    egl_context_t * const c = get_context(ctx);
1193
1194    return c->cnx->egl.eglQueryContext(
1195            dp->disp[c->impl].dpy, c->context, attribute, value);
1196}
1197
1198EGLContext eglGetCurrentContext(void)
1199{
1200    // could be called before eglInitialize(), but we wouldn't have a context
1201    // then, and this function would correctly return EGL_NO_CONTEXT.
1202
1203    EGLContext ctx = getContext();
1204    return ctx;
1205}
1206
1207EGLSurface eglGetCurrentSurface(EGLint readdraw)
1208{
1209    // could be called before eglInitialize(), but we wouldn't have a context
1210    // then, and this function would correctly return EGL_NO_SURFACE.
1211
1212    EGLContext ctx = getContext();
1213    if (ctx) {
1214        egl_context_t const * const c = get_context(ctx);
1215        if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1216        switch (readdraw) {
1217            case EGL_READ: return c->read;
1218            case EGL_DRAW: return c->draw;
1219            default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1220        }
1221    }
1222    return EGL_NO_SURFACE;
1223}
1224
1225EGLDisplay eglGetCurrentDisplay(void)
1226{
1227    // could be called before eglInitialize(), but we wouldn't have a context
1228    // then, and this function would correctly return EGL_NO_DISPLAY.
1229
1230    EGLContext ctx = getContext();
1231    if (ctx) {
1232        egl_context_t const * const c = get_context(ctx);
1233        if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1234        return c->dpy;
1235    }
1236    return EGL_NO_DISPLAY;
1237}
1238
1239EGLBoolean eglWaitGL(void)
1240{
1241    // could be called before eglInitialize(), but we wouldn't have a context
1242    // then, and this function would return GL_TRUE, which isn't wrong.
1243
1244    EGLBoolean res = EGL_TRUE;
1245    EGLContext ctx = getContext();
1246    if (ctx) {
1247        egl_context_t const * const c = get_context(ctx);
1248        if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1249        if (uint32_t(c->impl)>=2)
1250            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1251        egl_connection_t* const cnx = &gEGLImpl[c->impl];
1252        if (!cnx->dso)
1253            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1254        res = cnx->egl.eglWaitGL();
1255    }
1256    return res;
1257}
1258
1259EGLBoolean eglWaitNative(EGLint engine)
1260{
1261    // could be called before eglInitialize(), but we wouldn't have a context
1262    // then, and this function would return GL_TRUE, which isn't wrong.
1263
1264    EGLBoolean res = EGL_TRUE;
1265    EGLContext ctx = getContext();
1266    if (ctx) {
1267        egl_context_t const * const c = get_context(ctx);
1268        if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1269        if (uint32_t(c->impl)>=2)
1270            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1271        egl_connection_t* const cnx = &gEGLImpl[c->impl];
1272        if (!cnx->dso)
1273            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1274        res = cnx->egl.eglWaitNative(engine);
1275    }
1276    return res;
1277}
1278
1279EGLint eglGetError(void)
1280{
1281    EGLint result = EGL_SUCCESS;
1282    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1283        EGLint err = EGL_SUCCESS;
1284        egl_connection_t* const cnx = &gEGLImpl[i];
1285        if (cnx->dso)
1286            err = cnx->egl.eglGetError();
1287        if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
1288            result = err;
1289    }
1290    if (result == EGL_SUCCESS)
1291        result = getError();
1292    return result;
1293}
1294
1295__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
1296{
1297    // eglGetProcAddress() could be the very first function called
1298    // in which case we must make sure we've initialized ourselves, this
1299    // happens the first time egl_get_display() is called.
1300
1301    if (egl_init_drivers() == EGL_FALSE) {
1302        setError(EGL_BAD_PARAMETER, NULL);
1303        return  NULL;
1304    }
1305
1306    __eglMustCastToProperFunctionPointerType addr;
1307    addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap));
1308    if (addr) return addr;
1309
1310    return NULL; // TODO: finish implementation below
1311
1312    addr = findProcAddress(procname, gGLExtentionMap, NELEM(gGLExtentionMap));
1313    if (addr) return addr;
1314
1315    addr = 0;
1316    int slot = -1;
1317    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1318        egl_connection_t* const cnx = &gEGLImpl[i];
1319        if (cnx->dso) {
1320            if (cnx->egl.eglGetProcAddress) {
1321                addr = cnx->egl.eglGetProcAddress(procname);
1322                if (addr) {
1323                    if (slot == -1) {
1324                        slot = 0; // XXX: find free slot
1325                        if (slot == -1) {
1326                            addr = 0;
1327                            break;
1328                        }
1329                    }
1330                    //cnx->hooks->ext.extensions[slot] = addr;
1331                }
1332            }
1333        }
1334    }
1335
1336    if (slot >= 0) {
1337        addr = 0; // XXX: address of stub 'slot'
1338        gGLExtentionMap[slot].name = strdup(procname);
1339        gGLExtentionMap[slot].address = addr;
1340    }
1341
1342    return addr;
1343
1344
1345    /*
1346     *  TODO: For OpenGL ES extensions, we must generate a stub
1347     *  that looks like
1348     *      mov     r12, #0xFFFF0FFF
1349     *      ldr     r12, [r12, #-15]
1350     *      ldr     r12, [r12, #TLS_SLOT_OPENGL_API*4]
1351     *      mov     r12, [r12, #api_offset]
1352     *      ldrne   pc, r12
1353     *      mov     pc, #unsupported_extension
1354     *
1355     *  and write the address of the extension in *all*
1356     *  gl_hooks_t::gl_ext_t at offset "api_offset" from gl_hooks_t
1357     *
1358     */
1359}
1360
1361EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
1362{
1363    SurfaceRef _s(draw);
1364    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1365
1366    if (!validate_display_surface(dpy, draw))
1367        return EGL_FALSE;
1368    egl_display_t const * const dp = get_display(dpy);
1369    egl_surface_t const * const s = get_surface(draw);
1370    return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
1371}
1372
1373EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface surface,
1374                            NativePixmapType target)
1375{
1376    SurfaceRef _s(surface);
1377    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1378
1379    if (!validate_display_surface(dpy, surface))
1380        return EGL_FALSE;
1381    egl_display_t const * const dp = get_display(dpy);
1382    egl_surface_t const * const s = get_surface(surface);
1383    return s->cnx->egl.eglCopyBuffers(
1384            dp->disp[s->impl].dpy, s->surface, target);
1385}
1386
1387const char* eglQueryString(EGLDisplay dpy, EGLint name)
1388{
1389    egl_display_t const * const dp = get_display(dpy);
1390    switch (name) {
1391        case EGL_VENDOR:
1392            return gVendorString;
1393        case EGL_VERSION:
1394            return gVersionString;
1395        case EGL_EXTENSIONS:
1396            return gExtensionString;
1397        case EGL_CLIENT_APIS:
1398            return gClientApiString;
1399    }
1400    return setError(EGL_BAD_PARAMETER, (const char *)0);
1401}
1402
1403
1404// ----------------------------------------------------------------------------
1405// EGL 1.1
1406// ----------------------------------------------------------------------------
1407
1408EGLBoolean eglSurfaceAttrib(
1409        EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1410{
1411    SurfaceRef _s(surface);
1412    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1413
1414    if (!validate_display_surface(dpy, surface))
1415        return EGL_FALSE;
1416    egl_display_t const * const dp = get_display(dpy);
1417    egl_surface_t const * const s = get_surface(surface);
1418    if (s->cnx->egl.eglSurfaceAttrib) {
1419        return s->cnx->egl.eglSurfaceAttrib(
1420                dp->disp[s->impl].dpy, s->surface, attribute, value);
1421    }
1422    return setError(EGL_BAD_SURFACE, EGL_FALSE);
1423}
1424
1425EGLBoolean eglBindTexImage(
1426        EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1427{
1428    SurfaceRef _s(surface);
1429    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1430
1431    if (!validate_display_surface(dpy, surface))
1432        return EGL_FALSE;
1433    egl_display_t const * const dp = get_display(dpy);
1434    egl_surface_t const * const s = get_surface(surface);
1435    if (s->cnx->egl.eglBindTexImage) {
1436        return s->cnx->egl.eglBindTexImage(
1437                dp->disp[s->impl].dpy, s->surface, buffer);
1438    }
1439    return setError(EGL_BAD_SURFACE, EGL_FALSE);
1440}
1441
1442EGLBoolean eglReleaseTexImage(
1443        EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1444{
1445    SurfaceRef _s(surface);
1446    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1447
1448    if (!validate_display_surface(dpy, surface))
1449        return EGL_FALSE;
1450    egl_display_t const * const dp = get_display(dpy);
1451    egl_surface_t const * const s = get_surface(surface);
1452    if (s->cnx->egl.eglReleaseTexImage) {
1453        return s->cnx->egl.eglReleaseTexImage(
1454                dp->disp[s->impl].dpy, s->surface, buffer);
1455    }
1456    return setError(EGL_BAD_SURFACE, EGL_FALSE);
1457}
1458
1459EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1460{
1461    egl_display_t * const dp = get_display(dpy);
1462    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1463
1464    EGLBoolean res = EGL_TRUE;
1465    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1466        egl_connection_t* const cnx = &gEGLImpl[i];
1467        if (cnx->dso) {
1468            if (cnx->egl.eglSwapInterval) {
1469                if (cnx->egl.eglSwapInterval(
1470                        dp->disp[i].dpy, interval) == EGL_FALSE) {
1471                    res = EGL_FALSE;
1472                }
1473            }
1474        }
1475    }
1476    return res;
1477}
1478
1479
1480// ----------------------------------------------------------------------------
1481// EGL 1.2
1482// ----------------------------------------------------------------------------
1483
1484EGLBoolean eglWaitClient(void)
1485{
1486    // could be called before eglInitialize(), but we wouldn't have a context
1487    // then, and this function would return GL_TRUE, which isn't wrong.
1488    EGLBoolean res = EGL_TRUE;
1489    EGLContext ctx = getContext();
1490    if (ctx) {
1491        egl_context_t const * const c = get_context(ctx);
1492        if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1493        if (uint32_t(c->impl)>=2)
1494            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1495        egl_connection_t* const cnx = &gEGLImpl[c->impl];
1496        if (!cnx->dso)
1497            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1498        if (cnx->egl.eglWaitClient) {
1499            res = cnx->egl.eglWaitClient();
1500        } else {
1501            res = cnx->egl.eglWaitGL();
1502        }
1503    }
1504    return res;
1505}
1506
1507EGLBoolean eglBindAPI(EGLenum api)
1508{
1509    if (egl_init_drivers() == EGL_FALSE) {
1510        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1511    }
1512
1513    // bind this API on all EGLs
1514    EGLBoolean res = EGL_TRUE;
1515    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1516        egl_connection_t* const cnx = &gEGLImpl[i];
1517        if (cnx->dso) {
1518            if (cnx->egl.eglBindAPI) {
1519                if (cnx->egl.eglBindAPI(api) == EGL_FALSE) {
1520                    res = EGL_FALSE;
1521                }
1522            }
1523        }
1524    }
1525    return res;
1526}
1527
1528EGLenum eglQueryAPI(void)
1529{
1530    if (egl_init_drivers() == EGL_FALSE) {
1531        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1532    }
1533
1534    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1535        egl_connection_t* const cnx = &gEGLImpl[i];
1536        if (cnx->dso) {
1537            if (cnx->egl.eglQueryAPI) {
1538                // the first one we find is okay, because they all
1539                // should be the same
1540                return cnx->egl.eglQueryAPI();
1541            }
1542        }
1543    }
1544    // or, it can only be OpenGL ES
1545    return EGL_OPENGL_ES_API;
1546}
1547
1548EGLBoolean eglReleaseThread(void)
1549{
1550    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1551        egl_connection_t* const cnx = &gEGLImpl[i];
1552        if (cnx->dso) {
1553            if (cnx->egl.eglReleaseThread) {
1554                cnx->egl.eglReleaseThread();
1555            }
1556        }
1557    }
1558    clearTLS();
1559    return EGL_TRUE;
1560}
1561
1562EGLSurface eglCreatePbufferFromClientBuffer(
1563          EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1564          EGLConfig config, const EGLint *attrib_list)
1565{
1566    egl_display_t const* dp = 0;
1567    int i=0, index=0;
1568    egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
1569    if (!cnx) return EGL_FALSE;
1570    if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1571        return cnx->egl.eglCreatePbufferFromClientBuffer(
1572                dp->disp[i].dpy, buftype, buffer,
1573                dp->disp[i].config[index], attrib_list);
1574    }
1575    return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1576}
1577
1578// ----------------------------------------------------------------------------
1579// EGL_EGLEXT_VERSION 3
1580// ----------------------------------------------------------------------------
1581
1582EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1583        const EGLint *attrib_list)
1584{
1585    SurfaceRef _s(surface);
1586    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1587
1588    if (!validate_display_surface(dpy, surface))
1589        return EGL_FALSE;
1590
1591    egl_display_t const * const dp = get_display(dpy);
1592    egl_surface_t const * const s = get_surface(surface);
1593
1594    if (s->cnx->egl.eglLockSurfaceKHR) {
1595        return s->cnx->egl.eglLockSurfaceKHR(
1596                dp->disp[s->impl].dpy, s->surface, attrib_list);
1597    }
1598    return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1599}
1600
1601EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1602{
1603    SurfaceRef _s(surface);
1604    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1605
1606    if (!validate_display_surface(dpy, surface))
1607        return EGL_FALSE;
1608
1609    egl_display_t const * const dp = get_display(dpy);
1610    egl_surface_t const * const s = get_surface(surface);
1611
1612    if (s->cnx->egl.eglUnlockSurfaceKHR) {
1613        return s->cnx->egl.eglUnlockSurfaceKHR(
1614                dp->disp[s->impl].dpy, s->surface);
1615    }
1616    return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1617}
1618
1619EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1620        EGLClientBuffer buffer, const EGLint *attrib_list)
1621{
1622    if (ctx != EGL_NO_CONTEXT) {
1623        ContextRef _c(ctx);
1624        if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1625        if (!validate_display_context(dpy, ctx))
1626            return EGL_NO_IMAGE_KHR;
1627        egl_display_t const * const dp = get_display(dpy);
1628        egl_context_t * const c = get_context(ctx);
1629        // since we have an EGLContext, we know which implementation to use
1630        EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
1631                dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
1632        if (image == EGL_NO_IMAGE_KHR)
1633            return image;
1634
1635        egl_image_t* result = new egl_image_t(dpy, ctx);
1636        result->images[c->impl] = image;
1637        return (EGLImageKHR)result;
1638    } else {
1639        // EGL_NO_CONTEXT is a valid parameter
1640        egl_display_t const * const dp = get_display(dpy);
1641        if (dp == 0) {
1642            return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
1643        }
1644
1645        /* Since we don't have a way to know which implementation to call,
1646         * we're calling all of them. If at least one of the implementation
1647         * succeeded, this is a success.
1648         */
1649
1650        EGLint currentError = eglGetError();
1651
1652        EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS];
1653        bool success = false;
1654        for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1655            egl_connection_t* const cnx = &gEGLImpl[i];
1656            implImages[i] = EGL_NO_IMAGE_KHR;
1657            if (cnx->dso) {
1658                if (cnx->egl.eglCreateImageKHR) {
1659                    implImages[i] = cnx->egl.eglCreateImageKHR(
1660                            dp->disp[i].dpy, ctx, target, buffer, attrib_list);
1661                    if (implImages[i] != EGL_NO_IMAGE_KHR) {
1662                        success = true;
1663                    }
1664                }
1665            }
1666        }
1667
1668        if (!success) {
1669            // failure, if there was an error when we entered this function,
1670            // the error flag must not be updated.
1671            // Otherwise, the error is whatever happened in the implementation
1672            // that faulted.
1673            if (currentError != EGL_SUCCESS) {
1674                setError(currentError, EGL_NO_IMAGE_KHR);
1675            }
1676            return EGL_NO_IMAGE_KHR;
1677        } else {
1678            // In case of success, we need to clear all error flags
1679            // (especially those caused by the implementation that didn't
1680            // succeed). TODO: we could avoid this if we knew this was
1681            // a "full" success (all implementation succeeded).
1682            eglGetError();
1683        }
1684
1685        egl_image_t* result = new egl_image_t(dpy, ctx);
1686        memcpy(result->images, implImages, sizeof(implImages));
1687        return (EGLImageKHR)result;
1688    }
1689}
1690
1691EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1692{
1693    egl_display_t const * const dp = get_display(dpy);
1694     if (dp == 0) {
1695         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1696     }
1697
1698     ImageRef _i(img);
1699     if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1700
1701     egl_image_t* image = get_image(img);
1702     bool success = false;
1703     for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1704         egl_connection_t* const cnx = &gEGLImpl[i];
1705         if (image->images[i] != EGL_NO_IMAGE_KHR) {
1706             if (cnx->dso) {
1707                 if (cnx->egl.eglCreateImageKHR) {
1708                     if (cnx->egl.eglDestroyImageKHR(
1709                             dp->disp[i].dpy, image->images[i])) {
1710                         success = true;
1711                     }
1712                 }
1713             }
1714         }
1715     }
1716     if (!success)
1717         return EGL_FALSE;
1718
1719     _i.terminate();
1720
1721     return EGL_TRUE;
1722}
1723
1724
1725// ----------------------------------------------------------------------------
1726// ANDROID extensions
1727// ----------------------------------------------------------------------------
1728
1729EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
1730        EGLint left, EGLint top, EGLint width, EGLint height)
1731{
1732    SurfaceRef _s(draw);
1733    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1734
1735    if (!validate_display_surface(dpy, draw))
1736        return EGL_FALSE;
1737    egl_display_t const * const dp = get_display(dpy);
1738    egl_surface_t const * const s = get_surface(draw);
1739    if (s->cnx->egl.eglSetSwapRectangleANDROID) {
1740        return s->cnx->egl.eglSetSwapRectangleANDROID(
1741                dp->disp[s->impl].dpy, s->surface, left, top, width, height);
1742    }
1743    return setError(EGL_BAD_DISPLAY, NULL);
1744}
1745
1746EGLClientBuffer eglGetRenderBufferANDROID(EGLDisplay dpy, EGLSurface draw)
1747{
1748    SurfaceRef _s(draw);
1749    if (!_s.get()) return setError(EGL_BAD_SURFACE, (EGLClientBuffer*)0);
1750
1751    if (!validate_display_surface(dpy, draw))
1752        return 0;
1753    egl_display_t const * const dp = get_display(dpy);
1754    egl_surface_t const * const s = get_surface(draw);
1755    if (s->cnx->egl.eglGetRenderBufferANDROID) {
1756        return s->cnx->egl.eglGetRenderBufferANDROID(
1757                dp->disp[s->impl].dpy, s->surface);
1758    }
1759    return setError(EGL_BAD_DISPLAY, (EGLClientBuffer*)0);
1760}
1761