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