blob: 73aab26cc76c83f16d108c7c90a569b3c5644ed9 [file] [log] [blame]
Mathias Agopian518ec112011-05-13 16:21:08 -07001/*
2 ** Copyright 2007, The Android Open Source Project
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 ** http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16
17#include <ctype.h>
18#include <stdlib.h>
19#include <string.h>
20
21#include <hardware/gralloc.h>
22#include <system/window.h>
23
24#include <EGL/egl.h>
25#include <EGL/eglext.h>
26#include <GLES/gl.h>
27#include <GLES/glext.h>
28
29#include <cutils/log.h>
30#include <cutils/atomic.h>
31#include <cutils/properties.h>
32#include <cutils/memory.h>
33
34#include <utils/KeyedVector.h>
35#include <utils/SortedVector.h>
36#include <utils/String8.h>
37
38#include "egl_impl.h"
39#include "egl_tls.h"
Siva Velusamy0469dd62011-11-30 15:05:37 -080040#include "glestrace.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070041#include "hooks.h"
42
43#include "egl_display.h"
44#include "egl_impl.h"
45#include "egl_object.h"
46#include "egl_tls.h"
47
48using namespace android;
49
50// ----------------------------------------------------------------------------
51
Mathias Agopianbc2d79e2011-11-29 17:55:46 -080052#define EGL_VERSION_HW_ANDROID 0x3143
53
Mathias Agopian518ec112011-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 Yang1c3d72a2011-08-26 20:04:39 +080068 { "eglGetSystemTimeFrequencyNV",
69 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
70 { "eglGetSystemTimeNV",
71 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
Mathias Agopian518ec112011-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 Agopian518ec112011-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 Agopian81a63352011-07-29 17:55:48 -0700354 if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000355 ALOGE("EGLNativeWindowType %p already connected to another API",
Mathias Agopian81a63352011-07-29 17:55:48 -0700356 window);
357 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
358 }
359
Mathias Agopian518ec112011-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 Gennisbee205f2011-07-01 13:12:07 -0700364 int err = native_window_set_buffers_format(window, format);
365 if (err != 0) {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000366 ALOGE("error setting native window pixel format: %s (%d)",
Jamie Gennisbee205f2011-07-01 13:12:07 -0700367 strerror(-err), err);
Mathias Agopian81a63352011-07-29 17:55:48 -0700368 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Jamie Gennisbee205f2011-07-01 13:12:07 -0700369 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
370 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700371 }
372 }
373
Jamie Gennis59769462011-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 Agopian518ec112011-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 Agopian81a63352011-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 Agopian518ec112011-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 Agopianf0480de2011-11-13 20:50:07 -0800442 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700443 if (!_s.get())
444 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-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 Agopian518ec112011-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 Agopianf0480de2011-11-13 20:50:07 -0800463 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700464 if (!_s.get())
465 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700466
Mathias Agopian518ec112011-05-13 16:21:08 -0700467 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-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
Jamie Gennise8696a42012-01-15 18:54:57 -0800480void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
481 clearError();
482
483 egl_display_t const * const dp = validate_display(dpy);
484 if (!dp) {
485 return;
486 }
487
488 SurfaceRef _s(dp, surface);
489 if (!_s.get()) {
490 setError(EGL_BAD_SURFACE, EGL_FALSE);
491 return;
492 }
493
494 int64_t timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
495
496 egl_surface_t const * const s = get_surface(surface);
497 native_window_set_buffers_timestamp(s->win.get(), timestamp);
498}
499
Mathias Agopian518ec112011-05-13 16:21:08 -0700500// ----------------------------------------------------------------------------
501// Contexts
502// ----------------------------------------------------------------------------
503
504EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
505 EGLContext share_list, const EGLint *attrib_list)
506{
507 clearError();
508
509 egl_display_t const* dp = 0;
510 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
511 if (cnx) {
512 if (share_list != EGL_NO_CONTEXT) {
513 egl_context_t* const c = get_context(share_list);
514 share_list = c->context;
515 }
516 EGLContext context = cnx->egl.eglCreateContext(
517 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
518 dp->configs[intptr_t(config)].config,
519 share_list, attrib_list);
520 if (context != EGL_NO_CONTEXT) {
521 // figure out if it's a GLESv1 or GLESv2
522 int version = 0;
523 if (attrib_list) {
524 while (*attrib_list != EGL_NONE) {
525 GLint attr = *attrib_list++;
526 GLint value = *attrib_list++;
527 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
528 if (value == 1) {
529 version = GLESv1_INDEX;
530 } else if (value == 2) {
531 version = GLESv2_INDEX;
532 }
533 }
534 };
535 }
536 egl_context_t* c = new egl_context_t(dpy, context, config,
537 dp->configs[intptr_t(config)].impl, cnx, version);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800538#if EGL_TRACE
539 if (gEGLDebugLevel > 0)
540 GLTrace_eglCreateContext(version, c);
541#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700542 return c;
543 }
544 }
545 return EGL_NO_CONTEXT;
546}
547
548EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
549{
550 clearError();
551
552 egl_display_t const * const dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700553 if (!dp)
554 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700555
Mathias Agopianf0480de2011-11-13 20:50:07 -0800556 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700557 if (!_c.get())
558 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700559
Mathias Agopian518ec112011-05-13 16:21:08 -0700560 egl_context_t * const c = get_context(ctx);
561 EGLBoolean result = c->cnx->egl.eglDestroyContext(
562 dp->disp[c->impl].dpy, c->context);
563 if (result == EGL_TRUE) {
564 _c.terminate();
565 }
566 return result;
567}
568
Mathias Agopian518ec112011-05-13 16:21:08 -0700569EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
570 EGLSurface read, EGLContext ctx)
571{
572 clearError();
573
574 egl_display_t const * const dp = get_display(dpy);
575 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
576
Mathias Agopian5b287a62011-05-16 18:58:55 -0700577 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
578 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
579 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -0700580 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
581 (draw != EGL_NO_SURFACE) ) {
582 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
583 }
584
585 // get a reference to the object passed in
Mathias Agopianf0480de2011-11-13 20:50:07 -0800586 ContextRef _c(dp, ctx);
587 SurfaceRef _d(dp, draw);
588 SurfaceRef _r(dp, read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700589
590 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -0700591 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700592 // EGL_NO_CONTEXT is valid
593 return EGL_FALSE;
594 }
595
596 // these are the underlying implementation's object
597 EGLContext impl_ctx = EGL_NO_CONTEXT;
598 EGLSurface impl_draw = EGL_NO_SURFACE;
599 EGLSurface impl_read = EGL_NO_SURFACE;
600
601 // these are our objects structs passed in
602 egl_context_t * c = NULL;
603 egl_surface_t const * d = NULL;
604 egl_surface_t const * r = NULL;
605
606 // these are the current objects structs
607 egl_context_t * cur_c = get_context(getContext());
608
609 if (ctx != EGL_NO_CONTEXT) {
610 c = get_context(ctx);
611 impl_ctx = c->context;
612 } else {
613 // no context given, use the implementation of the current context
614 if (cur_c == NULL) {
615 // no current context
616 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
617 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
618 return setError(EGL_BAD_MATCH, EGL_FALSE);
619 }
620 // not an error, there is just no current context.
621 return EGL_TRUE;
622 }
623 }
624
625 // retrieve the underlying implementation's draw EGLSurface
626 if (draw != EGL_NO_SURFACE) {
627 d = get_surface(draw);
628 // make sure the EGLContext and EGLSurface passed in are for
629 // the same driver
630 if (c && d->impl != c->impl)
631 return setError(EGL_BAD_MATCH, EGL_FALSE);
632 impl_draw = d->surface;
633 }
634
635 // retrieve the underlying implementation's read EGLSurface
636 if (read != EGL_NO_SURFACE) {
637 r = get_surface(read);
638 // make sure the EGLContext and EGLSurface passed in are for
639 // the same driver
640 if (c && r->impl != c->impl)
641 return setError(EGL_BAD_MATCH, EGL_FALSE);
642 impl_read = r->surface;
643 }
644
Mathias Agopian518ec112011-05-13 16:21:08 -0700645
Mathias Agopianfb87e542012-01-30 18:20:52 -0800646 EGLBoolean result = const_cast<egl_display_t*>(dp)->makeCurrent(c, cur_c,
647 draw, read, ctx,
648 impl_draw, impl_read, impl_ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700649
650 if (result == EGL_TRUE) {
Mathias Agopianfb87e542012-01-30 18:20:52 -0800651 if (c) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700652 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
653 egl_tls_t::setContext(ctx);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800654#if EGL_TRACE
655 if (gEGLDebugLevel > 0)
Siva Velusamy93a826f2011-12-14 12:19:56 -0800656 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800657#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700658 _c.acquire();
659 _r.acquire();
660 _d.acquire();
Mathias Agopian518ec112011-05-13 16:21:08 -0700661 } else {
662 setGLHooksThreadSpecific(&gHooksNoContext);
663 egl_tls_t::setContext(EGL_NO_CONTEXT);
664 }
Mathias Agopian5fecea72011-08-25 18:38:24 -0700665 } else {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000666 // this will ALOGE the error
Mathias Agopian5fecea72011-08-25 18:38:24 -0700667 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
Steve Blocke6f43dd2012-01-06 19:20:56 +0000878 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
Mathias Agopian518ec112011-05-13 16:21:08 -0700879 "no more slots for eglGetProcAddress(\"%s\")",
880 procname);
881
Siva Velusamy0469dd62011-11-30 15:05:37 -0800882#if EGL_TRACE
883 gl_hooks_t *debugHooks = GLTrace_getGLHooks();
884#endif
885
Mathias Agopian518ec112011-05-13 16:21:08 -0700886 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
887 bool found = false;
888 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
889 egl_connection_t* const cnx = &gEGLImpl[i];
890 if (cnx->dso && cnx->egl.eglGetProcAddress) {
891 found = true;
892 // Extensions are independent of the bound context
893 cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
894 cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
895#if EGL_TRACE
Mathias Agopian48d438d2012-01-28 21:44:00 -0800896 debugHooks->ext.extensions[slot] =
897 gHooksTrace.ext.extensions[slot] =
Mathias Agopian518ec112011-05-13 16:21:08 -0700898#endif
899 cnx->egl.eglGetProcAddress(procname);
900 }
901 }
902 if (found) {
903 addr = gExtensionForwarders[slot];
904
905 if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) {
906 glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr;
907 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper;
908 }
909 if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) {
910 glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr;
911 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper;
912 }
913
914 sGLExtentionMap.add(name, addr);
915 sGLExtentionSlot++;
916 }
917 }
918
919 pthread_mutex_unlock(&sExtensionMapMutex);
920 return addr;
921}
922
923EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
924{
Mathias Agopian518ec112011-05-13 16:21:08 -0700925 clearError();
926
927 egl_display_t const * const dp = validate_display(dpy);
928 if (!dp) return EGL_FALSE;
929
Mathias Agopianf0480de2011-11-13 20:50:07 -0800930 SurfaceRef _s(dp, draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700931 if (!_s.get())
932 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700933
Siva Velusamy0469dd62011-11-30 15:05:37 -0800934#if EGL_TRACE
935 if (gEGLDebugLevel > 0)
936 GLTrace_eglSwapBuffers(dpy, draw);
937#endif
938
Mathias Agopian518ec112011-05-13 16:21:08 -0700939 egl_surface_t const * const s = get_surface(draw);
940 return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
941}
942
943EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
944 NativePixmapType target)
945{
946 clearError();
947
948 egl_display_t const * const dp = validate_display(dpy);
949 if (!dp) return EGL_FALSE;
950
Mathias Agopianf0480de2011-11-13 20:50:07 -0800951 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700952 if (!_s.get())
953 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700954
Mathias Agopian518ec112011-05-13 16:21:08 -0700955 egl_surface_t const * const s = get_surface(surface);
956 return s->cnx->egl.eglCopyBuffers(
957 dp->disp[s->impl].dpy, s->surface, target);
958}
959
960const char* eglQueryString(EGLDisplay dpy, EGLint name)
961{
962 clearError();
963
964 egl_display_t const * const dp = validate_display(dpy);
965 if (!dp) return (const char *) NULL;
966
967 switch (name) {
968 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800969 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -0700970 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800971 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -0700972 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800973 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -0700974 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -0800975 return dp->getClientApiString();
Mathias Agopianbc2d79e2011-11-29 17:55:46 -0800976 case EGL_VERSION_HW_ANDROID: {
977 if (gEGLImpl[IMPL_HARDWARE].dso) {
978 return dp->disp[IMPL_HARDWARE].queryString.version;
979 }
980 return dp->disp[IMPL_SOFTWARE].queryString.version;
981 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700982 }
983 return setError(EGL_BAD_PARAMETER, (const char *)0);
984}
985
986
987// ----------------------------------------------------------------------------
988// EGL 1.1
989// ----------------------------------------------------------------------------
990
991EGLBoolean eglSurfaceAttrib(
992 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
993{
994 clearError();
995
996 egl_display_t const * const dp = validate_display(dpy);
997 if (!dp) return EGL_FALSE;
998
Mathias Agopianf0480de2011-11-13 20:50:07 -0800999 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001000 if (!_s.get())
1001 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001002
Mathias Agopian518ec112011-05-13 16:21:08 -07001003 egl_surface_t const * const s = get_surface(surface);
1004 if (s->cnx->egl.eglSurfaceAttrib) {
1005 return s->cnx->egl.eglSurfaceAttrib(
1006 dp->disp[s->impl].dpy, s->surface, attribute, value);
1007 }
1008 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1009}
1010
1011EGLBoolean eglBindTexImage(
1012 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1013{
1014 clearError();
1015
1016 egl_display_t const * const dp = validate_display(dpy);
1017 if (!dp) return EGL_FALSE;
1018
Mathias Agopianf0480de2011-11-13 20:50:07 -08001019 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001020 if (!_s.get())
1021 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001022
Mathias Agopian518ec112011-05-13 16:21:08 -07001023 egl_surface_t const * const s = get_surface(surface);
1024 if (s->cnx->egl.eglBindTexImage) {
1025 return s->cnx->egl.eglBindTexImage(
1026 dp->disp[s->impl].dpy, s->surface, buffer);
1027 }
1028 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1029}
1030
1031EGLBoolean eglReleaseTexImage(
1032 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1033{
1034 clearError();
1035
1036 egl_display_t const * const dp = validate_display(dpy);
1037 if (!dp) return EGL_FALSE;
1038
Mathias Agopianf0480de2011-11-13 20:50:07 -08001039 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001040 if (!_s.get())
1041 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001042
Mathias Agopian518ec112011-05-13 16:21:08 -07001043 egl_surface_t const * const s = get_surface(surface);
1044 if (s->cnx->egl.eglReleaseTexImage) {
1045 return s->cnx->egl.eglReleaseTexImage(
1046 dp->disp[s->impl].dpy, s->surface, buffer);
1047 }
1048 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1049}
1050
1051EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1052{
1053 clearError();
1054
1055 egl_display_t const * const dp = validate_display(dpy);
1056 if (!dp) return EGL_FALSE;
1057
1058 EGLBoolean res = EGL_TRUE;
1059 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1060 egl_connection_t* const cnx = &gEGLImpl[i];
1061 if (cnx->dso) {
1062 if (cnx->egl.eglSwapInterval) {
1063 if (cnx->egl.eglSwapInterval(
1064 dp->disp[i].dpy, interval) == EGL_FALSE) {
1065 res = EGL_FALSE;
1066 }
1067 }
1068 }
1069 }
1070 return res;
1071}
1072
1073
1074// ----------------------------------------------------------------------------
1075// EGL 1.2
1076// ----------------------------------------------------------------------------
1077
1078EGLBoolean eglWaitClient(void)
1079{
1080 clearError();
1081
1082 // could be called before eglInitialize(), but we wouldn't have a context
1083 // then, and this function would return GL_TRUE, which isn't wrong.
1084 EGLBoolean res = EGL_TRUE;
1085 EGLContext ctx = getContext();
1086 if (ctx) {
1087 egl_context_t const * const c = get_context(ctx);
1088 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1089 if (uint32_t(c->impl)>=2)
1090 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1091 egl_connection_t* const cnx = &gEGLImpl[c->impl];
1092 if (!cnx->dso)
1093 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1094 if (cnx->egl.eglWaitClient) {
1095 res = cnx->egl.eglWaitClient();
1096 } else {
1097 res = cnx->egl.eglWaitGL();
1098 }
1099 }
1100 return res;
1101}
1102
1103EGLBoolean eglBindAPI(EGLenum api)
1104{
1105 clearError();
1106
1107 if (egl_init_drivers() == EGL_FALSE) {
1108 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1109 }
1110
1111 // bind this API on all EGLs
1112 EGLBoolean res = EGL_TRUE;
1113 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1114 egl_connection_t* const cnx = &gEGLImpl[i];
1115 if (cnx->dso) {
1116 if (cnx->egl.eglBindAPI) {
1117 if (cnx->egl.eglBindAPI(api) == EGL_FALSE) {
1118 res = EGL_FALSE;
1119 }
1120 }
1121 }
1122 }
1123 return res;
1124}
1125
1126EGLenum eglQueryAPI(void)
1127{
1128 clearError();
1129
1130 if (egl_init_drivers() == EGL_FALSE) {
1131 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1132 }
1133
1134 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1135 egl_connection_t* const cnx = &gEGLImpl[i];
1136 if (cnx->dso) {
1137 if (cnx->egl.eglQueryAPI) {
1138 // the first one we find is okay, because they all
1139 // should be the same
1140 return cnx->egl.eglQueryAPI();
1141 }
1142 }
1143 }
1144 // or, it can only be OpenGL ES
1145 return EGL_OPENGL_ES_API;
1146}
1147
1148EGLBoolean eglReleaseThread(void)
1149{
1150 clearError();
1151
1152 // If there is context bound to the thread, release it
Mathias Agopianfb87e542012-01-30 18:20:52 -08001153 egl_display_t::loseCurrent(get_context(getContext()));
Mathias Agopian518ec112011-05-13 16:21:08 -07001154
1155 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1156 egl_connection_t* const cnx = &gEGLImpl[i];
1157 if (cnx->dso) {
1158 if (cnx->egl.eglReleaseThread) {
1159 cnx->egl.eglReleaseThread();
1160 }
1161 }
1162 }
1163 egl_tls_t::clearTLS();
Siva Velusamy0469dd62011-11-30 15:05:37 -08001164#if EGL_TRACE
1165 if (gEGLDebugLevel > 0)
1166 GLTrace_eglReleaseThread();
1167#endif
Mathias Agopian518ec112011-05-13 16:21:08 -07001168 return EGL_TRUE;
1169}
1170
1171EGLSurface eglCreatePbufferFromClientBuffer(
1172 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1173 EGLConfig config, const EGLint *attrib_list)
1174{
1175 clearError();
1176
1177 egl_display_t const* dp = 0;
1178 egl_connection_t* cnx = validate_display_config(dpy, config, dp);
1179 if (!cnx) return EGL_FALSE;
1180 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1181 return cnx->egl.eglCreatePbufferFromClientBuffer(
1182 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
1183 buftype, buffer,
1184 dp->configs[intptr_t(config)].config, attrib_list);
1185 }
1186 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1187}
1188
1189// ----------------------------------------------------------------------------
1190// EGL_EGLEXT_VERSION 3
1191// ----------------------------------------------------------------------------
1192
1193EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1194 const EGLint *attrib_list)
1195{
1196 clearError();
1197
1198 egl_display_t const * const dp = validate_display(dpy);
1199 if (!dp) return EGL_FALSE;
1200
Mathias Agopianf0480de2011-11-13 20:50:07 -08001201 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001202 if (!_s.get())
1203 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001204
1205 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001206 if (s->cnx->egl.eglLockSurfaceKHR) {
1207 return s->cnx->egl.eglLockSurfaceKHR(
1208 dp->disp[s->impl].dpy, s->surface, attrib_list);
1209 }
1210 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1211}
1212
1213EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1214{
1215 clearError();
1216
1217 egl_display_t const * const dp = validate_display(dpy);
1218 if (!dp) return EGL_FALSE;
1219
Mathias Agopianf0480de2011-11-13 20:50:07 -08001220 SurfaceRef _s(dp, surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001221 if (!_s.get())
1222 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001223
1224 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001225 if (s->cnx->egl.eglUnlockSurfaceKHR) {
1226 return s->cnx->egl.eglUnlockSurfaceKHR(
1227 dp->disp[s->impl].dpy, s->surface);
1228 }
1229 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1230}
1231
1232EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1233 EGLClientBuffer buffer, const EGLint *attrib_list)
1234{
1235 clearError();
1236
1237 egl_display_t const * const dp = validate_display(dpy);
1238 if (!dp) return EGL_NO_IMAGE_KHR;
1239
1240 if (ctx != EGL_NO_CONTEXT) {
Mathias Agopianf0480de2011-11-13 20:50:07 -08001241 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001242 if (!_c.get())
1243 return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
Mathias Agopian518ec112011-05-13 16:21:08 -07001244 egl_context_t * const c = get_context(ctx);
1245 // since we have an EGLContext, we know which implementation to use
1246 EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
1247 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
1248 if (image == EGL_NO_IMAGE_KHR)
1249 return image;
1250
1251 egl_image_t* result = new egl_image_t(dpy, ctx);
1252 result->images[c->impl] = image;
1253 return (EGLImageKHR)result;
1254 } else {
1255 // EGL_NO_CONTEXT is a valid parameter
1256
1257 /* Since we don't have a way to know which implementation to call,
1258 * we're calling all of them. If at least one of the implementation
1259 * succeeded, this is a success.
1260 */
1261
1262 EGLint currentError = eglGetError();
1263
1264 EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS];
1265 bool success = false;
1266 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1267 egl_connection_t* const cnx = &gEGLImpl[i];
1268 implImages[i] = EGL_NO_IMAGE_KHR;
1269 if (cnx->dso) {
1270 if (cnx->egl.eglCreateImageKHR) {
1271 implImages[i] = cnx->egl.eglCreateImageKHR(
1272 dp->disp[i].dpy, ctx, target, buffer, attrib_list);
1273 if (implImages[i] != EGL_NO_IMAGE_KHR) {
1274 success = true;
1275 }
1276 }
1277 }
1278 }
1279
1280 if (!success) {
1281 // failure, if there was an error when we entered this function,
1282 // the error flag must not be updated.
1283 // Otherwise, the error is whatever happened in the implementation
1284 // that faulted.
1285 if (currentError != EGL_SUCCESS) {
1286 setError(currentError, EGL_NO_IMAGE_KHR);
1287 }
1288 return EGL_NO_IMAGE_KHR;
1289 } else {
1290 // In case of success, we need to clear all error flags
1291 // (especially those caused by the implementation that didn't
1292 // succeed). TODO: we could avoid this if we knew this was
1293 // a "full" success (all implementation succeeded).
1294 eglGetError();
1295 }
1296
1297 egl_image_t* result = new egl_image_t(dpy, ctx);
1298 memcpy(result->images, implImages, sizeof(implImages));
1299 return (EGLImageKHR)result;
1300 }
1301}
1302
1303EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1304{
1305 clearError();
1306
1307 egl_display_t const * const dp = validate_display(dpy);
1308 if (!dp) return EGL_FALSE;
1309
Mathias Agopianf0480de2011-11-13 20:50:07 -08001310 ImageRef _i(dp, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001311 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1312
1313 egl_image_t* image = get_image(img);
1314 bool success = false;
1315 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
1316 egl_connection_t* const cnx = &gEGLImpl[i];
1317 if (image->images[i] != EGL_NO_IMAGE_KHR) {
1318 if (cnx->dso) {
1319 if (cnx->egl.eglDestroyImageKHR) {
1320 if (cnx->egl.eglDestroyImageKHR(
1321 dp->disp[i].dpy, image->images[i])) {
1322 success = true;
1323 }
1324 }
1325 }
1326 }
1327 }
1328 if (!success)
1329 return EGL_FALSE;
1330
1331 _i.terminate();
1332
1333 return EGL_TRUE;
1334}
1335
1336// ----------------------------------------------------------------------------
1337// EGL_EGLEXT_VERSION 5
1338// ----------------------------------------------------------------------------
1339
1340
1341EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1342{
1343 clearError();
1344
1345 egl_display_t const * const dp = validate_display(dpy);
1346 if (!dp) return EGL_NO_SYNC_KHR;
1347
1348 EGLContext ctx = eglGetCurrentContext();
Mathias Agopianf0480de2011-11-13 20:50:07 -08001349 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001350 if (!_c.get())
1351 return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR);
1352
Mathias Agopian518ec112011-05-13 16:21:08 -07001353 egl_context_t * const c = get_context(ctx);
1354 EGLSyncKHR result = EGL_NO_SYNC_KHR;
1355 if (c->cnx->egl.eglCreateSyncKHR) {
1356 EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR(
1357 dp->disp[c->impl].dpy, type, attrib_list);
1358 if (sync == EGL_NO_SYNC_KHR)
1359 return sync;
1360 result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync);
1361 }
1362 return (EGLSyncKHR)result;
1363}
1364
1365EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1366{
1367 clearError();
1368
1369 egl_display_t const * const dp = validate_display(dpy);
1370 if (!dp) return EGL_FALSE;
1371
Mathias Agopianf0480de2011-11-13 20:50:07 -08001372 SyncRef _s(dp, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001373 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1374 egl_sync_t* syncObject = get_sync(sync);
1375
1376 EGLContext ctx = syncObject->context;
Mathias Agopianf0480de2011-11-13 20:50:07 -08001377 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001378 if (!_c.get())
1379 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001380
1381 EGLBoolean result = EGL_FALSE;
1382 egl_context_t * const c = get_context(ctx);
1383 if (c->cnx->egl.eglDestroySyncKHR) {
1384 result = c->cnx->egl.eglDestroySyncKHR(
1385 dp->disp[c->impl].dpy, syncObject->sync);
1386 if (result)
1387 _s.terminate();
1388 }
1389 return result;
1390}
1391
1392EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
1393{
1394 clearError();
1395
1396 egl_display_t const * const dp = validate_display(dpy);
1397 if (!dp) return EGL_FALSE;
1398
Mathias Agopianf0480de2011-11-13 20:50:07 -08001399 SyncRef _s(dp, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001400 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1401 egl_sync_t* syncObject = get_sync(sync);
1402
1403 EGLContext ctx = syncObject->context;
Mathias Agopianf0480de2011-11-13 20:50:07 -08001404 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001405 if (!_c.get())
1406 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001407
1408 egl_context_t * const c = get_context(ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -07001409 if (c->cnx->egl.eglClientWaitSyncKHR) {
1410 return c->cnx->egl.eglClientWaitSyncKHR(
1411 dp->disp[c->impl].dpy, syncObject->sync, flags, timeout);
1412 }
1413
1414 return EGL_FALSE;
1415}
1416
1417EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
1418{
1419 clearError();
1420
1421 egl_display_t const * const dp = validate_display(dpy);
1422 if (!dp) return EGL_FALSE;
1423
Mathias Agopianf0480de2011-11-13 20:50:07 -08001424 SyncRef _s(dp, sync);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001425 if (!_s.get())
1426 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001427
Mathias Agopian5b287a62011-05-16 18:58:55 -07001428 egl_sync_t* syncObject = get_sync(sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001429 EGLContext ctx = syncObject->context;
Mathias Agopianf0480de2011-11-13 20:50:07 -08001430 ContextRef _c(dp, ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001431 if (!_c.get())
1432 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001433
1434 egl_context_t * const c = get_context(ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -07001435 if (c->cnx->egl.eglGetSyncAttribKHR) {
1436 return c->cnx->egl.eglGetSyncAttribKHR(
1437 dp->disp[c->impl].dpy, syncObject->sync, attribute, value);
1438 }
1439
1440 return EGL_FALSE;
1441}
1442
1443// ----------------------------------------------------------------------------
1444// ANDROID extensions
1445// ----------------------------------------------------------------------------
1446
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001447/* ANDROID extensions entry-point go here */
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001448
1449// ----------------------------------------------------------------------------
1450// NVIDIA extensions
1451// ----------------------------------------------------------------------------
1452EGLuint64NV eglGetSystemTimeFrequencyNV()
1453{
1454 clearError();
1455
1456 if (egl_init_drivers() == EGL_FALSE) {
1457 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1458 }
1459
1460 EGLuint64NV ret = 0;
1461 egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE];
1462
1463 if (cnx->dso) {
1464 if (cnx->egl.eglGetSystemTimeFrequencyNV) {
1465 return cnx->egl.eglGetSystemTimeFrequencyNV();
1466 }
1467 }
1468
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001469 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001470}
1471
1472EGLuint64NV eglGetSystemTimeNV()
1473{
1474 clearError();
1475
1476 if (egl_init_drivers() == EGL_FALSE) {
1477 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1478 }
1479
1480 EGLuint64NV ret = 0;
1481 egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE];
1482
1483 if (cnx->dso) {
1484 if (cnx->egl.eglGetSystemTimeNV) {
1485 return cnx->egl.eglGetSystemTimeNV();
1486 }
1487 }
1488
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001489 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001490}