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