• 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