blob: a63d5b054d005deaea8936ec21cf6fbad243fe28 [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"
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 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;
113extern gl_hooks_t gHooksDebug;
114} // namespace android;
115
116// ----------------------------------------------------------------------------
117
118static inline void clearError() { egl_tls_t::clearError(); }
119static inline EGLContext getContext() { return egl_tls_t::getContext(); }
120
121// ----------------------------------------------------------------------------
122
123EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
124{
125 clearError();
126
127 uint32_t index = uint32_t(display);
128 if (index >= NUM_DISPLAYS) {
129 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
130 }
131
132 if (egl_init_drivers() == EGL_FALSE) {
133 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
134 }
135
136 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
137 return dpy;
138}
139
140// ----------------------------------------------------------------------------
141// Initialization
142// ----------------------------------------------------------------------------
143
144EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
145{
146 clearError();
147
148 egl_display_t * const dp = get_display(dpy);
149 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
150
151 EGLBoolean res = dp->initialize(major, minor);
152
153 return res;
154}
155
156EGLBoolean eglTerminate(EGLDisplay dpy)
157{
158 // NOTE: don't unload the drivers b/c some APIs can be called
159 // after eglTerminate() has been called. eglTerminate() only
160 // terminates an EGLDisplay, not a EGL itself.
161
162 clearError();
163
164 egl_display_t* const dp = get_display(dpy);
165 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
166
167 EGLBoolean res = dp->terminate();
168
169 return res;
170}
171
172// ----------------------------------------------------------------------------
173// configuration
174// ----------------------------------------------------------------------------
175
176EGLBoolean eglGetConfigs( EGLDisplay dpy,
177 EGLConfig *configs,
178 EGLint config_size, EGLint *num_config)
179{
180 clearError();
181
182 egl_display_t const * const dp = validate_display(dpy);
183 if (!dp) return EGL_FALSE;
184
185 GLint numConfigs = dp->numTotalConfigs;
186 if (!configs) {
187 *num_config = numConfigs;
188 return EGL_TRUE;
189 }
190
191 GLint n = 0;
192 for (intptr_t i=0 ; i<dp->numTotalConfigs && config_size ; i++) {
193 *configs++ = EGLConfig(i);
194 config_size--;
195 n++;
196 }
197
198 *num_config = n;
199 return EGL_TRUE;
200}
201
202EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
203 EGLConfig *configs, EGLint config_size,
204 EGLint *num_config)
205{
206 clearError();
207
208 egl_display_t const * const dp = validate_display(dpy);
209 if (!dp) return EGL_FALSE;
210
211 if (num_config==0) {
212 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
213 }
214
215 EGLint n;
216 EGLBoolean res = EGL_FALSE;
217 *num_config = 0;
218
219
220 // It is unfortunate, but we need to remap the EGL_CONFIG_IDs,
221 // to do this, we have to go through the attrib_list array once
222 // to figure out both its size and if it contains an EGL_CONFIG_ID
223 // key. If so, the full array is copied and patched.
224 // NOTE: we assume that there can be only one occurrence
225 // of EGL_CONFIG_ID.
226
227 EGLint patch_index = -1;
228 GLint attr;
229 size_t size = 0;
230 if (attrib_list) {
231 while ((attr=attrib_list[size]) != EGL_NONE) {
232 if (attr == EGL_CONFIG_ID)
233 patch_index = size;
234 size += 2;
235 }
236 }
237 if (patch_index >= 0) {
238 size += 2; // we need copy the sentinel as well
239 EGLint* new_list = (EGLint*)malloc(size*sizeof(EGLint));
240 if (new_list == 0)
241 return setError(EGL_BAD_ALLOC, EGL_FALSE);
242 memcpy(new_list, attrib_list, size*sizeof(EGLint));
243
244 // patch the requested EGL_CONFIG_ID
245 bool found = false;
246 EGLConfig ourConfig(0);
247 EGLint& configId(new_list[patch_index+1]);
248 for (intptr_t i=0 ; i<dp->numTotalConfigs ; i++) {
249 if (dp->configs[i].configId == configId) {
250 ourConfig = EGLConfig(i);
251 configId = dp->configs[i].implConfigId;
252 found = true;
253 break;
254 }
255 }
256
257 egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(ourConfig)].impl];
258 if (found && cnx->dso) {
259 // and switch to the new list
260 attrib_list = const_cast<const EGLint *>(new_list);
261
262 // At this point, the only configuration that can match is
263 // dp->configs[i][index], however, we don't know if it would be
264 // rejected because of the other attributes, so we do have to call
265 // cnx->egl.eglChooseConfig() -- but we don't have to loop
266 // through all the EGLimpl[].
267 // We also know we can only get a single config back, and we know
268 // which one.
269
270 res = cnx->egl.eglChooseConfig(
271 dp->disp[ dp->configs[intptr_t(ourConfig)].impl ].dpy,
272 attrib_list, configs, config_size, &n);
273 if (res && n>0) {
274 // n has to be 0 or 1, by construction, and we already know
275 // which config it will return (since there can be only one).
276 if (configs) {
277 configs[0] = ourConfig;
278 }
279 *num_config = 1;
280 }
281 }
282
283 free(const_cast<EGLint *>(attrib_list));
284 return res;
285 }
286
287
288 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
289 egl_connection_t* const cnx = &gEGLImpl[i];
290 if (cnx->dso) {
291 if (cnx->egl.eglChooseConfig(
292 dp->disp[i].dpy, attrib_list, configs, config_size, &n)) {
293 if (configs) {
294 // now we need to convert these client EGLConfig to our
295 // internal EGLConfig format.
296 // This is done in O(n Log(n)) time.
297 for (int j=0 ; j<n ; j++) {
298 egl_config_t key(i, configs[j]);
299 intptr_t index = binarySearch<egl_config_t>(
300 dp->configs, 0, dp->numTotalConfigs, key);
301 if (index >= 0) {
302 configs[j] = EGLConfig(index);
303 } else {
304 return setError(EGL_BAD_CONFIG, EGL_FALSE);
305 }
306 }
307 configs += n;
308 config_size -= n;
309 }
310 *num_config += n;
311 res = EGL_TRUE;
312 }
313 }
314 }
315 return res;
316}
317
318EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
319 EGLint attribute, EGLint *value)
320{
321 clearError();
322
323 egl_display_t const* dp = 0;
324 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
325 if (!cnx) return EGL_FALSE;
326
327 if (attribute == EGL_CONFIG_ID) {
328 *value = dp->configs[intptr_t(config)].configId;
329 return EGL_TRUE;
330 }
331 return cnx->egl.eglGetConfigAttrib(
332 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
333 dp->configs[intptr_t(config)].config, attribute, value);
334}
335
336// ----------------------------------------------------------------------------
337// surfaces
338// ----------------------------------------------------------------------------
339
340EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
341 NativeWindowType window,
342 const EGLint *attrib_list)
343{
344 clearError();
345
346 egl_display_t const* dp = 0;
347 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
348 if (cnx) {
349 EGLDisplay iDpy = dp->disp[ dp->configs[intptr_t(config)].impl ].dpy;
350 EGLConfig iConfig = dp->configs[intptr_t(config)].config;
351 EGLint format;
352
Mathias Agopian81a63352011-07-29 17:55:48 -0700353 if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) {
354 LOGE("EGLNativeWindowType %p already connected to another API",
355 window);
356 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
357 }
358
Mathias Agopian518ec112011-05-13 16:21:08 -0700359 // set the native window's buffers format to match this config
360 if (cnx->egl.eglGetConfigAttrib(iDpy,
361 iConfig, EGL_NATIVE_VISUAL_ID, &format)) {
362 if (format != 0) {
Jamie Gennisbee205f2011-07-01 13:12:07 -0700363 int err = native_window_set_buffers_format(window, format);
364 if (err != 0) {
365 LOGE("error setting native window pixel format: %s (%d)",
366 strerror(-err), err);
Mathias Agopian81a63352011-07-29 17:55:48 -0700367 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Jamie Gennisbee205f2011-07-01 13:12:07 -0700368 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
369 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700370 }
371 }
372
Jamie Gennis59769462011-11-19 18:04:43 -0800373 // the EGL spec requires that a new EGLSurface default to swap interval
374 // 1, so explicitly set that on the window here.
375 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
376 anw->setSwapInterval(anw, 1);
377
Mathias Agopian518ec112011-05-13 16:21:08 -0700378 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
379 iDpy, iConfig, window, attrib_list);
380 if (surface != EGL_NO_SURFACE) {
381 egl_surface_t* s = new egl_surface_t(dpy, config, window, surface,
382 dp->configs[intptr_t(config)].impl, cnx);
383 return s;
384 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700385
386 // EGLSurface creation failed
387 native_window_set_buffers_format(window, 0);
388 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700389 }
390 return EGL_NO_SURFACE;
391}
392
393EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
394 NativePixmapType pixmap,
395 const EGLint *attrib_list)
396{
397 clearError();
398
399 egl_display_t const* dp = 0;
400 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
401 if (cnx) {
402 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
403 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
404 dp->configs[intptr_t(config)].config, pixmap, attrib_list);
405 if (surface != EGL_NO_SURFACE) {
406 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
407 dp->configs[intptr_t(config)].impl, cnx);
408 return s;
409 }
410 }
411 return EGL_NO_SURFACE;
412}
413
414EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
415 const EGLint *attrib_list)
416{
417 clearError();
418
419 egl_display_t const* dp = 0;
420 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
421 if (cnx) {
422 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
423 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
424 dp->configs[intptr_t(config)].config, attrib_list);
425 if (surface != EGL_NO_SURFACE) {
426 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
427 dp->configs[intptr_t(config)].impl, cnx);
428 return s;
429 }
430 }
431 return EGL_NO_SURFACE;
432}
433
434EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
435{
436 clearError();
437
438 egl_display_t const * const dp = validate_display(dpy);
439 if (!dp) return EGL_FALSE;
440
Mathias Agopianf0480de2011-11-13 20:50:07 -0800441 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700442 if (!_s.get())
443 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700444
445 egl_surface_t * const s = get_surface(surface);
446 EGLBoolean result = s->cnx->egl.eglDestroySurface(
447 dp->disp[s->impl].dpy, s->surface);
448 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700449 _s.terminate();
450 }
451 return result;
452}
453
454EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
455 EGLint attribute, EGLint *value)
456{
457 clearError();
458
459 egl_display_t const * const dp = validate_display(dpy);
460 if (!dp) return EGL_FALSE;
461
Mathias Agopianf0480de2011-11-13 20:50:07 -0800462 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700463 if (!_s.get())
464 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700465
Mathias Agopian518ec112011-05-13 16:21:08 -0700466 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700467 EGLBoolean result(EGL_TRUE);
468 if (attribute == EGL_CONFIG_ID) {
469 // We need to remap EGL_CONFIG_IDs
470 *value = dp->configs[intptr_t(s->config)].configId;
471 } else {
472 result = s->cnx->egl.eglQuerySurface(
473 dp->disp[s->impl].dpy, s->surface, attribute, value);
474 }
475
476 return result;
477}
478
479// ----------------------------------------------------------------------------
480// Contexts
481// ----------------------------------------------------------------------------
482
483EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
484 EGLContext share_list, const EGLint *attrib_list)
485{
486 clearError();
487
488 egl_display_t const* dp = 0;
489 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
490 if (cnx) {
491 if (share_list != EGL_NO_CONTEXT) {
492 egl_context_t* const c = get_context(share_list);
493 share_list = c->context;
494 }
495 EGLContext context = cnx->egl.eglCreateContext(
496 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
497 dp->configs[intptr_t(config)].config,
498 share_list, attrib_list);
499 if (context != EGL_NO_CONTEXT) {
500 // figure out if it's a GLESv1 or GLESv2
501 int version = 0;
502 if (attrib_list) {
503 while (*attrib_list != EGL_NONE) {
504 GLint attr = *attrib_list++;
505 GLint value = *attrib_list++;
506 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
507 if (value == 1) {
508 version = GLESv1_INDEX;
509 } else if (value == 2) {
510 version = GLESv2_INDEX;
511 }
512 }
513 };
514 }
515 egl_context_t* c = new egl_context_t(dpy, context, config,
516 dp->configs[intptr_t(config)].impl, cnx, version);
517 return c;
518 }
519 }
520 return EGL_NO_CONTEXT;
521}
522
523EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
524{
525 clearError();
526
527 egl_display_t const * const dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700528 if (!dp)
529 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700530
Mathias Agopianf0480de2011-11-13 20:50:07 -0800531 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700532 if (!_c.get())
533 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700534
Mathias Agopian518ec112011-05-13 16:21:08 -0700535 egl_context_t * const c = get_context(ctx);
536 EGLBoolean result = c->cnx->egl.eglDestroyContext(
537 dp->disp[c->impl].dpy, c->context);
538 if (result == EGL_TRUE) {
539 _c.terminate();
540 }
541 return result;
542}
543
544static void loseCurrent(egl_context_t * cur_c)
545{
546 if (cur_c) {
547 egl_surface_t * cur_r = get_surface(cur_c->read);
548 egl_surface_t * cur_d = get_surface(cur_c->draw);
549
550 // by construction, these are either 0 or valid (possibly terminated)
551 // it should be impossible for these to be invalid
552 ContextRef _cur_c(cur_c);
553 SurfaceRef _cur_r(cur_r);
554 SurfaceRef _cur_d(cur_d);
555
556 cur_c->read = NULL;
557 cur_c->draw = NULL;
558
559 _cur_c.release();
560 _cur_r.release();
561 _cur_d.release();
562 }
563}
564
565EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
566 EGLSurface read, EGLContext ctx)
567{
568 clearError();
569
570 egl_display_t const * const dp = get_display(dpy);
571 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
572
Mathias Agopian5b287a62011-05-16 18:58:55 -0700573 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
574 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
575 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -0700576 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
577 (draw != EGL_NO_SURFACE) ) {
578 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
579 }
580
581 // get a reference to the object passed in
Mathias Agopianf0480de2011-11-13 20:50:07 -0800582 ContextRef _c(dp, ctx);
583 SurfaceRef _d(dp, draw);
584 SurfaceRef _r(dp, read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700585
586 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -0700587 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700588 // EGL_NO_CONTEXT is valid
589 return EGL_FALSE;
590 }
591
592 // these are the underlying implementation's object
593 EGLContext impl_ctx = EGL_NO_CONTEXT;
594 EGLSurface impl_draw = EGL_NO_SURFACE;
595 EGLSurface impl_read = EGL_NO_SURFACE;
596
597 // these are our objects structs passed in
598 egl_context_t * c = NULL;
599 egl_surface_t const * d = NULL;
600 egl_surface_t const * r = NULL;
601
602 // these are the current objects structs
603 egl_context_t * cur_c = get_context(getContext());
604
605 if (ctx != EGL_NO_CONTEXT) {
606 c = get_context(ctx);
607 impl_ctx = c->context;
608 } else {
609 // no context given, use the implementation of the current context
610 if (cur_c == NULL) {
611 // no current context
612 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
613 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
614 return setError(EGL_BAD_MATCH, EGL_FALSE);
615 }
616 // not an error, there is just no current context.
617 return EGL_TRUE;
618 }
619 }
620
621 // retrieve the underlying implementation's draw EGLSurface
622 if (draw != EGL_NO_SURFACE) {
623 d = get_surface(draw);
624 // make sure the EGLContext and EGLSurface passed in are for
625 // the same driver
626 if (c && d->impl != c->impl)
627 return setError(EGL_BAD_MATCH, EGL_FALSE);
628 impl_draw = d->surface;
629 }
630
631 // retrieve the underlying implementation's read EGLSurface
632 if (read != EGL_NO_SURFACE) {
633 r = get_surface(read);
634 // make sure the EGLContext and EGLSurface passed in are for
635 // the same driver
636 if (c && r->impl != c->impl)
637 return setError(EGL_BAD_MATCH, EGL_FALSE);
638 impl_read = r->surface;
639 }
640
641 EGLBoolean result;
642
643 if (c) {
644 result = c->cnx->egl.eglMakeCurrent(
645 dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
646 } else {
647 result = cur_c->cnx->egl.eglMakeCurrent(
648 dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
649 }
650
651 if (result == EGL_TRUE) {
652
653 loseCurrent(cur_c);
654
655 if (ctx != EGL_NO_CONTEXT) {
656 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
657 egl_tls_t::setContext(ctx);
658 if (gEGLDebugLevel > 0) {
659 CreateDbgContext(c->version, c->cnx->hooks[c->version]);
660 }
661 _c.acquire();
662 _r.acquire();
663 _d.acquire();
664 c->read = read;
665 c->draw = draw;
666 } else {
667 setGLHooksThreadSpecific(&gHooksNoContext);
668 egl_tls_t::setContext(EGL_NO_CONTEXT);
669 }
Mathias Agopian5fecea72011-08-25 18:38:24 -0700670 } else {
671 // this will LOGE the error
672 result = setError(c->cnx->egl.eglGetError(), EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700673 }
674 return result;
675}
676
677
678EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
679 EGLint attribute, EGLint *value)
680{
681 clearError();
682
683 egl_display_t const * const dp = validate_display(dpy);
684 if (!dp) return EGL_FALSE;
685
Mathias Agopianf0480de2011-11-13 20:50:07 -0800686 ContextRef _c(dp, ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700687 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
688
Mathias Agopian518ec112011-05-13 16:21:08 -0700689 egl_context_t * const c = get_context(ctx);
690
691 EGLBoolean result(EGL_TRUE);
692 if (attribute == EGL_CONFIG_ID) {
693 *value = dp->configs[intptr_t(c->config)].configId;
694 } else {
695 // We need to remap EGL_CONFIG_IDs
696 result = c->cnx->egl.eglQueryContext(
697 dp->disp[c->impl].dpy, c->context, attribute, value);
698 }
699
700 return result;
701}
702
703EGLContext eglGetCurrentContext(void)
704{
705 // could be called before eglInitialize(), but we wouldn't have a context
706 // then, and this function would correctly return EGL_NO_CONTEXT.
707
708 clearError();
709
710 EGLContext ctx = getContext();
711 return ctx;
712}
713
714EGLSurface eglGetCurrentSurface(EGLint readdraw)
715{
716 // could be called before eglInitialize(), but we wouldn't have a context
717 // then, and this function would correctly return EGL_NO_SURFACE.
718
719 clearError();
720
721 EGLContext ctx = getContext();
722 if (ctx) {
723 egl_context_t const * const c = get_context(ctx);
724 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
725 switch (readdraw) {
726 case EGL_READ: return c->read;
727 case EGL_DRAW: return c->draw;
728 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
729 }
730 }
731 return EGL_NO_SURFACE;
732}
733
734EGLDisplay eglGetCurrentDisplay(void)
735{
736 // could be called before eglInitialize(), but we wouldn't have a context
737 // then, and this function would correctly return EGL_NO_DISPLAY.
738
739 clearError();
740
741 EGLContext ctx = getContext();
742 if (ctx) {
743 egl_context_t const * const c = get_context(ctx);
744 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
745 return c->dpy;
746 }
747 return EGL_NO_DISPLAY;
748}
749
750EGLBoolean eglWaitGL(void)
751{
752 // could be called before eglInitialize(), but we wouldn't have a context
753 // then, and this function would return GL_TRUE, which isn't wrong.
754
755 clearError();
756
757 EGLBoolean res = EGL_TRUE;
758 EGLContext ctx = getContext();
759 if (ctx) {
760 egl_context_t const * const c = get_context(ctx);
761 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
762 if (uint32_t(c->impl)>=2)
763 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
764 egl_connection_t* const cnx = &gEGLImpl[c->impl];
765 if (!cnx->dso)
766 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
767 res = cnx->egl.eglWaitGL();
768 }
769 return res;
770}
771
772EGLBoolean eglWaitNative(EGLint engine)
773{
774 // could be called before eglInitialize(), but we wouldn't have a context
775 // then, and this function would return GL_TRUE, which isn't wrong.
776
777 clearError();
778
779 EGLBoolean res = EGL_TRUE;
780 EGLContext ctx = getContext();
781 if (ctx) {
782 egl_context_t const * const c = get_context(ctx);
783 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
784 if (uint32_t(c->impl)>=2)
785 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
786 egl_connection_t* const cnx = &gEGLImpl[c->impl];
787 if (!cnx->dso)
788 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
789 res = cnx->egl.eglWaitNative(engine);
790 }
791 return res;
792}
793
794EGLint eglGetError(void)
795{
796 EGLint result = EGL_SUCCESS;
797 EGLint err;
798 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
799 err = EGL_SUCCESS;
800 egl_connection_t* const cnx = &gEGLImpl[i];
801 if (cnx->dso)
802 err = cnx->egl.eglGetError();
803 if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
804 result = err;
805 }
806 err = egl_tls_t::getError();
807 if (result == EGL_SUCCESS)
808 result = err;
809 return result;
810}
811
812// Note: Similar implementations of these functions also exist in
813// gl2.cpp and gl.cpp, and are used by applications that call the
814// exported entry points directly.
815typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
816typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
817
818static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL;
819static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL;
820
821static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image)
822{
823 GLeglImageOES implImage =
824 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
825 glEGLImageTargetTexture2DOES_impl(target, implImage);
826}
827
828static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image)
829{
830 GLeglImageOES implImage =
831 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
832 glEGLImageTargetRenderbufferStorageOES_impl(target, implImage);
833}
834
835__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
836{
837 // eglGetProcAddress() could be the very first function called
838 // in which case we must make sure we've initialized ourselves, this
839 // happens the first time egl_get_display() is called.
840
841 clearError();
842
843 if (egl_init_drivers() == EGL_FALSE) {
844 setError(EGL_BAD_PARAMETER, NULL);
845 return NULL;
846 }
847
Jamie Gennisaca51c02011-11-03 17:42:43 -0700848 // The EGL_ANDROID_blob_cache extension should not be exposed to
849 // applications. It is used internally by the Android EGL layer.
Jamie Gennisc42fcf02011-11-09 15:35:34 -0800850 if (!strcmp(procname, "eglSetBlobCacheFuncsANDROID")) {
Jamie Gennisaca51c02011-11-03 17:42:43 -0700851 return NULL;
852 }
853
Mathias Agopian518ec112011-05-13 16:21:08 -0700854 __eglMustCastToProperFunctionPointerType addr;
855 addr = findProcAddress(procname, sExtentionMap, NELEM(sExtentionMap));
856 if (addr) return addr;
857
Jamie Gennisaca51c02011-11-03 17:42:43 -0700858
Mathias Agopian518ec112011-05-13 16:21:08 -0700859 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
860 pthread_mutex_lock(&sExtensionMapMutex);
861
862 /*
863 * Since eglGetProcAddress() is not associated to anything, it needs
864 * to return a function pointer that "works" regardless of what
865 * the current context is.
866 *
867 * For this reason, we return a "forwarder", a small stub that takes
868 * care of calling the function associated with the context
869 * currently bound.
870 *
871 * We first look for extensions we've already resolved, if we're seeing
872 * this extension for the first time, we go through all our
873 * implementations and call eglGetProcAddress() and record the
874 * result in the appropriate implementation hooks and return the
875 * address of the forwarder corresponding to that hook set.
876 *
877 */
878
879 const String8 name(procname);
880 addr = sGLExtentionMap.valueFor(name);
881 const int slot = sGLExtentionSlot;
882
883 LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
884 "no more slots for eglGetProcAddress(\"%s\")",
885 procname);
886
887 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
888 bool found = false;
889 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
890 egl_connection_t* const cnx = &gEGLImpl[i];
891 if (cnx->dso && cnx->egl.eglGetProcAddress) {
892 found = true;
893 // Extensions are independent of the bound context
894 cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
895 cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
896#if EGL_TRACE
897 gHooksDebug.ext.extensions[slot] = gHooksTrace.ext.extensions[slot] =
898#endif
899 cnx->egl.eglGetProcAddress(procname);
900 }
901 }
902 if (found) {
903 addr = gExtensionForwarders[slot];
904
905 if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) {
906 glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr;
907 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper;
908 }
909 if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) {
910 glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr;
911 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper;
912 }
913
914 sGLExtentionMap.add(name, addr);
915 sGLExtentionSlot++;
916 }
917 }
918
919 pthread_mutex_unlock(&sExtensionMapMutex);
920 return addr;
921}
922
923EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
924{
925 EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw);
926 if (gEGLDebugLevel > 0)
927 Debug_eglSwapBuffers(dpy, draw);
928
929 clearError();
930
931 egl_display_t const * const dp = validate_display(dpy);
932 if (!dp) return EGL_FALSE;
933
Mathias Agopianf0480de2011-11-13 20:50:07 -0800934 SurfaceRef _s(dp, draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700935 if (!_s.get())
936 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700937
Mathias Agopian518ec112011-05-13 16:21:08 -0700938 egl_surface_t const * const s = get_surface(draw);
939 return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
940}
941
942EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
943 NativePixmapType target)
944{
945 clearError();
946
947 egl_display_t const * const dp = validate_display(dpy);
948 if (!dp) return EGL_FALSE;
949
Mathias Agopianf0480de2011-11-13 20:50:07 -0800950 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700951 if (!_s.get())
952 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700953
Mathias Agopian518ec112011-05-13 16:21:08 -0700954 egl_surface_t const * const s = get_surface(surface);
955 return s->cnx->egl.eglCopyBuffers(
956 dp->disp[s->impl].dpy, s->surface, target);
957}
958
959const char* eglQueryString(EGLDisplay dpy, EGLint name)
960{
961 clearError();
962
963 egl_display_t const * const dp = validate_display(dpy);
964 if (!dp) return (const char *) NULL;
965
966 switch (name) {
967 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800968 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -0700969 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800970 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -0700971 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800972 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -0700973 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800974 return dp->getClientApiString();
Mathias Agopian518ec112011-05-13 16:21:08 -0700975 }
976 return setError(EGL_BAD_PARAMETER, (const char *)0);
977}
978
979
980// ----------------------------------------------------------------------------
981// EGL 1.1
982// ----------------------------------------------------------------------------
983
984EGLBoolean eglSurfaceAttrib(
985 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
986{
987 clearError();
988
989 egl_display_t const * const dp = validate_display(dpy);
990 if (!dp) return EGL_FALSE;
991
Mathias Agopianf0480de2011-11-13 20:50:07 -0800992 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700993 if (!_s.get())
994 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700995
Mathias Agopian518ec112011-05-13 16:21:08 -0700996 egl_surface_t const * const s = get_surface(surface);
997 if (s->cnx->egl.eglSurfaceAttrib) {
998 return s->cnx->egl.eglSurfaceAttrib(
999 dp->disp[s->impl].dpy, s->surface, attribute, value);
1000 }
1001 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1002}
1003
1004EGLBoolean eglBindTexImage(
1005 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1006{
1007 clearError();
1008
1009 egl_display_t const * const dp = validate_display(dpy);
1010 if (!dp) return EGL_FALSE;
1011
Mathias Agopianf0480de2011-11-13 20:50:07 -08001012 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001013 if (!_s.get())
1014 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001015
Mathias Agopian518ec112011-05-13 16:21:08 -07001016 egl_surface_t const * const s = get_surface(surface);
1017 if (s->cnx->egl.eglBindTexImage) {
1018 return s->cnx->egl.eglBindTexImage(
1019 dp->disp[s->impl].dpy, s->surface, buffer);
1020 }
1021 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1022}
1023
1024EGLBoolean eglReleaseTexImage(
1025 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1026{
1027 clearError();
1028
1029 egl_display_t const * const dp = validate_display(dpy);
1030 if (!dp) return EGL_FALSE;
1031
Mathias Agopianf0480de2011-11-13 20:50:07 -08001032 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001033 if (!_s.get())
1034 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001035
Mathias Agopian518ec112011-05-13 16:21:08 -07001036 egl_surface_t const * const s = get_surface(surface);
1037 if (s->cnx->egl.eglReleaseTexImage) {
1038 return s->cnx->egl.eglReleaseTexImage(
1039 dp->disp[s->impl].dpy, s->surface, buffer);
1040 }
1041 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1042}
1043
1044EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1045{
1046 clearError();
1047
1048 egl_display_t const * const dp = validate_display(dpy);
1049 if (!dp) return EGL_FALSE;
1050
1051 EGLBoolean res = EGL_TRUE;
1052 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1053 egl_connection_t* const cnx = &gEGLImpl[i];
1054 if (cnx->dso) {
1055 if (cnx->egl.eglSwapInterval) {
1056 if (cnx->egl.eglSwapInterval(
1057 dp->disp[i].dpy, interval) == EGL_FALSE) {
1058 res = EGL_FALSE;
1059 }
1060 }
1061 }
1062 }
1063 return res;
1064}
1065
1066
1067// ----------------------------------------------------------------------------
1068// EGL 1.2
1069// ----------------------------------------------------------------------------
1070
1071EGLBoolean eglWaitClient(void)
1072{
1073 clearError();
1074
1075 // could be called before eglInitialize(), but we wouldn't have a context
1076 // then, and this function would return GL_TRUE, which isn't wrong.
1077 EGLBoolean res = EGL_TRUE;
1078 EGLContext ctx = getContext();
1079 if (ctx) {
1080 egl_context_t const * const c = get_context(ctx);
1081 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1082 if (uint32_t(c->impl)>=2)
1083 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1084 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1085 if (!cnx->dso)
1086 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1087 if (cnx->egl.eglWaitClient) {
1088 res = cnx->egl.eglWaitClient();
1089 } else {
1090 res = cnx->egl.eglWaitGL();
1091 }
1092 }
1093 return res;
1094}
1095
1096EGLBoolean eglBindAPI(EGLenum api)
1097{
1098 clearError();
1099
1100 if (egl_init_drivers() == EGL_FALSE) {
1101 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1102 }
1103
1104 // bind this API on all EGLs
1105 EGLBoolean res = EGL_TRUE;
1106 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1107 egl_connection_t* const cnx = &gEGLImpl[i];
1108 if (cnx->dso) {
1109 if (cnx->egl.eglBindAPI) {
1110 if (cnx->egl.eglBindAPI(api) == EGL_FALSE) {
1111 res = EGL_FALSE;
1112 }
1113 }
1114 }
1115 }
1116 return res;
1117}
1118
1119EGLenum eglQueryAPI(void)
1120{
1121 clearError();
1122
1123 if (egl_init_drivers() == EGL_FALSE) {
1124 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1125 }
1126
1127 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1128 egl_connection_t* const cnx = &gEGLImpl[i];
1129 if (cnx->dso) {
1130 if (cnx->egl.eglQueryAPI) {
1131 // the first one we find is okay, because they all
1132 // should be the same
1133 return cnx->egl.eglQueryAPI();
1134 }
1135 }
1136 }
1137 // or, it can only be OpenGL ES
1138 return EGL_OPENGL_ES_API;
1139}
1140
1141EGLBoolean eglReleaseThread(void)
1142{
1143 clearError();
1144
1145 // If there is context bound to the thread, release it
1146 loseCurrent(get_context(getContext()));
1147
1148 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1149 egl_connection_t* const cnx = &gEGLImpl[i];
1150 if (cnx->dso) {
1151 if (cnx->egl.eglReleaseThread) {
1152 cnx->egl.eglReleaseThread();
1153 }
1154 }
1155 }
1156 egl_tls_t::clearTLS();
1157 dbgReleaseThread();
1158 return EGL_TRUE;
1159}
1160
1161EGLSurface eglCreatePbufferFromClientBuffer(
1162 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1163 EGLConfig config, const EGLint *attrib_list)
1164{
1165 clearError();
1166
1167 egl_display_t const* dp = 0;
1168 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
1169 if (!cnx) return EGL_FALSE;
1170 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1171 return cnx->egl.eglCreatePbufferFromClientBuffer(
1172 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1173 buftype, buffer,
1174 dp->configs[intptr_t(config)].config, attrib_list);
1175 }
1176 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1177}
1178
1179// ----------------------------------------------------------------------------
1180// EGL_EGLEXT_VERSION 3
1181// ----------------------------------------------------------------------------
1182
1183EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1184 const EGLint *attrib_list)
1185{
1186 clearError();
1187
1188 egl_display_t const * const dp = validate_display(dpy);
1189 if (!dp) return EGL_FALSE;
1190
Mathias Agopianf0480de2011-11-13 20:50:07 -08001191 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001192 if (!_s.get())
1193 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001194
1195 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001196 if (s->cnx->egl.eglLockSurfaceKHR) {
1197 return s->cnx->egl.eglLockSurfaceKHR(
1198 dp->disp[s->impl].dpy, s->surface, attrib_list);
1199 }
1200 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1201}
1202
1203EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1204{
1205 clearError();
1206
1207 egl_display_t const * const dp = validate_display(dpy);
1208 if (!dp) return EGL_FALSE;
1209
Mathias Agopianf0480de2011-11-13 20:50:07 -08001210 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001211 if (!_s.get())
1212 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001213
1214 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001215 if (s->cnx->egl.eglUnlockSurfaceKHR) {
1216 return s->cnx->egl.eglUnlockSurfaceKHR(
1217 dp->disp[s->impl].dpy, s->surface);
1218 }
1219 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1220}
1221
1222EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1223 EGLClientBuffer buffer, const EGLint *attrib_list)
1224{
1225 clearError();
1226
1227 egl_display_t const * const dp = validate_display(dpy);
1228 if (!dp) return EGL_NO_IMAGE_KHR;
1229
1230 if (ctx != EGL_NO_CONTEXT) {
Mathias Agopianf0480de2011-11-13 20:50:07 -08001231 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001232 if (!_c.get())
1233 return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
Mathias Agopian518ec112011-05-13 16:21:08 -07001234 egl_context_t * const c = get_context(ctx);
1235 // since we have an EGLContext, we know which implementation to use
1236 EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
1237 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
1238 if (image == EGL_NO_IMAGE_KHR)
1239 return image;
1240
1241 egl_image_t* result = new egl_image_t(dpy, ctx);
1242 result->images[c->impl] = image;
1243 return (EGLImageKHR)result;
1244 } else {
1245 // EGL_NO_CONTEXT is a valid parameter
1246
1247 /* Since we don't have a way to know which implementation to call,
1248 * we're calling all of them. If at least one of the implementation
1249 * succeeded, this is a success.
1250 */
1251
1252 EGLint currentError = eglGetError();
1253
1254 EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS];
1255 bool success = false;
1256 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1257 egl_connection_t* const cnx = &gEGLImpl[i];
1258 implImages[i] = EGL_NO_IMAGE_KHR;
1259 if (cnx->dso) {
1260 if (cnx->egl.eglCreateImageKHR) {
1261 implImages[i] = cnx->egl.eglCreateImageKHR(
1262 dp->disp[i].dpy, ctx, target, buffer, attrib_list);
1263 if (implImages[i] != EGL_NO_IMAGE_KHR) {
1264 success = true;
1265 }
1266 }
1267 }
1268 }
1269
1270 if (!success) {
1271 // failure, if there was an error when we entered this function,
1272 // the error flag must not be updated.
1273 // Otherwise, the error is whatever happened in the implementation
1274 // that faulted.
1275 if (currentError != EGL_SUCCESS) {
1276 setError(currentError, EGL_NO_IMAGE_KHR);
1277 }
1278 return EGL_NO_IMAGE_KHR;
1279 } else {
1280 // In case of success, we need to clear all error flags
1281 // (especially those caused by the implementation that didn't
1282 // succeed). TODO: we could avoid this if we knew this was
1283 // a "full" success (all implementation succeeded).
1284 eglGetError();
1285 }
1286
1287 egl_image_t* result = new egl_image_t(dpy, ctx);
1288 memcpy(result->images, implImages, sizeof(implImages));
1289 return (EGLImageKHR)result;
1290 }
1291}
1292
1293EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1294{
1295 clearError();
1296
1297 egl_display_t const * const dp = validate_display(dpy);
1298 if (!dp) return EGL_FALSE;
1299
Mathias Agopianf0480de2011-11-13 20:50:07 -08001300 ImageRef _i(dp, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001301 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1302
1303 egl_image_t* image = get_image(img);
1304 bool success = false;
1305 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1306 egl_connection_t* const cnx = &gEGLImpl[i];
1307 if (image->images[i] != EGL_NO_IMAGE_KHR) {
1308 if (cnx->dso) {
1309 if (cnx->egl.eglDestroyImageKHR) {
1310 if (cnx->egl.eglDestroyImageKHR(
1311 dp->disp[i].dpy, image->images[i])) {
1312 success = true;
1313 }
1314 }
1315 }
1316 }
1317 }
1318 if (!success)
1319 return EGL_FALSE;
1320
1321 _i.terminate();
1322
1323 return EGL_TRUE;
1324}
1325
1326// ----------------------------------------------------------------------------
1327// EGL_EGLEXT_VERSION 5
1328// ----------------------------------------------------------------------------
1329
1330
1331EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1332{
1333 clearError();
1334
1335 egl_display_t const * const dp = validate_display(dpy);
1336 if (!dp) return EGL_NO_SYNC_KHR;
1337
1338 EGLContext ctx = eglGetCurrentContext();
Mathias Agopianf0480de2011-11-13 20:50:07 -08001339 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001340 if (!_c.get())
1341 return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR);
1342
Mathias Agopian518ec112011-05-13 16:21:08 -07001343 egl_context_t * const c = get_context(ctx);
1344 EGLSyncKHR result = EGL_NO_SYNC_KHR;
1345 if (c->cnx->egl.eglCreateSyncKHR) {
1346 EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR(
1347 dp->disp[c->impl].dpy, type, attrib_list);
1348 if (sync == EGL_NO_SYNC_KHR)
1349 return sync;
1350 result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync);
1351 }
1352 return (EGLSyncKHR)result;
1353}
1354
1355EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1356{
1357 clearError();
1358
1359 egl_display_t const * const dp = validate_display(dpy);
1360 if (!dp) return EGL_FALSE;
1361
Mathias Agopianf0480de2011-11-13 20:50:07 -08001362 SyncRef _s(dp, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001363 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1364 egl_sync_t* syncObject = get_sync(sync);
1365
1366 EGLContext ctx = syncObject->context;
Mathias Agopianf0480de2011-11-13 20:50:07 -08001367 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001368 if (!_c.get())
1369 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001370
1371 EGLBoolean result = EGL_FALSE;
1372 egl_context_t * const c = get_context(ctx);
1373 if (c->cnx->egl.eglDestroySyncKHR) {
1374 result = c->cnx->egl.eglDestroySyncKHR(
1375 dp->disp[c->impl].dpy, syncObject->sync);
1376 if (result)
1377 _s.terminate();
1378 }
1379 return result;
1380}
1381
1382EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
1383{
1384 clearError();
1385
1386 egl_display_t const * const dp = validate_display(dpy);
1387 if (!dp) return EGL_FALSE;
1388
Mathias Agopianf0480de2011-11-13 20:50:07 -08001389 SyncRef _s(dp, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001390 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1391 egl_sync_t* syncObject = get_sync(sync);
1392
1393 EGLContext ctx = syncObject->context;
Mathias Agopianf0480de2011-11-13 20:50:07 -08001394 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001395 if (!_c.get())
1396 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001397
1398 egl_context_t * const c = get_context(ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -07001399 if (c->cnx->egl.eglClientWaitSyncKHR) {
1400 return c->cnx->egl.eglClientWaitSyncKHR(
1401 dp->disp[c->impl].dpy, syncObject->sync, flags, timeout);
1402 }
1403
1404 return EGL_FALSE;
1405}
1406
1407EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
1408{
1409 clearError();
1410
1411 egl_display_t const * const dp = validate_display(dpy);
1412 if (!dp) return EGL_FALSE;
1413
Mathias Agopianf0480de2011-11-13 20:50:07 -08001414 SyncRef _s(dp, sync);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001415 if (!_s.get())
1416 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001417
Mathias Agopian5b287a62011-05-16 18:58:55 -07001418 egl_sync_t* syncObject = get_sync(sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001419 EGLContext ctx = syncObject->context;
Mathias Agopianf0480de2011-11-13 20:50:07 -08001420 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001421 if (!_c.get())
1422 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001423
1424 egl_context_t * const c = get_context(ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -07001425 if (c->cnx->egl.eglGetSyncAttribKHR) {
1426 return c->cnx->egl.eglGetSyncAttribKHR(
1427 dp->disp[c->impl].dpy, syncObject->sync, attribute, value);
1428 }
1429
1430 return EGL_FALSE;
1431}
1432
1433// ----------------------------------------------------------------------------
1434// ANDROID extensions
1435// ----------------------------------------------------------------------------
1436
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001437/* ANDROID extensions entry-point go here */
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001438
1439// ----------------------------------------------------------------------------
1440// NVIDIA extensions
1441// ----------------------------------------------------------------------------
1442EGLuint64NV eglGetSystemTimeFrequencyNV()
1443{
1444 clearError();
1445
1446 if (egl_init_drivers() == EGL_FALSE) {
1447 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1448 }
1449
1450 EGLuint64NV ret = 0;
1451 egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE];
1452
1453 if (cnx->dso) {
1454 if (cnx->egl.eglGetSystemTimeFrequencyNV) {
1455 return cnx->egl.eglGetSystemTimeFrequencyNV();
1456 }
1457 }
1458
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001459 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001460}
1461
1462EGLuint64NV eglGetSystemTimeNV()
1463{
1464 clearError();
1465
1466 if (egl_init_drivers() == EGL_FALSE) {
1467 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1468 }
1469
1470 EGLuint64NV ret = 0;
1471 egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE];
1472
1473 if (cnx->dso) {
1474 if (cnx->egl.eglGetSystemTimeNV) {
1475 return cnx->egl.eglGetSystemTimeNV();
1476 }
1477 }
1478
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001479 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001480}