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