egl: replace replace _EGLDriver with _EGLDisplay->Driver in eglapi.c
[mesa.git] / src / egl / main / eglapi.c
1 /**************************************************************************
2 *
3 * Copyright 2008 VMware, Inc.
4 * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
5 * Copyright 2010-2011 LunarG, Inc.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sub license, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
18 * of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 *
28 **************************************************************************/
29
30
31 /**
32 * Public EGL API entrypoints
33 *
34 * Generally, we use the EGLDisplay parameter as a key to lookup the
35 * appropriate device driver handle, then jump though the driver's
36 * dispatch table to handle the function.
37 *
38 * That allows us the option of supporting multiple, simultaneous,
39 * heterogeneous hardware devices in the future.
40 *
41 * The EGLDisplay, EGLConfig, EGLContext and EGLSurface types are
42 * opaque handles. Internal objects are linked to a display to
43 * create the handles.
44 *
45 * For each public API entry point, the opaque handles are looked up
46 * before being dispatched to the drivers. When it fails to look up
47 * a handle, one of
48 *
49 * EGL_BAD_DISPLAY
50 * EGL_BAD_CONFIG
51 * EGL_BAD_CONTEXT
52 * EGL_BAD_SURFACE
53 * EGL_BAD_SCREEN_MESA
54 * EGL_BAD_MODE_MESA
55 *
56 * is generated and the driver function is not called. An
57 * uninitialized EGLDisplay has no driver associated with it. When
58 * such display is detected,
59 *
60 * EGL_NOT_INITIALIZED
61 *
62 * is generated.
63 *
64 * Some of the entry points use current display, context, or surface
65 * implicitly. For such entry points, the implicit objects are also
66 * checked before calling the driver function. Other than the
67 * errors listed above,
68 *
69 * EGL_BAD_CURRENT_SURFACE
70 *
71 * may also be generated.
72 *
73 * Notes on naming conventions:
74 *
75 * eglFooBar - public EGL function
76 * EGL_FOO_BAR - public EGL token
77 * EGLDatatype - public EGL datatype
78 *
79 * _eglFooBar - private EGL function
80 * _EGLDatatype - private EGL datatype, typedef'd struct
81 * _egl_struct - private EGL struct, non-typedef'd
82 *
83 */
84
85
86 #ifdef USE_LIBGLVND
87 #define EGLAPI
88 #undef PUBLIC
89 #define PUBLIC
90 #endif
91
92 #include <stdio.h>
93 #include <stdlib.h>
94 #include <string.h>
95 #include "c99_compat.h"
96 #include "c11/threads.h"
97 #include "util/macros.h"
98
99 #include "egldefines.h"
100 #include "eglglobals.h"
101 #include "eglcontext.h"
102 #include "egldisplay.h"
103 #include "egltypedefs.h"
104 #include "eglcurrent.h"
105 #include "egldevice.h"
106 #include "egldriver.h"
107 #include "eglsurface.h"
108 #include "eglconfig.h"
109 #include "eglimage.h"
110 #include "eglsync.h"
111
112 #include "GL/mesa_glinterop.h"
113
114 /**
115 * Macros to help return an API entrypoint.
116 *
117 * These macros will unlock the display and record the error code.
118 */
119 #define RETURN_EGL_ERROR(disp, err, ret) \
120 do { \
121 if (disp) \
122 _eglUnlockDisplay(disp); \
123 /* EGL error codes are non-zero */ \
124 if (err) \
125 _eglError(err, __func__); \
126 return ret; \
127 } while (0)
128
129 #define RETURN_EGL_SUCCESS(disp, ret) \
130 RETURN_EGL_ERROR(disp, EGL_SUCCESS, ret)
131
132 /* record EGL_SUCCESS only when ret evaluates to true */
133 #define RETURN_EGL_EVAL(disp, ret) \
134 RETURN_EGL_ERROR(disp, (ret) ? EGL_SUCCESS : 0, ret)
135
136
137 /*
138 * A bunch of macros and checks to simplify error checking.
139 */
140
141 #define _EGL_CHECK_DISPLAY(disp, ret, drv) \
142 do { \
143 drv = _eglCheckDisplay(disp, __func__); \
144 if (!drv) \
145 RETURN_EGL_ERROR(disp, 0, ret); \
146 } while (0)
147
148 #define _EGL_CHECK_OBJECT(disp, type, obj, ret, drv) \
149 do { \
150 drv = _eglCheck ## type(disp, obj, __func__); \
151 if (!drv) \
152 RETURN_EGL_ERROR(disp, 0, ret); \
153 } while (0)
154
155 #define _EGL_CHECK_SURFACE(disp, surf, ret, drv) \
156 _EGL_CHECK_OBJECT(disp, Surface, surf, ret, drv)
157
158 #define _EGL_CHECK_CONTEXT(disp, context, ret, drv) \
159 _EGL_CHECK_OBJECT(disp, Context, context, ret, drv)
160
161 #define _EGL_CHECK_CONFIG(disp, conf, ret, drv) \
162 _EGL_CHECK_OBJECT(disp, Config, conf, ret, drv)
163
164 #define _EGL_CHECK_SYNC(disp, s, ret, drv) \
165 _EGL_CHECK_OBJECT(disp, Sync, s, ret, drv)
166
167
168 struct _egl_entrypoint {
169 const char *name;
170 _EGLProc function;
171 };
172
173
174 static inline const _EGLDriver *
175 _eglCheckDisplay(_EGLDisplay *disp, const char *msg)
176 {
177 if (!disp) {
178 _eglError(EGL_BAD_DISPLAY, msg);
179 return NULL;
180 }
181 if (!disp->Initialized) {
182 _eglError(EGL_NOT_INITIALIZED, msg);
183 return NULL;
184 }
185 return disp->Driver;
186 }
187
188
189 static inline const _EGLDriver *
190 _eglCheckSurface(_EGLDisplay *disp, _EGLSurface *surf, const char *msg)
191 {
192 const _EGLDriver *drv = _eglCheckDisplay(disp, msg);
193 if (!drv)
194 return NULL;
195 if (!surf) {
196 _eglError(EGL_BAD_SURFACE, msg);
197 return NULL;
198 }
199 return drv;
200 }
201
202
203 static inline const _EGLDriver *
204 _eglCheckContext(_EGLDisplay *disp, _EGLContext *context, const char *msg)
205 {
206 const _EGLDriver *drv = _eglCheckDisplay(disp, msg);
207 if (!drv)
208 return NULL;
209 if (!context) {
210 _eglError(EGL_BAD_CONTEXT, msg);
211 return NULL;
212 }
213 return drv;
214 }
215
216
217 static inline const _EGLDriver *
218 _eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg)
219 {
220 const _EGLDriver *drv = _eglCheckDisplay(disp, msg);
221 if (!drv)
222 return NULL;
223 if (!conf) {
224 _eglError(EGL_BAD_CONFIG, msg);
225 return NULL;
226 }
227 return drv;
228 }
229
230
231 static inline const _EGLDriver *
232 _eglCheckSync(_EGLDisplay *disp, _EGLSync *s, const char *msg)
233 {
234 const _EGLDriver *drv = _eglCheckDisplay(disp, msg);
235 if (!drv)
236 return NULL;
237 if (!s) {
238 _eglError(EGL_BAD_PARAMETER, msg);
239 return NULL;
240 }
241 return drv;
242 }
243
244
245 /**
246 * Lookup and lock a display.
247 */
248 static inline _EGLDisplay *
249 _eglLockDisplay(EGLDisplay dpy)
250 {
251 _EGLDisplay *disp = _eglLookupDisplay(dpy);
252 if (disp)
253 mtx_lock(&disp->Mutex);
254 return disp;
255 }
256
257
258 /**
259 * Unlock a display.
260 */
261 static inline void
262 _eglUnlockDisplay(_EGLDisplay *disp)
263 {
264 mtx_unlock(&disp->Mutex);
265 }
266
267 static EGLBoolean
268 _eglSetFuncName(const char *funcName, _EGLDisplay *disp, EGLenum objectType, _EGLResource *object)
269 {
270 _EGLThreadInfo *thr = _eglGetCurrentThread();
271 if (!_eglIsCurrentThreadDummy()) {
272 thr->CurrentFuncName = funcName;
273 thr->CurrentObjectLabel = NULL;
274
275 if (objectType == EGL_OBJECT_THREAD_KHR)
276 thr->CurrentObjectLabel = thr->Label;
277 else if (objectType == EGL_OBJECT_DISPLAY_KHR && disp)
278 thr->CurrentObjectLabel = disp->Label;
279 else if (object)
280 thr->CurrentObjectLabel = object->Label;
281
282 return EGL_TRUE;
283 }
284
285 _eglDebugReport(EGL_BAD_ALLOC, funcName, EGL_DEBUG_MSG_CRITICAL_KHR, NULL);
286 return EGL_FALSE;
287 }
288
289 #define _EGL_FUNC_START(disp, objectType, object, ret) \
290 do { \
291 if (!_eglSetFuncName(__func__, disp, objectType, (_EGLResource *) object)) { \
292 if (disp) \
293 _eglUnlockDisplay(disp); \
294 return ret; \
295 } \
296 } while(0)
297
298 /**
299 * Convert an attribute list from EGLint[] to EGLAttrib[].
300 *
301 * Return an EGL error code. The output parameter out_attrib_list is modified
302 * only on success.
303 */
304 static EGLint
305 _eglConvertIntsToAttribs(const EGLint *int_list, EGLAttrib **out_attrib_list)
306 {
307 size_t len = 0;
308 EGLAttrib *attrib_list;
309
310 if (int_list) {
311 while (int_list[2*len] != EGL_NONE)
312 ++len;
313 }
314
315 if (len == 0) {
316 *out_attrib_list = NULL;
317 return EGL_SUCCESS;
318 }
319
320 if (2*len + 1 > SIZE_MAX / sizeof(EGLAttrib))
321 return EGL_BAD_ALLOC;
322
323 attrib_list = malloc((2*len + 1) * sizeof(EGLAttrib));
324 if (!attrib_list)
325 return EGL_BAD_ALLOC;
326
327 for (size_t i = 0; i < len; ++i) {
328 attrib_list[2*i + 0] = int_list[2*i + 0];
329 attrib_list[2*i + 1] = int_list[2*i + 1];
330 }
331
332 attrib_list[2*len] = EGL_NONE;
333
334 *out_attrib_list = attrib_list;
335 return EGL_SUCCESS;
336 }
337
338
339 static EGLint *
340 _eglConvertAttribsToInt(const EGLAttrib *attr_list)
341 {
342 size_t size = _eglNumAttribs(attr_list);
343 EGLint *int_attribs = NULL;
344
345 /* Convert attributes from EGLAttrib[] to EGLint[] */
346 if (size) {
347 int_attribs = calloc(size, sizeof(int_attribs[0]));
348 if (!int_attribs)
349 return NULL;
350
351 for (size_t i = 0; i < size; i++)
352 int_attribs[i] = attr_list[i];
353 }
354 return int_attribs;
355 }
356
357
358 /**
359 * This is typically the first EGL function that an application calls.
360 * It associates a private _EGLDisplay object to the native display.
361 */
362 EGLDisplay EGLAPIENTRY
363 eglGetDisplay(EGLNativeDisplayType nativeDisplay)
364 {
365 _EGLPlatformType plat;
366 _EGLDisplay *disp;
367 void *native_display_ptr;
368
369 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY);
370
371 STATIC_ASSERT(sizeof(void*) == sizeof(nativeDisplay));
372 native_display_ptr = (void*) nativeDisplay;
373
374 plat = _eglGetNativePlatform(native_display_ptr);
375 disp = _eglFindDisplay(plat, native_display_ptr, NULL);
376 return _eglGetDisplayHandle(disp);
377 }
378
379 static EGLDisplay
380 _eglGetPlatformDisplayCommon(EGLenum platform, void *native_display,
381 const EGLAttrib *attrib_list)
382 {
383 _EGLDisplay *disp;
384
385 switch (platform) {
386 #ifdef HAVE_X11_PLATFORM
387 case EGL_PLATFORM_X11_EXT:
388 disp = _eglGetX11Display((Display*) native_display, attrib_list);
389 break;
390 #endif
391 #ifdef HAVE_DRM_PLATFORM
392 case EGL_PLATFORM_GBM_MESA:
393 disp = _eglGetGbmDisplay((struct gbm_device*) native_display,
394 attrib_list);
395 break;
396 #endif
397 #ifdef HAVE_WAYLAND_PLATFORM
398 case EGL_PLATFORM_WAYLAND_EXT:
399 disp = _eglGetWaylandDisplay((struct wl_display*) native_display,
400 attrib_list);
401 break;
402 #endif
403 case EGL_PLATFORM_SURFACELESS_MESA:
404 disp = _eglGetSurfacelessDisplay(native_display, attrib_list);
405 break;
406 #ifdef HAVE_ANDROID_PLATFORM
407 case EGL_PLATFORM_ANDROID_KHR:
408 disp = _eglGetAndroidDisplay(native_display, attrib_list);
409 break;
410 #endif
411 case EGL_PLATFORM_DEVICE_EXT:
412 disp = _eglGetDeviceDisplay(native_display, attrib_list);
413 break;
414 default:
415 RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, NULL);
416 }
417
418 return _eglGetDisplayHandle(disp);
419 }
420
421 static EGLDisplay EGLAPIENTRY
422 eglGetPlatformDisplayEXT(EGLenum platform, void *native_display,
423 const EGLint *int_attribs)
424 {
425 EGLAttrib *attrib_list;
426 EGLDisplay disp;
427
428 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY);
429
430 if (_eglConvertIntsToAttribs(int_attribs, &attrib_list) != EGL_SUCCESS)
431 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, NULL);
432
433 disp = _eglGetPlatformDisplayCommon(platform, native_display, attrib_list);
434 free(attrib_list);
435 return disp;
436 }
437
438 EGLDisplay EGLAPIENTRY
439 eglGetPlatformDisplay(EGLenum platform, void *native_display,
440 const EGLAttrib *attrib_list)
441 {
442 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY);
443 return _eglGetPlatformDisplayCommon(platform, native_display, attrib_list);
444 }
445
446 /**
447 * Copy the extension into the string and update the string pointer.
448 */
449 static EGLint
450 _eglAppendExtension(char **str, const char *ext)
451 {
452 char *s = *str;
453 size_t len = strlen(ext);
454
455 if (s) {
456 memcpy(s, ext, len);
457 s[len++] = ' ';
458 s[len] = '\0';
459
460 *str += len;
461 }
462 else {
463 len++;
464 }
465
466 return (EGLint) len;
467 }
468
469 /**
470 * Examine the individual extension enable/disable flags and recompute
471 * the driver's Extensions string.
472 */
473 static void
474 _eglCreateExtensionsString(_EGLDisplay *disp)
475 {
476 #define _EGL_CHECK_EXTENSION(ext) \
477 do { \
478 if (disp->Extensions.ext) { \
479 _eglAppendExtension(&exts, "EGL_" #ext); \
480 assert(exts <= disp->ExtensionsString + _EGL_MAX_EXTENSIONS_LEN); \
481 } \
482 } while (0)
483
484 char *exts = disp->ExtensionsString;
485
486 /* Please keep these sorted alphabetically. */
487 _EGL_CHECK_EXTENSION(ANDROID_blob_cache);
488 _EGL_CHECK_EXTENSION(ANDROID_framebuffer_target);
489 _EGL_CHECK_EXTENSION(ANDROID_image_native_buffer);
490 _EGL_CHECK_EXTENSION(ANDROID_native_fence_sync);
491 _EGL_CHECK_EXTENSION(ANDROID_recordable);
492
493 _EGL_CHECK_EXTENSION(CHROMIUM_sync_control);
494
495 _EGL_CHECK_EXTENSION(EXT_buffer_age);
496 _EGL_CHECK_EXTENSION(EXT_create_context_robustness);
497 _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import);
498 _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import_modifiers);
499 _EGL_CHECK_EXTENSION(EXT_surface_CTA861_3_metadata);
500 _EGL_CHECK_EXTENSION(EXT_surface_SMPTE2086_metadata);
501 _EGL_CHECK_EXTENSION(EXT_swap_buffers_with_damage);
502
503 _EGL_CHECK_EXTENSION(IMG_context_priority);
504
505 _EGL_CHECK_EXTENSION(KHR_cl_event2);
506 _EGL_CHECK_EXTENSION(KHR_config_attribs);
507 _EGL_CHECK_EXTENSION(KHR_context_flush_control);
508 _EGL_CHECK_EXTENSION(KHR_create_context);
509 _EGL_CHECK_EXTENSION(KHR_create_context_no_error);
510 _EGL_CHECK_EXTENSION(KHR_fence_sync);
511 _EGL_CHECK_EXTENSION(KHR_get_all_proc_addresses);
512 _EGL_CHECK_EXTENSION(KHR_gl_colorspace);
513 _EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_image);
514 _EGL_CHECK_EXTENSION(KHR_gl_texture_2D_image);
515 _EGL_CHECK_EXTENSION(KHR_gl_texture_3D_image);
516 _EGL_CHECK_EXTENSION(KHR_gl_texture_cubemap_image);
517 if (disp->Extensions.KHR_image_base && disp->Extensions.KHR_image_pixmap)
518 disp->Extensions.KHR_image = EGL_TRUE;
519 _EGL_CHECK_EXTENSION(KHR_image);
520 _EGL_CHECK_EXTENSION(KHR_image_base);
521 _EGL_CHECK_EXTENSION(KHR_image_pixmap);
522 _EGL_CHECK_EXTENSION(KHR_mutable_render_buffer);
523 _EGL_CHECK_EXTENSION(KHR_no_config_context);
524 _EGL_CHECK_EXTENSION(KHR_partial_update);
525 _EGL_CHECK_EXTENSION(KHR_reusable_sync);
526 _EGL_CHECK_EXTENSION(KHR_surfaceless_context);
527 if (disp->Extensions.EXT_swap_buffers_with_damage)
528 _eglAppendExtension(&exts, "EGL_KHR_swap_buffers_with_damage");
529 _EGL_CHECK_EXTENSION(EXT_pixel_format_float);
530 _EGL_CHECK_EXTENSION(KHR_wait_sync);
531
532 if (disp->Extensions.KHR_no_config_context)
533 _eglAppendExtension(&exts, "EGL_MESA_configless_context");
534 _EGL_CHECK_EXTENSION(MESA_drm_image);
535 _EGL_CHECK_EXTENSION(MESA_image_dma_buf_export);
536 _EGL_CHECK_EXTENSION(MESA_query_driver);
537
538 _EGL_CHECK_EXTENSION(NOK_swap_region);
539 _EGL_CHECK_EXTENSION(NOK_texture_from_pixmap);
540
541 _EGL_CHECK_EXTENSION(NV_post_sub_buffer);
542
543 _EGL_CHECK_EXTENSION(WL_bind_wayland_display);
544 _EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image);
545
546 #undef _EGL_CHECK_EXTENSION
547 }
548
549 static void
550 _eglCreateAPIsString(_EGLDisplay *disp)
551 {
552 #define addstr(str) \
553 { \
554 const size_t old_len = strlen(disp->ClientAPIsString); \
555 const size_t add_len = sizeof(str); \
556 const size_t max_len = sizeof(disp->ClientAPIsString) - 1; \
557 if (old_len + add_len <= max_len) \
558 strcat(disp->ClientAPIsString, str " "); \
559 else \
560 assert(!"disp->ClientAPIsString is not large enough"); \
561 }
562
563 if (disp->ClientAPIs & EGL_OPENGL_BIT)
564 addstr("OpenGL");
565
566 if (disp->ClientAPIs & EGL_OPENGL_ES_BIT ||
567 disp->ClientAPIs & EGL_OPENGL_ES2_BIT ||
568 disp->ClientAPIs & EGL_OPENGL_ES3_BIT_KHR) {
569 addstr("OpenGL_ES");
570 }
571
572 if (disp->ClientAPIs & EGL_OPENVG_BIT)
573 addstr("OpenVG");
574
575 #undef addstr
576 }
577
578 static void
579 _eglComputeVersion(_EGLDisplay *disp)
580 {
581 disp->Version = 14;
582
583 if (disp->Extensions.KHR_fence_sync &&
584 disp->Extensions.KHR_cl_event2 &&
585 disp->Extensions.KHR_wait_sync &&
586 disp->Extensions.KHR_image_base &&
587 disp->Extensions.KHR_gl_texture_2D_image &&
588 disp->Extensions.KHR_gl_texture_3D_image &&
589 disp->Extensions.KHR_gl_texture_cubemap_image &&
590 disp->Extensions.KHR_gl_renderbuffer_image &&
591 disp->Extensions.KHR_create_context &&
592 disp->Extensions.EXT_create_context_robustness &&
593 disp->Extensions.KHR_get_all_proc_addresses &&
594 disp->Extensions.KHR_gl_colorspace &&
595 disp->Extensions.KHR_surfaceless_context)
596 disp->Version = 15;
597
598 /* For Android P and below limit the EGL version to 1.4 */
599 #if defined(ANDROID) && ANDROID_API_LEVEL <= 28
600 disp->Version = 14;
601 #endif
602 }
603
604 /**
605 * This is typically the second EGL function that an application calls.
606 * Here we load/initialize the actual hardware driver.
607 */
608 EGLBoolean EGLAPIENTRY
609 eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
610 {
611 _EGLDisplay *disp = _eglLockDisplay(dpy);
612
613 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
614
615 if (!disp)
616 RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
617
618 if (!disp->Initialized) {
619 if (!_eglInitializeDisplay(disp))
620 RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
621
622 /* limit to APIs supported by core */
623 disp->ClientAPIs &= _EGL_API_ALL_BITS;
624
625 /* EGL_KHR_get_all_proc_addresses is a corner-case extension. The spec
626 * classifies it as an EGL display extension, though conceptually it's an
627 * EGL client extension.
628 *
629 * From the EGL_KHR_get_all_proc_addresses spec:
630 *
631 * The EGL implementation must expose the name
632 * EGL_KHR_client_get_all_proc_addresses if and only if it exposes
633 * EGL_KHR_get_all_proc_addresses and supports
634 * EGL_EXT_client_extensions.
635 *
636 * Mesa unconditionally exposes both client extensions mentioned above,
637 * so the spec requires that each EGLDisplay unconditionally expose
638 * EGL_KHR_get_all_proc_addresses also.
639 */
640 disp->Extensions.KHR_get_all_proc_addresses = EGL_TRUE;
641
642 /* Extensions is used to provide EGL 1.3 functionality for 1.2 aware
643 * programs. It is driver agnostic and handled in the main EGL code.
644 */
645 disp->Extensions.KHR_config_attribs = EGL_TRUE;
646
647 _eglComputeVersion(disp);
648 _eglCreateExtensionsString(disp);
649 _eglCreateAPIsString(disp);
650 snprintf(disp->VersionString, sizeof(disp->VersionString),
651 "%d.%d", disp->Version / 10, disp->Version % 10);
652 }
653
654 /* Update applications version of major and minor if not NULL */
655 if ((major != NULL) && (minor != NULL)) {
656 *major = disp->Version / 10;
657 *minor = disp->Version % 10;
658 }
659
660 RETURN_EGL_SUCCESS(disp, EGL_TRUE);
661 }
662
663
664 EGLBoolean EGLAPIENTRY
665 eglTerminate(EGLDisplay dpy)
666 {
667 _EGLDisplay *disp = _eglLockDisplay(dpy);
668
669 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
670
671 if (!disp)
672 RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
673
674 if (disp->Initialized) {
675 disp->Driver->Terminate(disp);
676 /* do not reset disp->Driver */
677 disp->ClientAPIsString[0] = 0;
678 disp->Initialized = EGL_FALSE;
679
680 /* Reset blob cache funcs on terminate. */
681 disp->BlobCacheSet = NULL;
682 disp->BlobCacheGet = NULL;
683 }
684
685 RETURN_EGL_SUCCESS(disp, EGL_TRUE);
686 }
687
688
689 const char * EGLAPIENTRY
690 eglQueryString(EGLDisplay dpy, EGLint name)
691 {
692 _EGLDisplay *disp;
693 const _EGLDriver *drv;
694
695 #if !USE_LIBGLVND
696 if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) {
697 RETURN_EGL_SUCCESS(NULL, _eglGlobal.ClientExtensionString);
698 }
699 #endif
700
701 disp = _eglLockDisplay(dpy);
702 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, NULL);
703 _EGL_CHECK_DISPLAY(disp, NULL, drv);
704
705 switch (name) {
706 case EGL_VENDOR:
707 RETURN_EGL_SUCCESS(disp, _EGL_VENDOR_STRING);
708 case EGL_VERSION:
709 RETURN_EGL_SUCCESS(disp, disp->VersionString);
710 case EGL_EXTENSIONS:
711 RETURN_EGL_SUCCESS(disp, disp->ExtensionsString);
712 case EGL_CLIENT_APIS:
713 RETURN_EGL_SUCCESS(disp, disp->ClientAPIsString);
714 default:
715 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL);
716 }
717 }
718
719
720 EGLBoolean EGLAPIENTRY
721 eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
722 EGLint config_size, EGLint *num_config)
723 {
724 _EGLDisplay *disp = _eglLockDisplay(dpy);
725 const _EGLDriver *drv;
726 EGLBoolean ret;
727
728 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
729
730 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
731
732 if (!num_config)
733 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
734
735 ret = _eglGetConfigs(disp, configs, config_size, num_config);
736
737 RETURN_EGL_EVAL(disp, ret);
738 }
739
740
741 EGLBoolean EGLAPIENTRY
742 eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs,
743 EGLint config_size, EGLint *num_config)
744 {
745 _EGLDisplay *disp = _eglLockDisplay(dpy);
746 const _EGLDriver *drv;
747 EGLBoolean ret;
748
749 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
750
751 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
752
753 if (!num_config)
754 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
755
756 ret = _eglChooseConfig(disp, attrib_list, configs,
757 config_size, num_config);
758
759 RETURN_EGL_EVAL(disp, ret);
760 }
761
762
763 EGLBoolean EGLAPIENTRY
764 eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
765 EGLint attribute, EGLint *value)
766 {
767 _EGLDisplay *disp = _eglLockDisplay(dpy);
768 _EGLConfig *conf = _eglLookupConfig(config, disp);
769 const _EGLDriver *drv;
770 EGLBoolean ret;
771
772 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
773
774 _EGL_CHECK_CONFIG(disp, conf, EGL_FALSE, drv);
775
776 ret = _eglGetConfigAttrib(disp, conf, attribute, value);
777
778 RETURN_EGL_EVAL(disp, ret);
779 }
780
781
782 EGLContext EGLAPIENTRY
783 eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list,
784 const EGLint *attrib_list)
785 {
786 _EGLDisplay *disp = _eglLockDisplay(dpy);
787 _EGLConfig *conf = _eglLookupConfig(config, disp);
788 _EGLContext *share = _eglLookupContext(share_list, disp);
789 const _EGLDriver *drv;
790 _EGLContext *context;
791 EGLContext ret;
792
793 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_CONTEXT);
794
795 _EGL_CHECK_DISPLAY(disp, EGL_NO_CONTEXT, drv);
796
797 if (config != EGL_NO_CONFIG_KHR)
798 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_CONTEXT, drv);
799 else if (!disp->Extensions.KHR_no_config_context)
800 RETURN_EGL_ERROR(disp, EGL_BAD_CONFIG, EGL_NO_CONTEXT);
801
802 if (!share && share_list != EGL_NO_CONTEXT)
803 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
804
805 context = disp->Driver->CreateContext(disp, conf, share, attrib_list);
806 ret = (context) ? _eglLinkContext(context) : EGL_NO_CONTEXT;
807
808 RETURN_EGL_EVAL(disp, ret);
809 }
810
811
812 EGLBoolean EGLAPIENTRY
813 eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
814 {
815 _EGLDisplay *disp = _eglLockDisplay(dpy);
816 _EGLContext *context = _eglLookupContext(ctx, disp);
817 const _EGLDriver *drv;
818 EGLBoolean ret;
819
820 _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE);
821
822 _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv);
823 _eglUnlinkContext(context);
824 ret = disp->Driver->DestroyContext(disp, context);
825
826 RETURN_EGL_EVAL(disp, ret);
827 }
828
829
830 EGLBoolean EGLAPIENTRY
831 eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
832 EGLContext ctx)
833 {
834 _EGLDisplay *disp = _eglLockDisplay(dpy);
835 _EGLContext *context = _eglLookupContext(ctx, disp);
836 _EGLSurface *draw_surf = _eglLookupSurface(draw, disp);
837 _EGLSurface *read_surf = _eglLookupSurface(read, disp);
838 EGLBoolean ret;
839
840 _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE);
841
842 if (!disp)
843 RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
844
845 /* display is allowed to be uninitialized under certain condition */
846 if (!disp->Initialized) {
847 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE ||
848 ctx != EGL_NO_CONTEXT)
849 RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
850 }
851 if (!disp->Driver)
852 RETURN_EGL_SUCCESS(disp, EGL_TRUE);
853
854 if (!context && ctx != EGL_NO_CONTEXT)
855 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
856 if (!draw_surf || !read_surf) {
857 /* From the EGL 1.4 (20130211) spec:
858 *
859 * To release the current context without assigning a new one, set ctx
860 * to EGL_NO_CONTEXT and set draw and read to EGL_NO_SURFACE.
861 */
862 if (!disp->Extensions.KHR_surfaceless_context && ctx != EGL_NO_CONTEXT)
863 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
864
865 if ((!draw_surf && draw != EGL_NO_SURFACE) ||
866 (!read_surf && read != EGL_NO_SURFACE))
867 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
868 if (draw_surf || read_surf)
869 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
870 }
871
872 /* If a native window underlying either draw or read is no longer valid,
873 * an EGL_BAD_NATIVE_WINDOW error is generated.
874 */
875 if (draw_surf && draw_surf->Lost)
876 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE);
877 if (read_surf && read_surf->Lost)
878 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE);
879
880 ret = disp->Driver->MakeCurrent(disp, draw_surf, read_surf, context);
881
882 RETURN_EGL_EVAL(disp, ret);
883 }
884
885
886 EGLBoolean EGLAPIENTRY
887 eglQueryContext(EGLDisplay dpy, EGLContext ctx,
888 EGLint attribute, EGLint *value)
889 {
890 _EGLDisplay *disp = _eglLockDisplay(dpy);
891 _EGLContext *context = _eglLookupContext(ctx, disp);
892 const _EGLDriver *drv;
893 EGLBoolean ret;
894
895 _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE);
896
897 _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv);
898
899 ret = _eglQueryContext(context, attribute, value);
900
901 RETURN_EGL_EVAL(disp, ret);
902 }
903
904
905 /* In EGL specs 1.4 and 1.5, at the end of sections 3.5.1 and 3.5.4, it says
906 * that if native_surface was already used to create a window or pixmap, we
907 * can't create a new one. This is what this function checks for.
908 */
909 static bool
910 _eglNativeSurfaceAlreadyUsed(_EGLDisplay *disp, void *native_surface)
911 {
912 _EGLResource *list;
913
914 list = disp->ResourceLists[_EGL_RESOURCE_SURFACE];
915 while (list) {
916 _EGLSurface *surf = (_EGLSurface *) list;
917
918 list = list->Next;
919
920 if (surf->Type == EGL_PBUFFER_BIT)
921 continue;
922
923 if (surf->NativeSurface == native_surface)
924 return true;
925 }
926
927 return false;
928 }
929
930
931 static EGLSurface
932 _eglCreateWindowSurfaceCommon(_EGLDisplay *disp, EGLConfig config,
933 void *native_window, const EGLint *attrib_list)
934 {
935 _EGLConfig *conf = _eglLookupConfig(config, disp);
936 const _EGLDriver *drv;
937 _EGLSurface *surf;
938 EGLSurface ret;
939
940
941 if (native_window == NULL)
942 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
943
944 if (disp && (disp->Platform == _EGL_PLATFORM_SURFACELESS ||
945 disp->Platform == _EGL_PLATFORM_DEVICE)) {
946 /* From the EGL_MESA_platform_surfaceless spec (v1):
947 *
948 * eglCreatePlatformWindowSurface fails when called with a <display>
949 * that belongs to the surfaceless platform. It returns
950 * EGL_NO_SURFACE and generates EGL_BAD_NATIVE_WINDOW. The
951 * justification for this unconditional failure is that the
952 * surfaceless platform has no native windows, and therefore the
953 * <native_window> parameter is always invalid.
954 *
955 * This check must occur before checking the EGLConfig, which emits
956 * EGL_BAD_CONFIG.
957 */
958 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
959 }
960
961 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
962
963 if ((conf->SurfaceType & EGL_WINDOW_BIT) == 0)
964 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE);
965
966 if (_eglNativeSurfaceAlreadyUsed(disp, native_window))
967 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
968
969 surf = disp->Driver->CreateWindowSurface(disp, conf, native_window, attrib_list);
970 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
971
972 RETURN_EGL_EVAL(disp, ret);
973 }
974
975
976 EGLSurface EGLAPIENTRY
977 eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
978 EGLNativeWindowType window, const EGLint *attrib_list)
979 {
980 _EGLDisplay *disp = _eglLockDisplay(dpy);
981
982 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
983 STATIC_ASSERT(sizeof(void*) == sizeof(window));
984 return _eglCreateWindowSurfaceCommon(disp, config, (void*) window,
985 attrib_list);
986 }
987
988 static void *
989 _fixupNativeWindow(_EGLDisplay *disp, void *native_window)
990 {
991 #ifdef HAVE_X11_PLATFORM
992 if (disp && disp->Platform == _EGL_PLATFORM_X11 && native_window != NULL) {
993 /* The `native_window` parameter for the X11 platform differs between
994 * eglCreateWindowSurface() and eglCreatePlatformPixmapSurfaceEXT(). In
995 * eglCreateWindowSurface(), the type of `native_window` is an Xlib
996 * `Window`. In eglCreatePlatformWindowSurfaceEXT(), the type is
997 * `Window*`. Convert `Window*` to `Window` because that's what
998 * dri2_x11_create_window_surface() expects.
999 */
1000 return (void *)(* (Window*) native_window);
1001 }
1002 #endif
1003 return native_window;
1004 }
1005
1006 static EGLSurface EGLAPIENTRY
1007 eglCreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config,
1008 void *native_window,
1009 const EGLint *attrib_list)
1010 {
1011 _EGLDisplay *disp = _eglLockDisplay(dpy);
1012
1013 native_window = _fixupNativeWindow(disp, native_window);
1014
1015 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1016 return _eglCreateWindowSurfaceCommon(disp, config, native_window,
1017 attrib_list);
1018 }
1019
1020
1021 EGLSurface EGLAPIENTRY
1022 eglCreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config,
1023 void *native_window,
1024 const EGLAttrib *attrib_list)
1025 {
1026 _EGLDisplay *disp = _eglLockDisplay(dpy);
1027 EGLSurface surface;
1028 EGLint *int_attribs;
1029
1030 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1031
1032 int_attribs = _eglConvertAttribsToInt(attrib_list);
1033 if (attrib_list && !int_attribs)
1034 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
1035
1036 native_window = _fixupNativeWindow(disp, native_window);
1037 surface = _eglCreateWindowSurfaceCommon(disp, config, native_window,
1038 int_attribs);
1039 free(int_attribs);
1040 return surface;
1041 }
1042
1043 static void *
1044 _fixupNativePixmap(_EGLDisplay *disp, void *native_pixmap)
1045 {
1046 #ifdef HAVE_X11_PLATFORM
1047 /* The `native_pixmap` parameter for the X11 platform differs between
1048 * eglCreatePixmapSurface() and eglCreatePlatformPixmapSurfaceEXT(). In
1049 * eglCreatePixmapSurface(), the type of `native_pixmap` is an Xlib
1050 * `Pixmap`. In eglCreatePlatformPixmapSurfaceEXT(), the type is
1051 * `Pixmap*`. Convert `Pixmap*` to `Pixmap` because that's what
1052 * dri2_x11_create_pixmap_surface() expects.
1053 */
1054 if (disp && disp->Platform == _EGL_PLATFORM_X11 && native_pixmap != NULL)
1055 return (void *)(* (Pixmap*) native_pixmap);
1056 #endif
1057 return native_pixmap;
1058 }
1059
1060 static EGLSurface
1061 _eglCreatePixmapSurfaceCommon(_EGLDisplay *disp, EGLConfig config,
1062 void *native_pixmap, const EGLint *attrib_list)
1063 {
1064 _EGLConfig *conf = _eglLookupConfig(config, disp);
1065 const _EGLDriver *drv;
1066 _EGLSurface *surf;
1067 EGLSurface ret;
1068
1069 if (disp && (disp->Platform == _EGL_PLATFORM_SURFACELESS ||
1070 disp->Platform == _EGL_PLATFORM_DEVICE)) {
1071 /* From the EGL_MESA_platform_surfaceless spec (v1):
1072 *
1073 * [Like eglCreatePlatformWindowSurface,] eglCreatePlatformPixmapSurface
1074 * also fails when called with a <display> that belongs to the
1075 * surfaceless platform. It returns EGL_NO_SURFACE and generates
1076 * EGL_BAD_NATIVE_PIXMAP.
1077 *
1078 * This check must occur before checking the EGLConfig, which emits
1079 * EGL_BAD_CONFIG.
1080 */
1081 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
1082 }
1083
1084 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
1085
1086 if ((conf->SurfaceType & EGL_PIXMAP_BIT) == 0)
1087 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE);
1088
1089 if (native_pixmap == NULL)
1090 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
1091
1092 if (_eglNativeSurfaceAlreadyUsed(disp, native_pixmap))
1093 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
1094
1095 surf = disp->Driver->CreatePixmapSurface(disp, conf, native_pixmap, attrib_list);
1096 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1097
1098 RETURN_EGL_EVAL(disp, ret);
1099 }
1100
1101
1102 EGLSurface EGLAPIENTRY
1103 eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
1104 EGLNativePixmapType pixmap, const EGLint *attrib_list)
1105 {
1106 _EGLDisplay *disp = _eglLockDisplay(dpy);
1107
1108 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1109 STATIC_ASSERT(sizeof(void*) == sizeof(pixmap));
1110 return _eglCreatePixmapSurfaceCommon(disp, config, (void*) pixmap,
1111 attrib_list);
1112 }
1113
1114 static EGLSurface EGLAPIENTRY
1115 eglCreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config,
1116 void *native_pixmap,
1117 const EGLint *attrib_list)
1118 {
1119 _EGLDisplay *disp = _eglLockDisplay(dpy);
1120
1121 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1122 native_pixmap = _fixupNativePixmap(disp, native_pixmap);
1123 return _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap,
1124 attrib_list);
1125 }
1126
1127
1128 EGLSurface EGLAPIENTRY
1129 eglCreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config,
1130 void *native_pixmap,
1131 const EGLAttrib *attrib_list)
1132 {
1133 _EGLDisplay *disp = _eglLockDisplay(dpy);
1134 EGLSurface surface;
1135 EGLint *int_attribs;
1136
1137 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1138
1139 int_attribs = _eglConvertAttribsToInt(attrib_list);
1140 if (attrib_list && !int_attribs)
1141 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
1142
1143 native_pixmap = _fixupNativePixmap(disp, native_pixmap);
1144 surface = _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap,
1145 int_attribs);
1146 free(int_attribs);
1147 return surface;
1148 }
1149
1150
1151 EGLSurface EGLAPIENTRY
1152 eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
1153 const EGLint *attrib_list)
1154 {
1155 _EGLDisplay *disp = _eglLockDisplay(dpy);
1156 _EGLConfig *conf = _eglLookupConfig(config, disp);
1157 const _EGLDriver *drv;
1158 _EGLSurface *surf;
1159 EGLSurface ret;
1160
1161 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1162 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
1163
1164 if ((conf->SurfaceType & EGL_PBUFFER_BIT) == 0)
1165 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE);
1166
1167 surf = disp->Driver->CreatePbufferSurface(disp, conf, attrib_list);
1168 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1169
1170 RETURN_EGL_EVAL(disp, ret);
1171 }
1172
1173
1174 EGLBoolean EGLAPIENTRY
1175 eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
1176 {
1177 _EGLDisplay *disp = _eglLockDisplay(dpy);
1178 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1179 const _EGLDriver *drv;
1180 EGLBoolean ret;
1181
1182 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1183 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1184 _eglUnlinkSurface(surf);
1185 ret = disp->Driver->DestroySurface(disp, surf);
1186
1187 RETURN_EGL_EVAL(disp, ret);
1188 }
1189
1190 EGLBoolean EGLAPIENTRY
1191 eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
1192 EGLint attribute, EGLint *value)
1193 {
1194 _EGLDisplay *disp = _eglLockDisplay(dpy);
1195 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1196 const _EGLDriver *drv;
1197 EGLBoolean ret;
1198
1199 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1200 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1201
1202 if (disp->Driver->QuerySurface)
1203 ret = disp->Driver->QuerySurface(disp, surf, attribute, value);
1204 else
1205 ret = _eglQuerySurface(disp, surf, attribute, value);
1206
1207 RETURN_EGL_EVAL(disp, ret);
1208 }
1209
1210 EGLBoolean EGLAPIENTRY
1211 eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
1212 EGLint attribute, EGLint value)
1213 {
1214 _EGLDisplay *disp = _eglLockDisplay(dpy);
1215 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1216 const _EGLDriver *drv;
1217 EGLBoolean ret;
1218
1219 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1220 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1221
1222 ret = _eglSurfaceAttrib(disp, surf, attribute, value);
1223
1224 RETURN_EGL_EVAL(disp, ret);
1225 }
1226
1227
1228 EGLBoolean EGLAPIENTRY
1229 eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1230 {
1231 _EGLDisplay *disp = _eglLockDisplay(dpy);
1232 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1233 const _EGLDriver *drv;
1234 EGLBoolean ret;
1235
1236 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1237 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1238 ret = disp->Driver->BindTexImage(disp, surf, buffer);
1239
1240 RETURN_EGL_EVAL(disp, ret);
1241 }
1242
1243
1244 EGLBoolean EGLAPIENTRY
1245 eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1246 {
1247 _EGLDisplay *disp = _eglLockDisplay(dpy);
1248 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1249 const _EGLDriver *drv;
1250 EGLBoolean ret;
1251
1252 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1253 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1254 ret = disp->Driver->ReleaseTexImage(disp, surf, buffer);
1255
1256 RETURN_EGL_EVAL(disp, ret);
1257 }
1258
1259
1260 EGLBoolean EGLAPIENTRY
1261 eglSwapInterval(EGLDisplay dpy, EGLint interval)
1262 {
1263 _EGLDisplay *disp = _eglLockDisplay(dpy);
1264 _EGLContext *ctx = _eglGetCurrentContext();
1265 _EGLSurface *surf = ctx ? ctx->DrawSurface : NULL;
1266 const _EGLDriver *drv;
1267 EGLBoolean ret;
1268
1269 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1270 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1271
1272 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1273 ctx->Resource.Display != disp)
1274 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
1275
1276 if (_eglGetSurfaceHandle(surf) == EGL_NO_SURFACE)
1277 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1278
1279 if (surf->Type != EGL_WINDOW_BIT)
1280 RETURN_EGL_EVAL(disp, EGL_TRUE);
1281
1282 interval = CLAMP(interval,
1283 surf->Config->MinSwapInterval,
1284 surf->Config->MaxSwapInterval);
1285
1286 if (surf->SwapInterval != interval) {
1287 if (disp->Driver->SwapInterval)
1288 ret = disp->Driver->SwapInterval(disp, surf, interval);
1289 else
1290 ret = _eglSwapInterval(disp, surf, interval);
1291 }
1292 else {
1293 ret = EGL_TRUE;
1294 }
1295
1296 if (ret)
1297 surf->SwapInterval = interval;
1298
1299 RETURN_EGL_EVAL(disp, ret);
1300 }
1301
1302
1303 EGLBoolean EGLAPIENTRY
1304 eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1305 {
1306 _EGLContext *ctx = _eglGetCurrentContext();
1307 _EGLDisplay *disp = _eglLockDisplay(dpy);
1308 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1309 const _EGLDriver *drv;
1310 EGLBoolean ret;
1311
1312 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1313 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1314
1315 /* surface must be bound to current context in EGL 1.4 */
1316 #ifndef _EGL_BUILT_IN_DRIVER_HAIKU
1317 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1318 surf != ctx->DrawSurface)
1319 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1320 #endif
1321
1322 if (surf->Type != EGL_WINDOW_BIT)
1323 RETURN_EGL_EVAL(disp, EGL_TRUE);
1324
1325 /* From the EGL 1.5 spec:
1326 *
1327 * If eglSwapBuffers is called and the native window associated with
1328 * surface is no longer valid, an EGL_BAD_NATIVE_WINDOW error is
1329 * generated.
1330 */
1331 if (surf->Lost)
1332 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE);
1333
1334 ret = disp->Driver->SwapBuffers(disp, surf);
1335
1336 /* EGL_KHR_partial_update
1337 * Frame boundary successfully reached,
1338 * reset damage region and reset BufferAgeRead
1339 */
1340 if (ret) {
1341 surf->SetDamageRegionCalled = EGL_FALSE;
1342 surf->BufferAgeRead = EGL_FALSE;
1343 }
1344
1345 RETURN_EGL_EVAL(disp, ret);
1346 }
1347
1348
1349 static EGLBoolean
1350 _eglSwapBuffersWithDamageCommon(_EGLDisplay *disp, _EGLSurface *surf,
1351 const EGLint *rects, EGLint n_rects)
1352 {
1353 _EGLContext *ctx = _eglGetCurrentContext();
1354 const _EGLDriver *drv;
1355 EGLBoolean ret;
1356
1357 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1358
1359 /* surface must be bound to current context in EGL 1.4 */
1360 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1361 surf != ctx->DrawSurface)
1362 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1363
1364 if (surf->Type != EGL_WINDOW_BIT)
1365 RETURN_EGL_EVAL(disp, EGL_TRUE);
1366
1367 if ((n_rects > 0 && rects == NULL) || n_rects < 0)
1368 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1369
1370 ret = disp->Driver->SwapBuffersWithDamageEXT(disp, surf, rects, n_rects);
1371
1372 /* EGL_KHR_partial_update
1373 * Frame boundary successfully reached,
1374 * reset damage region and reset BufferAgeRead
1375 */
1376 if (ret) {
1377 surf->SetDamageRegionCalled = EGL_FALSE;
1378 surf->BufferAgeRead = EGL_FALSE;
1379 }
1380
1381 RETURN_EGL_EVAL(disp, ret);
1382 }
1383
1384 static EGLBoolean EGLAPIENTRY
1385 eglSwapBuffersWithDamageEXT(EGLDisplay dpy, EGLSurface surface,
1386 const EGLint *rects, EGLint n_rects)
1387 {
1388 _EGLDisplay *disp = _eglLockDisplay(dpy);
1389 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1390 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1391 return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects);
1392 }
1393
1394 static EGLBoolean EGLAPIENTRY
1395 eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface surface,
1396 const EGLint *rects, EGLint n_rects)
1397 {
1398 _EGLDisplay *disp = _eglLockDisplay(dpy);
1399 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1400 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1401 return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects);
1402 }
1403
1404 /**
1405 * Clamp the rectangles so that they lie within the surface.
1406 */
1407
1408 static void
1409 _eglSetDamageRegionKHRClampRects(_EGLSurface* surf,
1410 EGLint *rects, EGLint n_rects)
1411 {
1412 EGLint i;
1413 EGLint surf_height = surf->Height;
1414 EGLint surf_width = surf->Width;
1415
1416 for (i = 0; i < (4 * n_rects); i += 4) {
1417 EGLint x1, y1, x2, y2;
1418 x1 = rects[i];
1419 y1 = rects[i + 1];
1420 x2 = rects[i + 2] + x1;
1421 y2 = rects[i + 3] + y1;
1422
1423 rects[i] = CLAMP(x1, 0, surf_width);
1424 rects[i + 1] = CLAMP(y1, 0, surf_height);
1425 rects[i + 2] = CLAMP(x2, 0, surf_width) - rects[i];
1426 rects[i + 3] = CLAMP(y2, 0, surf_height) - rects[i + 1];
1427 }
1428 }
1429
1430 static EGLBoolean EGLAPIENTRY
1431 eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
1432 EGLint *rects, EGLint n_rects)
1433 {
1434 _EGLDisplay *disp = _eglLockDisplay(dpy);
1435 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1436 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1437 _EGLContext *ctx = _eglGetCurrentContext();
1438 const _EGLDriver *drv;
1439 EGLBoolean ret;
1440 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1441
1442 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1443 surf->Type != EGL_WINDOW_BIT ||
1444 ctx->DrawSurface != surf ||
1445 surf->SwapBehavior != EGL_BUFFER_DESTROYED)
1446 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
1447
1448 /* If the damage region is already set or
1449 * buffer age is not queried between
1450 * frame boundaries, throw bad access error
1451 */
1452
1453 if (surf->SetDamageRegionCalled || !surf->BufferAgeRead)
1454 RETURN_EGL_ERROR(disp, EGL_BAD_ACCESS, EGL_FALSE);
1455
1456 _eglSetDamageRegionKHRClampRects(surf, rects, n_rects);
1457 ret = disp->Driver->SetDamageRegion(disp, surf, rects, n_rects);
1458
1459 if (ret)
1460 surf->SetDamageRegionCalled = EGL_TRUE;
1461
1462 RETURN_EGL_EVAL(disp, ret);
1463 }
1464
1465 EGLBoolean EGLAPIENTRY
1466 eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1467 {
1468 _EGLDisplay *disp = _eglLockDisplay(dpy);
1469 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1470 const _EGLDriver *drv;
1471 EGLBoolean ret;
1472 void *native_pixmap_ptr;
1473
1474 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1475 STATIC_ASSERT(sizeof(void*) == sizeof(target));
1476 native_pixmap_ptr = (void*) target;
1477
1478 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1479 ret = disp->Driver->CopyBuffers(disp, surf, native_pixmap_ptr);
1480
1481 RETURN_EGL_EVAL(disp, ret);
1482 }
1483
1484
1485 static EGLBoolean
1486 _eglWaitClientCommon(void)
1487 {
1488 _EGLContext *ctx = _eglGetCurrentContext();
1489 _EGLDisplay *disp;
1490 EGLBoolean ret;
1491
1492 if (!ctx)
1493 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1494
1495 disp = ctx->Resource.Display;
1496 mtx_lock(&disp->Mutex);
1497
1498 /* let bad current context imply bad current surface */
1499 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1500 _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
1501 RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
1502
1503 /* a valid current context implies an initialized current display */
1504 assert(disp->Initialized);
1505 ret = disp->Driver->WaitClient(disp, ctx);
1506
1507 RETURN_EGL_EVAL(disp, ret);
1508 }
1509
1510 EGLBoolean EGLAPIENTRY
1511 eglWaitClient(void)
1512 {
1513 _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE);
1514 return _eglWaitClientCommon();
1515 }
1516
1517 EGLBoolean EGLAPIENTRY
1518 eglWaitGL(void)
1519 {
1520 /* Since we only support OpenGL and GLES, eglWaitGL is equivalent to eglWaitClient. */
1521 _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE);
1522 return _eglWaitClientCommon();
1523 }
1524
1525
1526 EGLBoolean EGLAPIENTRY
1527 eglWaitNative(EGLint engine)
1528 {
1529 _EGLContext *ctx = _eglGetCurrentContext();
1530 _EGLDisplay *disp;
1531 EGLBoolean ret;
1532
1533 if (!ctx)
1534 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1535
1536 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
1537
1538 disp = ctx->Resource.Display;
1539 mtx_lock(&disp->Mutex);
1540
1541 /* let bad current context imply bad current surface */
1542 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1543 _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
1544 RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
1545
1546 /* a valid current context implies an initialized current display */
1547 assert(disp->Initialized);
1548 ret = disp->Driver->WaitNative(engine);
1549
1550 RETURN_EGL_EVAL(disp, ret);
1551 }
1552
1553
1554 EGLDisplay EGLAPIENTRY
1555 eglGetCurrentDisplay(void)
1556 {
1557 _EGLContext *ctx = _eglGetCurrentContext();
1558 EGLDisplay ret;
1559
1560 ret = (ctx) ? _eglGetDisplayHandle(ctx->Resource.Display) : EGL_NO_DISPLAY;
1561
1562 RETURN_EGL_SUCCESS(NULL, ret);
1563 }
1564
1565
1566 EGLContext EGLAPIENTRY
1567 eglGetCurrentContext(void)
1568 {
1569 _EGLContext *ctx = _eglGetCurrentContext();
1570 EGLContext ret;
1571
1572 ret = _eglGetContextHandle(ctx);
1573
1574 RETURN_EGL_SUCCESS(NULL, ret);
1575 }
1576
1577
1578 EGLSurface EGLAPIENTRY
1579 eglGetCurrentSurface(EGLint readdraw)
1580 {
1581 _EGLContext *ctx = _eglGetCurrentContext();
1582 EGLint err = EGL_SUCCESS;
1583 _EGLSurface *surf;
1584 EGLSurface ret;
1585
1586 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_NO_SURFACE);
1587
1588 if (!ctx)
1589 RETURN_EGL_SUCCESS(NULL, EGL_NO_SURFACE);
1590
1591 switch (readdraw) {
1592 case EGL_DRAW:
1593 surf = ctx->DrawSurface;
1594 break;
1595 case EGL_READ:
1596 surf = ctx->ReadSurface;
1597 break;
1598 default:
1599 surf = NULL;
1600 err = EGL_BAD_PARAMETER;
1601 break;
1602 }
1603
1604 ret = _eglGetSurfaceHandle(surf);
1605
1606 RETURN_EGL_ERROR(NULL, err, ret);
1607 }
1608
1609
1610 EGLint EGLAPIENTRY
1611 eglGetError(void)
1612 {
1613 _EGLThreadInfo *t = _eglGetCurrentThread();
1614 EGLint e = t->LastError;
1615 if (!_eglIsCurrentThreadDummy())
1616 t->LastError = EGL_SUCCESS;
1617 return e;
1618 }
1619
1620
1621 /**
1622 ** EGL 1.2
1623 **/
1624
1625 /**
1626 * Specify the client API to use for subsequent calls including:
1627 * eglCreateContext()
1628 * eglGetCurrentContext()
1629 * eglGetCurrentDisplay()
1630 * eglGetCurrentSurface()
1631 * eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT)
1632 * eglWaitClient()
1633 * eglWaitNative()
1634 * See section 3.7 "Rendering Context" in the EGL specification for details.
1635 */
1636 EGLBoolean EGLAPIENTRY
1637 eglBindAPI(EGLenum api)
1638 {
1639 _EGLThreadInfo *t;
1640
1641 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
1642
1643 t = _eglGetCurrentThread();
1644 if (_eglIsCurrentThreadDummy())
1645 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
1646
1647 if (!_eglIsApiValid(api))
1648 RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, EGL_FALSE);
1649
1650 t->CurrentAPI = api;
1651
1652 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1653 }
1654
1655
1656 /**
1657 * Return the last value set with eglBindAPI().
1658 */
1659 EGLenum EGLAPIENTRY
1660 eglQueryAPI(void)
1661 {
1662 _EGLThreadInfo *t = _eglGetCurrentThread();
1663 EGLenum ret;
1664
1665 /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */
1666 ret = t->CurrentAPI;
1667
1668 RETURN_EGL_SUCCESS(NULL, ret);
1669 }
1670
1671
1672 EGLSurface EGLAPIENTRY
1673 eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
1674 EGLClientBuffer buffer, EGLConfig config,
1675 const EGLint *attrib_list)
1676 {
1677 _EGLDisplay *disp = _eglLockDisplay(dpy);
1678 _EGLConfig *conf = _eglLookupConfig(config, disp);
1679 const _EGLDriver *drv;
1680
1681 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1682
1683 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
1684
1685 /* OpenVG is not supported */
1686 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
1687 }
1688
1689
1690 EGLBoolean EGLAPIENTRY
1691 eglReleaseThread(void)
1692 {
1693 /* unbind current contexts */
1694 if (!_eglIsCurrentThreadDummy()) {
1695 _EGLThreadInfo *t = _eglGetCurrentThread();
1696 _EGLContext *ctx = t->CurrentContext;
1697
1698 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
1699
1700 if (ctx) {
1701 _EGLDisplay *disp = ctx->Resource.Display;
1702
1703 mtx_lock(&disp->Mutex);
1704 (void) disp->Driver->MakeCurrent(disp, NULL, NULL, NULL);
1705 mtx_unlock(&disp->Mutex);
1706 }
1707 }
1708
1709 _eglDestroyCurrentThread();
1710
1711 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1712 }
1713
1714
1715 static EGLImage
1716 _eglCreateImageCommon(_EGLDisplay *disp, EGLContext ctx, EGLenum target,
1717 EGLClientBuffer buffer, const EGLint *attr_list)
1718 {
1719 _EGLContext *context = _eglLookupContext(ctx, disp);
1720 const _EGLDriver *drv;
1721 _EGLImage *img;
1722 EGLImage ret;
1723
1724 _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
1725 if (!disp->Extensions.KHR_image_base)
1726 RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
1727 if (!context && ctx != EGL_NO_CONTEXT)
1728 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1729 /* "If <target> is EGL_LINUX_DMA_BUF_EXT, <dpy> must be a valid display,
1730 * <ctx> must be EGL_NO_CONTEXT..."
1731 */
1732 if (ctx != EGL_NO_CONTEXT && target == EGL_LINUX_DMA_BUF_EXT)
1733 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1734
1735 img = disp->Driver->CreateImageKHR(disp, context, target, buffer, attr_list);
1736 ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
1737
1738 RETURN_EGL_EVAL(disp, ret);
1739 }
1740
1741 static EGLImage EGLAPIENTRY
1742 eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1743 EGLClientBuffer buffer, const EGLint *attr_list)
1744 {
1745 _EGLDisplay *disp = _eglLockDisplay(dpy);
1746 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR);
1747 return _eglCreateImageCommon(disp, ctx, target, buffer, attr_list);
1748 }
1749
1750
1751 EGLImage EGLAPIENTRY
1752 eglCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1753 EGLClientBuffer buffer, const EGLAttrib *attr_list)
1754 {
1755 _EGLDisplay *disp = _eglLockDisplay(dpy);
1756 EGLImage image;
1757 EGLint *int_attribs;
1758
1759 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR);
1760
1761 int_attribs = _eglConvertAttribsToInt(attr_list);
1762 if (attr_list && !int_attribs)
1763 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_IMAGE);
1764
1765 image = _eglCreateImageCommon(disp, ctx, target, buffer, int_attribs);
1766 free(int_attribs);
1767 return image;
1768 }
1769
1770
1771 static EGLBoolean
1772 _eglDestroyImageCommon(_EGLDisplay *disp, _EGLImage *img)
1773 {
1774 const _EGLDriver *drv;
1775 EGLBoolean ret;
1776
1777 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1778 if (!disp->Extensions.KHR_image_base)
1779 RETURN_EGL_EVAL(disp, EGL_FALSE);
1780 if (!img)
1781 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1782
1783 _eglUnlinkImage(img);
1784 ret = disp->Driver->DestroyImageKHR(disp, img);
1785
1786 RETURN_EGL_EVAL(disp, ret);
1787 }
1788
1789 EGLBoolean EGLAPIENTRY
1790 eglDestroyImage(EGLDisplay dpy, EGLImage image)
1791 {
1792 _EGLDisplay *disp = _eglLockDisplay(dpy);
1793 _EGLImage *img = _eglLookupImage(image, disp);
1794 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
1795 return _eglDestroyImageCommon(disp, img);
1796 }
1797
1798 static EGLBoolean EGLAPIENTRY
1799 eglDestroyImageKHR(EGLDisplay dpy, EGLImage image)
1800 {
1801 _EGLDisplay *disp = _eglLockDisplay(dpy);
1802 _EGLImage *img = _eglLookupImage(image, disp);
1803 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
1804 return _eglDestroyImageCommon(disp, img);
1805 }
1806
1807
1808 static EGLSync
1809 _eglCreateSync(_EGLDisplay *disp, EGLenum type, const EGLAttrib *attrib_list,
1810 EGLBoolean orig_is_EGLAttrib,
1811 EGLenum invalid_type_error)
1812 {
1813 _EGLContext *ctx = _eglGetCurrentContext();
1814 const _EGLDriver *drv;
1815 _EGLSync *sync;
1816 EGLSync ret;
1817
1818 _EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv);
1819
1820 if (!disp->Extensions.KHR_cl_event2 && orig_is_EGLAttrib) {
1821 /* There exist two EGLAttrib variants of eglCreateSync*:
1822 * eglCreateSync64KHR which requires EGL_KHR_cl_event2, and eglCreateSync
1823 * which requires EGL 1.5. Here we use the presence of EGL_KHR_cl_event2
1824 * support as a proxy for EGL 1.5 support, even though that's not
1825 * entirely correct (though _eglComputeVersion does the same).
1826 *
1827 * The EGL spec provides no guidance on how to handle unsupported
1828 * functions. EGL_BAD_MATCH seems reasonable.
1829 */
1830 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1831 }
1832
1833 /* If type is EGL_SYNC_FENCE and no context is current for the bound API
1834 * (i.e., eglGetCurrentContext returns EGL_NO_CONTEXT ), an EGL_BAD_MATCH
1835 * error is generated.
1836 */
1837 if (!ctx &&
1838 (type == EGL_SYNC_FENCE_KHR || type == EGL_SYNC_NATIVE_FENCE_ANDROID))
1839 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1840
1841 /* return an error if the client API doesn't support GL_[OES|MESA]_EGL_sync. */
1842 if (ctx && (ctx->Resource.Display != disp ||
1843 (ctx->ClientAPI != EGL_OPENGL_ES_API &&
1844 ctx->ClientAPI != EGL_OPENGL_API)))
1845 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1846
1847 switch (type) {
1848 case EGL_SYNC_FENCE_KHR:
1849 if (!disp->Extensions.KHR_fence_sync)
1850 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1851 break;
1852 case EGL_SYNC_REUSABLE_KHR:
1853 if (!disp->Extensions.KHR_reusable_sync)
1854 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1855 break;
1856 case EGL_SYNC_CL_EVENT_KHR:
1857 if (!disp->Extensions.KHR_cl_event2)
1858 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1859 break;
1860 case EGL_SYNC_NATIVE_FENCE_ANDROID:
1861 if (!disp->Extensions.ANDROID_native_fence_sync)
1862 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1863 break;
1864 default:
1865 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1866 }
1867
1868 sync = disp->Driver->CreateSyncKHR(disp, type, attrib_list);
1869 ret = (sync) ? _eglLinkSync(sync) : EGL_NO_SYNC_KHR;
1870
1871 RETURN_EGL_EVAL(disp, ret);
1872 }
1873
1874
1875 static EGLSync EGLAPIENTRY
1876 eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *int_list)
1877 {
1878 _EGLDisplay *disp = _eglLockDisplay(dpy);
1879 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
1880
1881 EGLSync sync;
1882 EGLAttrib *attrib_list;
1883 EGLint err;
1884
1885 if (sizeof(int_list[0]) == sizeof(attrib_list[0])) {
1886 attrib_list = (EGLAttrib *) int_list;
1887 } else {
1888 err = _eglConvertIntsToAttribs(int_list, &attrib_list);
1889 if (err != EGL_SUCCESS)
1890 RETURN_EGL_ERROR(disp, err, EGL_NO_SYNC);
1891 }
1892
1893 sync = _eglCreateSync(disp, type, attrib_list, EGL_FALSE,
1894 EGL_BAD_ATTRIBUTE);
1895
1896 if (sizeof(int_list[0]) != sizeof(attrib_list[0]))
1897 free(attrib_list);
1898
1899 /* Don't double-unlock the display. _eglCreateSync already unlocked it. */
1900 return sync;
1901 }
1902
1903
1904 static EGLSync EGLAPIENTRY
1905 eglCreateSync64KHR(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
1906 {
1907 _EGLDisplay *disp = _eglLockDisplay(dpy);
1908 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
1909 return _eglCreateSync(disp, type, attrib_list, EGL_TRUE,
1910 EGL_BAD_ATTRIBUTE);
1911 }
1912
1913
1914 EGLSync EGLAPIENTRY
1915 eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
1916 {
1917 _EGLDisplay *disp = _eglLockDisplay(dpy);
1918 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
1919 return _eglCreateSync(disp, type, attrib_list, EGL_TRUE,
1920 EGL_BAD_PARAMETER);
1921 }
1922
1923
1924 static EGLBoolean
1925 _eglDestroySync(_EGLDisplay *disp, _EGLSync *s)
1926 {
1927 const _EGLDriver *drv;
1928 EGLBoolean ret;
1929
1930 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1931 assert(disp->Extensions.KHR_reusable_sync ||
1932 disp->Extensions.KHR_fence_sync ||
1933 disp->Extensions.ANDROID_native_fence_sync);
1934
1935 _eglUnlinkSync(s);
1936 ret = disp->Driver->DestroySyncKHR(disp, s);
1937
1938 RETURN_EGL_EVAL(disp, ret);
1939 }
1940
1941 EGLBoolean EGLAPIENTRY
1942 eglDestroySync(EGLDisplay dpy, EGLSync sync)
1943 {
1944 _EGLDisplay *disp = _eglLockDisplay(dpy);
1945 _EGLSync *s = _eglLookupSync(sync, disp);
1946 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
1947 return _eglDestroySync(disp, s);
1948 }
1949
1950 static EGLBoolean EGLAPIENTRY
1951 eglDestroySyncKHR(EGLDisplay dpy, EGLSync sync)
1952 {
1953 _EGLDisplay *disp = _eglLockDisplay(dpy);
1954 _EGLSync *s = _eglLookupSync(sync, disp);
1955 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
1956 return _eglDestroySync(disp, s);
1957 }
1958
1959
1960 static EGLint
1961 _eglClientWaitSyncCommon(_EGLDisplay *disp, EGLDisplay dpy,
1962 _EGLSync *s, EGLint flags, EGLTime timeout)
1963 {
1964 const _EGLDriver *drv;
1965 EGLint ret;
1966
1967 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1968 assert(disp->Extensions.KHR_reusable_sync ||
1969 disp->Extensions.KHR_fence_sync ||
1970 disp->Extensions.ANDROID_native_fence_sync);
1971
1972 if (s->SyncStatus == EGL_SIGNALED_KHR)
1973 RETURN_EGL_EVAL(disp, EGL_CONDITION_SATISFIED_KHR);
1974
1975 /* if sync type is EGL_SYNC_REUSABLE_KHR, dpy should be
1976 * unlocked here to allow other threads also to be able to
1977 * go into waiting state.
1978 */
1979
1980 if (s->Type == EGL_SYNC_REUSABLE_KHR)
1981 _eglUnlockDisplay(dpy);
1982
1983 ret = disp->Driver->ClientWaitSyncKHR(disp, s, flags, timeout);
1984
1985 /*
1986 * 'disp' is already unlocked for reusable sync type,
1987 * so passing 'NULL' to bypass unlocking display.
1988 */
1989 if (s->Type == EGL_SYNC_REUSABLE_KHR)
1990 RETURN_EGL_EVAL(NULL, ret);
1991 else
1992 RETURN_EGL_EVAL(disp, ret);
1993 }
1994
1995 EGLint EGLAPIENTRY
1996 eglClientWaitSync(EGLDisplay dpy, EGLSync sync,
1997 EGLint flags, EGLTime timeout)
1998 {
1999 _EGLDisplay *disp = _eglLockDisplay(dpy);
2000 _EGLSync *s = _eglLookupSync(sync, disp);
2001 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2002 return _eglClientWaitSyncCommon(disp, dpy, s, flags, timeout);
2003 }
2004
2005 static EGLint EGLAPIENTRY
2006 eglClientWaitSyncKHR(EGLDisplay dpy, EGLSync sync,
2007 EGLint flags, EGLTime timeout)
2008 {
2009 _EGLDisplay *disp = _eglLockDisplay(dpy);
2010 _EGLSync *s = _eglLookupSync(sync, disp);
2011 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2012 return _eglClientWaitSyncCommon(disp, dpy, s, flags, timeout);
2013 }
2014
2015
2016 static EGLint
2017 _eglWaitSyncCommon(_EGLDisplay *disp, _EGLSync *s, EGLint flags)
2018 {
2019 _EGLContext *ctx = _eglGetCurrentContext();
2020 const _EGLDriver *drv;
2021 EGLint ret;
2022
2023 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
2024 assert(disp->Extensions.KHR_wait_sync);
2025
2026 /* return an error if the client API doesn't support GL_[OES|MESA]_EGL_sync. */
2027 if (ctx == EGL_NO_CONTEXT ||
2028 (ctx->ClientAPI != EGL_OPENGL_ES_API &&
2029 ctx->ClientAPI != EGL_OPENGL_API))
2030 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
2031
2032 /* the API doesn't allow any flags yet */
2033 if (flags != 0)
2034 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2035
2036 ret = disp->Driver->WaitSyncKHR(disp, s);
2037
2038 RETURN_EGL_EVAL(disp, ret);
2039 }
2040
2041 static EGLint EGLAPIENTRY
2042 eglWaitSyncKHR(EGLDisplay dpy, EGLSync sync, EGLint flags)
2043 {
2044 _EGLDisplay *disp = _eglLockDisplay(dpy);
2045 _EGLSync *s = _eglLookupSync(sync, disp);
2046 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2047 return _eglWaitSyncCommon(disp, s, flags);
2048 }
2049
2050
2051 EGLBoolean EGLAPIENTRY
2052 eglWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags)
2053 {
2054 /* The KHR version returns EGLint, while the core version returns
2055 * EGLBoolean. In both cases, the return values can only be EGL_FALSE and
2056 * EGL_TRUE.
2057 */
2058 _EGLDisplay *disp = _eglLockDisplay(dpy);
2059 _EGLSync *s = _eglLookupSync(sync, disp);
2060 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2061 return _eglWaitSyncCommon(disp, s, flags);
2062 }
2063
2064
2065 static EGLBoolean EGLAPIENTRY
2066 eglSignalSyncKHR(EGLDisplay dpy, EGLSync sync, EGLenum mode)
2067 {
2068 _EGLDisplay *disp = _eglLockDisplay(dpy);
2069 _EGLSync *s = _eglLookupSync(sync, disp);
2070 const _EGLDriver *drv;
2071 EGLBoolean ret;
2072
2073 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2074
2075 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
2076 assert(disp->Extensions.KHR_reusable_sync);
2077 ret = disp->Driver->SignalSyncKHR(disp, s, mode);
2078
2079 RETURN_EGL_EVAL(disp, ret);
2080 }
2081
2082
2083 static EGLBoolean
2084 _eglGetSyncAttribCommon(_EGLDisplay *disp, _EGLSync *s, EGLint attribute, EGLAttrib *value)
2085 {
2086 const _EGLDriver *drv;
2087 EGLBoolean ret;
2088
2089 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
2090 assert(disp->Extensions.KHR_reusable_sync ||
2091 disp->Extensions.KHR_fence_sync ||
2092 disp->Extensions.ANDROID_native_fence_sync);
2093
2094 ret = _eglGetSyncAttrib(disp, s, attribute, value);
2095
2096 RETURN_EGL_EVAL(disp, ret);
2097 }
2098
2099 EGLBoolean EGLAPIENTRY
2100 eglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value)
2101 {
2102 _EGLDisplay *disp = _eglLockDisplay(dpy);
2103 _EGLSync *s = _eglLookupSync(sync, disp);
2104 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2105
2106 if (!value)
2107 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2108
2109 return _eglGetSyncAttribCommon(disp, s, attribute, value);
2110 }
2111
2112
2113 static EGLBoolean EGLAPIENTRY
2114 eglGetSyncAttribKHR(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint *value)
2115 {
2116 _EGLDisplay *disp = _eglLockDisplay(dpy);
2117 _EGLSync *s = _eglLookupSync(sync, disp);
2118 EGLAttrib attrib;
2119 EGLBoolean result;
2120
2121 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2122
2123 if (!value)
2124 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2125
2126 attrib = *value;
2127 result = _eglGetSyncAttribCommon(disp, s, attribute, &attrib);
2128
2129 /* The EGL_KHR_fence_sync spec says this about eglGetSyncAttribKHR:
2130 *
2131 * If any error occurs, <*value> is not modified.
2132 */
2133 if (result == EGL_FALSE)
2134 return result;
2135
2136 *value = attrib;
2137 return result;
2138 }
2139
2140 static EGLint EGLAPIENTRY
2141 eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync)
2142 {
2143 _EGLDisplay *disp = _eglLockDisplay(dpy);
2144 _EGLSync *s = _eglLookupSync(sync, disp);
2145 const _EGLDriver *drv;
2146 EGLBoolean ret;
2147
2148 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2149
2150 /* the spec doesn't seem to specify what happens if the fence
2151 * type is not EGL_SYNC_NATIVE_FENCE_ANDROID, but this seems
2152 * sensible:
2153 */
2154 if (!(s && (s->Type == EGL_SYNC_NATIVE_FENCE_ANDROID)))
2155 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_NATIVE_FENCE_FD_ANDROID);
2156
2157 _EGL_CHECK_SYNC(disp, s, EGL_NO_NATIVE_FENCE_FD_ANDROID, drv);
2158 assert(disp->Extensions.ANDROID_native_fence_sync);
2159 ret = disp->Driver->DupNativeFenceFDANDROID(disp, s);
2160
2161 RETURN_EGL_EVAL(disp, ret);
2162 }
2163
2164 static EGLBoolean EGLAPIENTRY
2165 eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface,
2166 EGLint numRects, const EGLint *rects)
2167 {
2168 _EGLContext *ctx = _eglGetCurrentContext();
2169 _EGLDisplay *disp = _eglLockDisplay(dpy);
2170 _EGLSurface *surf = _eglLookupSurface(surface, disp);
2171 const _EGLDriver *drv;
2172 EGLBoolean ret;
2173
2174 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
2175
2176 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
2177
2178 if (!disp->Extensions.NOK_swap_region)
2179 RETURN_EGL_EVAL(disp, EGL_FALSE);
2180
2181 /* surface must be bound to current context in EGL 1.4 */
2182 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
2183 surf != ctx->DrawSurface)
2184 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
2185
2186 ret = disp->Driver->SwapBuffersRegionNOK(disp, surf, numRects, rects);
2187
2188 RETURN_EGL_EVAL(disp, ret);
2189 }
2190
2191
2192 static EGLImage EGLAPIENTRY
2193 eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list)
2194 {
2195 _EGLDisplay *disp = _eglLockDisplay(dpy);
2196 const _EGLDriver *drv;
2197 _EGLImage *img;
2198 EGLImage ret;
2199
2200 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2201
2202 _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
2203 if (!disp->Extensions.MESA_drm_image)
2204 RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
2205
2206 img = disp->Driver->CreateDRMImageMESA(disp, attr_list);
2207 ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
2208
2209 RETURN_EGL_EVAL(disp, ret);
2210 }
2211
2212 static EGLBoolean EGLAPIENTRY
2213 eglExportDRMImageMESA(EGLDisplay dpy, EGLImage image,
2214 EGLint *name, EGLint *handle, EGLint *stride)
2215 {
2216 _EGLDisplay *disp = _eglLockDisplay(dpy);
2217 _EGLImage *img = _eglLookupImage(image, disp);
2218 const _EGLDriver *drv;
2219 EGLBoolean ret;
2220
2221 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
2222
2223 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2224 assert(disp->Extensions.MESA_drm_image);
2225
2226 if (!img)
2227 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2228
2229 ret = disp->Driver->ExportDRMImageMESA(disp, img, name, handle, stride);
2230
2231 RETURN_EGL_EVAL(disp, ret);
2232 }
2233
2234
2235 struct wl_display;
2236
2237 static EGLBoolean EGLAPIENTRY
2238 eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
2239 {
2240 _EGLDisplay *disp = _eglLockDisplay(dpy);
2241 const _EGLDriver *drv;
2242 EGLBoolean ret;
2243
2244 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2245
2246 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2247 assert(disp->Extensions.WL_bind_wayland_display);
2248
2249 if (!display)
2250 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2251
2252 ret = disp->Driver->BindWaylandDisplayWL(disp, display);
2253
2254 RETURN_EGL_EVAL(disp, ret);
2255 }
2256
2257 static EGLBoolean EGLAPIENTRY
2258 eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
2259 {
2260 _EGLDisplay *disp = _eglLockDisplay(dpy);
2261 const _EGLDriver *drv;
2262 EGLBoolean ret;
2263
2264 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2265
2266 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2267 assert(disp->Extensions.WL_bind_wayland_display);
2268
2269 if (!display)
2270 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2271
2272 ret = disp->Driver->UnbindWaylandDisplayWL(disp, display);
2273
2274 RETURN_EGL_EVAL(disp, ret);
2275 }
2276
2277 static EGLBoolean EGLAPIENTRY
2278 eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer,
2279 EGLint attribute, EGLint *value)
2280 {
2281 _EGLDisplay *disp = _eglLockDisplay(dpy);
2282 const _EGLDriver *drv;
2283 EGLBoolean ret;
2284
2285 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2286
2287 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2288 assert(disp->Extensions.WL_bind_wayland_display);
2289
2290 if (!buffer)
2291 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2292
2293 ret = disp->Driver->QueryWaylandBufferWL(disp, buffer, attribute, value);
2294
2295 RETURN_EGL_EVAL(disp, ret);
2296 }
2297
2298
2299 static struct wl_buffer * EGLAPIENTRY
2300 eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImage image)
2301 {
2302 _EGLDisplay *disp = _eglLockDisplay(dpy);
2303 _EGLImage *img;
2304 const _EGLDriver *drv;
2305 struct wl_buffer *ret;
2306
2307 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2308
2309 _EGL_CHECK_DISPLAY(disp, NULL, drv);
2310 if (!disp->Extensions.WL_create_wayland_buffer_from_image)
2311 RETURN_EGL_EVAL(disp, NULL);
2312
2313 img = _eglLookupImage(image, disp);
2314
2315 if (!img)
2316 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL);
2317
2318 ret = disp->Driver->CreateWaylandBufferFromImageWL(disp, img);
2319
2320 RETURN_EGL_EVAL(disp, ret);
2321 }
2322
2323 static EGLBoolean EGLAPIENTRY
2324 eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface,
2325 EGLint x, EGLint y, EGLint width, EGLint height)
2326 {
2327 _EGLDisplay *disp = _eglLockDisplay(dpy);
2328 _EGLSurface *surf = _eglLookupSurface(surface, disp);
2329 const _EGLDriver *drv;
2330 EGLBoolean ret;
2331
2332 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
2333
2334 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
2335
2336 if (!disp->Extensions.NV_post_sub_buffer)
2337 RETURN_EGL_EVAL(disp, EGL_FALSE);
2338
2339 ret = disp->Driver->PostSubBufferNV(disp, surf, x, y, width, height);
2340
2341 RETURN_EGL_EVAL(disp, ret);
2342 }
2343
2344 static EGLBoolean EGLAPIENTRY
2345 eglGetSyncValuesCHROMIUM(EGLDisplay dpy, EGLSurface surface,
2346 EGLuint64KHR *ust, EGLuint64KHR *msc,
2347 EGLuint64KHR *sbc)
2348 {
2349 _EGLDisplay *disp = _eglLockDisplay(dpy);
2350 _EGLSurface *surf = _eglLookupSurface(surface, disp);
2351 const _EGLDriver *drv;
2352 EGLBoolean ret;
2353
2354 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
2355
2356 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
2357 if (!disp->Extensions.CHROMIUM_sync_control)
2358 RETURN_EGL_EVAL(disp, EGL_FALSE);
2359
2360 if (!ust || !msc || !sbc)
2361 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2362
2363 ret = disp->Driver->GetSyncValuesCHROMIUM(disp, surf, ust, msc, sbc);
2364
2365 RETURN_EGL_EVAL(disp, ret);
2366 }
2367
2368 static EGLBoolean EGLAPIENTRY
2369 eglExportDMABUFImageQueryMESA(EGLDisplay dpy, EGLImage image,
2370 EGLint *fourcc, EGLint *nplanes,
2371 EGLuint64KHR *modifiers)
2372 {
2373 _EGLDisplay *disp = _eglLockDisplay(dpy);
2374 _EGLImage *img = _eglLookupImage(image, disp);
2375 const _EGLDriver *drv;
2376 EGLBoolean ret;
2377
2378 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
2379
2380 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2381 assert(disp->Extensions.MESA_image_dma_buf_export);
2382
2383 if (!img)
2384 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2385
2386 ret = disp->Driver->ExportDMABUFImageQueryMESA(disp, img, fourcc, nplanes, modifiers);
2387
2388 RETURN_EGL_EVAL(disp, ret);
2389 }
2390
2391 static EGLBoolean EGLAPIENTRY
2392 eglExportDMABUFImageMESA(EGLDisplay dpy, EGLImage image,
2393 int *fds, EGLint *strides, EGLint *offsets)
2394 {
2395 _EGLDisplay *disp = _eglLockDisplay(dpy);
2396 _EGLImage *img = _eglLookupImage(image, disp);
2397 const _EGLDriver *drv;
2398 EGLBoolean ret;
2399
2400 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
2401
2402 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2403 assert(disp->Extensions.MESA_image_dma_buf_export);
2404
2405 if (!img)
2406 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2407
2408 ret = disp->Driver->ExportDMABUFImageMESA(disp, img, fds, strides, offsets);
2409
2410 RETURN_EGL_EVAL(disp, ret);
2411 }
2412
2413 static EGLint EGLAPIENTRY
2414 eglLabelObjectKHR(EGLDisplay dpy, EGLenum objectType, EGLObjectKHR object,
2415 EGLLabelKHR label)
2416 {
2417 _EGLDisplay *disp = NULL;
2418 _EGLResourceType type;
2419
2420 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
2421
2422 if (objectType == EGL_OBJECT_THREAD_KHR) {
2423 _EGLThreadInfo *t = _eglGetCurrentThread();
2424
2425 if (!_eglIsCurrentThreadDummy()) {
2426 t->Label = label;
2427 return EGL_SUCCESS;
2428 }
2429
2430 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_BAD_ALLOC);
2431 }
2432
2433 disp = _eglLockDisplay(dpy);
2434 if (disp == NULL)
2435 RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_BAD_DISPLAY);
2436
2437 if (objectType == EGL_OBJECT_DISPLAY_KHR) {
2438 if (dpy != (EGLDisplay) object)
2439 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
2440
2441 disp->Label = label;
2442 RETURN_EGL_EVAL(disp, EGL_SUCCESS);
2443 }
2444
2445 switch (objectType) {
2446 case EGL_OBJECT_CONTEXT_KHR:
2447 type = _EGL_RESOURCE_CONTEXT;
2448 break;
2449 case EGL_OBJECT_SURFACE_KHR:
2450 type = _EGL_RESOURCE_SURFACE;
2451 break;
2452 case EGL_OBJECT_IMAGE_KHR:
2453 type = _EGL_RESOURCE_IMAGE;
2454 break;
2455 case EGL_OBJECT_SYNC_KHR:
2456 type = _EGL_RESOURCE_SYNC;
2457 break;
2458 case EGL_OBJECT_STREAM_KHR:
2459 default:
2460 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
2461 }
2462
2463 if (_eglCheckResource(object, type, disp)) {
2464 _EGLResource *res = (_EGLResource *) object;
2465
2466 res->Label = label;
2467 RETURN_EGL_EVAL(disp, EGL_SUCCESS);
2468 }
2469
2470 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
2471 }
2472
2473 static EGLint EGLAPIENTRY
2474 eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback,
2475 const EGLAttrib *attrib_list)
2476 {
2477 unsigned int newEnabled;
2478
2479 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
2480
2481 mtx_lock(_eglGlobal.Mutex);
2482
2483 newEnabled = _eglGlobal.debugTypesEnabled;
2484 if (attrib_list != NULL) {
2485 int i;
2486
2487 for (i = 0; attrib_list[i] != EGL_NONE; i += 2) {
2488 switch (attrib_list[i]) {
2489 case EGL_DEBUG_MSG_CRITICAL_KHR:
2490 case EGL_DEBUG_MSG_ERROR_KHR:
2491 case EGL_DEBUG_MSG_WARN_KHR:
2492 case EGL_DEBUG_MSG_INFO_KHR:
2493 if (attrib_list[i + 1])
2494 newEnabled |= DebugBitFromType(attrib_list[i]);
2495 else
2496 newEnabled &= ~DebugBitFromType(attrib_list[i]);
2497 break;
2498 default:
2499 // On error, set the last error code, call the current
2500 // debug callback, and return the error code.
2501 mtx_unlock(_eglGlobal.Mutex);
2502 _eglReportError(EGL_BAD_ATTRIBUTE, NULL,
2503 "Invalid attribute 0x%04lx", (unsigned long) attrib_list[i]);
2504 return EGL_BAD_ATTRIBUTE;
2505 }
2506 }
2507 }
2508
2509 if (callback != NULL) {
2510 _eglGlobal.debugCallback = callback;
2511 _eglGlobal.debugTypesEnabled = newEnabled;
2512 } else {
2513 _eglGlobal.debugCallback = NULL;
2514 _eglGlobal.debugTypesEnabled = _EGL_DEBUG_BIT_CRITICAL | _EGL_DEBUG_BIT_ERROR;
2515 }
2516
2517 mtx_unlock(_eglGlobal.Mutex);
2518 return EGL_SUCCESS;
2519 }
2520
2521 static EGLBoolean EGLAPIENTRY
2522 eglQueryDebugKHR(EGLint attribute, EGLAttrib *value)
2523 {
2524 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
2525
2526 mtx_lock(_eglGlobal.Mutex);
2527
2528 switch (attribute) {
2529 case EGL_DEBUG_MSG_CRITICAL_KHR:
2530 case EGL_DEBUG_MSG_ERROR_KHR:
2531 case EGL_DEBUG_MSG_WARN_KHR:
2532 case EGL_DEBUG_MSG_INFO_KHR:
2533 if (_eglGlobal.debugTypesEnabled & DebugBitFromType(attribute))
2534 *value = EGL_TRUE;
2535 else
2536 *value = EGL_FALSE;
2537 break;
2538 case EGL_DEBUG_CALLBACK_KHR:
2539 *value = (EGLAttrib) _eglGlobal.debugCallback;
2540 break;
2541 default:
2542 mtx_unlock(_eglGlobal.Mutex);
2543 _eglReportError(EGL_BAD_ATTRIBUTE, NULL,
2544 "Invalid attribute 0x%04lx", (unsigned long) attribute);
2545 return EGL_FALSE;
2546 }
2547
2548 mtx_unlock(_eglGlobal.Mutex);
2549 return EGL_TRUE;
2550 }
2551
2552 static int
2553 _eglFunctionCompare(const void *key, const void *elem)
2554 {
2555 const char *procname = key;
2556 const struct _egl_entrypoint *entrypoint = elem;
2557 return strcmp(procname, entrypoint->name);
2558 }
2559
2560 static EGLBoolean EGLAPIENTRY
2561 eglQueryDmaBufFormatsEXT(EGLDisplay dpy, EGLint max_formats,
2562 EGLint *formats, EGLint *num_formats)
2563 {
2564 _EGLDisplay *disp = _eglLockDisplay(dpy);
2565 const _EGLDriver *drv;
2566 EGLBoolean ret;
2567
2568 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2569
2570 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2571
2572 ret = disp->Driver->QueryDmaBufFormatsEXT(disp, max_formats, formats, num_formats);
2573
2574 RETURN_EGL_EVAL(disp, ret);
2575 }
2576
2577 static EGLBoolean EGLAPIENTRY
2578 eglQueryDmaBufModifiersEXT(EGLDisplay dpy, EGLint format, EGLint max_modifiers,
2579 EGLuint64KHR *modifiers, EGLBoolean *external_only,
2580 EGLint *num_modifiers)
2581 {
2582 _EGLDisplay *disp = _eglLockDisplay(dpy);
2583 const _EGLDriver *drv;
2584 EGLBoolean ret;
2585
2586 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2587
2588 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2589
2590 ret = disp->Driver->QueryDmaBufModifiersEXT(disp, format, max_modifiers, modifiers,
2591 external_only, num_modifiers);
2592
2593 RETURN_EGL_EVAL(disp, ret);
2594 }
2595
2596 static void EGLAPIENTRY
2597 eglSetBlobCacheFuncsANDROID(EGLDisplay *dpy, EGLSetBlobFuncANDROID set,
2598 EGLGetBlobFuncANDROID get)
2599 {
2600 /* This function does not return anything so we cannot
2601 * utilize the helper macros _EGL_FUNC_START or _EGL_CHECK_DISPLAY.
2602 */
2603 _EGLDisplay *disp = _eglLockDisplay(dpy);
2604 if (!_eglSetFuncName(__func__, disp, EGL_OBJECT_DISPLAY_KHR, NULL)) {
2605 if (disp)
2606 _eglUnlockDisplay(disp);
2607 return;
2608 }
2609
2610 const _EGLDriver *drv = _eglCheckDisplay(disp, __func__);
2611 if (!drv) {
2612 if (disp)
2613 _eglUnlockDisplay(disp);
2614 return;
2615 }
2616
2617 if (!set || !get) {
2618 _eglError(EGL_BAD_PARAMETER,
2619 "eglSetBlobCacheFuncsANDROID: NULL handler given");
2620 _eglUnlockDisplay(disp);
2621 return;
2622 }
2623
2624 if (disp->BlobCacheSet) {
2625 _eglError(EGL_BAD_PARAMETER,
2626 "eglSetBlobCacheFuncsANDROID: functions already set");
2627 _eglUnlockDisplay(disp);
2628 return;
2629 }
2630
2631 disp->BlobCacheSet = set;
2632 disp->BlobCacheGet = get;
2633
2634 disp->Driver->SetBlobCacheFuncsANDROID(disp, set, get);
2635
2636 _eglUnlockDisplay(disp);
2637 }
2638
2639 static EGLBoolean EGLAPIENTRY
2640 eglQueryDeviceAttribEXT(EGLDeviceEXT device,
2641 EGLint attribute,
2642 EGLAttrib *value)
2643 {
2644 _EGLDevice *dev = _eglLookupDevice(device);
2645 EGLBoolean ret;
2646
2647 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2648 if (!dev)
2649 RETURN_EGL_ERROR(NULL, EGL_BAD_DEVICE_EXT, EGL_FALSE);
2650
2651 ret = _eglQueryDeviceAttribEXT(dev, attribute, value);
2652 RETURN_EGL_EVAL(NULL, ret);
2653 }
2654
2655 static const char * EGLAPIENTRY
2656 eglQueryDeviceStringEXT(EGLDeviceEXT device,
2657 EGLint name)
2658 {
2659 _EGLDevice *dev = _eglLookupDevice(device);
2660
2661 _EGL_FUNC_START(NULL, EGL_NONE, NULL, NULL);
2662 if (!dev)
2663 RETURN_EGL_ERROR(NULL, EGL_BAD_DEVICE_EXT, NULL);
2664
2665 RETURN_EGL_EVAL(NULL, _eglQueryDeviceStringEXT(dev, name));
2666 }
2667
2668 static EGLBoolean EGLAPIENTRY
2669 eglQueryDevicesEXT(EGLint max_devices,
2670 EGLDeviceEXT *devices,
2671 EGLint *num_devices)
2672 {
2673 EGLBoolean ret;
2674
2675 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2676 ret = _eglQueryDevicesEXT(max_devices, (_EGLDevice **) devices,
2677 num_devices);
2678 RETURN_EGL_EVAL(NULL, ret);
2679 }
2680
2681 static EGLBoolean EGLAPIENTRY
2682 eglQueryDisplayAttribEXT(EGLDisplay dpy,
2683 EGLint attribute,
2684 EGLAttrib *value)
2685 {
2686 _EGLDisplay *disp = _eglLockDisplay(dpy);
2687 const _EGLDriver *drv;
2688
2689 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2690 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2691
2692 switch (attribute) {
2693 case EGL_DEVICE_EXT:
2694 *value = (EGLAttrib) disp->Device;
2695 break;
2696 default:
2697 RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_FALSE);
2698 }
2699 RETURN_EGL_SUCCESS(disp, EGL_TRUE);
2700 }
2701
2702 static char * EGLAPIENTRY
2703 eglGetDisplayDriverConfig(EGLDisplay dpy)
2704 {
2705 _EGLDisplay *disp = _eglLockDisplay(dpy);
2706 const _EGLDriver *drv;
2707 char *ret;
2708
2709 _EGL_FUNC_START(disp, EGL_NONE, NULL, NULL);
2710 _EGL_CHECK_DISPLAY(disp, NULL, drv);
2711
2712 assert(disp->Extensions.MESA_query_driver);
2713
2714 ret = disp->Driver->QueryDriverConfig(disp);
2715 RETURN_EGL_EVAL(disp, ret);
2716 }
2717
2718 static const char * EGLAPIENTRY
2719 eglGetDisplayDriverName(EGLDisplay dpy)
2720 {
2721 _EGLDisplay *disp = _eglLockDisplay(dpy);
2722 const _EGLDriver *drv;
2723 const char *ret;
2724
2725 _EGL_FUNC_START(disp, EGL_NONE, NULL, NULL);
2726 _EGL_CHECK_DISPLAY(disp, NULL, drv);
2727
2728 assert(disp->Extensions.MESA_query_driver);
2729
2730 ret = disp->Driver->QueryDriverName(disp);
2731 RETURN_EGL_EVAL(disp, ret);
2732 }
2733
2734 __eglMustCastToProperFunctionPointerType EGLAPIENTRY
2735 eglGetProcAddress(const char *procname)
2736 {
2737 static const struct _egl_entrypoint egl_functions[] = {
2738 #define EGL_ENTRYPOINT(f) { .name = #f, .function = (_EGLProc) f },
2739 #include "eglentrypoint.h"
2740 #undef EGL_ENTRYPOINT
2741 };
2742 _EGLProc ret = NULL;
2743
2744 if (!procname)
2745 RETURN_EGL_SUCCESS(NULL, NULL);
2746
2747 _EGL_FUNC_START(NULL, EGL_NONE, NULL, NULL);
2748
2749 if (strncmp(procname, "egl", 3) == 0) {
2750 const struct _egl_entrypoint *entrypoint =
2751 bsearch(procname,
2752 egl_functions, ARRAY_SIZE(egl_functions),
2753 sizeof(egl_functions[0]),
2754 _eglFunctionCompare);
2755 if (entrypoint)
2756 ret = entrypoint->function;
2757 }
2758
2759 if (!ret)
2760 ret = _eglGetDriverProc(procname);
2761
2762 RETURN_EGL_SUCCESS(NULL, ret);
2763 }
2764
2765 static int
2766 _eglLockDisplayInterop(EGLDisplay dpy, EGLContext context,
2767 _EGLDisplay **disp, const _EGLDriver **drv,
2768 _EGLContext **ctx)
2769 {
2770
2771 *disp = _eglLockDisplay(dpy);
2772 if (!*disp || !(*disp)->Initialized || !(*disp)->Driver) {
2773 if (*disp)
2774 _eglUnlockDisplay(*disp);
2775 return MESA_GLINTEROP_INVALID_DISPLAY;
2776 }
2777
2778 *drv = (*disp)->Driver;
2779
2780 *ctx = _eglLookupContext(context, *disp);
2781 if (!*ctx ||
2782 ((*ctx)->ClientAPI != EGL_OPENGL_API &&
2783 (*ctx)->ClientAPI != EGL_OPENGL_ES_API)) {
2784 _eglUnlockDisplay(*disp);
2785 return MESA_GLINTEROP_INVALID_CONTEXT;
2786 }
2787
2788 return MESA_GLINTEROP_SUCCESS;
2789 }
2790
2791 PUBLIC int
2792 MesaGLInteropEGLQueryDeviceInfo(EGLDisplay dpy, EGLContext context,
2793 struct mesa_glinterop_device_info *out)
2794 {
2795 _EGLDisplay *disp;
2796 const _EGLDriver *drv;
2797 _EGLContext *ctx;
2798 int ret;
2799
2800 ret = _eglLockDisplayInterop(dpy, context, &disp, &drv, &ctx);
2801 if (ret != MESA_GLINTEROP_SUCCESS)
2802 return ret;
2803
2804 if (disp->Driver->GLInteropQueryDeviceInfo)
2805 ret = disp->Driver->GLInteropQueryDeviceInfo(disp, ctx, out);
2806 else
2807 ret = MESA_GLINTEROP_UNSUPPORTED;
2808
2809 _eglUnlockDisplay(disp);
2810 return ret;
2811 }
2812
2813 PUBLIC int
2814 MesaGLInteropEGLExportObject(EGLDisplay dpy, EGLContext context,
2815 struct mesa_glinterop_export_in *in,
2816 struct mesa_glinterop_export_out *out)
2817 {
2818 _EGLDisplay *disp;
2819 const _EGLDriver *drv;
2820 _EGLContext *ctx;
2821 int ret;
2822
2823 ret = _eglLockDisplayInterop(dpy, context, &disp, &drv, &ctx);
2824 if (ret != MESA_GLINTEROP_SUCCESS)
2825 return ret;
2826
2827 if (disp->Driver->GLInteropExportObject)
2828 ret = disp->Driver->GLInteropExportObject(disp, ctx, in, out);
2829 else
2830 ret = MESA_GLINTEROP_UNSUPPORTED;
2831
2832 _eglUnlockDisplay(disp);
2833 return ret;
2834 }