blob: 2237eb6c0873887f7b59af69f72bd6adc0840b89 [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
373 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
374 iDpy, iConfig, window, attrib_list);
375 if (surface != EGL_NO_SURFACE) {
376 egl_surface_t* s = new egl_surface_t(dpy, config, window, surface,
377 dp->configs[intptr_t(config)].impl, cnx);
378 return s;
379 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700380
381 // EGLSurface creation failed
382 native_window_set_buffers_format(window, 0);
383 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700384 }
385 return EGL_NO_SURFACE;
386}
387
388EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
389 NativePixmapType pixmap,
390 const EGLint *attrib_list)
391{
392 clearError();
393
394 egl_display_t const* dp = 0;
395 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
396 if (cnx) {
397 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
398 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
399 dp->configs[intptr_t(config)].config, pixmap, attrib_list);
400 if (surface != EGL_NO_SURFACE) {
401 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
402 dp->configs[intptr_t(config)].impl, cnx);
403 return s;
404 }
405 }
406 return EGL_NO_SURFACE;
407}
408
409EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
410 const EGLint *attrib_list)
411{
412 clearError();
413
414 egl_display_t const* dp = 0;
415 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
416 if (cnx) {
417 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
418 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
419 dp->configs[intptr_t(config)].config, attrib_list);
420 if (surface != EGL_NO_SURFACE) {
421 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
422 dp->configs[intptr_t(config)].impl, cnx);
423 return s;
424 }
425 }
426 return EGL_NO_SURFACE;
427}
428
429EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
430{
431 clearError();
432
433 egl_display_t const * const dp = validate_display(dpy);
434 if (!dp) return EGL_FALSE;
435
Mathias Agopianf0480de2011-11-13 20:50:07 -0800436 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700437 if (!_s.get())
438 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700439
440 egl_surface_t * const s = get_surface(surface);
441 EGLBoolean result = s->cnx->egl.eglDestroySurface(
442 dp->disp[s->impl].dpy, s->surface);
443 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700444 _s.terminate();
445 }
446 return result;
447}
448
449EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
450 EGLint attribute, EGLint *value)
451{
452 clearError();
453
454 egl_display_t const * const dp = validate_display(dpy);
455 if (!dp) return EGL_FALSE;
456
Mathias Agopianf0480de2011-11-13 20:50:07 -0800457 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700458 if (!_s.get())
459 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700460
Mathias Agopian518ec112011-05-13 16:21:08 -0700461 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700462 EGLBoolean result(EGL_TRUE);
463 if (attribute == EGL_CONFIG_ID) {
464 // We need to remap EGL_CONFIG_IDs
465 *value = dp->configs[intptr_t(s->config)].configId;
466 } else {
467 result = s->cnx->egl.eglQuerySurface(
468 dp->disp[s->impl].dpy, s->surface, attribute, value);
469 }
470
471 return result;
472}
473
474// ----------------------------------------------------------------------------
475// Contexts
476// ----------------------------------------------------------------------------
477
478EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
479 EGLContext share_list, const EGLint *attrib_list)
480{
481 clearError();
482
483 egl_display_t const* dp = 0;
484 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
485 if (cnx) {
486 if (share_list != EGL_NO_CONTEXT) {
487 egl_context_t* const c = get_context(share_list);
488 share_list = c->context;
489 }
490 EGLContext context = cnx->egl.eglCreateContext(
491 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
492 dp->configs[intptr_t(config)].config,
493 share_list, attrib_list);
494 if (context != EGL_NO_CONTEXT) {
495 // figure out if it's a GLESv1 or GLESv2
496 int version = 0;
497 if (attrib_list) {
498 while (*attrib_list != EGL_NONE) {
499 GLint attr = *attrib_list++;
500 GLint value = *attrib_list++;
501 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
502 if (value == 1) {
503 version = GLESv1_INDEX;
504 } else if (value == 2) {
505 version = GLESv2_INDEX;
506 }
507 }
508 };
509 }
510 egl_context_t* c = new egl_context_t(dpy, context, config,
511 dp->configs[intptr_t(config)].impl, cnx, version);
512 return c;
513 }
514 }
515 return EGL_NO_CONTEXT;
516}
517
518EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
519{
520 clearError();
521
522 egl_display_t const * const dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700523 if (!dp)
524 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700525
Mathias Agopianf0480de2011-11-13 20:50:07 -0800526 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700527 if (!_c.get())
528 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700529
Mathias Agopian518ec112011-05-13 16:21:08 -0700530 egl_context_t * const c = get_context(ctx);
531 EGLBoolean result = c->cnx->egl.eglDestroyContext(
532 dp->disp[c->impl].dpy, c->context);
533 if (result == EGL_TRUE) {
534 _c.terminate();
535 }
536 return result;
537}
538
539static void loseCurrent(egl_context_t * cur_c)
540{
541 if (cur_c) {
542 egl_surface_t * cur_r = get_surface(cur_c->read);
543 egl_surface_t * cur_d = get_surface(cur_c->draw);
544
545 // by construction, these are either 0 or valid (possibly terminated)
546 // it should be impossible for these to be invalid
547 ContextRef _cur_c(cur_c);
548 SurfaceRef _cur_r(cur_r);
549 SurfaceRef _cur_d(cur_d);
550
551 cur_c->read = NULL;
552 cur_c->draw = NULL;
553
554 _cur_c.release();
555 _cur_r.release();
556 _cur_d.release();
557 }
558}
559
560EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
561 EGLSurface read, EGLContext ctx)
562{
563 clearError();
564
565 egl_display_t const * const dp = get_display(dpy);
566 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
567
Mathias Agopian5b287a62011-05-16 18:58:55 -0700568 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
569 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
570 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -0700571 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
572 (draw != EGL_NO_SURFACE) ) {
573 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
574 }
575
576 // get a reference to the object passed in
Mathias Agopianf0480de2011-11-13 20:50:07 -0800577 ContextRef _c(dp, ctx);
578 SurfaceRef _d(dp, draw);
579 SurfaceRef _r(dp, read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700580
581 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -0700582 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700583 // EGL_NO_CONTEXT is valid
584 return EGL_FALSE;
585 }
586
587 // these are the underlying implementation's object
588 EGLContext impl_ctx = EGL_NO_CONTEXT;
589 EGLSurface impl_draw = EGL_NO_SURFACE;
590 EGLSurface impl_read = EGL_NO_SURFACE;
591
592 // these are our objects structs passed in
593 egl_context_t * c = NULL;
594 egl_surface_t const * d = NULL;
595 egl_surface_t const * r = NULL;
596
597 // these are the current objects structs
598 egl_context_t * cur_c = get_context(getContext());
599
600 if (ctx != EGL_NO_CONTEXT) {
601 c = get_context(ctx);
602 impl_ctx = c->context;
603 } else {
604 // no context given, use the implementation of the current context
605 if (cur_c == NULL) {
606 // no current context
607 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
608 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
609 return setError(EGL_BAD_MATCH, EGL_FALSE);
610 }
611 // not an error, there is just no current context.
612 return EGL_TRUE;
613 }
614 }
615
616 // retrieve the underlying implementation's draw EGLSurface
617 if (draw != EGL_NO_SURFACE) {
618 d = get_surface(draw);
619 // make sure the EGLContext and EGLSurface passed in are for
620 // the same driver
621 if (c && d->impl != c->impl)
622 return setError(EGL_BAD_MATCH, EGL_FALSE);
623 impl_draw = d->surface;
624 }
625
626 // retrieve the underlying implementation's read EGLSurface
627 if (read != EGL_NO_SURFACE) {
628 r = get_surface(read);
629 // make sure the EGLContext and EGLSurface passed in are for
630 // the same driver
631 if (c && r->impl != c->impl)
632 return setError(EGL_BAD_MATCH, EGL_FALSE);
633 impl_read = r->surface;
634 }
635
636 EGLBoolean result;
637
638 if (c) {
639 result = c->cnx->egl.eglMakeCurrent(
640 dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
641 } else {
642 result = cur_c->cnx->egl.eglMakeCurrent(
643 dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
644 }
645
646 if (result == EGL_TRUE) {
647
648 loseCurrent(cur_c);
649
650 if (ctx != EGL_NO_CONTEXT) {
651 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
652 egl_tls_t::setContext(ctx);
653 if (gEGLDebugLevel > 0) {
654 CreateDbgContext(c->version, c->cnx->hooks[c->version]);
655 }
656 _c.acquire();
657 _r.acquire();
658 _d.acquire();
659 c->read = read;
660 c->draw = draw;
661 } else {
662 setGLHooksThreadSpecific(&gHooksNoContext);
663 egl_tls_t::setContext(EGL_NO_CONTEXT);
664 }
Mathias Agopian5fecea72011-08-25 18:38:24 -0700665 } else {
666 // this will LOGE the error
667 result = setError(c->cnx->egl.eglGetError(), EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700668 }
669 return result;
670}
671
672
673EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
674 EGLint attribute, EGLint *value)
675{
676 clearError();
677
678 egl_display_t const * const dp = validate_display(dpy);
679 if (!dp) return EGL_FALSE;
680
Mathias Agopianf0480de2011-11-13 20:50:07 -0800681 ContextRef _c(dp, ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700682 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
683
Mathias Agopian518ec112011-05-13 16:21:08 -0700684 egl_context_t * const c = get_context(ctx);
685
686 EGLBoolean result(EGL_TRUE);
687 if (attribute == EGL_CONFIG_ID) {
688 *value = dp->configs[intptr_t(c->config)].configId;
689 } else {
690 // We need to remap EGL_CONFIG_IDs
691 result = c->cnx->egl.eglQueryContext(
692 dp->disp[c->impl].dpy, c->context, attribute, value);
693 }
694
695 return result;
696}
697
698EGLContext eglGetCurrentContext(void)
699{
700 // could be called before eglInitialize(), but we wouldn't have a context
701 // then, and this function would correctly return EGL_NO_CONTEXT.
702
703 clearError();
704
705 EGLContext ctx = getContext();
706 return ctx;
707}
708
709EGLSurface eglGetCurrentSurface(EGLint readdraw)
710{
711 // could be called before eglInitialize(), but we wouldn't have a context
712 // then, and this function would correctly return EGL_NO_SURFACE.
713
714 clearError();
715
716 EGLContext ctx = getContext();
717 if (ctx) {
718 egl_context_t const * const c = get_context(ctx);
719 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
720 switch (readdraw) {
721 case EGL_READ: return c->read;
722 case EGL_DRAW: return c->draw;
723 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
724 }
725 }
726 return EGL_NO_SURFACE;
727}
728
729EGLDisplay eglGetCurrentDisplay(void)
730{
731 // could be called before eglInitialize(), but we wouldn't have a context
732 // then, and this function would correctly return EGL_NO_DISPLAY.
733
734 clearError();
735
736 EGLContext ctx = getContext();
737 if (ctx) {
738 egl_context_t const * const c = get_context(ctx);
739 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
740 return c->dpy;
741 }
742 return EGL_NO_DISPLAY;
743}
744
745EGLBoolean eglWaitGL(void)
746{
747 // could be called before eglInitialize(), but we wouldn't have a context
748 // then, and this function would return GL_TRUE, which isn't wrong.
749
750 clearError();
751
752 EGLBoolean res = EGL_TRUE;
753 EGLContext ctx = getContext();
754 if (ctx) {
755 egl_context_t const * const c = get_context(ctx);
756 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
757 if (uint32_t(c->impl)>=2)
758 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
759 egl_connection_t* const cnx = &gEGLImpl[c->impl];
760 if (!cnx->dso)
761 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
762 res = cnx->egl.eglWaitGL();
763 }
764 return res;
765}
766
767EGLBoolean eglWaitNative(EGLint engine)
768{
769 // could be called before eglInitialize(), but we wouldn't have a context
770 // then, and this function would return GL_TRUE, which isn't wrong.
771
772 clearError();
773
774 EGLBoolean res = EGL_TRUE;
775 EGLContext ctx = getContext();
776 if (ctx) {
777 egl_context_t const * const c = get_context(ctx);
778 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
779 if (uint32_t(c->impl)>=2)
780 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
781 egl_connection_t* const cnx = &gEGLImpl[c->impl];
782 if (!cnx->dso)
783 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
784 res = cnx->egl.eglWaitNative(engine);
785 }
786 return res;
787}
788
789EGLint eglGetError(void)
790{
791 EGLint result = EGL_SUCCESS;
792 EGLint err;
793 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
794 err = EGL_SUCCESS;
795 egl_connection_t* const cnx = &gEGLImpl[i];
796 if (cnx->dso)
797 err = cnx->egl.eglGetError();
798 if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
799 result = err;
800 }
801 err = egl_tls_t::getError();
802 if (result == EGL_SUCCESS)
803 result = err;
804 return result;
805}
806
807// Note: Similar implementations of these functions also exist in
808// gl2.cpp and gl.cpp, and are used by applications that call the
809// exported entry points directly.
810typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
811typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
812
813static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL;
814static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL;
815
816static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image)
817{
818 GLeglImageOES implImage =
819 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
820 glEGLImageTargetTexture2DOES_impl(target, implImage);
821}
822
823static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image)
824{
825 GLeglImageOES implImage =
826 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
827 glEGLImageTargetRenderbufferStorageOES_impl(target, implImage);
828}
829
830__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
831{
832 // eglGetProcAddress() could be the very first function called
833 // in which case we must make sure we've initialized ourselves, this
834 // happens the first time egl_get_display() is called.
835
836 clearError();
837
838 if (egl_init_drivers() == EGL_FALSE) {
839 setError(EGL_BAD_PARAMETER, NULL);
840 return NULL;
841 }
842
Jamie Gennisaca51c02011-11-03 17:42:43 -0700843 // The EGL_ANDROID_blob_cache extension should not be exposed to
844 // applications. It is used internally by the Android EGL layer.
Jamie Gennisc42fcf02011-11-09 15:35:34 -0800845 if (!strcmp(procname, "eglSetBlobCacheFuncsANDROID")) {
Jamie Gennisaca51c02011-11-03 17:42:43 -0700846 return NULL;
847 }
848
Mathias Agopian518ec112011-05-13 16:21:08 -0700849 __eglMustCastToProperFunctionPointerType addr;
850 addr = findProcAddress(procname, sExtentionMap, NELEM(sExtentionMap));
851 if (addr) return addr;
852
Jamie Gennisaca51c02011-11-03 17:42:43 -0700853
Mathias Agopian518ec112011-05-13 16:21:08 -0700854 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
855 pthread_mutex_lock(&sExtensionMapMutex);
856
857 /*
858 * Since eglGetProcAddress() is not associated to anything, it needs
859 * to return a function pointer that "works" regardless of what
860 * the current context is.
861 *
862 * For this reason, we return a "forwarder", a small stub that takes
863 * care of calling the function associated with the context
864 * currently bound.
865 *
866 * We first look for extensions we've already resolved, if we're seeing
867 * this extension for the first time, we go through all our
868 * implementations and call eglGetProcAddress() and record the
869 * result in the appropriate implementation hooks and return the
870 * address of the forwarder corresponding to that hook set.
871 *
872 */
873
874 const String8 name(procname);
875 addr = sGLExtentionMap.valueFor(name);
876 const int slot = sGLExtentionSlot;
877
878 LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
879 "no more slots for eglGetProcAddress(\"%s\")",
880 procname);
881
882 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
883 bool found = false;
884 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
885 egl_connection_t* const cnx = &gEGLImpl[i];
886 if (cnx->dso && cnx->egl.eglGetProcAddress) {
887 found = true;
888 // Extensions are independent of the bound context
889 cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
890 cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
891#if EGL_TRACE
892 gHooksDebug.ext.extensions[slot] = gHooksTrace.ext.extensions[slot] =
893#endif
894 cnx->egl.eglGetProcAddress(procname);
895 }
896 }
897 if (found) {
898 addr = gExtensionForwarders[slot];
899
900 if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) {
901 glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr;
902 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper;
903 }
904 if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) {
905 glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr;
906 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper;
907 }
908
909 sGLExtentionMap.add(name, addr);
910 sGLExtentionSlot++;
911 }
912 }
913
914 pthread_mutex_unlock(&sExtensionMapMutex);
915 return addr;
916}
917
918EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
919{
920 EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw);
921 if (gEGLDebugLevel > 0)
922 Debug_eglSwapBuffers(dpy, draw);
923
924 clearError();
925
926 egl_display_t const * const dp = validate_display(dpy);
927 if (!dp) return EGL_FALSE;
928
Mathias Agopianf0480de2011-11-13 20:50:07 -0800929 SurfaceRef _s(dp, draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700930 if (!_s.get())
931 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700932
Mathias Agopian518ec112011-05-13 16:21:08 -0700933 egl_surface_t const * const s = get_surface(draw);
934 return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
935}
936
937EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
938 NativePixmapType target)
939{
940 clearError();
941
942 egl_display_t const * const dp = validate_display(dpy);
943 if (!dp) return EGL_FALSE;
944
Mathias Agopianf0480de2011-11-13 20:50:07 -0800945 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700946 if (!_s.get())
947 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700948
Mathias Agopian518ec112011-05-13 16:21:08 -0700949 egl_surface_t const * const s = get_surface(surface);
950 return s->cnx->egl.eglCopyBuffers(
951 dp->disp[s->impl].dpy, s->surface, target);
952}
953
954const char* eglQueryString(EGLDisplay dpy, EGLint name)
955{
956 clearError();
957
958 egl_display_t const * const dp = validate_display(dpy);
959 if (!dp) return (const char *) NULL;
960
961 switch (name) {
962 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800963 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -0700964 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800965 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -0700966 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800967 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -0700968 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800969 return dp->getClientApiString();
Mathias Agopian518ec112011-05-13 16:21:08 -0700970 }
971 return setError(EGL_BAD_PARAMETER, (const char *)0);
972}
973
974
975// ----------------------------------------------------------------------------
976// EGL 1.1
977// ----------------------------------------------------------------------------
978
979EGLBoolean eglSurfaceAttrib(
980 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
981{
982 clearError();
983
984 egl_display_t const * const dp = validate_display(dpy);
985 if (!dp) return EGL_FALSE;
986
Mathias Agopianf0480de2011-11-13 20:50:07 -0800987 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700988 if (!_s.get())
989 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700990
Mathias Agopian518ec112011-05-13 16:21:08 -0700991 egl_surface_t const * const s = get_surface(surface);
992 if (s->cnx->egl.eglSurfaceAttrib) {
993 return s->cnx->egl.eglSurfaceAttrib(
994 dp->disp[s->impl].dpy, s->surface, attribute, value);
995 }
996 return setError(EGL_BAD_SURFACE, EGL_FALSE);
997}
998
999EGLBoolean eglBindTexImage(
1000 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1001{
1002 clearError();
1003
1004 egl_display_t const * const dp = validate_display(dpy);
1005 if (!dp) return EGL_FALSE;
1006
Mathias Agopianf0480de2011-11-13 20:50:07 -08001007 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001008 if (!_s.get())
1009 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001010
Mathias Agopian518ec112011-05-13 16:21:08 -07001011 egl_surface_t const * const s = get_surface(surface);
1012 if (s->cnx->egl.eglBindTexImage) {
1013 return s->cnx->egl.eglBindTexImage(
1014 dp->disp[s->impl].dpy, s->surface, buffer);
1015 }
1016 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1017}
1018
1019EGLBoolean eglReleaseTexImage(
1020 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1021{
1022 clearError();
1023
1024 egl_display_t const * const dp = validate_display(dpy);
1025 if (!dp) return EGL_FALSE;
1026
Mathias Agopianf0480de2011-11-13 20:50:07 -08001027 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001028 if (!_s.get())
1029 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001030
Mathias Agopian518ec112011-05-13 16:21:08 -07001031 egl_surface_t const * const s = get_surface(surface);
1032 if (s->cnx->egl.eglReleaseTexImage) {
1033 return s->cnx->egl.eglReleaseTexImage(
1034 dp->disp[s->impl].dpy, s->surface, buffer);
1035 }
1036 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1037}
1038
1039EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1040{
1041 clearError();
1042
1043 egl_display_t const * const dp = validate_display(dpy);
1044 if (!dp) return EGL_FALSE;
1045
1046 EGLBoolean res = EGL_TRUE;
1047 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1048 egl_connection_t* const cnx = &gEGLImpl[i];
1049 if (cnx->dso) {
1050 if (cnx->egl.eglSwapInterval) {
1051 if (cnx->egl.eglSwapInterval(
1052 dp->disp[i].dpy, interval) == EGL_FALSE) {
1053 res = EGL_FALSE;
1054 }
1055 }
1056 }
1057 }
1058 return res;
1059}
1060
1061
1062// ----------------------------------------------------------------------------
1063// EGL 1.2
1064// ----------------------------------------------------------------------------
1065
1066EGLBoolean eglWaitClient(void)
1067{
1068 clearError();
1069
1070 // could be called before eglInitialize(), but we wouldn't have a context
1071 // then, and this function would return GL_TRUE, which isn't wrong.
1072 EGLBoolean res = EGL_TRUE;
1073 EGLContext ctx = getContext();
1074 if (ctx) {
1075 egl_context_t const * const c = get_context(ctx);
1076 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1077 if (uint32_t(c->impl)>=2)
1078 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1079 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1080 if (!cnx->dso)
1081 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1082 if (cnx->egl.eglWaitClient) {
1083 res = cnx->egl.eglWaitClient();
1084 } else {
1085 res = cnx->egl.eglWaitGL();
1086 }
1087 }
1088 return res;
1089}
1090
1091EGLBoolean eglBindAPI(EGLenum api)
1092{
1093 clearError();
1094
1095 if (egl_init_drivers() == EGL_FALSE) {
1096 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1097 }
1098
1099 // bind this API on all EGLs
1100 EGLBoolean res = EGL_TRUE;
1101 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1102 egl_connection_t* const cnx = &gEGLImpl[i];
1103 if (cnx->dso) {
1104 if (cnx->egl.eglBindAPI) {
1105 if (cnx->egl.eglBindAPI(api) == EGL_FALSE) {
1106 res = EGL_FALSE;
1107 }
1108 }
1109 }
1110 }
1111 return res;
1112}
1113
1114EGLenum eglQueryAPI(void)
1115{
1116 clearError();
1117
1118 if (egl_init_drivers() == EGL_FALSE) {
1119 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1120 }
1121
1122 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1123 egl_connection_t* const cnx = &gEGLImpl[i];
1124 if (cnx->dso) {
1125 if (cnx->egl.eglQueryAPI) {
1126 // the first one we find is okay, because they all
1127 // should be the same
1128 return cnx->egl.eglQueryAPI();
1129 }
1130 }
1131 }
1132 // or, it can only be OpenGL ES
1133 return EGL_OPENGL_ES_API;
1134}
1135
1136EGLBoolean eglReleaseThread(void)
1137{
1138 clearError();
1139
1140 // If there is context bound to the thread, release it
1141 loseCurrent(get_context(getContext()));
1142
1143 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1144 egl_connection_t* const cnx = &gEGLImpl[i];
1145 if (cnx->dso) {
1146 if (cnx->egl.eglReleaseThread) {
1147 cnx->egl.eglReleaseThread();
1148 }
1149 }
1150 }
1151 egl_tls_t::clearTLS();
1152 dbgReleaseThread();
1153 return EGL_TRUE;
1154}
1155
1156EGLSurface eglCreatePbufferFromClientBuffer(
1157 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1158 EGLConfig config, const EGLint *attrib_list)
1159{
1160 clearError();
1161
1162 egl_display_t const* dp = 0;
1163 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
1164 if (!cnx) return EGL_FALSE;
1165 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1166 return cnx->egl.eglCreatePbufferFromClientBuffer(
1167 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1168 buftype, buffer,
1169 dp->configs[intptr_t(config)].config, attrib_list);
1170 }
1171 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1172}
1173
1174// ----------------------------------------------------------------------------
1175// EGL_EGLEXT_VERSION 3
1176// ----------------------------------------------------------------------------
1177
1178EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1179 const EGLint *attrib_list)
1180{
1181 clearError();
1182
1183 egl_display_t const * const dp = validate_display(dpy);
1184 if (!dp) return EGL_FALSE;
1185
Mathias Agopianf0480de2011-11-13 20:50:07 -08001186 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001187 if (!_s.get())
1188 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001189
1190 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001191 if (s->cnx->egl.eglLockSurfaceKHR) {
1192 return s->cnx->egl.eglLockSurfaceKHR(
1193 dp->disp[s->impl].dpy, s->surface, attrib_list);
1194 }
1195 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1196}
1197
1198EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1199{
1200 clearError();
1201
1202 egl_display_t const * const dp = validate_display(dpy);
1203 if (!dp) return EGL_FALSE;
1204
Mathias Agopianf0480de2011-11-13 20:50:07 -08001205 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001206 if (!_s.get())
1207 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001208
1209 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001210 if (s->cnx->egl.eglUnlockSurfaceKHR) {
1211 return s->cnx->egl.eglUnlockSurfaceKHR(
1212 dp->disp[s->impl].dpy, s->surface);
1213 }
1214 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1215}
1216
1217EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1218 EGLClientBuffer buffer, const EGLint *attrib_list)
1219{
1220 clearError();
1221
1222 egl_display_t const * const dp = validate_display(dpy);
1223 if (!dp) return EGL_NO_IMAGE_KHR;
1224
1225 if (ctx != EGL_NO_CONTEXT) {
Mathias Agopianf0480de2011-11-13 20:50:07 -08001226 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001227 if (!_c.get())
1228 return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
Mathias Agopian518ec112011-05-13 16:21:08 -07001229 egl_context_t * const c = get_context(ctx);
1230 // since we have an EGLContext, we know which implementation to use
1231 EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
1232 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
1233 if (image == EGL_NO_IMAGE_KHR)
1234 return image;
1235
1236 egl_image_t* result = new egl_image_t(dpy, ctx);
1237 result->images[c->impl] = image;
1238 return (EGLImageKHR)result;
1239 } else {
1240 // EGL_NO_CONTEXT is a valid parameter
1241
1242 /* Since we don't have a way to know which implementation to call,
1243 * we're calling all of them. If at least one of the implementation
1244 * succeeded, this is a success.
1245 */
1246
1247 EGLint currentError = eglGetError();
1248
1249 EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS];
1250 bool success = false;
1251 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1252 egl_connection_t* const cnx = &gEGLImpl[i];
1253 implImages[i] = EGL_NO_IMAGE_KHR;
1254 if (cnx->dso) {
1255 if (cnx->egl.eglCreateImageKHR) {
1256 implImages[i] = cnx->egl.eglCreateImageKHR(
1257 dp->disp[i].dpy, ctx, target, buffer, attrib_list);
1258 if (implImages[i] != EGL_NO_IMAGE_KHR) {
1259 success = true;
1260 }
1261 }
1262 }
1263 }
1264
1265 if (!success) {
1266 // failure, if there was an error when we entered this function,
1267 // the error flag must not be updated.
1268 // Otherwise, the error is whatever happened in the implementation
1269 // that faulted.
1270 if (currentError != EGL_SUCCESS) {
1271 setError(currentError, EGL_NO_IMAGE_KHR);
1272 }
1273 return EGL_NO_IMAGE_KHR;
1274 } else {
1275 // In case of success, we need to clear all error flags
1276 // (especially those caused by the implementation that didn't
1277 // succeed). TODO: we could avoid this if we knew this was
1278 // a "full" success (all implementation succeeded).
1279 eglGetError();
1280 }
1281
1282 egl_image_t* result = new egl_image_t(dpy, ctx);
1283 memcpy(result->images, implImages, sizeof(implImages));
1284 return (EGLImageKHR)result;
1285 }
1286}
1287
1288EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1289{
1290 clearError();
1291
1292 egl_display_t const * const dp = validate_display(dpy);
1293 if (!dp) return EGL_FALSE;
1294
Mathias Agopianf0480de2011-11-13 20:50:07 -08001295 ImageRef _i(dp, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001296 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1297
1298 egl_image_t* image = get_image(img);
1299 bool success = false;
1300 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1301 egl_connection_t* const cnx = &gEGLImpl[i];
1302 if (image->images[i] != EGL_NO_IMAGE_KHR) {
1303 if (cnx->dso) {
1304 if (cnx->egl.eglDestroyImageKHR) {
1305 if (cnx->egl.eglDestroyImageKHR(
1306 dp->disp[i].dpy, image->images[i])) {
1307 success = true;
1308 }
1309 }
1310 }
1311 }
1312 }
1313 if (!success)
1314 return EGL_FALSE;
1315
1316 _i.terminate();
1317
1318 return EGL_TRUE;
1319}
1320
1321// ----------------------------------------------------------------------------
1322// EGL_EGLEXT_VERSION 5
1323// ----------------------------------------------------------------------------
1324
1325
1326EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1327{
1328 clearError();
1329
1330 egl_display_t const * const dp = validate_display(dpy);
1331 if (!dp) return EGL_NO_SYNC_KHR;
1332
1333 EGLContext ctx = eglGetCurrentContext();
Mathias Agopianf0480de2011-11-13 20:50:07 -08001334 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001335 if (!_c.get())
1336 return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR);
1337
Mathias Agopian518ec112011-05-13 16:21:08 -07001338 egl_context_t * const c = get_context(ctx);
1339 EGLSyncKHR result = EGL_NO_SYNC_KHR;
1340 if (c->cnx->egl.eglCreateSyncKHR) {
1341 EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR(
1342 dp->disp[c->impl].dpy, type, attrib_list);
1343 if (sync == EGL_NO_SYNC_KHR)
1344 return sync;
1345 result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync);
1346 }
1347 return (EGLSyncKHR)result;
1348}
1349
1350EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1351{
1352 clearError();
1353
1354 egl_display_t const * const dp = validate_display(dpy);
1355 if (!dp) return EGL_FALSE;
1356
Mathias Agopianf0480de2011-11-13 20:50:07 -08001357 SyncRef _s(dp, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001358 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1359 egl_sync_t* syncObject = get_sync(sync);
1360
1361 EGLContext ctx = syncObject->context;
Mathias Agopianf0480de2011-11-13 20:50:07 -08001362 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001363 if (!_c.get())
1364 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001365
1366 EGLBoolean result = EGL_FALSE;
1367 egl_context_t * const c = get_context(ctx);
1368 if (c->cnx->egl.eglDestroySyncKHR) {
1369 result = c->cnx->egl.eglDestroySyncKHR(
1370 dp->disp[c->impl].dpy, syncObject->sync);
1371 if (result)
1372 _s.terminate();
1373 }
1374 return result;
1375}
1376
1377EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
1378{
1379 clearError();
1380
1381 egl_display_t const * const dp = validate_display(dpy);
1382 if (!dp) return EGL_FALSE;
1383
Mathias Agopianf0480de2011-11-13 20:50:07 -08001384 SyncRef _s(dp, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001385 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1386 egl_sync_t* syncObject = get_sync(sync);
1387
1388 EGLContext ctx = syncObject->context;
Mathias Agopianf0480de2011-11-13 20:50:07 -08001389 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001390 if (!_c.get())
1391 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001392
1393 egl_context_t * const c = get_context(ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -07001394 if (c->cnx->egl.eglClientWaitSyncKHR) {
1395 return c->cnx->egl.eglClientWaitSyncKHR(
1396 dp->disp[c->impl].dpy, syncObject->sync, flags, timeout);
1397 }
1398
1399 return EGL_FALSE;
1400}
1401
1402EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
1403{
1404 clearError();
1405
1406 egl_display_t const * const dp = validate_display(dpy);
1407 if (!dp) return EGL_FALSE;
1408
Mathias Agopianf0480de2011-11-13 20:50:07 -08001409 SyncRef _s(dp, sync);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001410 if (!_s.get())
1411 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001412
Mathias Agopian5b287a62011-05-16 18:58:55 -07001413 egl_sync_t* syncObject = get_sync(sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001414 EGLContext ctx = syncObject->context;
Mathias Agopianf0480de2011-11-13 20:50:07 -08001415 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001416 if (!_c.get())
1417 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001418
1419 egl_context_t * const c = get_context(ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -07001420 if (c->cnx->egl.eglGetSyncAttribKHR) {
1421 return c->cnx->egl.eglGetSyncAttribKHR(
1422 dp->disp[c->impl].dpy, syncObject->sync, attribute, value);
1423 }
1424
1425 return EGL_FALSE;
1426}
1427
1428// ----------------------------------------------------------------------------
1429// ANDROID extensions
1430// ----------------------------------------------------------------------------
1431
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001432/* ANDROID extensions entry-point go here */
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001433
1434// ----------------------------------------------------------------------------
1435// NVIDIA extensions
1436// ----------------------------------------------------------------------------
1437EGLuint64NV eglGetSystemTimeFrequencyNV()
1438{
1439 clearError();
1440
1441 if (egl_init_drivers() == EGL_FALSE) {
1442 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1443 }
1444
1445 EGLuint64NV ret = 0;
1446 egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE];
1447
1448 if (cnx->dso) {
1449 if (cnx->egl.eglGetSystemTimeFrequencyNV) {
1450 return cnx->egl.eglGetSystemTimeFrequencyNV();
1451 }
1452 }
1453
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001454 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001455}
1456
1457EGLuint64NV eglGetSystemTimeNV()
1458{
1459 clearError();
1460
1461 if (egl_init_drivers() == EGL_FALSE) {
1462 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1463 }
1464
1465 EGLuint64NV ret = 0;
1466 egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE];
1467
1468 if (cnx->dso) {
1469 if (cnx->egl.eglGetSystemTimeNV) {
1470 return cnx->egl.eglGetSystemTimeNV();
1471 }
1472 }
1473
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001474 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001475}