blob: 9228b0be2ddd28e44591f91c28ba363c88c00c57 [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 Agopian076b1cc2009-04-10 14:24:30 -070063 "EGL_ANDROID_image_native_buffer "
Mathias Agopiandf3ca302009-05-04 19:29:25 -070064 "EGL_ANDROID_swap_rectangle "
Mathias Agopian076b1cc2009-04-10 14:24:30 -070065 ;
66
67// ----------------------------------------------------------------------------
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080068
Mathias Agopian9429e9c2009-08-21 02:18:25 -070069class egl_object_t {
70 static SortedVector<egl_object_t*> sObjects;
71 static Mutex sLock;
72
73 volatile int32_t terminated;
74 mutable volatile int32_t count;
75
76public:
77 egl_object_t() : terminated(0), count(1) {
78 Mutex::Autolock _l(sLock);
79 sObjects.add(this);
80 }
81
82 inline bool isAlive() const { return !terminated; }
83
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080084private:
Mathias Agopian9429e9c2009-08-21 02:18:25 -070085 bool get() {
86 Mutex::Autolock _l(sLock);
87 if (egl_object_t::sObjects.indexOf(this) >= 0) {
88 android_atomic_inc(&count);
89 return true;
90 }
91 return false;
92 }
93
94 bool put() {
95 Mutex::Autolock _l(sLock);
96 if (android_atomic_dec(&count) == 1) {
97 sObjects.remove(this);
98 return true;
99 }
100 return false;
101 }
102
103public:
104 template <typename N, typename T>
105 struct LocalRef {
106 N* ref;
107 LocalRef(T o) : ref(0) {
108 N* native = reinterpret_cast<N*>(o);
109 if (o && native->get()) {
110 ref = native;
111 }
112 }
113 ~LocalRef() {
114 if (ref && ref->put()) {
115 delete ref;
116 }
117 }
118 inline N* get() {
119 return ref;
120 }
121 void acquire() const {
122 if (ref) {
123 android_atomic_inc(&ref->count);
124 }
125 }
126 void release() const {
127 if (ref) {
128 int32_t c = android_atomic_dec(&ref->count);
129 // ref->count cannot be 1 prior atomic_dec because we have
130 // a reference, and if we have one, it means there was
131 // already one before us.
132 LOGE_IF(c==1, "refcount is now 0 in release()");
133 }
134 }
135 void terminate() {
136 if (ref) {
137 ref->terminated = 1;
138 release();
139 }
140 }
141 };
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800142};
143
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700144SortedVector<egl_object_t*> egl_object_t::sObjects;
145Mutex egl_object_t::sLock;
146
Mathias Agopiancee79392010-07-26 21:14:59 -0700147
148struct egl_config_t {
149 egl_config_t() {}
150 egl_config_t(int impl, EGLConfig config)
151 : impl(impl), config(config), configId(0), implConfigId(0) { }
152 int impl; // the implementation this config is for
153 EGLConfig config; // the implementation's EGLConfig
154 EGLint configId; // our CONFIG_ID
155 EGLint implConfigId; // the implementation's CONFIG_ID
156 inline bool operator < (const egl_config_t& rhs) const {
157 if (impl < rhs.impl) return true;
158 if (impl > rhs.impl) return false;
159 return config < rhs.config;
160 }
161};
162
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700163struct egl_display_t {
164 enum { NOT_INITIALIZED, INITIALIZED, TERMINATED };
165
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800166 struct strings_t {
167 char const * vendor;
168 char const * version;
169 char const * clientApi;
170 char const * extensions;
171 };
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700172
173 struct DisplayImpl {
174 DisplayImpl() : dpy(EGL_NO_DISPLAY), config(0),
175 state(NOT_INITIALIZED), numConfigs(0) { }
176 EGLDisplay dpy;
177 EGLConfig* config;
178 EGLint state;
179 EGLint numConfigs;
180 strings_t queryString;
181 };
182
Mathias Agopiancee79392010-07-26 21:14:59 -0700183 uint32_t magic;
184 DisplayImpl disp[IMPL_NUM_IMPLEMENTATIONS];
185 EGLint numTotalConfigs;
186 egl_config_t* configs;
187 uint32_t refs;
188 Mutex lock;
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700189
Mathias Agopiancee79392010-07-26 21:14:59 -0700190 egl_display_t() : magic('_dpy'), numTotalConfigs(0), configs(0) { }
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700191 ~egl_display_t() { magic = 0; }
192 inline bool isValid() const { return magic == '_dpy'; }
193 inline bool isAlive() const { return isValid(); }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800194};
195
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700196struct egl_surface_t : public egl_object_t
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800197{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700198 typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
199
Mathias Agopiancee79392010-07-26 21:14:59 -0700200 egl_surface_t(EGLDisplay dpy, EGLSurface surface, EGLConfig config,
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700201 int impl, egl_connection_t const* cnx)
Mathias Agopiancee79392010-07-26 21:14:59 -0700202 : dpy(dpy), surface(surface), config(config), impl(impl), cnx(cnx) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800203 }
204 ~egl_surface_t() {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800205 }
206 EGLDisplay dpy;
207 EGLSurface surface;
Mathias Agopiancee79392010-07-26 21:14:59 -0700208 EGLConfig config;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800209 int impl;
210 egl_connection_t const* cnx;
211};
212
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700213struct egl_context_t : public egl_object_t
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800214{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700215 typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
216
Mathias Agopiancee79392010-07-26 21:14:59 -0700217 egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
Mathias Agopian618fa102009-10-14 02:06:37 -0700218 int impl, egl_connection_t const* cnx, int version)
219 : dpy(dpy), context(context), read(0), draw(0), impl(impl), cnx(cnx),
220 version(version)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800221 {
222 }
223 EGLDisplay dpy;
224 EGLContext context;
Mathias Agopiancee79392010-07-26 21:14:59 -0700225 EGLConfig config;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800226 EGLSurface read;
227 EGLSurface draw;
228 int impl;
229 egl_connection_t const* cnx;
Mathias Agopian618fa102009-10-14 02:06:37 -0700230 int version;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800231};
232
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700233struct egl_image_t : public egl_object_t
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700234{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700235 typedef egl_object_t::LocalRef<egl_image_t, EGLImageKHR> Ref;
236
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700237 egl_image_t(EGLDisplay dpy, EGLContext context)
238 : dpy(dpy), context(context)
239 {
240 memset(images, 0, sizeof(images));
241 }
242 EGLDisplay dpy;
243 EGLConfig context;
Mathias Agopian618fa102009-10-14 02:06:37 -0700244 EGLImageKHR images[IMPL_NUM_IMPLEMENTATIONS];
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700245};
246
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700247typedef egl_surface_t::Ref SurfaceRef;
248typedef egl_context_t::Ref ContextRef;
249typedef egl_image_t::Ref ImageRef;
250
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800251struct tls_t
252{
Mathias Agopiand274eae2009-07-31 16:21:17 -0700253 tls_t() : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(EGL_TRUE) { }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800254 EGLint error;
255 EGLContext ctx;
Mathias Agopiand274eae2009-07-31 16:21:17 -0700256 EGLBoolean logCallWithNoContext;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800257};
258
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800259
260// ----------------------------------------------------------------------------
261
Mathias Agopianbf41b112010-04-09 13:37:34 -0700262static egl_connection_t gEGLImpl[IMPL_NUM_IMPLEMENTATIONS];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800263static egl_display_t gDisplay[NUM_DISPLAYS];
264static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER;
265static pthread_key_t gEGLThreadLocalStorageKey = -1;
266
267// ----------------------------------------------------------------------------
268
Mathias Agopian618fa102009-10-14 02:06:37 -0700269EGLAPI gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS];
270EGLAPI gl_hooks_t gHooksNoContext;
Mathias Agopianeccc8cf2009-05-13 00:19:22 -0700271EGLAPI pthread_key_t gGLWrapperKey = -1;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800272
273// ----------------------------------------------------------------------------
274
275static __attribute__((noinline))
276const char *egl_strerror(EGLint err)
277{
278 switch (err){
279 case EGL_SUCCESS: return "EGL_SUCCESS";
280 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
281 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
282 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
283 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
284 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
285 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
286 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
287 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
288 case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
289 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
290 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
291 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
292 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
293 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
294 default: return "UNKNOWN";
295 }
296}
297
298static __attribute__((noinline))
299void clearTLS() {
300 if (gEGLThreadLocalStorageKey != -1) {
301 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
302 if (tls) {
303 delete tls;
304 pthread_setspecific(gEGLThreadLocalStorageKey, 0);
305 }
306 }
307}
308
309static tls_t* getTLS()
310{
311 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
312 if (tls == 0) {
313 tls = new tls_t;
314 pthread_setspecific(gEGLThreadLocalStorageKey, tls);
315 }
316 return tls;
317}
318
319template<typename T>
320static __attribute__((noinline))
321T setErrorEtc(const char* caller, int line, EGLint error, T returnValue) {
322 if (gEGLThreadLocalStorageKey == -1) {
323 pthread_mutex_lock(&gThreadLocalStorageKeyMutex);
324 if (gEGLThreadLocalStorageKey == -1)
325 pthread_key_create(&gEGLThreadLocalStorageKey, NULL);
326 pthread_mutex_unlock(&gThreadLocalStorageKeyMutex);
327 }
328 tls_t* tls = getTLS();
329 if (tls->error != error) {
330 LOGE("%s:%d error %x (%s)", caller, line, error, egl_strerror(error));
331 tls->error = error;
332 }
333 return returnValue;
334}
335
336static __attribute__((noinline))
337GLint getError() {
338 if (gEGLThreadLocalStorageKey == -1)
339 return EGL_SUCCESS;
340 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
341 if (!tls) return EGL_SUCCESS;
342 GLint error = tls->error;
343 tls->error = EGL_SUCCESS;
344 return error;
345}
346
347static __attribute__((noinline))
348void setContext(EGLContext ctx) {
349 if (gEGLThreadLocalStorageKey == -1) {
350 pthread_mutex_lock(&gThreadLocalStorageKeyMutex);
351 if (gEGLThreadLocalStorageKey == -1)
352 pthread_key_create(&gEGLThreadLocalStorageKey, NULL);
353 pthread_mutex_unlock(&gThreadLocalStorageKeyMutex);
354 }
355 tls_t* tls = getTLS();
356 tls->ctx = ctx;
357}
358
359static __attribute__((noinline))
360EGLContext getContext() {
361 if (gEGLThreadLocalStorageKey == -1)
362 return EGL_NO_CONTEXT;
363 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
364 if (!tls) return EGL_NO_CONTEXT;
365 return tls->ctx;
366}
367
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800368/*****************************************************************************/
369
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800370template<typename T>
371static __attribute__((noinline))
372int binarySearch(
373 T const sortedArray[], int first, int last, T key)
374{
375 while (first <= last) {
376 int mid = (first + last) / 2;
Mathias Agopiancee79392010-07-26 21:14:59 -0700377 if (sortedArray[mid] < key) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800378 first = mid + 1;
379 } else if (key < sortedArray[mid]) {
380 last = mid - 1;
381 } else {
382 return mid;
383 }
384 }
385 return -1;
386}
387
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800388static int cmp_configs(const void* a, const void *b)
389{
Mathias Agopiancee79392010-07-26 21:14:59 -0700390 const egl_config_t& c0 = *(egl_config_t const *)a;
391 const egl_config_t& c1 = *(egl_config_t const *)b;
392 return c0<c1 ? -1 : (c1<c0 ? 1 : 0);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800393}
394
395struct extention_map_t {
396 const char* name;
397 __eglMustCastToProperFunctionPointerType address;
398};
399
400static const extention_map_t gExtentionMap[] = {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700401 { "eglLockSurfaceKHR",
402 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
403 { "eglUnlockSurfaceKHR",
404 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
405 { "eglCreateImageKHR",
406 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
407 { "eglDestroyImageKHR",
408 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Mathias Agopian8d2e83b2009-06-24 22:37:39 -0700409 { "eglSetSwapRectangleANDROID",
410 (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800411};
412
Mathias Agopian24035332010-08-02 17:34:32 -0700413extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
414
415// accesses protected by gInitDriverMutex
416static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> gGLExtentionMap;
417static int gGLExtentionSlot = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800418
419static void(*findProcAddress(const char* name,
420 const extention_map_t* map, size_t n))()
421{
422 for (uint32_t i=0 ; i<n ; i++) {
423 if (!strcmp(name, map[i].name)) {
424 return map[i].address;
425 }
426 }
427 return NULL;
428}
429
430// ----------------------------------------------------------------------------
431
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800432static void gl_no_context() {
Mathias Agopiand274eae2009-07-31 16:21:17 -0700433 tls_t* tls = getTLS();
434 if (tls->logCallWithNoContext == EGL_TRUE) {
435 tls->logCallWithNoContext = EGL_FALSE;
436 LOGE("call to OpenGL ES API with no current context "
437 "(logged once per thread)");
438 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800439}
Mathias Agopiand274eae2009-07-31 16:21:17 -0700440
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800441static void early_egl_init(void)
442{
443#if !USE_FAST_TLS_KEY
444 pthread_key_create(&gGLWrapperKey, NULL);
445#endif
446 uint32_t addr = (uint32_t)((void*)gl_no_context);
447 android_memset32(
Mathias Agopian618fa102009-10-14 02:06:37 -0700448 (uint32_t*)(void*)&gHooksNoContext,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800449 addr,
Mathias Agopian618fa102009-10-14 02:06:37 -0700450 sizeof(gHooksNoContext));
451 setGlThreadSpecific(&gHooksNoContext);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800452}
453
454static pthread_once_t once_control = PTHREAD_ONCE_INIT;
455static int sEarlyInitState = pthread_once(&once_control, &early_egl_init);
456
457
458static inline
459egl_display_t* get_display(EGLDisplay dpy)
460{
461 uintptr_t index = uintptr_t(dpy)-1U;
462 return (index >= NUM_DISPLAYS) ? NULL : &gDisplay[index];
463}
464
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700465template<typename NATIVE, typename EGL>
466static inline NATIVE* egl_to_native_cast(EGL arg) {
467 return reinterpret_cast<NATIVE*>(arg);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800468}
469
470static inline
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700471egl_surface_t* get_surface(EGLSurface surface) {
472 return egl_to_native_cast<egl_surface_t>(surface);
473}
474
475static inline
476egl_context_t* get_context(EGLContext context) {
477 return egl_to_native_cast<egl_context_t>(context);
478}
479
480static inline
481egl_image_t* get_image(EGLImageKHR image) {
482 return egl_to_native_cast<egl_image_t>(image);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800483}
484
485static egl_connection_t* validate_display_config(
486 EGLDisplay dpy, EGLConfig config,
Mathias Agopiancee79392010-07-26 21:14:59 -0700487 egl_display_t const*& dp)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800488{
489 dp = get_display(dpy);
490 if (!dp) return setError(EGL_BAD_DISPLAY, (egl_connection_t*)NULL);
491
Mathias Agopiancee79392010-07-26 21:14:59 -0700492 if (intptr_t(config) >= dp->numTotalConfigs) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800493 return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
494 }
Mathias Agopiancee79392010-07-26 21:14:59 -0700495 egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(config)].impl];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800496 if (cnx->dso == 0) {
497 return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
498 }
499 return cnx;
500}
501
502static EGLBoolean validate_display_context(EGLDisplay dpy, EGLContext ctx)
503{
504 if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS)
505 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700506 if (!get_display(dpy)->isAlive())
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800507 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700508 if (!get_context(ctx)->isAlive())
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800509 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
510 return EGL_TRUE;
511}
512
513static EGLBoolean validate_display_surface(EGLDisplay dpy, EGLSurface surface)
514{
515 if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS)
516 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700517 if (!get_display(dpy)->isAlive())
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800518 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700519 if (!get_surface(surface)->isAlive())
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800520 return setError(EGL_BAD_SURFACE, EGL_FALSE);
521 return EGL_TRUE;
522}
523
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700524EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image)
525{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700526 ImageRef _i(image);
527 if (!_i.get()) return EGL_NO_IMAGE_KHR;
528
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700529 EGLContext context = getContext();
530 if (context == EGL_NO_CONTEXT || image == EGL_NO_IMAGE_KHR)
531 return EGL_NO_IMAGE_KHR;
532
533 egl_context_t const * const c = get_context(context);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700534 if (!c->isAlive())
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700535 return EGL_NO_IMAGE_KHR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800536
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700537 egl_image_t const * const i = get_image(image);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700538 return i->images[c->impl];
539}
540
Mathias Agopian923c6612009-08-17 18:07:06 -0700541// ----------------------------------------------------------------------------
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700542
Mathias Agopian923c6612009-08-17 18:07:06 -0700543// this mutex protects:
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700544// d->disp[]
Mathias Agopian923c6612009-08-17 18:07:06 -0700545// egl_init_drivers_locked()
546//
547static pthread_mutex_t gInitDriverMutex = PTHREAD_MUTEX_INITIALIZER;
548
549EGLBoolean egl_init_drivers_locked()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800550{
551 if (sEarlyInitState) {
Mathias Agopian923c6612009-08-17 18:07:06 -0700552 // initialized by static ctor. should be set here.
553 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800554 }
555
Mathias Agopiande586972009-05-28 17:39:03 -0700556 // get our driver loader
Mathias Agopian923c6612009-08-17 18:07:06 -0700557 Loader& loader(Loader::getInstance());
Mathias Agopiande586972009-05-28 17:39:03 -0700558
Mathias Agopian923c6612009-08-17 18:07:06 -0700559 // dynamically load all our EGL implementations for all displays
560 // and retrieve the corresponding EGLDisplay
561 // if that fails, don't use this driver.
562 // TODO: currently we only deal with EGL_DEFAULT_DISPLAY
563 egl_connection_t* cnx;
564 egl_display_t* d = &gDisplay[0];
565
566 cnx = &gEGLImpl[IMPL_SOFTWARE];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800567 if (cnx->dso == 0) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700568 cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_SOFTWARE];
569 cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_SOFTWARE];
570 cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 0, cnx);
Mathias Agopian923c6612009-08-17 18:07:06 -0700571 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700572 EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
Mathias Agopian923c6612009-08-17 18:07:06 -0700573 LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for software EGL!");
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700574 d->disp[IMPL_SOFTWARE].dpy = dpy;
Mathias Agopian923c6612009-08-17 18:07:06 -0700575 if (dpy == EGL_NO_DISPLAY) {
576 loader.close(cnx->dso);
577 cnx->dso = NULL;
578 }
579 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800580 }
581
582 cnx = &gEGLImpl[IMPL_HARDWARE];
Mathias Agopian923c6612009-08-17 18:07:06 -0700583 if (cnx->dso == 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800584 char value[PROPERTY_VALUE_MAX];
585 property_get("debug.egl.hw", value, "1");
586 if (atoi(value) != 0) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700587 cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_HARDWARE];
588 cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_HARDWARE];
589 cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 1, cnx);
Mathias Agopian923c6612009-08-17 18:07:06 -0700590 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700591 EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
Mathias Agopian923c6612009-08-17 18:07:06 -0700592 LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for hardware EGL!");
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700593 d->disp[IMPL_HARDWARE].dpy = dpy;
Mathias Agopian923c6612009-08-17 18:07:06 -0700594 if (dpy == EGL_NO_DISPLAY) {
595 loader.close(cnx->dso);
596 cnx->dso = NULL;
597 }
598 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800599 } else {
600 LOGD("3D hardware acceleration is disabled");
601 }
602 }
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700603
Mathias Agopian923c6612009-08-17 18:07:06 -0700604 if (!gEGLImpl[IMPL_SOFTWARE].dso && !gEGLImpl[IMPL_HARDWARE].dso) {
605 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800606 }
607
Mathias Agopian923c6612009-08-17 18:07:06 -0700608 return EGL_TRUE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800609}
610
Mathias Agopian923c6612009-08-17 18:07:06 -0700611EGLBoolean egl_init_drivers()
612{
613 EGLBoolean res;
614 pthread_mutex_lock(&gInitDriverMutex);
615 res = egl_init_drivers_locked();
616 pthread_mutex_unlock(&gInitDriverMutex);
617 return res;
618}
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700619
620// ----------------------------------------------------------------------------
621}; // namespace android
622// ----------------------------------------------------------------------------
623
624using namespace android;
625
626EGLDisplay eglGetDisplay(NativeDisplayType display)
627{
Mathias Agopian923c6612009-08-17 18:07:06 -0700628 uint32_t index = uint32_t(display);
629 if (index >= NUM_DISPLAYS) {
630 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
631 }
632
633 if (egl_init_drivers() == EGL_FALSE) {
634 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
635 }
636
637 EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU);
638 return dpy;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700639}
640
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800641// ----------------------------------------------------------------------------
642// Initialization
643// ----------------------------------------------------------------------------
644
645EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
646{
647 egl_display_t * const dp = get_display(dpy);
648 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
649
Mathias Agopian75bc2782010-02-05 16:17:01 -0800650 Mutex::Autolock _l(dp->lock);
651
652 if (dp->refs > 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800653 if (major != NULL) *major = VERSION_MAJOR;
654 if (minor != NULL) *minor = VERSION_MINOR;
Jack Palevich81cd0842010-03-15 20:45:21 -0700655 dp->refs++;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800656 return EGL_TRUE;
657 }
658
Mathias Agopian618fa102009-10-14 02:06:37 -0700659 setGlThreadSpecific(&gHooksNoContext);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800660
661 // initialize each EGL and
662 // build our own extension string first, based on the extension we know
663 // and the extension supported by our client implementation
Mathias Agopian618fa102009-10-14 02:06:37 -0700664 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800665 egl_connection_t* const cnx = &gEGLImpl[i];
666 cnx->major = -1;
667 cnx->minor = -1;
668 if (!cnx->dso)
669 continue;
670
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700671#if defined(ADRENO130)
672#warning "Adreno-130 eglInitialize() workaround"
673 /*
674 * The ADRENO 130 driver returns a different EGLDisplay each time
675 * eglGetDisplay() is called, but also makes the EGLDisplay invalid
676 * after eglTerminate() has been called, so that eglInitialize()
677 * cannot be called again. Therefore, we need to make sure to call
678 * eglGetDisplay() before calling eglInitialize();
679 */
680 if (i == IMPL_HARDWARE) {
681 dp->disp[i].dpy =
Mathias Agopian618fa102009-10-14 02:06:37 -0700682 cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700683 }
684#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800685
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700686
687 EGLDisplay idpy = dp->disp[i].dpy;
Mathias Agopian618fa102009-10-14 02:06:37 -0700688 if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800689 //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p",
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700690 // i, idpy, cnx->major, cnx->minor, cnx);
691
692 // display is now initialized
693 dp->disp[i].state = egl_display_t::INITIALIZED;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800694
695 // get the query-strings for this display for each implementation
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700696 dp->disp[i].queryString.vendor =
Mathias Agopian618fa102009-10-14 02:06:37 -0700697 cnx->egl.eglQueryString(idpy, EGL_VENDOR);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700698 dp->disp[i].queryString.version =
Mathias Agopian618fa102009-10-14 02:06:37 -0700699 cnx->egl.eglQueryString(idpy, EGL_VERSION);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700700 dp->disp[i].queryString.extensions =
Mathias Agopian618fa102009-10-14 02:06:37 -0700701 cnx->egl.eglQueryString(idpy, EGL_EXTENSIONS);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700702 dp->disp[i].queryString.clientApi =
Mathias Agopian618fa102009-10-14 02:06:37 -0700703 cnx->egl.eglQueryString(idpy, EGL_CLIENT_APIS);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800704
705 } else {
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700706 LOGW("%d: eglInitialize(%p) failed (%s)", i, idpy,
Mathias Agopian618fa102009-10-14 02:06:37 -0700707 egl_strerror(cnx->egl.eglGetError()));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800708 }
709 }
710
711 EGLBoolean res = EGL_FALSE;
Mathias Agopian618fa102009-10-14 02:06:37 -0700712 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800713 egl_connection_t* const cnx = &gEGLImpl[i];
714 if (cnx->dso && cnx->major>=0 && cnx->minor>=0) {
715 EGLint n;
Mathias Agopian618fa102009-10-14 02:06:37 -0700716 if (cnx->egl.eglGetConfigs(dp->disp[i].dpy, 0, 0, &n)) {
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700717 dp->disp[i].config = (EGLConfig*)malloc(sizeof(EGLConfig)*n);
718 if (dp->disp[i].config) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700719 if (cnx->egl.eglGetConfigs(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700720 dp->disp[i].dpy, dp->disp[i].config, n,
721 &dp->disp[i].numConfigs))
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800722 {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800723 dp->numTotalConfigs += n;
724 res = EGL_TRUE;
725 }
726 }
727 }
728 }
729 }
730
731 if (res == EGL_TRUE) {
Mathias Agopiancee79392010-07-26 21:14:59 -0700732 dp->configs = new egl_config_t[ dp->numTotalConfigs ];
733 for (int i=0, k=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
734 egl_connection_t* const cnx = &gEGLImpl[i];
735 if (cnx->dso && cnx->major>=0 && cnx->minor>=0) {
736 for (int j=0 ; j<dp->disp[i].numConfigs ; j++) {
737 dp->configs[k].impl = i;
738 dp->configs[k].config = dp->disp[i].config[j];
739 dp->configs[k].configId = k + 1; // CONFIG_ID start at 1
740 // store the implementation's CONFIG_ID
741 cnx->egl.eglGetConfigAttrib(
742 dp->disp[i].dpy,
743 dp->disp[i].config[j],
744 EGL_CONFIG_ID,
745 &dp->configs[k].implConfigId);
746 k++;
747 }
748 }
749 }
750
751 // sort our configurations so we can do binary-searches
752 qsort( dp->configs,
753 dp->numTotalConfigs,
754 sizeof(egl_config_t), cmp_configs);
755
Mathias Agopian75bc2782010-02-05 16:17:01 -0800756 dp->refs++;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800757 if (major != NULL) *major = VERSION_MAJOR;
758 if (minor != NULL) *minor = VERSION_MINOR;
759 return EGL_TRUE;
760 }
761 return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
762}
763
764EGLBoolean eglTerminate(EGLDisplay dpy)
765{
Mathias Agopian923c6612009-08-17 18:07:06 -0700766 // NOTE: don't unload the drivers b/c some APIs can be called
767 // after eglTerminate() has been called. eglTerminate() only
768 // terminates an EGLDisplay, not a EGL itself.
769
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800770 egl_display_t* const dp = get_display(dpy);
771 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian75bc2782010-02-05 16:17:01 -0800772
773 Mutex::Autolock _l(dp->lock);
774
775 if (dp->refs == 0) {
776 return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
777 }
778
779 // this is specific to Android, display termination is ref-counted.
Jack Palevich81cd0842010-03-15 20:45:21 -0700780 if (dp->refs > 1) {
781 dp->refs--;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800782 return EGL_TRUE;
Jack Palevich81cd0842010-03-15 20:45:21 -0700783 }
Mathias Agopiande586972009-05-28 17:39:03 -0700784
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800785 EGLBoolean res = EGL_FALSE;
Mathias Agopian618fa102009-10-14 02:06:37 -0700786 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800787 egl_connection_t* const cnx = &gEGLImpl[i];
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700788 if (cnx->dso && dp->disp[i].state == egl_display_t::INITIALIZED) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700789 if (cnx->egl.eglTerminate(dp->disp[i].dpy) == EGL_FALSE) {
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700790 LOGW("%d: eglTerminate(%p) failed (%s)", i, dp->disp[i].dpy,
Mathias Agopian618fa102009-10-14 02:06:37 -0700791 egl_strerror(cnx->egl.eglGetError()));
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700792 }
Mathias Agopian923c6612009-08-17 18:07:06 -0700793 // REVISIT: it's unclear what to do if eglTerminate() fails
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700794 free(dp->disp[i].config);
795
796 dp->disp[i].numConfigs = 0;
797 dp->disp[i].config = 0;
798 dp->disp[i].state = egl_display_t::TERMINATED;
799
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800800 res = EGL_TRUE;
801 }
802 }
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700803
804 // TODO: all egl_object_t should be marked for termination
805
Mathias Agopian75bc2782010-02-05 16:17:01 -0800806 dp->refs--;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800807 dp->numTotalConfigs = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -0700808 delete [] dp->configs;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800809 clearTLS();
810 return res;
811}
812
813// ----------------------------------------------------------------------------
814// configuration
815// ----------------------------------------------------------------------------
816
817EGLBoolean eglGetConfigs( EGLDisplay dpy,
818 EGLConfig *configs,
819 EGLint config_size, EGLint *num_config)
820{
821 egl_display_t const * const dp = get_display(dpy);
822 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
823
824 GLint numConfigs = dp->numTotalConfigs;
825 if (!configs) {
826 *num_config = numConfigs;
827 return EGL_TRUE;
828 }
Mathias Agopiancee79392010-07-26 21:14:59 -0700829
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800830 GLint n = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -0700831 for (intptr_t i=0 ; i<dp->numTotalConfigs && config_size ; i++) {
832 *configs++ = EGLConfig(i);
833 config_size--;
834 n++;
835 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800836
837 *num_config = n;
838 return EGL_TRUE;
839}
840
841EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
842 EGLConfig *configs, EGLint config_size,
843 EGLint *num_config)
844{
845 egl_display_t const * const dp = get_display(dpy);
846 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
847
Jack Palevich749c63d2009-03-25 15:12:17 -0700848 if (num_config==0) {
849 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800850 }
851
852 EGLint n;
853 EGLBoolean res = EGL_FALSE;
854 *num_config = 0;
855
856
857 // It is unfortunate, but we need to remap the EGL_CONFIG_IDs,
Mathias Agopiancee79392010-07-26 21:14:59 -0700858 // to do this, we have to go through the attrib_list array once
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800859 // to figure out both its size and if it contains an EGL_CONFIG_ID
860 // key. If so, the full array is copied and patched.
861 // NOTE: we assume that there can be only one occurrence
862 // of EGL_CONFIG_ID.
863
864 EGLint patch_index = -1;
865 GLint attr;
866 size_t size = 0;
Mathias Agopian04aed212010-05-17 14:45:43 -0700867 if (attrib_list) {
868 while ((attr=attrib_list[size]) != EGL_NONE) {
869 if (attr == EGL_CONFIG_ID)
870 patch_index = size;
871 size += 2;
872 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800873 }
874 if (patch_index >= 0) {
875 size += 2; // we need copy the sentinel as well
876 EGLint* new_list = (EGLint*)malloc(size*sizeof(EGLint));
877 if (new_list == 0)
878 return setError(EGL_BAD_ALLOC, EGL_FALSE);
879 memcpy(new_list, attrib_list, size*sizeof(EGLint));
880
881 // patch the requested EGL_CONFIG_ID
Mathias Agopiancee79392010-07-26 21:14:59 -0700882 bool found = false;
883 EGLConfig ourConfig(0);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800884 EGLint& configId(new_list[patch_index+1]);
Mathias Agopiancee79392010-07-26 21:14:59 -0700885 for (intptr_t i=0 ; i<dp->numTotalConfigs ; i++) {
886 if (dp->configs[i].configId == configId) {
887 ourConfig = EGLConfig(i);
888 configId = dp->configs[i].implConfigId;
889 found = true;
890 break;
891 }
892 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800893
Mathias Agopiancee79392010-07-26 21:14:59 -0700894 egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(ourConfig)].impl];
895 if (found && cnx->dso) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800896 // and switch to the new list
897 attrib_list = const_cast<const EGLint *>(new_list);
898
899 // At this point, the only configuration that can match is
900 // dp->configs[i][index], however, we don't know if it would be
901 // rejected because of the other attributes, so we do have to call
Mathias Agopian618fa102009-10-14 02:06:37 -0700902 // cnx->egl.eglChooseConfig() -- but we don't have to loop
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800903 // through all the EGLimpl[].
904 // We also know we can only get a single config back, and we know
905 // which one.
906
Mathias Agopian618fa102009-10-14 02:06:37 -0700907 res = cnx->egl.eglChooseConfig(
Mathias Agopiancee79392010-07-26 21:14:59 -0700908 dp->disp[ dp->configs[intptr_t(ourConfig)].impl ].dpy,
909 attrib_list, configs, config_size, &n);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800910 if (res && n>0) {
911 // n has to be 0 or 1, by construction, and we already know
912 // which config it will return (since there can be only one).
Jack Palevich749c63d2009-03-25 15:12:17 -0700913 if (configs) {
Mathias Agopiancee79392010-07-26 21:14:59 -0700914 configs[0] = ourConfig;
Jack Palevich749c63d2009-03-25 15:12:17 -0700915 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800916 *num_config = 1;
917 }
918 }
919
920 free(const_cast<EGLint *>(attrib_list));
921 return res;
922 }
923
Mathias Agopiancee79392010-07-26 21:14:59 -0700924
Mathias Agopian618fa102009-10-14 02:06:37 -0700925 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800926 egl_connection_t* const cnx = &gEGLImpl[i];
927 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700928 if (cnx->egl.eglChooseConfig(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700929 dp->disp[i].dpy, attrib_list, configs, config_size, &n)) {
Jack Palevich749c63d2009-03-25 15:12:17 -0700930 if (configs) {
931 // now we need to convert these client EGLConfig to our
Mathias Agopiancee79392010-07-26 21:14:59 -0700932 // internal EGLConfig format.
933 // This is done in O(n Log(n)) time.
Jack Palevich749c63d2009-03-25 15:12:17 -0700934 for (int j=0 ; j<n ; j++) {
Mathias Agopiancee79392010-07-26 21:14:59 -0700935 egl_config_t key(i, configs[j]);
936 intptr_t index = binarySearch<egl_config_t>(
937 dp->configs, 0, dp->numTotalConfigs, key);
Jack Palevich749c63d2009-03-25 15:12:17 -0700938 if (index >= 0) {
Mathias Agopiancee79392010-07-26 21:14:59 -0700939 configs[j] = EGLConfig(index);
Jack Palevich749c63d2009-03-25 15:12:17 -0700940 } else {
941 return setError(EGL_BAD_CONFIG, EGL_FALSE);
942 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800943 }
Jack Palevich749c63d2009-03-25 15:12:17 -0700944 configs += n;
945 config_size -= n;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800946 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800947 *num_config += n;
948 res = EGL_TRUE;
949 }
950 }
951 }
952 return res;
953}
954
955EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
956 EGLint attribute, EGLint *value)
957{
958 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -0700959 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800960 if (!cnx) return EGL_FALSE;
961
962 if (attribute == EGL_CONFIG_ID) {
Mathias Agopiancee79392010-07-26 21:14:59 -0700963 *value = dp->configs[intptr_t(config)].configId;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800964 return EGL_TRUE;
965 }
Mathias Agopian618fa102009-10-14 02:06:37 -0700966 return cnx->egl.eglGetConfigAttrib(
Mathias Agopiancee79392010-07-26 21:14:59 -0700967 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
968 dp->configs[intptr_t(config)].config, attribute, value);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800969}
970
971// ----------------------------------------------------------------------------
972// surfaces
973// ----------------------------------------------------------------------------
974
975EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
976 NativeWindowType window,
977 const EGLint *attrib_list)
978{
979 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -0700980 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800981 if (cnx) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700982 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopiancee79392010-07-26 21:14:59 -0700983 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
984 dp->configs[intptr_t(config)].config, window, attrib_list);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800985 if (surface != EGL_NO_SURFACE) {
Mathias Agopiancee79392010-07-26 21:14:59 -0700986 egl_surface_t* s = new egl_surface_t(dpy, surface, config,
987 dp->configs[intptr_t(config)].impl, cnx);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800988 return s;
989 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800990 }
991 return EGL_NO_SURFACE;
992}
993
994EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
995 NativePixmapType pixmap,
996 const EGLint *attrib_list)
997{
998 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -0700999 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001000 if (cnx) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001001 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopiancee79392010-07-26 21:14:59 -07001002 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1003 dp->configs[intptr_t(config)].config, pixmap, attrib_list);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001004 if (surface != EGL_NO_SURFACE) {
Mathias Agopiancee79392010-07-26 21:14:59 -07001005 egl_surface_t* s = new egl_surface_t(dpy, surface, config,
1006 dp->configs[intptr_t(config)].impl, cnx);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001007 return s;
1008 }
1009 }
1010 return EGL_NO_SURFACE;
1011}
1012
1013EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
1014 const EGLint *attrib_list)
1015{
1016 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -07001017 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001018 if (cnx) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001019 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopiancee79392010-07-26 21:14:59 -07001020 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1021 dp->configs[intptr_t(config)].config, attrib_list);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001022 if (surface != EGL_NO_SURFACE) {
Mathias Agopiancee79392010-07-26 21:14:59 -07001023 egl_surface_t* s = new egl_surface_t(dpy, surface, config,
1024 dp->configs[intptr_t(config)].impl, cnx);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001025 return s;
1026 }
1027 }
1028 return EGL_NO_SURFACE;
1029}
1030
1031EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
1032{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001033 SurfaceRef _s(surface);
1034 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1035
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001036 if (!validate_display_surface(dpy, surface))
1037 return EGL_FALSE;
1038 egl_display_t const * const dp = get_display(dpy);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001039
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001040 egl_surface_t * const s = get_surface(surface);
Mathias Agopian618fa102009-10-14 02:06:37 -07001041 EGLBoolean result = s->cnx->egl.eglDestroySurface(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001042 dp->disp[s->impl].dpy, s->surface);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001043 if (result == EGL_TRUE) {
1044 _s.terminate();
1045 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001046 return result;
1047}
1048
1049EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
1050 EGLint attribute, EGLint *value)
1051{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001052 SurfaceRef _s(surface);
1053 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1054
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001055 if (!validate_display_surface(dpy, surface))
1056 return EGL_FALSE;
1057 egl_display_t const * const dp = get_display(dpy);
1058 egl_surface_t const * const s = get_surface(surface);
1059
Mathias Agopiancee79392010-07-26 21:14:59 -07001060 EGLBoolean result(EGL_TRUE);
1061 if (attribute == EGL_CONFIG_ID) {
1062 // We need to remap EGL_CONFIG_IDs
1063 *value = dp->configs[intptr_t(s->config)].configId;
1064 } else {
1065 result = s->cnx->egl.eglQuerySurface(
1066 dp->disp[s->impl].dpy, s->surface, attribute, value);
1067 }
1068
1069 return result;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001070}
1071
1072// ----------------------------------------------------------------------------
Mathias Agopiancee79392010-07-26 21:14:59 -07001073// Contexts
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001074// ----------------------------------------------------------------------------
1075
1076EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
1077 EGLContext share_list, const EGLint *attrib_list)
1078{
1079 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -07001080 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001081 if (cnx) {
Jamie Gennis4c39f8f2010-07-02 11:39:12 -07001082 if (share_list != EGL_NO_CONTEXT) {
1083 egl_context_t* const c = get_context(share_list);
1084 share_list = c->context;
1085 }
Mathias Agopian618fa102009-10-14 02:06:37 -07001086 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopiancee79392010-07-26 21:14:59 -07001087 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1088 dp->configs[intptr_t(config)].config,
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001089 share_list, attrib_list);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001090 if (context != EGL_NO_CONTEXT) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001091 // figure out if it's a GLESv1 or GLESv2
1092 int version = 0;
1093 if (attrib_list) {
1094 while (*attrib_list != EGL_NONE) {
1095 GLint attr = *attrib_list++;
1096 GLint value = *attrib_list++;
1097 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
1098 if (value == 1) {
1099 version = GLESv1_INDEX;
1100 } else if (value == 2) {
1101 version = GLESv2_INDEX;
1102 }
1103 }
1104 };
1105 }
Mathias Agopiancee79392010-07-26 21:14:59 -07001106 egl_context_t* c = new egl_context_t(dpy, context, config,
1107 dp->configs[intptr_t(config)].impl, cnx, version);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001108 return c;
1109 }
1110 }
1111 return EGL_NO_CONTEXT;
1112}
1113
1114EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1115{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001116 ContextRef _c(ctx);
1117 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1118
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001119 if (!validate_display_context(dpy, ctx))
1120 return EGL_FALSE;
1121 egl_display_t const * const dp = get_display(dpy);
1122 egl_context_t * const c = get_context(ctx);
Mathias Agopian618fa102009-10-14 02:06:37 -07001123 EGLBoolean result = c->cnx->egl.eglDestroyContext(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001124 dp->disp[c->impl].dpy, c->context);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001125 if (result == EGL_TRUE) {
1126 _c.terminate();
1127 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001128 return result;
1129}
1130
1131EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
1132 EGLSurface read, EGLContext ctx)
1133{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001134 // get a reference to the object passed in
1135 ContextRef _c(ctx);
1136 SurfaceRef _d(draw);
1137 SurfaceRef _r(read);
1138
1139 // validate the display and the context (if not EGL_NO_CONTEXT)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001140 egl_display_t const * const dp = get_display(dpy);
1141 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001142 if ((ctx != EGL_NO_CONTEXT) && (!validate_display_context(dpy, ctx))) {
1143 // EGL_NO_CONTEXT is valid
1144 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001145 }
1146
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001147 // these are the underlying implementation's object
1148 EGLContext impl_ctx = EGL_NO_CONTEXT;
Mathias Agopianaf742132009-06-25 00:01:11 -07001149 EGLSurface impl_draw = EGL_NO_SURFACE;
1150 EGLSurface impl_read = EGL_NO_SURFACE;
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001151
1152 // these are our objects structs passed in
1153 egl_context_t * c = NULL;
1154 egl_surface_t const * d = NULL;
1155 egl_surface_t const * r = NULL;
1156
1157 // these are the current objects structs
1158 egl_context_t * cur_c = get_context(getContext());
1159 egl_surface_t * cur_r = NULL;
1160 egl_surface_t * cur_d = NULL;
1161
1162 if (ctx != EGL_NO_CONTEXT) {
1163 c = get_context(ctx);
1164 cur_r = get_surface(c->read);
1165 cur_d = get_surface(c->draw);
1166 impl_ctx = c->context;
1167 } else {
1168 // no context given, use the implementation of the current context
1169 if (cur_c == NULL) {
1170 // no current context
1171 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
Mathias Agopian8063c3a2010-01-25 11:30:11 -08001172 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
1173 return setError(EGL_BAD_MATCH, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001174 }
Mathias Agopian8063c3a2010-01-25 11:30:11 -08001175 // not an error, there is just no current context.
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001176 return EGL_TRUE;
1177 }
1178 }
1179
1180 // retrieve the underlying implementation's draw EGLSurface
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001181 if (draw != EGL_NO_SURFACE) {
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001182 d = get_surface(draw);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001183 // make sure the EGLContext and EGLSurface passed in are for
1184 // the same driver
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001185 if (c && d->impl != c->impl)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001186 return setError(EGL_BAD_MATCH, EGL_FALSE);
Mathias Agopianaf742132009-06-25 00:01:11 -07001187 impl_draw = d->surface;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001188 }
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001189
1190 // retrieve the underlying implementation's read EGLSurface
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001191 if (read != EGL_NO_SURFACE) {
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001192 r = get_surface(read);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001193 // make sure the EGLContext and EGLSurface passed in are for
1194 // the same driver
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001195 if (c && r->impl != c->impl)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001196 return setError(EGL_BAD_MATCH, EGL_FALSE);
Mathias Agopianaf742132009-06-25 00:01:11 -07001197 impl_read = r->surface;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001198 }
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001199
1200 EGLBoolean result;
1201
1202 if (c) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001203 result = c->cnx->egl.eglMakeCurrent(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001204 dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001205 } else {
Mathias Agopian618fa102009-10-14 02:06:37 -07001206 result = cur_c->cnx->egl.eglMakeCurrent(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001207 dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001208 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001209
1210 if (result == EGL_TRUE) {
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001211 // by construction, these are either 0 or valid (possibly terminated)
1212 // it should be impossible for these to be invalid
1213 ContextRef _cur_c(cur_c);
1214 SurfaceRef _cur_r(cur_r);
1215 SurfaceRef _cur_d(cur_d);
1216
1217 // cur_c has to be valid here (but could be terminated)
1218 if (ctx != EGL_NO_CONTEXT) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001219 setGlThreadSpecific(c->cnx->hooks[c->version]);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001220 setContext(ctx);
1221 _c.acquire();
1222 } else {
Mathias Agopian618fa102009-10-14 02:06:37 -07001223 setGlThreadSpecific(&gHooksNoContext);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001224 setContext(EGL_NO_CONTEXT);
1225 }
1226 _cur_c.release();
1227
1228 _r.acquire();
1229 _cur_r.release();
1230 if (c) c->read = read;
1231
1232 _d.acquire();
1233 _cur_d.release();
1234 if (c) c->draw = draw;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001235 }
1236 return result;
1237}
1238
1239
1240EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
1241 EGLint attribute, EGLint *value)
1242{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001243 ContextRef _c(ctx);
1244 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1245
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001246 if (!validate_display_context(dpy, ctx))
1247 return EGL_FALSE;
1248
1249 egl_display_t const * const dp = get_display(dpy);
1250 egl_context_t * const c = get_context(ctx);
1251
Mathias Agopiancee79392010-07-26 21:14:59 -07001252 EGLBoolean result(EGL_TRUE);
1253 if (attribute == EGL_CONFIG_ID) {
1254 *value = dp->configs[intptr_t(c->config)].configId;
1255 } else {
1256 // We need to remap EGL_CONFIG_IDs
1257 result = c->cnx->egl.eglQueryContext(
1258 dp->disp[c->impl].dpy, c->context, attribute, value);
1259 }
1260
1261 return result;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001262}
1263
1264EGLContext eglGetCurrentContext(void)
1265{
Mathias Agopian923c6612009-08-17 18:07:06 -07001266 // could be called before eglInitialize(), but we wouldn't have a context
1267 // then, and this function would correctly return EGL_NO_CONTEXT.
1268
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001269 EGLContext ctx = getContext();
1270 return ctx;
1271}
1272
1273EGLSurface eglGetCurrentSurface(EGLint readdraw)
1274{
Mathias Agopian923c6612009-08-17 18:07:06 -07001275 // could be called before eglInitialize(), but we wouldn't have a context
1276 // then, and this function would correctly return EGL_NO_SURFACE.
1277
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001278 EGLContext ctx = getContext();
1279 if (ctx) {
1280 egl_context_t const * const c = get_context(ctx);
1281 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1282 switch (readdraw) {
1283 case EGL_READ: return c->read;
1284 case EGL_DRAW: return c->draw;
1285 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1286 }
1287 }
1288 return EGL_NO_SURFACE;
1289}
1290
1291EGLDisplay eglGetCurrentDisplay(void)
1292{
Mathias Agopian923c6612009-08-17 18:07:06 -07001293 // could be called before eglInitialize(), but we wouldn't have a context
1294 // then, and this function would correctly return EGL_NO_DISPLAY.
1295
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001296 EGLContext ctx = getContext();
1297 if (ctx) {
1298 egl_context_t const * const c = get_context(ctx);
1299 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1300 return c->dpy;
1301 }
1302 return EGL_NO_DISPLAY;
1303}
1304
1305EGLBoolean eglWaitGL(void)
1306{
Mathias Agopian923c6612009-08-17 18:07:06 -07001307 // could be called before eglInitialize(), but we wouldn't have a context
1308 // then, and this function would return GL_TRUE, which isn't wrong.
1309
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001310 EGLBoolean res = EGL_TRUE;
1311 EGLContext ctx = getContext();
1312 if (ctx) {
1313 egl_context_t const * const c = get_context(ctx);
1314 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1315 if (uint32_t(c->impl)>=2)
1316 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1317 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1318 if (!cnx->dso)
1319 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian618fa102009-10-14 02:06:37 -07001320 res = cnx->egl.eglWaitGL();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001321 }
1322 return res;
1323}
1324
1325EGLBoolean eglWaitNative(EGLint engine)
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.eglWaitNative(engine);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001341 }
1342 return res;
1343}
1344
1345EGLint eglGetError(void)
1346{
1347 EGLint result = EGL_SUCCESS;
Mathias Agopian618fa102009-10-14 02:06:37 -07001348 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001349 EGLint err = EGL_SUCCESS;
1350 egl_connection_t* const cnx = &gEGLImpl[i];
1351 if (cnx->dso)
Mathias Agopian618fa102009-10-14 02:06:37 -07001352 err = cnx->egl.eglGetError();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001353 if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
1354 result = err;
1355 }
1356 if (result == EGL_SUCCESS)
1357 result = getError();
1358 return result;
1359}
1360
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001361__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001362{
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001363 // eglGetProcAddress() could be the very first function called
1364 // in which case we must make sure we've initialized ourselves, this
1365 // happens the first time egl_get_display() is called.
Mathias Agopian923c6612009-08-17 18:07:06 -07001366
1367 if (egl_init_drivers() == EGL_FALSE) {
1368 setError(EGL_BAD_PARAMETER, NULL);
1369 return NULL;
1370 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001371
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001372 __eglMustCastToProperFunctionPointerType addr;
1373 addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap));
1374 if (addr) return addr;
1375
Mathias Agopian24035332010-08-02 17:34:32 -07001376 // this protects accesses to gGLExtentionMap and gGLExtentionSlot
1377 pthread_mutex_lock(&gInitDriverMutex);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001378
Mathias Agopian24035332010-08-02 17:34:32 -07001379 /*
1380 * Since eglGetProcAddress() is not associated to anything, it needs
1381 * to return a function pointer that "works" regardless of what
1382 * the current context is.
1383 *
1384 * For this reason, we return a "forwarder", a small stub that takes
1385 * care of calling the function associated with the context
1386 * currently bound.
1387 *
1388 * We first look for extensions we've already resolved, if we're seeing
1389 * this extension for the first time, we go through all our
1390 * implementations and call eglGetProcAddress() and record the
1391 * result in the appropriate implementation hooks and return the
1392 * address of the forwarder corresponding to that hook set.
1393 *
1394 */
1395
1396 const String8 name(procname);
1397 addr = gGLExtentionMap.valueFor(name);
1398 const int slot = gGLExtentionSlot;
1399
1400 LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
1401 "no more slots for eglGetProcAddress(\"%s\")",
1402 procname);
1403
1404 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
1405 bool found = false;
1406 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1407 egl_connection_t* const cnx = &gEGLImpl[i];
1408 if (cnx->dso && cnx->egl.eglGetProcAddress) {
1409 found = true;
Mathias Agopian4a88b522010-08-13 12:19:04 -07001410 // Extensions are independent of the bound context
1411 cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
1412 cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopian24035332010-08-02 17:34:32 -07001413 cnx->egl.eglGetProcAddress(procname);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001414 }
1415 }
Mathias Agopian24035332010-08-02 17:34:32 -07001416 if (found) {
1417 addr = gExtensionForwarders[slot];
1418 gGLExtentionMap.add(name, addr);
1419 gGLExtentionSlot++;
1420 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001421 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001422
Mathias Agopian24035332010-08-02 17:34:32 -07001423 pthread_mutex_unlock(&gInitDriverMutex);
Mathias Agopian24035332010-08-02 17:34:32 -07001424 return addr;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001425}
1426
1427EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
1428{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001429 SurfaceRef _s(draw);
1430 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1431
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001432 if (!validate_display_surface(dpy, draw))
1433 return EGL_FALSE;
1434 egl_display_t const * const dp = get_display(dpy);
1435 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian618fa102009-10-14 02:06:37 -07001436 return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001437}
1438
1439EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1440 NativePixmapType target)
1441{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001442 SurfaceRef _s(surface);
1443 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1444
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001445 if (!validate_display_surface(dpy, surface))
1446 return EGL_FALSE;
1447 egl_display_t const * const dp = get_display(dpy);
1448 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian618fa102009-10-14 02:06:37 -07001449 return s->cnx->egl.eglCopyBuffers(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001450 dp->disp[s->impl].dpy, s->surface, target);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001451}
1452
1453const char* eglQueryString(EGLDisplay dpy, EGLint name)
1454{
1455 egl_display_t const * const dp = get_display(dpy);
1456 switch (name) {
1457 case EGL_VENDOR:
1458 return gVendorString;
1459 case EGL_VERSION:
1460 return gVersionString;
1461 case EGL_EXTENSIONS:
1462 return gExtensionString;
1463 case EGL_CLIENT_APIS:
1464 return gClientApiString;
1465 }
1466 return setError(EGL_BAD_PARAMETER, (const char *)0);
1467}
1468
1469
1470// ----------------------------------------------------------------------------
1471// EGL 1.1
1472// ----------------------------------------------------------------------------
1473
1474EGLBoolean eglSurfaceAttrib(
1475 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1476{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001477 SurfaceRef _s(surface);
1478 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1479
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001480 if (!validate_display_surface(dpy, surface))
1481 return EGL_FALSE;
1482 egl_display_t const * const dp = get_display(dpy);
1483 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian618fa102009-10-14 02:06:37 -07001484 if (s->cnx->egl.eglSurfaceAttrib) {
1485 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001486 dp->disp[s->impl].dpy, s->surface, attribute, value);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001487 }
1488 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1489}
1490
1491EGLBoolean eglBindTexImage(
1492 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1493{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001494 SurfaceRef _s(surface);
1495 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1496
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001497 if (!validate_display_surface(dpy, surface))
1498 return EGL_FALSE;
1499 egl_display_t const * const dp = get_display(dpy);
1500 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian618fa102009-10-14 02:06:37 -07001501 if (s->cnx->egl.eglBindTexImage) {
1502 return s->cnx->egl.eglBindTexImage(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001503 dp->disp[s->impl].dpy, s->surface, buffer);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001504 }
1505 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1506}
1507
1508EGLBoolean eglReleaseTexImage(
1509 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1510{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001511 SurfaceRef _s(surface);
1512 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1513
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001514 if (!validate_display_surface(dpy, surface))
1515 return EGL_FALSE;
1516 egl_display_t const * const dp = get_display(dpy);
1517 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian618fa102009-10-14 02:06:37 -07001518 if (s->cnx->egl.eglReleaseTexImage) {
1519 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001520 dp->disp[s->impl].dpy, s->surface, buffer);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001521 }
1522 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1523}
1524
1525EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1526{
1527 egl_display_t * const dp = get_display(dpy);
1528 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1529
1530 EGLBoolean res = EGL_TRUE;
Mathias Agopian618fa102009-10-14 02:06:37 -07001531 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001532 egl_connection_t* const cnx = &gEGLImpl[i];
1533 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001534 if (cnx->egl.eglSwapInterval) {
1535 if (cnx->egl.eglSwapInterval(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001536 dp->disp[i].dpy, interval) == EGL_FALSE) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001537 res = EGL_FALSE;
1538 }
1539 }
1540 }
1541 }
1542 return res;
1543}
1544
1545
1546// ----------------------------------------------------------------------------
1547// EGL 1.2
1548// ----------------------------------------------------------------------------
1549
1550EGLBoolean eglWaitClient(void)
1551{
Mathias Agopian923c6612009-08-17 18:07:06 -07001552 // could be called before eglInitialize(), but we wouldn't have a context
1553 // then, and this function would return GL_TRUE, which isn't wrong.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001554 EGLBoolean res = EGL_TRUE;
1555 EGLContext ctx = getContext();
1556 if (ctx) {
1557 egl_context_t const * const c = get_context(ctx);
1558 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1559 if (uint32_t(c->impl)>=2)
1560 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1561 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1562 if (!cnx->dso)
1563 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian618fa102009-10-14 02:06:37 -07001564 if (cnx->egl.eglWaitClient) {
1565 res = cnx->egl.eglWaitClient();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001566 } else {
Mathias Agopian618fa102009-10-14 02:06:37 -07001567 res = cnx->egl.eglWaitGL();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001568 }
1569 }
1570 return res;
1571}
1572
1573EGLBoolean eglBindAPI(EGLenum api)
1574{
Mathias Agopian923c6612009-08-17 18:07:06 -07001575 if (egl_init_drivers() == EGL_FALSE) {
1576 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1577 }
1578
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001579 // bind this API on all EGLs
1580 EGLBoolean res = EGL_TRUE;
Mathias Agopian618fa102009-10-14 02:06:37 -07001581 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001582 egl_connection_t* const cnx = &gEGLImpl[i];
1583 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001584 if (cnx->egl.eglBindAPI) {
1585 if (cnx->egl.eglBindAPI(api) == EGL_FALSE) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001586 res = EGL_FALSE;
1587 }
1588 }
1589 }
1590 }
1591 return res;
1592}
1593
1594EGLenum eglQueryAPI(void)
1595{
Mathias Agopian923c6612009-08-17 18:07:06 -07001596 if (egl_init_drivers() == EGL_FALSE) {
1597 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1598 }
1599
Mathias Agopian618fa102009-10-14 02:06:37 -07001600 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001601 egl_connection_t* const cnx = &gEGLImpl[i];
1602 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001603 if (cnx->egl.eglQueryAPI) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001604 // the first one we find is okay, because they all
1605 // should be the same
Mathias Agopian618fa102009-10-14 02:06:37 -07001606 return cnx->egl.eglQueryAPI();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001607 }
1608 }
1609 }
1610 // or, it can only be OpenGL ES
1611 return EGL_OPENGL_ES_API;
1612}
1613
1614EGLBoolean eglReleaseThread(void)
1615{
Mathias Agopian618fa102009-10-14 02:06:37 -07001616 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001617 egl_connection_t* const cnx = &gEGLImpl[i];
1618 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001619 if (cnx->egl.eglReleaseThread) {
1620 cnx->egl.eglReleaseThread();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001621 }
1622 }
1623 }
1624 clearTLS();
1625 return EGL_TRUE;
1626}
1627
1628EGLSurface eglCreatePbufferFromClientBuffer(
1629 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1630 EGLConfig config, const EGLint *attrib_list)
1631{
1632 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -07001633 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001634 if (!cnx) return EGL_FALSE;
Mathias Agopian618fa102009-10-14 02:06:37 -07001635 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1636 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopiancee79392010-07-26 21:14:59 -07001637 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1638 buftype, buffer,
1639 dp->configs[intptr_t(config)].config, attrib_list);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001640 }
1641 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1642}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001643
1644// ----------------------------------------------------------------------------
1645// EGL_EGLEXT_VERSION 3
1646// ----------------------------------------------------------------------------
1647
1648EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1649 const EGLint *attrib_list)
1650{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001651 SurfaceRef _s(surface);
1652 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1653
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001654 if (!validate_display_surface(dpy, surface))
Mathias Agopian24e5f522009-08-12 21:18:15 -07001655 return EGL_FALSE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001656
1657 egl_display_t const * const dp = get_display(dpy);
1658 egl_surface_t const * const s = get_surface(surface);
1659
Mathias Agopian618fa102009-10-14 02:06:37 -07001660 if (s->cnx->egl.eglLockSurfaceKHR) {
1661 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001662 dp->disp[s->impl].dpy, s->surface, attrib_list);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001663 }
Mathias Agopian24e5f522009-08-12 21:18:15 -07001664 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001665}
1666
1667EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1668{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001669 SurfaceRef _s(surface);
1670 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1671
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001672 if (!validate_display_surface(dpy, surface))
Mathias Agopian24e5f522009-08-12 21:18:15 -07001673 return EGL_FALSE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001674
1675 egl_display_t const * const dp = get_display(dpy);
1676 egl_surface_t const * const s = get_surface(surface);
1677
Mathias Agopian618fa102009-10-14 02:06:37 -07001678 if (s->cnx->egl.eglUnlockSurfaceKHR) {
1679 return s->cnx->egl.eglUnlockSurfaceKHR(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001680 dp->disp[s->impl].dpy, s->surface);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001681 }
Mathias Agopian24e5f522009-08-12 21:18:15 -07001682 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001683}
1684
1685EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1686 EGLClientBuffer buffer, const EGLint *attrib_list)
1687{
1688 if (ctx != EGL_NO_CONTEXT) {
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001689 ContextRef _c(ctx);
1690 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001691 if (!validate_display_context(dpy, ctx))
1692 return EGL_NO_IMAGE_KHR;
1693 egl_display_t const * const dp = get_display(dpy);
1694 egl_context_t * const c = get_context(ctx);
1695 // since we have an EGLContext, we know which implementation to use
Mathias Agopian618fa102009-10-14 02:06:37 -07001696 EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001697 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001698 if (image == EGL_NO_IMAGE_KHR)
1699 return image;
1700
1701 egl_image_t* result = new egl_image_t(dpy, ctx);
1702 result->images[c->impl] = image;
1703 return (EGLImageKHR)result;
1704 } else {
1705 // EGL_NO_CONTEXT is a valid parameter
1706 egl_display_t const * const dp = get_display(dpy);
1707 if (dp == 0) {
1708 return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
1709 }
Mathias Agopiandf2d9292009-10-28 21:00:29 -07001710
1711 /* Since we don't have a way to know which implementation to call,
1712 * we're calling all of them. If at least one of the implementation
1713 * succeeded, this is a success.
1714 */
1715
1716 EGLint currentError = eglGetError();
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001717
Mathias Agopian618fa102009-10-14 02:06:37 -07001718 EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS];
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001719 bool success = false;
Mathias Agopian618fa102009-10-14 02:06:37 -07001720 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001721 egl_connection_t* const cnx = &gEGLImpl[i];
1722 implImages[i] = EGL_NO_IMAGE_KHR;
1723 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001724 if (cnx->egl.eglCreateImageKHR) {
1725 implImages[i] = cnx->egl.eglCreateImageKHR(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001726 dp->disp[i].dpy, ctx, target, buffer, attrib_list);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001727 if (implImages[i] != EGL_NO_IMAGE_KHR) {
1728 success = true;
1729 }
1730 }
1731 }
1732 }
Mathias Agopiandf2d9292009-10-28 21:00:29 -07001733
1734 if (!success) {
1735 // failure, if there was an error when we entered this function,
1736 // the error flag must not be updated.
1737 // Otherwise, the error is whatever happened in the implementation
1738 // that faulted.
1739 if (currentError != EGL_SUCCESS) {
1740 setError(currentError, EGL_NO_IMAGE_KHR);
1741 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001742 return EGL_NO_IMAGE_KHR;
Mathias Agopiandf2d9292009-10-28 21:00:29 -07001743 } else {
1744 // In case of success, we need to clear all error flags
1745 // (especially those caused by the implementation that didn't
Mathias Agopian863e5fd2009-10-29 18:29:30 -07001746 // succeed). TODO: we could avoid this if we knew this was
Mathias Agopiandf2d9292009-10-28 21:00:29 -07001747 // a "full" success (all implementation succeeded).
1748 eglGetError();
1749 }
1750
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001751 egl_image_t* result = new egl_image_t(dpy, ctx);
1752 memcpy(result->images, implImages, sizeof(implImages));
1753 return (EGLImageKHR)result;
1754 }
1755}
1756
1757EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1758{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001759 egl_display_t const * const dp = get_display(dpy);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001760 if (dp == 0) {
1761 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1762 }
1763
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001764 ImageRef _i(img);
1765 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001766
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001767 egl_image_t* image = get_image(img);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001768 bool success = false;
Mathias Agopian618fa102009-10-14 02:06:37 -07001769 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001770 egl_connection_t* const cnx = &gEGLImpl[i];
1771 if (image->images[i] != EGL_NO_IMAGE_KHR) {
1772 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001773 if (cnx->egl.eglCreateImageKHR) {
1774 if (cnx->egl.eglDestroyImageKHR(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001775 dp->disp[i].dpy, image->images[i])) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001776 success = true;
1777 }
1778 }
1779 }
1780 }
1781 }
1782 if (!success)
1783 return EGL_FALSE;
1784
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001785 _i.terminate();
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001786
Mathias Agopian24e5f522009-08-12 21:18:15 -07001787 return EGL_TRUE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001788}
Mathias Agopiandf3ca302009-05-04 19:29:25 -07001789
1790
1791// ----------------------------------------------------------------------------
1792// ANDROID extensions
1793// ----------------------------------------------------------------------------
1794
1795EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
1796 EGLint left, EGLint top, EGLint width, EGLint height)
1797{
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001798 SurfaceRef _s(draw);
1799 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1800
Mathias Agopiandf3ca302009-05-04 19:29:25 -07001801 if (!validate_display_surface(dpy, draw))
1802 return EGL_FALSE;
1803 egl_display_t const * const dp = get_display(dpy);
1804 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian618fa102009-10-14 02:06:37 -07001805 if (s->cnx->egl.eglSetSwapRectangleANDROID) {
1806 return s->cnx->egl.eglSetSwapRectangleANDROID(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001807 dp->disp[s->impl].dpy, s->surface, left, top, width, height);
Mathias Agopiandf3ca302009-05-04 19:29:25 -07001808 }
Mathias Agopian24e5f522009-08-12 21:18:15 -07001809 return setError(EGL_BAD_DISPLAY, NULL);
Mathias Agopiandf3ca302009-05-04 19:29:25 -07001810}