blob: 66f9e2ddccc46e4acbaf964b7f11cfa4db390d0a [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/*
2 ** Copyright 2007, The Android Open Source Project
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 ** http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080017#include <ctype.h>
Mathias Agopiand8fb7b52009-05-17 18:50:16 -070018#include <stdlib.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080019#include <string.h>
20#include <errno.h>
21#include <dlfcn.h>
22
23#include <sys/ioctl.h>
24
25#if HAVE_ANDROID_OS
26#include <linux/android_pmem.h>
27#endif
28
29#include <EGL/egl.h>
30#include <EGL/eglext.h>
31#include <GLES/gl.h>
32#include <GLES/glext.h>
33
34#include <cutils/log.h>
35#include <cutils/atomic.h>
36#include <cutils/properties.h>
37#include <cutils/memory.h>
38
Mathias Agopian9429e9c2009-08-21 02:18:25 -070039#include <utils/SortedVector.h>
Mathias Agopian24035332010-08-02 17:34:32 -070040#include <utils/KeyedVector.h>
41#include <utils/String8.h>
Mathias Agopian9429e9c2009-08-21 02:18:25 -070042
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080043#include "hooks.h"
44#include "egl_impl.h"
Mathias Agopiande586972009-05-28 17:39:03 -070045#include "Loader.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080046
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080047#define setError(_e, _r) setErrorEtc(__FUNCTION__, __LINE__, _e, _r)
48
49// ----------------------------------------------------------------------------
50namespace android {
51// ----------------------------------------------------------------------------
52
53#define VERSION_MAJOR 1
54#define VERSION_MINOR 4
55static char const * const gVendorString = "Android";
Mathias Agopian923c6612009-08-17 18:07:06 -070056static char const * const gVersionString = "1.4 Android META-EGL";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080057static char const * const gClientApiString = "OpenGL ES";
Mathias Agopian076b1cc2009-04-10 14:24:30 -070058static char const * const gExtensionString =
59 "EGL_KHR_image "
Mathias Agopiane6bf8b32009-05-06 23:47:08 -070060 "EGL_KHR_image_base "
61 "EGL_KHR_image_pixmap "
Mathias Agopian8e4b5a32010-08-27 16:08:03 -070062 "EGL_KHR_gl_texture_2D_image "
Mathias Agopianc291f5852010-08-27 16:48:56 -070063 "EGL_KHR_fence_sync "
Mathias Agopian076b1cc2009-04-10 14:24:30 -070064 "EGL_ANDROID_image_native_buffer "
Mathias Agopiandf3ca302009-05-04 19:29:25 -070065 "EGL_ANDROID_swap_rectangle "
Mathias Agopian076b1cc2009-04-10 14:24:30 -070066 ;
67
68// ----------------------------------------------------------------------------
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080069
Mathias Agopian9429e9c2009-08-21 02:18:25 -070070class egl_object_t {
71 static SortedVector<egl_object_t*> sObjects;
72 static Mutex sLock;
73
74 volatile int32_t terminated;
75 mutable volatile int32_t count;
76
77public:
78 egl_object_t() : terminated(0), count(1) {
79 Mutex::Autolock _l(sLock);
80 sObjects.add(this);
81 }
82
83 inline bool isAlive() const { return !terminated; }
84
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080085private:
Mathias Agopian9429e9c2009-08-21 02:18:25 -070086 bool get() {
87 Mutex::Autolock _l(sLock);
88 if (egl_object_t::sObjects.indexOf(this) >= 0) {
89 android_atomic_inc(&count);
90 return true;
91 }
92 return false;
93 }
94
95 bool put() {
96 Mutex::Autolock _l(sLock);
97 if (android_atomic_dec(&count) == 1) {
98 sObjects.remove(this);
99 return true;
100 }
101 return false;
102 }
103
104public:
105 template <typename N, typename T>
106 struct LocalRef {
107 N* ref;
108 LocalRef(T o) : ref(0) {
109 N* native = reinterpret_cast<N*>(o);
110 if (o && native->get()) {
111 ref = native;
112 }
113 }
114 ~LocalRef() {
115 if (ref && ref->put()) {
116 delete ref;
117 }
118 }
119 inline N* get() {
120 return ref;
121 }
122 void acquire() const {
123 if (ref) {
124 android_atomic_inc(&ref->count);
125 }
126 }
127 void release() const {
128 if (ref) {
129 int32_t c = android_atomic_dec(&ref->count);
130 // ref->count cannot be 1 prior atomic_dec because we have
131 // a reference, and if we have one, it means there was
132 // already one before us.
133 LOGE_IF(c==1, "refcount is now 0 in release()");
134 }
135 }
136 void terminate() {
137 if (ref) {
138 ref->terminated = 1;
139 release();
140 }
141 }
142 };
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800143};
144
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700145SortedVector<egl_object_t*> egl_object_t::sObjects;
146Mutex egl_object_t::sLock;
147
Mathias Agopiancee79392010-07-26 21:14:59 -0700148
149struct egl_config_t {
150 egl_config_t() {}
151 egl_config_t(int impl, EGLConfig config)
152 : impl(impl), config(config), configId(0), implConfigId(0) { }
153 int impl; // the implementation this config is for
154 EGLConfig config; // the implementation's EGLConfig
155 EGLint configId; // our CONFIG_ID
156 EGLint implConfigId; // the implementation's CONFIG_ID
157 inline bool operator < (const egl_config_t& rhs) const {
158 if (impl < rhs.impl) return true;
159 if (impl > rhs.impl) return false;
160 return config < rhs.config;
161 }
162};
163
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700164struct egl_display_t {
165 enum { NOT_INITIALIZED, INITIALIZED, TERMINATED };
166
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800167 struct strings_t {
168 char const * vendor;
169 char const * version;
170 char const * clientApi;
171 char const * extensions;
172 };
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700173
174 struct DisplayImpl {
175 DisplayImpl() : dpy(EGL_NO_DISPLAY), config(0),
176 state(NOT_INITIALIZED), numConfigs(0) { }
177 EGLDisplay dpy;
178 EGLConfig* config;
179 EGLint state;
180 EGLint numConfigs;
181 strings_t queryString;
182 };
183
Mathias Agopiancee79392010-07-26 21:14:59 -0700184 uint32_t magic;
185 DisplayImpl disp[IMPL_NUM_IMPLEMENTATIONS];
186 EGLint numTotalConfigs;
187 egl_config_t* configs;
188 uint32_t refs;
189 Mutex lock;
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700190
Mathias Agopiancee79392010-07-26 21:14:59 -0700191 egl_display_t() : magic('_dpy'), numTotalConfigs(0), configs(0) { }
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700192 ~egl_display_t() { magic = 0; }
193 inline bool isValid() const { return magic == '_dpy'; }
194 inline bool isAlive() const { return isValid(); }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800195};
196
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700197struct egl_surface_t : public egl_object_t
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800198{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700199 typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
200
Mathias Agopiancee79392010-07-26 21:14:59 -0700201 egl_surface_t(EGLDisplay dpy, EGLSurface surface, EGLConfig config,
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700202 int impl, egl_connection_t const* cnx)
Mathias Agopiancee79392010-07-26 21:14:59 -0700203 : dpy(dpy), surface(surface), config(config), impl(impl), cnx(cnx) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800204 }
205 ~egl_surface_t() {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800206 }
207 EGLDisplay dpy;
208 EGLSurface surface;
Mathias Agopiancee79392010-07-26 21:14:59 -0700209 EGLConfig config;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800210 int impl;
211 egl_connection_t const* cnx;
212};
213
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700214struct egl_context_t : public egl_object_t
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800215{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700216 typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
217
Mathias Agopiancee79392010-07-26 21:14:59 -0700218 egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
Mathias Agopian618fa102009-10-14 02:06:37 -0700219 int impl, egl_connection_t const* cnx, int version)
220 : dpy(dpy), context(context), read(0), draw(0), impl(impl), cnx(cnx),
221 version(version)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800222 {
223 }
224 EGLDisplay dpy;
225 EGLContext context;
Mathias Agopiancee79392010-07-26 21:14:59 -0700226 EGLConfig config;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800227 EGLSurface read;
228 EGLSurface draw;
229 int impl;
230 egl_connection_t const* cnx;
Mathias Agopian618fa102009-10-14 02:06:37 -0700231 int version;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800232};
233
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700234struct egl_image_t : public egl_object_t
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700235{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700236 typedef egl_object_t::LocalRef<egl_image_t, EGLImageKHR> Ref;
237
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700238 egl_image_t(EGLDisplay dpy, EGLContext context)
239 : dpy(dpy), context(context)
240 {
241 memset(images, 0, sizeof(images));
242 }
243 EGLDisplay dpy;
Mathias Agopian77fbf8d2010-09-09 11:12:54 -0700244 EGLContext context;
Mathias Agopian618fa102009-10-14 02:06:37 -0700245 EGLImageKHR images[IMPL_NUM_IMPLEMENTATIONS];
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700246};
247
Mathias Agopianc291f5852010-08-27 16:48:56 -0700248struct egl_sync_t : public egl_object_t
249{
250 typedef egl_object_t::LocalRef<egl_sync_t, EGLSyncKHR> Ref;
251
252 egl_sync_t(EGLDisplay dpy, EGLContext context, EGLSyncKHR sync)
253 : dpy(dpy), context(context), sync(sync)
254 {
255 }
256 EGLDisplay dpy;
257 EGLContext context;
258 EGLSyncKHR sync;
259};
260
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700261typedef egl_surface_t::Ref SurfaceRef;
262typedef egl_context_t::Ref ContextRef;
263typedef egl_image_t::Ref ImageRef;
Mathias Agopianc291f5852010-08-27 16:48:56 -0700264typedef egl_sync_t::Ref SyncRef;
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700265
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800266struct tls_t
267{
Mathias Agopiand274eae2009-07-31 16:21:17 -0700268 tls_t() : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(EGL_TRUE) { }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800269 EGLint error;
270 EGLContext ctx;
Mathias Agopiand274eae2009-07-31 16:21:17 -0700271 EGLBoolean logCallWithNoContext;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800272};
273
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800274
275// ----------------------------------------------------------------------------
276
Mathias Agopianbf41b112010-04-09 13:37:34 -0700277static egl_connection_t gEGLImpl[IMPL_NUM_IMPLEMENTATIONS];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800278static egl_display_t gDisplay[NUM_DISPLAYS];
279static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER;
280static pthread_key_t gEGLThreadLocalStorageKey = -1;
281
282// ----------------------------------------------------------------------------
283
Mathias Agopian618fa102009-10-14 02:06:37 -0700284EGLAPI gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS];
285EGLAPI gl_hooks_t gHooksNoContext;
Mathias Agopianeccc8cf2009-05-13 00:19:22 -0700286EGLAPI pthread_key_t gGLWrapperKey = -1;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800287
288// ----------------------------------------------------------------------------
289
290static __attribute__((noinline))
291const char *egl_strerror(EGLint err)
292{
293 switch (err){
294 case EGL_SUCCESS: return "EGL_SUCCESS";
295 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
296 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
297 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
298 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
299 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
300 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
301 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
302 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
303 case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
304 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
305 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
306 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
307 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
308 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
309 default: return "UNKNOWN";
310 }
311}
312
313static __attribute__((noinline))
314void clearTLS() {
315 if (gEGLThreadLocalStorageKey != -1) {
316 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
317 if (tls) {
318 delete tls;
319 pthread_setspecific(gEGLThreadLocalStorageKey, 0);
320 }
321 }
322}
323
324static tls_t* getTLS()
325{
326 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
327 if (tls == 0) {
328 tls = new tls_t;
329 pthread_setspecific(gEGLThreadLocalStorageKey, tls);
330 }
331 return tls;
332}
333
334template<typename T>
335static __attribute__((noinline))
336T setErrorEtc(const char* caller, int line, EGLint error, T returnValue) {
337 if (gEGLThreadLocalStorageKey == -1) {
338 pthread_mutex_lock(&gThreadLocalStorageKeyMutex);
339 if (gEGLThreadLocalStorageKey == -1)
340 pthread_key_create(&gEGLThreadLocalStorageKey, NULL);
341 pthread_mutex_unlock(&gThreadLocalStorageKeyMutex);
342 }
343 tls_t* tls = getTLS();
344 if (tls->error != error) {
345 LOGE("%s:%d error %x (%s)", caller, line, error, egl_strerror(error));
346 tls->error = error;
347 }
348 return returnValue;
349}
350
351static __attribute__((noinline))
352GLint getError() {
353 if (gEGLThreadLocalStorageKey == -1)
354 return EGL_SUCCESS;
355 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
356 if (!tls) return EGL_SUCCESS;
357 GLint error = tls->error;
358 tls->error = EGL_SUCCESS;
359 return error;
360}
361
362static __attribute__((noinline))
363void setContext(EGLContext ctx) {
364 if (gEGLThreadLocalStorageKey == -1) {
365 pthread_mutex_lock(&gThreadLocalStorageKeyMutex);
366 if (gEGLThreadLocalStorageKey == -1)
367 pthread_key_create(&gEGLThreadLocalStorageKey, NULL);
368 pthread_mutex_unlock(&gThreadLocalStorageKeyMutex);
369 }
370 tls_t* tls = getTLS();
371 tls->ctx = ctx;
372}
373
374static __attribute__((noinline))
375EGLContext getContext() {
376 if (gEGLThreadLocalStorageKey == -1)
377 return EGL_NO_CONTEXT;
378 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
379 if (!tls) return EGL_NO_CONTEXT;
380 return tls->ctx;
381}
382
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800383/*****************************************************************************/
384
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800385template<typename T>
386static __attribute__((noinline))
387int binarySearch(
388 T const sortedArray[], int first, int last, T key)
389{
390 while (first <= last) {
391 int mid = (first + last) / 2;
Mathias Agopiancee79392010-07-26 21:14:59 -0700392 if (sortedArray[mid] < key) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800393 first = mid + 1;
394 } else if (key < sortedArray[mid]) {
395 last = mid - 1;
396 } else {
397 return mid;
398 }
399 }
400 return -1;
401}
402
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800403static int cmp_configs(const void* a, const void *b)
404{
Mathias Agopiancee79392010-07-26 21:14:59 -0700405 const egl_config_t& c0 = *(egl_config_t const *)a;
406 const egl_config_t& c1 = *(egl_config_t const *)b;
407 return c0<c1 ? -1 : (c1<c0 ? 1 : 0);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800408}
409
410struct extention_map_t {
411 const char* name;
412 __eglMustCastToProperFunctionPointerType address;
413};
414
415static const extention_map_t gExtentionMap[] = {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700416 { "eglLockSurfaceKHR",
417 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
418 { "eglUnlockSurfaceKHR",
419 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
420 { "eglCreateImageKHR",
421 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
422 { "eglDestroyImageKHR",
423 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Mathias Agopian8d2e83b2009-06-24 22:37:39 -0700424 { "eglSetSwapRectangleANDROID",
425 (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800426};
427
Mathias Agopian24035332010-08-02 17:34:32 -0700428extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
429
430// accesses protected by gInitDriverMutex
431static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> gGLExtentionMap;
432static int gGLExtentionSlot = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800433
434static void(*findProcAddress(const char* name,
435 const extention_map_t* map, size_t n))()
436{
437 for (uint32_t i=0 ; i<n ; i++) {
438 if (!strcmp(name, map[i].name)) {
439 return map[i].address;
440 }
441 }
442 return NULL;
443}
444
445// ----------------------------------------------------------------------------
446
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800447static void gl_no_context() {
Mathias Agopiand274eae2009-07-31 16:21:17 -0700448 tls_t* tls = getTLS();
449 if (tls->logCallWithNoContext == EGL_TRUE) {
450 tls->logCallWithNoContext = EGL_FALSE;
451 LOGE("call to OpenGL ES API with no current context "
452 "(logged once per thread)");
453 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800454}
Mathias Agopiand274eae2009-07-31 16:21:17 -0700455
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800456static void early_egl_init(void)
457{
458#if !USE_FAST_TLS_KEY
459 pthread_key_create(&gGLWrapperKey, NULL);
460#endif
461 uint32_t addr = (uint32_t)((void*)gl_no_context);
462 android_memset32(
Mathias Agopian618fa102009-10-14 02:06:37 -0700463 (uint32_t*)(void*)&gHooksNoContext,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800464 addr,
Mathias Agopian618fa102009-10-14 02:06:37 -0700465 sizeof(gHooksNoContext));
466 setGlThreadSpecific(&gHooksNoContext);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800467}
468
469static pthread_once_t once_control = PTHREAD_ONCE_INIT;
470static int sEarlyInitState = pthread_once(&once_control, &early_egl_init);
471
472
473static inline
474egl_display_t* get_display(EGLDisplay dpy)
475{
476 uintptr_t index = uintptr_t(dpy)-1U;
477 return (index >= NUM_DISPLAYS) ? NULL : &gDisplay[index];
478}
479
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700480template<typename NATIVE, typename EGL>
481static inline NATIVE* egl_to_native_cast(EGL arg) {
482 return reinterpret_cast<NATIVE*>(arg);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800483}
484
485static inline
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700486egl_surface_t* get_surface(EGLSurface surface) {
487 return egl_to_native_cast<egl_surface_t>(surface);
488}
489
490static inline
491egl_context_t* get_context(EGLContext context) {
492 return egl_to_native_cast<egl_context_t>(context);
493}
494
495static inline
496egl_image_t* get_image(EGLImageKHR image) {
497 return egl_to_native_cast<egl_image_t>(image);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800498}
499
Mathias Agopianc291f5852010-08-27 16:48:56 -0700500static inline
501egl_sync_t* get_sync(EGLSyncKHR sync) {
502 return egl_to_native_cast<egl_sync_t>(sync);
503}
504
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800505static egl_connection_t* validate_display_config(
506 EGLDisplay dpy, EGLConfig config,
Mathias Agopiancee79392010-07-26 21:14:59 -0700507 egl_display_t const*& dp)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800508{
509 dp = get_display(dpy);
510 if (!dp) return setError(EGL_BAD_DISPLAY, (egl_connection_t*)NULL);
511
Mathias Agopiancee79392010-07-26 21:14:59 -0700512 if (intptr_t(config) >= dp->numTotalConfigs) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800513 return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
514 }
Mathias Agopiancee79392010-07-26 21:14:59 -0700515 egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(config)].impl];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800516 if (cnx->dso == 0) {
517 return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
518 }
519 return cnx;
520}
521
522static EGLBoolean validate_display_context(EGLDisplay dpy, EGLContext ctx)
523{
524 if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS)
525 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700526 if (!get_display(dpy)->isAlive())
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800527 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700528 if (!get_context(ctx)->isAlive())
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800529 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
530 return EGL_TRUE;
531}
532
533static EGLBoolean validate_display_surface(EGLDisplay dpy, EGLSurface surface)
534{
535 if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS)
536 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700537 if (!get_display(dpy)->isAlive())
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800538 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700539 if (!get_surface(surface)->isAlive())
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800540 return setError(EGL_BAD_SURFACE, EGL_FALSE);
541 return EGL_TRUE;
542}
543
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700544EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image)
545{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700546 ImageRef _i(image);
547 if (!_i.get()) return EGL_NO_IMAGE_KHR;
548
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700549 EGLContext context = getContext();
550 if (context == EGL_NO_CONTEXT || image == EGL_NO_IMAGE_KHR)
551 return EGL_NO_IMAGE_KHR;
552
553 egl_context_t const * const c = get_context(context);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700554 if (!c->isAlive())
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700555 return EGL_NO_IMAGE_KHR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800556
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700557 egl_image_t const * const i = get_image(image);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700558 return i->images[c->impl];
559}
560
Mathias Agopian923c6612009-08-17 18:07:06 -0700561// ----------------------------------------------------------------------------
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700562
Mathias Agopian923c6612009-08-17 18:07:06 -0700563// this mutex protects:
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700564// d->disp[]
Mathias Agopian923c6612009-08-17 18:07:06 -0700565// egl_init_drivers_locked()
566//
567static pthread_mutex_t gInitDriverMutex = PTHREAD_MUTEX_INITIALIZER;
568
569EGLBoolean egl_init_drivers_locked()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800570{
571 if (sEarlyInitState) {
Mathias Agopian923c6612009-08-17 18:07:06 -0700572 // initialized by static ctor. should be set here.
573 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800574 }
575
Mathias Agopiande586972009-05-28 17:39:03 -0700576 // get our driver loader
Mathias Agopian923c6612009-08-17 18:07:06 -0700577 Loader& loader(Loader::getInstance());
Mathias Agopiande586972009-05-28 17:39:03 -0700578
Mathias Agopian923c6612009-08-17 18:07:06 -0700579 // dynamically load all our EGL implementations for all displays
580 // and retrieve the corresponding EGLDisplay
581 // if that fails, don't use this driver.
582 // TODO: currently we only deal with EGL_DEFAULT_DISPLAY
583 egl_connection_t* cnx;
584 egl_display_t* d = &gDisplay[0];
585
586 cnx = &gEGLImpl[IMPL_SOFTWARE];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800587 if (cnx->dso == 0) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700588 cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_SOFTWARE];
589 cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_SOFTWARE];
590 cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 0, cnx);
Mathias Agopian923c6612009-08-17 18:07:06 -0700591 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700592 EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
Mathias Agopian923c6612009-08-17 18:07:06 -0700593 LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for software EGL!");
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700594 d->disp[IMPL_SOFTWARE].dpy = dpy;
Mathias Agopian923c6612009-08-17 18:07:06 -0700595 if (dpy == EGL_NO_DISPLAY) {
596 loader.close(cnx->dso);
597 cnx->dso = NULL;
598 }
599 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800600 }
601
602 cnx = &gEGLImpl[IMPL_HARDWARE];
Mathias Agopian923c6612009-08-17 18:07:06 -0700603 if (cnx->dso == 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800604 char value[PROPERTY_VALUE_MAX];
605 property_get("debug.egl.hw", value, "1");
606 if (atoi(value) != 0) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700607 cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_HARDWARE];
608 cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_HARDWARE];
609 cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 1, cnx);
Mathias Agopian923c6612009-08-17 18:07:06 -0700610 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700611 EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
Mathias Agopian923c6612009-08-17 18:07:06 -0700612 LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for hardware EGL!");
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700613 d->disp[IMPL_HARDWARE].dpy = dpy;
Mathias Agopian923c6612009-08-17 18:07:06 -0700614 if (dpy == EGL_NO_DISPLAY) {
615 loader.close(cnx->dso);
616 cnx->dso = NULL;
617 }
618 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800619 } else {
620 LOGD("3D hardware acceleration is disabled");
621 }
622 }
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700623
Mathias Agopian923c6612009-08-17 18:07:06 -0700624 if (!gEGLImpl[IMPL_SOFTWARE].dso && !gEGLImpl[IMPL_HARDWARE].dso) {
625 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800626 }
627
Mathias Agopian923c6612009-08-17 18:07:06 -0700628 return EGL_TRUE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800629}
630
Mathias Agopian923c6612009-08-17 18:07:06 -0700631EGLBoolean egl_init_drivers()
632{
633 EGLBoolean res;
634 pthread_mutex_lock(&gInitDriverMutex);
635 res = egl_init_drivers_locked();
636 pthread_mutex_unlock(&gInitDriverMutex);
637 return res;
638}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700639
640// ----------------------------------------------------------------------------
641}; // namespace android
642// ----------------------------------------------------------------------------
643
644using namespace android;
645
646EGLDisplay eglGetDisplay(NativeDisplayType display)
647{
Mathias Agopian923c6612009-08-17 18:07:06 -0700648 uint32_t index = uint32_t(display);
649 if (index >= NUM_DISPLAYS) {
650 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
651 }
652
653 if (egl_init_drivers() == EGL_FALSE) {
654 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
655 }
656
657 EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU);
658 return dpy;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700659}
660
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800661// ----------------------------------------------------------------------------
662// Initialization
663// ----------------------------------------------------------------------------
664
665EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
666{
667 egl_display_t * const dp = get_display(dpy);
668 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
669
Mathias Agopian75bc2782010-02-05 16:17:01 -0800670 Mutex::Autolock _l(dp->lock);
671
672 if (dp->refs > 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800673 if (major != NULL) *major = VERSION_MAJOR;
674 if (minor != NULL) *minor = VERSION_MINOR;
Jack Palevich81cd0842010-03-15 20:45:21 -0700675 dp->refs++;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800676 return EGL_TRUE;
677 }
678
Mathias Agopian618fa102009-10-14 02:06:37 -0700679 setGlThreadSpecific(&gHooksNoContext);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800680
681 // initialize each EGL and
682 // build our own extension string first, based on the extension we know
683 // and the extension supported by our client implementation
Mathias Agopian618fa102009-10-14 02:06:37 -0700684 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800685 egl_connection_t* const cnx = &gEGLImpl[i];
686 cnx->major = -1;
687 cnx->minor = -1;
688 if (!cnx->dso)
689 continue;
690
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700691#if defined(ADRENO130)
692#warning "Adreno-130 eglInitialize() workaround"
693 /*
694 * The ADRENO 130 driver returns a different EGLDisplay each time
695 * eglGetDisplay() is called, but also makes the EGLDisplay invalid
696 * after eglTerminate() has been called, so that eglInitialize()
697 * cannot be called again. Therefore, we need to make sure to call
698 * eglGetDisplay() before calling eglInitialize();
699 */
700 if (i == IMPL_HARDWARE) {
701 dp->disp[i].dpy =
Mathias Agopian618fa102009-10-14 02:06:37 -0700702 cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700703 }
704#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800705
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700706
707 EGLDisplay idpy = dp->disp[i].dpy;
Mathias Agopian618fa102009-10-14 02:06:37 -0700708 if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800709 //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p",
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700710 // i, idpy, cnx->major, cnx->minor, cnx);
711
712 // display is now initialized
713 dp->disp[i].state = egl_display_t::INITIALIZED;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800714
715 // get the query-strings for this display for each implementation
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700716 dp->disp[i].queryString.vendor =
Mathias Agopian618fa102009-10-14 02:06:37 -0700717 cnx->egl.eglQueryString(idpy, EGL_VENDOR);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700718 dp->disp[i].queryString.version =
Mathias Agopian618fa102009-10-14 02:06:37 -0700719 cnx->egl.eglQueryString(idpy, EGL_VERSION);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700720 dp->disp[i].queryString.extensions =
Mathias Agopian618fa102009-10-14 02:06:37 -0700721 cnx->egl.eglQueryString(idpy, EGL_EXTENSIONS);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700722 dp->disp[i].queryString.clientApi =
Mathias Agopian618fa102009-10-14 02:06:37 -0700723 cnx->egl.eglQueryString(idpy, EGL_CLIENT_APIS);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800724
725 } else {
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700726 LOGW("%d: eglInitialize(%p) failed (%s)", i, idpy,
Mathias Agopian618fa102009-10-14 02:06:37 -0700727 egl_strerror(cnx->egl.eglGetError()));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800728 }
729 }
730
731 EGLBoolean res = EGL_FALSE;
Mathias Agopian618fa102009-10-14 02:06:37 -0700732 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800733 egl_connection_t* const cnx = &gEGLImpl[i];
734 if (cnx->dso && cnx->major>=0 && cnx->minor>=0) {
735 EGLint n;
Mathias Agopian618fa102009-10-14 02:06:37 -0700736 if (cnx->egl.eglGetConfigs(dp->disp[i].dpy, 0, 0, &n)) {
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700737 dp->disp[i].config = (EGLConfig*)malloc(sizeof(EGLConfig)*n);
738 if (dp->disp[i].config) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700739 if (cnx->egl.eglGetConfigs(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700740 dp->disp[i].dpy, dp->disp[i].config, n,
741 &dp->disp[i].numConfigs))
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800742 {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800743 dp->numTotalConfigs += n;
744 res = EGL_TRUE;
745 }
746 }
747 }
748 }
749 }
750
751 if (res == EGL_TRUE) {
Mathias Agopiancee79392010-07-26 21:14:59 -0700752 dp->configs = new egl_config_t[ dp->numTotalConfigs ];
753 for (int i=0, k=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
754 egl_connection_t* const cnx = &gEGLImpl[i];
755 if (cnx->dso && cnx->major>=0 && cnx->minor>=0) {
756 for (int j=0 ; j<dp->disp[i].numConfigs ; j++) {
757 dp->configs[k].impl = i;
758 dp->configs[k].config = dp->disp[i].config[j];
759 dp->configs[k].configId = k + 1; // CONFIG_ID start at 1
760 // store the implementation's CONFIG_ID
761 cnx->egl.eglGetConfigAttrib(
762 dp->disp[i].dpy,
763 dp->disp[i].config[j],
764 EGL_CONFIG_ID,
765 &dp->configs[k].implConfigId);
766 k++;
767 }
768 }
769 }
770
771 // sort our configurations so we can do binary-searches
772 qsort( dp->configs,
773 dp->numTotalConfigs,
774 sizeof(egl_config_t), cmp_configs);
775
Mathias Agopian75bc2782010-02-05 16:17:01 -0800776 dp->refs++;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800777 if (major != NULL) *major = VERSION_MAJOR;
778 if (minor != NULL) *minor = VERSION_MINOR;
779 return EGL_TRUE;
780 }
781 return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
782}
783
784EGLBoolean eglTerminate(EGLDisplay dpy)
785{
Mathias Agopian923c6612009-08-17 18:07:06 -0700786 // NOTE: don't unload the drivers b/c some APIs can be called
787 // after eglTerminate() has been called. eglTerminate() only
788 // terminates an EGLDisplay, not a EGL itself.
789
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800790 egl_display_t* const dp = get_display(dpy);
791 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian75bc2782010-02-05 16:17:01 -0800792
793 Mutex::Autolock _l(dp->lock);
794
795 if (dp->refs == 0) {
796 return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
797 }
798
799 // this is specific to Android, display termination is ref-counted.
Jack Palevich81cd0842010-03-15 20:45:21 -0700800 if (dp->refs > 1) {
801 dp->refs--;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800802 return EGL_TRUE;
Jack Palevich81cd0842010-03-15 20:45:21 -0700803 }
Mathias Agopiande586972009-05-28 17:39:03 -0700804
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800805 EGLBoolean res = EGL_FALSE;
Mathias Agopian618fa102009-10-14 02:06:37 -0700806 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800807 egl_connection_t* const cnx = &gEGLImpl[i];
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700808 if (cnx->dso && dp->disp[i].state == egl_display_t::INITIALIZED) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700809 if (cnx->egl.eglTerminate(dp->disp[i].dpy) == EGL_FALSE) {
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700810 LOGW("%d: eglTerminate(%p) failed (%s)", i, dp->disp[i].dpy,
Mathias Agopian618fa102009-10-14 02:06:37 -0700811 egl_strerror(cnx->egl.eglGetError()));
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700812 }
Mathias Agopian923c6612009-08-17 18:07:06 -0700813 // REVISIT: it's unclear what to do if eglTerminate() fails
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700814 free(dp->disp[i].config);
815
816 dp->disp[i].numConfigs = 0;
817 dp->disp[i].config = 0;
818 dp->disp[i].state = egl_display_t::TERMINATED;
819
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800820 res = EGL_TRUE;
821 }
822 }
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700823
824 // TODO: all egl_object_t should be marked for termination
825
Mathias Agopian75bc2782010-02-05 16:17:01 -0800826 dp->refs--;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800827 dp->numTotalConfigs = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -0700828 delete [] dp->configs;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800829 clearTLS();
830 return res;
831}
832
833// ----------------------------------------------------------------------------
834// configuration
835// ----------------------------------------------------------------------------
836
837EGLBoolean eglGetConfigs( EGLDisplay dpy,
838 EGLConfig *configs,
839 EGLint config_size, EGLint *num_config)
840{
841 egl_display_t const * const dp = get_display(dpy);
842 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
843
844 GLint numConfigs = dp->numTotalConfigs;
845 if (!configs) {
846 *num_config = numConfigs;
847 return EGL_TRUE;
848 }
Mathias Agopiancee79392010-07-26 21:14:59 -0700849
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800850 GLint n = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -0700851 for (intptr_t i=0 ; i<dp->numTotalConfigs && config_size ; i++) {
852 *configs++ = EGLConfig(i);
853 config_size--;
854 n++;
855 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800856
857 *num_config = n;
858 return EGL_TRUE;
859}
860
861EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
862 EGLConfig *configs, EGLint config_size,
863 EGLint *num_config)
864{
865 egl_display_t const * const dp = get_display(dpy);
866 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
867
Jack Palevich749c63d2009-03-25 15:12:17 -0700868 if (num_config==0) {
869 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800870 }
871
872 EGLint n;
873 EGLBoolean res = EGL_FALSE;
874 *num_config = 0;
875
876
877 // It is unfortunate, but we need to remap the EGL_CONFIG_IDs,
Mathias Agopiancee79392010-07-26 21:14:59 -0700878 // to do this, we have to go through the attrib_list array once
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800879 // to figure out both its size and if it contains an EGL_CONFIG_ID
880 // key. If so, the full array is copied and patched.
881 // NOTE: we assume that there can be only one occurrence
882 // of EGL_CONFIG_ID.
883
884 EGLint patch_index = -1;
885 GLint attr;
886 size_t size = 0;
Mathias Agopian04aed212010-05-17 14:45:43 -0700887 if (attrib_list) {
888 while ((attr=attrib_list[size]) != EGL_NONE) {
889 if (attr == EGL_CONFIG_ID)
890 patch_index = size;
891 size += 2;
892 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800893 }
894 if (patch_index >= 0) {
895 size += 2; // we need copy the sentinel as well
896 EGLint* new_list = (EGLint*)malloc(size*sizeof(EGLint));
897 if (new_list == 0)
898 return setError(EGL_BAD_ALLOC, EGL_FALSE);
899 memcpy(new_list, attrib_list, size*sizeof(EGLint));
900
901 // patch the requested EGL_CONFIG_ID
Mathias Agopiancee79392010-07-26 21:14:59 -0700902 bool found = false;
903 EGLConfig ourConfig(0);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800904 EGLint& configId(new_list[patch_index+1]);
Mathias Agopiancee79392010-07-26 21:14:59 -0700905 for (intptr_t i=0 ; i<dp->numTotalConfigs ; i++) {
906 if (dp->configs[i].configId == configId) {
907 ourConfig = EGLConfig(i);
908 configId = dp->configs[i].implConfigId;
909 found = true;
910 break;
911 }
912 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800913
Mathias Agopiancee79392010-07-26 21:14:59 -0700914 egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(ourConfig)].impl];
915 if (found && cnx->dso) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800916 // and switch to the new list
917 attrib_list = const_cast<const EGLint *>(new_list);
918
919 // At this point, the only configuration that can match is
920 // dp->configs[i][index], however, we don't know if it would be
921 // rejected because of the other attributes, so we do have to call
Mathias Agopian618fa102009-10-14 02:06:37 -0700922 // cnx->egl.eglChooseConfig() -- but we don't have to loop
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800923 // through all the EGLimpl[].
924 // We also know we can only get a single config back, and we know
925 // which one.
926
Mathias Agopian618fa102009-10-14 02:06:37 -0700927 res = cnx->egl.eglChooseConfig(
Mathias Agopiancee79392010-07-26 21:14:59 -0700928 dp->disp[ dp->configs[intptr_t(ourConfig)].impl ].dpy,
929 attrib_list, configs, config_size, &n);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800930 if (res && n>0) {
931 // n has to be 0 or 1, by construction, and we already know
932 // which config it will return (since there can be only one).
Jack Palevich749c63d2009-03-25 15:12:17 -0700933 if (configs) {
Mathias Agopiancee79392010-07-26 21:14:59 -0700934 configs[0] = ourConfig;
Jack Palevich749c63d2009-03-25 15:12:17 -0700935 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800936 *num_config = 1;
937 }
938 }
939
940 free(const_cast<EGLint *>(attrib_list));
941 return res;
942 }
943
Mathias Agopiancee79392010-07-26 21:14:59 -0700944
Mathias Agopian618fa102009-10-14 02:06:37 -0700945 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800946 egl_connection_t* const cnx = &gEGLImpl[i];
947 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700948 if (cnx->egl.eglChooseConfig(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700949 dp->disp[i].dpy, attrib_list, configs, config_size, &n)) {
Jack Palevich749c63d2009-03-25 15:12:17 -0700950 if (configs) {
951 // now we need to convert these client EGLConfig to our
Mathias Agopiancee79392010-07-26 21:14:59 -0700952 // internal EGLConfig format.
953 // This is done in O(n Log(n)) time.
Jack Palevich749c63d2009-03-25 15:12:17 -0700954 for (int j=0 ; j<n ; j++) {
Mathias Agopiancee79392010-07-26 21:14:59 -0700955 egl_config_t key(i, configs[j]);
956 intptr_t index = binarySearch<egl_config_t>(
957 dp->configs, 0, dp->numTotalConfigs, key);
Jack Palevich749c63d2009-03-25 15:12:17 -0700958 if (index >= 0) {
Mathias Agopiancee79392010-07-26 21:14:59 -0700959 configs[j] = EGLConfig(index);
Jack Palevich749c63d2009-03-25 15:12:17 -0700960 } else {
961 return setError(EGL_BAD_CONFIG, EGL_FALSE);
962 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800963 }
Jack Palevich749c63d2009-03-25 15:12:17 -0700964 configs += n;
965 config_size -= n;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800966 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800967 *num_config += n;
968 res = EGL_TRUE;
969 }
970 }
971 }
972 return res;
973}
974
975EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
976 EGLint attribute, EGLint *value)
977{
978 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -0700979 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800980 if (!cnx) return EGL_FALSE;
981
982 if (attribute == EGL_CONFIG_ID) {
Mathias Agopiancee79392010-07-26 21:14:59 -0700983 *value = dp->configs[intptr_t(config)].configId;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800984 return EGL_TRUE;
985 }
Mathias Agopian618fa102009-10-14 02:06:37 -0700986 return cnx->egl.eglGetConfigAttrib(
Mathias Agopiancee79392010-07-26 21:14:59 -0700987 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
988 dp->configs[intptr_t(config)].config, attribute, value);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800989}
990
991// ----------------------------------------------------------------------------
992// surfaces
993// ----------------------------------------------------------------------------
994
995EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
996 NativeWindowType window,
997 const EGLint *attrib_list)
998{
999 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -07001000 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001001 if (cnx) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001002 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopiancee79392010-07-26 21:14:59 -07001003 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1004 dp->configs[intptr_t(config)].config, window, attrib_list);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001005 if (surface != EGL_NO_SURFACE) {
Mathias Agopiancee79392010-07-26 21:14:59 -07001006 egl_surface_t* s = new egl_surface_t(dpy, surface, config,
1007 dp->configs[intptr_t(config)].impl, cnx);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001008 return s;
1009 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001010 }
1011 return EGL_NO_SURFACE;
1012}
1013
1014EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
1015 NativePixmapType pixmap,
1016 const EGLint *attrib_list)
1017{
1018 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -07001019 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001020 if (cnx) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001021 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopiancee79392010-07-26 21:14:59 -07001022 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1023 dp->configs[intptr_t(config)].config, pixmap, attrib_list);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001024 if (surface != EGL_NO_SURFACE) {
Mathias Agopiancee79392010-07-26 21:14:59 -07001025 egl_surface_t* s = new egl_surface_t(dpy, surface, config,
1026 dp->configs[intptr_t(config)].impl, cnx);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001027 return s;
1028 }
1029 }
1030 return EGL_NO_SURFACE;
1031}
1032
1033EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
1034 const EGLint *attrib_list)
1035{
1036 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -07001037 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001038 if (cnx) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001039 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopiancee79392010-07-26 21:14:59 -07001040 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1041 dp->configs[intptr_t(config)].config, attrib_list);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001042 if (surface != EGL_NO_SURFACE) {
Mathias Agopiancee79392010-07-26 21:14:59 -07001043 egl_surface_t* s = new egl_surface_t(dpy, surface, config,
1044 dp->configs[intptr_t(config)].impl, cnx);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001045 return s;
1046 }
1047 }
1048 return EGL_NO_SURFACE;
1049}
1050
1051EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
1052{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001053 SurfaceRef _s(surface);
1054 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1055
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001056 if (!validate_display_surface(dpy, surface))
1057 return EGL_FALSE;
1058 egl_display_t const * const dp = get_display(dpy);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001059
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001060 egl_surface_t * const s = get_surface(surface);
Mathias Agopian618fa102009-10-14 02:06:37 -07001061 EGLBoolean result = s->cnx->egl.eglDestroySurface(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001062 dp->disp[s->impl].dpy, s->surface);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001063 if (result == EGL_TRUE) {
1064 _s.terminate();
1065 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001066 return result;
1067}
1068
1069EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
1070 EGLint attribute, EGLint *value)
1071{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001072 SurfaceRef _s(surface);
1073 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1074
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001075 if (!validate_display_surface(dpy, surface))
1076 return EGL_FALSE;
1077 egl_display_t const * const dp = get_display(dpy);
1078 egl_surface_t const * const s = get_surface(surface);
1079
Mathias Agopiancee79392010-07-26 21:14:59 -07001080 EGLBoolean result(EGL_TRUE);
1081 if (attribute == EGL_CONFIG_ID) {
1082 // We need to remap EGL_CONFIG_IDs
1083 *value = dp->configs[intptr_t(s->config)].configId;
1084 } else {
1085 result = s->cnx->egl.eglQuerySurface(
1086 dp->disp[s->impl].dpy, s->surface, attribute, value);
1087 }
1088
1089 return result;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001090}
1091
1092// ----------------------------------------------------------------------------
Mathias Agopiancee79392010-07-26 21:14:59 -07001093// Contexts
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001094// ----------------------------------------------------------------------------
1095
1096EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
1097 EGLContext share_list, const EGLint *attrib_list)
1098{
1099 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -07001100 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001101 if (cnx) {
Jamie Gennis4c39f8f2010-07-02 11:39:12 -07001102 if (share_list != EGL_NO_CONTEXT) {
1103 egl_context_t* const c = get_context(share_list);
1104 share_list = c->context;
1105 }
Mathias Agopian618fa102009-10-14 02:06:37 -07001106 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopiancee79392010-07-26 21:14:59 -07001107 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1108 dp->configs[intptr_t(config)].config,
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001109 share_list, attrib_list);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001110 if (context != EGL_NO_CONTEXT) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001111 // figure out if it's a GLESv1 or GLESv2
1112 int version = 0;
1113 if (attrib_list) {
1114 while (*attrib_list != EGL_NONE) {
1115 GLint attr = *attrib_list++;
1116 GLint value = *attrib_list++;
1117 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
1118 if (value == 1) {
1119 version = GLESv1_INDEX;
1120 } else if (value == 2) {
1121 version = GLESv2_INDEX;
1122 }
1123 }
1124 };
1125 }
Mathias Agopiancee79392010-07-26 21:14:59 -07001126 egl_context_t* c = new egl_context_t(dpy, context, config,
1127 dp->configs[intptr_t(config)].impl, cnx, version);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001128 return c;
1129 }
1130 }
1131 return EGL_NO_CONTEXT;
1132}
1133
1134EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1135{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001136 ContextRef _c(ctx);
1137 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1138
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001139 if (!validate_display_context(dpy, ctx))
1140 return EGL_FALSE;
1141 egl_display_t const * const dp = get_display(dpy);
1142 egl_context_t * const c = get_context(ctx);
Mathias Agopian618fa102009-10-14 02:06:37 -07001143 EGLBoolean result = c->cnx->egl.eglDestroyContext(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001144 dp->disp[c->impl].dpy, c->context);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001145 if (result == EGL_TRUE) {
1146 _c.terminate();
1147 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001148 return result;
1149}
1150
1151EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
1152 EGLSurface read, EGLContext ctx)
1153{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001154 // get a reference to the object passed in
1155 ContextRef _c(ctx);
1156 SurfaceRef _d(draw);
1157 SurfaceRef _r(read);
1158
1159 // validate the display and the context (if not EGL_NO_CONTEXT)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001160 egl_display_t const * const dp = get_display(dpy);
1161 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001162 if ((ctx != EGL_NO_CONTEXT) && (!validate_display_context(dpy, ctx))) {
1163 // EGL_NO_CONTEXT is valid
1164 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001165 }
1166
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001167 // these are the underlying implementation's object
1168 EGLContext impl_ctx = EGL_NO_CONTEXT;
Mathias Agopianaf742132009-06-25 00:01:11 -07001169 EGLSurface impl_draw = EGL_NO_SURFACE;
1170 EGLSurface impl_read = EGL_NO_SURFACE;
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001171
1172 // these are our objects structs passed in
1173 egl_context_t * c = NULL;
1174 egl_surface_t const * d = NULL;
1175 egl_surface_t const * r = NULL;
1176
1177 // these are the current objects structs
1178 egl_context_t * cur_c = get_context(getContext());
1179 egl_surface_t * cur_r = NULL;
1180 egl_surface_t * cur_d = NULL;
1181
1182 if (ctx != EGL_NO_CONTEXT) {
1183 c = get_context(ctx);
1184 cur_r = get_surface(c->read);
1185 cur_d = get_surface(c->draw);
1186 impl_ctx = c->context;
1187 } else {
1188 // no context given, use the implementation of the current context
1189 if (cur_c == NULL) {
1190 // no current context
1191 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
Mathias Agopian8063c3a2010-01-25 11:30:11 -08001192 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
1193 return setError(EGL_BAD_MATCH, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001194 }
Mathias Agopian8063c3a2010-01-25 11:30:11 -08001195 // not an error, there is just no current context.
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001196 return EGL_TRUE;
1197 }
1198 }
1199
1200 // retrieve the underlying implementation's draw EGLSurface
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001201 if (draw != EGL_NO_SURFACE) {
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001202 d = get_surface(draw);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001203 // make sure the EGLContext and EGLSurface passed in are for
1204 // the same driver
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001205 if (c && d->impl != c->impl)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001206 return setError(EGL_BAD_MATCH, EGL_FALSE);
Mathias Agopianaf742132009-06-25 00:01:11 -07001207 impl_draw = d->surface;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001208 }
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001209
1210 // retrieve the underlying implementation's read EGLSurface
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001211 if (read != EGL_NO_SURFACE) {
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001212 r = get_surface(read);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001213 // make sure the EGLContext and EGLSurface passed in are for
1214 // the same driver
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001215 if (c && r->impl != c->impl)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001216 return setError(EGL_BAD_MATCH, EGL_FALSE);
Mathias Agopianaf742132009-06-25 00:01:11 -07001217 impl_read = r->surface;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001218 }
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001219
1220 EGLBoolean result;
1221
1222 if (c) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001223 result = c->cnx->egl.eglMakeCurrent(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001224 dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001225 } else {
Mathias Agopian618fa102009-10-14 02:06:37 -07001226 result = cur_c->cnx->egl.eglMakeCurrent(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001227 dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001228 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001229
1230 if (result == EGL_TRUE) {
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001231 // by construction, these are either 0 or valid (possibly terminated)
1232 // it should be impossible for these to be invalid
1233 ContextRef _cur_c(cur_c);
1234 SurfaceRef _cur_r(cur_r);
1235 SurfaceRef _cur_d(cur_d);
1236
1237 // cur_c has to be valid here (but could be terminated)
1238 if (ctx != EGL_NO_CONTEXT) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001239 setGlThreadSpecific(c->cnx->hooks[c->version]);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001240 setContext(ctx);
1241 _c.acquire();
1242 } else {
Mathias Agopian618fa102009-10-14 02:06:37 -07001243 setGlThreadSpecific(&gHooksNoContext);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001244 setContext(EGL_NO_CONTEXT);
1245 }
1246 _cur_c.release();
1247
1248 _r.acquire();
1249 _cur_r.release();
1250 if (c) c->read = read;
1251
1252 _d.acquire();
1253 _cur_d.release();
1254 if (c) c->draw = draw;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001255 }
1256 return result;
1257}
1258
1259
1260EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
1261 EGLint attribute, EGLint *value)
1262{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001263 ContextRef _c(ctx);
1264 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1265
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001266 if (!validate_display_context(dpy, ctx))
1267 return EGL_FALSE;
1268
1269 egl_display_t const * const dp = get_display(dpy);
1270 egl_context_t * const c = get_context(ctx);
1271
Mathias Agopiancee79392010-07-26 21:14:59 -07001272 EGLBoolean result(EGL_TRUE);
1273 if (attribute == EGL_CONFIG_ID) {
1274 *value = dp->configs[intptr_t(c->config)].configId;
1275 } else {
1276 // We need to remap EGL_CONFIG_IDs
1277 result = c->cnx->egl.eglQueryContext(
1278 dp->disp[c->impl].dpy, c->context, attribute, value);
1279 }
1280
1281 return result;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001282}
1283
1284EGLContext eglGetCurrentContext(void)
1285{
Mathias Agopian923c6612009-08-17 18:07:06 -07001286 // could be called before eglInitialize(), but we wouldn't have a context
1287 // then, and this function would correctly return EGL_NO_CONTEXT.
1288
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001289 EGLContext ctx = getContext();
1290 return ctx;
1291}
1292
1293EGLSurface eglGetCurrentSurface(EGLint readdraw)
1294{
Mathias Agopian923c6612009-08-17 18:07:06 -07001295 // could be called before eglInitialize(), but we wouldn't have a context
1296 // then, and this function would correctly return EGL_NO_SURFACE.
1297
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001298 EGLContext ctx = getContext();
1299 if (ctx) {
1300 egl_context_t const * const c = get_context(ctx);
1301 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1302 switch (readdraw) {
1303 case EGL_READ: return c->read;
1304 case EGL_DRAW: return c->draw;
1305 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1306 }
1307 }
1308 return EGL_NO_SURFACE;
1309}
1310
1311EGLDisplay eglGetCurrentDisplay(void)
1312{
Mathias Agopian923c6612009-08-17 18:07:06 -07001313 // could be called before eglInitialize(), but we wouldn't have a context
1314 // then, and this function would correctly return EGL_NO_DISPLAY.
1315
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001316 EGLContext ctx = getContext();
1317 if (ctx) {
1318 egl_context_t const * const c = get_context(ctx);
1319 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1320 return c->dpy;
1321 }
1322 return EGL_NO_DISPLAY;
1323}
1324
1325EGLBoolean eglWaitGL(void)
1326{
Mathias Agopian923c6612009-08-17 18:07:06 -07001327 // could be called before eglInitialize(), but we wouldn't have a context
1328 // then, and this function would return GL_TRUE, which isn't wrong.
1329
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001330 EGLBoolean res = EGL_TRUE;
1331 EGLContext ctx = getContext();
1332 if (ctx) {
1333 egl_context_t const * const c = get_context(ctx);
1334 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1335 if (uint32_t(c->impl)>=2)
1336 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1337 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1338 if (!cnx->dso)
1339 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian618fa102009-10-14 02:06:37 -07001340 res = cnx->egl.eglWaitGL();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001341 }
1342 return res;
1343}
1344
1345EGLBoolean eglWaitNative(EGLint engine)
1346{
Mathias Agopian923c6612009-08-17 18:07:06 -07001347 // could be called before eglInitialize(), but we wouldn't have a context
1348 // then, and this function would return GL_TRUE, which isn't wrong.
1349
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001350 EGLBoolean res = EGL_TRUE;
1351 EGLContext ctx = getContext();
1352 if (ctx) {
1353 egl_context_t const * const c = get_context(ctx);
1354 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1355 if (uint32_t(c->impl)>=2)
1356 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1357 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1358 if (!cnx->dso)
1359 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian618fa102009-10-14 02:06:37 -07001360 res = cnx->egl.eglWaitNative(engine);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001361 }
1362 return res;
1363}
1364
1365EGLint eglGetError(void)
1366{
1367 EGLint result = EGL_SUCCESS;
Mathias Agopian618fa102009-10-14 02:06:37 -07001368 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001369 EGLint err = EGL_SUCCESS;
1370 egl_connection_t* const cnx = &gEGLImpl[i];
1371 if (cnx->dso)
Mathias Agopian618fa102009-10-14 02:06:37 -07001372 err = cnx->egl.eglGetError();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001373 if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
1374 result = err;
1375 }
1376 if (result == EGL_SUCCESS)
1377 result = getError();
1378 return result;
1379}
1380
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001381__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001382{
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001383 // eglGetProcAddress() could be the very first function called
1384 // in which case we must make sure we've initialized ourselves, this
1385 // happens the first time egl_get_display() is called.
Mathias Agopian923c6612009-08-17 18:07:06 -07001386
1387 if (egl_init_drivers() == EGL_FALSE) {
1388 setError(EGL_BAD_PARAMETER, NULL);
1389 return NULL;
1390 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001391
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001392 __eglMustCastToProperFunctionPointerType addr;
1393 addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap));
1394 if (addr) return addr;
1395
Mathias Agopian24035332010-08-02 17:34:32 -07001396 // this protects accesses to gGLExtentionMap and gGLExtentionSlot
1397 pthread_mutex_lock(&gInitDriverMutex);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001398
Mathias Agopian24035332010-08-02 17:34:32 -07001399 /*
1400 * Since eglGetProcAddress() is not associated to anything, it needs
1401 * to return a function pointer that "works" regardless of what
1402 * the current context is.
1403 *
1404 * For this reason, we return a "forwarder", a small stub that takes
1405 * care of calling the function associated with the context
1406 * currently bound.
1407 *
1408 * We first look for extensions we've already resolved, if we're seeing
1409 * this extension for the first time, we go through all our
1410 * implementations and call eglGetProcAddress() and record the
1411 * result in the appropriate implementation hooks and return the
1412 * address of the forwarder corresponding to that hook set.
1413 *
1414 */
1415
1416 const String8 name(procname);
1417 addr = gGLExtentionMap.valueFor(name);
1418 const int slot = gGLExtentionSlot;
1419
1420 LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
1421 "no more slots for eglGetProcAddress(\"%s\")",
1422 procname);
1423
1424 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
1425 bool found = false;
1426 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1427 egl_connection_t* const cnx = &gEGLImpl[i];
1428 if (cnx->dso && cnx->egl.eglGetProcAddress) {
1429 found = true;
Mathias Agopian4a88b522010-08-13 12:19:04 -07001430 // Extensions are independent of the bound context
1431 cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
1432 cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopian24035332010-08-02 17:34:32 -07001433 cnx->egl.eglGetProcAddress(procname);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001434 }
1435 }
Mathias Agopian24035332010-08-02 17:34:32 -07001436 if (found) {
1437 addr = gExtensionForwarders[slot];
1438 gGLExtentionMap.add(name, addr);
1439 gGLExtentionSlot++;
1440 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001441 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001442
Mathias Agopian24035332010-08-02 17:34:32 -07001443 pthread_mutex_unlock(&gInitDriverMutex);
Mathias Agopian24035332010-08-02 17:34:32 -07001444 return addr;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001445}
1446
1447EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
1448{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001449 SurfaceRef _s(draw);
1450 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1451
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001452 if (!validate_display_surface(dpy, draw))
1453 return EGL_FALSE;
1454 egl_display_t const * const dp = get_display(dpy);
1455 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian618fa102009-10-14 02:06:37 -07001456 return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001457}
1458
1459EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1460 NativePixmapType target)
1461{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001462 SurfaceRef _s(surface);
1463 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1464
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001465 if (!validate_display_surface(dpy, surface))
1466 return EGL_FALSE;
1467 egl_display_t const * const dp = get_display(dpy);
1468 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian618fa102009-10-14 02:06:37 -07001469 return s->cnx->egl.eglCopyBuffers(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001470 dp->disp[s->impl].dpy, s->surface, target);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001471}
1472
1473const char* eglQueryString(EGLDisplay dpy, EGLint name)
1474{
1475 egl_display_t const * const dp = get_display(dpy);
1476 switch (name) {
1477 case EGL_VENDOR:
1478 return gVendorString;
1479 case EGL_VERSION:
1480 return gVersionString;
1481 case EGL_EXTENSIONS:
1482 return gExtensionString;
1483 case EGL_CLIENT_APIS:
1484 return gClientApiString;
1485 }
1486 return setError(EGL_BAD_PARAMETER, (const char *)0);
1487}
1488
1489
1490// ----------------------------------------------------------------------------
1491// EGL 1.1
1492// ----------------------------------------------------------------------------
1493
1494EGLBoolean eglSurfaceAttrib(
1495 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1496{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001497 SurfaceRef _s(surface);
1498 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1499
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001500 if (!validate_display_surface(dpy, surface))
1501 return EGL_FALSE;
1502 egl_display_t const * const dp = get_display(dpy);
1503 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian618fa102009-10-14 02:06:37 -07001504 if (s->cnx->egl.eglSurfaceAttrib) {
1505 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001506 dp->disp[s->impl].dpy, s->surface, attribute, value);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001507 }
1508 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1509}
1510
1511EGLBoolean eglBindTexImage(
1512 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1513{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001514 SurfaceRef _s(surface);
1515 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1516
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001517 if (!validate_display_surface(dpy, surface))
1518 return EGL_FALSE;
1519 egl_display_t const * const dp = get_display(dpy);
1520 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian618fa102009-10-14 02:06:37 -07001521 if (s->cnx->egl.eglBindTexImage) {
1522 return s->cnx->egl.eglBindTexImage(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001523 dp->disp[s->impl].dpy, s->surface, buffer);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001524 }
1525 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1526}
1527
1528EGLBoolean eglReleaseTexImage(
1529 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1530{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001531 SurfaceRef _s(surface);
1532 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1533
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001534 if (!validate_display_surface(dpy, surface))
1535 return EGL_FALSE;
1536 egl_display_t const * const dp = get_display(dpy);
1537 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian618fa102009-10-14 02:06:37 -07001538 if (s->cnx->egl.eglReleaseTexImage) {
1539 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001540 dp->disp[s->impl].dpy, s->surface, buffer);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001541 }
1542 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1543}
1544
1545EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1546{
1547 egl_display_t * const dp = get_display(dpy);
1548 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1549
1550 EGLBoolean res = EGL_TRUE;
Mathias Agopian618fa102009-10-14 02:06:37 -07001551 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001552 egl_connection_t* const cnx = &gEGLImpl[i];
1553 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001554 if (cnx->egl.eglSwapInterval) {
1555 if (cnx->egl.eglSwapInterval(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001556 dp->disp[i].dpy, interval) == EGL_FALSE) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001557 res = EGL_FALSE;
1558 }
1559 }
1560 }
1561 }
1562 return res;
1563}
1564
1565
1566// ----------------------------------------------------------------------------
1567// EGL 1.2
1568// ----------------------------------------------------------------------------
1569
1570EGLBoolean eglWaitClient(void)
1571{
Mathias Agopian923c6612009-08-17 18:07:06 -07001572 // could be called before eglInitialize(), but we wouldn't have a context
1573 // then, and this function would return GL_TRUE, which isn't wrong.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001574 EGLBoolean res = EGL_TRUE;
1575 EGLContext ctx = getContext();
1576 if (ctx) {
1577 egl_context_t const * const c = get_context(ctx);
1578 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1579 if (uint32_t(c->impl)>=2)
1580 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1581 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1582 if (!cnx->dso)
1583 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian618fa102009-10-14 02:06:37 -07001584 if (cnx->egl.eglWaitClient) {
1585 res = cnx->egl.eglWaitClient();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001586 } else {
Mathias Agopian618fa102009-10-14 02:06:37 -07001587 res = cnx->egl.eglWaitGL();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001588 }
1589 }
1590 return res;
1591}
1592
1593EGLBoolean eglBindAPI(EGLenum api)
1594{
Mathias Agopian923c6612009-08-17 18:07:06 -07001595 if (egl_init_drivers() == EGL_FALSE) {
1596 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1597 }
1598
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001599 // bind this API on all EGLs
1600 EGLBoolean res = EGL_TRUE;
Mathias Agopian618fa102009-10-14 02:06:37 -07001601 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001602 egl_connection_t* const cnx = &gEGLImpl[i];
1603 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001604 if (cnx->egl.eglBindAPI) {
1605 if (cnx->egl.eglBindAPI(api) == EGL_FALSE) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001606 res = EGL_FALSE;
1607 }
1608 }
1609 }
1610 }
1611 return res;
1612}
1613
1614EGLenum eglQueryAPI(void)
1615{
Mathias Agopian923c6612009-08-17 18:07:06 -07001616 if (egl_init_drivers() == EGL_FALSE) {
1617 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1618 }
1619
Mathias Agopian618fa102009-10-14 02:06:37 -07001620 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001621 egl_connection_t* const cnx = &gEGLImpl[i];
1622 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001623 if (cnx->egl.eglQueryAPI) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001624 // the first one we find is okay, because they all
1625 // should be the same
Mathias Agopian618fa102009-10-14 02:06:37 -07001626 return cnx->egl.eglQueryAPI();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001627 }
1628 }
1629 }
1630 // or, it can only be OpenGL ES
1631 return EGL_OPENGL_ES_API;
1632}
1633
1634EGLBoolean eglReleaseThread(void)
1635{
Mathias Agopian618fa102009-10-14 02:06:37 -07001636 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001637 egl_connection_t* const cnx = &gEGLImpl[i];
1638 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001639 if (cnx->egl.eglReleaseThread) {
1640 cnx->egl.eglReleaseThread();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001641 }
1642 }
1643 }
1644 clearTLS();
1645 return EGL_TRUE;
1646}
1647
1648EGLSurface eglCreatePbufferFromClientBuffer(
1649 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1650 EGLConfig config, const EGLint *attrib_list)
1651{
1652 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -07001653 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001654 if (!cnx) return EGL_FALSE;
Mathias Agopian618fa102009-10-14 02:06:37 -07001655 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1656 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopiancee79392010-07-26 21:14:59 -07001657 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1658 buftype, buffer,
1659 dp->configs[intptr_t(config)].config, attrib_list);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001660 }
1661 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1662}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001663
1664// ----------------------------------------------------------------------------
1665// EGL_EGLEXT_VERSION 3
1666// ----------------------------------------------------------------------------
1667
1668EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1669 const EGLint *attrib_list)
1670{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001671 SurfaceRef _s(surface);
1672 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1673
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001674 if (!validate_display_surface(dpy, surface))
Mathias Agopian24e5f522009-08-12 21:18:15 -07001675 return EGL_FALSE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001676
1677 egl_display_t const * const dp = get_display(dpy);
1678 egl_surface_t const * const s = get_surface(surface);
1679
Mathias Agopian618fa102009-10-14 02:06:37 -07001680 if (s->cnx->egl.eglLockSurfaceKHR) {
1681 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001682 dp->disp[s->impl].dpy, s->surface, attrib_list);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001683 }
Mathias Agopian24e5f522009-08-12 21:18:15 -07001684 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001685}
1686
1687EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1688{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001689 SurfaceRef _s(surface);
1690 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1691
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001692 if (!validate_display_surface(dpy, surface))
Mathias Agopian24e5f522009-08-12 21:18:15 -07001693 return EGL_FALSE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001694
1695 egl_display_t const * const dp = get_display(dpy);
1696 egl_surface_t const * const s = get_surface(surface);
1697
Mathias Agopian618fa102009-10-14 02:06:37 -07001698 if (s->cnx->egl.eglUnlockSurfaceKHR) {
1699 return s->cnx->egl.eglUnlockSurfaceKHR(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001700 dp->disp[s->impl].dpy, s->surface);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001701 }
Mathias Agopian24e5f522009-08-12 21:18:15 -07001702 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001703}
1704
1705EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1706 EGLClientBuffer buffer, const EGLint *attrib_list)
1707{
1708 if (ctx != EGL_NO_CONTEXT) {
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001709 ContextRef _c(ctx);
1710 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001711 if (!validate_display_context(dpy, ctx))
1712 return EGL_NO_IMAGE_KHR;
1713 egl_display_t const * const dp = get_display(dpy);
1714 egl_context_t * const c = get_context(ctx);
1715 // since we have an EGLContext, we know which implementation to use
Mathias Agopian618fa102009-10-14 02:06:37 -07001716 EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001717 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001718 if (image == EGL_NO_IMAGE_KHR)
1719 return image;
1720
1721 egl_image_t* result = new egl_image_t(dpy, ctx);
1722 result->images[c->impl] = image;
1723 return (EGLImageKHR)result;
1724 } else {
1725 // EGL_NO_CONTEXT is a valid parameter
1726 egl_display_t const * const dp = get_display(dpy);
1727 if (dp == 0) {
1728 return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
1729 }
Mathias Agopiandf2d9292009-10-28 21:00:29 -07001730
1731 /* Since we don't have a way to know which implementation to call,
1732 * we're calling all of them. If at least one of the implementation
1733 * succeeded, this is a success.
1734 */
1735
1736 EGLint currentError = eglGetError();
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001737
Mathias Agopian618fa102009-10-14 02:06:37 -07001738 EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS];
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001739 bool success = false;
Mathias Agopian618fa102009-10-14 02:06:37 -07001740 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001741 egl_connection_t* const cnx = &gEGLImpl[i];
1742 implImages[i] = EGL_NO_IMAGE_KHR;
1743 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001744 if (cnx->egl.eglCreateImageKHR) {
1745 implImages[i] = cnx->egl.eglCreateImageKHR(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001746 dp->disp[i].dpy, ctx, target, buffer, attrib_list);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001747 if (implImages[i] != EGL_NO_IMAGE_KHR) {
1748 success = true;
1749 }
1750 }
1751 }
1752 }
Mathias Agopiandf2d9292009-10-28 21:00:29 -07001753
1754 if (!success) {
1755 // failure, if there was an error when we entered this function,
1756 // the error flag must not be updated.
1757 // Otherwise, the error is whatever happened in the implementation
1758 // that faulted.
1759 if (currentError != EGL_SUCCESS) {
1760 setError(currentError, EGL_NO_IMAGE_KHR);
1761 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001762 return EGL_NO_IMAGE_KHR;
Mathias Agopiandf2d9292009-10-28 21:00:29 -07001763 } else {
1764 // In case of success, we need to clear all error flags
1765 // (especially those caused by the implementation that didn't
Mathias Agopian863e5fd2009-10-29 18:29:30 -07001766 // succeed). TODO: we could avoid this if we knew this was
Mathias Agopiandf2d9292009-10-28 21:00:29 -07001767 // a "full" success (all implementation succeeded).
1768 eglGetError();
1769 }
1770
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001771 egl_image_t* result = new egl_image_t(dpy, ctx);
1772 memcpy(result->images, implImages, sizeof(implImages));
1773 return (EGLImageKHR)result;
1774 }
1775}
1776
1777EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1778{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001779 egl_display_t const * const dp = get_display(dpy);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001780 if (dp == 0) {
1781 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1782 }
1783
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001784 ImageRef _i(img);
1785 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001786
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001787 egl_image_t* image = get_image(img);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001788 bool success = false;
Mathias Agopian618fa102009-10-14 02:06:37 -07001789 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001790 egl_connection_t* const cnx = &gEGLImpl[i];
1791 if (image->images[i] != EGL_NO_IMAGE_KHR) {
1792 if (cnx->dso) {
Mathias Agopian77fbf8d2010-09-09 11:12:54 -07001793 if (cnx->egl.eglDestroyImageKHR) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001794 if (cnx->egl.eglDestroyImageKHR(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001795 dp->disp[i].dpy, image->images[i])) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001796 success = true;
1797 }
1798 }
1799 }
1800 }
1801 }
1802 if (!success)
1803 return EGL_FALSE;
1804
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001805 _i.terminate();
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001806
Mathias Agopian24e5f522009-08-12 21:18:15 -07001807 return EGL_TRUE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001808}
Mathias Agopiandf3ca302009-05-04 19:29:25 -07001809
Mathias Agopianc291f5852010-08-27 16:48:56 -07001810// ----------------------------------------------------------------------------
1811// EGL_EGLEXT_VERSION 5
1812// ----------------------------------------------------------------------------
1813
1814
1815EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1816{
1817 EGLContext ctx = eglGetCurrentContext();
1818 ContextRef _c(ctx);
1819 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1820 if (!validate_display_context(dpy, ctx))
1821 return EGL_NO_IMAGE_KHR;
1822 egl_display_t const * const dp = get_display(dpy);
1823 egl_context_t * const c = get_context(ctx);
1824 EGLSyncKHR result = EGL_NO_IMAGE_KHR;
1825 if (c->cnx->egl.eglCreateSyncKHR) {
1826 EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR(
1827 dp->disp[c->impl].dpy, type, attrib_list);
1828 if (sync == EGL_NO_IMAGE_KHR)
1829 return sync;
1830 result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync);
1831 }
1832 return (EGLSyncKHR)result;
1833}
1834
1835EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1836{
1837 egl_display_t const * const dp = get_display(dpy);
1838 if (dp == 0) {
1839 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1840 }
1841
1842 SyncRef _s(sync);
1843 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1844 egl_sync_t* syncObject = get_sync(sync);
1845
1846 EGLContext ctx = syncObject->context;
1847 ContextRef _c(ctx);
1848 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1849 if (!validate_display_context(dpy, ctx))
1850 return EGL_FALSE;
1851
1852 egl_context_t * const c = get_context(ctx);
1853
1854 if (c->cnx->egl.eglDestroySyncKHR) {
1855 return c->cnx->egl.eglDestroySyncKHR(
1856 dp->disp[c->impl].dpy, syncObject->sync);
1857 }
1858
1859 return EGL_FALSE;
1860}
1861
1862EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
1863{
1864 egl_display_t const * const dp = get_display(dpy);
1865 if (dp == 0) {
1866 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1867 }
1868
1869 SyncRef _s(sync);
1870 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1871 egl_sync_t* syncObject = get_sync(sync);
1872
1873 EGLContext ctx = syncObject->context;
1874 ContextRef _c(ctx);
1875 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1876 if (!validate_display_context(dpy, ctx))
1877 return EGL_FALSE;
1878
1879 egl_context_t * const c = get_context(ctx);
1880
1881 if (c->cnx->egl.eglClientWaitSyncKHR) {
1882 return c->cnx->egl.eglClientWaitSyncKHR(
1883 dp->disp[c->impl].dpy, syncObject->sync, flags, timeout);
1884 }
1885
1886 return EGL_FALSE;
1887}
1888
1889EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
1890{
1891 egl_display_t const * const dp = get_display(dpy);
1892 if (dp == 0) {
1893 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1894 }
1895
1896 SyncRef _s(sync);
1897 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1898 egl_sync_t* syncObject = get_sync(sync);
1899
1900 EGLContext ctx = syncObject->context;
1901 ContextRef _c(ctx);
1902 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1903 if (!validate_display_context(dpy, ctx))
1904 return EGL_FALSE;
1905
1906 egl_context_t * const c = get_context(ctx);
1907
1908 if (c->cnx->egl.eglGetSyncAttribKHR) {
1909 return c->cnx->egl.eglGetSyncAttribKHR(
1910 dp->disp[c->impl].dpy, syncObject->sync, attribute, value);
1911 }
1912
1913 return EGL_FALSE;
1914}
Mathias Agopiandf3ca302009-05-04 19:29:25 -07001915
1916// ----------------------------------------------------------------------------
1917// ANDROID extensions
1918// ----------------------------------------------------------------------------
1919
1920EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
1921 EGLint left, EGLint top, EGLint width, EGLint height)
1922{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001923 SurfaceRef _s(draw);
1924 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1925
Mathias Agopiandf3ca302009-05-04 19:29:25 -07001926 if (!validate_display_surface(dpy, draw))
1927 return EGL_FALSE;
1928 egl_display_t const * const dp = get_display(dpy);
1929 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian618fa102009-10-14 02:06:37 -07001930 if (s->cnx->egl.eglSetSwapRectangleANDROID) {
1931 return s->cnx->egl.eglSetSwapRectangleANDROID(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001932 dp->disp[s->impl].dpy, s->surface, left, top, width, height);
Mathias Agopiandf3ca302009-05-04 19:29:25 -07001933 }
Mathias Agopian24e5f522009-08-12 21:18:15 -07001934 return setError(EGL_BAD_DISPLAY, NULL);
Mathias Agopiandf3ca302009-05-04 19:29:25 -07001935}