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