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