blob: aabba28bbb8dbd129146b9bf812dea7676405f29 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 ** Copyright 2007, The Android Open Source Project
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 ** http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017#include <ctype.h>
Mathias Agopian11be99d2009-05-17 18:50:16 -070018#include <stdlib.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080019#include <string.h>
20#include <errno.h>
21#include <dlfcn.h>
22
23#include <sys/ioctl.h>
24
Kenny Rootbb9d3942011-02-16 10:13:53 -080025#ifdef HAVE_ANDROID_OS
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026#include <linux/android_pmem.h>
27#endif
28
29#include <EGL/egl.h>
30#include <EGL/eglext.h>
31#include <GLES/gl.h>
32#include <GLES/glext.h>
33
34#include <cutils/log.h>
35#include <cutils/atomic.h>
36#include <cutils/properties.h>
37#include <cutils/memory.h>
38
Mathias Agopian4a34e882009-08-21 02:18:25 -070039#include <utils/SortedVector.h>
Mathias Agopian3944eab2010-08-02 17:34:32 -070040#include <utils/KeyedVector.h>
41#include <utils/String8.h>
Mathias Agopian4a34e882009-08-21 02:18:25 -070042
Mathias Agopian698a8aa2010-11-24 15:59:35 -080043#include <ui/egl/android_natives.h>
44
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045#include "hooks.h"
46#include "egl_impl.h"
Mathias Agopian9d17c052009-05-28 17:39:03 -070047#include "Loader.h"
David Li5c425f22011-03-10 16:40:37 -080048#include "glesv2dbg.h"
David Lice30eb82011-03-28 10:39:28 -070049#include "egl_tls.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051#define setError(_e, _r) setErrorEtc(__FUNCTION__, __LINE__, _e, _r)
52
53// ----------------------------------------------------------------------------
54namespace android {
55// ----------------------------------------------------------------------------
56
57#define VERSION_MAJOR 1
58#define VERSION_MINOR 4
59static char const * const gVendorString = "Android";
Mathias Agopiandcebf6f2009-08-17 18:07:06 -070060static char const * const gVersionString = "1.4 Android META-EGL";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061static char const * const gClientApiString = "OpenGL ES";
David Lice30eb82011-03-28 10:39:28 -070062static char const * const gExtensionString =
Mathias Agopian1473f462009-04-10 14:24:30 -070063 "EGL_KHR_image "
Mathias Agopian927d37c2009-05-06 23:47:08 -070064 "EGL_KHR_image_base "
65 "EGL_KHR_image_pixmap "
Mathias Agopianb20a4b92010-08-27 16:08:03 -070066 "EGL_KHR_gl_texture_2D_image "
Michael I. Gold3ece0102011-01-13 10:13:15 -080067 "EGL_KHR_gl_texture_cubemap_image "
68 "EGL_KHR_gl_renderbuffer_image "
Mathias Agopian9ca8a842010-08-27 16:48:56 -070069 "EGL_KHR_fence_sync "
Mathias Agopian1473f462009-04-10 14:24:30 -070070 "EGL_ANDROID_image_native_buffer "
Mathias Agopian2e20bff2009-05-04 19:29:25 -070071 "EGL_ANDROID_swap_rectangle "
Mathias Agopian1473f462009-04-10 14:24:30 -070072 ;
73
74// ----------------------------------------------------------------------------
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075
Eric Hassold8caf4c62011-03-25 11:26:02 -070076class egl_object_t;
77struct egl_display_t;
78static egl_display_t* get_display(EGLDisplay dpy);
Mathias Agopian4a34e882009-08-21 02:18:25 -070079
Eric Hassold8caf4c62011-03-25 11:26:02 -070080struct egl_config_t {
81 egl_config_t() {}
82 egl_config_t(int impl, EGLConfig config)
83 : impl(impl), config(config), configId(0), implConfigId(0) { }
84 int impl; // the implementation this config is for
85 EGLConfig config; // the implementation's EGLConfig
86 EGLint configId; // our CONFIG_ID
87 EGLint implConfigId; // the implementation's CONFIG_ID
88 inline bool operator < (const egl_config_t& rhs) const {
89 if (impl < rhs.impl) return true;
90 if (impl > rhs.impl) return false;
91 return config < rhs.config;
92 }
93};
94
95struct egl_display_t {
96 enum { NOT_INITIALIZED, INITIALIZED, TERMINATED };
97
98 struct strings_t {
99 char const * vendor;
100 char const * version;
101 char const * clientApi;
102 char const * extensions;
103 };
104
105 struct DisplayImpl {
106 DisplayImpl() : dpy(EGL_NO_DISPLAY), config(0),
107 state(NOT_INITIALIZED), numConfigs(0) { }
108 EGLDisplay dpy;
109 EGLConfig* config;
110 EGLint state;
111 EGLint numConfigs;
112 strings_t queryString;
113 };
114
115 uint32_t magic;
116 DisplayImpl disp[IMPL_NUM_IMPLEMENTATIONS];
117 EGLint numTotalConfigs;
118 egl_config_t* configs;
119 uint32_t refs;
120 Mutex lock;
121
122 SortedVector<egl_object_t*> objects;
123
Eric Hassold8bdf09b2011-03-31 16:52:02 -0700124 egl_display_t() : magic('_dpy'), numTotalConfigs(0), configs(0), refs(0) { }
Eric Hassold8caf4c62011-03-25 11:26:02 -0700125 ~egl_display_t() { magic = 0; }
126 inline bool isReady() const { return (refs > 0); }
127 inline bool isValid() const { return magic == '_dpy'; }
128 inline bool isAlive() const { return isValid(); }
129};
130
131class egl_object_t {
132 egl_display_t *display;
Mathias Agopian4a34e882009-08-21 02:18:25 -0700133 volatile int32_t terminated;
134 mutable volatile int32_t count;
135
136public:
Eric Hassold8caf4c62011-03-25 11:26:02 -0700137 egl_object_t(EGLDisplay dpy) : display(get_display(dpy)), terminated(0), count(1) {
138 Mutex::Autolock _l(display->lock);
139 display->objects.add(this);
Mathias Agopian4a34e882009-08-21 02:18:25 -0700140 }
141
142 inline bool isAlive() const { return !terminated; }
143
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144private:
Mathias Agopian4a34e882009-08-21 02:18:25 -0700145 bool get() {
Eric Hassold8caf4c62011-03-25 11:26:02 -0700146 Mutex::Autolock _l(display->lock);
147 if (display->objects.indexOf(this) >= 0) {
Mathias Agopian4a34e882009-08-21 02:18:25 -0700148 android_atomic_inc(&count);
149 return true;
150 }
151 return false;
152 }
153
154 bool put() {
Eric Hassold8caf4c62011-03-25 11:26:02 -0700155 Mutex::Autolock _l(display->lock);
Mathias Agopian4a34e882009-08-21 02:18:25 -0700156 if (android_atomic_dec(&count) == 1) {
Eric Hassold8caf4c62011-03-25 11:26:02 -0700157 display->objects.remove(this);
Mathias Agopian4a34e882009-08-21 02:18:25 -0700158 return true;
159 }
160 return false;
161 }
162
163public:
164 template <typename N, typename T>
165 struct LocalRef {
166 N* ref;
167 LocalRef(T o) : ref(0) {
168 N* native = reinterpret_cast<N*>(o);
169 if (o && native->get()) {
170 ref = native;
171 }
172 }
173 ~LocalRef() {
174 if (ref && ref->put()) {
175 delete ref;
176 }
177 }
178 inline N* get() {
179 return ref;
180 }
181 void acquire() const {
182 if (ref) {
183 android_atomic_inc(&ref->count);
184 }
185 }
186 void release() const {
187 if (ref) {
188 int32_t c = android_atomic_dec(&ref->count);
189 // ref->count cannot be 1 prior atomic_dec because we have
190 // a reference, and if we have one, it means there was
191 // already one before us.
192 LOGE_IF(c==1, "refcount is now 0 in release()");
193 }
194 }
195 void terminate() {
196 if (ref) {
197 ref->terminated = 1;
198 release();
199 }
200 }
201 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202};
203
Mathias Agopian4a34e882009-08-21 02:18:25 -0700204struct egl_surface_t : public egl_object_t
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205{
Mathias Agopian4a34e882009-08-21 02:18:25 -0700206 typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
207
Mathias Agopian698a8aa2010-11-24 15:59:35 -0800208 egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win,
209 EGLSurface surface, int impl, egl_connection_t const* cnx)
Eric Hassold8caf4c62011-03-25 11:26:02 -0700210 : egl_object_t(dpy), dpy(dpy), surface(surface), config(config), win(win), impl(impl), cnx(cnx) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 }
212 ~egl_surface_t() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213 }
214 EGLDisplay dpy;
215 EGLSurface surface;
Mathias Agopian3ad6c442010-07-26 21:14:59 -0700216 EGLConfig config;
Mathias Agopian698a8aa2010-11-24 15:59:35 -0800217 sp<ANativeWindow> win;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 int impl;
219 egl_connection_t const* cnx;
220};
221
Mathias Agopian4a34e882009-08-21 02:18:25 -0700222struct egl_context_t : public egl_object_t
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223{
Mathias Agopian4a34e882009-08-21 02:18:25 -0700224 typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
David Lice30eb82011-03-28 10:39:28 -0700225
Mathias Agopian3ad6c442010-07-26 21:14:59 -0700226 egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
David Lice30eb82011-03-28 10:39:28 -0700227 int impl, egl_connection_t const* cnx, int version)
228 : egl_object_t(dpy), dpy(dpy), context(context), config(config), read(0), draw(0),
229 impl(impl), cnx(cnx), version(version)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 {
231 }
David Li5c425f22011-03-10 16:40:37 -0800232 ~egl_context_t()
233 {
David Li5c425f22011-03-10 16:40:37 -0800234 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 EGLDisplay dpy;
236 EGLContext context;
Mathias Agopian3ad6c442010-07-26 21:14:59 -0700237 EGLConfig config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 EGLSurface read;
239 EGLSurface draw;
240 int impl;
241 egl_connection_t const* cnx;
Mathias Agopian6fc56992009-10-14 02:06:37 -0700242 int version;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243};
244
Mathias Agopian4a34e882009-08-21 02:18:25 -0700245struct egl_image_t : public egl_object_t
Mathias Agopian1473f462009-04-10 14:24:30 -0700246{
Mathias Agopian4a34e882009-08-21 02:18:25 -0700247 typedef egl_object_t::LocalRef<egl_image_t, EGLImageKHR> Ref;
248
Mathias Agopian1473f462009-04-10 14:24:30 -0700249 egl_image_t(EGLDisplay dpy, EGLContext context)
Eric Hassold8caf4c62011-03-25 11:26:02 -0700250 : egl_object_t(dpy), dpy(dpy), context(context)
Mathias Agopian1473f462009-04-10 14:24:30 -0700251 {
252 memset(images, 0, sizeof(images));
253 }
254 EGLDisplay dpy;
Mathias Agopian97961db2010-09-09 11:12:54 -0700255 EGLContext context;
Mathias Agopian6fc56992009-10-14 02:06:37 -0700256 EGLImageKHR images[IMPL_NUM_IMPLEMENTATIONS];
Mathias Agopian1473f462009-04-10 14:24:30 -0700257};
258
Mathias Agopian9ca8a842010-08-27 16:48:56 -0700259struct egl_sync_t : public egl_object_t
260{
261 typedef egl_object_t::LocalRef<egl_sync_t, EGLSyncKHR> Ref;
262
263 egl_sync_t(EGLDisplay dpy, EGLContext context, EGLSyncKHR sync)
Eric Hassold8caf4c62011-03-25 11:26:02 -0700264 : egl_object_t(dpy), dpy(dpy), context(context), sync(sync)
Mathias Agopian9ca8a842010-08-27 16:48:56 -0700265 {
266 }
267 EGLDisplay dpy;
268 EGLContext context;
269 EGLSyncKHR sync;
270};
271
Mathias Agopian4a34e882009-08-21 02:18:25 -0700272typedef egl_surface_t::Ref SurfaceRef;
273typedef egl_context_t::Ref ContextRef;
274typedef egl_image_t::Ref ImageRef;
Mathias Agopian9ca8a842010-08-27 16:48:56 -0700275typedef egl_sync_t::Ref SyncRef;
Mathias Agopian4a34e882009-08-21 02:18:25 -0700276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277// ----------------------------------------------------------------------------
278
Mathias Agopiane5478352010-04-09 13:37:34 -0700279static egl_connection_t gEGLImpl[IMPL_NUM_IMPLEMENTATIONS];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280static egl_display_t gDisplay[NUM_DISPLAYS];
281static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER;
282static pthread_key_t gEGLThreadLocalStorageKey = -1;
283
284// ----------------------------------------------------------------------------
285
Mathias Agopian6fc56992009-10-14 02:06:37 -0700286EGLAPI gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS];
287EGLAPI gl_hooks_t gHooksNoContext;
Mathias Agopian3cc68d22009-05-13 00:19:22 -0700288EGLAPI pthread_key_t gGLWrapperKey = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700290#if EGL_TRACE
291
292EGLAPI pthread_key_t gGLTraceKey = -1;
293
294// ----------------------------------------------------------------------------
295
David Li28ca2ab2011-03-01 16:08:10 -0800296static int gEGLTraceLevel, gEGLDebugLevel;
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700297static int gEGLApplicationTraceLevel;
David Li28ca2ab2011-03-01 16:08:10 -0800298extern EGLAPI gl_hooks_t gHooksTrace, gHooksDebug;
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700299
300static inline void setGlTraceThreadSpecific(gl_hooks_t const *value) {
301 pthread_setspecific(gGLTraceKey, value);
302}
303
304gl_hooks_t const* getGLTraceThreadSpecific() {
305 return static_cast<gl_hooks_t*>(pthread_getspecific(gGLTraceKey));
306}
307
308static void initEglTraceLevel() {
309 char value[PROPERTY_VALUE_MAX];
310 property_get("debug.egl.trace", value, "0");
311 int propertyLevel = atoi(value);
312 int applicationLevel = gEGLApplicationTraceLevel;
313 gEGLTraceLevel = propertyLevel > applicationLevel ? propertyLevel : applicationLevel;
David Li27f130a2011-04-08 18:43:16 -0700314
David Li28ca2ab2011-03-01 16:08:10 -0800315 property_get("debug.egl.debug_proc", value, "");
316 long pid = getpid();
317 char procPath[128] = {};
318 sprintf(procPath, "/proc/%ld/cmdline", pid);
319 FILE * file = fopen(procPath, "r");
320 if (file)
321 {
322 char cmdline[256] = {};
323 if (fgets(cmdline, sizeof(cmdline) - 1, file))
324 {
David Li28ca2ab2011-03-01 16:08:10 -0800325 if (!strcmp(value, cmdline))
326 gEGLDebugLevel = 1;
David Li27f130a2011-04-08 18:43:16 -0700327 }
David Li28ca2ab2011-03-01 16:08:10 -0800328 fclose(file);
329 }
David Li27f130a2011-04-08 18:43:16 -0700330
David Li28ca2ab2011-03-01 16:08:10 -0800331 if (gEGLDebugLevel > 0)
David Li940c3f82011-03-10 19:07:42 -0800332 {
333 property_get("debug.egl.debug_port", value, "5039");
David Li27f130a2011-04-08 18:43:16 -0700334 const unsigned short port = (unsigned short)atoi(value);
335 property_get("debug.egl.debug_forceUseFile", value, "0");
336 const bool forceUseFile = (bool)atoi(value);
337 property_get("debug.egl.debug_maxFileSize", value, "8");
338 const unsigned int maxFileSize = atoi(value) << 20;
339 property_get("debug.egl.debug_filePath", value, "/data/local/tmp/dump.gles2dbg");
340 StartDebugServer(port, forceUseFile, maxFileSize, value);
David Li940c3f82011-03-10 19:07:42 -0800341 }
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700342}
343
344static void setGLHooksThreadSpecific(gl_hooks_t const *value) {
345 if (gEGLTraceLevel > 0) {
346 setGlTraceThreadSpecific(value);
347 setGlThreadSpecific(&gHooksTrace);
David Li5c425f22011-03-10 16:40:37 -0800348 } else if (gEGLDebugLevel > 0 && value != &gHooksNoContext) {
David Li28ca2ab2011-03-01 16:08:10 -0800349 setGlTraceThreadSpecific(value);
350 setGlThreadSpecific(&gHooksDebug);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700351 } else {
352 setGlThreadSpecific(value);
353 }
354}
355
356/*
357 * Global entry point to allow applications to modify their own trace level.
358 * The effective trace level is the max of this level and the value of debug.egl.trace.
359 */
360extern "C"
361void setGLTraceLevel(int level) {
362 gEGLApplicationTraceLevel = level;
363}
364
365#else
366
367static inline void setGLHooksThreadSpecific(gl_hooks_t const *value) {
368 setGlThreadSpecific(value);
369}
370
371#endif
372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800373// ----------------------------------------------------------------------------
374
375static __attribute__((noinline))
376const char *egl_strerror(EGLint err)
377{
378 switch (err){
379 case EGL_SUCCESS: return "EGL_SUCCESS";
380 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
381 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
382 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
383 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
384 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
385 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
386 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
387 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
388 case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
389 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
390 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
391 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
392 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
393 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
394 default: return "UNKNOWN";
395 }
396}
397
398static __attribute__((noinline))
399void clearTLS() {
400 if (gEGLThreadLocalStorageKey != -1) {
401 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
402 if (tls) {
403 delete tls;
404 pthread_setspecific(gEGLThreadLocalStorageKey, 0);
405 }
406 }
407}
408
409static tls_t* getTLS()
410{
411 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
412 if (tls == 0) {
413 tls = new tls_t;
414 pthread_setspecific(gEGLThreadLocalStorageKey, tls);
415 }
416 return tls;
417}
418
Michael I. Golde7ff5dd2011-01-21 15:39:38 -0800419static inline void clearError() {
Jamie Gennise3b179c2011-01-30 16:50:04 -0800420 // This must clear the error from all the underlying EGL implementations as
421 // well as the EGL wrapper layer.
422 eglGetError();
Michael I. Golde7ff5dd2011-01-21 15:39:38 -0800423}
424
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425template<typename T>
426static __attribute__((noinline))
427T setErrorEtc(const char* caller, int line, EGLint error, T returnValue) {
428 if (gEGLThreadLocalStorageKey == -1) {
429 pthread_mutex_lock(&gThreadLocalStorageKeyMutex);
430 if (gEGLThreadLocalStorageKey == -1)
431 pthread_key_create(&gEGLThreadLocalStorageKey, NULL);
432 pthread_mutex_unlock(&gThreadLocalStorageKeyMutex);
433 }
434 tls_t* tls = getTLS();
435 if (tls->error != error) {
436 LOGE("%s:%d error %x (%s)", caller, line, error, egl_strerror(error));
437 tls->error = error;
438 }
439 return returnValue;
440}
441
442static __attribute__((noinline))
443GLint getError() {
444 if (gEGLThreadLocalStorageKey == -1)
445 return EGL_SUCCESS;
446 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
447 if (!tls) return EGL_SUCCESS;
448 GLint error = tls->error;
449 tls->error = EGL_SUCCESS;
450 return error;
451}
452
453static __attribute__((noinline))
454void setContext(EGLContext ctx) {
455 if (gEGLThreadLocalStorageKey == -1) {
456 pthread_mutex_lock(&gThreadLocalStorageKeyMutex);
457 if (gEGLThreadLocalStorageKey == -1)
458 pthread_key_create(&gEGLThreadLocalStorageKey, NULL);
459 pthread_mutex_unlock(&gThreadLocalStorageKeyMutex);
460 }
461 tls_t* tls = getTLS();
462 tls->ctx = ctx;
463}
464
465static __attribute__((noinline))
466EGLContext getContext() {
467 if (gEGLThreadLocalStorageKey == -1)
468 return EGL_NO_CONTEXT;
469 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
470 if (!tls) return EGL_NO_CONTEXT;
471 return tls->ctx;
472}
473
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800474/*****************************************************************************/
475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800476template<typename T>
477static __attribute__((noinline))
478int binarySearch(
479 T const sortedArray[], int first, int last, T key)
480{
481 while (first <= last) {
482 int mid = (first + last) / 2;
Mathias Agopian3ad6c442010-07-26 21:14:59 -0700483 if (sortedArray[mid] < key) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800484 first = mid + 1;
485 } else if (key < sortedArray[mid]) {
486 last = mid - 1;
487 } else {
488 return mid;
489 }
490 }
491 return -1;
492}
493
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800494static int cmp_configs(const void* a, const void *b)
495{
Mathias Agopian3ad6c442010-07-26 21:14:59 -0700496 const egl_config_t& c0 = *(egl_config_t const *)a;
497 const egl_config_t& c1 = *(egl_config_t const *)b;
498 return c0<c1 ? -1 : (c1<c0 ? 1 : 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800499}
500
501struct extention_map_t {
502 const char* name;
503 __eglMustCastToProperFunctionPointerType address;
504};
505
506static const extention_map_t gExtentionMap[] = {
Mathias Agopian1473f462009-04-10 14:24:30 -0700507 { "eglLockSurfaceKHR",
508 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
509 { "eglUnlockSurfaceKHR",
510 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
511 { "eglCreateImageKHR",
512 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
513 { "eglDestroyImageKHR",
514 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Mathias Agopianc1e3ec52009-06-24 22:37:39 -0700515 { "eglSetSwapRectangleANDROID",
516 (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800517};
518
Mathias Agopian3944eab2010-08-02 17:34:32 -0700519extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
520
521// accesses protected by gInitDriverMutex
522static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> gGLExtentionMap;
523static int gGLExtentionSlot = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800524
525static void(*findProcAddress(const char* name,
526 const extention_map_t* map, size_t n))()
527{
528 for (uint32_t i=0 ; i<n ; i++) {
529 if (!strcmp(name, map[i].name)) {
530 return map[i].address;
531 }
532 }
533 return NULL;
534}
535
536// ----------------------------------------------------------------------------
537
Mathias Agopian25b388c2010-09-23 16:38:38 -0700538static int gl_no_context() {
Mathias Agopian997d1072009-07-31 16:21:17 -0700539 tls_t* tls = getTLS();
540 if (tls->logCallWithNoContext == EGL_TRUE) {
541 tls->logCallWithNoContext = EGL_FALSE;
542 LOGE("call to OpenGL ES API with no current context "
543 "(logged once per thread)");
544 }
Mathias Agopian25b388c2010-09-23 16:38:38 -0700545 return 0;
Mathias Agopian5c6c5c72010-09-23 11:32:52 -0700546}
547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800548static void early_egl_init(void)
549{
550#if !USE_FAST_TLS_KEY
551 pthread_key_create(&gGLWrapperKey, NULL);
552#endif
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700553#if EGL_TRACE
554 pthread_key_create(&gGLTraceKey, NULL);
555 initEglTraceLevel();
556#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800557 uint32_t addr = (uint32_t)((void*)gl_no_context);
558 android_memset32(
Mathias Agopian6fc56992009-10-14 02:06:37 -0700559 (uint32_t*)(void*)&gHooksNoContext,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800560 addr,
Mathias Agopian6fc56992009-10-14 02:06:37 -0700561 sizeof(gHooksNoContext));
Mathias Agopian5c6c5c72010-09-23 11:32:52 -0700562
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700563 setGLHooksThreadSpecific(&gHooksNoContext);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800564}
565
566static pthread_once_t once_control = PTHREAD_ONCE_INIT;
567static int sEarlyInitState = pthread_once(&once_control, &early_egl_init);
568
569
570static inline
571egl_display_t* get_display(EGLDisplay dpy)
572{
573 uintptr_t index = uintptr_t(dpy)-1U;
574 return (index >= NUM_DISPLAYS) ? NULL : &gDisplay[index];
575}
576
Mathias Agopian1473f462009-04-10 14:24:30 -0700577template<typename NATIVE, typename EGL>
578static inline NATIVE* egl_to_native_cast(EGL arg) {
579 return reinterpret_cast<NATIVE*>(arg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580}
581
582static inline
David Lice30eb82011-03-28 10:39:28 -0700583egl_surface_t* get_surface(EGLSurface surface) {
Mathias Agopian1473f462009-04-10 14:24:30 -0700584 return egl_to_native_cast<egl_surface_t>(surface);
585}
586
587static inline
588egl_context_t* get_context(EGLContext context) {
589 return egl_to_native_cast<egl_context_t>(context);
590}
591
592static inline
593egl_image_t* get_image(EGLImageKHR image) {
594 return egl_to_native_cast<egl_image_t>(image);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595}
596
Mathias Agopian9ca8a842010-08-27 16:48:56 -0700597static inline
598egl_sync_t* get_sync(EGLSyncKHR sync) {
599 return egl_to_native_cast<egl_sync_t>(sync);
600}
601
Eric Hassold2a790ac2011-03-23 15:59:00 -0700602static inline
603egl_display_t* validate_display(EGLDisplay dpy)
604{
605 egl_display_t * const dp = get_display(dpy);
606 if (!dp) return setError(EGL_BAD_DISPLAY, (egl_display_t*)NULL);
607 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, (egl_display_t*)NULL);
608
609 return dp;
610}
611
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800612static egl_connection_t* validate_display_config(
613 EGLDisplay dpy, EGLConfig config,
Mathias Agopian3ad6c442010-07-26 21:14:59 -0700614 egl_display_t const*& dp)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800615{
Eric Hassold2a790ac2011-03-23 15:59:00 -0700616 dp = validate_display(dpy);
617 if (!dp) return (egl_connection_t*) NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800618
Mathias Agopian3ad6c442010-07-26 21:14:59 -0700619 if (intptr_t(config) >= dp->numTotalConfigs) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800620 return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
621 }
Mathias Agopian3ad6c442010-07-26 21:14:59 -0700622 egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(config)].impl];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623 if (cnx->dso == 0) {
624 return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
625 }
626 return cnx;
627}
628
629static EGLBoolean validate_display_context(EGLDisplay dpy, EGLContext ctx)
630{
Eric Hassold2a790ac2011-03-23 15:59:00 -0700631 egl_display_t const * const dp = validate_display(dpy);
632 if (!dp) return EGL_FALSE;
633 if (!dp->isAlive())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800634 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian4a34e882009-08-21 02:18:25 -0700635 if (!get_context(ctx)->isAlive())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800636 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
637 return EGL_TRUE;
638}
639
640static EGLBoolean validate_display_surface(EGLDisplay dpy, EGLSurface surface)
641{
Eric Hassold2a790ac2011-03-23 15:59:00 -0700642 egl_display_t const * const dp = validate_display(dpy);
643 if (!dp) return EGL_FALSE;
644 if (!dp->isAlive())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800645 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian4a34e882009-08-21 02:18:25 -0700646 if (!get_surface(surface)->isAlive())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800647 return setError(EGL_BAD_SURFACE, EGL_FALSE);
648 return EGL_TRUE;
649}
650
Mathias Agopian1473f462009-04-10 14:24:30 -0700651EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image)
652{
Mathias Agopian4a34e882009-08-21 02:18:25 -0700653 ImageRef _i(image);
654 if (!_i.get()) return EGL_NO_IMAGE_KHR;
655
Mathias Agopian1473f462009-04-10 14:24:30 -0700656 EGLContext context = getContext();
657 if (context == EGL_NO_CONTEXT || image == EGL_NO_IMAGE_KHR)
658 return EGL_NO_IMAGE_KHR;
659
660 egl_context_t const * const c = get_context(context);
Mathias Agopian4a34e882009-08-21 02:18:25 -0700661 if (!c->isAlive())
Mathias Agopian1473f462009-04-10 14:24:30 -0700662 return EGL_NO_IMAGE_KHR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800663
Mathias Agopian1473f462009-04-10 14:24:30 -0700664 egl_image_t const * const i = get_image(image);
Mathias Agopian1473f462009-04-10 14:24:30 -0700665 return i->images[c->impl];
666}
667
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700668// ----------------------------------------------------------------------------
Mathias Agopian1473f462009-04-10 14:24:30 -0700669
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700670// this mutex protects:
Mathias Agopian94263d72009-08-24 21:47:13 -0700671// d->disp[]
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700672// egl_init_drivers_locked()
673//
674static pthread_mutex_t gInitDriverMutex = PTHREAD_MUTEX_INITIALIZER;
675
676EGLBoolean egl_init_drivers_locked()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800677{
678 if (sEarlyInitState) {
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700679 // initialized by static ctor. should be set here.
680 return EGL_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681 }
682
Mathias Agopian9d17c052009-05-28 17:39:03 -0700683 // get our driver loader
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700684 Loader& loader(Loader::getInstance());
Mathias Agopian9d17c052009-05-28 17:39:03 -0700685
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700686 // dynamically load all our EGL implementations for all displays
687 // and retrieve the corresponding EGLDisplay
688 // if that fails, don't use this driver.
689 // TODO: currently we only deal with EGL_DEFAULT_DISPLAY
690 egl_connection_t* cnx;
691 egl_display_t* d = &gDisplay[0];
692
693 cnx = &gEGLImpl[IMPL_SOFTWARE];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694 if (cnx->dso == 0) {
Mathias Agopian6fc56992009-10-14 02:06:37 -0700695 cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_SOFTWARE];
696 cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_SOFTWARE];
697 cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 0, cnx);
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700698 if (cnx->dso) {
Mathias Agopian6fc56992009-10-14 02:06:37 -0700699 EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700700 LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for software EGL!");
Mathias Agopian94263d72009-08-24 21:47:13 -0700701 d->disp[IMPL_SOFTWARE].dpy = dpy;
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700702 if (dpy == EGL_NO_DISPLAY) {
703 loader.close(cnx->dso);
704 cnx->dso = NULL;
705 }
706 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800707 }
708
709 cnx = &gEGLImpl[IMPL_HARDWARE];
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700710 if (cnx->dso == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711 char value[PROPERTY_VALUE_MAX];
712 property_get("debug.egl.hw", value, "1");
713 if (atoi(value) != 0) {
Mathias Agopian6fc56992009-10-14 02:06:37 -0700714 cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_HARDWARE];
715 cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_HARDWARE];
716 cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 1, cnx);
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700717 if (cnx->dso) {
Mathias Agopian6fc56992009-10-14 02:06:37 -0700718 EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700719 LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for hardware EGL!");
Mathias Agopian94263d72009-08-24 21:47:13 -0700720 d->disp[IMPL_HARDWARE].dpy = dpy;
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700721 if (dpy == EGL_NO_DISPLAY) {
722 loader.close(cnx->dso);
723 cnx->dso = NULL;
724 }
725 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800726 } else {
727 LOGD("3D hardware acceleration is disabled");
728 }
729 }
Mathias Agopian94263d72009-08-24 21:47:13 -0700730
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700731 if (!gEGLImpl[IMPL_SOFTWARE].dso && !gEGLImpl[IMPL_HARDWARE].dso) {
732 return EGL_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800733 }
734
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700735 return EGL_TRUE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800736}
737
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700738EGLBoolean egl_init_drivers()
739{
740 EGLBoolean res;
741 pthread_mutex_lock(&gInitDriverMutex);
742 res = egl_init_drivers_locked();
743 pthread_mutex_unlock(&gInitDriverMutex);
744 return res;
745}
Mathias Agopian1473f462009-04-10 14:24:30 -0700746
747// ----------------------------------------------------------------------------
748}; // namespace android
749// ----------------------------------------------------------------------------
750
751using namespace android;
752
753EGLDisplay eglGetDisplay(NativeDisplayType display)
754{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -0800755 clearError();
756
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700757 uint32_t index = uint32_t(display);
758 if (index >= NUM_DISPLAYS) {
759 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
760 }
761
762 if (egl_init_drivers() == EGL_FALSE) {
763 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
764 }
765
766 EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU);
767 return dpy;
Mathias Agopian1473f462009-04-10 14:24:30 -0700768}
769
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800770// ----------------------------------------------------------------------------
771// Initialization
772// ----------------------------------------------------------------------------
773
774EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
775{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -0800776 clearError();
777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800778 egl_display_t * const dp = get_display(dpy);
779 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
780
Mathias Agopian6099ab72010-02-05 16:17:01 -0800781 Mutex::Autolock _l(dp->lock);
782
783 if (dp->refs > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 if (major != NULL) *major = VERSION_MAJOR;
785 if (minor != NULL) *minor = VERSION_MINOR;
Jack Palevich0a41c3c2010-03-15 20:45:21 -0700786 dp->refs++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 return EGL_TRUE;
788 }
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700789
790#if EGL_TRACE
791
792 // Called both at early_init time and at this time. (Early_init is pre-zygote, so
793 // the information from that call may be stale.)
794 initEglTraceLevel();
795
796#endif
797
798 setGLHooksThreadSpecific(&gHooksNoContext);
799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800800 // initialize each EGL and
801 // build our own extension string first, based on the extension we know
802 // and the extension supported by our client implementation
Mathias Agopian6fc56992009-10-14 02:06:37 -0700803 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800804 egl_connection_t* const cnx = &gEGLImpl[i];
805 cnx->major = -1;
806 cnx->minor = -1;
807 if (!cnx->dso)
808 continue;
809
Mathias Agopian94263d72009-08-24 21:47:13 -0700810#if defined(ADRENO130)
811#warning "Adreno-130 eglInitialize() workaround"
812 /*
813 * The ADRENO 130 driver returns a different EGLDisplay each time
814 * eglGetDisplay() is called, but also makes the EGLDisplay invalid
815 * after eglTerminate() has been called, so that eglInitialize()
816 * cannot be called again. Therefore, we need to make sure to call
817 * eglGetDisplay() before calling eglInitialize();
818 */
819 if (i == IMPL_HARDWARE) {
820 dp->disp[i].dpy =
Mathias Agopian6fc56992009-10-14 02:06:37 -0700821 cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
Mathias Agopian94263d72009-08-24 21:47:13 -0700822 }
823#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800824
Mathias Agopian94263d72009-08-24 21:47:13 -0700825
826 EGLDisplay idpy = dp->disp[i].dpy;
Mathias Agopian6fc56992009-10-14 02:06:37 -0700827 if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828 //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p",
Mathias Agopian94263d72009-08-24 21:47:13 -0700829 // i, idpy, cnx->major, cnx->minor, cnx);
830
831 // display is now initialized
832 dp->disp[i].state = egl_display_t::INITIALIZED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800833
834 // get the query-strings for this display for each implementation
Mathias Agopian94263d72009-08-24 21:47:13 -0700835 dp->disp[i].queryString.vendor =
Mathias Agopian6fc56992009-10-14 02:06:37 -0700836 cnx->egl.eglQueryString(idpy, EGL_VENDOR);
Mathias Agopian94263d72009-08-24 21:47:13 -0700837 dp->disp[i].queryString.version =
Mathias Agopian6fc56992009-10-14 02:06:37 -0700838 cnx->egl.eglQueryString(idpy, EGL_VERSION);
Mathias Agopian94263d72009-08-24 21:47:13 -0700839 dp->disp[i].queryString.extensions =
Mathias Agopian6fc56992009-10-14 02:06:37 -0700840 cnx->egl.eglQueryString(idpy, EGL_EXTENSIONS);
Mathias Agopian94263d72009-08-24 21:47:13 -0700841 dp->disp[i].queryString.clientApi =
Mathias Agopian6fc56992009-10-14 02:06:37 -0700842 cnx->egl.eglQueryString(idpy, EGL_CLIENT_APIS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800843
844 } else {
Mathias Agopian94263d72009-08-24 21:47:13 -0700845 LOGW("%d: eglInitialize(%p) failed (%s)", i, idpy,
Mathias Agopian6fc56992009-10-14 02:06:37 -0700846 egl_strerror(cnx->egl.eglGetError()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800847 }
848 }
849
850 EGLBoolean res = EGL_FALSE;
Mathias Agopian6fc56992009-10-14 02:06:37 -0700851 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800852 egl_connection_t* const cnx = &gEGLImpl[i];
853 if (cnx->dso && cnx->major>=0 && cnx->minor>=0) {
854 EGLint n;
Mathias Agopian6fc56992009-10-14 02:06:37 -0700855 if (cnx->egl.eglGetConfigs(dp->disp[i].dpy, 0, 0, &n)) {
Mathias Agopian94263d72009-08-24 21:47:13 -0700856 dp->disp[i].config = (EGLConfig*)malloc(sizeof(EGLConfig)*n);
857 if (dp->disp[i].config) {
Mathias Agopian6fc56992009-10-14 02:06:37 -0700858 if (cnx->egl.eglGetConfigs(
Mathias Agopian94263d72009-08-24 21:47:13 -0700859 dp->disp[i].dpy, dp->disp[i].config, n,
860 &dp->disp[i].numConfigs))
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800861 {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800862 dp->numTotalConfigs += n;
863 res = EGL_TRUE;
864 }
865 }
866 }
867 }
868 }
869
870 if (res == EGL_TRUE) {
Mathias Agopian3ad6c442010-07-26 21:14:59 -0700871 dp->configs = new egl_config_t[ dp->numTotalConfigs ];
872 for (int i=0, k=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
873 egl_connection_t* const cnx = &gEGLImpl[i];
874 if (cnx->dso && cnx->major>=0 && cnx->minor>=0) {
875 for (int j=0 ; j<dp->disp[i].numConfigs ; j++) {
876 dp->configs[k].impl = i;
877 dp->configs[k].config = dp->disp[i].config[j];
878 dp->configs[k].configId = k + 1; // CONFIG_ID start at 1
879 // store the implementation's CONFIG_ID
880 cnx->egl.eglGetConfigAttrib(
881 dp->disp[i].dpy,
882 dp->disp[i].config[j],
883 EGL_CONFIG_ID,
884 &dp->configs[k].implConfigId);
885 k++;
886 }
887 }
888 }
889
890 // sort our configurations so we can do binary-searches
891 qsort( dp->configs,
892 dp->numTotalConfigs,
893 sizeof(egl_config_t), cmp_configs);
894
Mathias Agopian6099ab72010-02-05 16:17:01 -0800895 dp->refs++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800896 if (major != NULL) *major = VERSION_MAJOR;
897 if (minor != NULL) *minor = VERSION_MINOR;
898 return EGL_TRUE;
899 }
900 return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
901}
902
903EGLBoolean eglTerminate(EGLDisplay dpy)
904{
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700905 // NOTE: don't unload the drivers b/c some APIs can be called
906 // after eglTerminate() has been called. eglTerminate() only
907 // terminates an EGLDisplay, not a EGL itself.
908
Michael I. Golde7ff5dd2011-01-21 15:39:38 -0800909 clearError();
910
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800911 egl_display_t* const dp = get_display(dpy);
912 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian6099ab72010-02-05 16:17:01 -0800913
914 Mutex::Autolock _l(dp->lock);
915
916 if (dp->refs == 0) {
917 return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
918 }
919
920 // this is specific to Android, display termination is ref-counted.
Jack Palevich0a41c3c2010-03-15 20:45:21 -0700921 if (dp->refs > 1) {
922 dp->refs--;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800923 return EGL_TRUE;
Jack Palevich0a41c3c2010-03-15 20:45:21 -0700924 }
Mathias Agopian9d17c052009-05-28 17:39:03 -0700925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926 EGLBoolean res = EGL_FALSE;
Mathias Agopian6fc56992009-10-14 02:06:37 -0700927 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800928 egl_connection_t* const cnx = &gEGLImpl[i];
Mathias Agopian94263d72009-08-24 21:47:13 -0700929 if (cnx->dso && dp->disp[i].state == egl_display_t::INITIALIZED) {
Mathias Agopian6fc56992009-10-14 02:06:37 -0700930 if (cnx->egl.eglTerminate(dp->disp[i].dpy) == EGL_FALSE) {
Mathias Agopian94263d72009-08-24 21:47:13 -0700931 LOGW("%d: eglTerminate(%p) failed (%s)", i, dp->disp[i].dpy,
Mathias Agopian6fc56992009-10-14 02:06:37 -0700932 egl_strerror(cnx->egl.eglGetError()));
Mathias Agopian94263d72009-08-24 21:47:13 -0700933 }
Mathias Agopiandcebf6f2009-08-17 18:07:06 -0700934 // REVISIT: it's unclear what to do if eglTerminate() fails
Mathias Agopian94263d72009-08-24 21:47:13 -0700935 free(dp->disp[i].config);
936
937 dp->disp[i].numConfigs = 0;
938 dp->disp[i].config = 0;
939 dp->disp[i].state = egl_display_t::TERMINATED;
940
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 res = EGL_TRUE;
942 }
943 }
Mathias Agopian4a34e882009-08-21 02:18:25 -0700944
945 // TODO: all egl_object_t should be marked for termination
946
Mathias Agopian6099ab72010-02-05 16:17:01 -0800947 dp->refs--;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948 dp->numTotalConfigs = 0;
Mathias Agopian3ad6c442010-07-26 21:14:59 -0700949 delete [] dp->configs;
Michael I. Goldf0ca1d32010-12-23 13:51:36 -0800950
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800951 return res;
952}
953
954// ----------------------------------------------------------------------------
955// configuration
956// ----------------------------------------------------------------------------
957
958EGLBoolean eglGetConfigs( EGLDisplay dpy,
959 EGLConfig *configs,
960 EGLint config_size, EGLint *num_config)
961{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -0800962 clearError();
963
Eric Hassold2a790ac2011-03-23 15:59:00 -0700964 egl_display_t const * const dp = validate_display(dpy);
965 if (!dp) return EGL_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800966
967 GLint numConfigs = dp->numTotalConfigs;
968 if (!configs) {
969 *num_config = numConfigs;
970 return EGL_TRUE;
971 }
Mathias Agopian3ad6c442010-07-26 21:14:59 -0700972
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 GLint n = 0;
Mathias Agopian3ad6c442010-07-26 21:14:59 -0700974 for (intptr_t i=0 ; i<dp->numTotalConfigs && config_size ; i++) {
975 *configs++ = EGLConfig(i);
976 config_size--;
977 n++;
978 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979
980 *num_config = n;
981 return EGL_TRUE;
982}
983
984EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
985 EGLConfig *configs, EGLint config_size,
986 EGLint *num_config)
987{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -0800988 clearError();
989
Eric Hassold2a790ac2011-03-23 15:59:00 -0700990 egl_display_t const * const dp = validate_display(dpy);
991 if (!dp) return EGL_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800992
Jack Palevich1badb712009-03-25 15:12:17 -0700993 if (num_config==0) {
994 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800995 }
996
997 EGLint n;
998 EGLBoolean res = EGL_FALSE;
999 *num_config = 0;
1000
1001
1002 // It is unfortunate, but we need to remap the EGL_CONFIG_IDs,
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001003 // to do this, we have to go through the attrib_list array once
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004 // to figure out both its size and if it contains an EGL_CONFIG_ID
1005 // key. If so, the full array is copied and patched.
1006 // NOTE: we assume that there can be only one occurrence
1007 // of EGL_CONFIG_ID.
1008
1009 EGLint patch_index = -1;
1010 GLint attr;
1011 size_t size = 0;
Mathias Agopian7e71fcf2010-05-17 14:45:43 -07001012 if (attrib_list) {
1013 while ((attr=attrib_list[size]) != EGL_NONE) {
1014 if (attr == EGL_CONFIG_ID)
1015 patch_index = size;
1016 size += 2;
1017 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 }
1019 if (patch_index >= 0) {
1020 size += 2; // we need copy the sentinel as well
1021 EGLint* new_list = (EGLint*)malloc(size*sizeof(EGLint));
1022 if (new_list == 0)
1023 return setError(EGL_BAD_ALLOC, EGL_FALSE);
1024 memcpy(new_list, attrib_list, size*sizeof(EGLint));
1025
1026 // patch the requested EGL_CONFIG_ID
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001027 bool found = false;
1028 EGLConfig ourConfig(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001029 EGLint& configId(new_list[patch_index+1]);
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001030 for (intptr_t i=0 ; i<dp->numTotalConfigs ; i++) {
1031 if (dp->configs[i].configId == configId) {
1032 ourConfig = EGLConfig(i);
1033 configId = dp->configs[i].implConfigId;
1034 found = true;
1035 break;
1036 }
1037 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001039 egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(ourConfig)].impl];
1040 if (found && cnx->dso) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001041 // and switch to the new list
1042 attrib_list = const_cast<const EGLint *>(new_list);
1043
1044 // At this point, the only configuration that can match is
1045 // dp->configs[i][index], however, we don't know if it would be
1046 // rejected because of the other attributes, so we do have to call
Mathias Agopian6fc56992009-10-14 02:06:37 -07001047 // cnx->egl.eglChooseConfig() -- but we don't have to loop
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001048 // through all the EGLimpl[].
1049 // We also know we can only get a single config back, and we know
1050 // which one.
1051
Mathias Agopian6fc56992009-10-14 02:06:37 -07001052 res = cnx->egl.eglChooseConfig(
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001053 dp->disp[ dp->configs[intptr_t(ourConfig)].impl ].dpy,
1054 attrib_list, configs, config_size, &n);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001055 if (res && n>0) {
1056 // n has to be 0 or 1, by construction, and we already know
1057 // which config it will return (since there can be only one).
Jack Palevich1badb712009-03-25 15:12:17 -07001058 if (configs) {
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001059 configs[0] = ourConfig;
Jack Palevich1badb712009-03-25 15:12:17 -07001060 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001061 *num_config = 1;
1062 }
1063 }
1064
1065 free(const_cast<EGLint *>(attrib_list));
1066 return res;
1067 }
1068
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001069
Mathias Agopian6fc56992009-10-14 02:06:37 -07001070 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071 egl_connection_t* const cnx = &gEGLImpl[i];
1072 if (cnx->dso) {
Mathias Agopian6fc56992009-10-14 02:06:37 -07001073 if (cnx->egl.eglChooseConfig(
Mathias Agopian94263d72009-08-24 21:47:13 -07001074 dp->disp[i].dpy, attrib_list, configs, config_size, &n)) {
Jack Palevich1badb712009-03-25 15:12:17 -07001075 if (configs) {
1076 // now we need to convert these client EGLConfig to our
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001077 // internal EGLConfig format.
1078 // This is done in O(n Log(n)) time.
Jack Palevich1badb712009-03-25 15:12:17 -07001079 for (int j=0 ; j<n ; j++) {
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001080 egl_config_t key(i, configs[j]);
1081 intptr_t index = binarySearch<egl_config_t>(
1082 dp->configs, 0, dp->numTotalConfigs, key);
Jack Palevich1badb712009-03-25 15:12:17 -07001083 if (index >= 0) {
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001084 configs[j] = EGLConfig(index);
Jack Palevich1badb712009-03-25 15:12:17 -07001085 } else {
1086 return setError(EGL_BAD_CONFIG, EGL_FALSE);
1087 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 }
Jack Palevich1badb712009-03-25 15:12:17 -07001089 configs += n;
1090 config_size -= n;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001091 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 *num_config += n;
1093 res = EGL_TRUE;
1094 }
1095 }
1096 }
1097 return res;
1098}
1099
1100EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
1101 EGLint attribute, EGLint *value)
1102{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001103 clearError();
1104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 egl_display_t const* dp = 0;
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001106 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001107 if (!cnx) return EGL_FALSE;
1108
1109 if (attribute == EGL_CONFIG_ID) {
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001110 *value = dp->configs[intptr_t(config)].configId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 return EGL_TRUE;
1112 }
Mathias Agopian6fc56992009-10-14 02:06:37 -07001113 return cnx->egl.eglGetConfigAttrib(
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001114 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1115 dp->configs[intptr_t(config)].config, attribute, value);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001116}
1117
1118// ----------------------------------------------------------------------------
1119// surfaces
1120// ----------------------------------------------------------------------------
1121
1122EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
1123 NativeWindowType window,
1124 const EGLint *attrib_list)
1125{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001126 clearError();
1127
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 egl_display_t const* dp = 0;
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001129 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001130 if (cnx) {
Mathias Agopian698a8aa2010-11-24 15:59:35 -08001131 EGLDisplay iDpy = dp->disp[ dp->configs[intptr_t(config)].impl ].dpy;
1132 EGLConfig iConfig = dp->configs[intptr_t(config)].config;
1133 EGLint format;
1134
1135 // set the native window's buffers format to match this config
1136 if (cnx->egl.eglGetConfigAttrib(iDpy,
1137 iConfig, EGL_NATIVE_VISUAL_ID, &format)) {
1138 if (format != 0) {
1139 native_window_set_buffers_geometry(window, 0, 0, format);
1140 }
1141 }
1142
Mathias Agopian6fc56992009-10-14 02:06:37 -07001143 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian698a8aa2010-11-24 15:59:35 -08001144 iDpy, iConfig, window, attrib_list);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001145 if (surface != EGL_NO_SURFACE) {
Mathias Agopian698a8aa2010-11-24 15:59:35 -08001146 egl_surface_t* s = new egl_surface_t(dpy, config, window, surface,
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001147 dp->configs[intptr_t(config)].impl, cnx);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001148 return s;
1149 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001150 }
1151 return EGL_NO_SURFACE;
1152}
1153
1154EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
1155 NativePixmapType pixmap,
1156 const EGLint *attrib_list)
1157{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001158 clearError();
1159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001160 egl_display_t const* dp = 0;
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001161 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001162 if (cnx) {
Mathias Agopian6fc56992009-10-14 02:06:37 -07001163 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001164 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1165 dp->configs[intptr_t(config)].config, pixmap, attrib_list);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001166 if (surface != EGL_NO_SURFACE) {
Mathias Agopian698a8aa2010-11-24 15:59:35 -08001167 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001168 dp->configs[intptr_t(config)].impl, cnx);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001169 return s;
1170 }
1171 }
1172 return EGL_NO_SURFACE;
1173}
1174
1175EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
1176 const EGLint *attrib_list)
1177{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001178 clearError();
1179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001180 egl_display_t const* dp = 0;
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001181 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 if (cnx) {
Mathias Agopian6fc56992009-10-14 02:06:37 -07001183 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001184 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1185 dp->configs[intptr_t(config)].config, attrib_list);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001186 if (surface != EGL_NO_SURFACE) {
Mathias Agopian698a8aa2010-11-24 15:59:35 -08001187 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001188 dp->configs[intptr_t(config)].impl, cnx);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001189 return s;
1190 }
1191 }
1192 return EGL_NO_SURFACE;
1193}
1194
1195EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
1196{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001197 clearError();
1198
Eric Hassold2a790ac2011-03-23 15:59:00 -07001199 egl_display_t const * const dp = validate_display(dpy);
1200 if (!dp) return EGL_FALSE;
1201
Mathias Agopian4a34e882009-08-21 02:18:25 -07001202 SurfaceRef _s(surface);
1203 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001205 if (!validate_display_surface(dpy, surface))
1206 return EGL_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001207
Mathias Agopian4a34e882009-08-21 02:18:25 -07001208 egl_surface_t * const s = get_surface(surface);
Mathias Agopian6fc56992009-10-14 02:06:37 -07001209 EGLBoolean result = s->cnx->egl.eglDestroySurface(
Mathias Agopian94263d72009-08-24 21:47:13 -07001210 dp->disp[s->impl].dpy, s->surface);
Mathias Agopian4a34e882009-08-21 02:18:25 -07001211 if (result == EGL_TRUE) {
Mathias Agopian698a8aa2010-11-24 15:59:35 -08001212 if (s->win != NULL) {
1213 native_window_set_buffers_geometry(s->win.get(), 0, 0, 0);
1214 }
Mathias Agopian4a34e882009-08-21 02:18:25 -07001215 _s.terminate();
1216 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001217 return result;
1218}
1219
1220EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
1221 EGLint attribute, EGLint *value)
1222{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001223 clearError();
1224
Eric Hassold2a790ac2011-03-23 15:59:00 -07001225 egl_display_t const * const dp = validate_display(dpy);
1226 if (!dp) return EGL_FALSE;
1227
Mathias Agopian4a34e882009-08-21 02:18:25 -07001228 SurfaceRef _s(surface);
1229 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001231 if (!validate_display_surface(dpy, surface))
1232 return EGL_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001233 egl_surface_t const * const s = get_surface(surface);
1234
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001235 EGLBoolean result(EGL_TRUE);
1236 if (attribute == EGL_CONFIG_ID) {
1237 // We need to remap EGL_CONFIG_IDs
1238 *value = dp->configs[intptr_t(s->config)].configId;
1239 } else {
1240 result = s->cnx->egl.eglQuerySurface(
1241 dp->disp[s->impl].dpy, s->surface, attribute, value);
1242 }
1243
1244 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001245}
1246
1247// ----------------------------------------------------------------------------
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001248// Contexts
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001249// ----------------------------------------------------------------------------
1250
1251EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
1252 EGLContext share_list, const EGLint *attrib_list)
1253{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001254 clearError();
1255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001256 egl_display_t const* dp = 0;
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001257 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001258 if (cnx) {
Jamie Gennis5149f912010-07-02 11:39:12 -07001259 if (share_list != EGL_NO_CONTEXT) {
1260 egl_context_t* const c = get_context(share_list);
1261 share_list = c->context;
1262 }
Mathias Agopian6fc56992009-10-14 02:06:37 -07001263 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001264 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1265 dp->configs[intptr_t(config)].config,
Mathias Agopian94263d72009-08-24 21:47:13 -07001266 share_list, attrib_list);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001267 if (context != EGL_NO_CONTEXT) {
Mathias Agopian6fc56992009-10-14 02:06:37 -07001268 // figure out if it's a GLESv1 or GLESv2
1269 int version = 0;
1270 if (attrib_list) {
1271 while (*attrib_list != EGL_NONE) {
1272 GLint attr = *attrib_list++;
1273 GLint value = *attrib_list++;
1274 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
1275 if (value == 1) {
1276 version = GLESv1_INDEX;
1277 } else if (value == 2) {
1278 version = GLESv2_INDEX;
1279 }
1280 }
1281 };
1282 }
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001283 egl_context_t* c = new egl_context_t(dpy, context, config,
1284 dp->configs[intptr_t(config)].impl, cnx, version);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001285 return c;
1286 }
1287 }
1288 return EGL_NO_CONTEXT;
1289}
1290
1291EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1292{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001293 clearError();
1294
Eric Hassold2a790ac2011-03-23 15:59:00 -07001295 egl_display_t const * const dp = validate_display(dpy);
1296 if (!dp) return EGL_FALSE;
1297
Mathias Agopian4a34e882009-08-21 02:18:25 -07001298 ContextRef _c(ctx);
1299 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1300
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001301 if (!validate_display_context(dpy, ctx))
1302 return EGL_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001303 egl_context_t * const c = get_context(ctx);
Mathias Agopian6fc56992009-10-14 02:06:37 -07001304 EGLBoolean result = c->cnx->egl.eglDestroyContext(
Mathias Agopian94263d72009-08-24 21:47:13 -07001305 dp->disp[c->impl].dpy, c->context);
Mathias Agopian4a34e882009-08-21 02:18:25 -07001306 if (result == EGL_TRUE) {
1307 _c.terminate();
1308 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001309 return result;
1310}
1311
Michael I. Goldf0ca1d32010-12-23 13:51:36 -08001312static void loseCurrent(egl_context_t * cur_c)
1313{
1314 if (cur_c) {
1315 egl_surface_t * cur_r = get_surface(cur_c->read);
1316 egl_surface_t * cur_d = get_surface(cur_c->draw);
1317
1318 // by construction, these are either 0 or valid (possibly terminated)
1319 // it should be impossible for these to be invalid
1320 ContextRef _cur_c(cur_c);
1321 SurfaceRef _cur_r(cur_r);
1322 SurfaceRef _cur_d(cur_d);
1323
1324 cur_c->read = NULL;
1325 cur_c->draw = NULL;
1326
1327 _cur_c.release();
1328 _cur_r.release();
1329 _cur_d.release();
1330 }
1331}
1332
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001333EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
1334 EGLSurface read, EGLContext ctx)
1335{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001336 clearError();
1337
Eric Hassold2a790ac2011-03-23 15:59:00 -07001338 egl_display_t const * const dp = get_display(dpy);
1339 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1340
1341 /* If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
1342 EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
1343 a valid but uninitialized display. */
1344 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
1345 (draw != EGL_NO_SURFACE) ) {
1346 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
1347 }
1348
Mathias Agopian4a34e882009-08-21 02:18:25 -07001349 // get a reference to the object passed in
1350 ContextRef _c(ctx);
1351 SurfaceRef _d(draw);
1352 SurfaceRef _r(read);
1353
Eric Hassold2a790ac2011-03-23 15:59:00 -07001354 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian4a34e882009-08-21 02:18:25 -07001355 if ((ctx != EGL_NO_CONTEXT) && (!validate_display_context(dpy, ctx))) {
1356 // EGL_NO_CONTEXT is valid
1357 return EGL_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001358 }
1359
Mathias Agopian4a34e882009-08-21 02:18:25 -07001360 // these are the underlying implementation's object
1361 EGLContext impl_ctx = EGL_NO_CONTEXT;
Mathias Agopian3a7e1832009-06-25 00:01:11 -07001362 EGLSurface impl_draw = EGL_NO_SURFACE;
1363 EGLSurface impl_read = EGL_NO_SURFACE;
Mathias Agopian4a34e882009-08-21 02:18:25 -07001364
1365 // these are our objects structs passed in
1366 egl_context_t * c = NULL;
1367 egl_surface_t const * d = NULL;
1368 egl_surface_t const * r = NULL;
1369
1370 // these are the current objects structs
1371 egl_context_t * cur_c = get_context(getContext());
Mathias Agopian4a34e882009-08-21 02:18:25 -07001372
1373 if (ctx != EGL_NO_CONTEXT) {
1374 c = get_context(ctx);
Mathias Agopian4a34e882009-08-21 02:18:25 -07001375 impl_ctx = c->context;
1376 } else {
1377 // no context given, use the implementation of the current context
1378 if (cur_c == NULL) {
1379 // no current context
1380 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
Mathias Agopian7552dcf2010-01-25 11:30:11 -08001381 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
1382 return setError(EGL_BAD_MATCH, EGL_FALSE);
Mathias Agopian4a34e882009-08-21 02:18:25 -07001383 }
Mathias Agopian7552dcf2010-01-25 11:30:11 -08001384 // not an error, there is just no current context.
Mathias Agopian4a34e882009-08-21 02:18:25 -07001385 return EGL_TRUE;
1386 }
1387 }
1388
1389 // retrieve the underlying implementation's draw EGLSurface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001390 if (draw != EGL_NO_SURFACE) {
Mathias Agopian4a34e882009-08-21 02:18:25 -07001391 d = get_surface(draw);
Mathias Agopian94263d72009-08-24 21:47:13 -07001392 // make sure the EGLContext and EGLSurface passed in are for
1393 // the same driver
Mathias Agopian4a34e882009-08-21 02:18:25 -07001394 if (c && d->impl != c->impl)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001395 return setError(EGL_BAD_MATCH, EGL_FALSE);
Mathias Agopian3a7e1832009-06-25 00:01:11 -07001396 impl_draw = d->surface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001397 }
Mathias Agopian4a34e882009-08-21 02:18:25 -07001398
1399 // retrieve the underlying implementation's read EGLSurface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001400 if (read != EGL_NO_SURFACE) {
Mathias Agopian4a34e882009-08-21 02:18:25 -07001401 r = get_surface(read);
Mathias Agopian94263d72009-08-24 21:47:13 -07001402 // make sure the EGLContext and EGLSurface passed in are for
1403 // the same driver
Mathias Agopian4a34e882009-08-21 02:18:25 -07001404 if (c && r->impl != c->impl)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001405 return setError(EGL_BAD_MATCH, EGL_FALSE);
Mathias Agopian3a7e1832009-06-25 00:01:11 -07001406 impl_read = r->surface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001407 }
Mathias Agopian4a34e882009-08-21 02:18:25 -07001408
1409 EGLBoolean result;
1410
1411 if (c) {
Mathias Agopian6fc56992009-10-14 02:06:37 -07001412 result = c->cnx->egl.eglMakeCurrent(
Mathias Agopian94263d72009-08-24 21:47:13 -07001413 dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
Mathias Agopian4a34e882009-08-21 02:18:25 -07001414 } else {
Mathias Agopian6fc56992009-10-14 02:06:37 -07001415 result = cur_c->cnx->egl.eglMakeCurrent(
Mathias Agopian94263d72009-08-24 21:47:13 -07001416 dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
Mathias Agopian4a34e882009-08-21 02:18:25 -07001417 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001418
1419 if (result == EGL_TRUE) {
Mathias Agopian4a34e882009-08-21 02:18:25 -07001420
Michael I. Goldf0ca1d32010-12-23 13:51:36 -08001421 loseCurrent(cur_c);
1422
Mathias Agopian4a34e882009-08-21 02:18:25 -07001423 if (ctx != EGL_NO_CONTEXT) {
Jack Palevichd4d0fb92010-10-26 15:21:24 -07001424 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
Mathias Agopian4a34e882009-08-21 02:18:25 -07001425 setContext(ctx);
David Lice30eb82011-03-28 10:39:28 -07001426 tls_t * const tls = getTLS();
1427 if (!tls->dbg && gEGLDebugLevel > 0)
1428 tls->dbg = CreateDbgContext(gEGLThreadLocalStorageKey, c->version,
1429 c->cnx->hooks[c->version]);
Mathias Agopian4a34e882009-08-21 02:18:25 -07001430 _c.acquire();
Michael I. Goldf0ca1d32010-12-23 13:51:36 -08001431 _r.acquire();
1432 _d.acquire();
1433 c->read = read;
1434 c->draw = draw;
Mathias Agopian4a34e882009-08-21 02:18:25 -07001435 } else {
Jack Palevichd4d0fb92010-10-26 15:21:24 -07001436 setGLHooksThreadSpecific(&gHooksNoContext);
Mathias Agopian4a34e882009-08-21 02:18:25 -07001437 setContext(EGL_NO_CONTEXT);
1438 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001439 }
1440 return result;
1441}
1442
1443
1444EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
1445 EGLint attribute, EGLint *value)
1446{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001447 clearError();
1448
Eric Hassold2a790ac2011-03-23 15:59:00 -07001449 egl_display_t const * const dp = validate_display(dpy);
1450 if (!dp) return EGL_FALSE;
1451
Mathias Agopian4a34e882009-08-21 02:18:25 -07001452 ContextRef _c(ctx);
1453 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1454
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001455 if (!validate_display_context(dpy, ctx))
1456 return EGL_FALSE;
1457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001458 egl_context_t * const c = get_context(ctx);
1459
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001460 EGLBoolean result(EGL_TRUE);
1461 if (attribute == EGL_CONFIG_ID) {
1462 *value = dp->configs[intptr_t(c->config)].configId;
1463 } else {
1464 // We need to remap EGL_CONFIG_IDs
1465 result = c->cnx->egl.eglQueryContext(
1466 dp->disp[c->impl].dpy, c->context, attribute, value);
1467 }
1468
1469 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470}
1471
1472EGLContext eglGetCurrentContext(void)
1473{
Mathias Agopiandcebf6f2009-08-17 18:07:06 -07001474 // could be called before eglInitialize(), but we wouldn't have a context
1475 // then, and this function would correctly return EGL_NO_CONTEXT.
1476
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001477 clearError();
1478
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001479 EGLContext ctx = getContext();
1480 return ctx;
1481}
1482
1483EGLSurface eglGetCurrentSurface(EGLint readdraw)
1484{
Mathias Agopiandcebf6f2009-08-17 18:07:06 -07001485 // could be called before eglInitialize(), but we wouldn't have a context
1486 // then, and this function would correctly return EGL_NO_SURFACE.
1487
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001488 clearError();
1489
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001490 EGLContext ctx = getContext();
1491 if (ctx) {
1492 egl_context_t const * const c = get_context(ctx);
1493 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1494 switch (readdraw) {
1495 case EGL_READ: return c->read;
1496 case EGL_DRAW: return c->draw;
1497 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1498 }
1499 }
1500 return EGL_NO_SURFACE;
1501}
1502
1503EGLDisplay eglGetCurrentDisplay(void)
1504{
Mathias Agopiandcebf6f2009-08-17 18:07:06 -07001505 // could be called before eglInitialize(), but we wouldn't have a context
1506 // then, and this function would correctly return EGL_NO_DISPLAY.
1507
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001508 clearError();
1509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001510 EGLContext ctx = getContext();
1511 if (ctx) {
1512 egl_context_t const * const c = get_context(ctx);
1513 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1514 return c->dpy;
1515 }
1516 return EGL_NO_DISPLAY;
1517}
1518
1519EGLBoolean eglWaitGL(void)
1520{
Mathias Agopiandcebf6f2009-08-17 18:07:06 -07001521 // could be called before eglInitialize(), but we wouldn't have a context
1522 // then, and this function would return GL_TRUE, which isn't wrong.
1523
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001524 clearError();
1525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001526 EGLBoolean res = EGL_TRUE;
1527 EGLContext ctx = getContext();
1528 if (ctx) {
1529 egl_context_t const * const c = get_context(ctx);
1530 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1531 if (uint32_t(c->impl)>=2)
1532 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1533 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1534 if (!cnx->dso)
1535 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian6fc56992009-10-14 02:06:37 -07001536 res = cnx->egl.eglWaitGL();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 }
1538 return res;
1539}
1540
1541EGLBoolean eglWaitNative(EGLint engine)
1542{
Mathias Agopiandcebf6f2009-08-17 18:07:06 -07001543 // could be called before eglInitialize(), but we wouldn't have a context
1544 // then, and this function would return GL_TRUE, which isn't wrong.
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001545
1546 clearError();
1547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548 EGLBoolean res = EGL_TRUE;
1549 EGLContext ctx = getContext();
1550 if (ctx) {
1551 egl_context_t const * const c = get_context(ctx);
1552 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1553 if (uint32_t(c->impl)>=2)
1554 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1555 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1556 if (!cnx->dso)
1557 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian6fc56992009-10-14 02:06:37 -07001558 res = cnx->egl.eglWaitNative(engine);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559 }
1560 return res;
1561}
1562
1563EGLint eglGetError(void)
1564{
1565 EGLint result = EGL_SUCCESS;
Mathias Agopianf65630a2010-09-21 15:43:59 -07001566 EGLint err;
Mathias Agopian6fc56992009-10-14 02:06:37 -07001567 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
Mathias Agopianf65630a2010-09-21 15:43:59 -07001568 err = EGL_SUCCESS;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001569 egl_connection_t* const cnx = &gEGLImpl[i];
1570 if (cnx->dso)
Mathias Agopian6fc56992009-10-14 02:06:37 -07001571 err = cnx->egl.eglGetError();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001572 if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
1573 result = err;
1574 }
Mathias Agopianf65630a2010-09-21 15:43:59 -07001575 err = getError();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001576 if (result == EGL_SUCCESS)
Mathias Agopianf65630a2010-09-21 15:43:59 -07001577 result = err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001578 return result;
1579}
1580
Michael I. Goldf4a43832011-01-04 01:16:59 -08001581// Note: Similar implementations of these functions also exist in
1582// gl2.cpp and gl.cpp, and are used by applications that call the
1583// exported entry points directly.
1584typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
1585typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
1586
1587static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL;
1588static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL;
1589
1590static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image)
1591{
1592 GLeglImageOES implImage =
1593 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
1594 glEGLImageTargetTexture2DOES_impl(target, implImage);
1595}
1596
1597static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image)
1598{
1599 GLeglImageOES implImage =
1600 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
1601 glEGLImageTargetRenderbufferStorageOES_impl(target, implImage);
1602}
1603
Mathias Agopian1473f462009-04-10 14:24:30 -07001604__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001605{
Mathias Agopian1473f462009-04-10 14:24:30 -07001606 // eglGetProcAddress() could be the very first function called
1607 // in which case we must make sure we've initialized ourselves, this
1608 // happens the first time egl_get_display() is called.
Mathias Agopiandcebf6f2009-08-17 18:07:06 -07001609
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001610 clearError();
1611
Mathias Agopiandcebf6f2009-08-17 18:07:06 -07001612 if (egl_init_drivers() == EGL_FALSE) {
1613 setError(EGL_BAD_PARAMETER, NULL);
1614 return NULL;
1615 }
Mathias Agopian1473f462009-04-10 14:24:30 -07001616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001617 __eglMustCastToProperFunctionPointerType addr;
1618 addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap));
1619 if (addr) return addr;
1620
Mathias Agopian3944eab2010-08-02 17:34:32 -07001621 // this protects accesses to gGLExtentionMap and gGLExtentionSlot
1622 pthread_mutex_lock(&gInitDriverMutex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001623
Mathias Agopian3944eab2010-08-02 17:34:32 -07001624 /*
1625 * Since eglGetProcAddress() is not associated to anything, it needs
1626 * to return a function pointer that "works" regardless of what
1627 * the current context is.
1628 *
1629 * For this reason, we return a "forwarder", a small stub that takes
1630 * care of calling the function associated with the context
1631 * currently bound.
1632 *
1633 * We first look for extensions we've already resolved, if we're seeing
1634 * this extension for the first time, we go through all our
1635 * implementations and call eglGetProcAddress() and record the
1636 * result in the appropriate implementation hooks and return the
1637 * address of the forwarder corresponding to that hook set.
1638 *
1639 */
1640
1641 const String8 name(procname);
1642 addr = gGLExtentionMap.valueFor(name);
1643 const int slot = gGLExtentionSlot;
1644
1645 LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
1646 "no more slots for eglGetProcAddress(\"%s\")",
1647 procname);
1648
1649 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
1650 bool found = false;
1651 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1652 egl_connection_t* const cnx = &gEGLImpl[i];
1653 if (cnx->dso && cnx->egl.eglGetProcAddress) {
1654 found = true;
Mathias Agopianab575012010-08-13 12:19:04 -07001655 // Extensions are independent of the bound context
1656 cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
1657 cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
Jack Palevichd4d0fb92010-10-26 15:21:24 -07001658#if EGL_TRACE
David Li28ca2ab2011-03-01 16:08:10 -08001659 gHooksDebug.ext.extensions[slot] = gHooksTrace.ext.extensions[slot] =
Jack Palevichd4d0fb92010-10-26 15:21:24 -07001660#endif
Mathias Agopian3944eab2010-08-02 17:34:32 -07001661 cnx->egl.eglGetProcAddress(procname);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001662 }
1663 }
Mathias Agopian3944eab2010-08-02 17:34:32 -07001664 if (found) {
1665 addr = gExtensionForwarders[slot];
Michael I. Goldf4a43832011-01-04 01:16:59 -08001666
1667 if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) {
1668 glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr;
1669 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper;
1670 }
1671 if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) {
1672 glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr;
1673 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper;
1674 }
1675
Mathias Agopian3944eab2010-08-02 17:34:32 -07001676 gGLExtentionMap.add(name, addr);
1677 gGLExtentionSlot++;
1678 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001679 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001680
Mathias Agopian3944eab2010-08-02 17:34:32 -07001681 pthread_mutex_unlock(&gInitDriverMutex);
Mathias Agopian3944eab2010-08-02 17:34:32 -07001682 return addr;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001683}
1684
1685EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
1686{
David Li55c94cc2011-03-04 17:50:48 -08001687 EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw);
1688 if (gEGLDebugLevel > 0)
1689 Debug_eglSwapBuffers(dpy, draw);
1690
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001691 clearError();
1692
Eric Hassold2a790ac2011-03-23 15:59:00 -07001693 egl_display_t const * const dp = validate_display(dpy);
1694 if (!dp) return EGL_FALSE;
1695
Mathias Agopian4a34e882009-08-21 02:18:25 -07001696 SurfaceRef _s(draw);
1697 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1698
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001699 if (!validate_display_surface(dpy, draw))
1700 return EGL_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian6fc56992009-10-14 02:06:37 -07001702 return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001703}
1704
1705EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1706 NativePixmapType target)
1707{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001708 clearError();
1709
Eric Hassold2a790ac2011-03-23 15:59:00 -07001710 egl_display_t const * const dp = validate_display(dpy);
1711 if (!dp) return EGL_FALSE;
1712
Mathias Agopian4a34e882009-08-21 02:18:25 -07001713 SurfaceRef _s(surface);
1714 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001716 if (!validate_display_surface(dpy, surface))
1717 return EGL_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001718 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian6fc56992009-10-14 02:06:37 -07001719 return s->cnx->egl.eglCopyBuffers(
Mathias Agopian94263d72009-08-24 21:47:13 -07001720 dp->disp[s->impl].dpy, s->surface, target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001721}
1722
1723const char* eglQueryString(EGLDisplay dpy, EGLint name)
1724{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001725 clearError();
1726
Eric Hassold2a790ac2011-03-23 15:59:00 -07001727 egl_display_t const * const dp = validate_display(dpy);
1728 if (!dp) return (const char *) NULL;
1729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001730 switch (name) {
1731 case EGL_VENDOR:
1732 return gVendorString;
1733 case EGL_VERSION:
1734 return gVersionString;
1735 case EGL_EXTENSIONS:
1736 return gExtensionString;
1737 case EGL_CLIENT_APIS:
1738 return gClientApiString;
1739 }
1740 return setError(EGL_BAD_PARAMETER, (const char *)0);
1741}
1742
1743
1744// ----------------------------------------------------------------------------
1745// EGL 1.1
1746// ----------------------------------------------------------------------------
1747
1748EGLBoolean eglSurfaceAttrib(
1749 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1750{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001751 clearError();
1752
Eric Hassold2a790ac2011-03-23 15:59:00 -07001753 egl_display_t const * const dp = validate_display(dpy);
1754 if (!dp) return EGL_FALSE;
1755
Mathias Agopian4a34e882009-08-21 02:18:25 -07001756 SurfaceRef _s(surface);
1757 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1758
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001759 if (!validate_display_surface(dpy, surface))
1760 return EGL_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001761 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian6fc56992009-10-14 02:06:37 -07001762 if (s->cnx->egl.eglSurfaceAttrib) {
1763 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopian94263d72009-08-24 21:47:13 -07001764 dp->disp[s->impl].dpy, s->surface, attribute, value);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001765 }
1766 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1767}
1768
1769EGLBoolean eglBindTexImage(
1770 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1771{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001772 clearError();
1773
Eric Hassold2a790ac2011-03-23 15:59:00 -07001774 egl_display_t const * const dp = validate_display(dpy);
1775 if (!dp) return EGL_FALSE;
1776
Mathias Agopian4a34e882009-08-21 02:18:25 -07001777 SurfaceRef _s(surface);
1778 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1779
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001780 if (!validate_display_surface(dpy, surface))
1781 return EGL_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001782 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian6fc56992009-10-14 02:06:37 -07001783 if (s->cnx->egl.eglBindTexImage) {
1784 return s->cnx->egl.eglBindTexImage(
Mathias Agopian94263d72009-08-24 21:47:13 -07001785 dp->disp[s->impl].dpy, s->surface, buffer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001786 }
1787 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1788}
1789
1790EGLBoolean eglReleaseTexImage(
1791 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1792{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001793 clearError();
1794
Eric Hassold2a790ac2011-03-23 15:59:00 -07001795 egl_display_t const * const dp = validate_display(dpy);
1796 if (!dp) return EGL_FALSE;
1797
Mathias Agopian4a34e882009-08-21 02:18:25 -07001798 SurfaceRef _s(surface);
1799 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001801 if (!validate_display_surface(dpy, surface))
1802 return EGL_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001803 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian6fc56992009-10-14 02:06:37 -07001804 if (s->cnx->egl.eglReleaseTexImage) {
1805 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopian94263d72009-08-24 21:47:13 -07001806 dp->disp[s->impl].dpy, s->surface, buffer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001807 }
1808 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1809}
1810
1811EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1812{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001813 clearError();
1814
Eric Hassold2a790ac2011-03-23 15:59:00 -07001815 egl_display_t const * const dp = validate_display(dpy);
1816 if (!dp) return EGL_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001817
1818 EGLBoolean res = EGL_TRUE;
Mathias Agopian6fc56992009-10-14 02:06:37 -07001819 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 egl_connection_t* const cnx = &gEGLImpl[i];
1821 if (cnx->dso) {
Mathias Agopian6fc56992009-10-14 02:06:37 -07001822 if (cnx->egl.eglSwapInterval) {
1823 if (cnx->egl.eglSwapInterval(
Mathias Agopian94263d72009-08-24 21:47:13 -07001824 dp->disp[i].dpy, interval) == EGL_FALSE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001825 res = EGL_FALSE;
1826 }
1827 }
1828 }
1829 }
1830 return res;
1831}
1832
1833
1834// ----------------------------------------------------------------------------
1835// EGL 1.2
1836// ----------------------------------------------------------------------------
1837
1838EGLBoolean eglWaitClient(void)
1839{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001840 clearError();
1841
Mathias Agopiandcebf6f2009-08-17 18:07:06 -07001842 // could be called before eglInitialize(), but we wouldn't have a context
1843 // then, and this function would return GL_TRUE, which isn't wrong.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001844 EGLBoolean res = EGL_TRUE;
1845 EGLContext ctx = getContext();
1846 if (ctx) {
1847 egl_context_t const * const c = get_context(ctx);
1848 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1849 if (uint32_t(c->impl)>=2)
1850 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1851 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1852 if (!cnx->dso)
1853 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian6fc56992009-10-14 02:06:37 -07001854 if (cnx->egl.eglWaitClient) {
1855 res = cnx->egl.eglWaitClient();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001856 } else {
Mathias Agopian6fc56992009-10-14 02:06:37 -07001857 res = cnx->egl.eglWaitGL();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001858 }
1859 }
1860 return res;
1861}
1862
1863EGLBoolean eglBindAPI(EGLenum api)
1864{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001865 clearError();
1866
Mathias Agopiandcebf6f2009-08-17 18:07:06 -07001867 if (egl_init_drivers() == EGL_FALSE) {
1868 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1869 }
1870
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001871 // bind this API on all EGLs
1872 EGLBoolean res = EGL_TRUE;
Mathias Agopian6fc56992009-10-14 02:06:37 -07001873 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001874 egl_connection_t* const cnx = &gEGLImpl[i];
1875 if (cnx->dso) {
Mathias Agopian6fc56992009-10-14 02:06:37 -07001876 if (cnx->egl.eglBindAPI) {
1877 if (cnx->egl.eglBindAPI(api) == EGL_FALSE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001878 res = EGL_FALSE;
1879 }
1880 }
1881 }
1882 }
1883 return res;
1884}
1885
1886EGLenum eglQueryAPI(void)
1887{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001888 clearError();
1889
Mathias Agopiandcebf6f2009-08-17 18:07:06 -07001890 if (egl_init_drivers() == EGL_FALSE) {
1891 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1892 }
1893
Mathias Agopian6fc56992009-10-14 02:06:37 -07001894 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001895 egl_connection_t* const cnx = &gEGLImpl[i];
1896 if (cnx->dso) {
Mathias Agopian6fc56992009-10-14 02:06:37 -07001897 if (cnx->egl.eglQueryAPI) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001898 // the first one we find is okay, because they all
1899 // should be the same
Mathias Agopian6fc56992009-10-14 02:06:37 -07001900 return cnx->egl.eglQueryAPI();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001901 }
1902 }
1903 }
1904 // or, it can only be OpenGL ES
1905 return EGL_OPENGL_ES_API;
1906}
1907
1908EGLBoolean eglReleaseThread(void)
1909{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001910 clearError();
1911
Michael I. Goldf0ca1d32010-12-23 13:51:36 -08001912 // If there is context bound to the thread, release it
1913 loseCurrent(get_context(getContext()));
1914
Mathias Agopian6fc56992009-10-14 02:06:37 -07001915 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001916 egl_connection_t* const cnx = &gEGLImpl[i];
1917 if (cnx->dso) {
Mathias Agopian6fc56992009-10-14 02:06:37 -07001918 if (cnx->egl.eglReleaseThread) {
1919 cnx->egl.eglReleaseThread();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001920 }
1921 }
1922 }
1923 clearTLS();
1924 return EGL_TRUE;
1925}
1926
1927EGLSurface eglCreatePbufferFromClientBuffer(
1928 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1929 EGLConfig config, const EGLint *attrib_list)
1930{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001931 clearError();
1932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001933 egl_display_t const* dp = 0;
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001934 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001935 if (!cnx) return EGL_FALSE;
Mathias Agopian6fc56992009-10-14 02:06:37 -07001936 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1937 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian3ad6c442010-07-26 21:14:59 -07001938 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1939 buftype, buffer,
1940 dp->configs[intptr_t(config)].config, attrib_list);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001941 }
1942 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1943}
Mathias Agopian1473f462009-04-10 14:24:30 -07001944
1945// ----------------------------------------------------------------------------
1946// EGL_EGLEXT_VERSION 3
1947// ----------------------------------------------------------------------------
1948
1949EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1950 const EGLint *attrib_list)
1951{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001952 clearError();
1953
Eric Hassold2a790ac2011-03-23 15:59:00 -07001954 egl_display_t const * const dp = validate_display(dpy);
1955 if (!dp) return EGL_FALSE;
1956
Mathias Agopian4a34e882009-08-21 02:18:25 -07001957 SurfaceRef _s(surface);
1958 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1959
Mathias Agopian1473f462009-04-10 14:24:30 -07001960 if (!validate_display_surface(dpy, surface))
Mathias Agopian88e3e6b2009-08-12 21:18:15 -07001961 return EGL_FALSE;
Mathias Agopian1473f462009-04-10 14:24:30 -07001962
Mathias Agopian1473f462009-04-10 14:24:30 -07001963 egl_surface_t const * const s = get_surface(surface);
1964
Mathias Agopian6fc56992009-10-14 02:06:37 -07001965 if (s->cnx->egl.eglLockSurfaceKHR) {
1966 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopian94263d72009-08-24 21:47:13 -07001967 dp->disp[s->impl].dpy, s->surface, attrib_list);
Mathias Agopian1473f462009-04-10 14:24:30 -07001968 }
Mathias Agopian88e3e6b2009-08-12 21:18:15 -07001969 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian1473f462009-04-10 14:24:30 -07001970}
1971
1972EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1973{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001974 clearError();
1975
Eric Hassold2a790ac2011-03-23 15:59:00 -07001976 egl_display_t const * const dp = validate_display(dpy);
1977 if (!dp) return EGL_FALSE;
1978
Mathias Agopian4a34e882009-08-21 02:18:25 -07001979 SurfaceRef _s(surface);
1980 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1981
Mathias Agopian1473f462009-04-10 14:24:30 -07001982 if (!validate_display_surface(dpy, surface))
Mathias Agopian88e3e6b2009-08-12 21:18:15 -07001983 return EGL_FALSE;
Mathias Agopian1473f462009-04-10 14:24:30 -07001984
Mathias Agopian1473f462009-04-10 14:24:30 -07001985 egl_surface_t const * const s = get_surface(surface);
1986
Mathias Agopian6fc56992009-10-14 02:06:37 -07001987 if (s->cnx->egl.eglUnlockSurfaceKHR) {
1988 return s->cnx->egl.eglUnlockSurfaceKHR(
Mathias Agopian94263d72009-08-24 21:47:13 -07001989 dp->disp[s->impl].dpy, s->surface);
Mathias Agopian1473f462009-04-10 14:24:30 -07001990 }
Mathias Agopian88e3e6b2009-08-12 21:18:15 -07001991 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian1473f462009-04-10 14:24:30 -07001992}
1993
1994EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1995 EGLClientBuffer buffer, const EGLint *attrib_list)
1996{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08001997 clearError();
1998
Eric Hassold2a790ac2011-03-23 15:59:00 -07001999 egl_display_t const * const dp = validate_display(dpy);
2000 if (!dp) return EGL_NO_IMAGE_KHR;
2001
Mathias Agopian1473f462009-04-10 14:24:30 -07002002 if (ctx != EGL_NO_CONTEXT) {
Mathias Agopian4a34e882009-08-21 02:18:25 -07002003 ContextRef _c(ctx);
2004 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
Mathias Agopian1473f462009-04-10 14:24:30 -07002005 if (!validate_display_context(dpy, ctx))
2006 return EGL_NO_IMAGE_KHR;
Mathias Agopian1473f462009-04-10 14:24:30 -07002007 egl_context_t * const c = get_context(ctx);
2008 // since we have an EGLContext, we know which implementation to use
Mathias Agopian6fc56992009-10-14 02:06:37 -07002009 EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
Mathias Agopian94263d72009-08-24 21:47:13 -07002010 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
Mathias Agopian1473f462009-04-10 14:24:30 -07002011 if (image == EGL_NO_IMAGE_KHR)
2012 return image;
2013
2014 egl_image_t* result = new egl_image_t(dpy, ctx);
2015 result->images[c->impl] = image;
2016 return (EGLImageKHR)result;
2017 } else {
2018 // EGL_NO_CONTEXT is a valid parameter
Mathias Agopianf007a2f2009-10-28 21:00:29 -07002019
2020 /* Since we don't have a way to know which implementation to call,
2021 * we're calling all of them. If at least one of the implementation
2022 * succeeded, this is a success.
2023 */
2024
2025 EGLint currentError = eglGetError();
Mathias Agopian1473f462009-04-10 14:24:30 -07002026
Mathias Agopian6fc56992009-10-14 02:06:37 -07002027 EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS];
Mathias Agopian1473f462009-04-10 14:24:30 -07002028 bool success = false;
Mathias Agopian6fc56992009-10-14 02:06:37 -07002029 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
Mathias Agopian1473f462009-04-10 14:24:30 -07002030 egl_connection_t* const cnx = &gEGLImpl[i];
2031 implImages[i] = EGL_NO_IMAGE_KHR;
2032 if (cnx->dso) {
Mathias Agopian6fc56992009-10-14 02:06:37 -07002033 if (cnx->egl.eglCreateImageKHR) {
2034 implImages[i] = cnx->egl.eglCreateImageKHR(
Mathias Agopian94263d72009-08-24 21:47:13 -07002035 dp->disp[i].dpy, ctx, target, buffer, attrib_list);
Mathias Agopian1473f462009-04-10 14:24:30 -07002036 if (implImages[i] != EGL_NO_IMAGE_KHR) {
2037 success = true;
2038 }
2039 }
2040 }
2041 }
Mathias Agopianf007a2f2009-10-28 21:00:29 -07002042
2043 if (!success) {
2044 // failure, if there was an error when we entered this function,
2045 // the error flag must not be updated.
2046 // Otherwise, the error is whatever happened in the implementation
2047 // that faulted.
2048 if (currentError != EGL_SUCCESS) {
2049 setError(currentError, EGL_NO_IMAGE_KHR);
2050 }
Mathias Agopian1473f462009-04-10 14:24:30 -07002051 return EGL_NO_IMAGE_KHR;
Mathias Agopianf007a2f2009-10-28 21:00:29 -07002052 } else {
2053 // In case of success, we need to clear all error flags
2054 // (especially those caused by the implementation that didn't
Mathias Agopian0b0722f2009-10-29 18:29:30 -07002055 // succeed). TODO: we could avoid this if we knew this was
Mathias Agopianf007a2f2009-10-28 21:00:29 -07002056 // a "full" success (all implementation succeeded).
2057 eglGetError();
2058 }
2059
Mathias Agopian1473f462009-04-10 14:24:30 -07002060 egl_image_t* result = new egl_image_t(dpy, ctx);
2061 memcpy(result->images, implImages, sizeof(implImages));
2062 return (EGLImageKHR)result;
2063 }
2064}
2065
2066EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
2067{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08002068 clearError();
2069
Eric Hassold2a790ac2011-03-23 15:59:00 -07002070 egl_display_t const * const dp = validate_display(dpy);
2071 if (!dp) return EGL_FALSE;
Mathias Agopian1473f462009-04-10 14:24:30 -07002072
Eric Hassold2a790ac2011-03-23 15:59:00 -07002073 ImageRef _i(img);
2074 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian1473f462009-04-10 14:24:30 -07002075
Eric Hassold2a790ac2011-03-23 15:59:00 -07002076 egl_image_t* image = get_image(img);
2077 bool success = false;
2078 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
2079 egl_connection_t* const cnx = &gEGLImpl[i];
2080 if (image->images[i] != EGL_NO_IMAGE_KHR) {
2081 if (cnx->dso) {
2082 if (cnx->egl.eglDestroyImageKHR) {
2083 if (cnx->egl.eglDestroyImageKHR(
2084 dp->disp[i].dpy, image->images[i])) {
2085 success = true;
2086 }
2087 }
2088 }
2089 }
2090 }
2091 if (!success)
2092 return EGL_FALSE;
Mathias Agopian1473f462009-04-10 14:24:30 -07002093
Eric Hassold2a790ac2011-03-23 15:59:00 -07002094 _i.terminate();
Mathias Agopian1473f462009-04-10 14:24:30 -07002095
Eric Hassold2a790ac2011-03-23 15:59:00 -07002096 return EGL_TRUE;
Mathias Agopian1473f462009-04-10 14:24:30 -07002097}
Mathias Agopian2e20bff2009-05-04 19:29:25 -07002098
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002099// ----------------------------------------------------------------------------
2100// EGL_EGLEXT_VERSION 5
2101// ----------------------------------------------------------------------------
2102
2103
2104EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
2105{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08002106 clearError();
2107
Eric Hassold2a790ac2011-03-23 15:59:00 -07002108 egl_display_t const * const dp = validate_display(dpy);
2109 if (!dp) return EGL_NO_SYNC_KHR;
2110
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002111 EGLContext ctx = eglGetCurrentContext();
2112 ContextRef _c(ctx);
Mathias Agopian4644ea72010-09-21 16:22:10 -07002113 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR);
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002114 if (!validate_display_context(dpy, ctx))
Mathias Agopian4644ea72010-09-21 16:22:10 -07002115 return EGL_NO_SYNC_KHR;
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002116 egl_context_t * const c = get_context(ctx);
Mathias Agopian4644ea72010-09-21 16:22:10 -07002117 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002118 if (c->cnx->egl.eglCreateSyncKHR) {
2119 EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR(
2120 dp->disp[c->impl].dpy, type, attrib_list);
Mathias Agopian4644ea72010-09-21 16:22:10 -07002121 if (sync == EGL_NO_SYNC_KHR)
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002122 return sync;
2123 result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync);
2124 }
2125 return (EGLSyncKHR)result;
2126}
2127
2128EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
2129{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08002130 clearError();
2131
Eric Hassold2a790ac2011-03-23 15:59:00 -07002132 egl_display_t const * const dp = validate_display(dpy);
2133 if (!dp) return EGL_FALSE;
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002134
2135 SyncRef _s(sync);
2136 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2137 egl_sync_t* syncObject = get_sync(sync);
2138
2139 EGLContext ctx = syncObject->context;
2140 ContextRef _c(ctx);
2141 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
2142 if (!validate_display_context(dpy, ctx))
2143 return EGL_FALSE;
2144
Mathias Agopian3d69bea2011-03-16 14:19:03 -07002145 EGLBoolean result = EGL_FALSE;
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002146 egl_context_t * const c = get_context(ctx);
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002147 if (c->cnx->egl.eglDestroySyncKHR) {
Mathias Agopian3d69bea2011-03-16 14:19:03 -07002148 result = c->cnx->egl.eglDestroySyncKHR(
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002149 dp->disp[c->impl].dpy, syncObject->sync);
Mathias Agopian3d69bea2011-03-16 14:19:03 -07002150 if (result)
2151 _s.terminate();
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002152 }
Mathias Agopian3d69bea2011-03-16 14:19:03 -07002153 return result;
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002154}
2155
2156EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
2157{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08002158 clearError();
2159
Eric Hassold2a790ac2011-03-23 15:59:00 -07002160 egl_display_t const * const dp = validate_display(dpy);
2161 if (!dp) return EGL_FALSE;
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002162
2163 SyncRef _s(sync);
2164 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2165 egl_sync_t* syncObject = get_sync(sync);
2166
2167 EGLContext ctx = syncObject->context;
2168 ContextRef _c(ctx);
2169 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
2170 if (!validate_display_context(dpy, ctx))
2171 return EGL_FALSE;
2172
2173 egl_context_t * const c = get_context(ctx);
2174
2175 if (c->cnx->egl.eglClientWaitSyncKHR) {
2176 return c->cnx->egl.eglClientWaitSyncKHR(
2177 dp->disp[c->impl].dpy, syncObject->sync, flags, timeout);
2178 }
2179
2180 return EGL_FALSE;
2181}
2182
2183EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
2184{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08002185 clearError();
2186
Eric Hassold2a790ac2011-03-23 15:59:00 -07002187 egl_display_t const * const dp = validate_display(dpy);
2188 if (!dp) return EGL_FALSE;
Mathias Agopian9ca8a842010-08-27 16:48:56 -07002189
2190 SyncRef _s(sync);
2191 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2192 egl_sync_t* syncObject = get_sync(sync);
2193
2194 EGLContext ctx = syncObject->context;
2195 ContextRef _c(ctx);
2196 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
2197 if (!validate_display_context(dpy, ctx))
2198 return EGL_FALSE;
2199
2200 egl_context_t * const c = get_context(ctx);
2201
2202 if (c->cnx->egl.eglGetSyncAttribKHR) {
2203 return c->cnx->egl.eglGetSyncAttribKHR(
2204 dp->disp[c->impl].dpy, syncObject->sync, attribute, value);
2205 }
2206
2207 return EGL_FALSE;
2208}
Mathias Agopian2e20bff2009-05-04 19:29:25 -07002209
2210// ----------------------------------------------------------------------------
2211// ANDROID extensions
2212// ----------------------------------------------------------------------------
2213
2214EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
2215 EGLint left, EGLint top, EGLint width, EGLint height)
2216{
Michael I. Golde7ff5dd2011-01-21 15:39:38 -08002217 clearError();
2218
Eric Hassold2a790ac2011-03-23 15:59:00 -07002219 egl_display_t const * const dp = validate_display(dpy);
2220 if (!dp) return EGL_FALSE;
2221
Mathias Agopian4a34e882009-08-21 02:18:25 -07002222 SurfaceRef _s(draw);
2223 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
2224
Mathias Agopian2e20bff2009-05-04 19:29:25 -07002225 if (!validate_display_surface(dpy, draw))
2226 return EGL_FALSE;
Mathias Agopian2e20bff2009-05-04 19:29:25 -07002227 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian6fc56992009-10-14 02:06:37 -07002228 if (s->cnx->egl.eglSetSwapRectangleANDROID) {
2229 return s->cnx->egl.eglSetSwapRectangleANDROID(
Mathias Agopian94263d72009-08-24 21:47:13 -07002230 dp->disp[s->impl].dpy, s->surface, left, top, width, height);
Mathias Agopian2e20bff2009-05-04 19:29:25 -07002231 }
Mathias Agopian88e3e6b2009-08-12 21:18:15 -07002232 return setError(EGL_BAD_DISPLAY, NULL);
Mathias Agopian2e20bff2009-05-04 19:29:25 -07002233}