blob: 4d800759707dd1a3dec5ffd48bade9fcca8d4cc9 [file] [log] [blame]
The Android Open Source Project9066cfe2009-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 Project9066cfe2009-03-03 19:31:44 -080017#include <ctype.h>
Mathias Agopian11be99d2009-05-17 18:50:16 -070018#include <stdlib.h>
The Android Open Source Project9066cfe2009-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 Rootbb9d3942011-02-16 10:13:53 -080025#ifdef HAVE_ANDROID_OS
The Android Open Source Project9066cfe2009-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 Agopian4a34e882009-08-21 02:18:25 -070039#include <utils/SortedVector.h>
Mathias Agopian3944eab2010-08-02 17:34:32 -070040#include <utils/KeyedVector.h>
41#include <utils/String8.h>
Mathias Agopian4a34e882009-08-21 02:18:25 -070042
Mathias Agopian698a8aa2010-11-24 15:59:35 -080043#include <ui/egl/android_natives.h>
44
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045#include "hooks.h"
46#include "egl_impl.h"
Mathias Agopian9d17c052009-05-28 17:39:03 -070047#include "Loader.h"
David Li5c425f22011-03-10 16:40:37 -080048#include "glesv2dbg.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049
The Android Open Source Project9066cfe2009-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 Agopiandcebf6f2009-08-17 18:07:06 -070059static char const * const gVersionString = "1.4 Android META-EGL";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060static char const * const gClientApiString = "OpenGL ES";
Mathias Agopian1473f462009-04-10 14:24:30 -070061static char const * const gExtensionString =
62 "EGL_KHR_image "
Mathias Agopian927d37c2009-05-06 23:47:08 -070063 "EGL_KHR_image_base "
64 "EGL_KHR_image_pixmap "
Mathias Agopianb20a4b92010-08-27 16:08:03 -070065 "EGL_KHR_gl_texture_2D_image "
Michael I. Gold3ece0102011-01-13 10:13:15 -080066 "EGL_KHR_gl_texture_cubemap_image "
67 "EGL_KHR_gl_renderbuffer_image "
Mathias Agopian9ca8a842010-08-27 16:48:56 -070068 "EGL_KHR_fence_sync "
Mathias Agopian1473f462009-04-10 14:24:30 -070069 "EGL_ANDROID_image_native_buffer "
Mathias Agopian2e20bff2009-05-04 19:29:25 -070070 "EGL_ANDROID_swap_rectangle "
Mathias Agopian1473f462009-04-10 14:24:30 -070071 ;
72
73// ----------------------------------------------------------------------------
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074
Mathias Agopian4a34e882009-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 Project9066cfe2009-03-03 19:31:44 -080090private:
Mathias Agopian4a34e882009-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 Project9066cfe2009-03-03 19:31:44 -0800148};
149
Mathias Agopian4a34e882009-08-21 02:18:25 -0700150SortedVector<egl_object_t*> egl_object_t::sObjects;
151Mutex egl_object_t::sLock;
152
Mathias Agopian3ad6c442010-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 Agopian94263d72009-08-24 21:47:13 -0700169struct egl_display_t {
170 enum { NOT_INITIALIZED, INITIALIZED, TERMINATED };
171
The Android Open Source Project9066cfe2009-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 Agopian94263d72009-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 Agopian3ad6c442010-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 Agopian94263d72009-08-24 21:47:13 -0700195
Mathias Agopian3ad6c442010-07-26 21:14:59 -0700196 egl_display_t() : magic('_dpy'), numTotalConfigs(0), configs(0) { }
Mathias Agopian4a34e882009-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 Project9066cfe2009-03-03 19:31:44 -0800200};
201
Mathias Agopian4a34e882009-08-21 02:18:25 -0700202struct egl_surface_t : public egl_object_t
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203{
Mathias Agopian4a34e882009-08-21 02:18:25 -0700204 typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
205
Mathias Agopian698a8aa2010-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 Project9066cfe2009-03-03 19:31:44 -0800209 }
210 ~egl_surface_t() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 }
212 EGLDisplay dpy;
213 EGLSurface surface;
Mathias Agopian3ad6c442010-07-26 21:14:59 -0700214 EGLConfig config;
Mathias Agopian698a8aa2010-11-24 15:59:35 -0800215 sp<ANativeWindow> win;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 int impl;
217 egl_connection_t const* cnx;
218};
219
Mathias Agopian4a34e882009-08-21 02:18:25 -0700220struct egl_context_t : public egl_object_t
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221{
Mathias Agopian4a34e882009-08-21 02:18:25 -0700222 typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
223
Mathias Agopian3ad6c442010-07-26 21:14:59 -0700224 egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
Mathias Agopian6fc56992009-10-14 02:06:37 -0700225 int impl, egl_connection_t const* cnx, int version)
Mathias Agopian791982b2010-12-08 15:34:02 -0800226 : dpy(dpy), context(context), config(config), read(0), draw(0), impl(impl),
David Li5c425f22011-03-10 16:40:37 -0800227 cnx(cnx), version(version), dbg(NULL)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 {
229 }
David Li5c425f22011-03-10 16:40:37 -0800230 ~egl_context_t()
231 {
232 if (dbg)
233 DestroyDbgContext(dbg);
234 dbg = NULL;
235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 EGLDisplay dpy;
237 EGLContext context;
Mathias Agopian3ad6c442010-07-26 21:14:59 -0700238 EGLConfig config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 EGLSurface read;
240 EGLSurface draw;
241 int impl;
242 egl_connection_t const* cnx;
Mathias Agopian6fc56992009-10-14 02:06:37 -0700243 int version;
David Li5c425f22011-03-10 16:40:37 -0800244 DbgContext * dbg;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245};
246
Mathias Agopian4a34e882009-08-21 02:18:25 -0700247struct egl_image_t : public egl_object_t
Mathias Agopian1473f462009-04-10 14:24:30 -0700248{
Mathias Agopian4a34e882009-08-21 02:18:25 -0700249 typedef egl_object_t::LocalRef<egl_image_t, EGLImageKHR> Ref;
250
Mathias Agopian1473f462009-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 Agopian97961db2010-09-09 11:12:54 -0700257 EGLContext context;
Mathias Agopian6fc56992009-10-14 02:06:37 -0700258 EGLImageKHR images[IMPL_NUM_IMPLEMENTATIONS];
Mathias Agopian1473f462009-04-10 14:24:30 -0700259};
260
Mathias Agopian9ca8a842010-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 Agopian4a34e882009-08-21 02:18:25 -0700274typedef egl_surface_t::Ref SurfaceRef;
275typedef egl_context_t::Ref ContextRef;
276typedef egl_image_t::Ref ImageRef;
Mathias Agopian9ca8a842010-08-27 16:48:56 -0700277typedef egl_sync_t::Ref SyncRef;
Mathias Agopian4a34e882009-08-21 02:18:25 -0700278
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279struct tls_t
280{
Mathias Agopian997d10702009-07-31 16:21:17 -0700281 tls_t() : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(EGL_TRUE) { }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 EGLint error;
283 EGLContext ctx;
Mathias Agopian997d10702009-07-31 16:21:17 -0700284 EGLBoolean logCallWithNoContext;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285};
286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287
288// ----------------------------------------------------------------------------
289
Mathias Agopiane5478352010-04-09 13:37:34 -0700290static egl_connection_t gEGLImpl[IMPL_NUM_IMPLEMENTATIONS];
The Android Open Source Project9066cfe2009-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 Agopian6fc56992009-10-14 02:06:37 -0700297EGLAPI gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS];
298EGLAPI gl_hooks_t gHooksNoContext;
Mathias Agopian3cc68d22009-05-13 00:19:22 -0700299EGLAPI pthread_key_t gGLWrapperKey = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800300
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700301#if EGL_TRACE
302
303EGLAPI pthread_key_t gGLTraceKey = -1;
304
305// ----------------------------------------------------------------------------
306
David Li28ca2ab2011-03-01 16:08:10 -0800307static int gEGLTraceLevel, gEGLDebugLevel;
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700308static int gEGLApplicationTraceLevel;
David Li28ca2ab2011-03-01 16:08:10 -0800309extern EGLAPI gl_hooks_t gHooksTrace, gHooksDebug;
Jack Palevichd4d0fb92010-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 Li28ca2ab2011-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 Li28ca2ab2011-03-01 16:08:10 -0800336 if (!strcmp(value, cmdline))
337 gEGLDebugLevel = 1;
338 }
339 fclose(file);
340 }
341
David Li28ca2ab2011-03-01 16:08:10 -0800342 if (gEGLDebugLevel > 0)
David Li940c3f82011-03-10 19:07:42 -0800343 {
344 property_get("debug.egl.debug_port", value, "5039");
345 StartDebugServer(atoi(value));
346 }
Jack Palevichd4d0fb92010-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 Li5c425f22011-03-10 16:40:37 -0800353 } else if (gEGLDebugLevel > 0 && value != &gHooksNoContext) {
David Li28ca2ab2011-03-01 16:08:10 -0800354 setGlTraceThreadSpecific(value);
355 setGlThreadSpecific(&gHooksDebug);
Jack Palevichd4d0fb92010-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 Project9066cfe2009-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. Golde7ff5dd2011-01-21 15:39:38 -0800424static inline void clearError() {
Jamie Gennise3b179c2011-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. Golde7ff5dd2011-01-21 15:39:38 -0800428}
429
The Android Open Source Project9066cfe2009-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 Project9066cfe2009-03-03 19:31:44 -0800479/*****************************************************************************/
480
The Android Open Source Project9066cfe2009-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 Agopian3ad6c442010-07-26 21:14:59 -0700488 if (sortedArray[mid] < key) {
The Android Open Source Project9066cfe2009-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 Project9066cfe2009-03-03 19:31:44 -0800499static int cmp_configs(const void* a, const void *b)
500{
Mathias Agopian3ad6c442010-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 Project9066cfe2009-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 Agopian1473f462009-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 Agopianc1e3ec52009-06-24 22:37:39 -0700520 { "eglSetSwapRectangleANDROID",
521 (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800522};
523
Mathias Agopian3944eab2010-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 Project9066cfe2009-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 Agopian25b388c2010-09-23 16:38:38 -0700543static int gl_no_context() {
Mathias Agopian997d10702009-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 Agopian25b388c2010-09-23 16:38:38 -0700550 return 0;
Mathias Agopian5c6c5c72010-09-23 11:32:52 -0700551}
552
The Android Open Source Project9066cfe2009-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 Palevichd4d0fb92010-10-26 15:21:24 -0700558#if EGL_TRACE
559 pthread_key_create(&gGLTraceKey, NULL);
560 initEglTraceLevel();
561#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800562 uint32_t addr = (uint32_t)((void*)gl_no_context);
563 android_memset32(
Mathias Agopian6fc56992009-10-14 02:06:37 -0700564 (uint32_t*)(void*)&gHooksNoContext,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800565 addr,
Mathias Agopian6fc56992009-10-14 02:06:37 -0700566 sizeof(gHooksNoContext));
Mathias Agopian5c6c5c72010-09-23 11:32:52 -0700567
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700568 setGLHooksThreadSpecific(&gHooksNoContext);
The Android Open Source Project9066cfe2009-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 Agopian1473f462009-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 Project9066cfe2009-03-03 19:31:44 -0800585}
586
587static inline
Mathias Agopian1473f462009-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 Li5c425f22011-03-10 16:40:37 -0800597DbgContext * getDbgContextThreadSpecific()
598{
599 return get_context(getContext())->dbg;
600}
601
Mathias Agopian1473f462009-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 Project9066cfe2009-03-03 19:31:44 -0800605}
606
Mathias Agopian9ca8a842010-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 Project9066cfe2009-03-03 19:31:44 -0800612static egl_connection_t* validate_display_config(
613 EGLDisplay dpy, EGLConfig config,
Mathias Agopian3ad6c442010-07-26 21:14:59 -0700614 egl_display_t const*& dp)
The Android Open Source Project9066cfe2009-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 Agopian3ad6c442010-07-26 21:14:59 -0700619 if (intptr_t(config) >= dp->numTotalConfigs) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800620 return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
621 }
Mathias Agopian3ad6c442010-07-26 21:14:59 -0700622 egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(config)].impl];
The Android Open Source Project9066cfe2009-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 Agopian4a34e882009-08-21 02:18:25 -0700633 if (!get_display(dpy)->isAlive())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800634 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian4a34e882009-08-21 02:18:25 -0700635 if (!get_context(ctx)->isAlive())
The Android Open Source Project9066cfe2009-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 Agopian4a34e882009-08-21 02:18:25 -0700644 if (!get_display(dpy)->isAlive())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800645 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian4a34e882009-08-21 02:18:25 -0700646 if (!get_surface(surface)->isAlive())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800647 return setError(EGL_BAD_SURFACE, EGL_FALSE);
648 return EGL_TRUE;
649}
650
Mathias Agopian1473f462009-04-10 14:24:30 -0700651EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image)
652{
Mathias Agopian4a34e882009-08-21 02:18:25 -0700653 ImageRef _i(image);
654 if (!_i.get()) return EGL_NO_IMAGE_KHR;
655
Mathias Agopian1473f462009-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 Agopian4a34e882009-08-21 02:18:25 -0700661 if (!c->isAlive())
Mathias Agopian1473f462009-04-10 14:24:30 -0700662 return EGL_NO_IMAGE_KHR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800663
Mathias Agopian1473f462009-04-10 14:24:30 -0700664 egl_image_t const * const i = get_image(image);
Mathias Agopian1473f462009-04-10 14:24:30 -0700665 return i->images[c->impl];
666}
667
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700668// ----------------------------------------------------------------------------
Mathias Agopian1473f462009-04-10 14:24:30 -0700669
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700670// this mutex protects:
Mathias Agopian94263d72009-08-24 21:47:13 -0700671// d->disp[]
Mathias Agopiandcebf6f2009-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 Project9066cfe2009-03-03 19:31:44 -0800677{
678 if (sEarlyInitState) {
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700679 // initialized by static ctor. should be set here.
680 return EGL_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681 }
682
Mathias Agopian9d17c052009-05-28 17:39:03 -0700683 // get our driver loader
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700684 Loader& loader(Loader::getInstance());
Mathias Agopian9d17c052009-05-28 17:39:03 -0700685
Mathias Agopiandcebf6f2009-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 Project9066cfe2009-03-03 19:31:44 -0800694 if (cnx->dso == 0) {
Mathias Agopian6fc56992009-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 Agopiandcebf6f2009-08-17 18:07:06 -0700698 if (cnx->dso) {
Mathias Agopian6fc56992009-10-14 02:06:37 -0700699 EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700700 LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for software EGL!");
Mathias Agopian94263d72009-08-24 21:47:13 -0700701 d->disp[IMPL_SOFTWARE].dpy = dpy;
Mathias Agopiandcebf6f2009-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 Project9066cfe2009-03-03 19:31:44 -0800707 }
708
709 cnx = &gEGLImpl[IMPL_HARDWARE];
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700710 if (cnx->dso == 0) {
The Android Open Source Project9066cfe2009-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 Agopian6fc56992009-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 Agopiandcebf6f2009-08-17 18:07:06 -0700717 if (cnx->dso) {
Mathias Agopian6fc56992009-10-14 02:06:37 -0700718 EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700719 LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for hardware EGL!");
Mathias Agopian94263d72009-08-24 21:47:13 -0700720 d->disp[IMPL_HARDWARE].dpy = dpy;
Mathias Agopiandcebf6f2009-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 Project9066cfe2009-03-03 19:31:44 -0800726 } else {
727 LOGD("3D hardware acceleration is disabled");
728 }
729 }
Mathias Agopian94263d72009-08-24 21:47:13 -0700730
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700731 if (!gEGLImpl[IMPL_SOFTWARE].dso && !gEGLImpl[IMPL_HARDWARE].dso) {
732 return EGL_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800733 }
734
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700735 return EGL_TRUE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800736}
737
Mathias Agopiandcebf6f2009-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 Agopian1473f462009-04-10 14:24:30 -0700746
747// ----------------------------------------------------------------------------
748}; // namespace android
749// ----------------------------------------------------------------------------
750
751using namespace android;
752
753EGLDisplay eglGetDisplay(NativeDisplayType display)
754{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -0800755 clearError();
756
Mathias Agopiandcebf6f2009-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 Agopian1473f462009-04-10 14:24:30 -0700768}
769
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800770// ----------------------------------------------------------------------------
771// Initialization
772// ----------------------------------------------------------------------------
773
774EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
775{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -0800776 clearError();
777
The Android Open Source Project9066cfe2009-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 Agopian6099ab72010-02-05 16:17:01 -0800781 Mutex::Autolock _l(dp->lock);
782
783 if (dp->refs > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 if (major != NULL) *major = VERSION_MAJOR;
785 if (minor != NULL) *minor = VERSION_MINOR;
Jack Palevich0a41c3c2010-03-15 20:45:21 -0700786 dp->refs++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 return EGL_TRUE;
788 }
Jack Palevichd4d0fb92010-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 Project9066cfe2009-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 Agopian6fc56992009-10-14 02:06:37 -0700803 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Project9066cfe2009-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 Agopian94263d72009-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 Agopian6fc56992009-10-14 02:06:37 -0700821 cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
Mathias Agopian94263d72009-08-24 21:47:13 -0700822 }
823#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800824
Mathias Agopian94263d72009-08-24 21:47:13 -0700825
826 EGLDisplay idpy = dp->disp[i].dpy;
Mathias Agopian6fc56992009-10-14 02:06:37 -0700827 if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828 //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p",
Mathias Agopian94263d72009-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 Project9066cfe2009-03-03 19:31:44 -0800833
834 // get the query-strings for this display for each implementation
Mathias Agopian94263d72009-08-24 21:47:13 -0700835 dp->disp[i].queryString.vendor =
Mathias Agopian6fc56992009-10-14 02:06:37 -0700836 cnx->egl.eglQueryString(idpy, EGL_VENDOR);
Mathias Agopian94263d72009-08-24 21:47:13 -0700837 dp->disp[i].queryString.version =
Mathias Agopian6fc56992009-10-14 02:06:37 -0700838 cnx->egl.eglQueryString(idpy, EGL_VERSION);
Mathias Agopian94263d72009-08-24 21:47:13 -0700839 dp->disp[i].queryString.extensions =
Mathias Agopian6fc56992009-10-14 02:06:37 -0700840 cnx->egl.eglQueryString(idpy, EGL_EXTENSIONS);
Mathias Agopian94263d72009-08-24 21:47:13 -0700841 dp->disp[i].queryString.clientApi =
Mathias Agopian6fc56992009-10-14 02:06:37 -0700842 cnx->egl.eglQueryString(idpy, EGL_CLIENT_APIS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800843
844 } else {
Mathias Agopian94263d72009-08-24 21:47:13 -0700845 LOGW("%d: eglInitialize(%p) failed (%s)", i, idpy,
Mathias Agopian6fc56992009-10-14 02:06:37 -0700846 egl_strerror(cnx->egl.eglGetError()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800847 }
848 }
849
850 EGLBoolean res = EGL_FALSE;
Mathias Agopian6fc56992009-10-14 02:06:37 -0700851 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Project9066cfe2009-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 Agopian6fc56992009-10-14 02:06:37 -0700855 if (cnx->egl.eglGetConfigs(dp->disp[i].dpy, 0, 0, &n)) {
Mathias Agopian94263d72009-08-24 21:47:13 -0700856 dp->disp[i].config = (EGLConfig*)malloc(sizeof(EGLConfig)*n);
857 if (dp->disp[i].config) {
Mathias Agopian6fc56992009-10-14 02:06:37 -0700858 if (cnx->egl.eglGetConfigs(
Mathias Agopian94263d72009-08-24 21:47:13 -0700859 dp->disp[i].dpy, dp->disp[i].config, n,
860 &dp->disp[i].numConfigs))
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800861 {
The Android Open Source Project9066cfe2009-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 Agopian3ad6c442010-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 Agopian6099ab72010-02-05 16:17:01 -0800895 dp->refs++;
The Android Open Source Project9066cfe2009-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 Agopiandcebf6f2009-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. Golde7ff5dd2011-01-21 15:39:38 -0800909 clearError();
910
The Android Open Source Project9066cfe2009-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 Agopian6099ab72010-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 Palevich0a41c3c2010-03-15 20:45:21 -0700921 if (dp->refs > 1) {
922 dp->refs--;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800923 return EGL_TRUE;
Jack Palevich0a41c3c2010-03-15 20:45:21 -0700924 }
Mathias Agopian9d17c052009-05-28 17:39:03 -0700925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926 EGLBoolean res = EGL_FALSE;
Mathias Agopian6fc56992009-10-14 02:06:37 -0700927 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800928 egl_connection_t* const cnx = &gEGLImpl[i];
Mathias Agopian94263d72009-08-24 21:47:13 -0700929 if (cnx->dso && dp->disp[i].state == egl_display_t::INITIALIZED) {
Mathias Agopian6fc56992009-10-14 02:06:37 -0700930 if (cnx->egl.eglTerminate(dp->disp[i].dpy) == EGL_FALSE) {
Mathias Agopian94263d72009-08-24 21:47:13 -0700931 LOGW("%d: eglTerminate(%p) failed (%s)", i, dp->disp[i].dpy,
Mathias Agopian6fc56992009-10-14 02:06:37 -0700932 egl_strerror(cnx->egl.eglGetError()));
Mathias Agopian94263d72009-08-24 21:47:13 -0700933 }
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700934 // REVISIT: it's unclear what to do if eglTerminate() fails
Mathias Agopian94263d72009-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 Project9066cfe2009-03-03 19:31:44 -0800941 res = EGL_TRUE;
942 }
943 }
Mathias Agopian4a34e882009-08-21 02:18:25 -0700944
945 // TODO: all egl_object_t should be marked for termination
946
Mathias Agopian6099ab72010-02-05 16:17:01 -0800947 dp->refs--;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948 dp->numTotalConfigs = 0;
Mathias Agopian3ad6c442010-07-26 21:14:59 -0700949 delete [] dp->configs;
Michael I. Goldf0ca1d32010-12-23 13:51:36 -0800950
The Android Open Source Project9066cfe2009-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. Golde7ff5dd2011-01-21 15:39:38 -0800962 clearError();
963
The Android Open Source Project9066cfe2009-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 Agopian3ad6c442010-07-26 21:14:59 -0700972
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 GLint n = 0;
Mathias Agopian3ad6c442010-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 Project9066cfe2009-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. Golde7ff5dd2011-01-21 15:39:38 -0800988 clearError();
989
The Android Open Source Project9066cfe2009-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 Palevich1badb712009-03-25 15:12:17 -0700993 if (num_config==0) {
994 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
The Android Open Source Project9066cfe2009-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 Agopian3ad6c442010-07-26 21:14:59 -07001003 // to do this, we have to go through the attrib_list array once
The Android Open Source Project9066cfe2009-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 Agopian7e71fcf2010-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 Project9066cfe2009-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 Agopian3ad6c442010-07-26 21:14:59 -07001027 bool found = false;
1028 EGLConfig ourConfig(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001029 EGLint& configId(new_list[patch_index+1]);
Mathias Agopian3ad6c442010-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 Project9066cfe2009-03-03 19:31:44 -08001038
Mathias Agopian3ad6c442010-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 Project9066cfe2009-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 Agopian6fc56992009-10-14 02:06:37 -07001047 // cnx->egl.eglChooseConfig() -- but we don't have to loop
The Android Open Source Project9066cfe2009-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 Agopian6fc56992009-10-14 02:06:37 -07001052 res = cnx->egl.eglChooseConfig(
Mathias Agopian3ad6c442010-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 Project9066cfe2009-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 Palevich1badb712009-03-25 15:12:17 -07001058 if (configs) {
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001059 configs[0] = ourConfig;
Jack Palevich1badb712009-03-25 15:12:17 -07001060 }
The Android Open Source Project9066cfe2009-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 Agopian3ad6c442010-07-26 21:14:59 -07001069
Mathias Agopian6fc56992009-10-14 02:06:37 -07001070 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071 egl_connection_t* const cnx = &gEGLImpl[i];
1072 if (cnx->dso) {
Mathias Agopian6fc56992009-10-14 02:06:37 -07001073 if (cnx->egl.eglChooseConfig(
Mathias Agopian94263d72009-08-24 21:47:13 -07001074 dp->disp[i].dpy, attrib_list, configs, config_size, &n)) {
Jack Palevich1badb712009-03-25 15:12:17 -07001075 if (configs) {
1076 // now we need to convert these client EGLConfig to our
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001077 // internal EGLConfig format.
1078 // This is done in O(n Log(n)) time.
Jack Palevich1badb712009-03-25 15:12:17 -07001079 for (int j=0 ; j<n ; j++) {
Mathias Agopian3ad6c442010-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 Palevich1badb712009-03-25 15:12:17 -07001083 if (index >= 0) {
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001084 configs[j] = EGLConfig(index);
Jack Palevich1badb712009-03-25 15:12:17 -07001085 } else {
1086 return setError(EGL_BAD_CONFIG, EGL_FALSE);
1087 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 }
Jack Palevich1badb712009-03-25 15:12:17 -07001089 configs += n;
1090 config_size -= n;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001091 }
The Android Open Source Project9066cfe2009-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. Golde7ff5dd2011-01-21 15:39:38 -08001103 clearError();
1104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 egl_display_t const* dp = 0;
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001106 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001107 if (!cnx) return EGL_FALSE;
1108
1109 if (attribute == EGL_CONFIG_ID) {
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001110 *value = dp->configs[intptr_t(config)].configId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 return EGL_TRUE;
1112 }
Mathias Agopian6fc56992009-10-14 02:06:37 -07001113 return cnx->egl.eglGetConfigAttrib(
Mathias Agopian3ad6c442010-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 Project9066cfe2009-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. Golde7ff5dd2011-01-21 15:39:38 -08001126 clearError();
1127
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 egl_display_t const* dp = 0;
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001129 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001130 if (cnx) {
Mathias Agopian698a8aa2010-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
1135 // set the native window's buffers format to match this config
1136 if (cnx->egl.eglGetConfigAttrib(iDpy,
1137 iConfig, EGL_NATIVE_VISUAL_ID, &format)) {
1138 if (format != 0) {
1139 native_window_set_buffers_geometry(window, 0, 0, format);
1140 }
1141 }
1142
Mathias Agopian6fc56992009-10-14 02:06:37 -07001143 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian698a8aa2010-11-24 15:59:35 -08001144 iDpy, iConfig, window, attrib_list);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001145 if (surface != EGL_NO_SURFACE) {
Mathias Agopian698a8aa2010-11-24 15:59:35 -08001146 egl_surface_t* s = new egl_surface_t(dpy, config, window, surface,
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001147 dp->configs[intptr_t(config)].impl, cnx);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001148 return s;
1149 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001150 }
1151 return EGL_NO_SURFACE;
1152}
1153
1154EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
1155 NativePixmapType pixmap,
1156 const EGLint *attrib_list)
1157{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001158 clearError();
1159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001160 egl_display_t const* dp = 0;
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001161 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001162 if (cnx) {
Mathias Agopian6fc56992009-10-14 02:06:37 -07001163 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001164 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1165 dp->configs[intptr_t(config)].config, pixmap, attrib_list);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001166 if (surface != EGL_NO_SURFACE) {
Mathias Agopian698a8aa2010-11-24 15:59:35 -08001167 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001168 dp->configs[intptr_t(config)].impl, cnx);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001169 return s;
1170 }
1171 }
1172 return EGL_NO_SURFACE;
1173}
1174
1175EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
1176 const EGLint *attrib_list)
1177{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001178 clearError();
1179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001180 egl_display_t const* dp = 0;
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001181 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 if (cnx) {
Mathias Agopian6fc56992009-10-14 02:06:37 -07001183 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001184 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1185 dp->configs[intptr_t(config)].config, attrib_list);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001186 if (surface != EGL_NO_SURFACE) {
Mathias Agopian698a8aa2010-11-24 15:59:35 -08001187 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001188 dp->configs[intptr_t(config)].impl, cnx);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001189 return s;
1190 }
1191 }
1192 return EGL_NO_SURFACE;
1193}
1194
1195EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
1196{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001197 clearError();
1198
Mathias Agopian4a34e882009-08-21 02:18:25 -07001199 SurfaceRef _s(surface);
1200 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001202 if (!validate_display_surface(dpy, surface))
1203 return EGL_FALSE;
1204 egl_display_t const * const dp = get_display(dpy);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001205
Mathias Agopian4a34e882009-08-21 02:18:25 -07001206 egl_surface_t * const s = get_surface(surface);
Mathias Agopian6fc56992009-10-14 02:06:37 -07001207 EGLBoolean result = s->cnx->egl.eglDestroySurface(
Mathias Agopian94263d72009-08-24 21:47:13 -07001208 dp->disp[s->impl].dpy, s->surface);
Mathias Agopian4a34e882009-08-21 02:18:25 -07001209 if (result == EGL_TRUE) {
Mathias Agopian698a8aa2010-11-24 15:59:35 -08001210 if (s->win != NULL) {
1211 native_window_set_buffers_geometry(s->win.get(), 0, 0, 0);
1212 }
Mathias Agopian4a34e882009-08-21 02:18:25 -07001213 _s.terminate();
1214 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001215 return result;
1216}
1217
1218EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
1219 EGLint attribute, EGLint *value)
1220{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001221 clearError();
1222
Mathias Agopian4a34e882009-08-21 02:18:25 -07001223 SurfaceRef _s(surface);
1224 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001226 if (!validate_display_surface(dpy, surface))
1227 return EGL_FALSE;
1228 egl_display_t const * const dp = get_display(dpy);
1229 egl_surface_t const * const s = get_surface(surface);
1230
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001231 EGLBoolean result(EGL_TRUE);
1232 if (attribute == EGL_CONFIG_ID) {
1233 // We need to remap EGL_CONFIG_IDs
1234 *value = dp->configs[intptr_t(s->config)].configId;
1235 } else {
1236 result = s->cnx->egl.eglQuerySurface(
1237 dp->disp[s->impl].dpy, s->surface, attribute, value);
1238 }
1239
1240 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001241}
1242
1243// ----------------------------------------------------------------------------
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001244// Contexts
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001245// ----------------------------------------------------------------------------
1246
1247EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
1248 EGLContext share_list, const EGLint *attrib_list)
1249{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001250 clearError();
1251
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001252 egl_display_t const* dp = 0;
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001253 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001254 if (cnx) {
Jamie Gennis5149f912010-07-02 11:39:12 -07001255 if (share_list != EGL_NO_CONTEXT) {
1256 egl_context_t* const c = get_context(share_list);
1257 share_list = c->context;
1258 }
Mathias Agopian6fc56992009-10-14 02:06:37 -07001259 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001260 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1261 dp->configs[intptr_t(config)].config,
Mathias Agopian94263d72009-08-24 21:47:13 -07001262 share_list, attrib_list);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001263 if (context != EGL_NO_CONTEXT) {
Mathias Agopian6fc56992009-10-14 02:06:37 -07001264 // figure out if it's a GLESv1 or GLESv2
1265 int version = 0;
1266 if (attrib_list) {
1267 while (*attrib_list != EGL_NONE) {
1268 GLint attr = *attrib_list++;
1269 GLint value = *attrib_list++;
1270 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
1271 if (value == 1) {
1272 version = GLESv1_INDEX;
1273 } else if (value == 2) {
1274 version = GLESv2_INDEX;
1275 }
1276 }
1277 };
1278 }
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001279 egl_context_t* c = new egl_context_t(dpy, context, config,
1280 dp->configs[intptr_t(config)].impl, cnx, version);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001281 return c;
1282 }
1283 }
1284 return EGL_NO_CONTEXT;
1285}
1286
1287EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1288{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001289 clearError();
1290
Mathias Agopian4a34e882009-08-21 02:18:25 -07001291 ContextRef _c(ctx);
1292 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001294 if (!validate_display_context(dpy, ctx))
1295 return EGL_FALSE;
1296 egl_display_t const * const dp = get_display(dpy);
1297 egl_context_t * const c = get_context(ctx);
Mathias Agopian6fc56992009-10-14 02:06:37 -07001298 EGLBoolean result = c->cnx->egl.eglDestroyContext(
Mathias Agopian94263d72009-08-24 21:47:13 -07001299 dp->disp[c->impl].dpy, c->context);
Mathias Agopian4a34e882009-08-21 02:18:25 -07001300 if (result == EGL_TRUE) {
1301 _c.terminate();
1302 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001303 return result;
1304}
1305
Michael I. Goldf0ca1d32010-12-23 13:51:36 -08001306static void loseCurrent(egl_context_t * cur_c)
1307{
1308 if (cur_c) {
1309 egl_surface_t * cur_r = get_surface(cur_c->read);
1310 egl_surface_t * cur_d = get_surface(cur_c->draw);
1311
1312 // by construction, these are either 0 or valid (possibly terminated)
1313 // it should be impossible for these to be invalid
1314 ContextRef _cur_c(cur_c);
1315 SurfaceRef _cur_r(cur_r);
1316 SurfaceRef _cur_d(cur_d);
1317
1318 cur_c->read = NULL;
1319 cur_c->draw = NULL;
1320
1321 _cur_c.release();
1322 _cur_r.release();
1323 _cur_d.release();
1324 }
1325}
1326
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001327EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
1328 EGLSurface read, EGLContext ctx)
1329{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001330 clearError();
1331
Mathias Agopian4a34e882009-08-21 02:18:25 -07001332 // get a reference to the object passed in
1333 ContextRef _c(ctx);
1334 SurfaceRef _d(draw);
1335 SurfaceRef _r(read);
1336
1337 // validate the display and the context (if not EGL_NO_CONTEXT)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001338 egl_display_t const * const dp = get_display(dpy);
1339 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian4a34e882009-08-21 02:18:25 -07001340 if ((ctx != EGL_NO_CONTEXT) && (!validate_display_context(dpy, ctx))) {
1341 // EGL_NO_CONTEXT is valid
1342 return EGL_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001343 }
1344
Mathias Agopian4a34e882009-08-21 02:18:25 -07001345 // these are the underlying implementation's object
1346 EGLContext impl_ctx = EGL_NO_CONTEXT;
Mathias Agopian3a7e1832009-06-25 00:01:11 -07001347 EGLSurface impl_draw = EGL_NO_SURFACE;
1348 EGLSurface impl_read = EGL_NO_SURFACE;
Mathias Agopian4a34e882009-08-21 02:18:25 -07001349
1350 // these are our objects structs passed in
1351 egl_context_t * c = NULL;
1352 egl_surface_t const * d = NULL;
1353 egl_surface_t const * r = NULL;
1354
1355 // these are the current objects structs
1356 egl_context_t * cur_c = get_context(getContext());
Mathias Agopian4a34e882009-08-21 02:18:25 -07001357
1358 if (ctx != EGL_NO_CONTEXT) {
1359 c = get_context(ctx);
Mathias Agopian4a34e882009-08-21 02:18:25 -07001360 impl_ctx = c->context;
1361 } else {
1362 // no context given, use the implementation of the current context
1363 if (cur_c == NULL) {
1364 // no current context
1365 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
Mathias Agopian7552dcf2010-01-25 11:30:11 -08001366 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
1367 return setError(EGL_BAD_MATCH, EGL_FALSE);
Mathias Agopian4a34e882009-08-21 02:18:25 -07001368 }
Mathias Agopian7552dcf2010-01-25 11:30:11 -08001369 // not an error, there is just no current context.
Mathias Agopian4a34e882009-08-21 02:18:25 -07001370 return EGL_TRUE;
1371 }
1372 }
1373
1374 // retrieve the underlying implementation's draw EGLSurface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 if (draw != EGL_NO_SURFACE) {
Mathias Agopian4a34e882009-08-21 02:18:25 -07001376 d = get_surface(draw);
Mathias Agopian94263d72009-08-24 21:47:13 -07001377 // make sure the EGLContext and EGLSurface passed in are for
1378 // the same driver
Mathias Agopian4a34e882009-08-21 02:18:25 -07001379 if (c && d->impl != c->impl)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001380 return setError(EGL_BAD_MATCH, EGL_FALSE);
Mathias Agopian3a7e1832009-06-25 00:01:11 -07001381 impl_draw = d->surface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001382 }
Mathias Agopian4a34e882009-08-21 02:18:25 -07001383
1384 // retrieve the underlying implementation's read EGLSurface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001385 if (read != EGL_NO_SURFACE) {
Mathias Agopian4a34e882009-08-21 02:18:25 -07001386 r = get_surface(read);
Mathias Agopian94263d72009-08-24 21:47:13 -07001387 // make sure the EGLContext and EGLSurface passed in are for
1388 // the same driver
Mathias Agopian4a34e882009-08-21 02:18:25 -07001389 if (c && r->impl != c->impl)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001390 return setError(EGL_BAD_MATCH, EGL_FALSE);
Mathias Agopian3a7e1832009-06-25 00:01:11 -07001391 impl_read = r->surface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392 }
Mathias Agopian4a34e882009-08-21 02:18:25 -07001393
1394 EGLBoolean result;
1395
1396 if (c) {
Mathias Agopian6fc56992009-10-14 02:06:37 -07001397 result = c->cnx->egl.eglMakeCurrent(
Mathias Agopian94263d72009-08-24 21:47:13 -07001398 dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
Mathias Agopian4a34e882009-08-21 02:18:25 -07001399 } else {
Mathias Agopian6fc56992009-10-14 02:06:37 -07001400 result = cur_c->cnx->egl.eglMakeCurrent(
Mathias Agopian94263d72009-08-24 21:47:13 -07001401 dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
Mathias Agopian4a34e882009-08-21 02:18:25 -07001402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001403
1404 if (result == EGL_TRUE) {
Mathias Agopian4a34e882009-08-21 02:18:25 -07001405
Michael I. Goldf0ca1d32010-12-23 13:51:36 -08001406 loseCurrent(cur_c);
1407
Mathias Agopian4a34e882009-08-21 02:18:25 -07001408 if (ctx != EGL_NO_CONTEXT) {
David Li5c425f22011-03-10 16:40:37 -08001409 if (!c->dbg && gEGLDebugLevel > 0)
1410 c->dbg = CreateDbgContext(c->version, c->cnx->hooks[c->version]);
Jack Palevichd4d0fb92010-10-26 15:21:24 -07001411 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
Mathias Agopian4a34e882009-08-21 02:18:25 -07001412 setContext(ctx);
1413 _c.acquire();
Michael I. Goldf0ca1d32010-12-23 13:51:36 -08001414 _r.acquire();
1415 _d.acquire();
1416 c->read = read;
1417 c->draw = draw;
Mathias Agopian4a34e882009-08-21 02:18:25 -07001418 } else {
Jack Palevichd4d0fb92010-10-26 15:21:24 -07001419 setGLHooksThreadSpecific(&gHooksNoContext);
Mathias Agopian4a34e882009-08-21 02:18:25 -07001420 setContext(EGL_NO_CONTEXT);
1421 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001422 }
1423 return result;
1424}
1425
1426
1427EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
1428 EGLint attribute, EGLint *value)
1429{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001430 clearError();
1431
Mathias Agopian4a34e882009-08-21 02:18:25 -07001432 ContextRef _c(ctx);
1433 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001435 if (!validate_display_context(dpy, ctx))
1436 return EGL_FALSE;
1437
1438 egl_display_t const * const dp = get_display(dpy);
1439 egl_context_t * const c = get_context(ctx);
1440
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001441 EGLBoolean result(EGL_TRUE);
1442 if (attribute == EGL_CONFIG_ID) {
1443 *value = dp->configs[intptr_t(c->config)].configId;
1444 } else {
1445 // We need to remap EGL_CONFIG_IDs
1446 result = c->cnx->egl.eglQueryContext(
1447 dp->disp[c->impl].dpy, c->context, attribute, value);
1448 }
1449
1450 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001451}
1452
1453EGLContext eglGetCurrentContext(void)
1454{
Mathias Agopiandcebf6f2009-08-17 18:07:06 -07001455 // could be called before eglInitialize(), but we wouldn't have a context
1456 // then, and this function would correctly return EGL_NO_CONTEXT.
1457
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001458 clearError();
1459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 EGLContext ctx = getContext();
1461 return ctx;
1462}
1463
1464EGLSurface eglGetCurrentSurface(EGLint readdraw)
1465{
Mathias Agopiandcebf6f2009-08-17 18:07:06 -07001466 // could be called before eglInitialize(), but we wouldn't have a context
1467 // then, and this function would correctly return EGL_NO_SURFACE.
1468
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001469 clearError();
1470
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001471 EGLContext ctx = getContext();
1472 if (ctx) {
1473 egl_context_t const * const c = get_context(ctx);
1474 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1475 switch (readdraw) {
1476 case EGL_READ: return c->read;
1477 case EGL_DRAW: return c->draw;
1478 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1479 }
1480 }
1481 return EGL_NO_SURFACE;
1482}
1483
1484EGLDisplay eglGetCurrentDisplay(void)
1485{
Mathias Agopiandcebf6f2009-08-17 18:07:06 -07001486 // could be called before eglInitialize(), but we wouldn't have a context
1487 // then, and this function would correctly return EGL_NO_DISPLAY.
1488
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001489 clearError();
1490
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 EGLContext ctx = getContext();
1492 if (ctx) {
1493 egl_context_t const * const c = get_context(ctx);
1494 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1495 return c->dpy;
1496 }
1497 return EGL_NO_DISPLAY;
1498}
1499
1500EGLBoolean eglWaitGL(void)
1501{
Mathias Agopiandcebf6f2009-08-17 18:07:06 -07001502 // could be called before eglInitialize(), but we wouldn't have a context
1503 // then, and this function would return GL_TRUE, which isn't wrong.
1504
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001505 clearError();
1506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 EGLBoolean res = EGL_TRUE;
1508 EGLContext ctx = getContext();
1509 if (ctx) {
1510 egl_context_t const * const c = get_context(ctx);
1511 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1512 if (uint32_t(c->impl)>=2)
1513 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1514 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1515 if (!cnx->dso)
1516 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian6fc56992009-10-14 02:06:37 -07001517 res = cnx->egl.eglWaitGL();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 }
1519 return res;
1520}
1521
1522EGLBoolean eglWaitNative(EGLint engine)
1523{
Mathias Agopiandcebf6f2009-08-17 18:07:06 -07001524 // could be called before eglInitialize(), but we wouldn't have a context
1525 // then, and this function would return GL_TRUE, which isn't wrong.
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001526
1527 clearError();
1528
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001529 EGLBoolean res = EGL_TRUE;
1530 EGLContext ctx = getContext();
1531 if (ctx) {
1532 egl_context_t const * const c = get_context(ctx);
1533 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1534 if (uint32_t(c->impl)>=2)
1535 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1536 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1537 if (!cnx->dso)
1538 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian6fc56992009-10-14 02:06:37 -07001539 res = cnx->egl.eglWaitNative(engine);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001540 }
1541 return res;
1542}
1543
1544EGLint eglGetError(void)
1545{
1546 EGLint result = EGL_SUCCESS;
Mathias Agopianf65630a2010-09-21 15:43:59 -07001547 EGLint err;
Mathias Agopian6fc56992009-10-14 02:06:37 -07001548 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
Mathias Agopianf65630a2010-09-21 15:43:59 -07001549 err = EGL_SUCCESS;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001550 egl_connection_t* const cnx = &gEGLImpl[i];
1551 if (cnx->dso)
Mathias Agopian6fc56992009-10-14 02:06:37 -07001552 err = cnx->egl.eglGetError();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001553 if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
1554 result = err;
1555 }
Mathias Agopianf65630a2010-09-21 15:43:59 -07001556 err = getError();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001557 if (result == EGL_SUCCESS)
Mathias Agopianf65630a2010-09-21 15:43:59 -07001558 result = err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559 return result;
1560}
1561
Michael I. Goldf4a43832011-01-04 01:16:59 -08001562// Note: Similar implementations of these functions also exist in
1563// gl2.cpp and gl.cpp, and are used by applications that call the
1564// exported entry points directly.
1565typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
1566typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
1567
1568static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL;
1569static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL;
1570
1571static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image)
1572{
1573 GLeglImageOES implImage =
1574 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
1575 glEGLImageTargetTexture2DOES_impl(target, implImage);
1576}
1577
1578static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image)
1579{
1580 GLeglImageOES implImage =
1581 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
1582 glEGLImageTargetRenderbufferStorageOES_impl(target, implImage);
1583}
1584
Mathias Agopian1473f462009-04-10 14:24:30 -07001585__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586{
Mathias Agopian1473f462009-04-10 14:24:30 -07001587 // eglGetProcAddress() could be the very first function called
1588 // in which case we must make sure we've initialized ourselves, this
1589 // happens the first time egl_get_display() is called.
Mathias Agopiandcebf6f2009-08-17 18:07:06 -07001590
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001591 clearError();
1592
Mathias Agopiandcebf6f2009-08-17 18:07:06 -07001593 if (egl_init_drivers() == EGL_FALSE) {
1594 setError(EGL_BAD_PARAMETER, NULL);
1595 return NULL;
1596 }
Mathias Agopian1473f462009-04-10 14:24:30 -07001597
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001598 __eglMustCastToProperFunctionPointerType addr;
1599 addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap));
1600 if (addr) return addr;
1601
Mathias Agopian3944eab2010-08-02 17:34:32 -07001602 // this protects accesses to gGLExtentionMap and gGLExtentionSlot
1603 pthread_mutex_lock(&gInitDriverMutex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001604
Mathias Agopian3944eab2010-08-02 17:34:32 -07001605 /*
1606 * Since eglGetProcAddress() is not associated to anything, it needs
1607 * to return a function pointer that "works" regardless of what
1608 * the current context is.
1609 *
1610 * For this reason, we return a "forwarder", a small stub that takes
1611 * care of calling the function associated with the context
1612 * currently bound.
1613 *
1614 * We first look for extensions we've already resolved, if we're seeing
1615 * this extension for the first time, we go through all our
1616 * implementations and call eglGetProcAddress() and record the
1617 * result in the appropriate implementation hooks and return the
1618 * address of the forwarder corresponding to that hook set.
1619 *
1620 */
1621
1622 const String8 name(procname);
1623 addr = gGLExtentionMap.valueFor(name);
1624 const int slot = gGLExtentionSlot;
1625
1626 LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
1627 "no more slots for eglGetProcAddress(\"%s\")",
1628 procname);
1629
1630 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
1631 bool found = false;
1632 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1633 egl_connection_t* const cnx = &gEGLImpl[i];
1634 if (cnx->dso && cnx->egl.eglGetProcAddress) {
1635 found = true;
Mathias Agopianab575012010-08-13 12:19:04 -07001636 // Extensions are independent of the bound context
1637 cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
1638 cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
Jack Palevichd4d0fb92010-10-26 15:21:24 -07001639#if EGL_TRACE
David Li28ca2ab2011-03-01 16:08:10 -08001640 gHooksDebug.ext.extensions[slot] = gHooksTrace.ext.extensions[slot] =
Jack Palevichd4d0fb92010-10-26 15:21:24 -07001641#endif
Mathias Agopian3944eab2010-08-02 17:34:32 -07001642 cnx->egl.eglGetProcAddress(procname);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 }
1644 }
Mathias Agopian3944eab2010-08-02 17:34:32 -07001645 if (found) {
1646 addr = gExtensionForwarders[slot];
Michael I. Goldf4a43832011-01-04 01:16:59 -08001647
1648 if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) {
1649 glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr;
1650 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper;
1651 }
1652 if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) {
1653 glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr;
1654 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper;
1655 }
1656
Mathias Agopian3944eab2010-08-02 17:34:32 -07001657 gGLExtentionMap.add(name, addr);
1658 gGLExtentionSlot++;
1659 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001660 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001661
Mathias Agopian3944eab2010-08-02 17:34:32 -07001662 pthread_mutex_unlock(&gInitDriverMutex);
Mathias Agopian3944eab2010-08-02 17:34:32 -07001663 return addr;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001664}
1665
1666EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
1667{
David Li55c94cc2011-03-04 17:50:48 -08001668 EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw);
1669 if (gEGLDebugLevel > 0)
1670 Debug_eglSwapBuffers(dpy, draw);
1671
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001672 clearError();
1673
Mathias Agopian4a34e882009-08-21 02:18:25 -07001674 SurfaceRef _s(draw);
1675 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1676
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001677 if (!validate_display_surface(dpy, draw))
1678 return EGL_FALSE;
1679 egl_display_t const * const dp = get_display(dpy);
1680 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian6fc56992009-10-14 02:06:37 -07001681 return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682}
1683
1684EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1685 NativePixmapType target)
1686{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001687 clearError();
1688
Mathias Agopian4a34e882009-08-21 02:18:25 -07001689 SurfaceRef _s(surface);
1690 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1691
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001692 if (!validate_display_surface(dpy, surface))
1693 return EGL_FALSE;
1694 egl_display_t const * const dp = get_display(dpy);
1695 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian6fc56992009-10-14 02:06:37 -07001696 return s->cnx->egl.eglCopyBuffers(
Mathias Agopian94263d72009-08-24 21:47:13 -07001697 dp->disp[s->impl].dpy, s->surface, target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001698}
1699
1700const char* eglQueryString(EGLDisplay dpy, EGLint name)
1701{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001702 clearError();
1703
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001704 egl_display_t const * const dp = get_display(dpy);
1705 switch (name) {
1706 case EGL_VENDOR:
1707 return gVendorString;
1708 case EGL_VERSION:
1709 return gVersionString;
1710 case EGL_EXTENSIONS:
1711 return gExtensionString;
1712 case EGL_CLIENT_APIS:
1713 return gClientApiString;
1714 }
1715 return setError(EGL_BAD_PARAMETER, (const char *)0);
1716}
1717
1718
1719// ----------------------------------------------------------------------------
1720// EGL 1.1
1721// ----------------------------------------------------------------------------
1722
1723EGLBoolean eglSurfaceAttrib(
1724 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1725{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001726 clearError();
1727
Mathias Agopian4a34e882009-08-21 02:18:25 -07001728 SurfaceRef _s(surface);
1729 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001731 if (!validate_display_surface(dpy, surface))
1732 return EGL_FALSE;
1733 egl_display_t const * const dp = get_display(dpy);
1734 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian6fc56992009-10-14 02:06:37 -07001735 if (s->cnx->egl.eglSurfaceAttrib) {
1736 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopian94263d72009-08-24 21:47:13 -07001737 dp->disp[s->impl].dpy, s->surface, attribute, value);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738 }
1739 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1740}
1741
1742EGLBoolean eglBindTexImage(
1743 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1744{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001745 clearError();
1746
Mathias Agopian4a34e882009-08-21 02:18:25 -07001747 SurfaceRef _s(surface);
1748 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1749
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001750 if (!validate_display_surface(dpy, surface))
1751 return EGL_FALSE;
1752 egl_display_t const * const dp = get_display(dpy);
1753 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian6fc56992009-10-14 02:06:37 -07001754 if (s->cnx->egl.eglBindTexImage) {
1755 return s->cnx->egl.eglBindTexImage(
Mathias Agopian94263d72009-08-24 21:47:13 -07001756 dp->disp[s->impl].dpy, s->surface, buffer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001757 }
1758 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1759}
1760
1761EGLBoolean eglReleaseTexImage(
1762 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1763{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001764 clearError();
1765
Mathias Agopian4a34e882009-08-21 02:18:25 -07001766 SurfaceRef _s(surface);
1767 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1768
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001769 if (!validate_display_surface(dpy, surface))
1770 return EGL_FALSE;
1771 egl_display_t const * const dp = get_display(dpy);
1772 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian6fc56992009-10-14 02:06:37 -07001773 if (s->cnx->egl.eglReleaseTexImage) {
1774 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopian94263d72009-08-24 21:47:13 -07001775 dp->disp[s->impl].dpy, s->surface, buffer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001776 }
1777 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1778}
1779
1780EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1781{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001782 clearError();
1783
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 egl_display_t * const dp = get_display(dpy);
1785 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1786
1787 EGLBoolean res = EGL_TRUE;
Mathias Agopian6fc56992009-10-14 02:06:37 -07001788 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001789 egl_connection_t* const cnx = &gEGLImpl[i];
1790 if (cnx->dso) {
Mathias Agopian6fc56992009-10-14 02:06:37 -07001791 if (cnx->egl.eglSwapInterval) {
1792 if (cnx->egl.eglSwapInterval(
Mathias Agopian94263d72009-08-24 21:47:13 -07001793 dp->disp[i].dpy, interval) == EGL_FALSE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001794 res = EGL_FALSE;
1795 }
1796 }
1797 }
1798 }
1799 return res;
1800}
1801
1802
1803// ----------------------------------------------------------------------------
1804// EGL 1.2
1805// ----------------------------------------------------------------------------
1806
1807EGLBoolean eglWaitClient(void)
1808{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001809 clearError();
1810
Mathias Agopiandcebf6f2009-08-17 18:07:06 -07001811 // could be called before eglInitialize(), but we wouldn't have a context
1812 // then, and this function would return GL_TRUE, which isn't wrong.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001813 EGLBoolean res = EGL_TRUE;
1814 EGLContext ctx = getContext();
1815 if (ctx) {
1816 egl_context_t const * const c = get_context(ctx);
1817 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1818 if (uint32_t(c->impl)>=2)
1819 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1820 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1821 if (!cnx->dso)
1822 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian6fc56992009-10-14 02:06:37 -07001823 if (cnx->egl.eglWaitClient) {
1824 res = cnx->egl.eglWaitClient();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001825 } else {
Mathias Agopian6fc56992009-10-14 02:06:37 -07001826 res = cnx->egl.eglWaitGL();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001827 }
1828 }
1829 return res;
1830}
1831
1832EGLBoolean eglBindAPI(EGLenum api)
1833{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001834 clearError();
1835
Mathias Agopiandcebf6f2009-08-17 18:07:06 -07001836 if (egl_init_drivers() == EGL_FALSE) {
1837 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1838 }
1839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001840 // bind this API on all EGLs
1841 EGLBoolean res = EGL_TRUE;
Mathias Agopian6fc56992009-10-14 02:06:37 -07001842 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001843 egl_connection_t* const cnx = &gEGLImpl[i];
1844 if (cnx->dso) {
Mathias Agopian6fc56992009-10-14 02:06:37 -07001845 if (cnx->egl.eglBindAPI) {
1846 if (cnx->egl.eglBindAPI(api) == EGL_FALSE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 res = EGL_FALSE;
1848 }
1849 }
1850 }
1851 }
1852 return res;
1853}
1854
1855EGLenum eglQueryAPI(void)
1856{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001857 clearError();
1858
Mathias Agopiandcebf6f2009-08-17 18:07:06 -07001859 if (egl_init_drivers() == EGL_FALSE) {
1860 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1861 }
1862
Mathias Agopian6fc56992009-10-14 02:06:37 -07001863 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001864 egl_connection_t* const cnx = &gEGLImpl[i];
1865 if (cnx->dso) {
Mathias Agopian6fc56992009-10-14 02:06:37 -07001866 if (cnx->egl.eglQueryAPI) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001867 // the first one we find is okay, because they all
1868 // should be the same
Mathias Agopian6fc56992009-10-14 02:06:37 -07001869 return cnx->egl.eglQueryAPI();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001870 }
1871 }
1872 }
1873 // or, it can only be OpenGL ES
1874 return EGL_OPENGL_ES_API;
1875}
1876
1877EGLBoolean eglReleaseThread(void)
1878{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001879 clearError();
1880
Michael I. Goldf0ca1d32010-12-23 13:51:36 -08001881 // If there is context bound to the thread, release it
1882 loseCurrent(get_context(getContext()));
1883
Mathias Agopian6fc56992009-10-14 02:06:37 -07001884 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001885 egl_connection_t* const cnx = &gEGLImpl[i];
1886 if (cnx->dso) {
Mathias Agopian6fc56992009-10-14 02:06:37 -07001887 if (cnx->egl.eglReleaseThread) {
1888 cnx->egl.eglReleaseThread();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001889 }
1890 }
1891 }
1892 clearTLS();
1893 return EGL_TRUE;
1894}
1895
1896EGLSurface eglCreatePbufferFromClientBuffer(
1897 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1898 EGLConfig config, const EGLint *attrib_list)
1899{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001900 clearError();
1901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001902 egl_display_t const* dp = 0;
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001903 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001904 if (!cnx) return EGL_FALSE;
Mathias Agopian6fc56992009-10-14 02:06:37 -07001905 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1906 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001907 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1908 buftype, buffer,
1909 dp->configs[intptr_t(config)].config, attrib_list);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001910 }
1911 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1912}
Mathias Agopian1473f462009-04-10 14:24:30 -07001913
1914// ----------------------------------------------------------------------------
1915// EGL_EGLEXT_VERSION 3
1916// ----------------------------------------------------------------------------
1917
1918EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1919 const EGLint *attrib_list)
1920{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001921 clearError();
1922
Mathias Agopian4a34e882009-08-21 02:18:25 -07001923 SurfaceRef _s(surface);
1924 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1925
Mathias Agopian1473f462009-04-10 14:24:30 -07001926 if (!validate_display_surface(dpy, surface))
Mathias Agopian88e3e6b2009-08-12 21:18:15 -07001927 return EGL_FALSE;
Mathias Agopian1473f462009-04-10 14:24:30 -07001928
1929 egl_display_t const * const dp = get_display(dpy);
1930 egl_surface_t const * const s = get_surface(surface);
1931
Mathias Agopian6fc56992009-10-14 02:06:37 -07001932 if (s->cnx->egl.eglLockSurfaceKHR) {
1933 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopian94263d72009-08-24 21:47:13 -07001934 dp->disp[s->impl].dpy, s->surface, attrib_list);
Mathias Agopian1473f462009-04-10 14:24:30 -07001935 }
Mathias Agopian88e3e6b2009-08-12 21:18:15 -07001936 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian1473f462009-04-10 14:24:30 -07001937}
1938
1939EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1940{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001941 clearError();
1942
Mathias Agopian4a34e882009-08-21 02:18:25 -07001943 SurfaceRef _s(surface);
1944 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1945
Mathias Agopian1473f462009-04-10 14:24:30 -07001946 if (!validate_display_surface(dpy, surface))
Mathias Agopian88e3e6b2009-08-12 21:18:15 -07001947 return EGL_FALSE;
Mathias Agopian1473f462009-04-10 14:24:30 -07001948
1949 egl_display_t const * const dp = get_display(dpy);
1950 egl_surface_t const * const s = get_surface(surface);
1951
Mathias Agopian6fc56992009-10-14 02:06:37 -07001952 if (s->cnx->egl.eglUnlockSurfaceKHR) {
1953 return s->cnx->egl.eglUnlockSurfaceKHR(
Mathias Agopian94263d72009-08-24 21:47:13 -07001954 dp->disp[s->impl].dpy, s->surface);
Mathias Agopian1473f462009-04-10 14:24:30 -07001955 }
Mathias Agopian88e3e6b2009-08-12 21:18:15 -07001956 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian1473f462009-04-10 14:24:30 -07001957}
1958
1959EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1960 EGLClientBuffer buffer, const EGLint *attrib_list)
1961{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001962 clearError();
1963
Mathias Agopian1473f462009-04-10 14:24:30 -07001964 if (ctx != EGL_NO_CONTEXT) {
Mathias Agopian4a34e882009-08-21 02:18:25 -07001965 ContextRef _c(ctx);
1966 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
Mathias Agopian1473f462009-04-10 14:24:30 -07001967 if (!validate_display_context(dpy, ctx))
1968 return EGL_NO_IMAGE_KHR;
1969 egl_display_t const * const dp = get_display(dpy);
1970 egl_context_t * const c = get_context(ctx);
1971 // since we have an EGLContext, we know which implementation to use
Mathias Agopian6fc56992009-10-14 02:06:37 -07001972 EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
Mathias Agopian94263d72009-08-24 21:47:13 -07001973 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
Mathias Agopian1473f462009-04-10 14:24:30 -07001974 if (image == EGL_NO_IMAGE_KHR)
1975 return image;
1976
1977 egl_image_t* result = new egl_image_t(dpy, ctx);
1978 result->images[c->impl] = image;
1979 return (EGLImageKHR)result;
1980 } else {
1981 // EGL_NO_CONTEXT is a valid parameter
1982 egl_display_t const * const dp = get_display(dpy);
1983 if (dp == 0) {
1984 return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
1985 }
Mathias Agopianf007a2f2009-10-28 21:00:29 -07001986
1987 /* Since we don't have a way to know which implementation to call,
1988 * we're calling all of them. If at least one of the implementation
1989 * succeeded, this is a success.
1990 */
1991
1992 EGLint currentError = eglGetError();
Mathias Agopian1473f462009-04-10 14:24:30 -07001993
Mathias Agopian6fc56992009-10-14 02:06:37 -07001994 EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS];
Mathias Agopian1473f462009-04-10 14:24:30 -07001995 bool success = false;
Mathias Agopian6fc56992009-10-14 02:06:37 -07001996 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
Mathias Agopian1473f462009-04-10 14:24:30 -07001997 egl_connection_t* const cnx = &gEGLImpl[i];
1998 implImages[i] = EGL_NO_IMAGE_KHR;
1999 if (cnx->dso) {
Mathias Agopian6fc56992009-10-14 02:06:37 -07002000 if (cnx->egl.eglCreateImageKHR) {
2001 implImages[i] = cnx->egl.eglCreateImageKHR(
Mathias Agopian94263d72009-08-24 21:47:13 -07002002 dp->disp[i].dpy, ctx, target, buffer, attrib_list);
Mathias Agopian1473f462009-04-10 14:24:30 -07002003 if (implImages[i] != EGL_NO_IMAGE_KHR) {
2004 success = true;
2005 }
2006 }
2007 }
2008 }
Mathias Agopianf007a2f2009-10-28 21:00:29 -07002009
2010 if (!success) {
2011 // failure, if there was an error when we entered this function,
2012 // the error flag must not be updated.
2013 // Otherwise, the error is whatever happened in the implementation
2014 // that faulted.
2015 if (currentError != EGL_SUCCESS) {
2016 setError(currentError, EGL_NO_IMAGE_KHR);
2017 }
Mathias Agopian1473f462009-04-10 14:24:30 -07002018 return EGL_NO_IMAGE_KHR;
Mathias Agopianf007a2f2009-10-28 21:00:29 -07002019 } else {
2020 // In case of success, we need to clear all error flags
2021 // (especially those caused by the implementation that didn't
Mathias Agopian0b0722f2009-10-29 18:29:30 -07002022 // succeed). TODO: we could avoid this if we knew this was
Mathias Agopianf007a2f2009-10-28 21:00:29 -07002023 // a "full" success (all implementation succeeded).
2024 eglGetError();
2025 }
2026
Mathias Agopian1473f462009-04-10 14:24:30 -07002027 egl_image_t* result = new egl_image_t(dpy, ctx);
2028 memcpy(result->images, implImages, sizeof(implImages));
2029 return (EGLImageKHR)result;
2030 }
2031}
2032
2033EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
2034{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08002035 clearError();
2036
Mathias Agopian4a34e882009-08-21 02:18:25 -07002037 egl_display_t const * const dp = get_display(dpy);
Mathias Agopian1473f462009-04-10 14:24:30 -07002038 if (dp == 0) {
2039 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2040 }
2041
Mathias Agopian4a34e882009-08-21 02:18:25 -07002042 ImageRef _i(img);
2043 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian1473f462009-04-10 14:24:30 -07002044
Mathias Agopian4a34e882009-08-21 02:18:25 -07002045 egl_image_t* image = get_image(img);
Mathias Agopian1473f462009-04-10 14:24:30 -07002046 bool success = false;
Mathias Agopian6fc56992009-10-14 02:06:37 -07002047 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
Mathias Agopian1473f462009-04-10 14:24:30 -07002048 egl_connection_t* const cnx = &gEGLImpl[i];
2049 if (image->images[i] != EGL_NO_IMAGE_KHR) {
2050 if (cnx->dso) {
Mathias Agopian97961db2010-09-09 11:12:54 -07002051 if (cnx->egl.eglDestroyImageKHR) {
Mathias Agopian6fc56992009-10-14 02:06:37 -07002052 if (cnx->egl.eglDestroyImageKHR(
Mathias Agopian94263d72009-08-24 21:47:13 -07002053 dp->disp[i].dpy, image->images[i])) {
Mathias Agopian1473f462009-04-10 14:24:30 -07002054 success = true;
2055 }
2056 }
2057 }
2058 }
2059 }
2060 if (!success)
2061 return EGL_FALSE;
2062
Mathias Agopian4a34e882009-08-21 02:18:25 -07002063 _i.terminate();
Mathias Agopian1473f462009-04-10 14:24:30 -07002064
Mathias Agopian88e3e6b2009-08-12 21:18:15 -07002065 return EGL_TRUE;
Mathias Agopian1473f462009-04-10 14:24:30 -07002066}
Mathias Agopian2e20bff2009-05-04 19:29:25 -07002067
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002068// ----------------------------------------------------------------------------
2069// EGL_EGLEXT_VERSION 5
2070// ----------------------------------------------------------------------------
2071
2072
2073EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
2074{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08002075 clearError();
2076
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002077 EGLContext ctx = eglGetCurrentContext();
2078 ContextRef _c(ctx);
Mathias Agopian4644ea72010-09-21 16:22:10 -07002079 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR);
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002080 if (!validate_display_context(dpy, ctx))
Mathias Agopian4644ea72010-09-21 16:22:10 -07002081 return EGL_NO_SYNC_KHR;
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002082 egl_display_t const * const dp = get_display(dpy);
2083 egl_context_t * const c = get_context(ctx);
Mathias Agopian4644ea72010-09-21 16:22:10 -07002084 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002085 if (c->cnx->egl.eglCreateSyncKHR) {
2086 EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR(
2087 dp->disp[c->impl].dpy, type, attrib_list);
Mathias Agopian4644ea72010-09-21 16:22:10 -07002088 if (sync == EGL_NO_SYNC_KHR)
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002089 return sync;
2090 result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync);
2091 }
2092 return (EGLSyncKHR)result;
2093}
2094
2095EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
2096{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08002097 clearError();
2098
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002099 egl_display_t const * const dp = get_display(dpy);
2100 if (dp == 0) {
2101 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2102 }
2103
2104 SyncRef _s(sync);
2105 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2106 egl_sync_t* syncObject = get_sync(sync);
2107
2108 EGLContext ctx = syncObject->context;
2109 ContextRef _c(ctx);
2110 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
2111 if (!validate_display_context(dpy, ctx))
2112 return EGL_FALSE;
2113
2114 egl_context_t * const c = get_context(ctx);
2115
2116 if (c->cnx->egl.eglDestroySyncKHR) {
2117 return c->cnx->egl.eglDestroySyncKHR(
2118 dp->disp[c->impl].dpy, syncObject->sync);
2119 }
2120
2121 return EGL_FALSE;
2122}
2123
2124EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
2125{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08002126 clearError();
2127
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002128 egl_display_t const * const dp = get_display(dpy);
2129 if (dp == 0) {
2130 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2131 }
2132
2133 SyncRef _s(sync);
2134 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2135 egl_sync_t* syncObject = get_sync(sync);
2136
2137 EGLContext ctx = syncObject->context;
2138 ContextRef _c(ctx);
2139 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
2140 if (!validate_display_context(dpy, ctx))
2141 return EGL_FALSE;
2142
2143 egl_context_t * const c = get_context(ctx);
2144
2145 if (c->cnx->egl.eglClientWaitSyncKHR) {
2146 return c->cnx->egl.eglClientWaitSyncKHR(
2147 dp->disp[c->impl].dpy, syncObject->sync, flags, timeout);
2148 }
2149
2150 return EGL_FALSE;
2151}
2152
2153EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
2154{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08002155 clearError();
2156
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002157 egl_display_t const * const dp = get_display(dpy);
2158 if (dp == 0) {
2159 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2160 }
2161
2162 SyncRef _s(sync);
2163 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2164 egl_sync_t* syncObject = get_sync(sync);
2165
2166 EGLContext ctx = syncObject->context;
2167 ContextRef _c(ctx);
2168 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
2169 if (!validate_display_context(dpy, ctx))
2170 return EGL_FALSE;
2171
2172 egl_context_t * const c = get_context(ctx);
2173
2174 if (c->cnx->egl.eglGetSyncAttribKHR) {
2175 return c->cnx->egl.eglGetSyncAttribKHR(
2176 dp->disp[c->impl].dpy, syncObject->sync, attribute, value);
2177 }
2178
2179 return EGL_FALSE;
2180}
Mathias Agopian2e20bff2009-05-04 19:29:25 -07002181
2182// ----------------------------------------------------------------------------
2183// ANDROID extensions
2184// ----------------------------------------------------------------------------
2185
2186EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
2187 EGLint left, EGLint top, EGLint width, EGLint height)
2188{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08002189 clearError();
2190
Mathias Agopian4a34e882009-08-21 02:18:25 -07002191 SurfaceRef _s(draw);
2192 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
2193
Mathias Agopian2e20bff2009-05-04 19:29:25 -07002194 if (!validate_display_surface(dpy, draw))
2195 return EGL_FALSE;
2196 egl_display_t const * const dp = get_display(dpy);
2197 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian6fc56992009-10-14 02:06:37 -07002198 if (s->cnx->egl.eglSetSwapRectangleANDROID) {
2199 return s->cnx->egl.eglSetSwapRectangleANDROID(
Mathias Agopian94263d72009-08-24 21:47:13 -07002200 dp->disp[s->impl].dpy, s->surface, left, top, width, height);
Mathias Agopian2e20bff2009-05-04 19:29:25 -07002201 }
Mathias Agopian88e3e6b2009-08-12 21:18:15 -07002202 return setError(EGL_BAD_DISPLAY, NULL);
Mathias Agopian2e20bff2009-05-04 19:29:25 -07002203}