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