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