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