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