blob: 75f70786169094e24a8084130a763213d112780b [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/*
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
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080017#include <ctype.h>
Mathias Agopiand8fb7b52009-05-17 18:50:16 -070018#include <stdlib.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080019#include <string.h>
20#include <errno.h>
21#include <dlfcn.h>
22
23#include <sys/ioctl.h>
24
Kenny Rootaf1cf072011-02-16 10:13:53 -080025#ifdef HAVE_ANDROID_OS
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080026#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
Mathias Agopian9429e9c2009-08-21 02:18:25 -070039#include <utils/SortedVector.h>
Mathias Agopian24035332010-08-02 17:34:32 -070040#include <utils/KeyedVector.h>
41#include <utils/String8.h>
Mathias Agopian9429e9c2009-08-21 02:18:25 -070042
Mathias Agopian644bb2a2010-11-24 15:59:35 -080043#include <ui/egl/android_natives.h>
44
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080045#include "hooks.h"
46#include "egl_impl.h"
Mathias Agopiande586972009-05-28 17:39:03 -070047#include "Loader.h"
David Li65948aa2011-03-10 16:40:37 -080048#include "glesv2dbg.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080049
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080050#define setError(_e, _r) setErrorEtc(__FUNCTION__, __LINE__, _e, _r)
51
52// ----------------------------------------------------------------------------
53namespace android {
54// ----------------------------------------------------------------------------
55
56#define VERSION_MAJOR 1
57#define VERSION_MINOR 4
58static char const * const gVendorString = "Android";
Mathias Agopian923c6612009-08-17 18:07:06 -070059static char const * const gVersionString = "1.4 Android META-EGL";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080060static char const * const gClientApiString = "OpenGL ES";
Mathias Agopian076b1cc2009-04-10 14:24:30 -070061static char const * const gExtensionString =
62 "EGL_KHR_image "
Mathias Agopiane6bf8b32009-05-06 23:47:08 -070063 "EGL_KHR_image_base "
64 "EGL_KHR_image_pixmap "
Mathias Agopian8e4b5a32010-08-27 16:08:03 -070065 "EGL_KHR_gl_texture_2D_image "
Michael I. Goldca41e362011-01-13 10:13:15 -080066 "EGL_KHR_gl_texture_cubemap_image "
67 "EGL_KHR_gl_renderbuffer_image "
Mathias Agopianc291f5852010-08-27 16:48:56 -070068 "EGL_KHR_fence_sync "
Mathias Agopian076b1cc2009-04-10 14:24:30 -070069 "EGL_ANDROID_image_native_buffer "
Mathias Agopiandf3ca302009-05-04 19:29:25 -070070 "EGL_ANDROID_swap_rectangle "
Mathias Agopian076b1cc2009-04-10 14:24:30 -070071 ;
72
73// ----------------------------------------------------------------------------
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080074
Mathias Agopian9429e9c2009-08-21 02:18:25 -070075class egl_object_t {
76 static SortedVector<egl_object_t*> sObjects;
77 static Mutex sLock;
78
79 volatile int32_t terminated;
80 mutable volatile int32_t count;
81
82public:
83 egl_object_t() : terminated(0), count(1) {
84 Mutex::Autolock _l(sLock);
85 sObjects.add(this);
86 }
87
88 inline bool isAlive() const { return !terminated; }
89
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080090private:
Mathias Agopian9429e9c2009-08-21 02:18:25 -070091 bool get() {
92 Mutex::Autolock _l(sLock);
93 if (egl_object_t::sObjects.indexOf(this) >= 0) {
94 android_atomic_inc(&count);
95 return true;
96 }
97 return false;
98 }
99
100 bool put() {
101 Mutex::Autolock _l(sLock);
102 if (android_atomic_dec(&count) == 1) {
103 sObjects.remove(this);
104 return true;
105 }
106 return false;
107 }
108
109public:
110 template <typename N, typename T>
111 struct LocalRef {
112 N* ref;
113 LocalRef(T o) : ref(0) {
114 N* native = reinterpret_cast<N*>(o);
115 if (o && native->get()) {
116 ref = native;
117 }
118 }
119 ~LocalRef() {
120 if (ref && ref->put()) {
121 delete ref;
122 }
123 }
124 inline N* get() {
125 return ref;
126 }
127 void acquire() const {
128 if (ref) {
129 android_atomic_inc(&ref->count);
130 }
131 }
132 void release() const {
133 if (ref) {
134 int32_t c = android_atomic_dec(&ref->count);
135 // ref->count cannot be 1 prior atomic_dec because we have
136 // a reference, and if we have one, it means there was
137 // already one before us.
138 LOGE_IF(c==1, "refcount is now 0 in release()");
139 }
140 }
141 void terminate() {
142 if (ref) {
143 ref->terminated = 1;
144 release();
145 }
146 }
147 };
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800148};
149
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700150SortedVector<egl_object_t*> egl_object_t::sObjects;
151Mutex egl_object_t::sLock;
152
Mathias Agopiancee79392010-07-26 21:14:59 -0700153
154struct egl_config_t {
155 egl_config_t() {}
156 egl_config_t(int impl, EGLConfig config)
157 : impl(impl), config(config), configId(0), implConfigId(0) { }
158 int impl; // the implementation this config is for
159 EGLConfig config; // the implementation's EGLConfig
160 EGLint configId; // our CONFIG_ID
161 EGLint implConfigId; // the implementation's CONFIG_ID
162 inline bool operator < (const egl_config_t& rhs) const {
163 if (impl < rhs.impl) return true;
164 if (impl > rhs.impl) return false;
165 return config < rhs.config;
166 }
167};
168
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700169struct egl_display_t {
170 enum { NOT_INITIALIZED, INITIALIZED, TERMINATED };
171
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800172 struct strings_t {
173 char const * vendor;
174 char const * version;
175 char const * clientApi;
176 char const * extensions;
177 };
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700178
179 struct DisplayImpl {
180 DisplayImpl() : dpy(EGL_NO_DISPLAY), config(0),
181 state(NOT_INITIALIZED), numConfigs(0) { }
182 EGLDisplay dpy;
183 EGLConfig* config;
184 EGLint state;
185 EGLint numConfigs;
186 strings_t queryString;
187 };
188
Mathias Agopiancee79392010-07-26 21:14:59 -0700189 uint32_t magic;
190 DisplayImpl disp[IMPL_NUM_IMPLEMENTATIONS];
191 EGLint numTotalConfigs;
192 egl_config_t* configs;
193 uint32_t refs;
194 Mutex lock;
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700195
Mathias Agopiancee79392010-07-26 21:14:59 -0700196 egl_display_t() : magic('_dpy'), numTotalConfigs(0), configs(0) { }
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700197 ~egl_display_t() { magic = 0; }
198 inline bool isValid() const { return magic == '_dpy'; }
199 inline bool isAlive() const { return isValid(); }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800200};
201
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700202struct egl_surface_t : public egl_object_t
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800203{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700204 typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
205
Mathias Agopian644bb2a2010-11-24 15:59:35 -0800206 egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win,
207 EGLSurface surface, int impl, egl_connection_t const* cnx)
208 : dpy(dpy), surface(surface), config(config), win(win), impl(impl), cnx(cnx) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800209 }
210 ~egl_surface_t() {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800211 }
212 EGLDisplay dpy;
213 EGLSurface surface;
Mathias Agopiancee79392010-07-26 21:14:59 -0700214 EGLConfig config;
Mathias Agopian644bb2a2010-11-24 15:59:35 -0800215 sp<ANativeWindow> win;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800216 int impl;
217 egl_connection_t const* cnx;
218};
219
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700220struct egl_context_t : public egl_object_t
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800221{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700222 typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
223
Mathias Agopiancee79392010-07-26 21:14:59 -0700224 egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
Mathias Agopian618fa102009-10-14 02:06:37 -0700225 int impl, egl_connection_t const* cnx, int version)
Mathias Agopianc3ce8802010-12-08 15:34:02 -0800226 : dpy(dpy), context(context), config(config), read(0), draw(0), impl(impl),
David Li65948aa2011-03-10 16:40:37 -0800227 cnx(cnx), version(version), dbg(NULL)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800228 {
229 }
David Li65948aa2011-03-10 16:40:37 -0800230 ~egl_context_t()
231 {
232 if (dbg)
233 DestroyDbgContext(dbg);
234 dbg = NULL;
235 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800236 EGLDisplay dpy;
237 EGLContext context;
Mathias Agopiancee79392010-07-26 21:14:59 -0700238 EGLConfig config;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800239 EGLSurface read;
240 EGLSurface draw;
241 int impl;
242 egl_connection_t const* cnx;
Mathias Agopian618fa102009-10-14 02:06:37 -0700243 int version;
David Li65948aa2011-03-10 16:40:37 -0800244 DbgContext * dbg;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800245};
246
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700247struct egl_image_t : public egl_object_t
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700248{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700249 typedef egl_object_t::LocalRef<egl_image_t, EGLImageKHR> Ref;
250
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700251 egl_image_t(EGLDisplay dpy, EGLContext context)
252 : dpy(dpy), context(context)
253 {
254 memset(images, 0, sizeof(images));
255 }
256 EGLDisplay dpy;
Mathias Agopian77fbf8d2010-09-09 11:12:54 -0700257 EGLContext context;
Mathias Agopian618fa102009-10-14 02:06:37 -0700258 EGLImageKHR images[IMPL_NUM_IMPLEMENTATIONS];
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700259};
260
Mathias Agopianc291f5852010-08-27 16:48:56 -0700261struct egl_sync_t : public egl_object_t
262{
263 typedef egl_object_t::LocalRef<egl_sync_t, EGLSyncKHR> Ref;
264
265 egl_sync_t(EGLDisplay dpy, EGLContext context, EGLSyncKHR sync)
266 : dpy(dpy), context(context), sync(sync)
267 {
268 }
269 EGLDisplay dpy;
270 EGLContext context;
271 EGLSyncKHR sync;
272};
273
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700274typedef egl_surface_t::Ref SurfaceRef;
275typedef egl_context_t::Ref ContextRef;
276typedef egl_image_t::Ref ImageRef;
Mathias Agopianc291f5852010-08-27 16:48:56 -0700277typedef egl_sync_t::Ref SyncRef;
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700278
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800279struct tls_t
280{
Mathias Agopiand274eae2009-07-31 16:21:17 -0700281 tls_t() : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(EGL_TRUE) { }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800282 EGLint error;
283 EGLContext ctx;
Mathias Agopiand274eae2009-07-31 16:21:17 -0700284 EGLBoolean logCallWithNoContext;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800285};
286
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800287
288// ----------------------------------------------------------------------------
289
Mathias Agopianbf41b112010-04-09 13:37:34 -0700290static egl_connection_t gEGLImpl[IMPL_NUM_IMPLEMENTATIONS];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800291static egl_display_t gDisplay[NUM_DISPLAYS];
292static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER;
293static pthread_key_t gEGLThreadLocalStorageKey = -1;
294
295// ----------------------------------------------------------------------------
296
Mathias Agopian618fa102009-10-14 02:06:37 -0700297EGLAPI gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS];
298EGLAPI gl_hooks_t gHooksNoContext;
Mathias Agopianeccc8cf2009-05-13 00:19:22 -0700299EGLAPI pthread_key_t gGLWrapperKey = -1;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800300
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700301#if EGL_TRACE
302
303EGLAPI pthread_key_t gGLTraceKey = -1;
304
305// ----------------------------------------------------------------------------
306
David Li2f5a6552011-03-01 16:08:10 -0800307static int gEGLTraceLevel, gEGLDebugLevel;
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700308static int gEGLApplicationTraceLevel;
David Li2f5a6552011-03-01 16:08:10 -0800309extern EGLAPI gl_hooks_t gHooksTrace, gHooksDebug;
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700310
311static inline void setGlTraceThreadSpecific(gl_hooks_t const *value) {
312 pthread_setspecific(gGLTraceKey, value);
313}
314
315gl_hooks_t const* getGLTraceThreadSpecific() {
316 return static_cast<gl_hooks_t*>(pthread_getspecific(gGLTraceKey));
317}
318
319static void initEglTraceLevel() {
320 char value[PROPERTY_VALUE_MAX];
321 property_get("debug.egl.trace", value, "0");
322 int propertyLevel = atoi(value);
323 int applicationLevel = gEGLApplicationTraceLevel;
324 gEGLTraceLevel = propertyLevel > applicationLevel ? propertyLevel : applicationLevel;
David Li2f5a6552011-03-01 16:08:10 -0800325
326 property_get("debug.egl.debug_proc", value, "");
327 long pid = getpid();
328 char procPath[128] = {};
329 sprintf(procPath, "/proc/%ld/cmdline", pid);
330 FILE * file = fopen(procPath, "r");
331 if (file)
332 {
333 char cmdline[256] = {};
334 if (fgets(cmdline, sizeof(cmdline) - 1, file))
335 {
David Li2f5a6552011-03-01 16:08:10 -0800336 if (!strcmp(value, cmdline))
337 gEGLDebugLevel = 1;
338 }
339 fclose(file);
340 }
341
David Li2f5a6552011-03-01 16:08:10 -0800342 if (gEGLDebugLevel > 0)
David Li85f33a72011-03-10 19:07:42 -0800343 {
344 property_get("debug.egl.debug_port", value, "5039");
345 StartDebugServer(atoi(value));
346 }
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700347}
348
349static void setGLHooksThreadSpecific(gl_hooks_t const *value) {
350 if (gEGLTraceLevel > 0) {
351 setGlTraceThreadSpecific(value);
352 setGlThreadSpecific(&gHooksTrace);
David Li65948aa2011-03-10 16:40:37 -0800353 } else if (gEGLDebugLevel > 0 && value != &gHooksNoContext) {
David Li2f5a6552011-03-01 16:08:10 -0800354 setGlTraceThreadSpecific(value);
355 setGlThreadSpecific(&gHooksDebug);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700356 } else {
357 setGlThreadSpecific(value);
358 }
359}
360
361/*
362 * Global entry point to allow applications to modify their own trace level.
363 * The effective trace level is the max of this level and the value of debug.egl.trace.
364 */
365extern "C"
366void setGLTraceLevel(int level) {
367 gEGLApplicationTraceLevel = level;
368}
369
370#else
371
372static inline void setGLHooksThreadSpecific(gl_hooks_t const *value) {
373 setGlThreadSpecific(value);
374}
375
376#endif
377
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800378// ----------------------------------------------------------------------------
379
380static __attribute__((noinline))
381const char *egl_strerror(EGLint err)
382{
383 switch (err){
384 case EGL_SUCCESS: return "EGL_SUCCESS";
385 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
386 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
387 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
388 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
389 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
390 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
391 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
392 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
393 case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
394 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
395 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
396 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
397 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
398 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
399 default: return "UNKNOWN";
400 }
401}
402
403static __attribute__((noinline))
404void clearTLS() {
405 if (gEGLThreadLocalStorageKey != -1) {
406 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
407 if (tls) {
408 delete tls;
409 pthread_setspecific(gEGLThreadLocalStorageKey, 0);
410 }
411 }
412}
413
414static tls_t* getTLS()
415{
416 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
417 if (tls == 0) {
418 tls = new tls_t;
419 pthread_setspecific(gEGLThreadLocalStorageKey, tls);
420 }
421 return tls;
422}
423
Michael I. Gold4aea6bf2011-01-21 15:39:38 -0800424static inline void clearError() {
Jamie Gennisf1cde8e2011-01-30 16:50:04 -0800425 // This must clear the error from all the underlying EGL implementations as
426 // well as the EGL wrapper layer.
427 eglGetError();
Michael I. Gold4aea6bf2011-01-21 15:39:38 -0800428}
429
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800430template<typename T>
431static __attribute__((noinline))
432T setErrorEtc(const char* caller, int line, EGLint error, T returnValue) {
433 if (gEGLThreadLocalStorageKey == -1) {
434 pthread_mutex_lock(&gThreadLocalStorageKeyMutex);
435 if (gEGLThreadLocalStorageKey == -1)
436 pthread_key_create(&gEGLThreadLocalStorageKey, NULL);
437 pthread_mutex_unlock(&gThreadLocalStorageKeyMutex);
438 }
439 tls_t* tls = getTLS();
440 if (tls->error != error) {
441 LOGE("%s:%d error %x (%s)", caller, line, error, egl_strerror(error));
442 tls->error = error;
443 }
444 return returnValue;
445}
446
447static __attribute__((noinline))
448GLint getError() {
449 if (gEGLThreadLocalStorageKey == -1)
450 return EGL_SUCCESS;
451 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
452 if (!tls) return EGL_SUCCESS;
453 GLint error = tls->error;
454 tls->error = EGL_SUCCESS;
455 return error;
456}
457
458static __attribute__((noinline))
459void setContext(EGLContext ctx) {
460 if (gEGLThreadLocalStorageKey == -1) {
461 pthread_mutex_lock(&gThreadLocalStorageKeyMutex);
462 if (gEGLThreadLocalStorageKey == -1)
463 pthread_key_create(&gEGLThreadLocalStorageKey, NULL);
464 pthread_mutex_unlock(&gThreadLocalStorageKeyMutex);
465 }
466 tls_t* tls = getTLS();
467 tls->ctx = ctx;
468}
469
470static __attribute__((noinline))
471EGLContext getContext() {
472 if (gEGLThreadLocalStorageKey == -1)
473 return EGL_NO_CONTEXT;
474 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
475 if (!tls) return EGL_NO_CONTEXT;
476 return tls->ctx;
477}
478
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800479/*****************************************************************************/
480
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800481template<typename T>
482static __attribute__((noinline))
483int binarySearch(
484 T const sortedArray[], int first, int last, T key)
485{
486 while (first <= last) {
487 int mid = (first + last) / 2;
Mathias Agopiancee79392010-07-26 21:14:59 -0700488 if (sortedArray[mid] < key) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800489 first = mid + 1;
490 } else if (key < sortedArray[mid]) {
491 last = mid - 1;
492 } else {
493 return mid;
494 }
495 }
496 return -1;
497}
498
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800499static int cmp_configs(const void* a, const void *b)
500{
Mathias Agopiancee79392010-07-26 21:14:59 -0700501 const egl_config_t& c0 = *(egl_config_t const *)a;
502 const egl_config_t& c1 = *(egl_config_t const *)b;
503 return c0<c1 ? -1 : (c1<c0 ? 1 : 0);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800504}
505
506struct extention_map_t {
507 const char* name;
508 __eglMustCastToProperFunctionPointerType address;
509};
510
511static const extention_map_t gExtentionMap[] = {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700512 { "eglLockSurfaceKHR",
513 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
514 { "eglUnlockSurfaceKHR",
515 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
516 { "eglCreateImageKHR",
517 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
518 { "eglDestroyImageKHR",
519 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Mathias Agopian8d2e83b2009-06-24 22:37:39 -0700520 { "eglSetSwapRectangleANDROID",
521 (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800522};
523
Mathias Agopian24035332010-08-02 17:34:32 -0700524extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
525
526// accesses protected by gInitDriverMutex
527static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> gGLExtentionMap;
528static int gGLExtentionSlot = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800529
530static void(*findProcAddress(const char* name,
531 const extention_map_t* map, size_t n))()
532{
533 for (uint32_t i=0 ; i<n ; i++) {
534 if (!strcmp(name, map[i].name)) {
535 return map[i].address;
536 }
537 }
538 return NULL;
539}
540
541// ----------------------------------------------------------------------------
542
Mathias Agopian6f087122010-09-23 16:38:38 -0700543static int gl_no_context() {
Mathias Agopiand274eae2009-07-31 16:21:17 -0700544 tls_t* tls = getTLS();
545 if (tls->logCallWithNoContext == EGL_TRUE) {
546 tls->logCallWithNoContext = EGL_FALSE;
547 LOGE("call to OpenGL ES API with no current context "
548 "(logged once per thread)");
549 }
Mathias Agopian6f087122010-09-23 16:38:38 -0700550 return 0;
Mathias Agopian05c53112010-09-23 11:32:52 -0700551}
552
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800553static void early_egl_init(void)
554{
555#if !USE_FAST_TLS_KEY
556 pthread_key_create(&gGLWrapperKey, NULL);
557#endif
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700558#if EGL_TRACE
559 pthread_key_create(&gGLTraceKey, NULL);
560 initEglTraceLevel();
561#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800562 uint32_t addr = (uint32_t)((void*)gl_no_context);
563 android_memset32(
Mathias Agopian618fa102009-10-14 02:06:37 -0700564 (uint32_t*)(void*)&gHooksNoContext,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800565 addr,
Mathias Agopian618fa102009-10-14 02:06:37 -0700566 sizeof(gHooksNoContext));
Mathias Agopian05c53112010-09-23 11:32:52 -0700567
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700568 setGLHooksThreadSpecific(&gHooksNoContext);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800569}
570
571static pthread_once_t once_control = PTHREAD_ONCE_INIT;
572static int sEarlyInitState = pthread_once(&once_control, &early_egl_init);
573
574
575static inline
576egl_display_t* get_display(EGLDisplay dpy)
577{
578 uintptr_t index = uintptr_t(dpy)-1U;
579 return (index >= NUM_DISPLAYS) ? NULL : &gDisplay[index];
580}
581
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700582template<typename NATIVE, typename EGL>
583static inline NATIVE* egl_to_native_cast(EGL arg) {
584 return reinterpret_cast<NATIVE*>(arg);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800585}
586
587static inline
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700588egl_surface_t* get_surface(EGLSurface surface) {
589 return egl_to_native_cast<egl_surface_t>(surface);
590}
591
592static inline
593egl_context_t* get_context(EGLContext context) {
594 return egl_to_native_cast<egl_context_t>(context);
595}
596
David Li65948aa2011-03-10 16:40:37 -0800597DbgContext * getDbgContextThreadSpecific()
598{
599 return get_context(getContext())->dbg;
600}
601
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700602static inline
603egl_image_t* get_image(EGLImageKHR image) {
604 return egl_to_native_cast<egl_image_t>(image);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800605}
606
Mathias Agopianc291f5852010-08-27 16:48:56 -0700607static inline
608egl_sync_t* get_sync(EGLSyncKHR sync) {
609 return egl_to_native_cast<egl_sync_t>(sync);
610}
611
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800612static egl_connection_t* validate_display_config(
613 EGLDisplay dpy, EGLConfig config,
Mathias Agopiancee79392010-07-26 21:14:59 -0700614 egl_display_t const*& dp)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800615{
616 dp = get_display(dpy);
617 if (!dp) return setError(EGL_BAD_DISPLAY, (egl_connection_t*)NULL);
618
Mathias Agopiancee79392010-07-26 21:14:59 -0700619 if (intptr_t(config) >= dp->numTotalConfigs) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800620 return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
621 }
Mathias Agopiancee79392010-07-26 21:14:59 -0700622 egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(config)].impl];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800623 if (cnx->dso == 0) {
624 return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
625 }
626 return cnx;
627}
628
629static EGLBoolean validate_display_context(EGLDisplay dpy, EGLContext ctx)
630{
631 if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS)
632 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700633 if (!get_display(dpy)->isAlive())
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800634 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700635 if (!get_context(ctx)->isAlive())
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800636 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
637 return EGL_TRUE;
638}
639
640static EGLBoolean validate_display_surface(EGLDisplay dpy, EGLSurface surface)
641{
642 if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS)
643 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700644 if (!get_display(dpy)->isAlive())
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800645 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700646 if (!get_surface(surface)->isAlive())
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800647 return setError(EGL_BAD_SURFACE, EGL_FALSE);
648 return EGL_TRUE;
649}
650
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700651EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image)
652{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700653 ImageRef _i(image);
654 if (!_i.get()) return EGL_NO_IMAGE_KHR;
655
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700656 EGLContext context = getContext();
657 if (context == EGL_NO_CONTEXT || image == EGL_NO_IMAGE_KHR)
658 return EGL_NO_IMAGE_KHR;
659
660 egl_context_t const * const c = get_context(context);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700661 if (!c->isAlive())
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700662 return EGL_NO_IMAGE_KHR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800663
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700664 egl_image_t const * const i = get_image(image);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700665 return i->images[c->impl];
666}
667
Mathias Agopian923c6612009-08-17 18:07:06 -0700668// ----------------------------------------------------------------------------
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700669
Mathias Agopian923c6612009-08-17 18:07:06 -0700670// this mutex protects:
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700671// d->disp[]
Mathias Agopian923c6612009-08-17 18:07:06 -0700672// egl_init_drivers_locked()
673//
674static pthread_mutex_t gInitDriverMutex = PTHREAD_MUTEX_INITIALIZER;
675
676EGLBoolean egl_init_drivers_locked()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800677{
678 if (sEarlyInitState) {
Mathias Agopian923c6612009-08-17 18:07:06 -0700679 // initialized by static ctor. should be set here.
680 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800681 }
682
Mathias Agopiande586972009-05-28 17:39:03 -0700683 // get our driver loader
Mathias Agopian923c6612009-08-17 18:07:06 -0700684 Loader& loader(Loader::getInstance());
Mathias Agopiande586972009-05-28 17:39:03 -0700685
Mathias Agopian923c6612009-08-17 18:07:06 -0700686 // dynamically load all our EGL implementations for all displays
687 // and retrieve the corresponding EGLDisplay
688 // if that fails, don't use this driver.
689 // TODO: currently we only deal with EGL_DEFAULT_DISPLAY
690 egl_connection_t* cnx;
691 egl_display_t* d = &gDisplay[0];
692
693 cnx = &gEGLImpl[IMPL_SOFTWARE];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800694 if (cnx->dso == 0) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700695 cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_SOFTWARE];
696 cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_SOFTWARE];
697 cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 0, cnx);
Mathias Agopian923c6612009-08-17 18:07:06 -0700698 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700699 EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
Mathias Agopian923c6612009-08-17 18:07:06 -0700700 LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for software EGL!");
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700701 d->disp[IMPL_SOFTWARE].dpy = dpy;
Mathias Agopian923c6612009-08-17 18:07:06 -0700702 if (dpy == EGL_NO_DISPLAY) {
703 loader.close(cnx->dso);
704 cnx->dso = NULL;
705 }
706 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800707 }
708
709 cnx = &gEGLImpl[IMPL_HARDWARE];
Mathias Agopian923c6612009-08-17 18:07:06 -0700710 if (cnx->dso == 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800711 char value[PROPERTY_VALUE_MAX];
712 property_get("debug.egl.hw", value, "1");
713 if (atoi(value) != 0) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700714 cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_HARDWARE];
715 cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_HARDWARE];
716 cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 1, cnx);
Mathias Agopian923c6612009-08-17 18:07:06 -0700717 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700718 EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
Mathias Agopian923c6612009-08-17 18:07:06 -0700719 LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for hardware EGL!");
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700720 d->disp[IMPL_HARDWARE].dpy = dpy;
Mathias Agopian923c6612009-08-17 18:07:06 -0700721 if (dpy == EGL_NO_DISPLAY) {
722 loader.close(cnx->dso);
723 cnx->dso = NULL;
724 }
725 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800726 } else {
727 LOGD("3D hardware acceleration is disabled");
728 }
729 }
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700730
Mathias Agopian923c6612009-08-17 18:07:06 -0700731 if (!gEGLImpl[IMPL_SOFTWARE].dso && !gEGLImpl[IMPL_HARDWARE].dso) {
732 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800733 }
734
Mathias Agopian923c6612009-08-17 18:07:06 -0700735 return EGL_TRUE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800736}
737
Mathias Agopian923c6612009-08-17 18:07:06 -0700738EGLBoolean egl_init_drivers()
739{
740 EGLBoolean res;
741 pthread_mutex_lock(&gInitDriverMutex);
742 res = egl_init_drivers_locked();
743 pthread_mutex_unlock(&gInitDriverMutex);
744 return res;
745}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700746
747// ----------------------------------------------------------------------------
748}; // namespace android
749// ----------------------------------------------------------------------------
750
751using namespace android;
752
753EGLDisplay eglGetDisplay(NativeDisplayType display)
754{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -0800755 clearError();
756
Mathias Agopian923c6612009-08-17 18:07:06 -0700757 uint32_t index = uint32_t(display);
758 if (index >= NUM_DISPLAYS) {
759 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
760 }
761
762 if (egl_init_drivers() == EGL_FALSE) {
763 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
764 }
765
766 EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU);
767 return dpy;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700768}
769
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800770// ----------------------------------------------------------------------------
771// Initialization
772// ----------------------------------------------------------------------------
773
774EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
775{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -0800776 clearError();
777
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800778 egl_display_t * const dp = get_display(dpy);
779 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
780
Mathias Agopian75bc2782010-02-05 16:17:01 -0800781 Mutex::Autolock _l(dp->lock);
782
783 if (dp->refs > 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800784 if (major != NULL) *major = VERSION_MAJOR;
785 if (minor != NULL) *minor = VERSION_MINOR;
Jack Palevich81cd0842010-03-15 20:45:21 -0700786 dp->refs++;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800787 return EGL_TRUE;
788 }
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700789
790#if EGL_TRACE
791
792 // Called both at early_init time and at this time. (Early_init is pre-zygote, so
793 // the information from that call may be stale.)
794 initEglTraceLevel();
795
796#endif
797
798 setGLHooksThreadSpecific(&gHooksNoContext);
799
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800800 // initialize each EGL and
801 // build our own extension string first, based on the extension we know
802 // and the extension supported by our client implementation
Mathias Agopian618fa102009-10-14 02:06:37 -0700803 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800804 egl_connection_t* const cnx = &gEGLImpl[i];
805 cnx->major = -1;
806 cnx->minor = -1;
807 if (!cnx->dso)
808 continue;
809
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700810#if defined(ADRENO130)
811#warning "Adreno-130 eglInitialize() workaround"
812 /*
813 * The ADRENO 130 driver returns a different EGLDisplay each time
814 * eglGetDisplay() is called, but also makes the EGLDisplay invalid
815 * after eglTerminate() has been called, so that eglInitialize()
816 * cannot be called again. Therefore, we need to make sure to call
817 * eglGetDisplay() before calling eglInitialize();
818 */
819 if (i == IMPL_HARDWARE) {
820 dp->disp[i].dpy =
Mathias Agopian618fa102009-10-14 02:06:37 -0700821 cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700822 }
823#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800824
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700825
826 EGLDisplay idpy = dp->disp[i].dpy;
Mathias Agopian618fa102009-10-14 02:06:37 -0700827 if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800828 //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p",
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700829 // i, idpy, cnx->major, cnx->minor, cnx);
830
831 // display is now initialized
832 dp->disp[i].state = egl_display_t::INITIALIZED;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800833
834 // get the query-strings for this display for each implementation
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700835 dp->disp[i].queryString.vendor =
Mathias Agopian618fa102009-10-14 02:06:37 -0700836 cnx->egl.eglQueryString(idpy, EGL_VENDOR);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700837 dp->disp[i].queryString.version =
Mathias Agopian618fa102009-10-14 02:06:37 -0700838 cnx->egl.eglQueryString(idpy, EGL_VERSION);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700839 dp->disp[i].queryString.extensions =
Mathias Agopian618fa102009-10-14 02:06:37 -0700840 cnx->egl.eglQueryString(idpy, EGL_EXTENSIONS);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700841 dp->disp[i].queryString.clientApi =
Mathias Agopian618fa102009-10-14 02:06:37 -0700842 cnx->egl.eglQueryString(idpy, EGL_CLIENT_APIS);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800843
844 } else {
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700845 LOGW("%d: eglInitialize(%p) failed (%s)", i, idpy,
Mathias Agopian618fa102009-10-14 02:06:37 -0700846 egl_strerror(cnx->egl.eglGetError()));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800847 }
848 }
849
850 EGLBoolean res = EGL_FALSE;
Mathias Agopian618fa102009-10-14 02:06:37 -0700851 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800852 egl_connection_t* const cnx = &gEGLImpl[i];
853 if (cnx->dso && cnx->major>=0 && cnx->minor>=0) {
854 EGLint n;
Mathias Agopian618fa102009-10-14 02:06:37 -0700855 if (cnx->egl.eglGetConfigs(dp->disp[i].dpy, 0, 0, &n)) {
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700856 dp->disp[i].config = (EGLConfig*)malloc(sizeof(EGLConfig)*n);
857 if (dp->disp[i].config) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700858 if (cnx->egl.eglGetConfigs(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700859 dp->disp[i].dpy, dp->disp[i].config, n,
860 &dp->disp[i].numConfigs))
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800861 {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800862 dp->numTotalConfigs += n;
863 res = EGL_TRUE;
864 }
865 }
866 }
867 }
868 }
869
870 if (res == EGL_TRUE) {
Mathias Agopiancee79392010-07-26 21:14:59 -0700871 dp->configs = new egl_config_t[ dp->numTotalConfigs ];
872 for (int i=0, k=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
873 egl_connection_t* const cnx = &gEGLImpl[i];
874 if (cnx->dso && cnx->major>=0 && cnx->minor>=0) {
875 for (int j=0 ; j<dp->disp[i].numConfigs ; j++) {
876 dp->configs[k].impl = i;
877 dp->configs[k].config = dp->disp[i].config[j];
878 dp->configs[k].configId = k + 1; // CONFIG_ID start at 1
879 // store the implementation's CONFIG_ID
880 cnx->egl.eglGetConfigAttrib(
881 dp->disp[i].dpy,
882 dp->disp[i].config[j],
883 EGL_CONFIG_ID,
884 &dp->configs[k].implConfigId);
885 k++;
886 }
887 }
888 }
889
890 // sort our configurations so we can do binary-searches
891 qsort( dp->configs,
892 dp->numTotalConfigs,
893 sizeof(egl_config_t), cmp_configs);
894
Mathias Agopian75bc2782010-02-05 16:17:01 -0800895 dp->refs++;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800896 if (major != NULL) *major = VERSION_MAJOR;
897 if (minor != NULL) *minor = VERSION_MINOR;
898 return EGL_TRUE;
899 }
900 return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
901}
902
903EGLBoolean eglTerminate(EGLDisplay dpy)
904{
Mathias Agopian923c6612009-08-17 18:07:06 -0700905 // NOTE: don't unload the drivers b/c some APIs can be called
906 // after eglTerminate() has been called. eglTerminate() only
907 // terminates an EGLDisplay, not a EGL itself.
908
Michael I. Gold4aea6bf2011-01-21 15:39:38 -0800909 clearError();
910
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800911 egl_display_t* const dp = get_display(dpy);
912 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian75bc2782010-02-05 16:17:01 -0800913
914 Mutex::Autolock _l(dp->lock);
915
916 if (dp->refs == 0) {
917 return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
918 }
919
920 // this is specific to Android, display termination is ref-counted.
Jack Palevich81cd0842010-03-15 20:45:21 -0700921 if (dp->refs > 1) {
922 dp->refs--;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800923 return EGL_TRUE;
Jack Palevich81cd0842010-03-15 20:45:21 -0700924 }
Mathias Agopiande586972009-05-28 17:39:03 -0700925
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800926 EGLBoolean res = EGL_FALSE;
Mathias Agopian618fa102009-10-14 02:06:37 -0700927 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800928 egl_connection_t* const cnx = &gEGLImpl[i];
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700929 if (cnx->dso && dp->disp[i].state == egl_display_t::INITIALIZED) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700930 if (cnx->egl.eglTerminate(dp->disp[i].dpy) == EGL_FALSE) {
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700931 LOGW("%d: eglTerminate(%p) failed (%s)", i, dp->disp[i].dpy,
Mathias Agopian618fa102009-10-14 02:06:37 -0700932 egl_strerror(cnx->egl.eglGetError()));
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700933 }
Mathias Agopian923c6612009-08-17 18:07:06 -0700934 // REVISIT: it's unclear what to do if eglTerminate() fails
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700935 free(dp->disp[i].config);
936
937 dp->disp[i].numConfigs = 0;
938 dp->disp[i].config = 0;
939 dp->disp[i].state = egl_display_t::TERMINATED;
940
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800941 res = EGL_TRUE;
942 }
943 }
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700944
945 // TODO: all egl_object_t should be marked for termination
946
Mathias Agopian75bc2782010-02-05 16:17:01 -0800947 dp->refs--;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800948 dp->numTotalConfigs = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -0700949 delete [] dp->configs;
Michael I. Gold0c3ce2a2010-12-23 13:51:36 -0800950
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800951 return res;
952}
953
954// ----------------------------------------------------------------------------
955// configuration
956// ----------------------------------------------------------------------------
957
958EGLBoolean eglGetConfigs( EGLDisplay dpy,
959 EGLConfig *configs,
960 EGLint config_size, EGLint *num_config)
961{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -0800962 clearError();
963
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800964 egl_display_t const * const dp = get_display(dpy);
965 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
966
967 GLint numConfigs = dp->numTotalConfigs;
968 if (!configs) {
969 *num_config = numConfigs;
970 return EGL_TRUE;
971 }
Mathias Agopiancee79392010-07-26 21:14:59 -0700972
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800973 GLint n = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -0700974 for (intptr_t i=0 ; i<dp->numTotalConfigs && config_size ; i++) {
975 *configs++ = EGLConfig(i);
976 config_size--;
977 n++;
978 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800979
980 *num_config = n;
981 return EGL_TRUE;
982}
983
984EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
985 EGLConfig *configs, EGLint config_size,
986 EGLint *num_config)
987{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -0800988 clearError();
989
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800990 egl_display_t const * const dp = get_display(dpy);
991 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
992
Jack Palevich749c63d2009-03-25 15:12:17 -0700993 if (num_config==0) {
994 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800995 }
996
997 EGLint n;
998 EGLBoolean res = EGL_FALSE;
999 *num_config = 0;
1000
1001
1002 // It is unfortunate, but we need to remap the EGL_CONFIG_IDs,
Mathias Agopiancee79392010-07-26 21:14:59 -07001003 // to do this, we have to go through the attrib_list array once
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001004 // to figure out both its size and if it contains an EGL_CONFIG_ID
1005 // key. If so, the full array is copied and patched.
1006 // NOTE: we assume that there can be only one occurrence
1007 // of EGL_CONFIG_ID.
1008
1009 EGLint patch_index = -1;
1010 GLint attr;
1011 size_t size = 0;
Mathias Agopian04aed212010-05-17 14:45:43 -07001012 if (attrib_list) {
1013 while ((attr=attrib_list[size]) != EGL_NONE) {
1014 if (attr == EGL_CONFIG_ID)
1015 patch_index = size;
1016 size += 2;
1017 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001018 }
1019 if (patch_index >= 0) {
1020 size += 2; // we need copy the sentinel as well
1021 EGLint* new_list = (EGLint*)malloc(size*sizeof(EGLint));
1022 if (new_list == 0)
1023 return setError(EGL_BAD_ALLOC, EGL_FALSE);
1024 memcpy(new_list, attrib_list, size*sizeof(EGLint));
1025
1026 // patch the requested EGL_CONFIG_ID
Mathias Agopiancee79392010-07-26 21:14:59 -07001027 bool found = false;
1028 EGLConfig ourConfig(0);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001029 EGLint& configId(new_list[patch_index+1]);
Mathias Agopiancee79392010-07-26 21:14:59 -07001030 for (intptr_t i=0 ; i<dp->numTotalConfigs ; i++) {
1031 if (dp->configs[i].configId == configId) {
1032 ourConfig = EGLConfig(i);
1033 configId = dp->configs[i].implConfigId;
1034 found = true;
1035 break;
1036 }
1037 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001038
Mathias Agopiancee79392010-07-26 21:14:59 -07001039 egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(ourConfig)].impl];
1040 if (found && cnx->dso) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001041 // and switch to the new list
1042 attrib_list = const_cast<const EGLint *>(new_list);
1043
1044 // At this point, the only configuration that can match is
1045 // dp->configs[i][index], however, we don't know if it would be
1046 // rejected because of the other attributes, so we do have to call
Mathias Agopian618fa102009-10-14 02:06:37 -07001047 // cnx->egl.eglChooseConfig() -- but we don't have to loop
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001048 // through all the EGLimpl[].
1049 // We also know we can only get a single config back, and we know
1050 // which one.
1051
Mathias Agopian618fa102009-10-14 02:06:37 -07001052 res = cnx->egl.eglChooseConfig(
Mathias Agopiancee79392010-07-26 21:14:59 -07001053 dp->disp[ dp->configs[intptr_t(ourConfig)].impl ].dpy,
1054 attrib_list, configs, config_size, &n);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001055 if (res && n>0) {
1056 // n has to be 0 or 1, by construction, and we already know
1057 // which config it will return (since there can be only one).
Jack Palevich749c63d2009-03-25 15:12:17 -07001058 if (configs) {
Mathias Agopiancee79392010-07-26 21:14:59 -07001059 configs[0] = ourConfig;
Jack Palevich749c63d2009-03-25 15:12:17 -07001060 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001061 *num_config = 1;
1062 }
1063 }
1064
1065 free(const_cast<EGLint *>(attrib_list));
1066 return res;
1067 }
1068
Mathias Agopiancee79392010-07-26 21:14:59 -07001069
Mathias Agopian618fa102009-10-14 02:06:37 -07001070 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001071 egl_connection_t* const cnx = &gEGLImpl[i];
1072 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001073 if (cnx->egl.eglChooseConfig(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001074 dp->disp[i].dpy, attrib_list, configs, config_size, &n)) {
Jack Palevich749c63d2009-03-25 15:12:17 -07001075 if (configs) {
1076 // now we need to convert these client EGLConfig to our
Mathias Agopiancee79392010-07-26 21:14:59 -07001077 // internal EGLConfig format.
1078 // This is done in O(n Log(n)) time.
Jack Palevich749c63d2009-03-25 15:12:17 -07001079 for (int j=0 ; j<n ; j++) {
Mathias Agopiancee79392010-07-26 21:14:59 -07001080 egl_config_t key(i, configs[j]);
1081 intptr_t index = binarySearch<egl_config_t>(
1082 dp->configs, 0, dp->numTotalConfigs, key);
Jack Palevich749c63d2009-03-25 15:12:17 -07001083 if (index >= 0) {
Mathias Agopiancee79392010-07-26 21:14:59 -07001084 configs[j] = EGLConfig(index);
Jack Palevich749c63d2009-03-25 15:12:17 -07001085 } else {
1086 return setError(EGL_BAD_CONFIG, EGL_FALSE);
1087 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001088 }
Jack Palevich749c63d2009-03-25 15:12:17 -07001089 configs += n;
1090 config_size -= n;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001091 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001092 *num_config += n;
1093 res = EGL_TRUE;
1094 }
1095 }
1096 }
1097 return res;
1098}
1099
1100EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
1101 EGLint attribute, EGLint *value)
1102{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001103 clearError();
1104
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001105 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -07001106 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001107 if (!cnx) return EGL_FALSE;
1108
1109 if (attribute == EGL_CONFIG_ID) {
Mathias Agopiancee79392010-07-26 21:14:59 -07001110 *value = dp->configs[intptr_t(config)].configId;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001111 return EGL_TRUE;
1112 }
Mathias Agopian618fa102009-10-14 02:06:37 -07001113 return cnx->egl.eglGetConfigAttrib(
Mathias Agopiancee79392010-07-26 21:14:59 -07001114 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1115 dp->configs[intptr_t(config)].config, attribute, value);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001116}
1117
1118// ----------------------------------------------------------------------------
1119// surfaces
1120// ----------------------------------------------------------------------------
1121
1122EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
1123 NativeWindowType window,
1124 const EGLint *attrib_list)
1125{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001126 clearError();
1127
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001128 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -07001129 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001130 if (cnx) {
Mathias Agopian644bb2a2010-11-24 15:59:35 -08001131 EGLDisplay iDpy = dp->disp[ dp->configs[intptr_t(config)].impl ].dpy;
1132 EGLConfig iConfig = dp->configs[intptr_t(config)].config;
1133 EGLint format;
1134
Jamie Gennis5c0c93a2011-03-14 15:34:04 -07001135 // for now fail if the window is not a Surface.
1136 int type = -1;
1137 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
1138 if ((anw->query(window, NATIVE_WINDOW_CONCRETE_TYPE, &type) != 0) ||
1139 (type == NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT)) {
1140 LOGE("native window is a SurfaceTextureClient (currently "
1141 "unsupported)");
1142 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
1143 }
1144
Mathias Agopian644bb2a2010-11-24 15:59:35 -08001145 // set the native window's buffers format to match this config
1146 if (cnx->egl.eglGetConfigAttrib(iDpy,
1147 iConfig, EGL_NATIVE_VISUAL_ID, &format)) {
1148 if (format != 0) {
1149 native_window_set_buffers_geometry(window, 0, 0, format);
1150 }
1151 }
1152
Mathias Agopian618fa102009-10-14 02:06:37 -07001153 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian644bb2a2010-11-24 15:59:35 -08001154 iDpy, iConfig, window, attrib_list);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001155 if (surface != EGL_NO_SURFACE) {
Mathias Agopian644bb2a2010-11-24 15:59:35 -08001156 egl_surface_t* s = new egl_surface_t(dpy, config, window, surface,
Mathias Agopiancee79392010-07-26 21:14:59 -07001157 dp->configs[intptr_t(config)].impl, cnx);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001158 return s;
1159 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001160 }
1161 return EGL_NO_SURFACE;
1162}
1163
1164EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
1165 NativePixmapType pixmap,
1166 const EGLint *attrib_list)
1167{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001168 clearError();
1169
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001170 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -07001171 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001172 if (cnx) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001173 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopiancee79392010-07-26 21:14:59 -07001174 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1175 dp->configs[intptr_t(config)].config, pixmap, attrib_list);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001176 if (surface != EGL_NO_SURFACE) {
Mathias Agopian644bb2a2010-11-24 15:59:35 -08001177 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
Mathias Agopiancee79392010-07-26 21:14:59 -07001178 dp->configs[intptr_t(config)].impl, cnx);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001179 return s;
1180 }
1181 }
1182 return EGL_NO_SURFACE;
1183}
1184
1185EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
1186 const EGLint *attrib_list)
1187{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001188 clearError();
1189
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001190 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -07001191 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001192 if (cnx) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001193 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopiancee79392010-07-26 21:14:59 -07001194 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1195 dp->configs[intptr_t(config)].config, attrib_list);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001196 if (surface != EGL_NO_SURFACE) {
Mathias Agopian644bb2a2010-11-24 15:59:35 -08001197 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
Mathias Agopiancee79392010-07-26 21:14:59 -07001198 dp->configs[intptr_t(config)].impl, cnx);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001199 return s;
1200 }
1201 }
1202 return EGL_NO_SURFACE;
1203}
1204
1205EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
1206{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001207 clearError();
1208
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001209 SurfaceRef _s(surface);
1210 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1211
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001212 if (!validate_display_surface(dpy, surface))
1213 return EGL_FALSE;
1214 egl_display_t const * const dp = get_display(dpy);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001215
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001216 egl_surface_t * const s = get_surface(surface);
Mathias Agopian618fa102009-10-14 02:06:37 -07001217 EGLBoolean result = s->cnx->egl.eglDestroySurface(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001218 dp->disp[s->impl].dpy, s->surface);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001219 if (result == EGL_TRUE) {
Mathias Agopian644bb2a2010-11-24 15:59:35 -08001220 if (s->win != NULL) {
1221 native_window_set_buffers_geometry(s->win.get(), 0, 0, 0);
1222 }
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001223 _s.terminate();
1224 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001225 return result;
1226}
1227
1228EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
1229 EGLint attribute, EGLint *value)
1230{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001231 clearError();
1232
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001233 SurfaceRef _s(surface);
1234 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1235
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001236 if (!validate_display_surface(dpy, surface))
1237 return EGL_FALSE;
1238 egl_display_t const * const dp = get_display(dpy);
1239 egl_surface_t const * const s = get_surface(surface);
1240
Mathias Agopiancee79392010-07-26 21:14:59 -07001241 EGLBoolean result(EGL_TRUE);
1242 if (attribute == EGL_CONFIG_ID) {
1243 // We need to remap EGL_CONFIG_IDs
1244 *value = dp->configs[intptr_t(s->config)].configId;
1245 } else {
1246 result = s->cnx->egl.eglQuerySurface(
1247 dp->disp[s->impl].dpy, s->surface, attribute, value);
1248 }
1249
1250 return result;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001251}
1252
1253// ----------------------------------------------------------------------------
Mathias Agopiancee79392010-07-26 21:14:59 -07001254// Contexts
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001255// ----------------------------------------------------------------------------
1256
1257EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
1258 EGLContext share_list, const EGLint *attrib_list)
1259{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001260 clearError();
1261
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001262 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -07001263 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001264 if (cnx) {
Jamie Gennis4c39f8f2010-07-02 11:39:12 -07001265 if (share_list != EGL_NO_CONTEXT) {
1266 egl_context_t* const c = get_context(share_list);
1267 share_list = c->context;
1268 }
Mathias Agopian618fa102009-10-14 02:06:37 -07001269 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopiancee79392010-07-26 21:14:59 -07001270 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1271 dp->configs[intptr_t(config)].config,
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001272 share_list, attrib_list);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001273 if (context != EGL_NO_CONTEXT) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001274 // figure out if it's a GLESv1 or GLESv2
1275 int version = 0;
1276 if (attrib_list) {
1277 while (*attrib_list != EGL_NONE) {
1278 GLint attr = *attrib_list++;
1279 GLint value = *attrib_list++;
1280 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
1281 if (value == 1) {
1282 version = GLESv1_INDEX;
1283 } else if (value == 2) {
1284 version = GLESv2_INDEX;
1285 }
1286 }
1287 };
1288 }
Mathias Agopiancee79392010-07-26 21:14:59 -07001289 egl_context_t* c = new egl_context_t(dpy, context, config,
1290 dp->configs[intptr_t(config)].impl, cnx, version);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001291 return c;
1292 }
1293 }
1294 return EGL_NO_CONTEXT;
1295}
1296
1297EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1298{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001299 clearError();
1300
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001301 ContextRef _c(ctx);
1302 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1303
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001304 if (!validate_display_context(dpy, ctx))
1305 return EGL_FALSE;
1306 egl_display_t const * const dp = get_display(dpy);
1307 egl_context_t * const c = get_context(ctx);
Mathias Agopian618fa102009-10-14 02:06:37 -07001308 EGLBoolean result = c->cnx->egl.eglDestroyContext(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001309 dp->disp[c->impl].dpy, c->context);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001310 if (result == EGL_TRUE) {
1311 _c.terminate();
1312 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001313 return result;
1314}
1315
Michael I. Gold0c3ce2a2010-12-23 13:51:36 -08001316static void loseCurrent(egl_context_t * cur_c)
1317{
1318 if (cur_c) {
1319 egl_surface_t * cur_r = get_surface(cur_c->read);
1320 egl_surface_t * cur_d = get_surface(cur_c->draw);
1321
1322 // by construction, these are either 0 or valid (possibly terminated)
1323 // it should be impossible for these to be invalid
1324 ContextRef _cur_c(cur_c);
1325 SurfaceRef _cur_r(cur_r);
1326 SurfaceRef _cur_d(cur_d);
1327
1328 cur_c->read = NULL;
1329 cur_c->draw = NULL;
1330
1331 _cur_c.release();
1332 _cur_r.release();
1333 _cur_d.release();
1334 }
1335}
1336
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001337EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
1338 EGLSurface read, EGLContext ctx)
1339{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001340 clearError();
1341
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001342 // get a reference to the object passed in
1343 ContextRef _c(ctx);
1344 SurfaceRef _d(draw);
1345 SurfaceRef _r(read);
1346
1347 // validate the display and the context (if not EGL_NO_CONTEXT)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001348 egl_display_t const * const dp = get_display(dpy);
1349 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001350 if ((ctx != EGL_NO_CONTEXT) && (!validate_display_context(dpy, ctx))) {
1351 // EGL_NO_CONTEXT is valid
1352 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001353 }
1354
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001355 // these are the underlying implementation's object
1356 EGLContext impl_ctx = EGL_NO_CONTEXT;
Mathias Agopianaf742132009-06-25 00:01:11 -07001357 EGLSurface impl_draw = EGL_NO_SURFACE;
1358 EGLSurface impl_read = EGL_NO_SURFACE;
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001359
1360 // these are our objects structs passed in
1361 egl_context_t * c = NULL;
1362 egl_surface_t const * d = NULL;
1363 egl_surface_t const * r = NULL;
1364
1365 // these are the current objects structs
1366 egl_context_t * cur_c = get_context(getContext());
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001367
1368 if (ctx != EGL_NO_CONTEXT) {
1369 c = get_context(ctx);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001370 impl_ctx = c->context;
1371 } else {
1372 // no context given, use the implementation of the current context
1373 if (cur_c == NULL) {
1374 // no current context
1375 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
Mathias Agopian8063c3a2010-01-25 11:30:11 -08001376 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
1377 return setError(EGL_BAD_MATCH, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001378 }
Mathias Agopian8063c3a2010-01-25 11:30:11 -08001379 // not an error, there is just no current context.
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001380 return EGL_TRUE;
1381 }
1382 }
1383
1384 // retrieve the underlying implementation's draw EGLSurface
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001385 if (draw != EGL_NO_SURFACE) {
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001386 d = get_surface(draw);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001387 // make sure the EGLContext and EGLSurface passed in are for
1388 // the same driver
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001389 if (c && d->impl != c->impl)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001390 return setError(EGL_BAD_MATCH, EGL_FALSE);
Mathias Agopianaf742132009-06-25 00:01:11 -07001391 impl_draw = d->surface;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001392 }
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001393
1394 // retrieve the underlying implementation's read EGLSurface
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001395 if (read != EGL_NO_SURFACE) {
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001396 r = get_surface(read);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001397 // make sure the EGLContext and EGLSurface passed in are for
1398 // the same driver
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001399 if (c && r->impl != c->impl)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001400 return setError(EGL_BAD_MATCH, EGL_FALSE);
Mathias Agopianaf742132009-06-25 00:01:11 -07001401 impl_read = r->surface;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001402 }
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001403
1404 EGLBoolean result;
1405
1406 if (c) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001407 result = c->cnx->egl.eglMakeCurrent(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001408 dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001409 } else {
Mathias Agopian618fa102009-10-14 02:06:37 -07001410 result = cur_c->cnx->egl.eglMakeCurrent(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001411 dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001412 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001413
1414 if (result == EGL_TRUE) {
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001415
Michael I. Gold0c3ce2a2010-12-23 13:51:36 -08001416 loseCurrent(cur_c);
1417
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001418 if (ctx != EGL_NO_CONTEXT) {
David Li65948aa2011-03-10 16:40:37 -08001419 if (!c->dbg && gEGLDebugLevel > 0)
1420 c->dbg = CreateDbgContext(c->version, c->cnx->hooks[c->version]);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -07001421 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001422 setContext(ctx);
1423 _c.acquire();
Michael I. Gold0c3ce2a2010-12-23 13:51:36 -08001424 _r.acquire();
1425 _d.acquire();
1426 c->read = read;
1427 c->draw = draw;
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001428 } else {
Jack Palevicha2dd6cf2010-10-26 15:21:24 -07001429 setGLHooksThreadSpecific(&gHooksNoContext);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001430 setContext(EGL_NO_CONTEXT);
1431 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001432 }
1433 return result;
1434}
1435
1436
1437EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
1438 EGLint attribute, EGLint *value)
1439{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001440 clearError();
1441
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001442 ContextRef _c(ctx);
1443 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1444
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001445 if (!validate_display_context(dpy, ctx))
1446 return EGL_FALSE;
1447
1448 egl_display_t const * const dp = get_display(dpy);
1449 egl_context_t * const c = get_context(ctx);
1450
Mathias Agopiancee79392010-07-26 21:14:59 -07001451 EGLBoolean result(EGL_TRUE);
1452 if (attribute == EGL_CONFIG_ID) {
1453 *value = dp->configs[intptr_t(c->config)].configId;
1454 } else {
1455 // We need to remap EGL_CONFIG_IDs
1456 result = c->cnx->egl.eglQueryContext(
1457 dp->disp[c->impl].dpy, c->context, attribute, value);
1458 }
1459
1460 return result;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001461}
1462
1463EGLContext eglGetCurrentContext(void)
1464{
Mathias Agopian923c6612009-08-17 18:07:06 -07001465 // could be called before eglInitialize(), but we wouldn't have a context
1466 // then, and this function would correctly return EGL_NO_CONTEXT.
1467
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001468 clearError();
1469
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001470 EGLContext ctx = getContext();
1471 return ctx;
1472}
1473
1474EGLSurface eglGetCurrentSurface(EGLint readdraw)
1475{
Mathias Agopian923c6612009-08-17 18:07:06 -07001476 // could be called before eglInitialize(), but we wouldn't have a context
1477 // then, and this function would correctly return EGL_NO_SURFACE.
1478
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001479 clearError();
1480
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001481 EGLContext ctx = getContext();
1482 if (ctx) {
1483 egl_context_t const * const c = get_context(ctx);
1484 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1485 switch (readdraw) {
1486 case EGL_READ: return c->read;
1487 case EGL_DRAW: return c->draw;
1488 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1489 }
1490 }
1491 return EGL_NO_SURFACE;
1492}
1493
1494EGLDisplay eglGetCurrentDisplay(void)
1495{
Mathias Agopian923c6612009-08-17 18:07:06 -07001496 // could be called before eglInitialize(), but we wouldn't have a context
1497 // then, and this function would correctly return EGL_NO_DISPLAY.
1498
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001499 clearError();
1500
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001501 EGLContext ctx = getContext();
1502 if (ctx) {
1503 egl_context_t const * const c = get_context(ctx);
1504 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1505 return c->dpy;
1506 }
1507 return EGL_NO_DISPLAY;
1508}
1509
1510EGLBoolean eglWaitGL(void)
1511{
Mathias Agopian923c6612009-08-17 18:07:06 -07001512 // could be called before eglInitialize(), but we wouldn't have a context
1513 // then, and this function would return GL_TRUE, which isn't wrong.
1514
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001515 clearError();
1516
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001517 EGLBoolean res = EGL_TRUE;
1518 EGLContext ctx = getContext();
1519 if (ctx) {
1520 egl_context_t const * const c = get_context(ctx);
1521 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1522 if (uint32_t(c->impl)>=2)
1523 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1524 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1525 if (!cnx->dso)
1526 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian618fa102009-10-14 02:06:37 -07001527 res = cnx->egl.eglWaitGL();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001528 }
1529 return res;
1530}
1531
1532EGLBoolean eglWaitNative(EGLint engine)
1533{
Mathias Agopian923c6612009-08-17 18:07:06 -07001534 // could be called before eglInitialize(), but we wouldn't have a context
1535 // then, and this function would return GL_TRUE, which isn't wrong.
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001536
1537 clearError();
1538
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001539 EGLBoolean res = EGL_TRUE;
1540 EGLContext ctx = getContext();
1541 if (ctx) {
1542 egl_context_t const * const c = get_context(ctx);
1543 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1544 if (uint32_t(c->impl)>=2)
1545 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1546 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1547 if (!cnx->dso)
1548 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian618fa102009-10-14 02:06:37 -07001549 res = cnx->egl.eglWaitNative(engine);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001550 }
1551 return res;
1552}
1553
1554EGLint eglGetError(void)
1555{
1556 EGLint result = EGL_SUCCESS;
Mathias Agopian02dafb52010-09-21 15:43:59 -07001557 EGLint err;
Mathias Agopian618fa102009-10-14 02:06:37 -07001558 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
Mathias Agopian02dafb52010-09-21 15:43:59 -07001559 err = EGL_SUCCESS;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001560 egl_connection_t* const cnx = &gEGLImpl[i];
1561 if (cnx->dso)
Mathias Agopian618fa102009-10-14 02:06:37 -07001562 err = cnx->egl.eglGetError();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001563 if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
1564 result = err;
1565 }
Mathias Agopian02dafb52010-09-21 15:43:59 -07001566 err = getError();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001567 if (result == EGL_SUCCESS)
Mathias Agopian02dafb52010-09-21 15:43:59 -07001568 result = err;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001569 return result;
1570}
1571
Michael I. Gold609bb4d2011-01-04 01:16:59 -08001572// Note: Similar implementations of these functions also exist in
1573// gl2.cpp and gl.cpp, and are used by applications that call the
1574// exported entry points directly.
1575typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
1576typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
1577
1578static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL;
1579static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL;
1580
1581static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image)
1582{
1583 GLeglImageOES implImage =
1584 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
1585 glEGLImageTargetTexture2DOES_impl(target, implImage);
1586}
1587
1588static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image)
1589{
1590 GLeglImageOES implImage =
1591 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
1592 glEGLImageTargetRenderbufferStorageOES_impl(target, implImage);
1593}
1594
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001595__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001596{
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001597 // eglGetProcAddress() could be the very first function called
1598 // in which case we must make sure we've initialized ourselves, this
1599 // happens the first time egl_get_display() is called.
Mathias Agopian923c6612009-08-17 18:07:06 -07001600
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001601 clearError();
1602
Mathias Agopian923c6612009-08-17 18:07:06 -07001603 if (egl_init_drivers() == EGL_FALSE) {
1604 setError(EGL_BAD_PARAMETER, NULL);
1605 return NULL;
1606 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001607
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001608 __eglMustCastToProperFunctionPointerType addr;
1609 addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap));
1610 if (addr) return addr;
1611
Mathias Agopian24035332010-08-02 17:34:32 -07001612 // this protects accesses to gGLExtentionMap and gGLExtentionSlot
1613 pthread_mutex_lock(&gInitDriverMutex);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001614
Mathias Agopian24035332010-08-02 17:34:32 -07001615 /*
1616 * Since eglGetProcAddress() is not associated to anything, it needs
1617 * to return a function pointer that "works" regardless of what
1618 * the current context is.
1619 *
1620 * For this reason, we return a "forwarder", a small stub that takes
1621 * care of calling the function associated with the context
1622 * currently bound.
1623 *
1624 * We first look for extensions we've already resolved, if we're seeing
1625 * this extension for the first time, we go through all our
1626 * implementations and call eglGetProcAddress() and record the
1627 * result in the appropriate implementation hooks and return the
1628 * address of the forwarder corresponding to that hook set.
1629 *
1630 */
1631
1632 const String8 name(procname);
1633 addr = gGLExtentionMap.valueFor(name);
1634 const int slot = gGLExtentionSlot;
1635
1636 LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
1637 "no more slots for eglGetProcAddress(\"%s\")",
1638 procname);
1639
1640 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
1641 bool found = false;
1642 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1643 egl_connection_t* const cnx = &gEGLImpl[i];
1644 if (cnx->dso && cnx->egl.eglGetProcAddress) {
1645 found = true;
Mathias Agopian4a88b522010-08-13 12:19:04 -07001646 // Extensions are independent of the bound context
1647 cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
1648 cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
Jack Palevicha2dd6cf2010-10-26 15:21:24 -07001649#if EGL_TRACE
David Li2f5a6552011-03-01 16:08:10 -08001650 gHooksDebug.ext.extensions[slot] = gHooksTrace.ext.extensions[slot] =
Jack Palevicha2dd6cf2010-10-26 15:21:24 -07001651#endif
Mathias Agopian24035332010-08-02 17:34:32 -07001652 cnx->egl.eglGetProcAddress(procname);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001653 }
1654 }
Mathias Agopian24035332010-08-02 17:34:32 -07001655 if (found) {
1656 addr = gExtensionForwarders[slot];
Michael I. Gold609bb4d2011-01-04 01:16:59 -08001657
1658 if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) {
1659 glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr;
1660 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper;
1661 }
1662 if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) {
1663 glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr;
1664 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper;
1665 }
1666
Mathias Agopian24035332010-08-02 17:34:32 -07001667 gGLExtentionMap.add(name, addr);
1668 gGLExtentionSlot++;
1669 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001670 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001671
Mathias Agopian24035332010-08-02 17:34:32 -07001672 pthread_mutex_unlock(&gInitDriverMutex);
Mathias Agopian24035332010-08-02 17:34:32 -07001673 return addr;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001674}
1675
1676EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
1677{
David Lib33d5cf2011-03-04 17:50:48 -08001678 EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw);
1679 if (gEGLDebugLevel > 0)
1680 Debug_eglSwapBuffers(dpy, draw);
1681
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001682 clearError();
1683
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001684 SurfaceRef _s(draw);
1685 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1686
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001687 if (!validate_display_surface(dpy, draw))
1688 return EGL_FALSE;
1689 egl_display_t const * const dp = get_display(dpy);
1690 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian618fa102009-10-14 02:06:37 -07001691 return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001692}
1693
1694EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1695 NativePixmapType target)
1696{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001697 clearError();
1698
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001699 SurfaceRef _s(surface);
1700 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1701
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001702 if (!validate_display_surface(dpy, surface))
1703 return EGL_FALSE;
1704 egl_display_t const * const dp = get_display(dpy);
1705 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian618fa102009-10-14 02:06:37 -07001706 return s->cnx->egl.eglCopyBuffers(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001707 dp->disp[s->impl].dpy, s->surface, target);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001708}
1709
1710const char* eglQueryString(EGLDisplay dpy, EGLint name)
1711{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001712 clearError();
1713
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001714 egl_display_t const * const dp = get_display(dpy);
1715 switch (name) {
1716 case EGL_VENDOR:
1717 return gVendorString;
1718 case EGL_VERSION:
1719 return gVersionString;
1720 case EGL_EXTENSIONS:
1721 return gExtensionString;
1722 case EGL_CLIENT_APIS:
1723 return gClientApiString;
1724 }
1725 return setError(EGL_BAD_PARAMETER, (const char *)0);
1726}
1727
1728
1729// ----------------------------------------------------------------------------
1730// EGL 1.1
1731// ----------------------------------------------------------------------------
1732
1733EGLBoolean eglSurfaceAttrib(
1734 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1735{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001736 clearError();
1737
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001738 SurfaceRef _s(surface);
1739 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1740
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001741 if (!validate_display_surface(dpy, surface))
1742 return EGL_FALSE;
1743 egl_display_t const * const dp = get_display(dpy);
1744 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian618fa102009-10-14 02:06:37 -07001745 if (s->cnx->egl.eglSurfaceAttrib) {
1746 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001747 dp->disp[s->impl].dpy, s->surface, attribute, value);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001748 }
1749 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1750}
1751
1752EGLBoolean eglBindTexImage(
1753 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1754{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001755 clearError();
1756
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001757 SurfaceRef _s(surface);
1758 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1759
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001760 if (!validate_display_surface(dpy, surface))
1761 return EGL_FALSE;
1762 egl_display_t const * const dp = get_display(dpy);
1763 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian618fa102009-10-14 02:06:37 -07001764 if (s->cnx->egl.eglBindTexImage) {
1765 return s->cnx->egl.eglBindTexImage(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001766 dp->disp[s->impl].dpy, s->surface, buffer);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001767 }
1768 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1769}
1770
1771EGLBoolean eglReleaseTexImage(
1772 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1773{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001774 clearError();
1775
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001776 SurfaceRef _s(surface);
1777 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1778
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001779 if (!validate_display_surface(dpy, surface))
1780 return EGL_FALSE;
1781 egl_display_t const * const dp = get_display(dpy);
1782 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian618fa102009-10-14 02:06:37 -07001783 if (s->cnx->egl.eglReleaseTexImage) {
1784 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001785 dp->disp[s->impl].dpy, s->surface, buffer);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001786 }
1787 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1788}
1789
1790EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1791{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001792 clearError();
1793
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001794 egl_display_t * const dp = get_display(dpy);
1795 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1796
1797 EGLBoolean res = EGL_TRUE;
Mathias Agopian618fa102009-10-14 02:06:37 -07001798 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001799 egl_connection_t* const cnx = &gEGLImpl[i];
1800 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001801 if (cnx->egl.eglSwapInterval) {
1802 if (cnx->egl.eglSwapInterval(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001803 dp->disp[i].dpy, interval) == EGL_FALSE) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001804 res = EGL_FALSE;
1805 }
1806 }
1807 }
1808 }
1809 return res;
1810}
1811
1812
1813// ----------------------------------------------------------------------------
1814// EGL 1.2
1815// ----------------------------------------------------------------------------
1816
1817EGLBoolean eglWaitClient(void)
1818{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001819 clearError();
1820
Mathias Agopian923c6612009-08-17 18:07:06 -07001821 // could be called before eglInitialize(), but we wouldn't have a context
1822 // then, and this function would return GL_TRUE, which isn't wrong.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001823 EGLBoolean res = EGL_TRUE;
1824 EGLContext ctx = getContext();
1825 if (ctx) {
1826 egl_context_t const * const c = get_context(ctx);
1827 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1828 if (uint32_t(c->impl)>=2)
1829 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1830 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1831 if (!cnx->dso)
1832 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian618fa102009-10-14 02:06:37 -07001833 if (cnx->egl.eglWaitClient) {
1834 res = cnx->egl.eglWaitClient();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001835 } else {
Mathias Agopian618fa102009-10-14 02:06:37 -07001836 res = cnx->egl.eglWaitGL();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001837 }
1838 }
1839 return res;
1840}
1841
1842EGLBoolean eglBindAPI(EGLenum api)
1843{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001844 clearError();
1845
Mathias Agopian923c6612009-08-17 18:07:06 -07001846 if (egl_init_drivers() == EGL_FALSE) {
1847 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1848 }
1849
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001850 // bind this API on all EGLs
1851 EGLBoolean res = EGL_TRUE;
Mathias Agopian618fa102009-10-14 02:06:37 -07001852 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001853 egl_connection_t* const cnx = &gEGLImpl[i];
1854 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001855 if (cnx->egl.eglBindAPI) {
1856 if (cnx->egl.eglBindAPI(api) == EGL_FALSE) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001857 res = EGL_FALSE;
1858 }
1859 }
1860 }
1861 }
1862 return res;
1863}
1864
1865EGLenum eglQueryAPI(void)
1866{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001867 clearError();
1868
Mathias Agopian923c6612009-08-17 18:07:06 -07001869 if (egl_init_drivers() == EGL_FALSE) {
1870 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1871 }
1872
Mathias Agopian618fa102009-10-14 02:06:37 -07001873 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001874 egl_connection_t* const cnx = &gEGLImpl[i];
1875 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001876 if (cnx->egl.eglQueryAPI) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001877 // the first one we find is okay, because they all
1878 // should be the same
Mathias Agopian618fa102009-10-14 02:06:37 -07001879 return cnx->egl.eglQueryAPI();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001880 }
1881 }
1882 }
1883 // or, it can only be OpenGL ES
1884 return EGL_OPENGL_ES_API;
1885}
1886
1887EGLBoolean eglReleaseThread(void)
1888{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001889 clearError();
1890
Michael I. Gold0c3ce2a2010-12-23 13:51:36 -08001891 // If there is context bound to the thread, release it
1892 loseCurrent(get_context(getContext()));
1893
Mathias Agopian618fa102009-10-14 02:06:37 -07001894 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001895 egl_connection_t* const cnx = &gEGLImpl[i];
1896 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001897 if (cnx->egl.eglReleaseThread) {
1898 cnx->egl.eglReleaseThread();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001899 }
1900 }
1901 }
1902 clearTLS();
1903 return EGL_TRUE;
1904}
1905
1906EGLSurface eglCreatePbufferFromClientBuffer(
1907 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1908 EGLConfig config, const EGLint *attrib_list)
1909{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001910 clearError();
1911
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001912 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -07001913 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001914 if (!cnx) return EGL_FALSE;
Mathias Agopian618fa102009-10-14 02:06:37 -07001915 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1916 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopiancee79392010-07-26 21:14:59 -07001917 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1918 buftype, buffer,
1919 dp->configs[intptr_t(config)].config, attrib_list);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001920 }
1921 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1922}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001923
1924// ----------------------------------------------------------------------------
1925// EGL_EGLEXT_VERSION 3
1926// ----------------------------------------------------------------------------
1927
1928EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1929 const EGLint *attrib_list)
1930{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001931 clearError();
1932
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001933 SurfaceRef _s(surface);
1934 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1935
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001936 if (!validate_display_surface(dpy, surface))
Mathias Agopian24e5f522009-08-12 21:18:15 -07001937 return EGL_FALSE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001938
1939 egl_display_t const * const dp = get_display(dpy);
1940 egl_surface_t const * const s = get_surface(surface);
1941
Mathias Agopian618fa102009-10-14 02:06:37 -07001942 if (s->cnx->egl.eglLockSurfaceKHR) {
1943 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001944 dp->disp[s->impl].dpy, s->surface, attrib_list);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001945 }
Mathias Agopian24e5f522009-08-12 21:18:15 -07001946 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001947}
1948
1949EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1950{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001951 clearError();
1952
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001953 SurfaceRef _s(surface);
1954 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1955
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001956 if (!validate_display_surface(dpy, surface))
Mathias Agopian24e5f522009-08-12 21:18:15 -07001957 return EGL_FALSE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001958
1959 egl_display_t const * const dp = get_display(dpy);
1960 egl_surface_t const * const s = get_surface(surface);
1961
Mathias Agopian618fa102009-10-14 02:06:37 -07001962 if (s->cnx->egl.eglUnlockSurfaceKHR) {
1963 return s->cnx->egl.eglUnlockSurfaceKHR(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001964 dp->disp[s->impl].dpy, s->surface);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001965 }
Mathias Agopian24e5f522009-08-12 21:18:15 -07001966 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001967}
1968
1969EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1970 EGLClientBuffer buffer, const EGLint *attrib_list)
1971{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001972 clearError();
1973
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001974 if (ctx != EGL_NO_CONTEXT) {
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001975 ContextRef _c(ctx);
1976 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001977 if (!validate_display_context(dpy, ctx))
1978 return EGL_NO_IMAGE_KHR;
1979 egl_display_t const * const dp = get_display(dpy);
1980 egl_context_t * const c = get_context(ctx);
1981 // since we have an EGLContext, we know which implementation to use
Mathias Agopian618fa102009-10-14 02:06:37 -07001982 EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001983 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001984 if (image == EGL_NO_IMAGE_KHR)
1985 return image;
1986
1987 egl_image_t* result = new egl_image_t(dpy, ctx);
1988 result->images[c->impl] = image;
1989 return (EGLImageKHR)result;
1990 } else {
1991 // EGL_NO_CONTEXT is a valid parameter
1992 egl_display_t const * const dp = get_display(dpy);
1993 if (dp == 0) {
1994 return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
1995 }
Mathias Agopiandf2d9292009-10-28 21:00:29 -07001996
1997 /* Since we don't have a way to know which implementation to call,
1998 * we're calling all of them. If at least one of the implementation
1999 * succeeded, this is a success.
2000 */
2001
2002 EGLint currentError = eglGetError();
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002003
Mathias Agopian618fa102009-10-14 02:06:37 -07002004 EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS];
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002005 bool success = false;
Mathias Agopian618fa102009-10-14 02:06:37 -07002006 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002007 egl_connection_t* const cnx = &gEGLImpl[i];
2008 implImages[i] = EGL_NO_IMAGE_KHR;
2009 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07002010 if (cnx->egl.eglCreateImageKHR) {
2011 implImages[i] = cnx->egl.eglCreateImageKHR(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07002012 dp->disp[i].dpy, ctx, target, buffer, attrib_list);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002013 if (implImages[i] != EGL_NO_IMAGE_KHR) {
2014 success = true;
2015 }
2016 }
2017 }
2018 }
Mathias Agopiandf2d9292009-10-28 21:00:29 -07002019
2020 if (!success) {
2021 // failure, if there was an error when we entered this function,
2022 // the error flag must not be updated.
2023 // Otherwise, the error is whatever happened in the implementation
2024 // that faulted.
2025 if (currentError != EGL_SUCCESS) {
2026 setError(currentError, EGL_NO_IMAGE_KHR);
2027 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002028 return EGL_NO_IMAGE_KHR;
Mathias Agopiandf2d9292009-10-28 21:00:29 -07002029 } else {
2030 // In case of success, we need to clear all error flags
2031 // (especially those caused by the implementation that didn't
Mathias Agopian863e5fd2009-10-29 18:29:30 -07002032 // succeed). TODO: we could avoid this if we knew this was
Mathias Agopiandf2d9292009-10-28 21:00:29 -07002033 // a "full" success (all implementation succeeded).
2034 eglGetError();
2035 }
2036
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002037 egl_image_t* result = new egl_image_t(dpy, ctx);
2038 memcpy(result->images, implImages, sizeof(implImages));
2039 return (EGLImageKHR)result;
2040 }
2041}
2042
2043EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
2044{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08002045 clearError();
2046
Mathias Agopian9429e9c2009-08-21 02:18:25 -07002047 egl_display_t const * const dp = get_display(dpy);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002048 if (dp == 0) {
2049 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2050 }
2051
Mathias Agopian9429e9c2009-08-21 02:18:25 -07002052 ImageRef _i(img);
2053 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002054
Mathias Agopian9429e9c2009-08-21 02:18:25 -07002055 egl_image_t* image = get_image(img);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002056 bool success = false;
Mathias Agopian618fa102009-10-14 02:06:37 -07002057 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002058 egl_connection_t* const cnx = &gEGLImpl[i];
2059 if (image->images[i] != EGL_NO_IMAGE_KHR) {
2060 if (cnx->dso) {
Mathias Agopian77fbf8d2010-09-09 11:12:54 -07002061 if (cnx->egl.eglDestroyImageKHR) {
Mathias Agopian618fa102009-10-14 02:06:37 -07002062 if (cnx->egl.eglDestroyImageKHR(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07002063 dp->disp[i].dpy, image->images[i])) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002064 success = true;
2065 }
2066 }
2067 }
2068 }
2069 }
2070 if (!success)
2071 return EGL_FALSE;
2072
Mathias Agopian9429e9c2009-08-21 02:18:25 -07002073 _i.terminate();
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002074
Mathias Agopian24e5f522009-08-12 21:18:15 -07002075 return EGL_TRUE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002076}
Mathias Agopiandf3ca302009-05-04 19:29:25 -07002077
Mathias Agopianc291f5852010-08-27 16:48:56 -07002078// ----------------------------------------------------------------------------
2079// EGL_EGLEXT_VERSION 5
2080// ----------------------------------------------------------------------------
2081
2082
2083EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
2084{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08002085 clearError();
2086
Mathias Agopianc291f5852010-08-27 16:48:56 -07002087 EGLContext ctx = eglGetCurrentContext();
2088 ContextRef _c(ctx);
Mathias Agopiana93b9572010-09-21 16:22:10 -07002089 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR);
Mathias Agopianc291f5852010-08-27 16:48:56 -07002090 if (!validate_display_context(dpy, ctx))
Mathias Agopiana93b9572010-09-21 16:22:10 -07002091 return EGL_NO_SYNC_KHR;
Mathias Agopianc291f5852010-08-27 16:48:56 -07002092 egl_display_t const * const dp = get_display(dpy);
2093 egl_context_t * const c = get_context(ctx);
Mathias Agopiana93b9572010-09-21 16:22:10 -07002094 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopianc291f5852010-08-27 16:48:56 -07002095 if (c->cnx->egl.eglCreateSyncKHR) {
2096 EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR(
2097 dp->disp[c->impl].dpy, type, attrib_list);
Mathias Agopiana93b9572010-09-21 16:22:10 -07002098 if (sync == EGL_NO_SYNC_KHR)
Mathias Agopianc291f5852010-08-27 16:48:56 -07002099 return sync;
2100 result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync);
2101 }
2102 return (EGLSyncKHR)result;
2103}
2104
2105EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
2106{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08002107 clearError();
2108
Mathias Agopianc291f5852010-08-27 16:48:56 -07002109 egl_display_t const * const dp = get_display(dpy);
2110 if (dp == 0) {
2111 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2112 }
2113
2114 SyncRef _s(sync);
2115 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2116 egl_sync_t* syncObject = get_sync(sync);
2117
2118 EGLContext ctx = syncObject->context;
2119 ContextRef _c(ctx);
2120 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
2121 if (!validate_display_context(dpy, ctx))
2122 return EGL_FALSE;
2123
Mathias Agopian36bdf142011-03-16 14:19:03 -07002124 EGLBoolean result = EGL_FALSE;
Mathias Agopianc291f5852010-08-27 16:48:56 -07002125 egl_context_t * const c = get_context(ctx);
Mathias Agopianc291f5852010-08-27 16:48:56 -07002126 if (c->cnx->egl.eglDestroySyncKHR) {
Mathias Agopian36bdf142011-03-16 14:19:03 -07002127 result = c->cnx->egl.eglDestroySyncKHR(
Mathias Agopianc291f5852010-08-27 16:48:56 -07002128 dp->disp[c->impl].dpy, syncObject->sync);
Mathias Agopian36bdf142011-03-16 14:19:03 -07002129 if (result)
2130 _s.terminate();
Mathias Agopianc291f5852010-08-27 16:48:56 -07002131 }
Mathias Agopian36bdf142011-03-16 14:19:03 -07002132 return result;
Mathias Agopianc291f5852010-08-27 16:48:56 -07002133}
2134
2135EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
2136{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08002137 clearError();
2138
Mathias Agopianc291f5852010-08-27 16:48:56 -07002139 egl_display_t const * const dp = get_display(dpy);
2140 if (dp == 0) {
2141 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2142 }
2143
2144 SyncRef _s(sync);
2145 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2146 egl_sync_t* syncObject = get_sync(sync);
2147
2148 EGLContext ctx = syncObject->context;
2149 ContextRef _c(ctx);
2150 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
2151 if (!validate_display_context(dpy, ctx))
2152 return EGL_FALSE;
2153
2154 egl_context_t * const c = get_context(ctx);
2155
2156 if (c->cnx->egl.eglClientWaitSyncKHR) {
2157 return c->cnx->egl.eglClientWaitSyncKHR(
2158 dp->disp[c->impl].dpy, syncObject->sync, flags, timeout);
2159 }
2160
2161 return EGL_FALSE;
2162}
2163
2164EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
2165{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08002166 clearError();
2167
Mathias Agopianc291f5852010-08-27 16:48:56 -07002168 egl_display_t const * const dp = get_display(dpy);
2169 if (dp == 0) {
2170 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2171 }
2172
2173 SyncRef _s(sync);
2174 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2175 egl_sync_t* syncObject = get_sync(sync);
2176
2177 EGLContext ctx = syncObject->context;
2178 ContextRef _c(ctx);
2179 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
2180 if (!validate_display_context(dpy, ctx))
2181 return EGL_FALSE;
2182
2183 egl_context_t * const c = get_context(ctx);
2184
2185 if (c->cnx->egl.eglGetSyncAttribKHR) {
2186 return c->cnx->egl.eglGetSyncAttribKHR(
2187 dp->disp[c->impl].dpy, syncObject->sync, attribute, value);
2188 }
2189
2190 return EGL_FALSE;
2191}
Mathias Agopiandf3ca302009-05-04 19:29:25 -07002192
2193// ----------------------------------------------------------------------------
2194// ANDROID extensions
2195// ----------------------------------------------------------------------------
2196
2197EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
2198 EGLint left, EGLint top, EGLint width, EGLint height)
2199{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08002200 clearError();
2201
Mathias Agopian9429e9c2009-08-21 02:18:25 -07002202 SurfaceRef _s(draw);
2203 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
2204
Mathias Agopiandf3ca302009-05-04 19:29:25 -07002205 if (!validate_display_surface(dpy, draw))
2206 return EGL_FALSE;
2207 egl_display_t const * const dp = get_display(dpy);
2208 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian618fa102009-10-14 02:06:37 -07002209 if (s->cnx->egl.eglSetSwapRectangleANDROID) {
2210 return s->cnx->egl.eglSetSwapRectangleANDROID(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07002211 dp->disp[s->impl].dpy, s->surface, left, top, width, height);
Mathias Agopiandf3ca302009-05-04 19:29:25 -07002212 }
Mathias Agopian24e5f522009-08-12 21:18:15 -07002213 return setError(EGL_BAD_DISPLAY, NULL);
Mathias Agopiandf3ca302009-05-04 19:29:25 -07002214}