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