blob: 2b0ed5dfd6541333d1394a37641b16a22dbdea5d [file] [log] [blame]
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001/*
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
17#include <ctype.h>
18#include <stdlib.h>
19#include <string.h>
20
21#include <hardware/gralloc.h>
22#include <system/window.h>
23
24#include <EGL/egl.h>
25#include <EGL/eglext.h>
26#include <GLES/gl.h>
27#include <GLES/glext.h>
28
29#include <cutils/log.h>
30#include <cutils/atomic.h>
31#include <cutils/properties.h>
32#include <cutils/memory.h>
33
34#include <utils/KeyedVector.h>
35#include <utils/SortedVector.h>
36#include <utils/String8.h>
37
38#include "egl_impl.h"
39#include "egl_tls.h"
40#include "glesv2dbg.h"
41#include "hooks.h"
42
43#include "egl_display.h"
44#include "egl_impl.h"
45#include "egl_object.h"
46#include "egl_tls.h"
47
48using namespace android;
49
50// ----------------------------------------------------------------------------
51
Mathias Agopiancadd3252011-11-29 17:55:46 -080052#define EGL_VERSION_HW_ANDROID 0x3143
53
Mathias Agopian7adf4ef2011-05-13 16:21:08 -070054struct extention_map_t {
55 const char* name;
56 __eglMustCastToProperFunctionPointerType address;
57};
58
59static const extention_map_t sExtentionMap[] = {
60 { "eglLockSurfaceKHR",
61 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
62 { "eglUnlockSurfaceKHR",
63 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
64 { "eglCreateImageKHR",
65 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
66 { "eglDestroyImageKHR",
67 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Jonas Yang1b1d73f2011-08-26 20:04:39 +080068 { "eglGetSystemTimeFrequencyNV",
69 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
70 { "eglGetSystemTimeNV",
71 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
Mathias Agopian7adf4ef2011-05-13 16:21:08 -070072};
73
74// accesses protected by sExtensionMapMutex
75static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
76static int sGLExtentionSlot = 0;
77static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
78
79static void(*findProcAddress(const char* name,
80 const extention_map_t* map, size_t n))() {
81 for (uint32_t i=0 ; i<n ; i++) {
82 if (!strcmp(name, map[i].name)) {
83 return map[i].address;
84 }
85 }
86 return NULL;
87}
88
89// ----------------------------------------------------------------------------
90
91template<typename T>
92static __attribute__((noinline))
93int binarySearch(T const sortedArray[], int first, int last, T key) {
94 while (first <= last) {
95 int mid = (first + last) / 2;
96 if (sortedArray[mid] < key) {
97 first = mid + 1;
98 } else if (key < sortedArray[mid]) {
99 last = mid - 1;
100 } else {
101 return mid;
102 }
103 }
104 return -1;
105}
106
107// ----------------------------------------------------------------------------
108
109namespace android {
110extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
111extern EGLBoolean egl_init_drivers();
112extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
113extern int gEGLDebugLevel;
114extern gl_hooks_t gHooksTrace;
115extern gl_hooks_t gHooksDebug;
116} // namespace android;
117
118// ----------------------------------------------------------------------------
119
120static inline void clearError() { egl_tls_t::clearError(); }
121static inline EGLContext getContext() { return egl_tls_t::getContext(); }
122
123// ----------------------------------------------------------------------------
124
125EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
126{
127 clearError();
128
129 uint32_t index = uint32_t(display);
130 if (index >= NUM_DISPLAYS) {
131 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
132 }
133
134 if (egl_init_drivers() == EGL_FALSE) {
135 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
136 }
137
138 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
139 return dpy;
140}
141
142// ----------------------------------------------------------------------------
143// Initialization
144// ----------------------------------------------------------------------------
145
146EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
147{
148 clearError();
149
150 egl_display_t * const dp = get_display(dpy);
151 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
152
153 EGLBoolean res = dp->initialize(major, minor);
154
155 return res;
156}
157
158EGLBoolean eglTerminate(EGLDisplay dpy)
159{
160 // NOTE: don't unload the drivers b/c some APIs can be called
161 // after eglTerminate() has been called. eglTerminate() only
162 // terminates an EGLDisplay, not a EGL itself.
163
164 clearError();
165
166 egl_display_t* const dp = get_display(dpy);
167 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
168
169 EGLBoolean res = dp->terminate();
170
171 return res;
172}
173
174// ----------------------------------------------------------------------------
175// configuration
176// ----------------------------------------------------------------------------
177
178EGLBoolean eglGetConfigs( EGLDisplay dpy,
179 EGLConfig *configs,
180 EGLint config_size, EGLint *num_config)
181{
182 clearError();
183
184 egl_display_t const * const dp = validate_display(dpy);
185 if (!dp) return EGL_FALSE;
186
187 GLint numConfigs = dp->numTotalConfigs;
188 if (!configs) {
189 *num_config = numConfigs;
190 return EGL_TRUE;
191 }
192
193 GLint n = 0;
194 for (intptr_t i=0 ; i<dp->numTotalConfigs && config_size ; i++) {
195 *configs++ = EGLConfig(i);
196 config_size--;
197 n++;
198 }
199
200 *num_config = n;
201 return EGL_TRUE;
202}
203
204EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
205 EGLConfig *configs, EGLint config_size,
206 EGLint *num_config)
207{
208 clearError();
209
210 egl_display_t const * const dp = validate_display(dpy);
211 if (!dp) return EGL_FALSE;
212
213 if (num_config==0) {
214 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
215 }
216
217 EGLint n;
218 EGLBoolean res = EGL_FALSE;
219 *num_config = 0;
220
221
222 // It is unfortunate, but we need to remap the EGL_CONFIG_IDs,
223 // to do this, we have to go through the attrib_list array once
224 // to figure out both its size and if it contains an EGL_CONFIG_ID
225 // key. If so, the full array is copied and patched.
226 // NOTE: we assume that there can be only one occurrence
227 // of EGL_CONFIG_ID.
228
229 EGLint patch_index = -1;
230 GLint attr;
231 size_t size = 0;
232 if (attrib_list) {
233 while ((attr=attrib_list[size]) != EGL_NONE) {
234 if (attr == EGL_CONFIG_ID)
235 patch_index = size;
236 size += 2;
237 }
238 }
239 if (patch_index >= 0) {
240 size += 2; // we need copy the sentinel as well
241 EGLint* new_list = (EGLint*)malloc(size*sizeof(EGLint));
242 if (new_list == 0)
243 return setError(EGL_BAD_ALLOC, EGL_FALSE);
244 memcpy(new_list, attrib_list, size*sizeof(EGLint));
245
246 // patch the requested EGL_CONFIG_ID
247 bool found = false;
248 EGLConfig ourConfig(0);
249 EGLint& configId(new_list[patch_index+1]);
250 for (intptr_t i=0 ; i<dp->numTotalConfigs ; i++) {
251 if (dp->configs[i].configId == configId) {
252 ourConfig = EGLConfig(i);
253 configId = dp->configs[i].implConfigId;
254 found = true;
255 break;
256 }
257 }
258
259 egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(ourConfig)].impl];
260 if (found && cnx->dso) {
261 // and switch to the new list
262 attrib_list = const_cast<const EGLint *>(new_list);
263
264 // At this point, the only configuration that can match is
265 // dp->configs[i][index], however, we don't know if it would be
266 // rejected because of the other attributes, so we do have to call
267 // cnx->egl.eglChooseConfig() -- but we don't have to loop
268 // through all the EGLimpl[].
269 // We also know we can only get a single config back, and we know
270 // which one.
271
272 res = cnx->egl.eglChooseConfig(
273 dp->disp[ dp->configs[intptr_t(ourConfig)].impl ].dpy,
274 attrib_list, configs, config_size, &n);
275 if (res && n>0) {
276 // n has to be 0 or 1, by construction, and we already know
277 // which config it will return (since there can be only one).
278 if (configs) {
279 configs[0] = ourConfig;
280 }
281 *num_config = 1;
282 }
283 }
284
285 free(const_cast<EGLint *>(attrib_list));
286 return res;
287 }
288
289
290 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
291 egl_connection_t* const cnx = &gEGLImpl[i];
292 if (cnx->dso) {
293 if (cnx->egl.eglChooseConfig(
294 dp->disp[i].dpy, attrib_list, configs, config_size, &n)) {
295 if (configs) {
296 // now we need to convert these client EGLConfig to our
297 // internal EGLConfig format.
298 // This is done in O(n Log(n)) time.
299 for (int j=0 ; j<n ; j++) {
300 egl_config_t key(i, configs[j]);
301 intptr_t index = binarySearch<egl_config_t>(
302 dp->configs, 0, dp->numTotalConfigs, key);
303 if (index >= 0) {
304 configs[j] = EGLConfig(index);
305 } else {
306 return setError(EGL_BAD_CONFIG, EGL_FALSE);
307 }
308 }
309 configs += n;
310 config_size -= n;
311 }
312 *num_config += n;
313 res = EGL_TRUE;
314 }
315 }
316 }
317 return res;
318}
319
320EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
321 EGLint attribute, EGLint *value)
322{
323 clearError();
324
325 egl_display_t const* dp = 0;
326 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
327 if (!cnx) return EGL_FALSE;
328
329 if (attribute == EGL_CONFIG_ID) {
330 *value = dp->configs[intptr_t(config)].configId;
331 return EGL_TRUE;
332 }
333 return cnx->egl.eglGetConfigAttrib(
334 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
335 dp->configs[intptr_t(config)].config, attribute, value);
336}
337
338// ----------------------------------------------------------------------------
339// surfaces
340// ----------------------------------------------------------------------------
341
342EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
343 NativeWindowType window,
344 const EGLint *attrib_list)
345{
346 clearError();
347
348 egl_display_t const* dp = 0;
349 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
350 if (cnx) {
351 EGLDisplay iDpy = dp->disp[ dp->configs[intptr_t(config)].impl ].dpy;
352 EGLConfig iConfig = dp->configs[intptr_t(config)].config;
353 EGLint format;
354
Mathias Agopian982d2da2011-07-29 17:55:48 -0700355 if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) {
356 LOGE("EGLNativeWindowType %p already connected to another API",
357 window);
358 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
359 }
360
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700361 // set the native window's buffers format to match this config
362 if (cnx->egl.eglGetConfigAttrib(iDpy,
363 iConfig, EGL_NATIVE_VISUAL_ID, &format)) {
364 if (format != 0) {
Jamie Gennis97eae022011-07-01 13:12:07 -0700365 int err = native_window_set_buffers_format(window, format);
366 if (err != 0) {
367 LOGE("error setting native window pixel format: %s (%d)",
368 strerror(-err), err);
Mathias Agopian982d2da2011-07-29 17:55:48 -0700369 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Jamie Gennis97eae022011-07-01 13:12:07 -0700370 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
371 }
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700372 }
373 }
374
Jamie Gennis87f32652011-11-19 18:04:43 -0800375 // the EGL spec requires that a new EGLSurface default to swap interval
376 // 1, so explicitly set that on the window here.
377 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
378 anw->setSwapInterval(anw, 1);
379
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700380 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
381 iDpy, iConfig, window, attrib_list);
382 if (surface != EGL_NO_SURFACE) {
383 egl_surface_t* s = new egl_surface_t(dpy, config, window, surface,
384 dp->configs[intptr_t(config)].impl, cnx);
385 return s;
386 }
Mathias Agopian982d2da2011-07-29 17:55:48 -0700387
388 // EGLSurface creation failed
389 native_window_set_buffers_format(window, 0);
390 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700391 }
392 return EGL_NO_SURFACE;
393}
394
395EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
396 NativePixmapType pixmap,
397 const EGLint *attrib_list)
398{
399 clearError();
400
401 egl_display_t const* dp = 0;
402 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
403 if (cnx) {
404 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
405 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
406 dp->configs[intptr_t(config)].config, pixmap, attrib_list);
407 if (surface != EGL_NO_SURFACE) {
408 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
409 dp->configs[intptr_t(config)].impl, cnx);
410 return s;
411 }
412 }
413 return EGL_NO_SURFACE;
414}
415
416EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
417 const EGLint *attrib_list)
418{
419 clearError();
420
421 egl_display_t const* dp = 0;
422 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
423 if (cnx) {
424 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
425 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
426 dp->configs[intptr_t(config)].config, attrib_list);
427 if (surface != EGL_NO_SURFACE) {
428 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
429 dp->configs[intptr_t(config)].impl, cnx);
430 return s;
431 }
432 }
433 return EGL_NO_SURFACE;
434}
435
436EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
437{
438 clearError();
439
440 egl_display_t const * const dp = validate_display(dpy);
441 if (!dp) return EGL_FALSE;
442
Mathias Agopian274e03c2011-11-13 20:50:07 -0800443 SurfaceRef _s(dp, surface);
Mathias Agopianf1e4e062011-05-16 18:58:55 -0700444 if (!_s.get())
445 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700446
447 egl_surface_t * const s = get_surface(surface);
448 EGLBoolean result = s->cnx->egl.eglDestroySurface(
449 dp->disp[s->impl].dpy, s->surface);
450 if (result == EGL_TRUE) {
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700451 _s.terminate();
452 }
453 return result;
454}
455
456EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
457 EGLint attribute, EGLint *value)
458{
459 clearError();
460
461 egl_display_t const * const dp = validate_display(dpy);
462 if (!dp) return EGL_FALSE;
463
Mathias Agopian274e03c2011-11-13 20:50:07 -0800464 SurfaceRef _s(dp, surface);
Mathias Agopianf1e4e062011-05-16 18:58:55 -0700465 if (!_s.get())
466 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700467
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700468 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700469 EGLBoolean result(EGL_TRUE);
470 if (attribute == EGL_CONFIG_ID) {
471 // We need to remap EGL_CONFIG_IDs
472 *value = dp->configs[intptr_t(s->config)].configId;
473 } else {
474 result = s->cnx->egl.eglQuerySurface(
475 dp->disp[s->impl].dpy, s->surface, attribute, value);
476 }
477
478 return result;
479}
480
481// ----------------------------------------------------------------------------
482// Contexts
483// ----------------------------------------------------------------------------
484
485EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
486 EGLContext share_list, const EGLint *attrib_list)
487{
488 clearError();
489
490 egl_display_t const* dp = 0;
491 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
492 if (cnx) {
493 if (share_list != EGL_NO_CONTEXT) {
494 egl_context_t* const c = get_context(share_list);
495 share_list = c->context;
496 }
497 EGLContext context = cnx->egl.eglCreateContext(
498 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
499 dp->configs[intptr_t(config)].config,
500 share_list, attrib_list);
501 if (context != EGL_NO_CONTEXT) {
502 // figure out if it's a GLESv1 or GLESv2
503 int version = 0;
504 if (attrib_list) {
505 while (*attrib_list != EGL_NONE) {
506 GLint attr = *attrib_list++;
507 GLint value = *attrib_list++;
508 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
509 if (value == 1) {
510 version = GLESv1_INDEX;
511 } else if (value == 2) {
512 version = GLESv2_INDEX;
513 }
514 }
515 };
516 }
517 egl_context_t* c = new egl_context_t(dpy, context, config,
518 dp->configs[intptr_t(config)].impl, cnx, version);
519 return c;
520 }
521 }
522 return EGL_NO_CONTEXT;
523}
524
525EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
526{
527 clearError();
528
529 egl_display_t const * const dp = validate_display(dpy);
Mathias Agopianf1e4e062011-05-16 18:58:55 -0700530 if (!dp)
531 return EGL_FALSE;
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700532
Mathias Agopian274e03c2011-11-13 20:50:07 -0800533 ContextRef _c(dp, ctx);
Mathias Agopianf1e4e062011-05-16 18:58:55 -0700534 if (!_c.get())
535 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700536
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700537 egl_context_t * const c = get_context(ctx);
538 EGLBoolean result = c->cnx->egl.eglDestroyContext(
539 dp->disp[c->impl].dpy, c->context);
540 if (result == EGL_TRUE) {
541 _c.terminate();
542 }
543 return result;
544}
545
546static void loseCurrent(egl_context_t * cur_c)
547{
548 if (cur_c) {
549 egl_surface_t * cur_r = get_surface(cur_c->read);
550 egl_surface_t * cur_d = get_surface(cur_c->draw);
551
552 // by construction, these are either 0 or valid (possibly terminated)
553 // it should be impossible for these to be invalid
554 ContextRef _cur_c(cur_c);
555 SurfaceRef _cur_r(cur_r);
556 SurfaceRef _cur_d(cur_d);
557
558 cur_c->read = NULL;
559 cur_c->draw = NULL;
560
561 _cur_c.release();
562 _cur_r.release();
563 _cur_d.release();
564 }
565}
566
567EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
568 EGLSurface read, EGLContext ctx)
569{
570 clearError();
571
572 egl_display_t const * const dp = get_display(dpy);
573 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
574
Mathias Agopianf1e4e062011-05-16 18:58:55 -0700575 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
576 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
577 // a valid but uninitialized display.
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700578 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
579 (draw != EGL_NO_SURFACE) ) {
580 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
581 }
582
583 // get a reference to the object passed in
Mathias Agopian274e03c2011-11-13 20:50:07 -0800584 ContextRef _c(dp, ctx);
585 SurfaceRef _d(dp, draw);
586 SurfaceRef _r(dp, read);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700587
588 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopianf1e4e062011-05-16 18:58:55 -0700589 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700590 // EGL_NO_CONTEXT is valid
591 return EGL_FALSE;
592 }
593
594 // these are the underlying implementation's object
595 EGLContext impl_ctx = EGL_NO_CONTEXT;
596 EGLSurface impl_draw = EGL_NO_SURFACE;
597 EGLSurface impl_read = EGL_NO_SURFACE;
598
599 // these are our objects structs passed in
600 egl_context_t * c = NULL;
601 egl_surface_t const * d = NULL;
602 egl_surface_t const * r = NULL;
603
604 // these are the current objects structs
605 egl_context_t * cur_c = get_context(getContext());
606
607 if (ctx != EGL_NO_CONTEXT) {
608 c = get_context(ctx);
609 impl_ctx = c->context;
610 } else {
611 // no context given, use the implementation of the current context
612 if (cur_c == NULL) {
613 // no current context
614 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
615 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
616 return setError(EGL_BAD_MATCH, EGL_FALSE);
617 }
618 // not an error, there is just no current context.
619 return EGL_TRUE;
620 }
621 }
622
623 // retrieve the underlying implementation's draw EGLSurface
624 if (draw != EGL_NO_SURFACE) {
625 d = get_surface(draw);
626 // make sure the EGLContext and EGLSurface passed in are for
627 // the same driver
628 if (c && d->impl != c->impl)
629 return setError(EGL_BAD_MATCH, EGL_FALSE);
630 impl_draw = d->surface;
631 }
632
633 // retrieve the underlying implementation's read EGLSurface
634 if (read != EGL_NO_SURFACE) {
635 r = get_surface(read);
636 // make sure the EGLContext and EGLSurface passed in are for
637 // the same driver
638 if (c && r->impl != c->impl)
639 return setError(EGL_BAD_MATCH, EGL_FALSE);
640 impl_read = r->surface;
641 }
642
643 EGLBoolean result;
644
645 if (c) {
646 result = c->cnx->egl.eglMakeCurrent(
647 dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
648 } else {
649 result = cur_c->cnx->egl.eglMakeCurrent(
650 dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
651 }
652
653 if (result == EGL_TRUE) {
654
655 loseCurrent(cur_c);
656
657 if (ctx != EGL_NO_CONTEXT) {
658 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
659 egl_tls_t::setContext(ctx);
660 if (gEGLDebugLevel > 0) {
661 CreateDbgContext(c->version, c->cnx->hooks[c->version]);
662 }
663 _c.acquire();
664 _r.acquire();
665 _d.acquire();
666 c->read = read;
667 c->draw = draw;
668 } else {
669 setGLHooksThreadSpecific(&gHooksNoContext);
670 egl_tls_t::setContext(EGL_NO_CONTEXT);
671 }
Mathias Agopianca07e342011-08-25 18:38:24 -0700672 } else {
673 // this will LOGE the error
674 result = setError(c->cnx->egl.eglGetError(), EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700675 }
676 return result;
677}
678
679
680EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
681 EGLint attribute, EGLint *value)
682{
683 clearError();
684
685 egl_display_t const * const dp = validate_display(dpy);
686 if (!dp) return EGL_FALSE;
687
Mathias Agopian274e03c2011-11-13 20:50:07 -0800688 ContextRef _c(dp, ctx);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700689 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
690
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700691 egl_context_t * const c = get_context(ctx);
692
693 EGLBoolean result(EGL_TRUE);
694 if (attribute == EGL_CONFIG_ID) {
695 *value = dp->configs[intptr_t(c->config)].configId;
696 } else {
697 // We need to remap EGL_CONFIG_IDs
698 result = c->cnx->egl.eglQueryContext(
699 dp->disp[c->impl].dpy, c->context, attribute, value);
700 }
701
702 return result;
703}
704
705EGLContext eglGetCurrentContext(void)
706{
707 // could be called before eglInitialize(), but we wouldn't have a context
708 // then, and this function would correctly return EGL_NO_CONTEXT.
709
710 clearError();
711
712 EGLContext ctx = getContext();
713 return ctx;
714}
715
716EGLSurface eglGetCurrentSurface(EGLint readdraw)
717{
718 // could be called before eglInitialize(), but we wouldn't have a context
719 // then, and this function would correctly return EGL_NO_SURFACE.
720
721 clearError();
722
723 EGLContext ctx = getContext();
724 if (ctx) {
725 egl_context_t const * const c = get_context(ctx);
726 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
727 switch (readdraw) {
728 case EGL_READ: return c->read;
729 case EGL_DRAW: return c->draw;
730 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
731 }
732 }
733 return EGL_NO_SURFACE;
734}
735
736EGLDisplay eglGetCurrentDisplay(void)
737{
738 // could be called before eglInitialize(), but we wouldn't have a context
739 // then, and this function would correctly return EGL_NO_DISPLAY.
740
741 clearError();
742
743 EGLContext ctx = getContext();
744 if (ctx) {
745 egl_context_t const * const c = get_context(ctx);
746 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
747 return c->dpy;
748 }
749 return EGL_NO_DISPLAY;
750}
751
752EGLBoolean eglWaitGL(void)
753{
754 // could be called before eglInitialize(), but we wouldn't have a context
755 // then, and this function would return GL_TRUE, which isn't wrong.
756
757 clearError();
758
759 EGLBoolean res = EGL_TRUE;
760 EGLContext ctx = getContext();
761 if (ctx) {
762 egl_context_t const * const c = get_context(ctx);
763 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
764 if (uint32_t(c->impl)>=2)
765 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
766 egl_connection_t* const cnx = &gEGLImpl[c->impl];
767 if (!cnx->dso)
768 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
769 res = cnx->egl.eglWaitGL();
770 }
771 return res;
772}
773
774EGLBoolean eglWaitNative(EGLint engine)
775{
776 // could be called before eglInitialize(), but we wouldn't have a context
777 // then, and this function would return GL_TRUE, which isn't wrong.
778
779 clearError();
780
781 EGLBoolean res = EGL_TRUE;
782 EGLContext ctx = getContext();
783 if (ctx) {
784 egl_context_t const * const c = get_context(ctx);
785 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
786 if (uint32_t(c->impl)>=2)
787 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
788 egl_connection_t* const cnx = &gEGLImpl[c->impl];
789 if (!cnx->dso)
790 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
791 res = cnx->egl.eglWaitNative(engine);
792 }
793 return res;
794}
795
796EGLint eglGetError(void)
797{
798 EGLint result = EGL_SUCCESS;
799 EGLint err;
800 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
801 err = EGL_SUCCESS;
802 egl_connection_t* const cnx = &gEGLImpl[i];
803 if (cnx->dso)
804 err = cnx->egl.eglGetError();
805 if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
806 result = err;
807 }
808 err = egl_tls_t::getError();
809 if (result == EGL_SUCCESS)
810 result = err;
811 return result;
812}
813
814// Note: Similar implementations of these functions also exist in
815// gl2.cpp and gl.cpp, and are used by applications that call the
816// exported entry points directly.
817typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
818typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
819
820static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL;
821static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL;
822
823static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image)
824{
825 GLeglImageOES implImage =
826 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
827 glEGLImageTargetTexture2DOES_impl(target, implImage);
828}
829
830static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image)
831{
832 GLeglImageOES implImage =
833 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
834 glEGLImageTargetRenderbufferStorageOES_impl(target, implImage);
835}
836
837__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
838{
839 // eglGetProcAddress() could be the very first function called
840 // in which case we must make sure we've initialized ourselves, this
841 // happens the first time egl_get_display() is called.
842
843 clearError();
844
845 if (egl_init_drivers() == EGL_FALSE) {
846 setError(EGL_BAD_PARAMETER, NULL);
847 return NULL;
848 }
849
Jamie Gennis0dc908c2011-11-03 17:42:43 -0700850 // The EGL_ANDROID_blob_cache extension should not be exposed to
851 // applications. It is used internally by the Android EGL layer.
Jamie Gennisb7928462011-11-09 15:35:34 -0800852 if (!strcmp(procname, "eglSetBlobCacheFuncsANDROID")) {
Jamie Gennis0dc908c2011-11-03 17:42:43 -0700853 return NULL;
854 }
855
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700856 __eglMustCastToProperFunctionPointerType addr;
857 addr = findProcAddress(procname, sExtentionMap, NELEM(sExtentionMap));
858 if (addr) return addr;
859
Jamie Gennis0dc908c2011-11-03 17:42:43 -0700860
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700861 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
862 pthread_mutex_lock(&sExtensionMapMutex);
863
864 /*
865 * Since eglGetProcAddress() is not associated to anything, it needs
866 * to return a function pointer that "works" regardless of what
867 * the current context is.
868 *
869 * For this reason, we return a "forwarder", a small stub that takes
870 * care of calling the function associated with the context
871 * currently bound.
872 *
873 * We first look for extensions we've already resolved, if we're seeing
874 * this extension for the first time, we go through all our
875 * implementations and call eglGetProcAddress() and record the
876 * result in the appropriate implementation hooks and return the
877 * address of the forwarder corresponding to that hook set.
878 *
879 */
880
881 const String8 name(procname);
882 addr = sGLExtentionMap.valueFor(name);
883 const int slot = sGLExtentionSlot;
884
885 LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
886 "no more slots for eglGetProcAddress(\"%s\")",
887 procname);
888
889 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
890 bool found = false;
891 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
892 egl_connection_t* const cnx = &gEGLImpl[i];
893 if (cnx->dso && cnx->egl.eglGetProcAddress) {
894 found = true;
895 // Extensions are independent of the bound context
896 cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
897 cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
898#if EGL_TRACE
899 gHooksDebug.ext.extensions[slot] = gHooksTrace.ext.extensions[slot] =
900#endif
901 cnx->egl.eglGetProcAddress(procname);
902 }
903 }
904 if (found) {
905 addr = gExtensionForwarders[slot];
906
907 if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) {
908 glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr;
909 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper;
910 }
911 if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) {
912 glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr;
913 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper;
914 }
915
916 sGLExtentionMap.add(name, addr);
917 sGLExtentionSlot++;
918 }
919 }
920
921 pthread_mutex_unlock(&sExtensionMapMutex);
922 return addr;
923}
924
925EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
926{
927 EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw);
928 if (gEGLDebugLevel > 0)
929 Debug_eglSwapBuffers(dpy, draw);
930
931 clearError();
932
933 egl_display_t const * const dp = validate_display(dpy);
934 if (!dp) return EGL_FALSE;
935
Mathias Agopian274e03c2011-11-13 20:50:07 -0800936 SurfaceRef _s(dp, draw);
Mathias Agopianf1e4e062011-05-16 18:58:55 -0700937 if (!_s.get())
938 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700939
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700940 egl_surface_t const * const s = get_surface(draw);
941 return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
942}
943
944EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
945 NativePixmapType target)
946{
947 clearError();
948
949 egl_display_t const * const dp = validate_display(dpy);
950 if (!dp) return EGL_FALSE;
951
Mathias Agopian274e03c2011-11-13 20:50:07 -0800952 SurfaceRef _s(dp, surface);
Mathias Agopianf1e4e062011-05-16 18:58:55 -0700953 if (!_s.get())
954 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700955
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700956 egl_surface_t const * const s = get_surface(surface);
957 return s->cnx->egl.eglCopyBuffers(
958 dp->disp[s->impl].dpy, s->surface, target);
959}
960
961const char* eglQueryString(EGLDisplay dpy, EGLint name)
962{
963 clearError();
964
965 egl_display_t const * const dp = validate_display(dpy);
966 if (!dp) return (const char *) NULL;
967
968 switch (name) {
969 case EGL_VENDOR:
Mathias Agopiane88740e2011-11-13 23:52:47 -0800970 return dp->getVendorString();
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700971 case EGL_VERSION:
Mathias Agopiane88740e2011-11-13 23:52:47 -0800972 return dp->getVersionString();
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700973 case EGL_EXTENSIONS:
Mathias Agopiane88740e2011-11-13 23:52:47 -0800974 return dp->getExtensionString();
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700975 case EGL_CLIENT_APIS:
Mathias Agopiane88740e2011-11-13 23:52:47 -0800976 return dp->getClientApiString();
Mathias Agopiancadd3252011-11-29 17:55:46 -0800977 case EGL_VERSION_HW_ANDROID: {
978 if (gEGLImpl[IMPL_HARDWARE].dso) {
979 return dp->disp[IMPL_HARDWARE].queryString.version;
980 }
981 return dp->disp[IMPL_SOFTWARE].queryString.version;
982 }
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700983 }
984 return setError(EGL_BAD_PARAMETER, (const char *)0);
985}
986
987
988// ----------------------------------------------------------------------------
989// EGL 1.1
990// ----------------------------------------------------------------------------
991
992EGLBoolean eglSurfaceAttrib(
993 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
994{
995 clearError();
996
997 egl_display_t const * const dp = validate_display(dpy);
998 if (!dp) return EGL_FALSE;
999
Mathias Agopian274e03c2011-11-13 20:50:07 -08001000 SurfaceRef _s(dp, surface);
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001001 if (!_s.get())
1002 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001003
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001004 egl_surface_t const * const s = get_surface(surface);
1005 if (s->cnx->egl.eglSurfaceAttrib) {
1006 return s->cnx->egl.eglSurfaceAttrib(
1007 dp->disp[s->impl].dpy, s->surface, attribute, value);
1008 }
1009 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1010}
1011
1012EGLBoolean eglBindTexImage(
1013 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1014{
1015 clearError();
1016
1017 egl_display_t const * const dp = validate_display(dpy);
1018 if (!dp) return EGL_FALSE;
1019
Mathias Agopian274e03c2011-11-13 20:50:07 -08001020 SurfaceRef _s(dp, surface);
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001021 if (!_s.get())
1022 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001023
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001024 egl_surface_t const * const s = get_surface(surface);
1025 if (s->cnx->egl.eglBindTexImage) {
1026 return s->cnx->egl.eglBindTexImage(
1027 dp->disp[s->impl].dpy, s->surface, buffer);
1028 }
1029 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1030}
1031
1032EGLBoolean eglReleaseTexImage(
1033 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1034{
1035 clearError();
1036
1037 egl_display_t const * const dp = validate_display(dpy);
1038 if (!dp) return EGL_FALSE;
1039
Mathias Agopian274e03c2011-11-13 20:50:07 -08001040 SurfaceRef _s(dp, surface);
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001041 if (!_s.get())
1042 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001043
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001044 egl_surface_t const * const s = get_surface(surface);
1045 if (s->cnx->egl.eglReleaseTexImage) {
1046 return s->cnx->egl.eglReleaseTexImage(
1047 dp->disp[s->impl].dpy, s->surface, buffer);
1048 }
1049 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1050}
1051
1052EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1053{
1054 clearError();
1055
1056 egl_display_t const * const dp = validate_display(dpy);
1057 if (!dp) return EGL_FALSE;
1058
1059 EGLBoolean res = EGL_TRUE;
1060 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1061 egl_connection_t* const cnx = &gEGLImpl[i];
1062 if (cnx->dso) {
1063 if (cnx->egl.eglSwapInterval) {
1064 if (cnx->egl.eglSwapInterval(
1065 dp->disp[i].dpy, interval) == EGL_FALSE) {
1066 res = EGL_FALSE;
1067 }
1068 }
1069 }
1070 }
1071 return res;
1072}
1073
1074
1075// ----------------------------------------------------------------------------
1076// EGL 1.2
1077// ----------------------------------------------------------------------------
1078
1079EGLBoolean eglWaitClient(void)
1080{
1081 clearError();
1082
1083 // could be called before eglInitialize(), but we wouldn't have a context
1084 // then, and this function would return GL_TRUE, which isn't wrong.
1085 EGLBoolean res = EGL_TRUE;
1086 EGLContext ctx = getContext();
1087 if (ctx) {
1088 egl_context_t const * const c = get_context(ctx);
1089 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1090 if (uint32_t(c->impl)>=2)
1091 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1092 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1093 if (!cnx->dso)
1094 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1095 if (cnx->egl.eglWaitClient) {
1096 res = cnx->egl.eglWaitClient();
1097 } else {
1098 res = cnx->egl.eglWaitGL();
1099 }
1100 }
1101 return res;
1102}
1103
1104EGLBoolean eglBindAPI(EGLenum api)
1105{
1106 clearError();
1107
1108 if (egl_init_drivers() == EGL_FALSE) {
1109 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1110 }
1111
1112 // bind this API on all EGLs
1113 EGLBoolean res = EGL_TRUE;
1114 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1115 egl_connection_t* const cnx = &gEGLImpl[i];
1116 if (cnx->dso) {
1117 if (cnx->egl.eglBindAPI) {
1118 if (cnx->egl.eglBindAPI(api) == EGL_FALSE) {
1119 res = EGL_FALSE;
1120 }
1121 }
1122 }
1123 }
1124 return res;
1125}
1126
1127EGLenum eglQueryAPI(void)
1128{
1129 clearError();
1130
1131 if (egl_init_drivers() == EGL_FALSE) {
1132 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1133 }
1134
1135 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1136 egl_connection_t* const cnx = &gEGLImpl[i];
1137 if (cnx->dso) {
1138 if (cnx->egl.eglQueryAPI) {
1139 // the first one we find is okay, because they all
1140 // should be the same
1141 return cnx->egl.eglQueryAPI();
1142 }
1143 }
1144 }
1145 // or, it can only be OpenGL ES
1146 return EGL_OPENGL_ES_API;
1147}
1148
1149EGLBoolean eglReleaseThread(void)
1150{
1151 clearError();
1152
1153 // If there is context bound to the thread, release it
1154 loseCurrent(get_context(getContext()));
1155
1156 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1157 egl_connection_t* const cnx = &gEGLImpl[i];
1158 if (cnx->dso) {
1159 if (cnx->egl.eglReleaseThread) {
1160 cnx->egl.eglReleaseThread();
1161 }
1162 }
1163 }
1164 egl_tls_t::clearTLS();
1165 dbgReleaseThread();
1166 return EGL_TRUE;
1167}
1168
1169EGLSurface eglCreatePbufferFromClientBuffer(
1170 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1171 EGLConfig config, const EGLint *attrib_list)
1172{
1173 clearError();
1174
1175 egl_display_t const* dp = 0;
1176 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
1177 if (!cnx) return EGL_FALSE;
1178 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1179 return cnx->egl.eglCreatePbufferFromClientBuffer(
1180 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1181 buftype, buffer,
1182 dp->configs[intptr_t(config)].config, attrib_list);
1183 }
1184 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1185}
1186
1187// ----------------------------------------------------------------------------
1188// EGL_EGLEXT_VERSION 3
1189// ----------------------------------------------------------------------------
1190
1191EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1192 const EGLint *attrib_list)
1193{
1194 clearError();
1195
1196 egl_display_t const * const dp = validate_display(dpy);
1197 if (!dp) return EGL_FALSE;
1198
Mathias Agopian274e03c2011-11-13 20:50:07 -08001199 SurfaceRef _s(dp, surface);
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001200 if (!_s.get())
1201 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001202
1203 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001204 if (s->cnx->egl.eglLockSurfaceKHR) {
1205 return s->cnx->egl.eglLockSurfaceKHR(
1206 dp->disp[s->impl].dpy, s->surface, attrib_list);
1207 }
1208 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1209}
1210
1211EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1212{
1213 clearError();
1214
1215 egl_display_t const * const dp = validate_display(dpy);
1216 if (!dp) return EGL_FALSE;
1217
Mathias Agopian274e03c2011-11-13 20:50:07 -08001218 SurfaceRef _s(dp, surface);
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001219 if (!_s.get())
1220 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001221
1222 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001223 if (s->cnx->egl.eglUnlockSurfaceKHR) {
1224 return s->cnx->egl.eglUnlockSurfaceKHR(
1225 dp->disp[s->impl].dpy, s->surface);
1226 }
1227 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1228}
1229
1230EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1231 EGLClientBuffer buffer, const EGLint *attrib_list)
1232{
1233 clearError();
1234
1235 egl_display_t const * const dp = validate_display(dpy);
1236 if (!dp) return EGL_NO_IMAGE_KHR;
1237
1238 if (ctx != EGL_NO_CONTEXT) {
Mathias Agopian274e03c2011-11-13 20:50:07 -08001239 ContextRef _c(dp, ctx);
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001240 if (!_c.get())
1241 return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001242 egl_context_t * const c = get_context(ctx);
1243 // since we have an EGLContext, we know which implementation to use
1244 EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
1245 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
1246 if (image == EGL_NO_IMAGE_KHR)
1247 return image;
1248
1249 egl_image_t* result = new egl_image_t(dpy, ctx);
1250 result->images[c->impl] = image;
1251 return (EGLImageKHR)result;
1252 } else {
1253 // EGL_NO_CONTEXT is a valid parameter
1254
1255 /* Since we don't have a way to know which implementation to call,
1256 * we're calling all of them. If at least one of the implementation
1257 * succeeded, this is a success.
1258 */
1259
1260 EGLint currentError = eglGetError();
1261
1262 EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS];
1263 bool success = false;
1264 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1265 egl_connection_t* const cnx = &gEGLImpl[i];
1266 implImages[i] = EGL_NO_IMAGE_KHR;
1267 if (cnx->dso) {
1268 if (cnx->egl.eglCreateImageKHR) {
1269 implImages[i] = cnx->egl.eglCreateImageKHR(
1270 dp->disp[i].dpy, ctx, target, buffer, attrib_list);
1271 if (implImages[i] != EGL_NO_IMAGE_KHR) {
1272 success = true;
1273 }
1274 }
1275 }
1276 }
1277
1278 if (!success) {
1279 // failure, if there was an error when we entered this function,
1280 // the error flag must not be updated.
1281 // Otherwise, the error is whatever happened in the implementation
1282 // that faulted.
1283 if (currentError != EGL_SUCCESS) {
1284 setError(currentError, EGL_NO_IMAGE_KHR);
1285 }
1286 return EGL_NO_IMAGE_KHR;
1287 } else {
1288 // In case of success, we need to clear all error flags
1289 // (especially those caused by the implementation that didn't
1290 // succeed). TODO: we could avoid this if we knew this was
1291 // a "full" success (all implementation succeeded).
1292 eglGetError();
1293 }
1294
1295 egl_image_t* result = new egl_image_t(dpy, ctx);
1296 memcpy(result->images, implImages, sizeof(implImages));
1297 return (EGLImageKHR)result;
1298 }
1299}
1300
1301EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1302{
1303 clearError();
1304
1305 egl_display_t const * const dp = validate_display(dpy);
1306 if (!dp) return EGL_FALSE;
1307
Mathias Agopian274e03c2011-11-13 20:50:07 -08001308 ImageRef _i(dp, img);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001309 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1310
1311 egl_image_t* image = get_image(img);
1312 bool success = false;
1313 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1314 egl_connection_t* const cnx = &gEGLImpl[i];
1315 if (image->images[i] != EGL_NO_IMAGE_KHR) {
1316 if (cnx->dso) {
1317 if (cnx->egl.eglDestroyImageKHR) {
1318 if (cnx->egl.eglDestroyImageKHR(
1319 dp->disp[i].dpy, image->images[i])) {
1320 success = true;
1321 }
1322 }
1323 }
1324 }
1325 }
1326 if (!success)
1327 return EGL_FALSE;
1328
1329 _i.terminate();
1330
1331 return EGL_TRUE;
1332}
1333
1334// ----------------------------------------------------------------------------
1335// EGL_EGLEXT_VERSION 5
1336// ----------------------------------------------------------------------------
1337
1338
1339EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1340{
1341 clearError();
1342
1343 egl_display_t const * const dp = validate_display(dpy);
1344 if (!dp) return EGL_NO_SYNC_KHR;
1345
1346 EGLContext ctx = eglGetCurrentContext();
Mathias Agopian274e03c2011-11-13 20:50:07 -08001347 ContextRef _c(dp, ctx);
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001348 if (!_c.get())
1349 return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR);
1350
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001351 egl_context_t * const c = get_context(ctx);
1352 EGLSyncKHR result = EGL_NO_SYNC_KHR;
1353 if (c->cnx->egl.eglCreateSyncKHR) {
1354 EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR(
1355 dp->disp[c->impl].dpy, type, attrib_list);
1356 if (sync == EGL_NO_SYNC_KHR)
1357 return sync;
1358 result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync);
1359 }
1360 return (EGLSyncKHR)result;
1361}
1362
1363EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1364{
1365 clearError();
1366
1367 egl_display_t const * const dp = validate_display(dpy);
1368 if (!dp) return EGL_FALSE;
1369
Mathias Agopian274e03c2011-11-13 20:50:07 -08001370 SyncRef _s(dp, sync);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001371 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1372 egl_sync_t* syncObject = get_sync(sync);
1373
1374 EGLContext ctx = syncObject->context;
Mathias Agopian274e03c2011-11-13 20:50:07 -08001375 ContextRef _c(dp, ctx);
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001376 if (!_c.get())
1377 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001378
1379 EGLBoolean result = EGL_FALSE;
1380 egl_context_t * const c = get_context(ctx);
1381 if (c->cnx->egl.eglDestroySyncKHR) {
1382 result = c->cnx->egl.eglDestroySyncKHR(
1383 dp->disp[c->impl].dpy, syncObject->sync);
1384 if (result)
1385 _s.terminate();
1386 }
1387 return result;
1388}
1389
1390EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
1391{
1392 clearError();
1393
1394 egl_display_t const * const dp = validate_display(dpy);
1395 if (!dp) return EGL_FALSE;
1396
Mathias Agopian274e03c2011-11-13 20:50:07 -08001397 SyncRef _s(dp, sync);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001398 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1399 egl_sync_t* syncObject = get_sync(sync);
1400
1401 EGLContext ctx = syncObject->context;
Mathias Agopian274e03c2011-11-13 20:50:07 -08001402 ContextRef _c(dp, ctx);
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001403 if (!_c.get())
1404 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001405
1406 egl_context_t * const c = get_context(ctx);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001407 if (c->cnx->egl.eglClientWaitSyncKHR) {
1408 return c->cnx->egl.eglClientWaitSyncKHR(
1409 dp->disp[c->impl].dpy, syncObject->sync, flags, timeout);
1410 }
1411
1412 return EGL_FALSE;
1413}
1414
1415EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
1416{
1417 clearError();
1418
1419 egl_display_t const * const dp = validate_display(dpy);
1420 if (!dp) return EGL_FALSE;
1421
Mathias Agopian274e03c2011-11-13 20:50:07 -08001422 SyncRef _s(dp, sync);
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001423 if (!_s.get())
1424 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001425
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001426 egl_sync_t* syncObject = get_sync(sync);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001427 EGLContext ctx = syncObject->context;
Mathias Agopian274e03c2011-11-13 20:50:07 -08001428 ContextRef _c(dp, ctx);
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001429 if (!_c.get())
1430 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001431
1432 egl_context_t * const c = get_context(ctx);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001433 if (c->cnx->egl.eglGetSyncAttribKHR) {
1434 return c->cnx->egl.eglGetSyncAttribKHR(
1435 dp->disp[c->impl].dpy, syncObject->sync, attribute, value);
1436 }
1437
1438 return EGL_FALSE;
1439}
1440
1441// ----------------------------------------------------------------------------
1442// ANDROID extensions
1443// ----------------------------------------------------------------------------
1444
Mathias Agopiane88740e2011-11-13 23:52:47 -08001445/* ANDROID extensions entry-point go here */
Jonas Yang1b1d73f2011-08-26 20:04:39 +08001446
1447// ----------------------------------------------------------------------------
1448// NVIDIA extensions
1449// ----------------------------------------------------------------------------
1450EGLuint64NV eglGetSystemTimeFrequencyNV()
1451{
1452 clearError();
1453
1454 if (egl_init_drivers() == EGL_FALSE) {
1455 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1456 }
1457
1458 EGLuint64NV ret = 0;
1459 egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE];
1460
1461 if (cnx->dso) {
1462 if (cnx->egl.eglGetSystemTimeFrequencyNV) {
1463 return cnx->egl.eglGetSystemTimeFrequencyNV();
1464 }
1465 }
1466
Mathias Agopian97bc75d2011-10-05 19:15:05 -07001467 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1b1d73f2011-08-26 20:04:39 +08001468}
1469
1470EGLuint64NV eglGetSystemTimeNV()
1471{
1472 clearError();
1473
1474 if (egl_init_drivers() == EGL_FALSE) {
1475 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1476 }
1477
1478 EGLuint64NV ret = 0;
1479 egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE];
1480
1481 if (cnx->dso) {
1482 if (cnx->egl.eglGetSystemTimeNV) {
1483 return cnx->egl.eglGetSystemTimeNV();
1484 }
1485 }
1486
Mathias Agopian97bc75d2011-10-05 19:15:05 -07001487 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1b1d73f2011-08-26 20:04:39 +08001488}