blob: 1dbba3f9d4a49c30e6d0490059888be308c95a2c [file] [log] [blame]
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001/*
2 ** Copyright 2007, The Android Open Source Project
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 ** http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16
17#include <ctype.h>
18#include <stdlib.h>
19#include <string.h>
20
21#include <hardware/gralloc.h>
22#include <system/window.h>
23
24#include <EGL/egl.h>
25#include <EGL/eglext.h>
26#include <GLES/gl.h>
27#include <GLES/glext.h>
28
29#include <cutils/log.h>
30#include <cutils/atomic.h>
31#include <cutils/properties.h>
32#include <cutils/memory.h>
33
34#include <utils/KeyedVector.h>
35#include <utils/SortedVector.h>
36#include <utils/String8.h>
37
38#include "egl_impl.h"
39#include "egl_tls.h"
Siva Velusamydb974682011-11-30 15:05:37 -080040#include "glestrace.h"
Mathias Agopian7adf4ef2011-05-13 16:21:08 -070041#include "hooks.h"
42
43#include "egl_display.h"
44#include "egl_impl.h"
45#include "egl_object.h"
46#include "egl_tls.h"
47
48using namespace android;
49
50// ----------------------------------------------------------------------------
51
Mathias Agopiancadd3252011-11-29 17:55:46 -080052#define EGL_VERSION_HW_ANDROID 0x3143
53
Mathias Agopian7adf4ef2011-05-13 16:21:08 -070054struct extention_map_t {
55 const char* name;
56 __eglMustCastToProperFunctionPointerType address;
57};
58
59static const extention_map_t sExtentionMap[] = {
60 { "eglLockSurfaceKHR",
61 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
62 { "eglUnlockSurfaceKHR",
63 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
64 { "eglCreateImageKHR",
65 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
66 { "eglDestroyImageKHR",
67 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Jonas Yang1b1d73f2011-08-26 20:04:39 +080068 { "eglGetSystemTimeFrequencyNV",
69 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
70 { "eglGetSystemTimeNV",
71 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
Mathias Agopian7adf4ef2011-05-13 16:21:08 -070072};
73
74// accesses protected by sExtensionMapMutex
75static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
76static int sGLExtentionSlot = 0;
77static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
78
79static void(*findProcAddress(const char* name,
80 const extention_map_t* map, size_t n))() {
81 for (uint32_t i=0 ; i<n ; i++) {
82 if (!strcmp(name, map[i].name)) {
83 return map[i].address;
84 }
85 }
86 return NULL;
87}
88
89// ----------------------------------------------------------------------------
90
91template<typename T>
92static __attribute__((noinline))
93int binarySearch(T const sortedArray[], int first, int last, T key) {
94 while (first <= last) {
95 int mid = (first + last) / 2;
96 if (sortedArray[mid] < key) {
97 first = mid + 1;
98 } else if (key < sortedArray[mid]) {
99 last = mid - 1;
100 } else {
101 return mid;
102 }
103 }
104 return -1;
105}
106
107// ----------------------------------------------------------------------------
108
109namespace android {
110extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
111extern EGLBoolean egl_init_drivers();
112extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
113extern int gEGLDebugLevel;
114extern gl_hooks_t gHooksTrace;
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700115} // namespace android;
116
117// ----------------------------------------------------------------------------
118
119static inline void clearError() { egl_tls_t::clearError(); }
120static inline EGLContext getContext() { return egl_tls_t::getContext(); }
121
122// ----------------------------------------------------------------------------
123
124EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
125{
126 clearError();
127
128 uint32_t index = uint32_t(display);
129 if (index >= NUM_DISPLAYS) {
130 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
131 }
132
133 if (egl_init_drivers() == EGL_FALSE) {
134 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
135 }
136
137 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
138 return dpy;
139}
140
141// ----------------------------------------------------------------------------
142// Initialization
143// ----------------------------------------------------------------------------
144
145EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
146{
147 clearError();
148
149 egl_display_t * const dp = get_display(dpy);
150 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
151
152 EGLBoolean res = dp->initialize(major, minor);
153
154 return res;
155}
156
157EGLBoolean eglTerminate(EGLDisplay dpy)
158{
159 // NOTE: don't unload the drivers b/c some APIs can be called
160 // after eglTerminate() has been called. eglTerminate() only
161 // terminates an EGLDisplay, not a EGL itself.
162
163 clearError();
164
165 egl_display_t* const dp = get_display(dpy);
166 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
167
168 EGLBoolean res = dp->terminate();
169
170 return res;
171}
172
173// ----------------------------------------------------------------------------
174// configuration
175// ----------------------------------------------------------------------------
176
177EGLBoolean eglGetConfigs( EGLDisplay dpy,
178 EGLConfig *configs,
179 EGLint config_size, EGLint *num_config)
180{
181 clearError();
182
183 egl_display_t const * const dp = validate_display(dpy);
184 if (!dp) return EGL_FALSE;
185
186 GLint numConfigs = dp->numTotalConfigs;
187 if (!configs) {
188 *num_config = numConfigs;
189 return EGL_TRUE;
190 }
191
192 GLint n = 0;
193 for (intptr_t i=0 ; i<dp->numTotalConfigs && config_size ; i++) {
194 *configs++ = EGLConfig(i);
195 config_size--;
196 n++;
197 }
198
199 *num_config = n;
200 return EGL_TRUE;
201}
202
203EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
204 EGLConfig *configs, EGLint config_size,
205 EGLint *num_config)
206{
207 clearError();
208
209 egl_display_t const * const dp = validate_display(dpy);
210 if (!dp) return EGL_FALSE;
211
212 if (num_config==0) {
213 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
214 }
215
216 EGLint n;
217 EGLBoolean res = EGL_FALSE;
218 *num_config = 0;
219
220
221 // It is unfortunate, but we need to remap the EGL_CONFIG_IDs,
222 // to do this, we have to go through the attrib_list array once
223 // to figure out both its size and if it contains an EGL_CONFIG_ID
224 // key. If so, the full array is copied and patched.
225 // NOTE: we assume that there can be only one occurrence
226 // of EGL_CONFIG_ID.
227
228 EGLint patch_index = -1;
229 GLint attr;
230 size_t size = 0;
231 if (attrib_list) {
232 while ((attr=attrib_list[size]) != EGL_NONE) {
233 if (attr == EGL_CONFIG_ID)
234 patch_index = size;
235 size += 2;
236 }
237 }
238 if (patch_index >= 0) {
239 size += 2; // we need copy the sentinel as well
240 EGLint* new_list = (EGLint*)malloc(size*sizeof(EGLint));
241 if (new_list == 0)
242 return setError(EGL_BAD_ALLOC, EGL_FALSE);
243 memcpy(new_list, attrib_list, size*sizeof(EGLint));
244
245 // patch the requested EGL_CONFIG_ID
246 bool found = false;
247 EGLConfig ourConfig(0);
248 EGLint& configId(new_list[patch_index+1]);
249 for (intptr_t i=0 ; i<dp->numTotalConfigs ; i++) {
250 if (dp->configs[i].configId == configId) {
251 ourConfig = EGLConfig(i);
252 configId = dp->configs[i].implConfigId;
253 found = true;
254 break;
255 }
256 }
257
258 egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(ourConfig)].impl];
259 if (found && cnx->dso) {
260 // and switch to the new list
261 attrib_list = const_cast<const EGLint *>(new_list);
262
263 // At this point, the only configuration that can match is
264 // dp->configs[i][index], however, we don't know if it would be
265 // rejected because of the other attributes, so we do have to call
266 // cnx->egl.eglChooseConfig() -- but we don't have to loop
267 // through all the EGLimpl[].
268 // We also know we can only get a single config back, and we know
269 // which one.
270
271 res = cnx->egl.eglChooseConfig(
272 dp->disp[ dp->configs[intptr_t(ourConfig)].impl ].dpy,
273 attrib_list, configs, config_size, &n);
274 if (res && n>0) {
275 // n has to be 0 or 1, by construction, and we already know
276 // which config it will return (since there can be only one).
277 if (configs) {
278 configs[0] = ourConfig;
279 }
280 *num_config = 1;
281 }
282 }
283
284 free(const_cast<EGLint *>(attrib_list));
285 return res;
286 }
287
288
289 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
290 egl_connection_t* const cnx = &gEGLImpl[i];
291 if (cnx->dso) {
292 if (cnx->egl.eglChooseConfig(
293 dp->disp[i].dpy, attrib_list, configs, config_size, &n)) {
294 if (configs) {
295 // now we need to convert these client EGLConfig to our
296 // internal EGLConfig format.
297 // This is done in O(n Log(n)) time.
298 for (int j=0 ; j<n ; j++) {
299 egl_config_t key(i, configs[j]);
300 intptr_t index = binarySearch<egl_config_t>(
301 dp->configs, 0, dp->numTotalConfigs, key);
302 if (index >= 0) {
303 configs[j] = EGLConfig(index);
304 } else {
305 return setError(EGL_BAD_CONFIG, EGL_FALSE);
306 }
307 }
308 configs += n;
309 config_size -= n;
310 }
311 *num_config += n;
312 res = EGL_TRUE;
313 }
314 }
315 }
316 return res;
317}
318
319EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
320 EGLint attribute, EGLint *value)
321{
322 clearError();
323
324 egl_display_t const* dp = 0;
325 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
326 if (!cnx) return EGL_FALSE;
327
328 if (attribute == EGL_CONFIG_ID) {
329 *value = dp->configs[intptr_t(config)].configId;
330 return EGL_TRUE;
331 }
332 return cnx->egl.eglGetConfigAttrib(
333 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
334 dp->configs[intptr_t(config)].config, attribute, value);
335}
336
337// ----------------------------------------------------------------------------
338// surfaces
339// ----------------------------------------------------------------------------
340
341EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
342 NativeWindowType window,
343 const EGLint *attrib_list)
344{
345 clearError();
346
347 egl_display_t const* dp = 0;
348 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
349 if (cnx) {
350 EGLDisplay iDpy = dp->disp[ dp->configs[intptr_t(config)].impl ].dpy;
351 EGLConfig iConfig = dp->configs[intptr_t(config)].config;
352 EGLint format;
353
Mathias Agopian982d2da2011-07-29 17:55:48 -0700354 if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) {
355 LOGE("EGLNativeWindowType %p already connected to another API",
356 window);
357 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
358 }
359
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700360 // set the native window's buffers format to match this config
361 if (cnx->egl.eglGetConfigAttrib(iDpy,
362 iConfig, EGL_NATIVE_VISUAL_ID, &format)) {
363 if (format != 0) {
Jamie Gennis97eae022011-07-01 13:12:07 -0700364 int err = native_window_set_buffers_format(window, format);
365 if (err != 0) {
366 LOGE("error setting native window pixel format: %s (%d)",
367 strerror(-err), err);
Mathias Agopian982d2da2011-07-29 17:55:48 -0700368 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Jamie Gennis97eae022011-07-01 13:12:07 -0700369 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
370 }
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700371 }
372 }
373
Jamie Gennis87f32652011-11-19 18:04:43 -0800374 // the EGL spec requires that a new EGLSurface default to swap interval
375 // 1, so explicitly set that on the window here.
376 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
377 anw->setSwapInterval(anw, 1);
378
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700379 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
380 iDpy, iConfig, window, attrib_list);
381 if (surface != EGL_NO_SURFACE) {
382 egl_surface_t* s = new egl_surface_t(dpy, config, window, surface,
383 dp->configs[intptr_t(config)].impl, cnx);
384 return s;
385 }
Mathias Agopian982d2da2011-07-29 17:55:48 -0700386
387 // EGLSurface creation failed
388 native_window_set_buffers_format(window, 0);
389 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700390 }
391 return EGL_NO_SURFACE;
392}
393
394EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
395 NativePixmapType pixmap,
396 const EGLint *attrib_list)
397{
398 clearError();
399
400 egl_display_t const* dp = 0;
401 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
402 if (cnx) {
403 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
404 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
405 dp->configs[intptr_t(config)].config, pixmap, attrib_list);
406 if (surface != EGL_NO_SURFACE) {
407 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
408 dp->configs[intptr_t(config)].impl, cnx);
409 return s;
410 }
411 }
412 return EGL_NO_SURFACE;
413}
414
415EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
416 const EGLint *attrib_list)
417{
418 clearError();
419
420 egl_display_t const* dp = 0;
421 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
422 if (cnx) {
423 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
424 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
425 dp->configs[intptr_t(config)].config, attrib_list);
426 if (surface != EGL_NO_SURFACE) {
427 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
428 dp->configs[intptr_t(config)].impl, cnx);
429 return s;
430 }
431 }
432 return EGL_NO_SURFACE;
433}
434
435EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
436{
437 clearError();
438
439 egl_display_t const * const dp = validate_display(dpy);
440 if (!dp) return EGL_FALSE;
441
Mathias Agopian274e03c2011-11-13 20:50:07 -0800442 SurfaceRef _s(dp, surface);
Mathias Agopianf1e4e062011-05-16 18:58:55 -0700443 if (!_s.get())
444 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700445
446 egl_surface_t * const s = get_surface(surface);
447 EGLBoolean result = s->cnx->egl.eglDestroySurface(
448 dp->disp[s->impl].dpy, s->surface);
449 if (result == EGL_TRUE) {
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700450 _s.terminate();
451 }
452 return result;
453}
454
455EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
456 EGLint attribute, EGLint *value)
457{
458 clearError();
459
460 egl_display_t const * const dp = validate_display(dpy);
461 if (!dp) return EGL_FALSE;
462
Mathias Agopian274e03c2011-11-13 20:50:07 -0800463 SurfaceRef _s(dp, surface);
Mathias Agopianf1e4e062011-05-16 18:58:55 -0700464 if (!_s.get())
465 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700466
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700467 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700468 EGLBoolean result(EGL_TRUE);
469 if (attribute == EGL_CONFIG_ID) {
470 // We need to remap EGL_CONFIG_IDs
471 *value = dp->configs[intptr_t(s->config)].configId;
472 } else {
473 result = s->cnx->egl.eglQuerySurface(
474 dp->disp[s->impl].dpy, s->surface, attribute, value);
475 }
476
477 return result;
478}
479
480// ----------------------------------------------------------------------------
481// Contexts
482// ----------------------------------------------------------------------------
483
484EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
485 EGLContext share_list, const EGLint *attrib_list)
486{
487 clearError();
488
489 egl_display_t const* dp = 0;
490 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
491 if (cnx) {
492 if (share_list != EGL_NO_CONTEXT) {
493 egl_context_t* const c = get_context(share_list);
494 share_list = c->context;
495 }
496 EGLContext context = cnx->egl.eglCreateContext(
497 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
498 dp->configs[intptr_t(config)].config,
499 share_list, attrib_list);
500 if (context != EGL_NO_CONTEXT) {
501 // figure out if it's a GLESv1 or GLESv2
502 int version = 0;
503 if (attrib_list) {
504 while (*attrib_list != EGL_NONE) {
505 GLint attr = *attrib_list++;
506 GLint value = *attrib_list++;
507 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
508 if (value == 1) {
509 version = GLESv1_INDEX;
510 } else if (value == 2) {
511 version = GLESv2_INDEX;
512 }
513 }
514 };
515 }
516 egl_context_t* c = new egl_context_t(dpy, context, config,
517 dp->configs[intptr_t(config)].impl, cnx, version);
Siva Velusamydb974682011-11-30 15:05:37 -0800518#if EGL_TRACE
519 if (gEGLDebugLevel > 0)
520 GLTrace_eglCreateContext(version, c);
521#endif
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700522 return c;
523 }
524 }
525 return EGL_NO_CONTEXT;
526}
527
528EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
529{
530 clearError();
531
532 egl_display_t const * const dp = validate_display(dpy);
Mathias Agopianf1e4e062011-05-16 18:58:55 -0700533 if (!dp)
534 return EGL_FALSE;
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700535
Mathias Agopian274e03c2011-11-13 20:50:07 -0800536 ContextRef _c(dp, ctx);
Mathias Agopianf1e4e062011-05-16 18:58:55 -0700537 if (!_c.get())
538 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700539
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700540 egl_context_t * const c = get_context(ctx);
541 EGLBoolean result = c->cnx->egl.eglDestroyContext(
542 dp->disp[c->impl].dpy, c->context);
543 if (result == EGL_TRUE) {
544 _c.terminate();
545 }
546 return result;
547}
548
549static void loseCurrent(egl_context_t * cur_c)
550{
551 if (cur_c) {
552 egl_surface_t * cur_r = get_surface(cur_c->read);
553 egl_surface_t * cur_d = get_surface(cur_c->draw);
554
555 // by construction, these are either 0 or valid (possibly terminated)
556 // it should be impossible for these to be invalid
557 ContextRef _cur_c(cur_c);
558 SurfaceRef _cur_r(cur_r);
559 SurfaceRef _cur_d(cur_d);
560
561 cur_c->read = NULL;
562 cur_c->draw = NULL;
563
564 _cur_c.release();
565 _cur_r.release();
566 _cur_d.release();
567 }
568}
569
570EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
571 EGLSurface read, EGLContext ctx)
572{
573 clearError();
574
575 egl_display_t const * const dp = get_display(dpy);
576 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
577
Mathias Agopianf1e4e062011-05-16 18:58:55 -0700578 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
579 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
580 // a valid but uninitialized display.
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700581 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
582 (draw != EGL_NO_SURFACE) ) {
583 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
584 }
585
586 // get a reference to the object passed in
Mathias Agopian274e03c2011-11-13 20:50:07 -0800587 ContextRef _c(dp, ctx);
588 SurfaceRef _d(dp, draw);
589 SurfaceRef _r(dp, read);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700590
591 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopianf1e4e062011-05-16 18:58:55 -0700592 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700593 // EGL_NO_CONTEXT is valid
594 return EGL_FALSE;
595 }
596
597 // these are the underlying implementation's object
598 EGLContext impl_ctx = EGL_NO_CONTEXT;
599 EGLSurface impl_draw = EGL_NO_SURFACE;
600 EGLSurface impl_read = EGL_NO_SURFACE;
601
602 // these are our objects structs passed in
603 egl_context_t * c = NULL;
604 egl_surface_t const * d = NULL;
605 egl_surface_t const * r = NULL;
606
607 // these are the current objects structs
608 egl_context_t * cur_c = get_context(getContext());
609
610 if (ctx != EGL_NO_CONTEXT) {
611 c = get_context(ctx);
612 impl_ctx = c->context;
613 } else {
614 // no context given, use the implementation of the current context
615 if (cur_c == NULL) {
616 // no current context
617 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
618 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
619 return setError(EGL_BAD_MATCH, EGL_FALSE);
620 }
621 // not an error, there is just no current context.
622 return EGL_TRUE;
623 }
624 }
625
626 // retrieve the underlying implementation's draw EGLSurface
627 if (draw != EGL_NO_SURFACE) {
628 d = get_surface(draw);
629 // make sure the EGLContext and EGLSurface passed in are for
630 // the same driver
631 if (c && d->impl != c->impl)
632 return setError(EGL_BAD_MATCH, EGL_FALSE);
633 impl_draw = d->surface;
634 }
635
636 // retrieve the underlying implementation's read EGLSurface
637 if (read != EGL_NO_SURFACE) {
638 r = get_surface(read);
639 // make sure the EGLContext and EGLSurface passed in are for
640 // the same driver
641 if (c && r->impl != c->impl)
642 return setError(EGL_BAD_MATCH, EGL_FALSE);
643 impl_read = r->surface;
644 }
645
646 EGLBoolean result;
647
648 if (c) {
649 result = c->cnx->egl.eglMakeCurrent(
650 dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
651 } else {
652 result = cur_c->cnx->egl.eglMakeCurrent(
653 dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
654 }
655
656 if (result == EGL_TRUE) {
657
658 loseCurrent(cur_c);
659
660 if (ctx != EGL_NO_CONTEXT) {
661 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
662 egl_tls_t::setContext(ctx);
Siva Velusamydb974682011-11-30 15:05:37 -0800663#if EGL_TRACE
664 if (gEGLDebugLevel > 0)
665 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version]);
666#endif
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700667 _c.acquire();
668 _r.acquire();
669 _d.acquire();
670 c->read = read;
671 c->draw = draw;
672 } else {
673 setGLHooksThreadSpecific(&gHooksNoContext);
674 egl_tls_t::setContext(EGL_NO_CONTEXT);
675 }
Mathias Agopianca07e342011-08-25 18:38:24 -0700676 } else {
677 // this will LOGE the error
678 result = setError(c->cnx->egl.eglGetError(), EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700679 }
680 return result;
681}
682
683
684EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
685 EGLint attribute, EGLint *value)
686{
687 clearError();
688
689 egl_display_t const * const dp = validate_display(dpy);
690 if (!dp) return EGL_FALSE;
691
Mathias Agopian274e03c2011-11-13 20:50:07 -0800692 ContextRef _c(dp, ctx);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700693 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
694
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700695 egl_context_t * const c = get_context(ctx);
696
697 EGLBoolean result(EGL_TRUE);
698 if (attribute == EGL_CONFIG_ID) {
699 *value = dp->configs[intptr_t(c->config)].configId;
700 } else {
701 // We need to remap EGL_CONFIG_IDs
702 result = c->cnx->egl.eglQueryContext(
703 dp->disp[c->impl].dpy, c->context, attribute, value);
704 }
705
706 return result;
707}
708
709EGLContext eglGetCurrentContext(void)
710{
711 // could be called before eglInitialize(), but we wouldn't have a context
712 // then, and this function would correctly return EGL_NO_CONTEXT.
713
714 clearError();
715
716 EGLContext ctx = getContext();
717 return ctx;
718}
719
720EGLSurface eglGetCurrentSurface(EGLint readdraw)
721{
722 // could be called before eglInitialize(), but we wouldn't have a context
723 // then, and this function would correctly return EGL_NO_SURFACE.
724
725 clearError();
726
727 EGLContext ctx = getContext();
728 if (ctx) {
729 egl_context_t const * const c = get_context(ctx);
730 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
731 switch (readdraw) {
732 case EGL_READ: return c->read;
733 case EGL_DRAW: return c->draw;
734 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
735 }
736 }
737 return EGL_NO_SURFACE;
738}
739
740EGLDisplay eglGetCurrentDisplay(void)
741{
742 // could be called before eglInitialize(), but we wouldn't have a context
743 // then, and this function would correctly return EGL_NO_DISPLAY.
744
745 clearError();
746
747 EGLContext ctx = getContext();
748 if (ctx) {
749 egl_context_t const * const c = get_context(ctx);
750 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
751 return c->dpy;
752 }
753 return EGL_NO_DISPLAY;
754}
755
756EGLBoolean eglWaitGL(void)
757{
758 // could be called before eglInitialize(), but we wouldn't have a context
759 // then, and this function would return GL_TRUE, which isn't wrong.
760
761 clearError();
762
763 EGLBoolean res = EGL_TRUE;
764 EGLContext ctx = getContext();
765 if (ctx) {
766 egl_context_t const * const c = get_context(ctx);
767 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
768 if (uint32_t(c->impl)>=2)
769 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
770 egl_connection_t* const cnx = &gEGLImpl[c->impl];
771 if (!cnx->dso)
772 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
773 res = cnx->egl.eglWaitGL();
774 }
775 return res;
776}
777
778EGLBoolean eglWaitNative(EGLint engine)
779{
780 // could be called before eglInitialize(), but we wouldn't have a context
781 // then, and this function would return GL_TRUE, which isn't wrong.
782
783 clearError();
784
785 EGLBoolean res = EGL_TRUE;
786 EGLContext ctx = getContext();
787 if (ctx) {
788 egl_context_t const * const c = get_context(ctx);
789 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
790 if (uint32_t(c->impl)>=2)
791 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
792 egl_connection_t* const cnx = &gEGLImpl[c->impl];
793 if (!cnx->dso)
794 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
795 res = cnx->egl.eglWaitNative(engine);
796 }
797 return res;
798}
799
800EGLint eglGetError(void)
801{
802 EGLint result = EGL_SUCCESS;
803 EGLint err;
804 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
805 err = EGL_SUCCESS;
806 egl_connection_t* const cnx = &gEGLImpl[i];
807 if (cnx->dso)
808 err = cnx->egl.eglGetError();
809 if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
810 result = err;
811 }
812 err = egl_tls_t::getError();
813 if (result == EGL_SUCCESS)
814 result = err;
815 return result;
816}
817
818// Note: Similar implementations of these functions also exist in
819// gl2.cpp and gl.cpp, and are used by applications that call the
820// exported entry points directly.
821typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
822typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
823
824static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL;
825static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL;
826
827static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image)
828{
829 GLeglImageOES implImage =
830 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
831 glEGLImageTargetTexture2DOES_impl(target, implImage);
832}
833
834static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image)
835{
836 GLeglImageOES implImage =
837 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
838 glEGLImageTargetRenderbufferStorageOES_impl(target, implImage);
839}
840
841__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
842{
843 // eglGetProcAddress() could be the very first function called
844 // in which case we must make sure we've initialized ourselves, this
845 // happens the first time egl_get_display() is called.
846
847 clearError();
848
849 if (egl_init_drivers() == EGL_FALSE) {
850 setError(EGL_BAD_PARAMETER, NULL);
851 return NULL;
852 }
853
Jamie Gennis0dc908c2011-11-03 17:42:43 -0700854 // The EGL_ANDROID_blob_cache extension should not be exposed to
855 // applications. It is used internally by the Android EGL layer.
Jamie Gennisb7928462011-11-09 15:35:34 -0800856 if (!strcmp(procname, "eglSetBlobCacheFuncsANDROID")) {
Jamie Gennis0dc908c2011-11-03 17:42:43 -0700857 return NULL;
858 }
859
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700860 __eglMustCastToProperFunctionPointerType addr;
861 addr = findProcAddress(procname, sExtentionMap, NELEM(sExtentionMap));
862 if (addr) return addr;
863
Jamie Gennis0dc908c2011-11-03 17:42:43 -0700864
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700865 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
866 pthread_mutex_lock(&sExtensionMapMutex);
867
868 /*
869 * Since eglGetProcAddress() is not associated to anything, it needs
870 * to return a function pointer that "works" regardless of what
871 * the current context is.
872 *
873 * For this reason, we return a "forwarder", a small stub that takes
874 * care of calling the function associated with the context
875 * currently bound.
876 *
877 * We first look for extensions we've already resolved, if we're seeing
878 * this extension for the first time, we go through all our
879 * implementations and call eglGetProcAddress() and record the
880 * result in the appropriate implementation hooks and return the
881 * address of the forwarder corresponding to that hook set.
882 *
883 */
884
885 const String8 name(procname);
886 addr = sGLExtentionMap.valueFor(name);
887 const int slot = sGLExtentionSlot;
888
889 LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
890 "no more slots for eglGetProcAddress(\"%s\")",
891 procname);
892
Siva Velusamydb974682011-11-30 15:05:37 -0800893#if EGL_TRACE
894 gl_hooks_t *debugHooks = GLTrace_getGLHooks();
895#endif
896
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700897 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
898 bool found = false;
899 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
900 egl_connection_t* const cnx = &gEGLImpl[i];
901 if (cnx->dso && cnx->egl.eglGetProcAddress) {
902 found = true;
903 // Extensions are independent of the bound context
904 cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
905 cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
906#if EGL_TRACE
Siva Velusamydb974682011-11-30 15:05:37 -0800907 debugHooks->ext.extensions[slot] = gHooksTrace.ext.extensions[slot] =
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700908#endif
909 cnx->egl.eglGetProcAddress(procname);
910 }
911 }
912 if (found) {
913 addr = gExtensionForwarders[slot];
914
915 if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) {
916 glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr;
917 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper;
918 }
919 if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) {
920 glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr;
921 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper;
922 }
923
924 sGLExtentionMap.add(name, addr);
925 sGLExtentionSlot++;
926 }
927 }
928
929 pthread_mutex_unlock(&sExtensionMapMutex);
930 return addr;
931}
932
933EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
934{
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700935 clearError();
936
937 egl_display_t const * const dp = validate_display(dpy);
938 if (!dp) return EGL_FALSE;
939
Mathias Agopian274e03c2011-11-13 20:50:07 -0800940 SurfaceRef _s(dp, draw);
Mathias Agopianf1e4e062011-05-16 18:58:55 -0700941 if (!_s.get())
942 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700943
Siva Velusamydb974682011-11-30 15:05:37 -0800944#if EGL_TRACE
945 if (gEGLDebugLevel > 0)
946 GLTrace_eglSwapBuffers(dpy, draw);
947#endif
948
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700949 egl_surface_t const * const s = get_surface(draw);
950 return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
951}
952
953EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
954 NativePixmapType target)
955{
956 clearError();
957
958 egl_display_t const * const dp = validate_display(dpy);
959 if (!dp) return EGL_FALSE;
960
Mathias Agopian274e03c2011-11-13 20:50:07 -0800961 SurfaceRef _s(dp, surface);
Mathias Agopianf1e4e062011-05-16 18:58:55 -0700962 if (!_s.get())
963 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700964
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700965 egl_surface_t const * const s = get_surface(surface);
966 return s->cnx->egl.eglCopyBuffers(
967 dp->disp[s->impl].dpy, s->surface, target);
968}
969
970const char* eglQueryString(EGLDisplay dpy, EGLint name)
971{
972 clearError();
973
974 egl_display_t const * const dp = validate_display(dpy);
975 if (!dp) return (const char *) NULL;
976
977 switch (name) {
978 case EGL_VENDOR:
Mathias Agopiane88740e2011-11-13 23:52:47 -0800979 return dp->getVendorString();
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700980 case EGL_VERSION:
Mathias Agopiane88740e2011-11-13 23:52:47 -0800981 return dp->getVersionString();
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700982 case EGL_EXTENSIONS:
Mathias Agopiane88740e2011-11-13 23:52:47 -0800983 return dp->getExtensionString();
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700984 case EGL_CLIENT_APIS:
Mathias Agopiane88740e2011-11-13 23:52:47 -0800985 return dp->getClientApiString();
Mathias Agopiancadd3252011-11-29 17:55:46 -0800986 case EGL_VERSION_HW_ANDROID: {
987 if (gEGLImpl[IMPL_HARDWARE].dso) {
988 return dp->disp[IMPL_HARDWARE].queryString.version;
989 }
990 return dp->disp[IMPL_SOFTWARE].queryString.version;
991 }
Mathias Agopian7adf4ef2011-05-13 16:21:08 -0700992 }
993 return setError(EGL_BAD_PARAMETER, (const char *)0);
994}
995
996
997// ----------------------------------------------------------------------------
998// EGL 1.1
999// ----------------------------------------------------------------------------
1000
1001EGLBoolean eglSurfaceAttrib(
1002 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1003{
1004 clearError();
1005
1006 egl_display_t const * const dp = validate_display(dpy);
1007 if (!dp) return EGL_FALSE;
1008
Mathias Agopian274e03c2011-11-13 20:50:07 -08001009 SurfaceRef _s(dp, surface);
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001010 if (!_s.get())
1011 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001012
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001013 egl_surface_t const * const s = get_surface(surface);
1014 if (s->cnx->egl.eglSurfaceAttrib) {
1015 return s->cnx->egl.eglSurfaceAttrib(
1016 dp->disp[s->impl].dpy, s->surface, attribute, value);
1017 }
1018 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1019}
1020
1021EGLBoolean eglBindTexImage(
1022 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1023{
1024 clearError();
1025
1026 egl_display_t const * const dp = validate_display(dpy);
1027 if (!dp) return EGL_FALSE;
1028
Mathias Agopian274e03c2011-11-13 20:50:07 -08001029 SurfaceRef _s(dp, surface);
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001030 if (!_s.get())
1031 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001032
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001033 egl_surface_t const * const s = get_surface(surface);
1034 if (s->cnx->egl.eglBindTexImage) {
1035 return s->cnx->egl.eglBindTexImage(
1036 dp->disp[s->impl].dpy, s->surface, buffer);
1037 }
1038 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1039}
1040
1041EGLBoolean eglReleaseTexImage(
1042 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1043{
1044 clearError();
1045
1046 egl_display_t const * const dp = validate_display(dpy);
1047 if (!dp) return EGL_FALSE;
1048
Mathias Agopian274e03c2011-11-13 20:50:07 -08001049 SurfaceRef _s(dp, surface);
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001050 if (!_s.get())
1051 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001052
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001053 egl_surface_t const * const s = get_surface(surface);
1054 if (s->cnx->egl.eglReleaseTexImage) {
1055 return s->cnx->egl.eglReleaseTexImage(
1056 dp->disp[s->impl].dpy, s->surface, buffer);
1057 }
1058 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1059}
1060
1061EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1062{
1063 clearError();
1064
1065 egl_display_t const * const dp = validate_display(dpy);
1066 if (!dp) return EGL_FALSE;
1067
1068 EGLBoolean res = EGL_TRUE;
1069 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1070 egl_connection_t* const cnx = &gEGLImpl[i];
1071 if (cnx->dso) {
1072 if (cnx->egl.eglSwapInterval) {
1073 if (cnx->egl.eglSwapInterval(
1074 dp->disp[i].dpy, interval) == EGL_FALSE) {
1075 res = EGL_FALSE;
1076 }
1077 }
1078 }
1079 }
1080 return res;
1081}
1082
1083
1084// ----------------------------------------------------------------------------
1085// EGL 1.2
1086// ----------------------------------------------------------------------------
1087
1088EGLBoolean eglWaitClient(void)
1089{
1090 clearError();
1091
1092 // could be called before eglInitialize(), but we wouldn't have a context
1093 // then, and this function would return GL_TRUE, which isn't wrong.
1094 EGLBoolean res = EGL_TRUE;
1095 EGLContext ctx = getContext();
1096 if (ctx) {
1097 egl_context_t const * const c = get_context(ctx);
1098 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1099 if (uint32_t(c->impl)>=2)
1100 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1101 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1102 if (!cnx->dso)
1103 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1104 if (cnx->egl.eglWaitClient) {
1105 res = cnx->egl.eglWaitClient();
1106 } else {
1107 res = cnx->egl.eglWaitGL();
1108 }
1109 }
1110 return res;
1111}
1112
1113EGLBoolean eglBindAPI(EGLenum api)
1114{
1115 clearError();
1116
1117 if (egl_init_drivers() == EGL_FALSE) {
1118 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1119 }
1120
1121 // bind this API on all EGLs
1122 EGLBoolean res = EGL_TRUE;
1123 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1124 egl_connection_t* const cnx = &gEGLImpl[i];
1125 if (cnx->dso) {
1126 if (cnx->egl.eglBindAPI) {
1127 if (cnx->egl.eglBindAPI(api) == EGL_FALSE) {
1128 res = EGL_FALSE;
1129 }
1130 }
1131 }
1132 }
1133 return res;
1134}
1135
1136EGLenum eglQueryAPI(void)
1137{
1138 clearError();
1139
1140 if (egl_init_drivers() == EGL_FALSE) {
1141 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1142 }
1143
1144 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1145 egl_connection_t* const cnx = &gEGLImpl[i];
1146 if (cnx->dso) {
1147 if (cnx->egl.eglQueryAPI) {
1148 // the first one we find is okay, because they all
1149 // should be the same
1150 return cnx->egl.eglQueryAPI();
1151 }
1152 }
1153 }
1154 // or, it can only be OpenGL ES
1155 return EGL_OPENGL_ES_API;
1156}
1157
1158EGLBoolean eglReleaseThread(void)
1159{
1160 clearError();
1161
1162 // If there is context bound to the thread, release it
1163 loseCurrent(get_context(getContext()));
1164
1165 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1166 egl_connection_t* const cnx = &gEGLImpl[i];
1167 if (cnx->dso) {
1168 if (cnx->egl.eglReleaseThread) {
1169 cnx->egl.eglReleaseThread();
1170 }
1171 }
1172 }
1173 egl_tls_t::clearTLS();
Siva Velusamydb974682011-11-30 15:05:37 -08001174#if EGL_TRACE
1175 if (gEGLDebugLevel > 0)
1176 GLTrace_eglReleaseThread();
1177#endif
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001178 return EGL_TRUE;
1179}
1180
1181EGLSurface eglCreatePbufferFromClientBuffer(
1182 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1183 EGLConfig config, const EGLint *attrib_list)
1184{
1185 clearError();
1186
1187 egl_display_t const* dp = 0;
1188 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
1189 if (!cnx) return EGL_FALSE;
1190 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1191 return cnx->egl.eglCreatePbufferFromClientBuffer(
1192 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1193 buftype, buffer,
1194 dp->configs[intptr_t(config)].config, attrib_list);
1195 }
1196 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1197}
1198
1199// ----------------------------------------------------------------------------
1200// EGL_EGLEXT_VERSION 3
1201// ----------------------------------------------------------------------------
1202
1203EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1204 const EGLint *attrib_list)
1205{
1206 clearError();
1207
1208 egl_display_t const * const dp = validate_display(dpy);
1209 if (!dp) return EGL_FALSE;
1210
Mathias Agopian274e03c2011-11-13 20:50:07 -08001211 SurfaceRef _s(dp, surface);
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001212 if (!_s.get())
1213 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001214
1215 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001216 if (s->cnx->egl.eglLockSurfaceKHR) {
1217 return s->cnx->egl.eglLockSurfaceKHR(
1218 dp->disp[s->impl].dpy, s->surface, attrib_list);
1219 }
1220 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1221}
1222
1223EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1224{
1225 clearError();
1226
1227 egl_display_t const * const dp = validate_display(dpy);
1228 if (!dp) return EGL_FALSE;
1229
Mathias Agopian274e03c2011-11-13 20:50:07 -08001230 SurfaceRef _s(dp, surface);
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001231 if (!_s.get())
1232 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001233
1234 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001235 if (s->cnx->egl.eglUnlockSurfaceKHR) {
1236 return s->cnx->egl.eglUnlockSurfaceKHR(
1237 dp->disp[s->impl].dpy, s->surface);
1238 }
1239 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1240}
1241
1242EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1243 EGLClientBuffer buffer, const EGLint *attrib_list)
1244{
1245 clearError();
1246
1247 egl_display_t const * const dp = validate_display(dpy);
1248 if (!dp) return EGL_NO_IMAGE_KHR;
1249
1250 if (ctx != EGL_NO_CONTEXT) {
Mathias Agopian274e03c2011-11-13 20:50:07 -08001251 ContextRef _c(dp, ctx);
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001252 if (!_c.get())
1253 return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001254 egl_context_t * const c = get_context(ctx);
1255 // since we have an EGLContext, we know which implementation to use
1256 EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
1257 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
1258 if (image == EGL_NO_IMAGE_KHR)
1259 return image;
1260
1261 egl_image_t* result = new egl_image_t(dpy, ctx);
1262 result->images[c->impl] = image;
1263 return (EGLImageKHR)result;
1264 } else {
1265 // EGL_NO_CONTEXT is a valid parameter
1266
1267 /* Since we don't have a way to know which implementation to call,
1268 * we're calling all of them. If at least one of the implementation
1269 * succeeded, this is a success.
1270 */
1271
1272 EGLint currentError = eglGetError();
1273
1274 EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS];
1275 bool success = false;
1276 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1277 egl_connection_t* const cnx = &gEGLImpl[i];
1278 implImages[i] = EGL_NO_IMAGE_KHR;
1279 if (cnx->dso) {
1280 if (cnx->egl.eglCreateImageKHR) {
1281 implImages[i] = cnx->egl.eglCreateImageKHR(
1282 dp->disp[i].dpy, ctx, target, buffer, attrib_list);
1283 if (implImages[i] != EGL_NO_IMAGE_KHR) {
1284 success = true;
1285 }
1286 }
1287 }
1288 }
1289
1290 if (!success) {
1291 // failure, if there was an error when we entered this function,
1292 // the error flag must not be updated.
1293 // Otherwise, the error is whatever happened in the implementation
1294 // that faulted.
1295 if (currentError != EGL_SUCCESS) {
1296 setError(currentError, EGL_NO_IMAGE_KHR);
1297 }
1298 return EGL_NO_IMAGE_KHR;
1299 } else {
1300 // In case of success, we need to clear all error flags
1301 // (especially those caused by the implementation that didn't
1302 // succeed). TODO: we could avoid this if we knew this was
1303 // a "full" success (all implementation succeeded).
1304 eglGetError();
1305 }
1306
1307 egl_image_t* result = new egl_image_t(dpy, ctx);
1308 memcpy(result->images, implImages, sizeof(implImages));
1309 return (EGLImageKHR)result;
1310 }
1311}
1312
1313EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1314{
1315 clearError();
1316
1317 egl_display_t const * const dp = validate_display(dpy);
1318 if (!dp) return EGL_FALSE;
1319
Mathias Agopian274e03c2011-11-13 20:50:07 -08001320 ImageRef _i(dp, img);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001321 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1322
1323 egl_image_t* image = get_image(img);
1324 bool success = false;
1325 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1326 egl_connection_t* const cnx = &gEGLImpl[i];
1327 if (image->images[i] != EGL_NO_IMAGE_KHR) {
1328 if (cnx->dso) {
1329 if (cnx->egl.eglDestroyImageKHR) {
1330 if (cnx->egl.eglDestroyImageKHR(
1331 dp->disp[i].dpy, image->images[i])) {
1332 success = true;
1333 }
1334 }
1335 }
1336 }
1337 }
1338 if (!success)
1339 return EGL_FALSE;
1340
1341 _i.terminate();
1342
1343 return EGL_TRUE;
1344}
1345
1346// ----------------------------------------------------------------------------
1347// EGL_EGLEXT_VERSION 5
1348// ----------------------------------------------------------------------------
1349
1350
1351EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1352{
1353 clearError();
1354
1355 egl_display_t const * const dp = validate_display(dpy);
1356 if (!dp) return EGL_NO_SYNC_KHR;
1357
1358 EGLContext ctx = eglGetCurrentContext();
Mathias Agopian274e03c2011-11-13 20:50:07 -08001359 ContextRef _c(dp, ctx);
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001360 if (!_c.get())
1361 return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR);
1362
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001363 egl_context_t * const c = get_context(ctx);
1364 EGLSyncKHR result = EGL_NO_SYNC_KHR;
1365 if (c->cnx->egl.eglCreateSyncKHR) {
1366 EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR(
1367 dp->disp[c->impl].dpy, type, attrib_list);
1368 if (sync == EGL_NO_SYNC_KHR)
1369 return sync;
1370 result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync);
1371 }
1372 return (EGLSyncKHR)result;
1373}
1374
1375EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1376{
1377 clearError();
1378
1379 egl_display_t const * const dp = validate_display(dpy);
1380 if (!dp) return EGL_FALSE;
1381
Mathias Agopian274e03c2011-11-13 20:50:07 -08001382 SyncRef _s(dp, sync);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001383 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1384 egl_sync_t* syncObject = get_sync(sync);
1385
1386 EGLContext ctx = syncObject->context;
Mathias Agopian274e03c2011-11-13 20:50:07 -08001387 ContextRef _c(dp, ctx);
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001388 if (!_c.get())
1389 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001390
1391 EGLBoolean result = EGL_FALSE;
1392 egl_context_t * const c = get_context(ctx);
1393 if (c->cnx->egl.eglDestroySyncKHR) {
1394 result = c->cnx->egl.eglDestroySyncKHR(
1395 dp->disp[c->impl].dpy, syncObject->sync);
1396 if (result)
1397 _s.terminate();
1398 }
1399 return result;
1400}
1401
1402EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
1403{
1404 clearError();
1405
1406 egl_display_t const * const dp = validate_display(dpy);
1407 if (!dp) return EGL_FALSE;
1408
Mathias Agopian274e03c2011-11-13 20:50:07 -08001409 SyncRef _s(dp, sync);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001410 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1411 egl_sync_t* syncObject = get_sync(sync);
1412
1413 EGLContext ctx = syncObject->context;
Mathias Agopian274e03c2011-11-13 20:50:07 -08001414 ContextRef _c(dp, ctx);
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001415 if (!_c.get())
1416 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001417
1418 egl_context_t * const c = get_context(ctx);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001419 if (c->cnx->egl.eglClientWaitSyncKHR) {
1420 return c->cnx->egl.eglClientWaitSyncKHR(
1421 dp->disp[c->impl].dpy, syncObject->sync, flags, timeout);
1422 }
1423
1424 return EGL_FALSE;
1425}
1426
1427EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
1428{
1429 clearError();
1430
1431 egl_display_t const * const dp = validate_display(dpy);
1432 if (!dp) return EGL_FALSE;
1433
Mathias Agopian274e03c2011-11-13 20:50:07 -08001434 SyncRef _s(dp, sync);
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001435 if (!_s.get())
1436 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001437
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001438 egl_sync_t* syncObject = get_sync(sync);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001439 EGLContext ctx = syncObject->context;
Mathias Agopian274e03c2011-11-13 20:50:07 -08001440 ContextRef _c(dp, ctx);
Mathias Agopianf1e4e062011-05-16 18:58:55 -07001441 if (!_c.get())
1442 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001443
1444 egl_context_t * const c = get_context(ctx);
Mathias Agopian7adf4ef2011-05-13 16:21:08 -07001445 if (c->cnx->egl.eglGetSyncAttribKHR) {
1446 return c->cnx->egl.eglGetSyncAttribKHR(
1447 dp->disp[c->impl].dpy, syncObject->sync, attribute, value);
1448 }
1449
1450 return EGL_FALSE;
1451}
1452
1453// ----------------------------------------------------------------------------
1454// ANDROID extensions
1455// ----------------------------------------------------------------------------
1456
Mathias Agopiane88740e2011-11-13 23:52:47 -08001457/* ANDROID extensions entry-point go here */
Jonas Yang1b1d73f2011-08-26 20:04:39 +08001458
1459// ----------------------------------------------------------------------------
1460// NVIDIA extensions
1461// ----------------------------------------------------------------------------
1462EGLuint64NV eglGetSystemTimeFrequencyNV()
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.eglGetSystemTimeFrequencyNV) {
1475 return cnx->egl.eglGetSystemTimeFrequencyNV();
1476 }
1477 }
1478
Mathias Agopian97bc75d2011-10-05 19:15:05 -07001479 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1b1d73f2011-08-26 20:04:39 +08001480}
1481
1482EGLuint64NV eglGetSystemTimeNV()
1483{
1484 clearError();
1485
1486 if (egl_init_drivers() == EGL_FALSE) {
1487 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1488 }
1489
1490 EGLuint64NV ret = 0;
1491 egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE];
1492
1493 if (cnx->dso) {
1494 if (cnx->egl.eglGetSystemTimeNV) {
1495 return cnx->egl.eglGetSystemTimeNV();
1496 }
1497 }
1498
Mathias Agopian97bc75d2011-10-05 19:15:05 -07001499 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1b1d73f2011-08-26 20:04:39 +08001500}