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