egl.cpp revision 85f33a7168c5563aa7765b91d5d045fe62bcfcd8
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        // set the native window's buffers format to match this config
1136        if (cnx->egl.eglGetConfigAttrib(iDpy,
1137                iConfig, EGL_NATIVE_VISUAL_ID, &format)) {
1138            if (format != 0) {
1139                native_window_set_buffers_geometry(window, 0, 0, format);
1140            }
1141        }
1142
1143        EGLSurface surface = cnx->egl.eglCreateWindowSurface(
1144                iDpy, iConfig, window, attrib_list);
1145        if (surface != EGL_NO_SURFACE) {
1146            egl_surface_t* s = new egl_surface_t(dpy, config, window, surface,
1147                    dp->configs[intptr_t(config)].impl, cnx);
1148            return s;
1149        }
1150    }
1151    return EGL_NO_SURFACE;
1152}
1153
1154EGLSurface eglCreatePixmapSurface(  EGLDisplay dpy, EGLConfig config,
1155                                    NativePixmapType pixmap,
1156                                    const EGLint *attrib_list)
1157{
1158    clearError();
1159
1160    egl_display_t const* dp = 0;
1161    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
1162    if (cnx) {
1163        EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
1164                dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1165                dp->configs[intptr_t(config)].config, pixmap, attrib_list);
1166        if (surface != EGL_NO_SURFACE) {
1167            egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
1168                    dp->configs[intptr_t(config)].impl, cnx);
1169            return s;
1170        }
1171    }
1172    return EGL_NO_SURFACE;
1173}
1174
1175EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
1176                                    const EGLint *attrib_list)
1177{
1178    clearError();
1179
1180    egl_display_t const* dp = 0;
1181    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
1182    if (cnx) {
1183        EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
1184                dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1185                dp->configs[intptr_t(config)].config, attrib_list);
1186        if (surface != EGL_NO_SURFACE) {
1187            egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
1188                    dp->configs[intptr_t(config)].impl, cnx);
1189            return s;
1190        }
1191    }
1192    return EGL_NO_SURFACE;
1193}
1194
1195EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
1196{
1197    clearError();
1198
1199    SurfaceRef _s(surface);
1200    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1201
1202    if (!validate_display_surface(dpy, surface))
1203        return EGL_FALSE;
1204    egl_display_t const * const dp = get_display(dpy);
1205
1206    egl_surface_t * const s = get_surface(surface);
1207    EGLBoolean result = s->cnx->egl.eglDestroySurface(
1208            dp->disp[s->impl].dpy, s->surface);
1209    if (result == EGL_TRUE) {
1210        if (s->win != NULL) {
1211            native_window_set_buffers_geometry(s->win.get(), 0, 0, 0);
1212        }
1213        _s.terminate();
1214    }
1215    return result;
1216}
1217
1218EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
1219                            EGLint attribute, EGLint *value)
1220{
1221    clearError();
1222
1223    SurfaceRef _s(surface);
1224    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1225
1226    if (!validate_display_surface(dpy, surface))
1227        return EGL_FALSE;
1228    egl_display_t const * const dp = get_display(dpy);
1229    egl_surface_t const * const s = get_surface(surface);
1230
1231    EGLBoolean result(EGL_TRUE);
1232    if (attribute == EGL_CONFIG_ID) {
1233        // We need to remap EGL_CONFIG_IDs
1234        *value = dp->configs[intptr_t(s->config)].configId;
1235    } else {
1236        result = s->cnx->egl.eglQuerySurface(
1237                dp->disp[s->impl].dpy, s->surface, attribute, value);
1238    }
1239
1240    return result;
1241}
1242
1243// ----------------------------------------------------------------------------
1244// Contexts
1245// ----------------------------------------------------------------------------
1246
1247EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
1248                            EGLContext share_list, const EGLint *attrib_list)
1249{
1250    clearError();
1251
1252    egl_display_t const* dp = 0;
1253    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
1254    if (cnx) {
1255        if (share_list != EGL_NO_CONTEXT) {
1256            egl_context_t* const c = get_context(share_list);
1257            share_list = c->context;
1258        }
1259        EGLContext context = cnx->egl.eglCreateContext(
1260                dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1261                dp->configs[intptr_t(config)].config,
1262                share_list, attrib_list);
1263        if (context != EGL_NO_CONTEXT) {
1264            // figure out if it's a GLESv1 or GLESv2
1265            int version = 0;
1266            if (attrib_list) {
1267                while (*attrib_list != EGL_NONE) {
1268                    GLint attr = *attrib_list++;
1269                    GLint value = *attrib_list++;
1270                    if (attr == EGL_CONTEXT_CLIENT_VERSION) {
1271                        if (value == 1) {
1272                            version = GLESv1_INDEX;
1273                        } else if (value == 2) {
1274                            version = GLESv2_INDEX;
1275                        }
1276                    }
1277                };
1278            }
1279            egl_context_t* c = new egl_context_t(dpy, context, config,
1280                    dp->configs[intptr_t(config)].impl, cnx, version);
1281            return c;
1282        }
1283    }
1284    return EGL_NO_CONTEXT;
1285}
1286
1287EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1288{
1289    clearError();
1290
1291    ContextRef _c(ctx);
1292    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1293
1294    if (!validate_display_context(dpy, ctx))
1295        return EGL_FALSE;
1296    egl_display_t const * const dp = get_display(dpy);
1297    egl_context_t * const c = get_context(ctx);
1298    EGLBoolean result = c->cnx->egl.eglDestroyContext(
1299            dp->disp[c->impl].dpy, c->context);
1300    if (result == EGL_TRUE) {
1301        _c.terminate();
1302    }
1303    return result;
1304}
1305
1306static void loseCurrent(egl_context_t * cur_c)
1307{
1308    if (cur_c) {
1309        egl_surface_t * cur_r = get_surface(cur_c->read);
1310        egl_surface_t * cur_d = get_surface(cur_c->draw);
1311
1312        // by construction, these are either 0 or valid (possibly terminated)
1313        // it should be impossible for these to be invalid
1314        ContextRef _cur_c(cur_c);
1315        SurfaceRef _cur_r(cur_r);
1316        SurfaceRef _cur_d(cur_d);
1317
1318        cur_c->read = NULL;
1319        cur_c->draw = NULL;
1320
1321        _cur_c.release();
1322        _cur_r.release();
1323        _cur_d.release();
1324    }
1325}
1326
1327EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
1328                            EGLSurface read, EGLContext ctx)
1329{
1330    clearError();
1331
1332    // get a reference to the object passed in
1333    ContextRef _c(ctx);
1334    SurfaceRef _d(draw);
1335    SurfaceRef _r(read);
1336
1337    // validate the display and the context (if not EGL_NO_CONTEXT)
1338    egl_display_t const * const dp = get_display(dpy);
1339    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1340    if ((ctx != EGL_NO_CONTEXT) && (!validate_display_context(dpy, ctx))) {
1341        // EGL_NO_CONTEXT is valid
1342        return EGL_FALSE;
1343    }
1344
1345    // these are the underlying implementation's object
1346    EGLContext impl_ctx  = EGL_NO_CONTEXT;
1347    EGLSurface impl_draw = EGL_NO_SURFACE;
1348    EGLSurface impl_read = EGL_NO_SURFACE;
1349
1350    // these are our objects structs passed in
1351    egl_context_t       * c = NULL;
1352    egl_surface_t const * d = NULL;
1353    egl_surface_t const * r = NULL;
1354
1355    // these are the current objects structs
1356    egl_context_t * cur_c = get_context(getContext());
1357
1358    if (ctx != EGL_NO_CONTEXT) {
1359        c = get_context(ctx);
1360        impl_ctx = c->context;
1361    } else {
1362        // no context given, use the implementation of the current context
1363        if (cur_c == NULL) {
1364            // no current context
1365            if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
1366                // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
1367                return setError(EGL_BAD_MATCH, EGL_FALSE);
1368            }
1369            // not an error, there is just no current context.
1370            return EGL_TRUE;
1371        }
1372    }
1373
1374    // retrieve the underlying implementation's draw EGLSurface
1375    if (draw != EGL_NO_SURFACE) {
1376        d = get_surface(draw);
1377        // make sure the EGLContext and EGLSurface passed in are for
1378        // the same driver
1379        if (c && d->impl != c->impl)
1380            return setError(EGL_BAD_MATCH, EGL_FALSE);
1381        impl_draw = d->surface;
1382    }
1383
1384    // retrieve the underlying implementation's read EGLSurface
1385    if (read != EGL_NO_SURFACE) {
1386        r = get_surface(read);
1387        // make sure the EGLContext and EGLSurface passed in are for
1388        // the same driver
1389        if (c && r->impl != c->impl)
1390            return setError(EGL_BAD_MATCH, EGL_FALSE);
1391        impl_read = r->surface;
1392    }
1393
1394    EGLBoolean result;
1395
1396    if (c) {
1397        result = c->cnx->egl.eglMakeCurrent(
1398                dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
1399    } else {
1400        result = cur_c->cnx->egl.eglMakeCurrent(
1401                dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
1402    }
1403
1404    if (result == EGL_TRUE) {
1405
1406        loseCurrent(cur_c);
1407
1408        if (ctx != EGL_NO_CONTEXT) {
1409            if (!c->dbg && gEGLDebugLevel > 0)
1410                c->dbg = CreateDbgContext(c->version, c->cnx->hooks[c->version]);
1411            setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
1412            setContext(ctx);
1413            _c.acquire();
1414            _r.acquire();
1415            _d.acquire();
1416            c->read = read;
1417            c->draw = draw;
1418        } else {
1419            setGLHooksThreadSpecific(&gHooksNoContext);
1420            setContext(EGL_NO_CONTEXT);
1421        }
1422    }
1423    return result;
1424}
1425
1426
1427EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
1428                            EGLint attribute, EGLint *value)
1429{
1430    clearError();
1431
1432    ContextRef _c(ctx);
1433    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1434
1435    if (!validate_display_context(dpy, ctx))
1436        return EGL_FALSE;
1437
1438    egl_display_t const * const dp = get_display(dpy);
1439    egl_context_t * const c = get_context(ctx);
1440
1441    EGLBoolean result(EGL_TRUE);
1442    if (attribute == EGL_CONFIG_ID) {
1443        *value = dp->configs[intptr_t(c->config)].configId;
1444    } else {
1445        // We need to remap EGL_CONFIG_IDs
1446        result = c->cnx->egl.eglQueryContext(
1447                dp->disp[c->impl].dpy, c->context, attribute, value);
1448    }
1449
1450    return result;
1451}
1452
1453EGLContext eglGetCurrentContext(void)
1454{
1455    // could be called before eglInitialize(), but we wouldn't have a context
1456    // then, and this function would correctly return EGL_NO_CONTEXT.
1457
1458    clearError();
1459
1460    EGLContext ctx = getContext();
1461    return ctx;
1462}
1463
1464EGLSurface eglGetCurrentSurface(EGLint readdraw)
1465{
1466    // could be called before eglInitialize(), but we wouldn't have a context
1467    // then, and this function would correctly return EGL_NO_SURFACE.
1468
1469    clearError();
1470
1471    EGLContext ctx = getContext();
1472    if (ctx) {
1473        egl_context_t const * const c = get_context(ctx);
1474        if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1475        switch (readdraw) {
1476            case EGL_READ: return c->read;
1477            case EGL_DRAW: return c->draw;
1478            default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1479        }
1480    }
1481    return EGL_NO_SURFACE;
1482}
1483
1484EGLDisplay eglGetCurrentDisplay(void)
1485{
1486    // could be called before eglInitialize(), but we wouldn't have a context
1487    // then, and this function would correctly return EGL_NO_DISPLAY.
1488
1489    clearError();
1490
1491    EGLContext ctx = getContext();
1492    if (ctx) {
1493        egl_context_t const * const c = get_context(ctx);
1494        if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1495        return c->dpy;
1496    }
1497    return EGL_NO_DISPLAY;
1498}
1499
1500EGLBoolean eglWaitGL(void)
1501{
1502    // could be called before eglInitialize(), but we wouldn't have a context
1503    // then, and this function would return GL_TRUE, which isn't wrong.
1504
1505    clearError();
1506
1507    EGLBoolean res = EGL_TRUE;
1508    EGLContext ctx = getContext();
1509    if (ctx) {
1510        egl_context_t const * const c = get_context(ctx);
1511        if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1512        if (uint32_t(c->impl)>=2)
1513            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1514        egl_connection_t* const cnx = &gEGLImpl[c->impl];
1515        if (!cnx->dso)
1516            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1517        res = cnx->egl.eglWaitGL();
1518    }
1519    return res;
1520}
1521
1522EGLBoolean eglWaitNative(EGLint engine)
1523{
1524    // could be called before eglInitialize(), but we wouldn't have a context
1525    // then, and this function would return GL_TRUE, which isn't wrong.
1526
1527    clearError();
1528
1529    EGLBoolean res = EGL_TRUE;
1530    EGLContext ctx = getContext();
1531    if (ctx) {
1532        egl_context_t const * const c = get_context(ctx);
1533        if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1534        if (uint32_t(c->impl)>=2)
1535            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1536        egl_connection_t* const cnx = &gEGLImpl[c->impl];
1537        if (!cnx->dso)
1538            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1539        res = cnx->egl.eglWaitNative(engine);
1540    }
1541    return res;
1542}
1543
1544EGLint eglGetError(void)
1545{
1546    EGLint result = EGL_SUCCESS;
1547    EGLint err;
1548    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1549        err = EGL_SUCCESS;
1550        egl_connection_t* const cnx = &gEGLImpl[i];
1551        if (cnx->dso)
1552            err = cnx->egl.eglGetError();
1553        if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
1554            result = err;
1555    }
1556    err = getError();
1557    if (result == EGL_SUCCESS)
1558        result = err;
1559    return result;
1560}
1561
1562// Note: Similar implementations of these functions also exist in
1563// gl2.cpp and gl.cpp, and are used by applications that call the
1564// exported entry points directly.
1565typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
1566typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
1567
1568static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL;
1569static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL;
1570
1571static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image)
1572{
1573    GLeglImageOES implImage =
1574        (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
1575    glEGLImageTargetTexture2DOES_impl(target, implImage);
1576}
1577
1578static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image)
1579{
1580    GLeglImageOES implImage =
1581        (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
1582    glEGLImageTargetRenderbufferStorageOES_impl(target, implImage);
1583}
1584
1585__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
1586{
1587    // eglGetProcAddress() could be the very first function called
1588    // in which case we must make sure we've initialized ourselves, this
1589    // happens the first time egl_get_display() is called.
1590
1591    clearError();
1592
1593    if (egl_init_drivers() == EGL_FALSE) {
1594        setError(EGL_BAD_PARAMETER, NULL);
1595        return  NULL;
1596    }
1597
1598    __eglMustCastToProperFunctionPointerType addr;
1599    addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap));
1600    if (addr) return addr;
1601
1602    // this protects accesses to gGLExtentionMap and gGLExtentionSlot
1603    pthread_mutex_lock(&gInitDriverMutex);
1604
1605        /*
1606         * Since eglGetProcAddress() is not associated to anything, it needs
1607         * to return a function pointer that "works" regardless of what
1608         * the current context is.
1609         *
1610         * For this reason, we return a "forwarder", a small stub that takes
1611         * care of calling the function associated with the context
1612         * currently bound.
1613         *
1614         * We first look for extensions we've already resolved, if we're seeing
1615         * this extension for the first time, we go through all our
1616         * implementations and call eglGetProcAddress() and record the
1617         * result in the appropriate implementation hooks and return the
1618         * address of the forwarder corresponding to that hook set.
1619         *
1620         */
1621
1622        const String8 name(procname);
1623        addr = gGLExtentionMap.valueFor(name);
1624        const int slot = gGLExtentionSlot;
1625
1626        LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
1627                "no more slots for eglGetProcAddress(\"%s\")",
1628                procname);
1629
1630        if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
1631            bool found = false;
1632            for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1633                egl_connection_t* const cnx = &gEGLImpl[i];
1634                if (cnx->dso && cnx->egl.eglGetProcAddress) {
1635                    found = true;
1636                    // Extensions are independent of the bound context
1637                    cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
1638                    cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
1639#if EGL_TRACE
1640                    gHooksDebug.ext.extensions[slot] = gHooksTrace.ext.extensions[slot] =
1641#endif
1642                            cnx->egl.eglGetProcAddress(procname);
1643                }
1644            }
1645            if (found) {
1646                addr = gExtensionForwarders[slot];
1647
1648                if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) {
1649                    glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr;
1650                    addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper;
1651                }
1652                if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) {
1653                    glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr;
1654                    addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper;
1655                }
1656
1657                gGLExtentionMap.add(name, addr);
1658                gGLExtentionSlot++;
1659            }
1660        }
1661
1662    pthread_mutex_unlock(&gInitDriverMutex);
1663    return addr;
1664}
1665
1666EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
1667{
1668    EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw);
1669    if (gEGLDebugLevel > 0)
1670        Debug_eglSwapBuffers(dpy, draw);
1671
1672    clearError();
1673
1674    SurfaceRef _s(draw);
1675    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1676
1677    if (!validate_display_surface(dpy, draw))
1678        return EGL_FALSE;
1679    egl_display_t const * const dp = get_display(dpy);
1680    egl_surface_t const * const s = get_surface(draw);
1681    return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
1682}
1683
1684EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface surface,
1685                            NativePixmapType target)
1686{
1687    clearError();
1688
1689    SurfaceRef _s(surface);
1690    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1691
1692    if (!validate_display_surface(dpy, surface))
1693        return EGL_FALSE;
1694    egl_display_t const * const dp = get_display(dpy);
1695    egl_surface_t const * const s = get_surface(surface);
1696    return s->cnx->egl.eglCopyBuffers(
1697            dp->disp[s->impl].dpy, s->surface, target);
1698}
1699
1700const char* eglQueryString(EGLDisplay dpy, EGLint name)
1701{
1702    clearError();
1703
1704    egl_display_t const * const dp = get_display(dpy);
1705    switch (name) {
1706        case EGL_VENDOR:
1707            return gVendorString;
1708        case EGL_VERSION:
1709            return gVersionString;
1710        case EGL_EXTENSIONS:
1711            return gExtensionString;
1712        case EGL_CLIENT_APIS:
1713            return gClientApiString;
1714    }
1715    return setError(EGL_BAD_PARAMETER, (const char *)0);
1716}
1717
1718
1719// ----------------------------------------------------------------------------
1720// EGL 1.1
1721// ----------------------------------------------------------------------------
1722
1723EGLBoolean eglSurfaceAttrib(
1724        EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1725{
1726    clearError();
1727
1728    SurfaceRef _s(surface);
1729    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1730
1731    if (!validate_display_surface(dpy, surface))
1732        return EGL_FALSE;
1733    egl_display_t const * const dp = get_display(dpy);
1734    egl_surface_t const * const s = get_surface(surface);
1735    if (s->cnx->egl.eglSurfaceAttrib) {
1736        return s->cnx->egl.eglSurfaceAttrib(
1737                dp->disp[s->impl].dpy, s->surface, attribute, value);
1738    }
1739    return setError(EGL_BAD_SURFACE, EGL_FALSE);
1740}
1741
1742EGLBoolean eglBindTexImage(
1743        EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1744{
1745    clearError();
1746
1747    SurfaceRef _s(surface);
1748    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1749
1750    if (!validate_display_surface(dpy, surface))
1751        return EGL_FALSE;
1752    egl_display_t const * const dp = get_display(dpy);
1753    egl_surface_t const * const s = get_surface(surface);
1754    if (s->cnx->egl.eglBindTexImage) {
1755        return s->cnx->egl.eglBindTexImage(
1756                dp->disp[s->impl].dpy, s->surface, buffer);
1757    }
1758    return setError(EGL_BAD_SURFACE, EGL_FALSE);
1759}
1760
1761EGLBoolean eglReleaseTexImage(
1762        EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1763{
1764    clearError();
1765
1766    SurfaceRef _s(surface);
1767    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1768
1769    if (!validate_display_surface(dpy, surface))
1770        return EGL_FALSE;
1771    egl_display_t const * const dp = get_display(dpy);
1772    egl_surface_t const * const s = get_surface(surface);
1773    if (s->cnx->egl.eglReleaseTexImage) {
1774        return s->cnx->egl.eglReleaseTexImage(
1775                dp->disp[s->impl].dpy, s->surface, buffer);
1776    }
1777    return setError(EGL_BAD_SURFACE, EGL_FALSE);
1778}
1779
1780EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1781{
1782    clearError();
1783
1784    egl_display_t * const dp = get_display(dpy);
1785    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1786
1787    EGLBoolean res = EGL_TRUE;
1788    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1789        egl_connection_t* const cnx = &gEGLImpl[i];
1790        if (cnx->dso) {
1791            if (cnx->egl.eglSwapInterval) {
1792                if (cnx->egl.eglSwapInterval(
1793                        dp->disp[i].dpy, interval) == EGL_FALSE) {
1794                    res = EGL_FALSE;
1795                }
1796            }
1797        }
1798    }
1799    return res;
1800}
1801
1802
1803// ----------------------------------------------------------------------------
1804// EGL 1.2
1805// ----------------------------------------------------------------------------
1806
1807EGLBoolean eglWaitClient(void)
1808{
1809    clearError();
1810
1811    // could be called before eglInitialize(), but we wouldn't have a context
1812    // then, and this function would return GL_TRUE, which isn't wrong.
1813    EGLBoolean res = EGL_TRUE;
1814    EGLContext ctx = getContext();
1815    if (ctx) {
1816        egl_context_t const * const c = get_context(ctx);
1817        if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1818        if (uint32_t(c->impl)>=2)
1819            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1820        egl_connection_t* const cnx = &gEGLImpl[c->impl];
1821        if (!cnx->dso)
1822            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1823        if (cnx->egl.eglWaitClient) {
1824            res = cnx->egl.eglWaitClient();
1825        } else {
1826            res = cnx->egl.eglWaitGL();
1827        }
1828    }
1829    return res;
1830}
1831
1832EGLBoolean eglBindAPI(EGLenum api)
1833{
1834    clearError();
1835
1836    if (egl_init_drivers() == EGL_FALSE) {
1837        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1838    }
1839
1840    // bind this API on all EGLs
1841    EGLBoolean res = EGL_TRUE;
1842    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1843        egl_connection_t* const cnx = &gEGLImpl[i];
1844        if (cnx->dso) {
1845            if (cnx->egl.eglBindAPI) {
1846                if (cnx->egl.eglBindAPI(api) == EGL_FALSE) {
1847                    res = EGL_FALSE;
1848                }
1849            }
1850        }
1851    }
1852    return res;
1853}
1854
1855EGLenum eglQueryAPI(void)
1856{
1857    clearError();
1858
1859    if (egl_init_drivers() == EGL_FALSE) {
1860        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1861    }
1862
1863    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1864        egl_connection_t* const cnx = &gEGLImpl[i];
1865        if (cnx->dso) {
1866            if (cnx->egl.eglQueryAPI) {
1867                // the first one we find is okay, because they all
1868                // should be the same
1869                return cnx->egl.eglQueryAPI();
1870            }
1871        }
1872    }
1873    // or, it can only be OpenGL ES
1874    return EGL_OPENGL_ES_API;
1875}
1876
1877EGLBoolean eglReleaseThread(void)
1878{
1879    clearError();
1880
1881    // If there is context bound to the thread, release it
1882    loseCurrent(get_context(getContext()));
1883
1884    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1885        egl_connection_t* const cnx = &gEGLImpl[i];
1886        if (cnx->dso) {
1887            if (cnx->egl.eglReleaseThread) {
1888                cnx->egl.eglReleaseThread();
1889            }
1890        }
1891    }
1892    clearTLS();
1893    return EGL_TRUE;
1894}
1895
1896EGLSurface eglCreatePbufferFromClientBuffer(
1897          EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1898          EGLConfig config, const EGLint *attrib_list)
1899{
1900    clearError();
1901
1902    egl_display_t const* dp = 0;
1903    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
1904    if (!cnx) return EGL_FALSE;
1905    if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1906        return cnx->egl.eglCreatePbufferFromClientBuffer(
1907                dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1908                buftype, buffer,
1909                dp->configs[intptr_t(config)].config, attrib_list);
1910    }
1911    return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1912}
1913
1914// ----------------------------------------------------------------------------
1915// EGL_EGLEXT_VERSION 3
1916// ----------------------------------------------------------------------------
1917
1918EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1919        const EGLint *attrib_list)
1920{
1921    clearError();
1922
1923    SurfaceRef _s(surface);
1924    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1925
1926    if (!validate_display_surface(dpy, surface))
1927        return EGL_FALSE;
1928
1929    egl_display_t const * const dp = get_display(dpy);
1930    egl_surface_t const * const s = get_surface(surface);
1931
1932    if (s->cnx->egl.eglLockSurfaceKHR) {
1933        return s->cnx->egl.eglLockSurfaceKHR(
1934                dp->disp[s->impl].dpy, s->surface, attrib_list);
1935    }
1936    return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1937}
1938
1939EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1940{
1941    clearError();
1942
1943    SurfaceRef _s(surface);
1944    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1945
1946    if (!validate_display_surface(dpy, surface))
1947        return EGL_FALSE;
1948
1949    egl_display_t const * const dp = get_display(dpy);
1950    egl_surface_t const * const s = get_surface(surface);
1951
1952    if (s->cnx->egl.eglUnlockSurfaceKHR) {
1953        return s->cnx->egl.eglUnlockSurfaceKHR(
1954                dp->disp[s->impl].dpy, s->surface);
1955    }
1956    return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1957}
1958
1959EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1960        EGLClientBuffer buffer, const EGLint *attrib_list)
1961{
1962    clearError();
1963
1964    if (ctx != EGL_NO_CONTEXT) {
1965        ContextRef _c(ctx);
1966        if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1967        if (!validate_display_context(dpy, ctx))
1968            return EGL_NO_IMAGE_KHR;
1969        egl_display_t const * const dp = get_display(dpy);
1970        egl_context_t * const c = get_context(ctx);
1971        // since we have an EGLContext, we know which implementation to use
1972        EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
1973                dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
1974        if (image == EGL_NO_IMAGE_KHR)
1975            return image;
1976
1977        egl_image_t* result = new egl_image_t(dpy, ctx);
1978        result->images[c->impl] = image;
1979        return (EGLImageKHR)result;
1980    } else {
1981        // EGL_NO_CONTEXT is a valid parameter
1982        egl_display_t const * const dp = get_display(dpy);
1983        if (dp == 0) {
1984            return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
1985        }
1986
1987        /* Since we don't have a way to know which implementation to call,
1988         * we're calling all of them. If at least one of the implementation
1989         * succeeded, this is a success.
1990         */
1991
1992        EGLint currentError = eglGetError();
1993
1994        EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS];
1995        bool success = false;
1996        for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1997            egl_connection_t* const cnx = &gEGLImpl[i];
1998            implImages[i] = EGL_NO_IMAGE_KHR;
1999            if (cnx->dso) {
2000                if (cnx->egl.eglCreateImageKHR) {
2001                    implImages[i] = cnx->egl.eglCreateImageKHR(
2002                            dp->disp[i].dpy, ctx, target, buffer, attrib_list);
2003                    if (implImages[i] != EGL_NO_IMAGE_KHR) {
2004                        success = true;
2005                    }
2006                }
2007            }
2008        }
2009
2010        if (!success) {
2011            // failure, if there was an error when we entered this function,
2012            // the error flag must not be updated.
2013            // Otherwise, the error is whatever happened in the implementation
2014            // that faulted.
2015            if (currentError != EGL_SUCCESS) {
2016                setError(currentError, EGL_NO_IMAGE_KHR);
2017            }
2018            return EGL_NO_IMAGE_KHR;
2019        } else {
2020            // In case of success, we need to clear all error flags
2021            // (especially those caused by the implementation that didn't
2022            // succeed). TODO: we could avoid this if we knew this was
2023            // a "full" success (all implementation succeeded).
2024            eglGetError();
2025        }
2026
2027        egl_image_t* result = new egl_image_t(dpy, ctx);
2028        memcpy(result->images, implImages, sizeof(implImages));
2029        return (EGLImageKHR)result;
2030    }
2031}
2032
2033EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
2034{
2035    clearError();
2036
2037    egl_display_t const * const dp = get_display(dpy);
2038     if (dp == 0) {
2039         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2040     }
2041
2042     ImageRef _i(img);
2043     if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2044
2045     egl_image_t* image = get_image(img);
2046     bool success = false;
2047     for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
2048         egl_connection_t* const cnx = &gEGLImpl[i];
2049         if (image->images[i] != EGL_NO_IMAGE_KHR) {
2050             if (cnx->dso) {
2051                 if (cnx->egl.eglDestroyImageKHR) {
2052                     if (cnx->egl.eglDestroyImageKHR(
2053                             dp->disp[i].dpy, image->images[i])) {
2054                         success = true;
2055                     }
2056                 }
2057             }
2058         }
2059     }
2060     if (!success)
2061         return EGL_FALSE;
2062
2063     _i.terminate();
2064
2065     return EGL_TRUE;
2066}
2067
2068// ----------------------------------------------------------------------------
2069// EGL_EGLEXT_VERSION 5
2070// ----------------------------------------------------------------------------
2071
2072
2073EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
2074{
2075    clearError();
2076
2077    EGLContext ctx = eglGetCurrentContext();
2078    ContextRef _c(ctx);
2079    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR);
2080    if (!validate_display_context(dpy, ctx))
2081        return EGL_NO_SYNC_KHR;
2082    egl_display_t const * const dp = get_display(dpy);
2083    egl_context_t * const c = get_context(ctx);
2084    EGLSyncKHR result = EGL_NO_SYNC_KHR;
2085    if (c->cnx->egl.eglCreateSyncKHR) {
2086        EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR(
2087                dp->disp[c->impl].dpy, type, attrib_list);
2088        if (sync == EGL_NO_SYNC_KHR)
2089            return sync;
2090        result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync);
2091    }
2092    return (EGLSyncKHR)result;
2093}
2094
2095EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
2096{
2097    clearError();
2098
2099    egl_display_t const * const dp = get_display(dpy);
2100    if (dp == 0) {
2101        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2102    }
2103
2104    SyncRef _s(sync);
2105    if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2106    egl_sync_t* syncObject = get_sync(sync);
2107
2108    EGLContext ctx = syncObject->context;
2109    ContextRef _c(ctx);
2110    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
2111    if (!validate_display_context(dpy, ctx))
2112        return EGL_FALSE;
2113
2114    egl_context_t * const c = get_context(ctx);
2115
2116    if (c->cnx->egl.eglDestroySyncKHR) {
2117        return c->cnx->egl.eglDestroySyncKHR(
2118                dp->disp[c->impl].dpy, syncObject->sync);
2119    }
2120
2121    return EGL_FALSE;
2122}
2123
2124EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
2125{
2126    clearError();
2127
2128    egl_display_t const * const dp = get_display(dpy);
2129    if (dp == 0) {
2130        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2131    }
2132
2133    SyncRef _s(sync);
2134    if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2135    egl_sync_t* syncObject = get_sync(sync);
2136
2137    EGLContext ctx = syncObject->context;
2138    ContextRef _c(ctx);
2139    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
2140    if (!validate_display_context(dpy, ctx))
2141        return EGL_FALSE;
2142
2143    egl_context_t * const c = get_context(ctx);
2144
2145    if (c->cnx->egl.eglClientWaitSyncKHR) {
2146        return c->cnx->egl.eglClientWaitSyncKHR(
2147                dp->disp[c->impl].dpy, syncObject->sync, flags, timeout);
2148    }
2149
2150    return EGL_FALSE;
2151}
2152
2153EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
2154{
2155    clearError();
2156
2157    egl_display_t const * const dp = get_display(dpy);
2158    if (dp == 0) {
2159        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2160    }
2161
2162    SyncRef _s(sync);
2163    if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2164    egl_sync_t* syncObject = get_sync(sync);
2165
2166    EGLContext ctx = syncObject->context;
2167    ContextRef _c(ctx);
2168    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
2169    if (!validate_display_context(dpy, ctx))
2170        return EGL_FALSE;
2171
2172    egl_context_t * const c = get_context(ctx);
2173
2174    if (c->cnx->egl.eglGetSyncAttribKHR) {
2175        return c->cnx->egl.eglGetSyncAttribKHR(
2176                dp->disp[c->impl].dpy, syncObject->sync, attribute, value);
2177    }
2178
2179    return EGL_FALSE;
2180}
2181
2182// ----------------------------------------------------------------------------
2183// ANDROID extensions
2184// ----------------------------------------------------------------------------
2185
2186EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
2187        EGLint left, EGLint top, EGLint width, EGLint height)
2188{
2189    clearError();
2190
2191    SurfaceRef _s(draw);
2192    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
2193
2194    if (!validate_display_surface(dpy, draw))
2195        return EGL_FALSE;
2196    egl_display_t const * const dp = get_display(dpy);
2197    egl_surface_t const * const s = get_surface(draw);
2198    if (s->cnx->egl.eglSetSwapRectangleANDROID) {
2199        return s->cnx->egl.eglSetSwapRectangleANDROID(
2200                dp->disp[s->impl].dpy, s->surface, left, top, width, height);
2201    }
2202    return setError(EGL_BAD_DISPLAY, NULL);
2203}
2204