blob: 9cf722381f533f72deba9b73d921e3002e828681 [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/*
2 ** Copyright 2007, The Android Open Source Project
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 ** http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080017#include <ctype.h>
Mathias Agopiand8fb7b52009-05-17 18:50:16 -070018#include <stdlib.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080019#include <string.h>
20#include <errno.h>
21#include <dlfcn.h>
22
23#include <sys/ioctl.h>
24
Kenny Rootaf1cf072011-02-16 10:13:53 -080025#ifdef HAVE_ANDROID_OS
The Android Open Source Projectedbf3b62009-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 Agopian9429e9c2009-08-21 02:18:25 -070039#include <utils/SortedVector.h>
Mathias Agopian24035332010-08-02 17:34:32 -070040#include <utils/KeyedVector.h>
41#include <utils/String8.h>
Mathias Agopian9429e9c2009-08-21 02:18:25 -070042
Mathias Agopian644bb2a2010-11-24 15:59:35 -080043#include <ui/egl/android_natives.h>
44
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080045#include "hooks.h"
46#include "egl_impl.h"
Mathias Agopiande586972009-05-28 17:39:03 -070047#include "Loader.h"
David Li65948aa2011-03-10 16:40:37 -080048#include "glesv2dbg.h"
David Li864f8392011-03-28 10:39:28 -070049#include "egl_tls.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080050
The Android Open Source Projectedbf3b62009-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 Agopian923c6612009-08-17 18:07:06 -070060static char const * const gVersionString = "1.4 Android META-EGL";
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080061static char const * const gClientApiString = "OpenGL ES";
David Li864f8392011-03-28 10:39:28 -070062static char const * const gExtensionString =
Mathias Agopian076b1cc2009-04-10 14:24:30 -070063 "EGL_KHR_image "
Mathias Agopiane6bf8b32009-05-06 23:47:08 -070064 "EGL_KHR_image_base "
65 "EGL_KHR_image_pixmap "
Mathias Agopian8e4b5a32010-08-27 16:08:03 -070066 "EGL_KHR_gl_texture_2D_image "
Michael I. Goldca41e362011-01-13 10:13:15 -080067 "EGL_KHR_gl_texture_cubemap_image "
68 "EGL_KHR_gl_renderbuffer_image "
Mathias Agopianc291f5852010-08-27 16:48:56 -070069 "EGL_KHR_fence_sync "
Mathias Agopian076b1cc2009-04-10 14:24:30 -070070 "EGL_ANDROID_image_native_buffer "
Mathias Agopiandf3ca302009-05-04 19:29:25 -070071 "EGL_ANDROID_swap_rectangle "
Mathias Agopian076b1cc2009-04-10 14:24:30 -070072 ;
73
74// ----------------------------------------------------------------------------
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080075
Eric Hassold11c01562011-03-25 11:26:02 -070076class egl_object_t;
77struct egl_display_t;
78static egl_display_t* get_display(EGLDisplay dpy);
Mathias Agopian9429e9c2009-08-21 02:18:25 -070079
Eric Hassold11c01562011-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 Hassold7fecf8c2011-03-31 16:52:02 -0700124 egl_display_t() : magic('_dpy'), numTotalConfigs(0), configs(0), refs(0) { }
Eric Hassold11c01562011-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 Agopian9429e9c2009-08-21 02:18:25 -0700133 volatile int32_t terminated;
134 mutable volatile int32_t count;
135
136public:
Eric Hassold11c01562011-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 Agopian9429e9c2009-08-21 02:18:25 -0700140 }
141
142 inline bool isAlive() const { return !terminated; }
143
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800144private:
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700145 bool get() {
Eric Hassold11c01562011-03-25 11:26:02 -0700146 Mutex::Autolock _l(display->lock);
147 if (display->objects.indexOf(this) >= 0) {
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700148 android_atomic_inc(&count);
149 return true;
150 }
151 return false;
152 }
153
154 bool put() {
Eric Hassold11c01562011-03-25 11:26:02 -0700155 Mutex::Autolock _l(display->lock);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700156 if (android_atomic_dec(&count) == 1) {
Eric Hassold11c01562011-03-25 11:26:02 -0700157 display->objects.remove(this);
Mathias Agopian9429e9c2009-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 Projectedbf3b62009-03-03 19:31:44 -0800202};
203
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700204struct egl_surface_t : public egl_object_t
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800205{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700206 typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
207
Mathias Agopian644bb2a2010-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 Hassold11c01562011-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 Projectedbf3b62009-03-03 19:31:44 -0800211 }
212 ~egl_surface_t() {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800213 }
214 EGLDisplay dpy;
215 EGLSurface surface;
Mathias Agopiancee79392010-07-26 21:14:59 -0700216 EGLConfig config;
Mathias Agopian644bb2a2010-11-24 15:59:35 -0800217 sp<ANativeWindow> win;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800218 int impl;
219 egl_connection_t const* cnx;
220};
221
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700222struct egl_context_t : public egl_object_t
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800223{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700224 typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
David Li864f8392011-03-28 10:39:28 -0700225
Mathias Agopiancee79392010-07-26 21:14:59 -0700226 egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
David Li864f8392011-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 Projectedbf3b62009-03-03 19:31:44 -0800230 {
231 }
David Li65948aa2011-03-10 16:40:37 -0800232 ~egl_context_t()
233 {
David Li65948aa2011-03-10 16:40:37 -0800234 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800235 EGLDisplay dpy;
236 EGLContext context;
Mathias Agopiancee79392010-07-26 21:14:59 -0700237 EGLConfig config;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800238 EGLSurface read;
239 EGLSurface draw;
240 int impl;
241 egl_connection_t const* cnx;
Mathias Agopian618fa102009-10-14 02:06:37 -0700242 int version;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800243};
244
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700245struct egl_image_t : public egl_object_t
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700246{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700247 typedef egl_object_t::LocalRef<egl_image_t, EGLImageKHR> Ref;
248
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700249 egl_image_t(EGLDisplay dpy, EGLContext context)
Eric Hassold11c01562011-03-25 11:26:02 -0700250 : egl_object_t(dpy), dpy(dpy), context(context)
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700251 {
252 memset(images, 0, sizeof(images));
253 }
254 EGLDisplay dpy;
Mathias Agopian77fbf8d2010-09-09 11:12:54 -0700255 EGLContext context;
Mathias Agopian618fa102009-10-14 02:06:37 -0700256 EGLImageKHR images[IMPL_NUM_IMPLEMENTATIONS];
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700257};
258
Mathias Agopianc291f5852010-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 Hassold11c01562011-03-25 11:26:02 -0700264 : egl_object_t(dpy), dpy(dpy), context(context), sync(sync)
Mathias Agopianc291f5852010-08-27 16:48:56 -0700265 {
266 }
267 EGLDisplay dpy;
268 EGLContext context;
269 EGLSyncKHR sync;
270};
271
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700272typedef egl_surface_t::Ref SurfaceRef;
273typedef egl_context_t::Ref ContextRef;
274typedef egl_image_t::Ref ImageRef;
Mathias Agopianc291f5852010-08-27 16:48:56 -0700275typedef egl_sync_t::Ref SyncRef;
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700276
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800277// ----------------------------------------------------------------------------
278
Mathias Agopianbf41b112010-04-09 13:37:34 -0700279static egl_connection_t gEGLImpl[IMPL_NUM_IMPLEMENTATIONS];
The Android Open Source Projectedbf3b62009-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 Agopian618fa102009-10-14 02:06:37 -0700286EGLAPI gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS];
287EGLAPI gl_hooks_t gHooksNoContext;
Mathias Agopianeccc8cf2009-05-13 00:19:22 -0700288EGLAPI pthread_key_t gGLWrapperKey = -1;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800289
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700290#if EGL_TRACE
291
292EGLAPI pthread_key_t gGLTraceKey = -1;
293
294// ----------------------------------------------------------------------------
295
David Li2f5a6552011-03-01 16:08:10 -0800296static int gEGLTraceLevel, gEGLDebugLevel;
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700297static int gEGLApplicationTraceLevel;
David Li2f5a6552011-03-01 16:08:10 -0800298extern EGLAPI gl_hooks_t gHooksTrace, gHooksDebug;
Jack Palevicha2dd6cf2010-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 Li499c6f02011-04-08 18:43:16 -0700314
David Li2f5a6552011-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 Li2f5a6552011-03-01 16:08:10 -0800325 if (!strcmp(value, cmdline))
326 gEGLDebugLevel = 1;
David Li499c6f02011-04-08 18:43:16 -0700327 }
David Li2f5a6552011-03-01 16:08:10 -0800328 fclose(file);
329 }
David Li499c6f02011-04-08 18:43:16 -0700330
David Li2f5a6552011-03-01 16:08:10 -0800331 if (gEGLDebugLevel > 0)
David Li85f33a72011-03-10 19:07:42 -0800332 {
333 property_get("debug.egl.debug_port", value, "5039");
David Li499c6f02011-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 Li85f33a72011-03-10 19:07:42 -0800341 }
Jack Palevicha2dd6cf2010-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 Li65948aa2011-03-10 16:40:37 -0800348 } else if (gEGLDebugLevel > 0 && value != &gHooksNoContext) {
David Li2f5a6552011-03-01 16:08:10 -0800349 setGlTraceThreadSpecific(value);
350 setGlThreadSpecific(&gHooksDebug);
Jack Palevicha2dd6cf2010-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 Projectedbf3b62009-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. Gold4aea6bf2011-01-21 15:39:38 -0800419static inline void clearError() {
Jamie Gennisf1cde8e2011-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. Gold4aea6bf2011-01-21 15:39:38 -0800423}
424
The Android Open Source Projectedbf3b62009-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 Projectedbf3b62009-03-03 19:31:44 -0800474/*****************************************************************************/
475
The Android Open Source Projectedbf3b62009-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 Agopiancee79392010-07-26 21:14:59 -0700483 if (sortedArray[mid] < key) {
The Android Open Source Projectedbf3b62009-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 Projectedbf3b62009-03-03 19:31:44 -0800494static int cmp_configs(const void* a, const void *b)
495{
Mathias Agopiancee79392010-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 Projectedbf3b62009-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 Agopian076b1cc2009-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 Agopian8d2e83b2009-06-24 22:37:39 -0700515 { "eglSetSwapRectangleANDROID",
516 (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800517};
518
Mathias Agopian24035332010-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 Projectedbf3b62009-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 Agopian6f087122010-09-23 16:38:38 -0700538static int gl_no_context() {
Mathias Agopiand274eae2009-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 Agopian6f087122010-09-23 16:38:38 -0700545 return 0;
Mathias Agopian05c53112010-09-23 11:32:52 -0700546}
547
The Android Open Source Projectedbf3b62009-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 Palevicha2dd6cf2010-10-26 15:21:24 -0700553#if EGL_TRACE
554 pthread_key_create(&gGLTraceKey, NULL);
555 initEglTraceLevel();
556#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800557 uint32_t addr = (uint32_t)((void*)gl_no_context);
558 android_memset32(
Mathias Agopian618fa102009-10-14 02:06:37 -0700559 (uint32_t*)(void*)&gHooksNoContext,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800560 addr,
Mathias Agopian618fa102009-10-14 02:06:37 -0700561 sizeof(gHooksNoContext));
Mathias Agopian05c53112010-09-23 11:32:52 -0700562
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700563 setGLHooksThreadSpecific(&gHooksNoContext);
The Android Open Source Projectedbf3b62009-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 Agopian076b1cc2009-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 Projectedbf3b62009-03-03 19:31:44 -0800580}
581
582static inline
David Li864f8392011-03-28 10:39:28 -0700583egl_surface_t* get_surface(EGLSurface surface) {
Mathias Agopian076b1cc2009-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 Projectedbf3b62009-03-03 19:31:44 -0800595}
596
Mathias Agopianc291f5852010-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 Hassold3ede7c12011-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 Projectedbf3b62009-03-03 19:31:44 -0800612static egl_connection_t* validate_display_config(
613 EGLDisplay dpy, EGLConfig config,
Mathias Agopiancee79392010-07-26 21:14:59 -0700614 egl_display_t const*& dp)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800615{
Eric Hassold3ede7c12011-03-23 15:59:00 -0700616 dp = validate_display(dpy);
617 if (!dp) return (egl_connection_t*) NULL;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800618
Mathias Agopiancee79392010-07-26 21:14:59 -0700619 if (intptr_t(config) >= dp->numTotalConfigs) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800620 return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
621 }
Mathias Agopiancee79392010-07-26 21:14:59 -0700622 egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(config)].impl];
The Android Open Source Projectedbf3b62009-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 Hassold3ede7c12011-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 Projectedbf3b62009-03-03 19:31:44 -0800634 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700635 if (!get_context(ctx)->isAlive())
The Android Open Source Projectedbf3b62009-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 Hassold3ede7c12011-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 Projectedbf3b62009-03-03 19:31:44 -0800645 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700646 if (!get_surface(surface)->isAlive())
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800647 return setError(EGL_BAD_SURFACE, EGL_FALSE);
648 return EGL_TRUE;
649}
650
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700651EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image)
652{
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700653 ImageRef _i(image);
654 if (!_i.get()) return EGL_NO_IMAGE_KHR;
655
Mathias Agopian076b1cc2009-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 Agopian9429e9c2009-08-21 02:18:25 -0700661 if (!c->isAlive())
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700662 return EGL_NO_IMAGE_KHR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800663
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700664 egl_image_t const * const i = get_image(image);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700665 return i->images[c->impl];
666}
667
Mathias Agopian923c6612009-08-17 18:07:06 -0700668// ----------------------------------------------------------------------------
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700669
Mathias Agopian923c6612009-08-17 18:07:06 -0700670// this mutex protects:
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700671// d->disp[]
Mathias Agopian923c6612009-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 Projectedbf3b62009-03-03 19:31:44 -0800677{
678 if (sEarlyInitState) {
Mathias Agopian923c6612009-08-17 18:07:06 -0700679 // initialized by static ctor. should be set here.
680 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800681 }
682
Mathias Agopiande586972009-05-28 17:39:03 -0700683 // get our driver loader
Mathias Agopian923c6612009-08-17 18:07:06 -0700684 Loader& loader(Loader::getInstance());
Mathias Agopiande586972009-05-28 17:39:03 -0700685
Mathias Agopian923c6612009-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 Projectedbf3b62009-03-03 19:31:44 -0800694 if (cnx->dso == 0) {
Mathias Agopian618fa102009-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 Agopian923c6612009-08-17 18:07:06 -0700698 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700699 EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
Mathias Agopian923c6612009-08-17 18:07:06 -0700700 LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for software EGL!");
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700701 d->disp[IMPL_SOFTWARE].dpy = dpy;
Mathias Agopian923c6612009-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 Projectedbf3b62009-03-03 19:31:44 -0800707 }
708
709 cnx = &gEGLImpl[IMPL_HARDWARE];
Mathias Agopian923c6612009-08-17 18:07:06 -0700710 if (cnx->dso == 0) {
The Android Open Source Projectedbf3b62009-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 Agopian618fa102009-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 Agopian923c6612009-08-17 18:07:06 -0700717 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700718 EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
Mathias Agopian923c6612009-08-17 18:07:06 -0700719 LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for hardware EGL!");
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700720 d->disp[IMPL_HARDWARE].dpy = dpy;
Mathias Agopian923c6612009-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 Projectedbf3b62009-03-03 19:31:44 -0800726 } else {
727 LOGD("3D hardware acceleration is disabled");
728 }
729 }
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700730
Mathias Agopian923c6612009-08-17 18:07:06 -0700731 if (!gEGLImpl[IMPL_SOFTWARE].dso && !gEGLImpl[IMPL_HARDWARE].dso) {
732 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800733 }
734
Mathias Agopian923c6612009-08-17 18:07:06 -0700735 return EGL_TRUE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800736}
737
Mathias Agopian923c6612009-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 Agopian076b1cc2009-04-10 14:24:30 -0700746
747// ----------------------------------------------------------------------------
748}; // namespace android
749// ----------------------------------------------------------------------------
750
751using namespace android;
752
753EGLDisplay eglGetDisplay(NativeDisplayType display)
754{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -0800755 clearError();
756
Mathias Agopian923c6612009-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 Agopian076b1cc2009-04-10 14:24:30 -0700768}
769
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800770// ----------------------------------------------------------------------------
771// Initialization
772// ----------------------------------------------------------------------------
773
774EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
775{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -0800776 clearError();
777
The Android Open Source Projectedbf3b62009-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 Agopian75bc2782010-02-05 16:17:01 -0800781 Mutex::Autolock _l(dp->lock);
782
783 if (dp->refs > 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800784 if (major != NULL) *major = VERSION_MAJOR;
785 if (minor != NULL) *minor = VERSION_MINOR;
Jack Palevich81cd0842010-03-15 20:45:21 -0700786 dp->refs++;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800787 return EGL_TRUE;
788 }
Jack Palevicha2dd6cf2010-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 Projectedbf3b62009-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 Agopian618fa102009-10-14 02:06:37 -0700803 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-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 Agopiana69e0ed2009-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 Agopian618fa102009-10-14 02:06:37 -0700821 cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700822 }
823#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800824
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700825
826 EGLDisplay idpy = dp->disp[i].dpy;
Mathias Agopian618fa102009-10-14 02:06:37 -0700827 if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800828 //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p",
Mathias Agopiana69e0ed2009-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 Projectedbf3b62009-03-03 19:31:44 -0800833
834 // get the query-strings for this display for each implementation
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700835 dp->disp[i].queryString.vendor =
Mathias Agopian618fa102009-10-14 02:06:37 -0700836 cnx->egl.eglQueryString(idpy, EGL_VENDOR);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700837 dp->disp[i].queryString.version =
Mathias Agopian618fa102009-10-14 02:06:37 -0700838 cnx->egl.eglQueryString(idpy, EGL_VERSION);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700839 dp->disp[i].queryString.extensions =
Mathias Agopian618fa102009-10-14 02:06:37 -0700840 cnx->egl.eglQueryString(idpy, EGL_EXTENSIONS);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700841 dp->disp[i].queryString.clientApi =
Mathias Agopian618fa102009-10-14 02:06:37 -0700842 cnx->egl.eglQueryString(idpy, EGL_CLIENT_APIS);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800843
844 } else {
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700845 LOGW("%d: eglInitialize(%p) failed (%s)", i, idpy,
Mathias Agopian618fa102009-10-14 02:06:37 -0700846 egl_strerror(cnx->egl.eglGetError()));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800847 }
848 }
849
850 EGLBoolean res = EGL_FALSE;
Mathias Agopian618fa102009-10-14 02:06:37 -0700851 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-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 Agopian618fa102009-10-14 02:06:37 -0700855 if (cnx->egl.eglGetConfigs(dp->disp[i].dpy, 0, 0, &n)) {
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700856 dp->disp[i].config = (EGLConfig*)malloc(sizeof(EGLConfig)*n);
857 if (dp->disp[i].config) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700858 if (cnx->egl.eglGetConfigs(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700859 dp->disp[i].dpy, dp->disp[i].config, n,
860 &dp->disp[i].numConfigs))
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800861 {
The Android Open Source Projectedbf3b62009-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 Agopiancee79392010-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 Agopian75bc2782010-02-05 16:17:01 -0800895 dp->refs++;
The Android Open Source Projectedbf3b62009-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 Agopian923c6612009-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. Gold4aea6bf2011-01-21 15:39:38 -0800909 clearError();
910
The Android Open Source Projectedbf3b62009-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 Agopian75bc2782010-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 Palevich81cd0842010-03-15 20:45:21 -0700921 if (dp->refs > 1) {
922 dp->refs--;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800923 return EGL_TRUE;
Jack Palevich81cd0842010-03-15 20:45:21 -0700924 }
Mathias Agopiande586972009-05-28 17:39:03 -0700925
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800926 EGLBoolean res = EGL_FALSE;
Mathias Agopian618fa102009-10-14 02:06:37 -0700927 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800928 egl_connection_t* const cnx = &gEGLImpl[i];
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700929 if (cnx->dso && dp->disp[i].state == egl_display_t::INITIALIZED) {
Mathias Agopian618fa102009-10-14 02:06:37 -0700930 if (cnx->egl.eglTerminate(dp->disp[i].dpy) == EGL_FALSE) {
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700931 LOGW("%d: eglTerminate(%p) failed (%s)", i, dp->disp[i].dpy,
Mathias Agopian618fa102009-10-14 02:06:37 -0700932 egl_strerror(cnx->egl.eglGetError()));
Mathias Agopiana69e0ed2009-08-24 21:47:13 -0700933 }
Mathias Agopian923c6612009-08-17 18:07:06 -0700934 // REVISIT: it's unclear what to do if eglTerminate() fails
Mathias Agopiana69e0ed2009-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 Projectedbf3b62009-03-03 19:31:44 -0800941 res = EGL_TRUE;
942 }
943 }
Mathias Agopian9429e9c2009-08-21 02:18:25 -0700944
945 // TODO: all egl_object_t should be marked for termination
946
Mathias Agopian75bc2782010-02-05 16:17:01 -0800947 dp->refs--;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800948 dp->numTotalConfigs = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -0700949 delete [] dp->configs;
Michael I. Gold0c3ce2a2010-12-23 13:51:36 -0800950
The Android Open Source Projectedbf3b62009-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. Gold4aea6bf2011-01-21 15:39:38 -0800962 clearError();
963
Eric Hassold3ede7c12011-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 Projectedbf3b62009-03-03 19:31:44 -0800966
967 GLint numConfigs = dp->numTotalConfigs;
968 if (!configs) {
969 *num_config = numConfigs;
970 return EGL_TRUE;
971 }
Mathias Agopiancee79392010-07-26 21:14:59 -0700972
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800973 GLint n = 0;
Mathias Agopiancee79392010-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 Projectedbf3b62009-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. Gold4aea6bf2011-01-21 15:39:38 -0800988 clearError();
989
Eric Hassold3ede7c12011-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 Projectedbf3b62009-03-03 19:31:44 -0800992
Jack Palevich749c63d2009-03-25 15:12:17 -0700993 if (num_config==0) {
994 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
The Android Open Source Projectedbf3b62009-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 Agopiancee79392010-07-26 21:14:59 -07001003 // to do this, we have to go through the attrib_list array once
The Android Open Source Projectedbf3b62009-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 Agopian04aed212010-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 Projectedbf3b62009-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 Agopiancee79392010-07-26 21:14:59 -07001027 bool found = false;
1028 EGLConfig ourConfig(0);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001029 EGLint& configId(new_list[patch_index+1]);
Mathias Agopiancee79392010-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 Projectedbf3b62009-03-03 19:31:44 -08001038
Mathias Agopiancee79392010-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 Projectedbf3b62009-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 Agopian618fa102009-10-14 02:06:37 -07001047 // cnx->egl.eglChooseConfig() -- but we don't have to loop
The Android Open Source Projectedbf3b62009-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 Agopian618fa102009-10-14 02:06:37 -07001052 res = cnx->egl.eglChooseConfig(
Mathias Agopiancee79392010-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 Projectedbf3b62009-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 Palevich749c63d2009-03-25 15:12:17 -07001058 if (configs) {
Mathias Agopiancee79392010-07-26 21:14:59 -07001059 configs[0] = ourConfig;
Jack Palevich749c63d2009-03-25 15:12:17 -07001060 }
The Android Open Source Projectedbf3b62009-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 Agopiancee79392010-07-26 21:14:59 -07001069
Mathias Agopian618fa102009-10-14 02:06:37 -07001070 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001071 egl_connection_t* const cnx = &gEGLImpl[i];
1072 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001073 if (cnx->egl.eglChooseConfig(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001074 dp->disp[i].dpy, attrib_list, configs, config_size, &n)) {
Jack Palevich749c63d2009-03-25 15:12:17 -07001075 if (configs) {
1076 // now we need to convert these client EGLConfig to our
Mathias Agopiancee79392010-07-26 21:14:59 -07001077 // internal EGLConfig format.
1078 // This is done in O(n Log(n)) time.
Jack Palevich749c63d2009-03-25 15:12:17 -07001079 for (int j=0 ; j<n ; j++) {
Mathias Agopiancee79392010-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 Palevich749c63d2009-03-25 15:12:17 -07001083 if (index >= 0) {
Mathias Agopiancee79392010-07-26 21:14:59 -07001084 configs[j] = EGLConfig(index);
Jack Palevich749c63d2009-03-25 15:12:17 -07001085 } else {
1086 return setError(EGL_BAD_CONFIG, EGL_FALSE);
1087 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001088 }
Jack Palevich749c63d2009-03-25 15:12:17 -07001089 configs += n;
1090 config_size -= n;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001091 }
The Android Open Source Projectedbf3b62009-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. Gold4aea6bf2011-01-21 15:39:38 -08001103 clearError();
1104
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001105 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -07001106 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001107 if (!cnx) return EGL_FALSE;
1108
1109 if (attribute == EGL_CONFIG_ID) {
Mathias Agopiancee79392010-07-26 21:14:59 -07001110 *value = dp->configs[intptr_t(config)].configId;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001111 return EGL_TRUE;
1112 }
Mathias Agopian618fa102009-10-14 02:06:37 -07001113 return cnx->egl.eglGetConfigAttrib(
Mathias Agopiancee79392010-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 Projectedbf3b62009-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. Gold4aea6bf2011-01-21 15:39:38 -08001126 clearError();
1127
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001128 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -07001129 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001130 if (cnx) {
Mathias Agopian644bb2a2010-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
Jamie Gennis5c0c93a2011-03-14 15:34:04 -07001135 // for now fail if the window is not a Surface.
1136 int type = -1;
1137 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
1138 if ((anw->query(window, NATIVE_WINDOW_CONCRETE_TYPE, &type) != 0) ||
1139 (type == NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT)) {
1140 LOGE("native window is a SurfaceTextureClient (currently "
1141 "unsupported)");
1142 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
1143 }
1144
Mathias Agopian644bb2a2010-11-24 15:59:35 -08001145 // set the native window's buffers format to match this config
1146 if (cnx->egl.eglGetConfigAttrib(iDpy,
1147 iConfig, EGL_NATIVE_VISUAL_ID, &format)) {
1148 if (format != 0) {
1149 native_window_set_buffers_geometry(window, 0, 0, format);
1150 }
1151 }
1152
Mathias Agopian618fa102009-10-14 02:06:37 -07001153 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian644bb2a2010-11-24 15:59:35 -08001154 iDpy, iConfig, window, attrib_list);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001155 if (surface != EGL_NO_SURFACE) {
Mathias Agopian644bb2a2010-11-24 15:59:35 -08001156 egl_surface_t* s = new egl_surface_t(dpy, config, window, surface,
Mathias Agopiancee79392010-07-26 21:14:59 -07001157 dp->configs[intptr_t(config)].impl, cnx);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001158 return s;
1159 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001160 }
1161 return EGL_NO_SURFACE;
1162}
1163
1164EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
1165 NativePixmapType pixmap,
1166 const EGLint *attrib_list)
1167{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001168 clearError();
1169
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001170 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -07001171 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001172 if (cnx) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001173 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopiancee79392010-07-26 21:14:59 -07001174 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1175 dp->configs[intptr_t(config)].config, pixmap, attrib_list);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001176 if (surface != EGL_NO_SURFACE) {
Mathias Agopian644bb2a2010-11-24 15:59:35 -08001177 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
Mathias Agopiancee79392010-07-26 21:14:59 -07001178 dp->configs[intptr_t(config)].impl, cnx);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001179 return s;
1180 }
1181 }
1182 return EGL_NO_SURFACE;
1183}
1184
1185EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
1186 const EGLint *attrib_list)
1187{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001188 clearError();
1189
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001190 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -07001191 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001192 if (cnx) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001193 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopiancee79392010-07-26 21:14:59 -07001194 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1195 dp->configs[intptr_t(config)].config, attrib_list);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001196 if (surface != EGL_NO_SURFACE) {
Mathias Agopian644bb2a2010-11-24 15:59:35 -08001197 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
Mathias Agopiancee79392010-07-26 21:14:59 -07001198 dp->configs[intptr_t(config)].impl, cnx);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001199 return s;
1200 }
1201 }
1202 return EGL_NO_SURFACE;
1203}
1204
1205EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
1206{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001207 clearError();
1208
Eric Hassold3ede7c12011-03-23 15:59:00 -07001209 egl_display_t const * const dp = validate_display(dpy);
1210 if (!dp) return EGL_FALSE;
1211
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001212 SurfaceRef _s(surface);
1213 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1214
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001215 if (!validate_display_surface(dpy, surface))
1216 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001217
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001218 egl_surface_t * const s = get_surface(surface);
Mathias Agopian618fa102009-10-14 02:06:37 -07001219 EGLBoolean result = s->cnx->egl.eglDestroySurface(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001220 dp->disp[s->impl].dpy, s->surface);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001221 if (result == EGL_TRUE) {
Mathias Agopian644bb2a2010-11-24 15:59:35 -08001222 if (s->win != NULL) {
1223 native_window_set_buffers_geometry(s->win.get(), 0, 0, 0);
1224 }
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001225 _s.terminate();
1226 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001227 return result;
1228}
1229
1230EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
1231 EGLint attribute, EGLint *value)
1232{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001233 clearError();
1234
Eric Hassold3ede7c12011-03-23 15:59:00 -07001235 egl_display_t const * const dp = validate_display(dpy);
1236 if (!dp) return EGL_FALSE;
1237
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001238 SurfaceRef _s(surface);
1239 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1240
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001241 if (!validate_display_surface(dpy, surface))
1242 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001243 egl_surface_t const * const s = get_surface(surface);
1244
Mathias Agopiancee79392010-07-26 21:14:59 -07001245 EGLBoolean result(EGL_TRUE);
1246 if (attribute == EGL_CONFIG_ID) {
1247 // We need to remap EGL_CONFIG_IDs
1248 *value = dp->configs[intptr_t(s->config)].configId;
1249 } else {
1250 result = s->cnx->egl.eglQuerySurface(
1251 dp->disp[s->impl].dpy, s->surface, attribute, value);
1252 }
1253
1254 return result;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001255}
1256
1257// ----------------------------------------------------------------------------
Mathias Agopiancee79392010-07-26 21:14:59 -07001258// Contexts
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001259// ----------------------------------------------------------------------------
1260
1261EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
1262 EGLContext share_list, const EGLint *attrib_list)
1263{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001264 clearError();
1265
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001266 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -07001267 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001268 if (cnx) {
Jamie Gennis4c39f8f2010-07-02 11:39:12 -07001269 if (share_list != EGL_NO_CONTEXT) {
1270 egl_context_t* const c = get_context(share_list);
1271 share_list = c->context;
1272 }
Mathias Agopian618fa102009-10-14 02:06:37 -07001273 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopiancee79392010-07-26 21:14:59 -07001274 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1275 dp->configs[intptr_t(config)].config,
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001276 share_list, attrib_list);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001277 if (context != EGL_NO_CONTEXT) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001278 // figure out if it's a GLESv1 or GLESv2
1279 int version = 0;
1280 if (attrib_list) {
1281 while (*attrib_list != EGL_NONE) {
1282 GLint attr = *attrib_list++;
1283 GLint value = *attrib_list++;
1284 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
1285 if (value == 1) {
1286 version = GLESv1_INDEX;
1287 } else if (value == 2) {
1288 version = GLESv2_INDEX;
1289 }
1290 }
1291 };
1292 }
Mathias Agopiancee79392010-07-26 21:14:59 -07001293 egl_context_t* c = new egl_context_t(dpy, context, config,
1294 dp->configs[intptr_t(config)].impl, cnx, version);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001295 return c;
1296 }
1297 }
1298 return EGL_NO_CONTEXT;
1299}
1300
1301EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1302{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001303 clearError();
1304
Eric Hassold3ede7c12011-03-23 15:59:00 -07001305 egl_display_t const * const dp = validate_display(dpy);
1306 if (!dp) return EGL_FALSE;
1307
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001308 ContextRef _c(ctx);
1309 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1310
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001311 if (!validate_display_context(dpy, ctx))
1312 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001313 egl_context_t * const c = get_context(ctx);
Mathias Agopian618fa102009-10-14 02:06:37 -07001314 EGLBoolean result = c->cnx->egl.eglDestroyContext(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001315 dp->disp[c->impl].dpy, c->context);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001316 if (result == EGL_TRUE) {
1317 _c.terminate();
1318 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001319 return result;
1320}
1321
Michael I. Gold0c3ce2a2010-12-23 13:51:36 -08001322static void loseCurrent(egl_context_t * cur_c)
1323{
1324 if (cur_c) {
1325 egl_surface_t * cur_r = get_surface(cur_c->read);
1326 egl_surface_t * cur_d = get_surface(cur_c->draw);
1327
1328 // by construction, these are either 0 or valid (possibly terminated)
1329 // it should be impossible for these to be invalid
1330 ContextRef _cur_c(cur_c);
1331 SurfaceRef _cur_r(cur_r);
1332 SurfaceRef _cur_d(cur_d);
1333
1334 cur_c->read = NULL;
1335 cur_c->draw = NULL;
1336
1337 _cur_c.release();
1338 _cur_r.release();
1339 _cur_d.release();
1340 }
1341}
1342
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001343EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
1344 EGLSurface read, EGLContext ctx)
1345{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001346 clearError();
1347
Eric Hassold3ede7c12011-03-23 15:59:00 -07001348 egl_display_t const * const dp = get_display(dpy);
1349 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1350
1351 /* If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
1352 EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
1353 a valid but uninitialized display. */
1354 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
1355 (draw != EGL_NO_SURFACE) ) {
1356 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
1357 }
1358
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001359 // get a reference to the object passed in
1360 ContextRef _c(ctx);
1361 SurfaceRef _d(draw);
1362 SurfaceRef _r(read);
1363
Eric Hassold3ede7c12011-03-23 15:59:00 -07001364 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001365 if ((ctx != EGL_NO_CONTEXT) && (!validate_display_context(dpy, ctx))) {
1366 // EGL_NO_CONTEXT is valid
1367 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001368 }
1369
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001370 // these are the underlying implementation's object
1371 EGLContext impl_ctx = EGL_NO_CONTEXT;
Mathias Agopianaf742132009-06-25 00:01:11 -07001372 EGLSurface impl_draw = EGL_NO_SURFACE;
1373 EGLSurface impl_read = EGL_NO_SURFACE;
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001374
1375 // these are our objects structs passed in
1376 egl_context_t * c = NULL;
1377 egl_surface_t const * d = NULL;
1378 egl_surface_t const * r = NULL;
1379
1380 // these are the current objects structs
1381 egl_context_t * cur_c = get_context(getContext());
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001382
1383 if (ctx != EGL_NO_CONTEXT) {
1384 c = get_context(ctx);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001385 impl_ctx = c->context;
1386 } else {
1387 // no context given, use the implementation of the current context
1388 if (cur_c == NULL) {
1389 // no current context
1390 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
Mathias Agopian8063c3a2010-01-25 11:30:11 -08001391 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
1392 return setError(EGL_BAD_MATCH, EGL_FALSE);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001393 }
Mathias Agopian8063c3a2010-01-25 11:30:11 -08001394 // not an error, there is just no current context.
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001395 return EGL_TRUE;
1396 }
1397 }
1398
1399 // retrieve the underlying implementation's draw EGLSurface
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001400 if (draw != EGL_NO_SURFACE) {
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001401 d = get_surface(draw);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001402 // make sure the EGLContext and EGLSurface passed in are for
1403 // the same driver
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001404 if (c && d->impl != c->impl)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001405 return setError(EGL_BAD_MATCH, EGL_FALSE);
Mathias Agopianaf742132009-06-25 00:01:11 -07001406 impl_draw = d->surface;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001407 }
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001408
1409 // retrieve the underlying implementation's read EGLSurface
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001410 if (read != EGL_NO_SURFACE) {
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001411 r = get_surface(read);
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001412 // make sure the EGLContext and EGLSurface passed in are for
1413 // the same driver
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001414 if (c && r->impl != c->impl)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001415 return setError(EGL_BAD_MATCH, EGL_FALSE);
Mathias Agopianaf742132009-06-25 00:01:11 -07001416 impl_read = r->surface;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001417 }
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001418
1419 EGLBoolean result;
1420
1421 if (c) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001422 result = c->cnx->egl.eglMakeCurrent(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001423 dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001424 } else {
Mathias Agopian618fa102009-10-14 02:06:37 -07001425 result = cur_c->cnx->egl.eglMakeCurrent(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001426 dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001427 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001428
1429 if (result == EGL_TRUE) {
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001430
Michael I. Gold0c3ce2a2010-12-23 13:51:36 -08001431 loseCurrent(cur_c);
1432
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001433 if (ctx != EGL_NO_CONTEXT) {
Jack Palevicha2dd6cf2010-10-26 15:21:24 -07001434 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001435 setContext(ctx);
David Li864f8392011-03-28 10:39:28 -07001436 tls_t * const tls = getTLS();
1437 if (!tls->dbg && gEGLDebugLevel > 0)
1438 tls->dbg = CreateDbgContext(gEGLThreadLocalStorageKey, c->version,
1439 c->cnx->hooks[c->version]);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001440 _c.acquire();
Michael I. Gold0c3ce2a2010-12-23 13:51:36 -08001441 _r.acquire();
1442 _d.acquire();
1443 c->read = read;
1444 c->draw = draw;
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001445 } else {
Jack Palevicha2dd6cf2010-10-26 15:21:24 -07001446 setGLHooksThreadSpecific(&gHooksNoContext);
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001447 setContext(EGL_NO_CONTEXT);
1448 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001449 }
1450 return result;
1451}
1452
1453
1454EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
1455 EGLint attribute, EGLint *value)
1456{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001457 clearError();
1458
Eric Hassold3ede7c12011-03-23 15:59:00 -07001459 egl_display_t const * const dp = validate_display(dpy);
1460 if (!dp) return EGL_FALSE;
1461
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001462 ContextRef _c(ctx);
1463 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1464
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001465 if (!validate_display_context(dpy, ctx))
1466 return EGL_FALSE;
1467
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001468 egl_context_t * const c = get_context(ctx);
1469
Mathias Agopiancee79392010-07-26 21:14:59 -07001470 EGLBoolean result(EGL_TRUE);
1471 if (attribute == EGL_CONFIG_ID) {
1472 *value = dp->configs[intptr_t(c->config)].configId;
1473 } else {
1474 // We need to remap EGL_CONFIG_IDs
1475 result = c->cnx->egl.eglQueryContext(
1476 dp->disp[c->impl].dpy, c->context, attribute, value);
1477 }
1478
1479 return result;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001480}
1481
1482EGLContext eglGetCurrentContext(void)
1483{
Mathias Agopian923c6612009-08-17 18:07:06 -07001484 // could be called before eglInitialize(), but we wouldn't have a context
1485 // then, and this function would correctly return EGL_NO_CONTEXT.
1486
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001487 clearError();
1488
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001489 EGLContext ctx = getContext();
1490 return ctx;
1491}
1492
1493EGLSurface eglGetCurrentSurface(EGLint readdraw)
1494{
Mathias Agopian923c6612009-08-17 18:07:06 -07001495 // could be called before eglInitialize(), but we wouldn't have a context
1496 // then, and this function would correctly return EGL_NO_SURFACE.
1497
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001498 clearError();
1499
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001500 EGLContext ctx = getContext();
1501 if (ctx) {
1502 egl_context_t const * const c = get_context(ctx);
1503 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1504 switch (readdraw) {
1505 case EGL_READ: return c->read;
1506 case EGL_DRAW: return c->draw;
1507 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1508 }
1509 }
1510 return EGL_NO_SURFACE;
1511}
1512
1513EGLDisplay eglGetCurrentDisplay(void)
1514{
Mathias Agopian923c6612009-08-17 18:07:06 -07001515 // could be called before eglInitialize(), but we wouldn't have a context
1516 // then, and this function would correctly return EGL_NO_DISPLAY.
1517
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001518 clearError();
1519
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001520 EGLContext ctx = getContext();
1521 if (ctx) {
1522 egl_context_t const * const c = get_context(ctx);
1523 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1524 return c->dpy;
1525 }
1526 return EGL_NO_DISPLAY;
1527}
1528
1529EGLBoolean eglWaitGL(void)
1530{
Mathias Agopian923c6612009-08-17 18:07:06 -07001531 // could be called before eglInitialize(), but we wouldn't have a context
1532 // then, and this function would return GL_TRUE, which isn't wrong.
1533
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001534 clearError();
1535
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001536 EGLBoolean res = EGL_TRUE;
1537 EGLContext ctx = getContext();
1538 if (ctx) {
1539 egl_context_t const * const c = get_context(ctx);
1540 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1541 if (uint32_t(c->impl)>=2)
1542 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1543 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1544 if (!cnx->dso)
1545 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian618fa102009-10-14 02:06:37 -07001546 res = cnx->egl.eglWaitGL();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001547 }
1548 return res;
1549}
1550
1551EGLBoolean eglWaitNative(EGLint engine)
1552{
Mathias Agopian923c6612009-08-17 18:07:06 -07001553 // could be called before eglInitialize(), but we wouldn't have a context
1554 // then, and this function would return GL_TRUE, which isn't wrong.
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001555
1556 clearError();
1557
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001558 EGLBoolean res = EGL_TRUE;
1559 EGLContext ctx = getContext();
1560 if (ctx) {
1561 egl_context_t const * const c = get_context(ctx);
1562 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1563 if (uint32_t(c->impl)>=2)
1564 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1565 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1566 if (!cnx->dso)
1567 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian618fa102009-10-14 02:06:37 -07001568 res = cnx->egl.eglWaitNative(engine);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001569 }
1570 return res;
1571}
1572
1573EGLint eglGetError(void)
1574{
1575 EGLint result = EGL_SUCCESS;
Mathias Agopian02dafb52010-09-21 15:43:59 -07001576 EGLint err;
Mathias Agopian618fa102009-10-14 02:06:37 -07001577 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
Mathias Agopian02dafb52010-09-21 15:43:59 -07001578 err = EGL_SUCCESS;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001579 egl_connection_t* const cnx = &gEGLImpl[i];
1580 if (cnx->dso)
Mathias Agopian618fa102009-10-14 02:06:37 -07001581 err = cnx->egl.eglGetError();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001582 if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
1583 result = err;
1584 }
Mathias Agopian02dafb52010-09-21 15:43:59 -07001585 err = getError();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001586 if (result == EGL_SUCCESS)
Mathias Agopian02dafb52010-09-21 15:43:59 -07001587 result = err;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001588 return result;
1589}
1590
Michael I. Gold609bb4d2011-01-04 01:16:59 -08001591// Note: Similar implementations of these functions also exist in
1592// gl2.cpp and gl.cpp, and are used by applications that call the
1593// exported entry points directly.
1594typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
1595typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
1596
1597static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL;
1598static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL;
1599
1600static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image)
1601{
1602 GLeglImageOES implImage =
1603 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
1604 glEGLImageTargetTexture2DOES_impl(target, implImage);
1605}
1606
1607static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image)
1608{
1609 GLeglImageOES implImage =
1610 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
1611 glEGLImageTargetRenderbufferStorageOES_impl(target, implImage);
1612}
1613
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001614__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001615{
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001616 // eglGetProcAddress() could be the very first function called
1617 // in which case we must make sure we've initialized ourselves, this
1618 // happens the first time egl_get_display() is called.
Mathias Agopian923c6612009-08-17 18:07:06 -07001619
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001620 clearError();
1621
Mathias Agopian923c6612009-08-17 18:07:06 -07001622 if (egl_init_drivers() == EGL_FALSE) {
1623 setError(EGL_BAD_PARAMETER, NULL);
1624 return NULL;
1625 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001626
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001627 __eglMustCastToProperFunctionPointerType addr;
1628 addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap));
1629 if (addr) return addr;
1630
Mathias Agopian24035332010-08-02 17:34:32 -07001631 // this protects accesses to gGLExtentionMap and gGLExtentionSlot
1632 pthread_mutex_lock(&gInitDriverMutex);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001633
Mathias Agopian24035332010-08-02 17:34:32 -07001634 /*
1635 * Since eglGetProcAddress() is not associated to anything, it needs
1636 * to return a function pointer that "works" regardless of what
1637 * the current context is.
1638 *
1639 * For this reason, we return a "forwarder", a small stub that takes
1640 * care of calling the function associated with the context
1641 * currently bound.
1642 *
1643 * We first look for extensions we've already resolved, if we're seeing
1644 * this extension for the first time, we go through all our
1645 * implementations and call eglGetProcAddress() and record the
1646 * result in the appropriate implementation hooks and return the
1647 * address of the forwarder corresponding to that hook set.
1648 *
1649 */
1650
1651 const String8 name(procname);
1652 addr = gGLExtentionMap.valueFor(name);
1653 const int slot = gGLExtentionSlot;
1654
1655 LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
1656 "no more slots for eglGetProcAddress(\"%s\")",
1657 procname);
1658
1659 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
1660 bool found = false;
1661 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1662 egl_connection_t* const cnx = &gEGLImpl[i];
1663 if (cnx->dso && cnx->egl.eglGetProcAddress) {
1664 found = true;
Mathias Agopian4a88b522010-08-13 12:19:04 -07001665 // Extensions are independent of the bound context
1666 cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
1667 cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
Jack Palevicha2dd6cf2010-10-26 15:21:24 -07001668#if EGL_TRACE
David Li2f5a6552011-03-01 16:08:10 -08001669 gHooksDebug.ext.extensions[slot] = gHooksTrace.ext.extensions[slot] =
Jack Palevicha2dd6cf2010-10-26 15:21:24 -07001670#endif
Mathias Agopian24035332010-08-02 17:34:32 -07001671 cnx->egl.eglGetProcAddress(procname);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001672 }
1673 }
Mathias Agopian24035332010-08-02 17:34:32 -07001674 if (found) {
1675 addr = gExtensionForwarders[slot];
Michael I. Gold609bb4d2011-01-04 01:16:59 -08001676
1677 if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) {
1678 glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr;
1679 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper;
1680 }
1681 if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) {
1682 glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr;
1683 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper;
1684 }
1685
Mathias Agopian24035332010-08-02 17:34:32 -07001686 gGLExtentionMap.add(name, addr);
1687 gGLExtentionSlot++;
1688 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001689 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001690
Mathias Agopian24035332010-08-02 17:34:32 -07001691 pthread_mutex_unlock(&gInitDriverMutex);
Mathias Agopian24035332010-08-02 17:34:32 -07001692 return addr;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001693}
1694
1695EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
1696{
David Lib33d5cf2011-03-04 17:50:48 -08001697 EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw);
1698 if (gEGLDebugLevel > 0)
1699 Debug_eglSwapBuffers(dpy, draw);
1700
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001701 clearError();
1702
Eric Hassold3ede7c12011-03-23 15:59:00 -07001703 egl_display_t const * const dp = validate_display(dpy);
1704 if (!dp) return EGL_FALSE;
1705
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001706 SurfaceRef _s(draw);
1707 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1708
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001709 if (!validate_display_surface(dpy, draw))
1710 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001711 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian618fa102009-10-14 02:06:37 -07001712 return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001713}
1714
1715EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1716 NativePixmapType target)
1717{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001718 clearError();
1719
Eric Hassold3ede7c12011-03-23 15:59:00 -07001720 egl_display_t const * const dp = validate_display(dpy);
1721 if (!dp) return EGL_FALSE;
1722
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001723 SurfaceRef _s(surface);
1724 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1725
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001726 if (!validate_display_surface(dpy, surface))
1727 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001728 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian618fa102009-10-14 02:06:37 -07001729 return s->cnx->egl.eglCopyBuffers(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001730 dp->disp[s->impl].dpy, s->surface, target);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001731}
1732
1733const char* eglQueryString(EGLDisplay dpy, EGLint name)
1734{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001735 clearError();
1736
Eric Hassold3ede7c12011-03-23 15:59:00 -07001737 egl_display_t const * const dp = validate_display(dpy);
1738 if (!dp) return (const char *) NULL;
1739
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001740 switch (name) {
1741 case EGL_VENDOR:
1742 return gVendorString;
1743 case EGL_VERSION:
1744 return gVersionString;
1745 case EGL_EXTENSIONS:
1746 return gExtensionString;
1747 case EGL_CLIENT_APIS:
1748 return gClientApiString;
1749 }
1750 return setError(EGL_BAD_PARAMETER, (const char *)0);
1751}
1752
1753
1754// ----------------------------------------------------------------------------
1755// EGL 1.1
1756// ----------------------------------------------------------------------------
1757
1758EGLBoolean eglSurfaceAttrib(
1759 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1760{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001761 clearError();
1762
Eric Hassold3ede7c12011-03-23 15:59:00 -07001763 egl_display_t const * const dp = validate_display(dpy);
1764 if (!dp) return EGL_FALSE;
1765
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001766 SurfaceRef _s(surface);
1767 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1768
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001769 if (!validate_display_surface(dpy, surface))
1770 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001771 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian618fa102009-10-14 02:06:37 -07001772 if (s->cnx->egl.eglSurfaceAttrib) {
1773 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001774 dp->disp[s->impl].dpy, s->surface, attribute, value);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001775 }
1776 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1777}
1778
1779EGLBoolean eglBindTexImage(
1780 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1781{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001782 clearError();
1783
Eric Hassold3ede7c12011-03-23 15:59:00 -07001784 egl_display_t const * const dp = validate_display(dpy);
1785 if (!dp) return EGL_FALSE;
1786
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001787 SurfaceRef _s(surface);
1788 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1789
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001790 if (!validate_display_surface(dpy, surface))
1791 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001792 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian618fa102009-10-14 02:06:37 -07001793 if (s->cnx->egl.eglBindTexImage) {
1794 return s->cnx->egl.eglBindTexImage(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001795 dp->disp[s->impl].dpy, s->surface, buffer);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001796 }
1797 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1798}
1799
1800EGLBoolean eglReleaseTexImage(
1801 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1802{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001803 clearError();
1804
Eric Hassold3ede7c12011-03-23 15:59:00 -07001805 egl_display_t const * const dp = validate_display(dpy);
1806 if (!dp) return EGL_FALSE;
1807
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001808 SurfaceRef _s(surface);
1809 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1810
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001811 if (!validate_display_surface(dpy, surface))
1812 return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001813 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian618fa102009-10-14 02:06:37 -07001814 if (s->cnx->egl.eglReleaseTexImage) {
1815 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001816 dp->disp[s->impl].dpy, s->surface, buffer);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001817 }
1818 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1819}
1820
1821EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1822{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001823 clearError();
1824
Eric Hassold3ede7c12011-03-23 15:59:00 -07001825 egl_display_t const * const dp = validate_display(dpy);
1826 if (!dp) return EGL_FALSE;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001827
1828 EGLBoolean res = EGL_TRUE;
Mathias Agopian618fa102009-10-14 02:06:37 -07001829 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001830 egl_connection_t* const cnx = &gEGLImpl[i];
1831 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001832 if (cnx->egl.eglSwapInterval) {
1833 if (cnx->egl.eglSwapInterval(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001834 dp->disp[i].dpy, interval) == EGL_FALSE) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001835 res = EGL_FALSE;
1836 }
1837 }
1838 }
1839 }
1840 return res;
1841}
1842
1843
1844// ----------------------------------------------------------------------------
1845// EGL 1.2
1846// ----------------------------------------------------------------------------
1847
1848EGLBoolean eglWaitClient(void)
1849{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001850 clearError();
1851
Mathias Agopian923c6612009-08-17 18:07:06 -07001852 // could be called before eglInitialize(), but we wouldn't have a context
1853 // then, and this function would return GL_TRUE, which isn't wrong.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001854 EGLBoolean res = EGL_TRUE;
1855 EGLContext ctx = getContext();
1856 if (ctx) {
1857 egl_context_t const * const c = get_context(ctx);
1858 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1859 if (uint32_t(c->impl)>=2)
1860 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1861 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1862 if (!cnx->dso)
1863 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian618fa102009-10-14 02:06:37 -07001864 if (cnx->egl.eglWaitClient) {
1865 res = cnx->egl.eglWaitClient();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001866 } else {
Mathias Agopian618fa102009-10-14 02:06:37 -07001867 res = cnx->egl.eglWaitGL();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001868 }
1869 }
1870 return res;
1871}
1872
1873EGLBoolean eglBindAPI(EGLenum api)
1874{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001875 clearError();
1876
Mathias Agopian923c6612009-08-17 18:07:06 -07001877 if (egl_init_drivers() == EGL_FALSE) {
1878 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1879 }
1880
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001881 // bind this API on all EGLs
1882 EGLBoolean res = EGL_TRUE;
Mathias Agopian618fa102009-10-14 02:06:37 -07001883 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001884 egl_connection_t* const cnx = &gEGLImpl[i];
1885 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001886 if (cnx->egl.eglBindAPI) {
1887 if (cnx->egl.eglBindAPI(api) == EGL_FALSE) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001888 res = EGL_FALSE;
1889 }
1890 }
1891 }
1892 }
1893 return res;
1894}
1895
1896EGLenum eglQueryAPI(void)
1897{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001898 clearError();
1899
Mathias Agopian923c6612009-08-17 18:07:06 -07001900 if (egl_init_drivers() == EGL_FALSE) {
1901 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1902 }
1903
Mathias Agopian618fa102009-10-14 02:06:37 -07001904 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001905 egl_connection_t* const cnx = &gEGLImpl[i];
1906 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001907 if (cnx->egl.eglQueryAPI) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001908 // the first one we find is okay, because they all
1909 // should be the same
Mathias Agopian618fa102009-10-14 02:06:37 -07001910 return cnx->egl.eglQueryAPI();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001911 }
1912 }
1913 }
1914 // or, it can only be OpenGL ES
1915 return EGL_OPENGL_ES_API;
1916}
1917
1918EGLBoolean eglReleaseThread(void)
1919{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001920 clearError();
1921
Michael I. Gold0c3ce2a2010-12-23 13:51:36 -08001922 // If there is context bound to the thread, release it
1923 loseCurrent(get_context(getContext()));
1924
Mathias Agopian618fa102009-10-14 02:06:37 -07001925 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001926 egl_connection_t* const cnx = &gEGLImpl[i];
1927 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07001928 if (cnx->egl.eglReleaseThread) {
1929 cnx->egl.eglReleaseThread();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001930 }
1931 }
1932 }
1933 clearTLS();
1934 return EGL_TRUE;
1935}
1936
1937EGLSurface eglCreatePbufferFromClientBuffer(
1938 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1939 EGLConfig config, const EGLint *attrib_list)
1940{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001941 clearError();
1942
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001943 egl_display_t const* dp = 0;
Mathias Agopiancee79392010-07-26 21:14:59 -07001944 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001945 if (!cnx) return EGL_FALSE;
Mathias Agopian618fa102009-10-14 02:06:37 -07001946 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1947 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopiancee79392010-07-26 21:14:59 -07001948 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1949 buftype, buffer,
1950 dp->configs[intptr_t(config)].config, attrib_list);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001951 }
1952 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1953}
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001954
1955// ----------------------------------------------------------------------------
1956// EGL_EGLEXT_VERSION 3
1957// ----------------------------------------------------------------------------
1958
1959EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1960 const EGLint *attrib_list)
1961{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001962 clearError();
1963
Eric Hassold3ede7c12011-03-23 15:59:00 -07001964 egl_display_t const * const dp = validate_display(dpy);
1965 if (!dp) return EGL_FALSE;
1966
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001967 SurfaceRef _s(surface);
1968 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1969
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001970 if (!validate_display_surface(dpy, surface))
Mathias Agopian24e5f522009-08-12 21:18:15 -07001971 return EGL_FALSE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001972
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001973 egl_surface_t const * const s = get_surface(surface);
1974
Mathias Agopian618fa102009-10-14 02:06:37 -07001975 if (s->cnx->egl.eglLockSurfaceKHR) {
1976 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001977 dp->disp[s->impl].dpy, s->surface, attrib_list);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001978 }
Mathias Agopian24e5f522009-08-12 21:18:15 -07001979 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001980}
1981
1982EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1983{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08001984 clearError();
1985
Eric Hassold3ede7c12011-03-23 15:59:00 -07001986 egl_display_t const * const dp = validate_display(dpy);
1987 if (!dp) return EGL_FALSE;
1988
Mathias Agopian9429e9c2009-08-21 02:18:25 -07001989 SurfaceRef _s(surface);
1990 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
1991
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001992 if (!validate_display_surface(dpy, surface))
Mathias Agopian24e5f522009-08-12 21:18:15 -07001993 return EGL_FALSE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001994
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001995 egl_surface_t const * const s = get_surface(surface);
1996
Mathias Agopian618fa102009-10-14 02:06:37 -07001997 if (s->cnx->egl.eglUnlockSurfaceKHR) {
1998 return s->cnx->egl.eglUnlockSurfaceKHR(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07001999 dp->disp[s->impl].dpy, s->surface);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002000 }
Mathias Agopian24e5f522009-08-12 21:18:15 -07002001 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002002}
2003
2004EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
2005 EGLClientBuffer buffer, const EGLint *attrib_list)
2006{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08002007 clearError();
2008
Eric Hassold3ede7c12011-03-23 15:59:00 -07002009 egl_display_t const * const dp = validate_display(dpy);
2010 if (!dp) return EGL_NO_IMAGE_KHR;
2011
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002012 if (ctx != EGL_NO_CONTEXT) {
Mathias Agopian9429e9c2009-08-21 02:18:25 -07002013 ContextRef _c(ctx);
2014 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002015 if (!validate_display_context(dpy, ctx))
2016 return EGL_NO_IMAGE_KHR;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002017 egl_context_t * const c = get_context(ctx);
2018 // since we have an EGLContext, we know which implementation to use
Mathias Agopian618fa102009-10-14 02:06:37 -07002019 EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07002020 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002021 if (image == EGL_NO_IMAGE_KHR)
2022 return image;
2023
2024 egl_image_t* result = new egl_image_t(dpy, ctx);
2025 result->images[c->impl] = image;
2026 return (EGLImageKHR)result;
2027 } else {
2028 // EGL_NO_CONTEXT is a valid parameter
Mathias Agopiandf2d9292009-10-28 21:00:29 -07002029
2030 /* Since we don't have a way to know which implementation to call,
2031 * we're calling all of them. If at least one of the implementation
2032 * succeeded, this is a success.
2033 */
2034
2035 EGLint currentError = eglGetError();
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002036
Mathias Agopian618fa102009-10-14 02:06:37 -07002037 EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS];
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002038 bool success = false;
Mathias Agopian618fa102009-10-14 02:06:37 -07002039 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002040 egl_connection_t* const cnx = &gEGLImpl[i];
2041 implImages[i] = EGL_NO_IMAGE_KHR;
2042 if (cnx->dso) {
Mathias Agopian618fa102009-10-14 02:06:37 -07002043 if (cnx->egl.eglCreateImageKHR) {
2044 implImages[i] = cnx->egl.eglCreateImageKHR(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07002045 dp->disp[i].dpy, ctx, target, buffer, attrib_list);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002046 if (implImages[i] != EGL_NO_IMAGE_KHR) {
2047 success = true;
2048 }
2049 }
2050 }
2051 }
Mathias Agopiandf2d9292009-10-28 21:00:29 -07002052
2053 if (!success) {
2054 // failure, if there was an error when we entered this function,
2055 // the error flag must not be updated.
2056 // Otherwise, the error is whatever happened in the implementation
2057 // that faulted.
2058 if (currentError != EGL_SUCCESS) {
2059 setError(currentError, EGL_NO_IMAGE_KHR);
2060 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002061 return EGL_NO_IMAGE_KHR;
Mathias Agopiandf2d9292009-10-28 21:00:29 -07002062 } else {
2063 // In case of success, we need to clear all error flags
2064 // (especially those caused by the implementation that didn't
Mathias Agopian863e5fd2009-10-29 18:29:30 -07002065 // succeed). TODO: we could avoid this if we knew this was
Mathias Agopiandf2d9292009-10-28 21:00:29 -07002066 // a "full" success (all implementation succeeded).
2067 eglGetError();
2068 }
2069
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002070 egl_image_t* result = new egl_image_t(dpy, ctx);
2071 memcpy(result->images, implImages, sizeof(implImages));
2072 return (EGLImageKHR)result;
2073 }
2074}
2075
2076EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
2077{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08002078 clearError();
2079
Eric Hassold3ede7c12011-03-23 15:59:00 -07002080 egl_display_t const * const dp = validate_display(dpy);
2081 if (!dp) return EGL_FALSE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002082
Eric Hassold3ede7c12011-03-23 15:59:00 -07002083 ImageRef _i(img);
2084 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002085
Eric Hassold3ede7c12011-03-23 15:59:00 -07002086 egl_image_t* image = get_image(img);
2087 bool success = false;
2088 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
2089 egl_connection_t* const cnx = &gEGLImpl[i];
2090 if (image->images[i] != EGL_NO_IMAGE_KHR) {
2091 if (cnx->dso) {
2092 if (cnx->egl.eglDestroyImageKHR) {
2093 if (cnx->egl.eglDestroyImageKHR(
2094 dp->disp[i].dpy, image->images[i])) {
2095 success = true;
2096 }
2097 }
2098 }
2099 }
2100 }
2101 if (!success)
2102 return EGL_FALSE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002103
Eric Hassold3ede7c12011-03-23 15:59:00 -07002104 _i.terminate();
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002105
Eric Hassold3ede7c12011-03-23 15:59:00 -07002106 return EGL_TRUE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002107}
Mathias Agopiandf3ca302009-05-04 19:29:25 -07002108
Mathias Agopianc291f5852010-08-27 16:48:56 -07002109// ----------------------------------------------------------------------------
2110// EGL_EGLEXT_VERSION 5
2111// ----------------------------------------------------------------------------
2112
2113
2114EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
2115{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08002116 clearError();
2117
Eric Hassold3ede7c12011-03-23 15:59:00 -07002118 egl_display_t const * const dp = validate_display(dpy);
2119 if (!dp) return EGL_NO_SYNC_KHR;
2120
Mathias Agopianc291f5852010-08-27 16:48:56 -07002121 EGLContext ctx = eglGetCurrentContext();
2122 ContextRef _c(ctx);
Mathias Agopiana93b9572010-09-21 16:22:10 -07002123 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR);
Mathias Agopianc291f5852010-08-27 16:48:56 -07002124 if (!validate_display_context(dpy, ctx))
Mathias Agopiana93b9572010-09-21 16:22:10 -07002125 return EGL_NO_SYNC_KHR;
Mathias Agopianc291f5852010-08-27 16:48:56 -07002126 egl_context_t * const c = get_context(ctx);
Mathias Agopiana93b9572010-09-21 16:22:10 -07002127 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopianc291f5852010-08-27 16:48:56 -07002128 if (c->cnx->egl.eglCreateSyncKHR) {
2129 EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR(
2130 dp->disp[c->impl].dpy, type, attrib_list);
Mathias Agopiana93b9572010-09-21 16:22:10 -07002131 if (sync == EGL_NO_SYNC_KHR)
Mathias Agopianc291f5852010-08-27 16:48:56 -07002132 return sync;
2133 result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync);
2134 }
2135 return (EGLSyncKHR)result;
2136}
2137
2138EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
2139{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08002140 clearError();
2141
Eric Hassold3ede7c12011-03-23 15:59:00 -07002142 egl_display_t const * const dp = validate_display(dpy);
2143 if (!dp) return EGL_FALSE;
Mathias Agopianc291f5852010-08-27 16:48:56 -07002144
2145 SyncRef _s(sync);
2146 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2147 egl_sync_t* syncObject = get_sync(sync);
2148
2149 EGLContext ctx = syncObject->context;
2150 ContextRef _c(ctx);
2151 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
2152 if (!validate_display_context(dpy, ctx))
2153 return EGL_FALSE;
2154
Mathias Agopian36bdf142011-03-16 14:19:03 -07002155 EGLBoolean result = EGL_FALSE;
Mathias Agopianc291f5852010-08-27 16:48:56 -07002156 egl_context_t * const c = get_context(ctx);
Mathias Agopianc291f5852010-08-27 16:48:56 -07002157 if (c->cnx->egl.eglDestroySyncKHR) {
Mathias Agopian36bdf142011-03-16 14:19:03 -07002158 result = c->cnx->egl.eglDestroySyncKHR(
Mathias Agopianc291f5852010-08-27 16:48:56 -07002159 dp->disp[c->impl].dpy, syncObject->sync);
Mathias Agopian36bdf142011-03-16 14:19:03 -07002160 if (result)
2161 _s.terminate();
Mathias Agopianc291f5852010-08-27 16:48:56 -07002162 }
Mathias Agopian36bdf142011-03-16 14:19:03 -07002163 return result;
Mathias Agopianc291f5852010-08-27 16:48:56 -07002164}
2165
2166EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
2167{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08002168 clearError();
2169
Eric Hassold3ede7c12011-03-23 15:59:00 -07002170 egl_display_t const * const dp = validate_display(dpy);
2171 if (!dp) return EGL_FALSE;
Mathias Agopianc291f5852010-08-27 16:48:56 -07002172
2173 SyncRef _s(sync);
2174 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2175 egl_sync_t* syncObject = get_sync(sync);
2176
2177 EGLContext ctx = syncObject->context;
2178 ContextRef _c(ctx);
2179 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
2180 if (!validate_display_context(dpy, ctx))
2181 return EGL_FALSE;
2182
2183 egl_context_t * const c = get_context(ctx);
2184
2185 if (c->cnx->egl.eglClientWaitSyncKHR) {
2186 return c->cnx->egl.eglClientWaitSyncKHR(
2187 dp->disp[c->impl].dpy, syncObject->sync, flags, timeout);
2188 }
2189
2190 return EGL_FALSE;
2191}
2192
2193EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
2194{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08002195 clearError();
2196
Eric Hassold3ede7c12011-03-23 15:59:00 -07002197 egl_display_t const * const dp = validate_display(dpy);
2198 if (!dp) return EGL_FALSE;
Mathias Agopianc291f5852010-08-27 16:48:56 -07002199
2200 SyncRef _s(sync);
2201 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2202 egl_sync_t* syncObject = get_sync(sync);
2203
2204 EGLContext ctx = syncObject->context;
2205 ContextRef _c(ctx);
2206 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
2207 if (!validate_display_context(dpy, ctx))
2208 return EGL_FALSE;
2209
2210 egl_context_t * const c = get_context(ctx);
2211
2212 if (c->cnx->egl.eglGetSyncAttribKHR) {
2213 return c->cnx->egl.eglGetSyncAttribKHR(
2214 dp->disp[c->impl].dpy, syncObject->sync, attribute, value);
2215 }
2216
2217 return EGL_FALSE;
2218}
Mathias Agopiandf3ca302009-05-04 19:29:25 -07002219
2220// ----------------------------------------------------------------------------
2221// ANDROID extensions
2222// ----------------------------------------------------------------------------
2223
2224EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
2225 EGLint left, EGLint top, EGLint width, EGLint height)
2226{
Michael I. Gold4aea6bf2011-01-21 15:39:38 -08002227 clearError();
2228
Eric Hassold3ede7c12011-03-23 15:59:00 -07002229 egl_display_t const * const dp = validate_display(dpy);
2230 if (!dp) return EGL_FALSE;
2231
Mathias Agopian9429e9c2009-08-21 02:18:25 -07002232 SurfaceRef _s(draw);
2233 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
2234
Mathias Agopiandf3ca302009-05-04 19:29:25 -07002235 if (!validate_display_surface(dpy, draw))
2236 return EGL_FALSE;
Mathias Agopiandf3ca302009-05-04 19:29:25 -07002237 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian618fa102009-10-14 02:06:37 -07002238 if (s->cnx->egl.eglSetSwapRectangleANDROID) {
2239 return s->cnx->egl.eglSetSwapRectangleANDROID(
Mathias Agopiana69e0ed2009-08-24 21:47:13 -07002240 dp->disp[s->impl].dpy, s->surface, left, top, width, height);
Mathias Agopiandf3ca302009-05-04 19:29:25 -07002241 }
Mathias Agopian24e5f522009-08-12 21:18:15 -07002242 return setError(EGL_BAD_DISPLAY, NULL);
Mathias Agopiandf3ca302009-05-04 19:29:25 -07002243}