blob: 363595ee3ffb067a66e1c31d8ac1b9644b4a4c67 [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>
40
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080041#include "hooks.h"
42#include "egl_impl.h"
Mathias Agopiande586972009-05-28 17:39:03 -070043#include "Loader.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080044
45#define MAKE_CONFIG(_impl, _index) ((EGLConfig)(((_impl)<<24) | (_index)))
46#define setError(_e, _r) setErrorEtc(__FUNCTION__, __LINE__, _e, _r)
47
48// ----------------------------------------------------------------------------
49namespace android {
50// ----------------------------------------------------------------------------
51
52#define VERSION_MAJOR 1
53#define VERSION_MINOR 4
54static char const * const gVendorString = "Android";
Mathias Agopian923c6612009-08-17 18:07:06 -070055static char const * const gVersionString = "1.4 Android META-EGL";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080056static char const * const gClientApiString = "OpenGL ES";
Mathias Agopian076b1cc2009-04-10 14:24:30 -070057static char const * const gExtensionString =
58 "EGL_KHR_image "
Mathias Agopiane6bf8b32009-05-06 23:47:08 -070059 "EGL_KHR_image_base "
60 "EGL_KHR_image_pixmap "
Mathias Agopian076b1cc2009-04-10 14:24:30 -070061 "EGL_ANDROID_image_native_buffer "
Mathias Agopiandf3ca302009-05-04 19:29:25 -070062 "EGL_ANDROID_swap_rectangle "
Mathias Agopian8d2e83b2009-06-24 22:37:39 -070063 "EGL_ANDROID_get_render_buffer "
Mathias Agopian076b1cc2009-04-10 14:24:30 -070064 ;
65
66// ----------------------------------------------------------------------------
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080067
Mathias Agopian9429e9c2009-08-21 02:18:25 -070068class egl_object_t {
69 static SortedVector<egl_object_t*> sObjects;
70 static Mutex sLock;
71
72 volatile int32_t terminated;
73 mutable volatile int32_t count;
74
75public:
76 egl_object_t() : terminated(0), count(1) {
77 Mutex::Autolock _l(sLock);
78 sObjects.add(this);
79 }
80
81 inline bool isAlive() const { return !terminated; }
82
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080083private:
Mathias Agopian9429e9c2009-08-21 02:18:25 -070084 bool get() {
85 Mutex::Autolock _l(sLock);
86 if (egl_object_t::sObjects.indexOf(this) >= 0) {
87 android_atomic_inc(&count);
88 return true;
89 }
90 return false;
91 }
92
93 bool put() {
94 Mutex::Autolock _l(sLock);
95 if (android_atomic_dec(&count) == 1) {
96 sObjects.remove(this);
97 return true;
98 }
99 return false;
100 }
101
102public:
103 template <typename N, typename T>
104 struct LocalRef {
105 N* ref;
106 LocalRef(T o) : ref(0) {
107 N* native = reinterpret_cast<N*>(o);
108 if (o && native->get()) {
109 ref = native;
110 }
111 }
112 ~LocalRef() {
113 if (ref && ref->put()) {
114 delete ref;
115 }
116 }
117 inline N* get() {
118 return ref;
119 }
120 void acquire() const {
121 if (ref) {
122 android_atomic_inc(&ref->count);
123 }
124 }
125 void release() const {
126 if (ref) {
127 int32_t c = android_atomic_dec(&ref->count);
128 // ref->count cannot be 1 prior atomic_dec because we have
129 // a reference, and if we have one, it means there was
130 // already one before us.
131 LOGE_IF(c==1, "refcount is now 0 in release()");
132 }
133 }
134 void terminate() {
135 if (ref) {
136 ref->terminated = 1;
137 release();
138 }
139 }
140 };
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800141};
142
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700143SortedVector<egl_object_t*> egl_object_t::sObjects;
144Mutex egl_object_t::sLock;
145
146struct egl_display_t
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800147{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700148 uint32_t magic;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700149 EGLDisplay dpys[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
150 EGLConfig* configs[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
151 EGLint numConfigs[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800152 EGLint numTotalConfigs;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800153 volatile int32_t refs;
154 struct strings_t {
155 char const * vendor;
156 char const * version;
157 char const * clientApi;
158 char const * extensions;
159 };
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700160 strings_t queryString[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700161 egl_display_t() : magic('_dpy') { }
162 ~egl_display_t() { magic = 0; }
163 inline bool isValid() const { return magic == '_dpy'; }
164 inline bool isAlive() const { return isValid(); }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800165};
166
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700167struct egl_surface_t : public egl_object_t
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800168{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700169 typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
170
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800171 egl_surface_t(EGLDisplay dpy, EGLSurface surface,
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700172 int impl, egl_connection_t const* cnx)
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700173 : dpy(dpy), surface(surface), impl(impl), cnx(cnx) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800174 }
175 ~egl_surface_t() {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800176 }
177 EGLDisplay dpy;
178 EGLSurface surface;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800179 int impl;
180 egl_connection_t const* cnx;
181};
182
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700183struct egl_context_t : public egl_object_t
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800184{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700185 typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
186
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800187 egl_context_t(EGLDisplay dpy, EGLContext context,
188 int impl, egl_connection_t const* cnx)
189 : dpy(dpy), context(context), read(0), draw(0), impl(impl), cnx(cnx)
190 {
191 }
192 EGLDisplay dpy;
193 EGLContext context;
194 EGLSurface read;
195 EGLSurface draw;
196 int impl;
197 egl_connection_t const* cnx;
198};
199
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700200struct egl_image_t : public egl_object_t
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700201{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700202 typedef egl_object_t::LocalRef<egl_image_t, EGLImageKHR> Ref;
203
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700204 egl_image_t(EGLDisplay dpy, EGLContext context)
205 : dpy(dpy), context(context)
206 {
207 memset(images, 0, sizeof(images));
208 }
209 EGLDisplay dpy;
210 EGLConfig context;
211 EGLImageKHR images[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
212};
213
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700214typedef egl_surface_t::Ref SurfaceRef;
215typedef egl_context_t::Ref ContextRef;
216typedef egl_image_t::Ref ImageRef;
217
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800218struct tls_t
219{
Mathias Agopiand274eae2009-07-31 16:21:17 -0700220 tls_t() : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(EGL_TRUE) { }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800221 EGLint error;
222 EGLContext ctx;
Mathias Agopiand274eae2009-07-31 16:21:17 -0700223 EGLBoolean logCallWithNoContext;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800224};
225
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800226
227// ----------------------------------------------------------------------------
228
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700229egl_connection_t gEGLImpl[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800230static egl_display_t gDisplay[NUM_DISPLAYS];
231static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER;
232static pthread_key_t gEGLThreadLocalStorageKey = -1;
233
234// ----------------------------------------------------------------------------
235
Mathias Agopianeccc8cf2009-05-13 00:19:22 -0700236EGLAPI gl_hooks_t gHooks[IMPL_NUM_IMPLEMENTATIONS];
237EGLAPI pthread_key_t gGLWrapperKey = -1;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800238
239// ----------------------------------------------------------------------------
240
241static __attribute__((noinline))
242const char *egl_strerror(EGLint err)
243{
244 switch (err){
245 case EGL_SUCCESS: return "EGL_SUCCESS";
246 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
247 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
248 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
249 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
250 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
251 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
252 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
253 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
254 case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
255 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
256 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
257 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
258 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
259 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
260 default: return "UNKNOWN";
261 }
262}
263
264static __attribute__((noinline))
265void clearTLS() {
266 if (gEGLThreadLocalStorageKey != -1) {
267 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
268 if (tls) {
269 delete tls;
270 pthread_setspecific(gEGLThreadLocalStorageKey, 0);
271 }
272 }
273}
274
275static tls_t* getTLS()
276{
277 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
278 if (tls == 0) {
279 tls = new tls_t;
280 pthread_setspecific(gEGLThreadLocalStorageKey, tls);
281 }
282 return tls;
283}
284
285template<typename T>
286static __attribute__((noinline))
287T setErrorEtc(const char* caller, int line, EGLint error, T returnValue) {
288 if (gEGLThreadLocalStorageKey == -1) {
289 pthread_mutex_lock(&gThreadLocalStorageKeyMutex);
290 if (gEGLThreadLocalStorageKey == -1)
291 pthread_key_create(&gEGLThreadLocalStorageKey, NULL);
292 pthread_mutex_unlock(&gThreadLocalStorageKeyMutex);
293 }
294 tls_t* tls = getTLS();
295 if (tls->error != error) {
296 LOGE("%s:%d error %x (%s)", caller, line, error, egl_strerror(error));
297 tls->error = error;
298 }
299 return returnValue;
300}
301
302static __attribute__((noinline))
303GLint getError() {
304 if (gEGLThreadLocalStorageKey == -1)
305 return EGL_SUCCESS;
306 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
307 if (!tls) return EGL_SUCCESS;
308 GLint error = tls->error;
309 tls->error = EGL_SUCCESS;
310 return error;
311}
312
313static __attribute__((noinline))
314void setContext(EGLContext ctx) {
315 if (gEGLThreadLocalStorageKey == -1) {
316 pthread_mutex_lock(&gThreadLocalStorageKeyMutex);
317 if (gEGLThreadLocalStorageKey == -1)
318 pthread_key_create(&gEGLThreadLocalStorageKey, NULL);
319 pthread_mutex_unlock(&gThreadLocalStorageKeyMutex);
320 }
321 tls_t* tls = getTLS();
322 tls->ctx = ctx;
323}
324
325static __attribute__((noinline))
326EGLContext getContext() {
327 if (gEGLThreadLocalStorageKey == -1)
328 return EGL_NO_CONTEXT;
329 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
330 if (!tls) return EGL_NO_CONTEXT;
331 return tls->ctx;
332}
333
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800334/*****************************************************************************/
335
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800336template<typename T>
337static __attribute__((noinline))
338int binarySearch(
339 T const sortedArray[], int first, int last, T key)
340{
341 while (first <= last) {
342 int mid = (first + last) / 2;
343 if (key > sortedArray[mid]) {
344 first = mid + 1;
345 } else if (key < sortedArray[mid]) {
346 last = mid - 1;
347 } else {
348 return mid;
349 }
350 }
351 return -1;
352}
353
354static EGLint configToUniqueId(egl_display_t const* dp, int i, int index)
355{
356 // NOTE: this mapping works only if we have no more than two EGLimpl
357 return (i>0 ? dp->numConfigs[0] : 0) + index;
358}
359
360static void uniqueIdToConfig(egl_display_t const* dp, EGLint configId,
361 int& i, int& index)
362{
363 // NOTE: this mapping works only if we have no more than two EGLimpl
364 size_t numConfigs = dp->numConfigs[0];
365 i = configId / numConfigs;
366 index = configId % numConfigs;
367}
368
369static int cmp_configs(const void* a, const void *b)
370{
371 EGLConfig c0 = *(EGLConfig const *)a;
372 EGLConfig c1 = *(EGLConfig const *)b;
373 return c0<c1 ? -1 : (c0>c1 ? 1 : 0);
374}
375
376struct extention_map_t {
377 const char* name;
378 __eglMustCastToProperFunctionPointerType address;
379};
380
381static const extention_map_t gExtentionMap[] = {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700382 { "eglLockSurfaceKHR",
383 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
384 { "eglUnlockSurfaceKHR",
385 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
386 { "eglCreateImageKHR",
387 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
388 { "eglDestroyImageKHR",
389 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Mathias Agopian8d2e83b2009-06-24 22:37:39 -0700390 { "eglSetSwapRectangleANDROID",
391 (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
392 { "eglGetRenderBufferANDROID",
393 (__eglMustCastToProperFunctionPointerType)&eglGetRenderBufferANDROID },
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800394};
395
396static extention_map_t gGLExtentionMap[MAX_NUMBER_OF_GL_EXTENSIONS];
397
398static void(*findProcAddress(const char* name,
399 const extention_map_t* map, size_t n))()
400{
401 for (uint32_t i=0 ; i<n ; i++) {
402 if (!strcmp(name, map[i].name)) {
403 return map[i].address;
404 }
405 }
406 return NULL;
407}
408
409// ----------------------------------------------------------------------------
410
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800411static void gl_no_context() {
Mathias Agopiand274eae2009-07-31 16:21:17 -0700412 tls_t* tls = getTLS();
413 if (tls->logCallWithNoContext == EGL_TRUE) {
414 tls->logCallWithNoContext = EGL_FALSE;
415 LOGE("call to OpenGL ES API with no current context "
416 "(logged once per thread)");
417 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800418}
Mathias Agopiand274eae2009-07-31 16:21:17 -0700419
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800420static void early_egl_init(void)
421{
422#if !USE_FAST_TLS_KEY
423 pthread_key_create(&gGLWrapperKey, NULL);
424#endif
425 uint32_t addr = (uint32_t)((void*)gl_no_context);
426 android_memset32(
427 (uint32_t*)(void*)&gHooks[IMPL_NO_CONTEXT],
428 addr,
429 sizeof(gHooks[IMPL_NO_CONTEXT]));
430 setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]);
431}
432
433static pthread_once_t once_control = PTHREAD_ONCE_INIT;
434static int sEarlyInitState = pthread_once(&once_control, &early_egl_init);
435
436
437static inline
438egl_display_t* get_display(EGLDisplay dpy)
439{
440 uintptr_t index = uintptr_t(dpy)-1U;
441 return (index >= NUM_DISPLAYS) ? NULL : &gDisplay[index];
442}
443
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700444template<typename NATIVE, typename EGL>
445static inline NATIVE* egl_to_native_cast(EGL arg) {
446 return reinterpret_cast<NATIVE*>(arg);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800447}
448
449static inline
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700450egl_surface_t* get_surface(EGLSurface surface) {
451 return egl_to_native_cast<egl_surface_t>(surface);
452}
453
454static inline
455egl_context_t* get_context(EGLContext context) {
456 return egl_to_native_cast<egl_context_t>(context);
457}
458
459static inline
460egl_image_t* get_image(EGLImageKHR image) {
461 return egl_to_native_cast<egl_image_t>(image);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800462}
463
464static egl_connection_t* validate_display_config(
465 EGLDisplay dpy, EGLConfig config,
466 egl_display_t const*& dp, int& impl, int& index)
467{
468 dp = get_display(dpy);
469 if (!dp) return setError(EGL_BAD_DISPLAY, (egl_connection_t*)NULL);
470
471 impl = uintptr_t(config)>>24;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700472 if (uint32_t(impl) >= IMPL_NUM_DRIVERS_IMPLEMENTATIONS) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800473 return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
474 }
475 index = uintptr_t(config) & 0xFFFFFF;
476 if (index >= dp->numConfigs[impl]) {
477 return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
478 }
479 egl_connection_t* const cnx = &gEGLImpl[impl];
480 if (cnx->dso == 0) {
481 return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
482 }
483 return cnx;
484}
485
486static EGLBoolean validate_display_context(EGLDisplay dpy, EGLContext ctx)
487{
488 if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS)
489 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700490 if (!get_display(dpy)->isAlive())
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800491 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700492 if (!get_context(ctx)->isAlive())
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800493 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
494 return EGL_TRUE;
495}
496
497static EGLBoolean validate_display_surface(EGLDisplay dpy, EGLSurface surface)
498{
499 if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS)
500 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700501 if (!get_display(dpy)->isAlive())
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800502 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700503 if (!get_surface(surface)->isAlive())
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800504 return setError(EGL_BAD_SURFACE, EGL_FALSE);
505 return EGL_TRUE;
506}
507
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700508EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image)
509{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700510 ImageRef _i(image);
511 if (!_i.get()) return EGL_NO_IMAGE_KHR;
512
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700513 EGLContext context = getContext();
514 if (context == EGL_NO_CONTEXT || image == EGL_NO_IMAGE_KHR)
515 return EGL_NO_IMAGE_KHR;
516
517 egl_context_t const * const c = get_context(context);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700518 if (!c->isAlive())
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700519 return EGL_NO_IMAGE_KHR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800520
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700521 egl_image_t const * const i = get_image(image);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700522 return i->images[c->impl];
523}
524
Mathias Agopian923c6612009-08-17 18:07:06 -0700525// ----------------------------------------------------------------------------
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700526
Mathias Agopian923c6612009-08-17 18:07:06 -0700527// this mutex protects:
528// d->dpys[]
529// egl_init_drivers_locked()
530//
531static pthread_mutex_t gInitDriverMutex = PTHREAD_MUTEX_INITIALIZER;
532
533EGLBoolean egl_init_drivers_locked()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800534{
535 if (sEarlyInitState) {
Mathias Agopian923c6612009-08-17 18:07:06 -0700536 // initialized by static ctor. should be set here.
537 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800538 }
539
Mathias Agopiande586972009-05-28 17:39:03 -0700540 // get our driver loader
Mathias Agopian923c6612009-08-17 18:07:06 -0700541 Loader& loader(Loader::getInstance());
Mathias Agopiande586972009-05-28 17:39:03 -0700542
Mathias Agopian923c6612009-08-17 18:07:06 -0700543 // dynamically load all our EGL implementations for all displays
544 // and retrieve the corresponding EGLDisplay
545 // if that fails, don't use this driver.
546 // TODO: currently we only deal with EGL_DEFAULT_DISPLAY
547 egl_connection_t* cnx;
548 egl_display_t* d = &gDisplay[0];
549
550 cnx = &gEGLImpl[IMPL_SOFTWARE];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800551 if (cnx->dso == 0) {
552 cnx->hooks = &gHooks[IMPL_SOFTWARE];
Mathias Agopian923c6612009-08-17 18:07:06 -0700553 cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 0, cnx->hooks);
554 if (cnx->dso) {
555 EGLDisplay dpy = cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
556 LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for software EGL!");
557 d->dpys[IMPL_SOFTWARE] = dpy;
558 if (dpy == EGL_NO_DISPLAY) {
559 loader.close(cnx->dso);
560 cnx->dso = NULL;
561 }
562 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800563 }
564
565 cnx = &gEGLImpl[IMPL_HARDWARE];
Mathias Agopian923c6612009-08-17 18:07:06 -0700566 if (cnx->dso == 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800567 char value[PROPERTY_VALUE_MAX];
568 property_get("debug.egl.hw", value, "1");
569 if (atoi(value) != 0) {
570 cnx->hooks = &gHooks[IMPL_HARDWARE];
Mathias Agopian923c6612009-08-17 18:07:06 -0700571 cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 1, cnx->hooks);
572 if (cnx->dso) {
573 EGLDisplay dpy = cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
574 LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for hardware EGL!");
575 d->dpys[IMPL_HARDWARE] = dpy;
576 if (dpy == EGL_NO_DISPLAY) {
577 loader.close(cnx->dso);
578 cnx->dso = NULL;
579 }
580 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800581 } else {
582 LOGD("3D hardware acceleration is disabled");
583 }
584 }
Mathias Agopian923c6612009-08-17 18:07:06 -0700585
586 if (!gEGLImpl[IMPL_SOFTWARE].dso && !gEGLImpl[IMPL_HARDWARE].dso) {
587 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800588 }
589
Mathias Agopian923c6612009-08-17 18:07:06 -0700590 return EGL_TRUE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800591}
592
Mathias Agopian923c6612009-08-17 18:07:06 -0700593EGLBoolean egl_init_drivers()
594{
595 EGLBoolean res;
596 pthread_mutex_lock(&gInitDriverMutex);
597 res = egl_init_drivers_locked();
598 pthread_mutex_unlock(&gInitDriverMutex);
599 return res;
600}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700601
602// ----------------------------------------------------------------------------
603}; // namespace android
604// ----------------------------------------------------------------------------
605
606using namespace android;
607
608EGLDisplay eglGetDisplay(NativeDisplayType display)
609{
Mathias Agopian923c6612009-08-17 18:07:06 -0700610 uint32_t index = uint32_t(display);
611 if (index >= NUM_DISPLAYS) {
612 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
613 }
614
615 if (egl_init_drivers() == EGL_FALSE) {
616 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
617 }
618
619 EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU);
620 return dpy;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700621}
622
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800623// ----------------------------------------------------------------------------
624// Initialization
625// ----------------------------------------------------------------------------
626
627EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
628{
629 egl_display_t * const dp = get_display(dpy);
630 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
631
632 if (android_atomic_inc(&dp->refs) > 0) {
633 if (major != NULL) *major = VERSION_MAJOR;
634 if (minor != NULL) *minor = VERSION_MINOR;
635 return EGL_TRUE;
636 }
637
638 setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]);
639
640 // initialize each EGL and
641 // build our own extension string first, based on the extension we know
642 // and the extension supported by our client implementation
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700643 for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800644 egl_connection_t* const cnx = &gEGLImpl[i];
645 cnx->major = -1;
646 cnx->minor = -1;
647 if (!cnx->dso)
648 continue;
649
650 if (cnx->hooks->egl.eglInitialize(
651 dp->dpys[i], &cnx->major, &cnx->minor)) {
652
653 //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p",
654 // i, dp->dpys[i], cnx->major, cnx->minor, cnx);
655
656 // get the query-strings for this display for each implementation
657 dp->queryString[i].vendor =
658 cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_VENDOR);
659 dp->queryString[i].version =
660 cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_VERSION);
661 dp->queryString[i].extensions = strdup(
662 cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_EXTENSIONS));
663 dp->queryString[i].clientApi =
664 cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_CLIENT_APIS);
665
666 } else {
667 LOGD("%d: eglInitialize() failed (%s)",
668 i, egl_strerror(cnx->hooks->egl.eglGetError()));
669 }
670 }
671
672 EGLBoolean res = EGL_FALSE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700673 for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800674 egl_connection_t* const cnx = &gEGLImpl[i];
675 if (cnx->dso && cnx->major>=0 && cnx->minor>=0) {
676 EGLint n;
677 if (cnx->hooks->egl.eglGetConfigs(dp->dpys[i], 0, 0, &n)) {
678 dp->configs[i] = (EGLConfig*)malloc(sizeof(EGLConfig)*n);
679 if (dp->configs[i]) {
680 if (cnx->hooks->egl.eglGetConfigs(
681 dp->dpys[i], dp->configs[i], n, &dp->numConfigs[i]))
682 {
683 // sort the configurations so we can do binary searches
684 qsort( dp->configs[i],
685 dp->numConfigs[i],
686 sizeof(EGLConfig), cmp_configs);
687
688 dp->numTotalConfigs += n;
689 res = EGL_TRUE;
690 }
691 }
692 }
693 }
694 }
695
696 if (res == EGL_TRUE) {
697 if (major != NULL) *major = VERSION_MAJOR;
698 if (minor != NULL) *minor = VERSION_MINOR;
699 return EGL_TRUE;
700 }
701 return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
702}
703
704EGLBoolean eglTerminate(EGLDisplay dpy)
705{
Mathias Agopian923c6612009-08-17 18:07:06 -0700706 // NOTE: don't unload the drivers b/c some APIs can be called
707 // after eglTerminate() has been called. eglTerminate() only
708 // terminates an EGLDisplay, not a EGL itself.
709
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800710 egl_display_t* const dp = get_display(dpy);
711 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
712 if (android_atomic_dec(&dp->refs) != 1)
713 return EGL_TRUE;
Mathias Agopiande586972009-05-28 17:39:03 -0700714
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800715 EGLBoolean res = EGL_FALSE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700716 for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800717 egl_connection_t* const cnx = &gEGLImpl[i];
718 if (cnx->dso) {
719 cnx->hooks->egl.eglTerminate(dp->dpys[i]);
Mathias Agopian923c6612009-08-17 18:07:06 -0700720 // REVISIT: it's unclear what to do if eglTerminate() fails
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800721 free(dp->configs[i]);
722 free((void*)dp->queryString[i].extensions);
723 dp->numConfigs[i] = 0;
724 dp->dpys[i] = EGL_NO_DISPLAY;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800725 res = EGL_TRUE;
726 }
727 }
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700728
729 // TODO: all egl_object_t should be marked for termination
730
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800731 dp->numTotalConfigs = 0;
732 clearTLS();
733 return res;
734}
735
736// ----------------------------------------------------------------------------
737// configuration
738// ----------------------------------------------------------------------------
739
740EGLBoolean eglGetConfigs( EGLDisplay dpy,
741 EGLConfig *configs,
742 EGLint config_size, EGLint *num_config)
743{
744 egl_display_t const * const dp = get_display(dpy);
745 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
746
747 GLint numConfigs = dp->numTotalConfigs;
748 if (!configs) {
749 *num_config = numConfigs;
750 return EGL_TRUE;
751 }
752 GLint n = 0;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700753 for (int j=0 ; j<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; j++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800754 for (int i=0 ; i<dp->numConfigs[j] && config_size ; i++) {
755 *configs++ = MAKE_CONFIG(j, i);
756 config_size--;
757 n++;
758 }
759 }
760
761 *num_config = n;
762 return EGL_TRUE;
763}
764
765EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
766 EGLConfig *configs, EGLint config_size,
767 EGLint *num_config)
768{
769 egl_display_t const * const dp = get_display(dpy);
770 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
771
Jack Palevich749c63d2009-03-25 15:12:17 -0700772 if (num_config==0) {
773 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800774 }
775
776 EGLint n;
777 EGLBoolean res = EGL_FALSE;
778 *num_config = 0;
779
780
781 // It is unfortunate, but we need to remap the EGL_CONFIG_IDs,
782 // to do this, we have to go through the attrib_list array once
783 // to figure out both its size and if it contains an EGL_CONFIG_ID
784 // key. If so, the full array is copied and patched.
785 // NOTE: we assume that there can be only one occurrence
786 // of EGL_CONFIG_ID.
787
788 EGLint patch_index = -1;
789 GLint attr;
790 size_t size = 0;
Mathias Agopiandacd7a32009-07-09 17:33:15 -0700791 while ((attr=attrib_list[size]) != EGL_NONE) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800792 if (attr == EGL_CONFIG_ID)
793 patch_index = size;
794 size += 2;
795 }
796 if (patch_index >= 0) {
797 size += 2; // we need copy the sentinel as well
798 EGLint* new_list = (EGLint*)malloc(size*sizeof(EGLint));
799 if (new_list == 0)
800 return setError(EGL_BAD_ALLOC, EGL_FALSE);
801 memcpy(new_list, attrib_list, size*sizeof(EGLint));
802
803 // patch the requested EGL_CONFIG_ID
804 int i, index;
805 EGLint& configId(new_list[patch_index+1]);
806 uniqueIdToConfig(dp, configId, i, index);
807
808 egl_connection_t* const cnx = &gEGLImpl[i];
809 if (cnx->dso) {
810 cnx->hooks->egl.eglGetConfigAttrib(
811 dp->dpys[i], dp->configs[i][index],
812 EGL_CONFIG_ID, &configId);
813
814 // and switch to the new list
815 attrib_list = const_cast<const EGLint *>(new_list);
816
817 // At this point, the only configuration that can match is
818 // dp->configs[i][index], however, we don't know if it would be
819 // rejected because of the other attributes, so we do have to call
820 // cnx->hooks->egl.eglChooseConfig() -- but we don't have to loop
821 // through all the EGLimpl[].
822 // We also know we can only get a single config back, and we know
823 // which one.
824
825 res = cnx->hooks->egl.eglChooseConfig(
826 dp->dpys[i], attrib_list, configs, config_size, &n);
827 if (res && n>0) {
828 // n has to be 0 or 1, by construction, and we already know
829 // which config it will return (since there can be only one).
Jack Palevich749c63d2009-03-25 15:12:17 -0700830 if (configs) {
831 configs[0] = MAKE_CONFIG(i, index);
832 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800833 *num_config = 1;
834 }
835 }
836
837 free(const_cast<EGLint *>(attrib_list));
838 return res;
839 }
840
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700841 for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800842 egl_connection_t* const cnx = &gEGLImpl[i];
843 if (cnx->dso) {
844 if (cnx->hooks->egl.eglChooseConfig(
845 dp->dpys[i], attrib_list, configs, config_size, &n)) {
Jack Palevich749c63d2009-03-25 15:12:17 -0700846 if (configs) {
847 // now we need to convert these client EGLConfig to our
848 // internal EGLConfig format. This is done in O(n log n).
849 for (int j=0 ; j<n ; j++) {
850 int index = binarySearch<EGLConfig>(
851 dp->configs[i], 0, dp->numConfigs[i]-1, configs[j]);
852 if (index >= 0) {
853 if (configs) {
854 configs[j] = MAKE_CONFIG(i, index);
855 }
856 } else {
857 return setError(EGL_BAD_CONFIG, EGL_FALSE);
858 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800859 }
Jack Palevich749c63d2009-03-25 15:12:17 -0700860 configs += n;
861 config_size -= n;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800862 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800863 *num_config += n;
864 res = EGL_TRUE;
865 }
866 }
867 }
868 return res;
869}
870
871EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
872 EGLint attribute, EGLint *value)
873{
874 egl_display_t const* dp = 0;
875 int i=0, index=0;
876 egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
877 if (!cnx) return EGL_FALSE;
878
879 if (attribute == EGL_CONFIG_ID) {
880 // EGL_CONFIG_IDs must be unique, just use the order of the selected
881 // EGLConfig.
882 *value = configToUniqueId(dp, i, index);
883 return EGL_TRUE;
884 }
885 return cnx->hooks->egl.eglGetConfigAttrib(
886 dp->dpys[i], dp->configs[i][index], attribute, value);
887}
888
889// ----------------------------------------------------------------------------
890// surfaces
891// ----------------------------------------------------------------------------
892
893EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
894 NativeWindowType window,
895 const EGLint *attrib_list)
896{
897 egl_display_t const* dp = 0;
898 int i=0, index=0;
899 egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
900 if (cnx) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800901 EGLSurface surface = cnx->hooks->egl.eglCreateWindowSurface(
902 dp->dpys[i], dp->configs[i][index], window, attrib_list);
903 if (surface != EGL_NO_SURFACE) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700904 egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800905 return s;
906 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800907 }
908 return EGL_NO_SURFACE;
909}
910
911EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
912 NativePixmapType pixmap,
913 const EGLint *attrib_list)
914{
915 egl_display_t const* dp = 0;
916 int i=0, index=0;
917 egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
918 if (cnx) {
919 EGLSurface surface = cnx->hooks->egl.eglCreatePixmapSurface(
920 dp->dpys[i], dp->configs[i][index], pixmap, attrib_list);
921 if (surface != EGL_NO_SURFACE) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700922 egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800923 return s;
924 }
925 }
926 return EGL_NO_SURFACE;
927}
928
929EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
930 const EGLint *attrib_list)
931{
932 egl_display_t const* dp = 0;
933 int i=0, index=0;
934 egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
935 if (cnx) {
936 EGLSurface surface = cnx->hooks->egl.eglCreatePbufferSurface(
937 dp->dpys[i], dp->configs[i][index], attrib_list);
938 if (surface != EGL_NO_SURFACE) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700939 egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800940 return s;
941 }
942 }
943 return EGL_NO_SURFACE;
944}
945
946EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
947{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700948 SurfaceRef _s(surface);
949 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
950
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800951 if (!validate_display_surface(dpy, surface))
952 return EGL_FALSE;
953 egl_display_t const * const dp = get_display(dpy);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800954
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700955 egl_surface_t * const s = get_surface(surface);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800956 EGLBoolean result = s->cnx->hooks->egl.eglDestroySurface(
957 dp->dpys[s->impl], s->surface);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700958 if (result == EGL_TRUE) {
959 _s.terminate();
960 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800961 return result;
962}
963
964EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
965 EGLint attribute, EGLint *value)
966{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700967 SurfaceRef _s(surface);
968 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
969
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800970 if (!validate_display_surface(dpy, surface))
971 return EGL_FALSE;
972 egl_display_t const * const dp = get_display(dpy);
973 egl_surface_t const * const s = get_surface(surface);
974
975 return s->cnx->hooks->egl.eglQuerySurface(
976 dp->dpys[s->impl], s->surface, attribute, value);
977}
978
979// ----------------------------------------------------------------------------
980// contextes
981// ----------------------------------------------------------------------------
982
983EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
984 EGLContext share_list, const EGLint *attrib_list)
985{
986 egl_display_t const* dp = 0;
987 int i=0, index=0;
988 egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
989 if (cnx) {
990 EGLContext context = cnx->hooks->egl.eglCreateContext(
991 dp->dpys[i], dp->configs[i][index], share_list, attrib_list);
992 if (context != EGL_NO_CONTEXT) {
993 egl_context_t* c = new egl_context_t(dpy, context, i, cnx);
994 return c;
995 }
996 }
997 return EGL_NO_CONTEXT;
998}
999
1000EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1001{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001002 ContextRef _c(ctx);
1003 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1004
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001005 if (!validate_display_context(dpy, ctx))
1006 return EGL_FALSE;
1007 egl_display_t const * const dp = get_display(dpy);
1008 egl_context_t * const c = get_context(ctx);
1009 EGLBoolean result = c->cnx->hooks->egl.eglDestroyContext(
1010 dp->dpys[c->impl], c->context);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001011 if (result == EGL_TRUE) {
1012 _c.terminate();
1013 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001014 return result;
1015}
1016
1017EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
1018 EGLSurface read, EGLContext ctx)
1019{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001020 // get a reference to the object passed in
1021 ContextRef _c(ctx);
1022 SurfaceRef _d(draw);
1023 SurfaceRef _r(read);
1024
1025 // validate the display and the context (if not EGL_NO_CONTEXT)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001026 egl_display_t const * const dp = get_display(dpy);
1027 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001028 if ((ctx != EGL_NO_CONTEXT) && (!validate_display_context(dpy, ctx))) {
1029 // EGL_NO_CONTEXT is valid
1030 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001031 }
1032
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001033 // these are the underlying implementation's object
1034 EGLContext impl_ctx = EGL_NO_CONTEXT;
Mathias Agopianaf742132009-06-25 00:01:11 -07001035 EGLSurface impl_draw = EGL_NO_SURFACE;
1036 EGLSurface impl_read = EGL_NO_SURFACE;
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001037
1038 // these are our objects structs passed in
1039 egl_context_t * c = NULL;
1040 egl_surface_t const * d = NULL;
1041 egl_surface_t const * r = NULL;
1042
1043 // these are the current objects structs
1044 egl_context_t * cur_c = get_context(getContext());
1045 egl_surface_t * cur_r = NULL;
1046 egl_surface_t * cur_d = NULL;
1047
1048 if (ctx != EGL_NO_CONTEXT) {
1049 c = get_context(ctx);
1050 cur_r = get_surface(c->read);
1051 cur_d = get_surface(c->draw);
1052 impl_ctx = c->context;
1053 } else {
1054 // no context given, use the implementation of the current context
1055 if (cur_c == NULL) {
1056 // no current context
1057 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
1058 // calling eglMakeCurrent( ..., EGL_NO_CONTEXT, !=0, !=0);
1059 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1060 }
1061 // not an error, there is just not current context.
1062 return EGL_TRUE;
1063 }
1064 }
1065
1066 // retrieve the underlying implementation's draw EGLSurface
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001067 if (draw != EGL_NO_SURFACE) {
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001068 d = get_surface(draw);
1069 // make sure the EGLContext and EGLSurface passed in are for the same driver
1070 if (c && d->impl != c->impl)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001071 return setError(EGL_BAD_MATCH, EGL_FALSE);
Mathias Agopianaf742132009-06-25 00:01:11 -07001072 impl_draw = d->surface;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001073 }
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001074
1075 // retrieve the underlying implementation's read EGLSurface
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001076 if (read != EGL_NO_SURFACE) {
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001077 r = get_surface(read);
1078 // make sure the EGLContext and EGLSurface passed in are for the same driver
1079 if (c && r->impl != c->impl)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001080 return setError(EGL_BAD_MATCH, EGL_FALSE);
Mathias Agopianaf742132009-06-25 00:01:11 -07001081 impl_read = r->surface;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001082 }
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001083
1084 EGLBoolean result;
1085
1086 if (c) {
1087 result = c->cnx->hooks->egl.eglMakeCurrent(
1088 dp->dpys[c->impl], impl_draw, impl_read, impl_ctx);
1089 } else {
1090 result = cur_c->cnx->hooks->egl.eglMakeCurrent(
1091 dp->dpys[cur_c->impl], impl_draw, impl_read, impl_ctx);
1092 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001093
1094 if (result == EGL_TRUE) {
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001095 // by construction, these are either 0 or valid (possibly terminated)
1096 // it should be impossible for these to be invalid
1097 ContextRef _cur_c(cur_c);
1098 SurfaceRef _cur_r(cur_r);
1099 SurfaceRef _cur_d(cur_d);
1100
1101 // cur_c has to be valid here (but could be terminated)
1102 if (ctx != EGL_NO_CONTEXT) {
1103 setGlThreadSpecific(c->cnx->hooks);
1104 setContext(ctx);
1105 _c.acquire();
1106 } else {
1107 setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]);
1108 setContext(EGL_NO_CONTEXT);
1109 }
1110 _cur_c.release();
1111
1112 _r.acquire();
1113 _cur_r.release();
1114 if (c) c->read = read;
1115
1116 _d.acquire();
1117 _cur_d.release();
1118 if (c) c->draw = draw;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001119 }
1120 return result;
1121}
1122
1123
1124EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
1125 EGLint attribute, EGLint *value)
1126{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001127 ContextRef _c(ctx);
1128 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1129
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001130 if (!validate_display_context(dpy, ctx))
1131 return EGL_FALSE;
1132
1133 egl_display_t const * const dp = get_display(dpy);
1134 egl_context_t * const c = get_context(ctx);
1135
1136 return c->cnx->hooks->egl.eglQueryContext(
1137 dp->dpys[c->impl], c->context, attribute, value);
1138}
1139
1140EGLContext eglGetCurrentContext(void)
1141{
Mathias Agopian923c6612009-08-17 18:07:06 -07001142 // could be called before eglInitialize(), but we wouldn't have a context
1143 // then, and this function would correctly return EGL_NO_CONTEXT.
1144
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001145 EGLContext ctx = getContext();
1146 return ctx;
1147}
1148
1149EGLSurface eglGetCurrentSurface(EGLint readdraw)
1150{
Mathias Agopian923c6612009-08-17 18:07:06 -07001151 // could be called before eglInitialize(), but we wouldn't have a context
1152 // then, and this function would correctly return EGL_NO_SURFACE.
1153
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001154 EGLContext ctx = getContext();
1155 if (ctx) {
1156 egl_context_t const * const c = get_context(ctx);
1157 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1158 switch (readdraw) {
1159 case EGL_READ: return c->read;
1160 case EGL_DRAW: return c->draw;
1161 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1162 }
1163 }
1164 return EGL_NO_SURFACE;
1165}
1166
1167EGLDisplay eglGetCurrentDisplay(void)
1168{
Mathias Agopian923c6612009-08-17 18:07:06 -07001169 // could be called before eglInitialize(), but we wouldn't have a context
1170 // then, and this function would correctly return EGL_NO_DISPLAY.
1171
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001172 EGLContext ctx = getContext();
1173 if (ctx) {
1174 egl_context_t const * const c = get_context(ctx);
1175 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1176 return c->dpy;
1177 }
1178 return EGL_NO_DISPLAY;
1179}
1180
1181EGLBoolean eglWaitGL(void)
1182{
Mathias Agopian923c6612009-08-17 18:07:06 -07001183 // could be called before eglInitialize(), but we wouldn't have a context
1184 // then, and this function would return GL_TRUE, which isn't wrong.
1185
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001186 EGLBoolean res = EGL_TRUE;
1187 EGLContext ctx = getContext();
1188 if (ctx) {
1189 egl_context_t const * const c = get_context(ctx);
1190 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1191 if (uint32_t(c->impl)>=2)
1192 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1193 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1194 if (!cnx->dso)
1195 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1196 res = cnx->hooks->egl.eglWaitGL();
1197 }
1198 return res;
1199}
1200
1201EGLBoolean eglWaitNative(EGLint engine)
1202{
Mathias Agopian923c6612009-08-17 18:07:06 -07001203 // could be called before eglInitialize(), but we wouldn't have a context
1204 // then, and this function would return GL_TRUE, which isn't wrong.
1205
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001206 EGLBoolean res = EGL_TRUE;
1207 EGLContext ctx = getContext();
1208 if (ctx) {
1209 egl_context_t const * const c = get_context(ctx);
1210 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1211 if (uint32_t(c->impl)>=2)
1212 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1213 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1214 if (!cnx->dso)
1215 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1216 res = cnx->hooks->egl.eglWaitNative(engine);
1217 }
1218 return res;
1219}
1220
1221EGLint eglGetError(void)
1222{
1223 EGLint result = EGL_SUCCESS;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001224 for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001225 EGLint err = EGL_SUCCESS;
1226 egl_connection_t* const cnx = &gEGLImpl[i];
1227 if (cnx->dso)
1228 err = cnx->hooks->egl.eglGetError();
1229 if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
1230 result = err;
1231 }
1232 if (result == EGL_SUCCESS)
1233 result = getError();
1234 return result;
1235}
1236
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001237__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001238{
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001239 // eglGetProcAddress() could be the very first function called
1240 // in which case we must make sure we've initialized ourselves, this
1241 // happens the first time egl_get_display() is called.
Mathias Agopian923c6612009-08-17 18:07:06 -07001242
1243 if (egl_init_drivers() == EGL_FALSE) {
1244 setError(EGL_BAD_PARAMETER, NULL);
1245 return NULL;
1246 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001247
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001248 __eglMustCastToProperFunctionPointerType addr;
1249 addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap));
1250 if (addr) return addr;
1251
1252 return NULL; // TODO: finish implementation below
1253
1254 addr = findProcAddress(procname, gGLExtentionMap, NELEM(gGLExtentionMap));
1255 if (addr) return addr;
1256
1257 addr = 0;
1258 int slot = -1;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001259 for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001260 egl_connection_t* const cnx = &gEGLImpl[i];
1261 if (cnx->dso) {
1262 if (cnx->hooks->egl.eglGetProcAddress) {
1263 addr = cnx->hooks->egl.eglGetProcAddress(procname);
1264 if (addr) {
1265 if (slot == -1) {
1266 slot = 0; // XXX: find free slot
1267 if (slot == -1) {
1268 addr = 0;
1269 break;
1270 }
1271 }
1272 cnx->hooks->ext.extensions[slot] = addr;
1273 }
1274 }
1275 }
1276 }
1277
1278 if (slot >= 0) {
1279 addr = 0; // XXX: address of stub 'slot'
1280 gGLExtentionMap[slot].name = strdup(procname);
1281 gGLExtentionMap[slot].address = addr;
1282 }
1283
1284 return addr;
1285
1286
1287 /*
1288 * TODO: For OpenGL ES extensions, we must generate a stub
1289 * that looks like
1290 * mov r12, #0xFFFF0FFF
1291 * ldr r12, [r12, #-15]
1292 * ldr r12, [r12, #TLS_SLOT_OPENGL_API*4]
1293 * mov r12, [r12, #api_offset]
1294 * ldrne pc, r12
1295 * mov pc, #unsupported_extension
1296 *
1297 * and write the address of the extension in *all*
1298 * gl_hooks_t::gl_ext_t at offset "api_offset" from gl_hooks_t
1299 *
1300 */
1301}
1302
1303EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
1304{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001305 SurfaceRef _s(draw);
1306 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1307
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001308 if (!validate_display_surface(dpy, draw))
1309 return EGL_FALSE;
1310 egl_display_t const * const dp = get_display(dpy);
1311 egl_surface_t const * const s = get_surface(draw);
1312 return s->cnx->hooks->egl.eglSwapBuffers(dp->dpys[s->impl], s->surface);
1313}
1314
1315EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1316 NativePixmapType target)
1317{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001318 SurfaceRef _s(surface);
1319 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1320
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001321 if (!validate_display_surface(dpy, surface))
1322 return EGL_FALSE;
1323 egl_display_t const * const dp = get_display(dpy);
1324 egl_surface_t const * const s = get_surface(surface);
1325 return s->cnx->hooks->egl.eglCopyBuffers(
1326 dp->dpys[s->impl], s->surface, target);
1327}
1328
1329const char* eglQueryString(EGLDisplay dpy, EGLint name)
1330{
1331 egl_display_t const * const dp = get_display(dpy);
1332 switch (name) {
1333 case EGL_VENDOR:
1334 return gVendorString;
1335 case EGL_VERSION:
1336 return gVersionString;
1337 case EGL_EXTENSIONS:
1338 return gExtensionString;
1339 case EGL_CLIENT_APIS:
1340 return gClientApiString;
1341 }
1342 return setError(EGL_BAD_PARAMETER, (const char *)0);
1343}
1344
1345
1346// ----------------------------------------------------------------------------
1347// EGL 1.1
1348// ----------------------------------------------------------------------------
1349
1350EGLBoolean eglSurfaceAttrib(
1351 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1352{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001353 SurfaceRef _s(surface);
1354 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1355
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001356 if (!validate_display_surface(dpy, surface))
1357 return EGL_FALSE;
1358 egl_display_t const * const dp = get_display(dpy);
1359 egl_surface_t const * const s = get_surface(surface);
1360 if (s->cnx->hooks->egl.eglSurfaceAttrib) {
1361 return s->cnx->hooks->egl.eglSurfaceAttrib(
1362 dp->dpys[s->impl], s->surface, attribute, value);
1363 }
1364 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1365}
1366
1367EGLBoolean eglBindTexImage(
1368 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1369{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001370 SurfaceRef _s(surface);
1371 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1372
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001373 if (!validate_display_surface(dpy, surface))
1374 return EGL_FALSE;
1375 egl_display_t const * const dp = get_display(dpy);
1376 egl_surface_t const * const s = get_surface(surface);
1377 if (s->cnx->hooks->egl.eglBindTexImage) {
1378 return s->cnx->hooks->egl.eglBindTexImage(
1379 dp->dpys[s->impl], s->surface, buffer);
1380 }
1381 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1382}
1383
1384EGLBoolean eglReleaseTexImage(
1385 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1386{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001387 SurfaceRef _s(surface);
1388 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1389
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001390 if (!validate_display_surface(dpy, surface))
1391 return EGL_FALSE;
1392 egl_display_t const * const dp = get_display(dpy);
1393 egl_surface_t const * const s = get_surface(surface);
1394 if (s->cnx->hooks->egl.eglReleaseTexImage) {
1395 return s->cnx->hooks->egl.eglReleaseTexImage(
1396 dp->dpys[s->impl], s->surface, buffer);
1397 }
1398 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1399}
1400
1401EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1402{
1403 egl_display_t * const dp = get_display(dpy);
1404 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1405
1406 EGLBoolean res = EGL_TRUE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001407 for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001408 egl_connection_t* const cnx = &gEGLImpl[i];
1409 if (cnx->dso) {
1410 if (cnx->hooks->egl.eglSwapInterval) {
1411 if (cnx->hooks->egl.eglSwapInterval(dp->dpys[i], interval) == EGL_FALSE) {
1412 res = EGL_FALSE;
1413 }
1414 }
1415 }
1416 }
1417 return res;
1418}
1419
1420
1421// ----------------------------------------------------------------------------
1422// EGL 1.2
1423// ----------------------------------------------------------------------------
1424
1425EGLBoolean eglWaitClient(void)
1426{
Mathias Agopian923c6612009-08-17 18:07:06 -07001427 // could be called before eglInitialize(), but we wouldn't have a context
1428 // then, and this function would return GL_TRUE, which isn't wrong.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001429 EGLBoolean res = EGL_TRUE;
1430 EGLContext ctx = getContext();
1431 if (ctx) {
1432 egl_context_t const * const c = get_context(ctx);
1433 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1434 if (uint32_t(c->impl)>=2)
1435 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1436 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1437 if (!cnx->dso)
1438 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1439 if (cnx->hooks->egl.eglWaitClient) {
1440 res = cnx->hooks->egl.eglWaitClient();
1441 } else {
1442 res = cnx->hooks->egl.eglWaitGL();
1443 }
1444 }
1445 return res;
1446}
1447
1448EGLBoolean eglBindAPI(EGLenum api)
1449{
Mathias Agopian923c6612009-08-17 18:07:06 -07001450 if (egl_init_drivers() == EGL_FALSE) {
1451 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1452 }
1453
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001454 // bind this API on all EGLs
1455 EGLBoolean res = EGL_TRUE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001456 for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001457 egl_connection_t* const cnx = &gEGLImpl[i];
1458 if (cnx->dso) {
1459 if (cnx->hooks->egl.eglBindAPI) {
1460 if (cnx->hooks->egl.eglBindAPI(api) == EGL_FALSE) {
1461 res = EGL_FALSE;
1462 }
1463 }
1464 }
1465 }
1466 return res;
1467}
1468
1469EGLenum eglQueryAPI(void)
1470{
Mathias Agopian923c6612009-08-17 18:07:06 -07001471 if (egl_init_drivers() == EGL_FALSE) {
1472 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1473 }
1474
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001475 for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001476 egl_connection_t* const cnx = &gEGLImpl[i];
1477 if (cnx->dso) {
1478 if (cnx->hooks->egl.eglQueryAPI) {
1479 // the first one we find is okay, because they all
1480 // should be the same
1481 return cnx->hooks->egl.eglQueryAPI();
1482 }
1483 }
1484 }
1485 // or, it can only be OpenGL ES
1486 return EGL_OPENGL_ES_API;
1487}
1488
1489EGLBoolean eglReleaseThread(void)
1490{
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001491 for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001492 egl_connection_t* const cnx = &gEGLImpl[i];
1493 if (cnx->dso) {
1494 if (cnx->hooks->egl.eglReleaseThread) {
1495 cnx->hooks->egl.eglReleaseThread();
1496 }
1497 }
1498 }
1499 clearTLS();
1500 return EGL_TRUE;
1501}
1502
1503EGLSurface eglCreatePbufferFromClientBuffer(
1504 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1505 EGLConfig config, const EGLint *attrib_list)
1506{
1507 egl_display_t const* dp = 0;
1508 int i=0, index=0;
1509 egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
1510 if (!cnx) return EGL_FALSE;
1511 if (cnx->hooks->egl.eglCreatePbufferFromClientBuffer) {
1512 return cnx->hooks->egl.eglCreatePbufferFromClientBuffer(
1513 dp->dpys[i], buftype, buffer, dp->configs[i][index], attrib_list);
1514 }
1515 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1516}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001517
1518// ----------------------------------------------------------------------------
1519// EGL_EGLEXT_VERSION 3
1520// ----------------------------------------------------------------------------
1521
1522EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1523 const EGLint *attrib_list)
1524{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001525 SurfaceRef _s(surface);
1526 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1527
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001528 if (!validate_display_surface(dpy, surface))
Mathias Agopian24e5f522009-08-12 21:18:15 -07001529 return EGL_FALSE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001530
1531 egl_display_t const * const dp = get_display(dpy);
1532 egl_surface_t const * const s = get_surface(surface);
1533
1534 if (s->cnx->hooks->egl.eglLockSurfaceKHR) {
Mathias Agopian24e5f522009-08-12 21:18:15 -07001535 return s->cnx->hooks->egl.eglLockSurfaceKHR(
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001536 dp->dpys[s->impl], s->surface, attrib_list);
1537 }
Mathias Agopian24e5f522009-08-12 21:18:15 -07001538 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001539}
1540
1541EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1542{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001543 SurfaceRef _s(surface);
1544 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1545
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001546 if (!validate_display_surface(dpy, surface))
Mathias Agopian24e5f522009-08-12 21:18:15 -07001547 return EGL_FALSE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001548
1549 egl_display_t const * const dp = get_display(dpy);
1550 egl_surface_t const * const s = get_surface(surface);
1551
1552 if (s->cnx->hooks->egl.eglUnlockSurfaceKHR) {
Mathias Agopian24e5f522009-08-12 21:18:15 -07001553 return s->cnx->hooks->egl.eglUnlockSurfaceKHR(
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001554 dp->dpys[s->impl], s->surface);
1555 }
Mathias Agopian24e5f522009-08-12 21:18:15 -07001556 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001557}
1558
1559EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1560 EGLClientBuffer buffer, const EGLint *attrib_list)
1561{
1562 if (ctx != EGL_NO_CONTEXT) {
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001563 ContextRef _c(ctx);
1564 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001565 if (!validate_display_context(dpy, ctx))
1566 return EGL_NO_IMAGE_KHR;
1567 egl_display_t const * const dp = get_display(dpy);
1568 egl_context_t * const c = get_context(ctx);
1569 // since we have an EGLContext, we know which implementation to use
1570 EGLImageKHR image = c->cnx->hooks->egl.eglCreateImageKHR(
1571 dp->dpys[c->impl], c->context, target, buffer, attrib_list);
1572 if (image == EGL_NO_IMAGE_KHR)
1573 return image;
1574
1575 egl_image_t* result = new egl_image_t(dpy, ctx);
1576 result->images[c->impl] = image;
1577 return (EGLImageKHR)result;
1578 } else {
1579 // EGL_NO_CONTEXT is a valid parameter
1580 egl_display_t const * const dp = get_display(dpy);
1581 if (dp == 0) {
1582 return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
1583 }
1584 // since we don't have a way to know which implementation to call,
1585 // we're calling all of them
1586
1587 EGLImageKHR implImages[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
1588 bool success = false;
1589 for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
1590 egl_connection_t* const cnx = &gEGLImpl[i];
1591 implImages[i] = EGL_NO_IMAGE_KHR;
1592 if (cnx->dso) {
1593 if (cnx->hooks->egl.eglCreateImageKHR) {
1594 implImages[i] = cnx->hooks->egl.eglCreateImageKHR(
1595 dp->dpys[i], ctx, target, buffer, attrib_list);
1596 if (implImages[i] != EGL_NO_IMAGE_KHR) {
1597 success = true;
1598 }
1599 }
1600 }
1601 }
1602 if (!success)
1603 return EGL_NO_IMAGE_KHR;
1604
1605 egl_image_t* result = new egl_image_t(dpy, ctx);
1606 memcpy(result->images, implImages, sizeof(implImages));
1607 return (EGLImageKHR)result;
1608 }
1609}
1610
1611EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1612{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001613 egl_display_t const * const dp = get_display(dpy);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001614 if (dp == 0) {
1615 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1616 }
1617
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001618 ImageRef _i(img);
1619 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001620
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001621 egl_image_t* image = get_image(img);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001622 bool success = false;
1623 for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
1624 egl_connection_t* const cnx = &gEGLImpl[i];
1625 if (image->images[i] != EGL_NO_IMAGE_KHR) {
1626 if (cnx->dso) {
1627 if (cnx->hooks->egl.eglCreateImageKHR) {
1628 if (cnx->hooks->egl.eglDestroyImageKHR(
1629 dp->dpys[i], image->images[i])) {
1630 success = true;
1631 }
1632 }
1633 }
1634 }
1635 }
1636 if (!success)
1637 return EGL_FALSE;
1638
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001639 _i.terminate();
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001640
Mathias Agopian24e5f522009-08-12 21:18:15 -07001641 return EGL_TRUE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001642}
Mathias Agopiandf3ca302009-05-04 19:29:25 -07001643
1644
1645// ----------------------------------------------------------------------------
1646// ANDROID extensions
1647// ----------------------------------------------------------------------------
1648
1649EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
1650 EGLint left, EGLint top, EGLint width, EGLint height)
1651{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001652 SurfaceRef _s(draw);
1653 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1654
Mathias Agopiandf3ca302009-05-04 19:29:25 -07001655 if (!validate_display_surface(dpy, draw))
1656 return EGL_FALSE;
1657 egl_display_t const * const dp = get_display(dpy);
1658 egl_surface_t const * const s = get_surface(draw);
1659 if (s->cnx->hooks->egl.eglSetSwapRectangleANDROID) {
1660 return s->cnx->hooks->egl.eglSetSwapRectangleANDROID(dp->dpys[s->impl],
1661 s->surface, left, top, width, height);
1662 }
Mathias Agopian24e5f522009-08-12 21:18:15 -07001663 return setError(EGL_BAD_DISPLAY, NULL);
Mathias Agopiandf3ca302009-05-04 19:29:25 -07001664}
1665
Mathias Agopian8d2e83b2009-06-24 22:37:39 -07001666EGLClientBuffer eglGetRenderBufferANDROID(EGLDisplay dpy, EGLSurface draw)
1667{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001668 SurfaceRef _s(draw);
1669 if (!_s.get()) return setError(EGL_BAD_SURFACE, (EGLClientBuffer*)0);
1670
Mathias Agopian8d2e83b2009-06-24 22:37:39 -07001671 if (!validate_display_surface(dpy, draw))
1672 return 0;
1673 egl_display_t const * const dp = get_display(dpy);
1674 egl_surface_t const * const s = get_surface(draw);
1675 if (s->cnx->hooks->egl.eglGetRenderBufferANDROID) {
1676 return s->cnx->hooks->egl.eglGetRenderBufferANDROID(dp->dpys[s->impl],
1677 s->surface);
1678 }
Mathias Agopian24e5f522009-08-12 21:18:15 -07001679 return setError(EGL_BAD_DISPLAY, (EGLClientBuffer*)0);
Mathias Agopian8d2e83b2009-06-24 22:37:39 -07001680}