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