egl: drop EGL driver `name`
[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 "util/macros.h"
92
93 #include "eglglobals.h"
94 #include "eglcontext.h"
95 #include "egldisplay.h"
96 #include "egltypedefs.h"
97 #include "eglcurrent.h"
98 #include "egldriver.h"
99 #include "eglsurface.h"
100 #include "eglconfig.h"
101 #include "eglimage.h"
102 #include "eglsync.h"
103
104 #include "GL/mesa_glinterop.h"
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 _eglDebugReport(EGL_BAD_ALLOC, funcName, EGL_DEBUG_MSG_CRITICAL_KHR, NULL);
278 return EGL_FALSE;
279 }
280
281 #define _EGL_FUNC_START(disp, objectType, object, ret) \
282 do { \
283 if (!_eglSetFuncName(__func__, disp, objectType, (_EGLResource *) object)) { \
284 if (disp) \
285 _eglUnlockDisplay(disp); \
286 return ret; \
287 } \
288 } while(0)
289
290 /**
291 * Convert an attribute list from EGLint[] to EGLAttrib[].
292 *
293 * Return an EGL error code. The output parameter out_attrib_list is modified
294 * only on success.
295 */
296 static EGLint
297 _eglConvertIntsToAttribs(const EGLint *int_list, EGLAttrib **out_attrib_list)
298 {
299 size_t len = 0;
300 EGLAttrib *attrib_list;
301
302 if (int_list) {
303 while (int_list[2*len] != EGL_NONE)
304 ++len;
305 }
306
307 if (len == 0) {
308 *out_attrib_list = NULL;
309 return EGL_SUCCESS;
310 }
311
312 if (2*len + 1 > SIZE_MAX / sizeof(EGLAttrib))
313 return EGL_BAD_ALLOC;
314
315 attrib_list = malloc((2*len + 1) * sizeof(EGLAttrib));
316 if (!attrib_list)
317 return EGL_BAD_ALLOC;
318
319 for (size_t i = 0; i < len; ++i) {
320 attrib_list[2*i + 0] = int_list[2*i + 0];
321 attrib_list[2*i + 1] = int_list[2*i + 1];
322 }
323
324 attrib_list[2*len] = EGL_NONE;
325
326 *out_attrib_list = attrib_list;
327 return EGL_SUCCESS;
328 }
329
330
331 static EGLint *
332 _eglConvertAttribsToInt(const EGLAttrib *attr_list)
333 {
334 EGLint *int_attribs = NULL;
335
336 /* Convert attributes from EGLAttrib[] to EGLint[] */
337 if (attr_list) {
338 int i, size = 0;
339
340 while (attr_list[size] != EGL_NONE)
341 size += 2;
342
343 size += 1; /* add space for EGL_NONE */
344
345 int_attribs = calloc(size, sizeof(int_attribs[0]));
346 if (!int_attribs)
347 return NULL;
348
349 for (i = 0; i < size; i++)
350 int_attribs[i] = attr_list[i];
351 }
352 return int_attribs;
353 }
354
355
356 /**
357 * This is typically the first EGL function that an application calls.
358 * It associates a private _EGLDisplay object to the native display.
359 */
360 EGLDisplay EGLAPIENTRY
361 eglGetDisplay(EGLNativeDisplayType nativeDisplay)
362 {
363 _EGLPlatformType plat;
364 _EGLDisplay *dpy;
365 void *native_display_ptr;
366
367 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY);
368
369 STATIC_ASSERT(sizeof(void*) == sizeof(nativeDisplay));
370 native_display_ptr = (void*) nativeDisplay;
371
372 plat = _eglGetNativePlatform(native_display_ptr);
373 dpy = _eglFindDisplay(plat, native_display_ptr);
374 return _eglGetDisplayHandle(dpy);
375 }
376
377 static EGLDisplay
378 _eglGetPlatformDisplayCommon(EGLenum platform, void *native_display,
379 const EGLint *attrib_list)
380 {
381 _EGLDisplay *dpy;
382
383 switch (platform) {
384 #ifdef HAVE_X11_PLATFORM
385 case EGL_PLATFORM_X11_EXT:
386 dpy = _eglGetX11Display((Display*) native_display, attrib_list);
387 break;
388 #endif
389 #ifdef HAVE_DRM_PLATFORM
390 case EGL_PLATFORM_GBM_MESA:
391 dpy = _eglGetGbmDisplay((struct gbm_device*) native_display,
392 attrib_list);
393 break;
394 #endif
395 #ifdef HAVE_WAYLAND_PLATFORM
396 case EGL_PLATFORM_WAYLAND_EXT:
397 dpy = _eglGetWaylandDisplay((struct wl_display*) native_display,
398 attrib_list);
399 break;
400 #endif
401 #ifdef HAVE_SURFACELESS_PLATFORM
402 case EGL_PLATFORM_SURFACELESS_MESA:
403 dpy = _eglGetSurfacelessDisplay(native_display, attrib_list);
404 break;
405 #endif
406 default:
407 RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, NULL);
408 }
409
410 return _eglGetDisplayHandle(dpy);
411 }
412
413 static EGLDisplay EGLAPIENTRY
414 eglGetPlatformDisplayEXT(EGLenum platform, void *native_display,
415 const EGLint *attrib_list)
416 {
417 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY);
418 return _eglGetPlatformDisplayCommon(platform, native_display, attrib_list);
419 }
420
421 EGLDisplay EGLAPIENTRY
422 eglGetPlatformDisplay(EGLenum platform, void *native_display,
423 const EGLAttrib *attrib_list)
424 {
425 EGLDisplay display;
426 EGLint *int_attribs;
427
428 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY);
429
430 int_attribs = _eglConvertAttribsToInt(attrib_list);
431 if (attrib_list && !int_attribs)
432 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, NULL);
433
434 display = _eglGetPlatformDisplayCommon(platform, native_display, int_attribs);
435 free(int_attribs);
436 return display;
437 }
438
439 /**
440 * Copy the extension into the string and update the string pointer.
441 */
442 static EGLint
443 _eglAppendExtension(char **str, const char *ext)
444 {
445 char *s = *str;
446 size_t len = strlen(ext);
447
448 if (s) {
449 memcpy(s, ext, len);
450 s[len++] = ' ';
451 s[len] = '\0';
452
453 *str += len;
454 }
455 else {
456 len++;
457 }
458
459 return (EGLint) len;
460 }
461
462 /**
463 * Examine the individual extension enable/disable flags and recompute
464 * the driver's Extensions string.
465 */
466 static void
467 _eglCreateExtensionsString(_EGLDisplay *dpy)
468 {
469 #define _EGL_CHECK_EXTENSION(ext) \
470 do { \
471 if (dpy->Extensions.ext) { \
472 _eglAppendExtension(&exts, "EGL_" #ext); \
473 assert(exts <= dpy->ExtensionsString + _EGL_MAX_EXTENSIONS_LEN); \
474 } \
475 } while (0)
476
477 char *exts = dpy->ExtensionsString;
478
479 /* Please keep these sorted alphabetically. */
480 _EGL_CHECK_EXTENSION(ANDROID_framebuffer_target);
481 _EGL_CHECK_EXTENSION(ANDROID_image_native_buffer);
482 _EGL_CHECK_EXTENSION(ANDROID_native_fence_sync);
483 _EGL_CHECK_EXTENSION(ANDROID_recordable);
484
485 _EGL_CHECK_EXTENSION(CHROMIUM_sync_control);
486
487 _EGL_CHECK_EXTENSION(EXT_buffer_age);
488 _EGL_CHECK_EXTENSION(EXT_create_context_robustness);
489 _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import);
490 _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import_modifiers);
491 _EGL_CHECK_EXTENSION(EXT_swap_buffers_with_damage);
492
493 _EGL_CHECK_EXTENSION(KHR_cl_event2);
494 _EGL_CHECK_EXTENSION(KHR_config_attribs);
495 _EGL_CHECK_EXTENSION(KHR_create_context);
496 _EGL_CHECK_EXTENSION(KHR_create_context_no_error);
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_partial_update);
510 _EGL_CHECK_EXTENSION(KHR_reusable_sync);
511 _EGL_CHECK_EXTENSION(KHR_surfaceless_context);
512 if (dpy->Extensions.EXT_swap_buffers_with_damage)
513 _eglAppendExtension(&exts, "EGL_KHR_swap_buffers_with_damage");
514 _EGL_CHECK_EXTENSION(KHR_wait_sync);
515
516 if (dpy->Extensions.KHR_no_config_context)
517 _eglAppendExtension(&exts, "EGL_MESA_configless_context");
518 _EGL_CHECK_EXTENSION(MESA_drm_image);
519 _EGL_CHECK_EXTENSION(MESA_image_dma_buf_export);
520
521 _EGL_CHECK_EXTENSION(NOK_swap_region);
522 _EGL_CHECK_EXTENSION(NOK_texture_from_pixmap);
523
524 _EGL_CHECK_EXTENSION(NV_post_sub_buffer);
525
526 _EGL_CHECK_EXTENSION(WL_bind_wayland_display);
527 _EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image);
528
529 #undef _EGL_CHECK_EXTENSION
530 }
531
532 static void
533 _eglCreateAPIsString(_EGLDisplay *dpy)
534 {
535 if (dpy->ClientAPIs & EGL_OPENGL_BIT)
536 strcat(dpy->ClientAPIsString, "OpenGL ");
537
538 if (dpy->ClientAPIs & EGL_OPENGL_ES_BIT ||
539 dpy->ClientAPIs & EGL_OPENGL_ES2_BIT ||
540 dpy->ClientAPIs & EGL_OPENGL_ES3_BIT_KHR) {
541 strcat(dpy->ClientAPIsString, "OpenGL_ES ");
542 }
543
544 if (dpy->ClientAPIs & EGL_OPENVG_BIT)
545 strcat(dpy->ClientAPIsString, "OpenVG ");
546
547 assert(strlen(dpy->ClientAPIsString) < sizeof(dpy->ClientAPIsString));
548 }
549
550 static void
551 _eglComputeVersion(_EGLDisplay *disp)
552 {
553 disp->Version = 14;
554
555 if (disp->Extensions.KHR_fence_sync &&
556 disp->Extensions.KHR_cl_event2 &&
557 disp->Extensions.KHR_wait_sync &&
558 disp->Extensions.KHR_image_base &&
559 disp->Extensions.KHR_gl_texture_2D_image &&
560 disp->Extensions.KHR_gl_texture_3D_image &&
561 disp->Extensions.KHR_gl_texture_cubemap_image &&
562 disp->Extensions.KHR_gl_renderbuffer_image &&
563 disp->Extensions.KHR_create_context &&
564 disp->Extensions.EXT_create_context_robustness &&
565 disp->Extensions.KHR_get_all_proc_addresses &&
566 disp->Extensions.KHR_gl_colorspace &&
567 disp->Extensions.KHR_surfaceless_context)
568 disp->Version = 15;
569 }
570
571 /**
572 * This is typically the second EGL function that an application calls.
573 * Here we load/initialize the actual hardware driver.
574 */
575 EGLBoolean EGLAPIENTRY
576 eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
577 {
578 _EGLDisplay *disp = _eglLockDisplay(dpy);
579
580 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
581
582 if (!disp)
583 RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
584
585 if (!disp->Initialized) {
586 if (!_eglMatchDriver(disp))
587 RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
588
589 /* limit to APIs supported by core */
590 disp->ClientAPIs &= _EGL_API_ALL_BITS;
591
592 /* EGL_KHR_get_all_proc_addresses is a corner-case extension. The spec
593 * classifies it as an EGL display extension, though conceptually it's an
594 * EGL client extension.
595 *
596 * From the EGL_KHR_get_all_proc_addresses spec:
597 *
598 * The EGL implementation must expose the name
599 * EGL_KHR_client_get_all_proc_addresses if and only if it exposes
600 * EGL_KHR_get_all_proc_addresses and supports
601 * EGL_EXT_client_extensions.
602 *
603 * Mesa unconditionally exposes both client extensions mentioned above,
604 * so the spec requires that each EGLDisplay unconditionally expose
605 * EGL_KHR_get_all_proc_addresses also.
606 */
607 disp->Extensions.KHR_get_all_proc_addresses = EGL_TRUE;
608
609 /* Extensions is used to provide EGL 1.3 functionality for 1.2 aware
610 * programs. It is driver agnostic and handled in the main EGL code.
611 */
612 disp->Extensions.KHR_config_attribs = EGL_TRUE;
613
614 _eglComputeVersion(disp);
615 _eglCreateExtensionsString(disp);
616 _eglCreateAPIsString(disp);
617 snprintf(disp->VersionString, sizeof(disp->VersionString),
618 "%d.%d", disp->Version / 10, disp->Version % 10);
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 && 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 && 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 if (native_pixmap == NULL)
1023 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
1024
1025 surf = drv->API.CreatePixmapSurface(drv, disp, conf, native_pixmap,
1026 attrib_list);
1027 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1028
1029 RETURN_EGL_EVAL(disp, ret);
1030 }
1031
1032
1033 EGLSurface EGLAPIENTRY
1034 eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
1035 EGLNativePixmapType pixmap, const EGLint *attrib_list)
1036 {
1037 _EGLDisplay *disp = _eglLockDisplay(dpy);
1038
1039 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1040 STATIC_ASSERT(sizeof(void*) == sizeof(pixmap));
1041 return _eglCreatePixmapSurfaceCommon(disp, config, (void*) pixmap,
1042 attrib_list);
1043 }
1044
1045 static EGLSurface EGLAPIENTRY
1046 eglCreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config,
1047 void *native_pixmap,
1048 const EGLint *attrib_list)
1049 {
1050 _EGLDisplay *disp = _eglLockDisplay(dpy);
1051
1052 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1053 native_pixmap = _fixupNativePixmap(disp, native_pixmap);
1054 return _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap,
1055 attrib_list);
1056 }
1057
1058
1059 EGLSurface EGLAPIENTRY
1060 eglCreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config,
1061 void *native_pixmap,
1062 const EGLAttrib *attrib_list)
1063 {
1064 _EGLDisplay *disp = _eglLockDisplay(dpy);
1065 EGLSurface surface;
1066 EGLint *int_attribs;
1067
1068 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1069
1070 int_attribs = _eglConvertAttribsToInt(attrib_list);
1071 if (attrib_list && !int_attribs)
1072 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
1073
1074 native_pixmap = _fixupNativePixmap(disp, native_pixmap);
1075 surface = _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap,
1076 int_attribs);
1077 free(int_attribs);
1078 return surface;
1079 }
1080
1081
1082 EGLSurface EGLAPIENTRY
1083 eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
1084 const EGLint *attrib_list)
1085 {
1086 _EGLDisplay *disp = _eglLockDisplay(dpy);
1087 _EGLConfig *conf = _eglLookupConfig(config, disp);
1088 _EGLDriver *drv;
1089 _EGLSurface *surf;
1090 EGLSurface ret;
1091
1092 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1093 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
1094
1095 if ((conf->SurfaceType & EGL_PBUFFER_BIT) == 0)
1096 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE);
1097
1098 surf = drv->API.CreatePbufferSurface(drv, disp, conf, attrib_list);
1099 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1100
1101 RETURN_EGL_EVAL(disp, ret);
1102 }
1103
1104
1105 EGLBoolean EGLAPIENTRY
1106 eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
1107 {
1108 _EGLDisplay *disp = _eglLockDisplay(dpy);
1109 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1110 _EGLDriver *drv;
1111 EGLBoolean ret;
1112
1113 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1114 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1115 _eglUnlinkSurface(surf);
1116 ret = drv->API.DestroySurface(drv, disp, surf);
1117
1118 RETURN_EGL_EVAL(disp, ret);
1119 }
1120
1121 EGLBoolean EGLAPIENTRY
1122 eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
1123 EGLint attribute, EGLint *value)
1124 {
1125 _EGLDisplay *disp = _eglLockDisplay(dpy);
1126 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1127 _EGLDriver *drv;
1128 EGLBoolean ret;
1129
1130 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1131 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1132 ret = drv->API.QuerySurface(drv, disp, surf, attribute, value);
1133
1134 RETURN_EGL_EVAL(disp, ret);
1135 }
1136
1137 EGLBoolean EGLAPIENTRY
1138 eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
1139 EGLint attribute, EGLint value)
1140 {
1141 _EGLDisplay *disp = _eglLockDisplay(dpy);
1142 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1143 _EGLDriver *drv;
1144 EGLBoolean ret;
1145
1146 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1147 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1148 ret = drv->API.SurfaceAttrib(drv, disp, surf, attribute, value);
1149
1150 RETURN_EGL_EVAL(disp, ret);
1151 }
1152
1153
1154 EGLBoolean EGLAPIENTRY
1155 eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1156 {
1157 _EGLDisplay *disp = _eglLockDisplay(dpy);
1158 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1159 _EGLDriver *drv;
1160 EGLBoolean ret;
1161
1162 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1163 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1164 ret = drv->API.BindTexImage(drv, disp, surf, buffer);
1165
1166 RETURN_EGL_EVAL(disp, ret);
1167 }
1168
1169
1170 EGLBoolean EGLAPIENTRY
1171 eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1172 {
1173 _EGLDisplay *disp = _eglLockDisplay(dpy);
1174 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1175 _EGLDriver *drv;
1176 EGLBoolean ret;
1177
1178 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1179 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1180 ret = drv->API.ReleaseTexImage(drv, disp, surf, buffer);
1181
1182 RETURN_EGL_EVAL(disp, ret);
1183 }
1184
1185
1186 EGLBoolean EGLAPIENTRY
1187 eglSwapInterval(EGLDisplay dpy, EGLint interval)
1188 {
1189 _EGLDisplay *disp = _eglLockDisplay(dpy);
1190 _EGLContext *ctx = _eglGetCurrentContext();
1191 _EGLSurface *surf = ctx ? ctx->DrawSurface : NULL;
1192 _EGLDriver *drv;
1193 EGLBoolean ret;
1194
1195 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1196 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1197
1198 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1199 ctx->Resource.Display != disp)
1200 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
1201
1202 if (_eglGetSurfaceHandle(surf) == EGL_NO_SURFACE)
1203 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1204
1205 interval = CLAMP(interval,
1206 surf->Config->MinSwapInterval,
1207 surf->Config->MaxSwapInterval);
1208
1209 if (surf->SwapInterval != interval)
1210 ret = drv->API.SwapInterval(drv, disp, surf, interval);
1211 else
1212 ret = EGL_TRUE;
1213
1214 if (ret)
1215 surf->SwapInterval = interval;
1216
1217 RETURN_EGL_EVAL(disp, ret);
1218 }
1219
1220
1221 EGLBoolean EGLAPIENTRY
1222 eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1223 {
1224 _EGLContext *ctx = _eglGetCurrentContext();
1225 _EGLDisplay *disp = _eglLockDisplay(dpy);
1226 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1227 _EGLDriver *drv;
1228 EGLBoolean ret;
1229
1230 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1231 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1232
1233 /* surface must be bound to current context in EGL 1.4 */
1234 #ifndef _EGL_BUILT_IN_DRIVER_HAIKU
1235 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1236 surf != ctx->DrawSurface)
1237 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1238 #endif
1239
1240 /* From the EGL 1.5 spec:
1241 *
1242 * If eglSwapBuffers is called and the native window associated with
1243 * surface is no longer valid, an EGL_BAD_NATIVE_WINDOW error is
1244 * generated.
1245 */
1246 if (surf->Lost)
1247 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE);
1248
1249 ret = drv->API.SwapBuffers(drv, disp, surf);
1250
1251 /* EGL_KHR_partial_update
1252 * Frame boundary successfully reached,
1253 * reset damage region and reset BufferAgeRead
1254 */
1255 if (ret) {
1256 surf->SetDamageRegionCalled = EGL_FALSE;
1257 surf->BufferAgeRead = EGL_FALSE;
1258 }
1259
1260 RETURN_EGL_EVAL(disp, ret);
1261 }
1262
1263
1264 static EGLBoolean
1265 _eglSwapBuffersWithDamageCommon(_EGLDisplay *disp, _EGLSurface *surf,
1266 EGLint *rects, EGLint n_rects)
1267 {
1268 _EGLContext *ctx = _eglGetCurrentContext();
1269 _EGLDriver *drv;
1270 EGLBoolean ret;
1271
1272 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1273
1274 /* surface must be bound to current context in EGL 1.4 */
1275 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1276 surf != ctx->DrawSurface)
1277 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1278
1279 if ((n_rects > 0 && rects == NULL) || n_rects < 0)
1280 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1281
1282 ret = drv->API.SwapBuffersWithDamageEXT(drv, disp, surf, rects, n_rects);
1283
1284 /* EGL_KHR_partial_update
1285 * Frame boundary successfully reached,
1286 * reset damage region and reset BufferAgeRead
1287 */
1288 if (ret) {
1289 surf->SetDamageRegionCalled = EGL_FALSE;
1290 surf->BufferAgeRead = EGL_FALSE;
1291 }
1292
1293 RETURN_EGL_EVAL(disp, ret);
1294 }
1295
1296 static EGLBoolean EGLAPIENTRY
1297 eglSwapBuffersWithDamageEXT(EGLDisplay dpy, EGLSurface surface,
1298 EGLint *rects, EGLint n_rects)
1299 {
1300 _EGLDisplay *disp = _eglLockDisplay(dpy);
1301 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1302 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1303 return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects);
1304 }
1305
1306 static EGLBoolean EGLAPIENTRY
1307 eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface surface,
1308 EGLint *rects, EGLint n_rects)
1309 {
1310 _EGLDisplay *disp = _eglLockDisplay(dpy);
1311 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1312 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1313 return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects);
1314 }
1315
1316 /**
1317 * If the width of the passed rect is greater than the surface's
1318 * width then it is clamped to the width of the surface. Same with
1319 * height.
1320 */
1321
1322 static void
1323 _eglSetDamageRegionKHRClampRects(_EGLDisplay* disp, _EGLSurface* surf,
1324 EGLint *rects, EGLint n_rects)
1325 {
1326 EGLint i;
1327 EGLint surf_height = surf->Height;
1328 EGLint surf_width = surf->Width;
1329
1330 for (i = 0; i < (4 * n_rects); i += 4) {
1331 EGLint x, y, rect_width, rect_height;
1332 x = rects[i];
1333 y = rects[i + 1];
1334 rect_width = rects[i + 2];
1335 rect_height = rects[i + 3];
1336
1337 if (rect_width > surf_width - x)
1338 rects[i + 2] = surf_width - x;
1339
1340 if (rect_height > surf_height - y)
1341 rects[i + 3] = surf_height - y;
1342 }
1343 }
1344
1345 static EGLBoolean EGLAPIENTRY
1346 eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
1347 EGLint *rects, EGLint n_rects)
1348 {
1349 _EGLDisplay *disp = _eglLockDisplay(dpy);
1350 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1351 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1352 _EGLContext *ctx = _eglGetCurrentContext();
1353 _EGLDriver *drv;
1354 EGLBoolean ret;
1355 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1356
1357 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1358 surf->Type != EGL_WINDOW_BIT ||
1359 ctx->DrawSurface != surf ||
1360 surf->SwapBehavior != EGL_BUFFER_DESTROYED)
1361 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
1362
1363 /* If the damage region is already set or
1364 * buffer age is not queried between
1365 * frame boundaries, throw bad access error
1366 */
1367
1368 if (surf->SetDamageRegionCalled || !surf->BufferAgeRead)
1369 RETURN_EGL_ERROR(disp, EGL_BAD_ACCESS, EGL_FALSE);
1370
1371 _eglSetDamageRegionKHRClampRects(disp, surf, rects, n_rects);
1372 ret = drv->API.SetDamageRegion(drv, disp, surf, rects, n_rects);
1373
1374 if (ret)
1375 surf->SetDamageRegionCalled = EGL_TRUE;
1376
1377 RETURN_EGL_EVAL(disp, ret);
1378 }
1379
1380 EGLBoolean EGLAPIENTRY
1381 eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1382 {
1383 _EGLDisplay *disp = _eglLockDisplay(dpy);
1384 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1385 _EGLDriver *drv;
1386 EGLBoolean ret;
1387 void *native_pixmap_ptr;
1388
1389 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1390 STATIC_ASSERT(sizeof(void*) == sizeof(target));
1391 native_pixmap_ptr = (void*) target;
1392
1393 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1394 if (disp->Platform != _eglGetNativePlatform(disp->PlatformDisplay))
1395 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_FALSE);
1396 ret = drv->API.CopyBuffers(drv, disp, surf, native_pixmap_ptr);
1397
1398 RETURN_EGL_EVAL(disp, ret);
1399 }
1400
1401
1402 static EGLBoolean
1403 _eglWaitClientCommon(void)
1404 {
1405 _EGLContext *ctx = _eglGetCurrentContext();
1406 _EGLDisplay *disp;
1407 _EGLDriver *drv;
1408 EGLBoolean ret;
1409
1410 if (!ctx)
1411 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1412
1413 disp = ctx->Resource.Display;
1414 mtx_lock(&disp->Mutex);
1415
1416 /* let bad current context imply bad current surface */
1417 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1418 _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
1419 RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
1420
1421 /* a valid current context implies an initialized current display */
1422 assert(disp->Initialized);
1423 drv = disp->Driver;
1424 ret = drv->API.WaitClient(drv, disp, ctx);
1425
1426 RETURN_EGL_EVAL(disp, ret);
1427 }
1428
1429 EGLBoolean EGLAPIENTRY
1430 eglWaitClient(void)
1431 {
1432 _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE);
1433 return _eglWaitClientCommon();
1434 }
1435
1436 EGLBoolean EGLAPIENTRY
1437 eglWaitGL(void)
1438 {
1439 /* Since we only support OpenGL and GLES, eglWaitGL is equivalent to eglWaitClient. */
1440 _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE);
1441 return _eglWaitClientCommon();
1442 }
1443
1444
1445 EGLBoolean EGLAPIENTRY
1446 eglWaitNative(EGLint engine)
1447 {
1448 _EGLContext *ctx = _eglGetCurrentContext();
1449 _EGLDisplay *disp;
1450 _EGLDriver *drv;
1451 EGLBoolean ret;
1452
1453 if (!ctx)
1454 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1455
1456 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
1457
1458 disp = ctx->Resource.Display;
1459 mtx_lock(&disp->Mutex);
1460
1461 /* let bad current context imply bad current surface */
1462 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1463 _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
1464 RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
1465
1466 /* a valid current context implies an initialized current display */
1467 assert(disp->Initialized);
1468 drv = disp->Driver;
1469 ret = drv->API.WaitNative(drv, disp, engine);
1470
1471 RETURN_EGL_EVAL(disp, ret);
1472 }
1473
1474
1475 EGLDisplay EGLAPIENTRY
1476 eglGetCurrentDisplay(void)
1477 {
1478 _EGLContext *ctx = _eglGetCurrentContext();
1479 EGLDisplay ret;
1480
1481 ret = (ctx) ? _eglGetDisplayHandle(ctx->Resource.Display) : EGL_NO_DISPLAY;
1482
1483 RETURN_EGL_SUCCESS(NULL, ret);
1484 }
1485
1486
1487 EGLContext EGLAPIENTRY
1488 eglGetCurrentContext(void)
1489 {
1490 _EGLContext *ctx = _eglGetCurrentContext();
1491 EGLContext ret;
1492
1493 ret = _eglGetContextHandle(ctx);
1494
1495 RETURN_EGL_SUCCESS(NULL, ret);
1496 }
1497
1498
1499 EGLSurface EGLAPIENTRY
1500 eglGetCurrentSurface(EGLint readdraw)
1501 {
1502 _EGLContext *ctx = _eglGetCurrentContext();
1503 EGLint err = EGL_SUCCESS;
1504 _EGLSurface *surf;
1505 EGLSurface ret;
1506
1507 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_NO_SURFACE);
1508
1509 if (!ctx)
1510 RETURN_EGL_SUCCESS(NULL, EGL_NO_SURFACE);
1511
1512 switch (readdraw) {
1513 case EGL_DRAW:
1514 surf = ctx->DrawSurface;
1515 break;
1516 case EGL_READ:
1517 surf = ctx->ReadSurface;
1518 break;
1519 default:
1520 surf = NULL;
1521 err = EGL_BAD_PARAMETER;
1522 break;
1523 }
1524
1525 ret = _eglGetSurfaceHandle(surf);
1526
1527 RETURN_EGL_ERROR(NULL, err, ret);
1528 }
1529
1530
1531 EGLint EGLAPIENTRY
1532 eglGetError(void)
1533 {
1534 _EGLThreadInfo *t = _eglGetCurrentThread();
1535 EGLint e = t->LastError;
1536 if (!_eglIsCurrentThreadDummy())
1537 t->LastError = EGL_SUCCESS;
1538 return e;
1539 }
1540
1541
1542 /**
1543 ** EGL 1.2
1544 **/
1545
1546 /**
1547 * Specify the client API to use for subsequent calls including:
1548 * eglCreateContext()
1549 * eglGetCurrentContext()
1550 * eglGetCurrentDisplay()
1551 * eglGetCurrentSurface()
1552 * eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT)
1553 * eglWaitClient()
1554 * eglWaitNative()
1555 * See section 3.7 "Rendering Context" in the EGL specification for details.
1556 */
1557 EGLBoolean EGLAPIENTRY
1558 eglBindAPI(EGLenum api)
1559 {
1560 _EGLThreadInfo *t;
1561
1562 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
1563
1564 t = _eglGetCurrentThread();
1565 if (_eglIsCurrentThreadDummy())
1566 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
1567
1568 if (!_eglIsApiValid(api))
1569 RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, EGL_FALSE);
1570
1571 t->CurrentAPI = api;
1572
1573 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1574 }
1575
1576
1577 /**
1578 * Return the last value set with eglBindAPI().
1579 */
1580 EGLenum EGLAPIENTRY
1581 eglQueryAPI(void)
1582 {
1583 _EGLThreadInfo *t = _eglGetCurrentThread();
1584 EGLenum ret;
1585
1586 /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */
1587 ret = t->CurrentAPI;
1588
1589 RETURN_EGL_SUCCESS(NULL, ret);
1590 }
1591
1592
1593 EGLSurface EGLAPIENTRY
1594 eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
1595 EGLClientBuffer buffer, EGLConfig config,
1596 const EGLint *attrib_list)
1597 {
1598 _EGLDisplay *disp = _eglLockDisplay(dpy);
1599 _EGLConfig *conf = _eglLookupConfig(config, disp);
1600 _EGLDriver *drv;
1601 _EGLSurface *surf;
1602 EGLSurface ret;
1603
1604 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1605
1606 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
1607
1608 surf = drv->API.CreatePbufferFromClientBuffer(drv, disp, buftype, buffer,
1609 conf, attrib_list);
1610 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1611
1612 RETURN_EGL_EVAL(disp, ret);
1613 }
1614
1615
1616 EGLBoolean EGLAPIENTRY
1617 eglReleaseThread(void)
1618 {
1619 /* unbind current contexts */
1620 if (!_eglIsCurrentThreadDummy()) {
1621 _EGLThreadInfo *t = _eglGetCurrentThread();
1622 _EGLContext *ctx = t->CurrentContext;
1623
1624 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
1625
1626 if (ctx) {
1627 _EGLDisplay *disp = ctx->Resource.Display;
1628 _EGLDriver *drv;
1629
1630 mtx_lock(&disp->Mutex);
1631 drv = disp->Driver;
1632 (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
1633 mtx_unlock(&disp->Mutex);
1634 }
1635 }
1636
1637 _eglDestroyCurrentThread();
1638
1639 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1640 }
1641
1642
1643 static EGLImage
1644 _eglCreateImageCommon(_EGLDisplay *disp, EGLContext ctx, EGLenum target,
1645 EGLClientBuffer buffer, const EGLint *attr_list)
1646 {
1647 _EGLContext *context = _eglLookupContext(ctx, disp);
1648 _EGLDriver *drv;
1649 _EGLImage *img;
1650 EGLImage ret;
1651
1652 _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
1653 if (!disp->Extensions.KHR_image_base)
1654 RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
1655 if (!context && ctx != EGL_NO_CONTEXT)
1656 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1657 /* "If <target> is EGL_LINUX_DMA_BUF_EXT, <dpy> must be a valid display,
1658 * <ctx> must be EGL_NO_CONTEXT..."
1659 */
1660 if (ctx != EGL_NO_CONTEXT && target == EGL_LINUX_DMA_BUF_EXT)
1661 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1662
1663 img = drv->API.CreateImageKHR(drv, disp, context, target,
1664 buffer, attr_list);
1665 ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
1666
1667 RETURN_EGL_EVAL(disp, ret);
1668 }
1669
1670 static EGLImage EGLAPIENTRY
1671 eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1672 EGLClientBuffer buffer, const EGLint *attr_list)
1673 {
1674 _EGLDisplay *disp = _eglLockDisplay(dpy);
1675 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR);
1676 return _eglCreateImageCommon(disp, ctx, target, buffer, attr_list);
1677 }
1678
1679
1680 EGLImage EGLAPIENTRY
1681 eglCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1682 EGLClientBuffer buffer, const EGLAttrib *attr_list)
1683 {
1684 _EGLDisplay *disp = _eglLockDisplay(dpy);
1685 EGLImage image;
1686 EGLint *int_attribs;
1687
1688 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR);
1689
1690 int_attribs = _eglConvertAttribsToInt(attr_list);
1691 if (attr_list && !int_attribs)
1692 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_IMAGE);
1693
1694 image = _eglCreateImageCommon(disp, ctx, target, buffer, int_attribs);
1695 free(int_attribs);
1696 return image;
1697 }
1698
1699
1700 static EGLBoolean
1701 _eglDestroyImageCommon(_EGLDisplay *disp, _EGLImage *img)
1702 {
1703 _EGLDriver *drv;
1704 EGLBoolean ret;
1705
1706 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1707 if (!disp->Extensions.KHR_image_base)
1708 RETURN_EGL_EVAL(disp, EGL_FALSE);
1709 if (!img)
1710 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1711
1712 _eglUnlinkImage(img);
1713 ret = drv->API.DestroyImageKHR(drv, disp, img);
1714
1715 RETURN_EGL_EVAL(disp, ret);
1716 }
1717
1718 EGLBoolean EGLAPIENTRY
1719 eglDestroyImage(EGLDisplay dpy, EGLImage image)
1720 {
1721 _EGLDisplay *disp = _eglLockDisplay(dpy);
1722 _EGLImage *img = _eglLookupImage(image, disp);
1723 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
1724 return _eglDestroyImageCommon(disp, img);
1725 }
1726
1727 static EGLBoolean EGLAPIENTRY
1728 eglDestroyImageKHR(EGLDisplay dpy, EGLImage image)
1729 {
1730 _EGLDisplay *disp = _eglLockDisplay(dpy);
1731 _EGLImage *img = _eglLookupImage(image, disp);
1732 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
1733 return _eglDestroyImageCommon(disp, img);
1734 }
1735
1736
1737 static EGLSync
1738 _eglCreateSync(_EGLDisplay *disp, EGLenum type, const EGLAttrib *attrib_list,
1739 EGLBoolean orig_is_EGLAttrib,
1740 EGLenum invalid_type_error)
1741 {
1742 _EGLContext *ctx = _eglGetCurrentContext();
1743 _EGLDriver *drv;
1744 _EGLSync *sync;
1745 EGLSync ret;
1746
1747 _EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv);
1748
1749 if (!disp->Extensions.KHR_cl_event2 && orig_is_EGLAttrib) {
1750 /* There exist two EGLAttrib variants of eglCreateSync*:
1751 * eglCreateSync64KHR which requires EGL_KHR_cl_event2, and eglCreateSync
1752 * which requires EGL 1.5. Here we use the presence of EGL_KHR_cl_event2
1753 * support as a proxy for EGL 1.5 support, even though that's not
1754 * entirely correct (though _eglComputeVersion does the same).
1755 *
1756 * The EGL spec provides no guidance on how to handle unsupported
1757 * functions. EGL_BAD_MATCH seems reasonable.
1758 */
1759 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1760 }
1761
1762 /* If type is EGL_SYNC_FENCE and no context is current for the bound API
1763 * (i.e., eglGetCurrentContext returns EGL_NO_CONTEXT ), an EGL_BAD_MATCH
1764 * error is generated.
1765 */
1766 if (!ctx &&
1767 (type == EGL_SYNC_FENCE_KHR || type == EGL_SYNC_NATIVE_FENCE_ANDROID))
1768 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1769
1770 /* return an error if the client API doesn't support GL_OES_EGL_sync */
1771 if (ctx && (ctx->Resource.Display != disp ||
1772 ctx->ClientAPI != EGL_OPENGL_ES_API))
1773 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1774
1775 switch (type) {
1776 case EGL_SYNC_FENCE_KHR:
1777 if (!disp->Extensions.KHR_fence_sync)
1778 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1779 break;
1780 case EGL_SYNC_REUSABLE_KHR:
1781 if (!disp->Extensions.KHR_reusable_sync)
1782 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1783 break;
1784 case EGL_SYNC_CL_EVENT_KHR:
1785 if (!disp->Extensions.KHR_cl_event2)
1786 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1787 break;
1788 case EGL_SYNC_NATIVE_FENCE_ANDROID:
1789 if (!disp->Extensions.ANDROID_native_fence_sync)
1790 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1791 break;
1792 default:
1793 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1794 }
1795
1796 sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list);
1797 ret = (sync) ? _eglLinkSync(sync) : EGL_NO_SYNC_KHR;
1798
1799 RETURN_EGL_EVAL(disp, ret);
1800 }
1801
1802
1803 static EGLSync EGLAPIENTRY
1804 eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *int_list)
1805 {
1806 _EGLDisplay *disp = _eglLockDisplay(dpy);
1807 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
1808
1809 EGLSync sync;
1810 EGLAttrib *attrib_list;
1811 EGLint err;
1812
1813 if (sizeof(int_list[0]) == sizeof(attrib_list[0])) {
1814 attrib_list = (EGLAttrib *) int_list;
1815 } else {
1816 err = _eglConvertIntsToAttribs(int_list, &attrib_list);
1817 if (err != EGL_SUCCESS)
1818 RETURN_EGL_ERROR(disp, err, EGL_NO_SYNC);
1819 }
1820
1821 sync = _eglCreateSync(disp, type, attrib_list, EGL_FALSE,
1822 EGL_BAD_ATTRIBUTE);
1823
1824 if (sizeof(int_list[0]) != sizeof(attrib_list[0]))
1825 free(attrib_list);
1826
1827 /* Don't double-unlock the display. _eglCreateSync already unlocked it. */
1828 return sync;
1829 }
1830
1831
1832 static EGLSync EGLAPIENTRY
1833 eglCreateSync64KHR(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
1834 {
1835 _EGLDisplay *disp = _eglLockDisplay(dpy);
1836 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
1837 return _eglCreateSync(disp, type, attrib_list, EGL_TRUE,
1838 EGL_BAD_ATTRIBUTE);
1839 }
1840
1841
1842 EGLSync EGLAPIENTRY
1843 eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
1844 {
1845 _EGLDisplay *disp = _eglLockDisplay(dpy);
1846 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
1847 return _eglCreateSync(disp, type, attrib_list, EGL_TRUE,
1848 EGL_BAD_PARAMETER);
1849 }
1850
1851
1852 static EGLBoolean
1853 _eglDestroySync(_EGLDisplay *disp, _EGLSync *s)
1854 {
1855 _EGLDriver *drv;
1856 EGLBoolean ret;
1857
1858 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1859 assert(disp->Extensions.KHR_reusable_sync ||
1860 disp->Extensions.KHR_fence_sync ||
1861 disp->Extensions.ANDROID_native_fence_sync);
1862
1863 _eglUnlinkSync(s);
1864 ret = drv->API.DestroySyncKHR(drv, disp, s);
1865
1866 RETURN_EGL_EVAL(disp, ret);
1867 }
1868
1869 EGLBoolean EGLAPIENTRY
1870 eglDestroySync(EGLDisplay dpy, EGLSync sync)
1871 {
1872 _EGLDisplay *disp = _eglLockDisplay(dpy);
1873 _EGLSync *s = _eglLookupSync(sync, disp);
1874 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
1875 return _eglDestroySync(disp, s);
1876 }
1877
1878 static EGLBoolean EGLAPIENTRY
1879 eglDestroySyncKHR(EGLDisplay dpy, EGLSync sync)
1880 {
1881 _EGLDisplay *disp = _eglLockDisplay(dpy);
1882 _EGLSync *s = _eglLookupSync(sync, disp);
1883 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
1884 return _eglDestroySync(disp, s);
1885 }
1886
1887
1888 static EGLint
1889 _eglClientWaitSyncCommon(_EGLDisplay *disp, EGLDisplay dpy,
1890 _EGLSync *s, EGLint flags, EGLTime timeout)
1891 {
1892 _EGLDriver *drv;
1893 EGLint ret;
1894
1895 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1896 assert(disp->Extensions.KHR_reusable_sync ||
1897 disp->Extensions.KHR_fence_sync ||
1898 disp->Extensions.ANDROID_native_fence_sync);
1899
1900 if (s->SyncStatus == EGL_SIGNALED_KHR)
1901 RETURN_EGL_EVAL(disp, EGL_CONDITION_SATISFIED_KHR);
1902
1903 /* if sync type is EGL_SYNC_REUSABLE_KHR, dpy should be
1904 * unlocked here to allow other threads also to be able to
1905 * go into waiting state.
1906 */
1907
1908 if (s->Type == EGL_SYNC_REUSABLE_KHR)
1909 _eglUnlockDisplay(dpy);
1910
1911 ret = drv->API.ClientWaitSyncKHR(drv, disp, s, flags, timeout);
1912
1913 /*
1914 * 'disp' is already unlocked for reusable sync type,
1915 * so passing 'NULL' to bypass unlocking display.
1916 */
1917 if (s->Type == EGL_SYNC_REUSABLE_KHR)
1918 RETURN_EGL_EVAL(NULL, ret);
1919 else
1920 RETURN_EGL_EVAL(disp, ret);
1921 }
1922
1923 EGLint EGLAPIENTRY
1924 eglClientWaitSync(EGLDisplay dpy, EGLSync sync,
1925 EGLint flags, EGLTime timeout)
1926 {
1927 _EGLDisplay *disp = _eglLockDisplay(dpy);
1928 _EGLSync *s = _eglLookupSync(sync, disp);
1929 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
1930 return _eglClientWaitSyncCommon(disp, dpy, s, flags, timeout);
1931 }
1932
1933 static EGLint EGLAPIENTRY
1934 eglClientWaitSyncKHR(EGLDisplay dpy, EGLSync sync,
1935 EGLint flags, EGLTime timeout)
1936 {
1937 _EGLDisplay *disp = _eglLockDisplay(dpy);
1938 _EGLSync *s = _eglLookupSync(sync, disp);
1939 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
1940 return _eglClientWaitSyncCommon(disp, dpy, s, flags, timeout);
1941 }
1942
1943
1944 static EGLint
1945 _eglWaitSyncCommon(_EGLDisplay *disp, _EGLSync *s, EGLint flags)
1946 {
1947 _EGLContext *ctx = _eglGetCurrentContext();
1948 _EGLDriver *drv;
1949 EGLint ret;
1950
1951 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1952 assert(disp->Extensions.KHR_wait_sync);
1953
1954 /* return an error if the client API doesn't support GL_OES_EGL_sync */
1955 if (ctx == EGL_NO_CONTEXT || ctx->ClientAPI != EGL_OPENGL_ES_API)
1956 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
1957
1958 /* the API doesn't allow any flags yet */
1959 if (flags != 0)
1960 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1961
1962 ret = drv->API.WaitSyncKHR(drv, disp, s);
1963
1964 RETURN_EGL_EVAL(disp, ret);
1965 }
1966
1967 static EGLint EGLAPIENTRY
1968 eglWaitSyncKHR(EGLDisplay dpy, EGLSync sync, EGLint flags)
1969 {
1970 _EGLDisplay *disp = _eglLockDisplay(dpy);
1971 _EGLSync *s = _eglLookupSync(sync, disp);
1972 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
1973 return _eglWaitSyncCommon(disp, s, flags);
1974 }
1975
1976
1977 EGLBoolean EGLAPIENTRY
1978 eglWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags)
1979 {
1980 /* The KHR version returns EGLint, while the core version returns
1981 * EGLBoolean. In both cases, the return values can only be EGL_FALSE and
1982 * EGL_TRUE.
1983 */
1984 _EGLDisplay *disp = _eglLockDisplay(dpy);
1985 _EGLSync *s = _eglLookupSync(sync, disp);
1986 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
1987 return _eglWaitSyncCommon(disp, s, flags);
1988 }
1989
1990
1991 static EGLBoolean EGLAPIENTRY
1992 eglSignalSyncKHR(EGLDisplay dpy, EGLSync sync, EGLenum mode)
1993 {
1994 _EGLDisplay *disp = _eglLockDisplay(dpy);
1995 _EGLSync *s = _eglLookupSync(sync, disp);
1996 _EGLDriver *drv;
1997 EGLBoolean ret;
1998
1999 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2000
2001 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
2002 assert(disp->Extensions.KHR_reusable_sync);
2003 ret = drv->API.SignalSyncKHR(drv, disp, s, mode);
2004
2005 RETURN_EGL_EVAL(disp, ret);
2006 }
2007
2008
2009 static EGLBoolean
2010 _eglGetSyncAttribCommon(_EGLDisplay *disp, _EGLSync *s, EGLint attribute, EGLAttrib *value)
2011 {
2012 _EGLDriver *drv;
2013 EGLBoolean ret;
2014
2015 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
2016 assert(disp->Extensions.KHR_reusable_sync ||
2017 disp->Extensions.KHR_fence_sync ||
2018 disp->Extensions.ANDROID_native_fence_sync);
2019 ret = drv->API.GetSyncAttrib(drv, disp, s, attribute, value);
2020
2021 RETURN_EGL_EVAL(disp, ret);
2022 }
2023
2024 EGLBoolean EGLAPIENTRY
2025 eglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value)
2026 {
2027 _EGLDisplay *disp = _eglLockDisplay(dpy);
2028 _EGLSync *s = _eglLookupSync(sync, disp);
2029 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2030 return _eglGetSyncAttribCommon(disp, s, attribute, value);
2031 }
2032
2033
2034 static EGLBoolean EGLAPIENTRY
2035 eglGetSyncAttribKHR(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint *value)
2036 {
2037 _EGLDisplay *disp = _eglLockDisplay(dpy);
2038 _EGLSync *s = _eglLookupSync(sync, disp);
2039 EGLAttrib attrib;
2040 EGLBoolean result;
2041
2042 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2043
2044 if (!value)
2045 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2046
2047 attrib = *value;
2048 result = _eglGetSyncAttribCommon(disp, s, attribute, &attrib);
2049
2050 /* The EGL_KHR_fence_sync spec says this about eglGetSyncAttribKHR:
2051 *
2052 * If any error occurs, <*value> is not modified.
2053 */
2054 if (result == EGL_FALSE)
2055 return result;
2056
2057 *value = attrib;
2058 return result;
2059 }
2060
2061 static EGLint EGLAPIENTRY
2062 eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync)
2063 {
2064 _EGLDisplay *disp = _eglLockDisplay(dpy);
2065 _EGLSync *s = _eglLookupSync(sync, disp);
2066 _EGLDriver *drv;
2067 EGLBoolean ret;
2068
2069 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2070
2071 /* the spec doesn't seem to specify what happens if the fence
2072 * type is not EGL_SYNC_NATIVE_FENCE_ANDROID, but this seems
2073 * sensible:
2074 */
2075 if (!(s && (s->Type == EGL_SYNC_NATIVE_FENCE_ANDROID)))
2076 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_NATIVE_FENCE_FD_ANDROID);
2077
2078 _EGL_CHECK_SYNC(disp, s, EGL_NO_NATIVE_FENCE_FD_ANDROID, drv);
2079 assert(disp->Extensions.ANDROID_native_fence_sync);
2080 ret = drv->API.DupNativeFenceFDANDROID(drv, disp, s);
2081
2082 RETURN_EGL_EVAL(disp, ret);
2083 }
2084
2085 static EGLBoolean EGLAPIENTRY
2086 eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface,
2087 EGLint numRects, const EGLint *rects)
2088 {
2089 _EGLContext *ctx = _eglGetCurrentContext();
2090 _EGLDisplay *disp = _eglLockDisplay(dpy);
2091 _EGLSurface *surf = _eglLookupSurface(surface, disp);
2092 _EGLDriver *drv;
2093 EGLBoolean ret;
2094
2095 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
2096
2097 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
2098
2099 if (!disp->Extensions.NOK_swap_region)
2100 RETURN_EGL_EVAL(disp, EGL_FALSE);
2101
2102 /* surface must be bound to current context in EGL 1.4 */
2103 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
2104 surf != ctx->DrawSurface)
2105 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
2106
2107 ret = drv->API.SwapBuffersRegionNOK(drv, disp, surf, numRects, rects);
2108
2109 RETURN_EGL_EVAL(disp, ret);
2110 }
2111
2112
2113 static EGLImage EGLAPIENTRY
2114 eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list)
2115 {
2116 _EGLDisplay *disp = _eglLockDisplay(dpy);
2117 _EGLDriver *drv;
2118 _EGLImage *img;
2119 EGLImage ret;
2120
2121 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2122
2123 _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
2124 if (!disp->Extensions.MESA_drm_image)
2125 RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
2126
2127 img = drv->API.CreateDRMImageMESA(drv, disp, attr_list);
2128 ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
2129
2130 RETURN_EGL_EVAL(disp, ret);
2131 }
2132
2133 static EGLBoolean EGLAPIENTRY
2134 eglExportDRMImageMESA(EGLDisplay dpy, EGLImage image,
2135 EGLint *name, EGLint *handle, EGLint *stride)
2136 {
2137 _EGLDisplay *disp = _eglLockDisplay(dpy);
2138 _EGLImage *img = _eglLookupImage(image, disp);
2139 _EGLDriver *drv;
2140 EGLBoolean ret;
2141
2142 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
2143
2144 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2145 assert(disp->Extensions.MESA_drm_image);
2146
2147 if (!img)
2148 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2149
2150 ret = drv->API.ExportDRMImageMESA(drv, disp, img, name, handle, stride);
2151
2152 RETURN_EGL_EVAL(disp, ret);
2153 }
2154
2155
2156 struct wl_display;
2157
2158 static EGLBoolean EGLAPIENTRY
2159 eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
2160 {
2161 _EGLDisplay *disp = _eglLockDisplay(dpy);
2162 _EGLDriver *drv;
2163 EGLBoolean ret;
2164
2165 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2166
2167 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2168 assert(disp->Extensions.WL_bind_wayland_display);
2169
2170 if (!display)
2171 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2172
2173 ret = drv->API.BindWaylandDisplayWL(drv, disp, display);
2174
2175 RETURN_EGL_EVAL(disp, ret);
2176 }
2177
2178 static EGLBoolean EGLAPIENTRY
2179 eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
2180 {
2181 _EGLDisplay *disp = _eglLockDisplay(dpy);
2182 _EGLDriver *drv;
2183 EGLBoolean ret;
2184
2185 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2186
2187 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2188 assert(disp->Extensions.WL_bind_wayland_display);
2189
2190 if (!display)
2191 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2192
2193 ret = drv->API.UnbindWaylandDisplayWL(drv, disp, display);
2194
2195 RETURN_EGL_EVAL(disp, ret);
2196 }
2197
2198 static EGLBoolean EGLAPIENTRY
2199 eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer,
2200 EGLint attribute, EGLint *value)
2201 {
2202 _EGLDisplay *disp = _eglLockDisplay(dpy);
2203 _EGLDriver *drv;
2204 EGLBoolean ret;
2205
2206 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2207
2208 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2209 assert(disp->Extensions.WL_bind_wayland_display);
2210
2211 if (!buffer)
2212 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2213
2214 ret = drv->API.QueryWaylandBufferWL(drv, disp, buffer, attribute, value);
2215
2216 RETURN_EGL_EVAL(disp, ret);
2217 }
2218
2219
2220 static struct wl_buffer * EGLAPIENTRY
2221 eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImage image)
2222 {
2223 _EGLDisplay *disp = _eglLockDisplay(dpy);
2224 _EGLImage *img;
2225 _EGLDriver *drv;
2226 struct wl_buffer *ret;
2227
2228 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2229
2230 _EGL_CHECK_DISPLAY(disp, NULL, drv);
2231 if (!disp->Extensions.WL_create_wayland_buffer_from_image)
2232 RETURN_EGL_EVAL(disp, NULL);
2233
2234 img = _eglLookupImage(image, disp);
2235
2236 if (!img)
2237 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL);
2238
2239 ret = drv->API.CreateWaylandBufferFromImageWL(drv, disp, img);
2240
2241 RETURN_EGL_EVAL(disp, ret);
2242 }
2243
2244 static EGLBoolean EGLAPIENTRY
2245 eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface,
2246 EGLint x, EGLint y, EGLint width, EGLint height)
2247 {
2248 _EGLDisplay *disp = _eglLockDisplay(dpy);
2249 _EGLSurface *surf = _eglLookupSurface(surface, disp);
2250 _EGLDriver *drv;
2251 EGLBoolean ret;
2252
2253 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
2254
2255 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
2256
2257 if (!disp->Extensions.NV_post_sub_buffer)
2258 RETURN_EGL_EVAL(disp, EGL_FALSE);
2259
2260 ret = drv->API.PostSubBufferNV(drv, disp, surf, x, y, width, height);
2261
2262 RETURN_EGL_EVAL(disp, ret);
2263 }
2264
2265 static EGLBoolean EGLAPIENTRY
2266 eglGetSyncValuesCHROMIUM(EGLDisplay display, EGLSurface surface,
2267 EGLuint64KHR *ust, EGLuint64KHR *msc,
2268 EGLuint64KHR *sbc)
2269 {
2270 _EGLDisplay *disp = _eglLockDisplay(display);
2271 _EGLSurface *surf = _eglLookupSurface(surface, disp);
2272 _EGLDriver *drv;
2273 EGLBoolean ret;
2274
2275 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
2276
2277 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
2278 if (!disp->Extensions.CHROMIUM_sync_control)
2279 RETURN_EGL_EVAL(disp, EGL_FALSE);
2280
2281 if (!ust || !msc || !sbc)
2282 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2283
2284 ret = drv->API.GetSyncValuesCHROMIUM(disp, surf, ust, msc, sbc);
2285
2286 RETURN_EGL_EVAL(disp, ret);
2287 }
2288
2289 static EGLBoolean EGLAPIENTRY
2290 eglExportDMABUFImageQueryMESA(EGLDisplay dpy, EGLImage image,
2291 EGLint *fourcc, EGLint *nplanes,
2292 EGLuint64KHR *modifiers)
2293 {
2294 _EGLDisplay *disp = _eglLockDisplay(dpy);
2295 _EGLImage *img = _eglLookupImage(image, disp);
2296 _EGLDriver *drv;
2297 EGLBoolean ret;
2298
2299 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
2300
2301 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2302 assert(disp->Extensions.MESA_image_dma_buf_export);
2303
2304 if (!img)
2305 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2306
2307 ret = drv->API.ExportDMABUFImageQueryMESA(drv, disp, img, fourcc, nplanes,
2308 modifiers);
2309
2310 RETURN_EGL_EVAL(disp, ret);
2311 }
2312
2313 static EGLBoolean EGLAPIENTRY
2314 eglExportDMABUFImageMESA(EGLDisplay dpy, EGLImage image,
2315 int *fds, EGLint *strides, EGLint *offsets)
2316 {
2317 _EGLDisplay *disp = _eglLockDisplay(dpy);
2318 _EGLImage *img = _eglLookupImage(image, disp);
2319 _EGLDriver *drv;
2320 EGLBoolean ret;
2321
2322 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
2323
2324 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2325 assert(disp->Extensions.MESA_image_dma_buf_export);
2326
2327 if (!img)
2328 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2329
2330 ret = drv->API.ExportDMABUFImageMESA(drv, disp, img, fds, strides, offsets);
2331
2332 RETURN_EGL_EVAL(disp, ret);
2333 }
2334
2335 static EGLint EGLAPIENTRY
2336 eglLabelObjectKHR(EGLDisplay dpy, EGLenum objectType, EGLObjectKHR object,
2337 EGLLabelKHR label)
2338 {
2339 _EGLDisplay *disp = NULL;
2340 _EGLResourceType type;
2341
2342 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
2343
2344 if (objectType == EGL_OBJECT_THREAD_KHR) {
2345 _EGLThreadInfo *t = _eglGetCurrentThread();
2346
2347 if (!_eglIsCurrentThreadDummy()) {
2348 t->Label = label;
2349 return EGL_SUCCESS;
2350 }
2351
2352 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_BAD_ALLOC);
2353 }
2354
2355 disp = _eglLockDisplay(dpy);
2356 if (disp == NULL)
2357 RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_BAD_DISPLAY);
2358
2359 if (objectType == EGL_OBJECT_DISPLAY_KHR) {
2360 if (dpy != (EGLDisplay) object)
2361 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
2362
2363 disp->Label = label;
2364 RETURN_EGL_EVAL(disp, EGL_SUCCESS);
2365 }
2366
2367 switch (objectType) {
2368 case EGL_OBJECT_CONTEXT_KHR:
2369 type = _EGL_RESOURCE_CONTEXT;
2370 break;
2371 case EGL_OBJECT_SURFACE_KHR:
2372 type = _EGL_RESOURCE_SURFACE;
2373 break;
2374 case EGL_OBJECT_IMAGE_KHR:
2375 type = _EGL_RESOURCE_IMAGE;
2376 break;
2377 case EGL_OBJECT_SYNC_KHR:
2378 type = _EGL_RESOURCE_SYNC;
2379 break;
2380 case EGL_OBJECT_STREAM_KHR:
2381 default:
2382 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
2383 }
2384
2385 if (_eglCheckResource(object, type, disp)) {
2386 _EGLResource *res = (_EGLResource *) object;
2387
2388 res->Label = label;
2389 RETURN_EGL_EVAL(disp, EGL_SUCCESS);
2390 }
2391
2392 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
2393 }
2394
2395 static EGLint EGLAPIENTRY
2396 eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback,
2397 const EGLAttrib *attrib_list)
2398 {
2399 unsigned int newEnabled;
2400
2401 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
2402
2403 mtx_lock(_eglGlobal.Mutex);
2404
2405 newEnabled = _eglGlobal.debugTypesEnabled;
2406 if (attrib_list != NULL) {
2407 int i;
2408
2409 for (i = 0; attrib_list[i] != EGL_NONE; i += 2) {
2410 switch (attrib_list[i]) {
2411 case EGL_DEBUG_MSG_CRITICAL_KHR:
2412 case EGL_DEBUG_MSG_ERROR_KHR:
2413 case EGL_DEBUG_MSG_WARN_KHR:
2414 case EGL_DEBUG_MSG_INFO_KHR:
2415 if (attrib_list[i + 1])
2416 newEnabled |= DebugBitFromType(attrib_list[i]);
2417 else
2418 newEnabled &= ~DebugBitFromType(attrib_list[i]);
2419 break;
2420 default:
2421 // On error, set the last error code, call the current
2422 // debug callback, and return the error code.
2423 mtx_unlock(_eglGlobal.Mutex);
2424 _eglReportError(EGL_BAD_ATTRIBUTE, NULL,
2425 "Invalid attribute 0x%04lx", (unsigned long) attrib_list[i]);
2426 return EGL_BAD_ATTRIBUTE;
2427 }
2428 }
2429 }
2430
2431 if (callback != NULL) {
2432 _eglGlobal.debugCallback = callback;
2433 _eglGlobal.debugTypesEnabled = newEnabled;
2434 } else {
2435 _eglGlobal.debugCallback = NULL;
2436 _eglGlobal.debugTypesEnabled = _EGL_DEBUG_BIT_CRITICAL | _EGL_DEBUG_BIT_ERROR;
2437 }
2438
2439 mtx_unlock(_eglGlobal.Mutex);
2440 return EGL_SUCCESS;
2441 }
2442
2443 static EGLBoolean EGLAPIENTRY
2444 eglQueryDebugKHR(EGLint attribute, EGLAttrib *value)
2445 {
2446 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
2447
2448 mtx_lock(_eglGlobal.Mutex);
2449
2450 switch (attribute) {
2451 case EGL_DEBUG_MSG_CRITICAL_KHR:
2452 case EGL_DEBUG_MSG_ERROR_KHR:
2453 case EGL_DEBUG_MSG_WARN_KHR:
2454 case EGL_DEBUG_MSG_INFO_KHR:
2455 if (_eglGlobal.debugTypesEnabled & DebugBitFromType(attribute))
2456 *value = EGL_TRUE;
2457 else
2458 *value = EGL_FALSE;
2459 break;
2460 case EGL_DEBUG_CALLBACK_KHR:
2461 *value = (EGLAttrib) _eglGlobal.debugCallback;
2462 break;
2463 default:
2464 mtx_unlock(_eglGlobal.Mutex);
2465 _eglReportError(EGL_BAD_ATTRIBUTE, NULL,
2466 "Invalid attribute 0x%04lx", (unsigned long) attribute);
2467 return EGL_FALSE;
2468 }
2469
2470 mtx_unlock(_eglGlobal.Mutex);
2471 return EGL_TRUE;
2472 }
2473
2474 static int
2475 _eglFunctionCompare(const void *key, const void *elem)
2476 {
2477 const char *procname = key;
2478 const struct _egl_entrypoint *entrypoint = elem;
2479 return strcmp(procname, entrypoint->name);
2480 }
2481
2482 static EGLBoolean EGLAPIENTRY
2483 eglQueryDmaBufFormatsEXT(EGLDisplay dpy, EGLint max_formats,
2484 EGLint *formats, EGLint *num_formats)
2485 {
2486 _EGLDisplay *disp = _eglLockDisplay(dpy);
2487 _EGLDriver *drv;
2488 EGLBoolean ret;
2489
2490 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2491
2492 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2493
2494 ret = drv->API.QueryDmaBufFormatsEXT(drv, disp, max_formats, formats,
2495 num_formats);
2496
2497 RETURN_EGL_EVAL(disp, ret);
2498 }
2499
2500 static EGLBoolean EGLAPIENTRY
2501 eglQueryDmaBufModifiersEXT(EGLDisplay dpy, EGLint format, EGLint max_modifiers,
2502 EGLuint64KHR *modifiers, EGLBoolean *external_only,
2503 EGLint *num_modifiers)
2504 {
2505 _EGLDisplay *disp = _eglLockDisplay(dpy);
2506 _EGLDriver *drv;
2507 EGLBoolean ret;
2508
2509 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2510
2511 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2512
2513 ret = drv->API.QueryDmaBufModifiersEXT(drv, disp, format, max_modifiers,
2514 modifiers, external_only,
2515 num_modifiers);
2516
2517 RETURN_EGL_EVAL(disp, ret);
2518 }
2519
2520 __eglMustCastToProperFunctionPointerType EGLAPIENTRY
2521 eglGetProcAddress(const char *procname)
2522 {
2523 static const struct _egl_entrypoint egl_functions[] = {
2524 #define EGL_ENTRYPOINT(f) { .name = #f, .function = (_EGLProc) f },
2525 #include "eglentrypoint.h"
2526 #undef EGL_ENTRYPOINT
2527 };
2528 _EGLProc ret = NULL;
2529
2530 if (!procname)
2531 RETURN_EGL_SUCCESS(NULL, NULL);
2532
2533 _EGL_FUNC_START(NULL, EGL_NONE, NULL, NULL);
2534
2535 if (strncmp(procname, "egl", 3) == 0) {
2536 const struct _egl_entrypoint *entrypoint =
2537 bsearch(procname,
2538 egl_functions, ARRAY_SIZE(egl_functions),
2539 sizeof(egl_functions[0]),
2540 _eglFunctionCompare);
2541 if (entrypoint)
2542 ret = entrypoint->function;
2543 }
2544
2545 if (!ret)
2546 ret = _eglGetDriverProc(procname);
2547
2548 RETURN_EGL_SUCCESS(NULL, ret);
2549 }
2550
2551 static int
2552 _eglLockDisplayInterop(EGLDisplay dpy, EGLContext context,
2553 _EGLDisplay **disp, _EGLDriver **drv,
2554 _EGLContext **ctx)
2555 {
2556
2557 *disp = _eglLockDisplay(dpy);
2558 if (!*disp || !(*disp)->Initialized || !(*disp)->Driver) {
2559 if (*disp)
2560 _eglUnlockDisplay(*disp);
2561 return MESA_GLINTEROP_INVALID_DISPLAY;
2562 }
2563
2564 *drv = (*disp)->Driver;
2565
2566 *ctx = _eglLookupContext(context, *disp);
2567 if (!*ctx ||
2568 ((*ctx)->ClientAPI != EGL_OPENGL_API &&
2569 (*ctx)->ClientAPI != EGL_OPENGL_ES_API)) {
2570 _eglUnlockDisplay(*disp);
2571 return MESA_GLINTEROP_INVALID_CONTEXT;
2572 }
2573
2574 return MESA_GLINTEROP_SUCCESS;
2575 }
2576
2577 PUBLIC int
2578 MesaGLInteropEGLQueryDeviceInfo(EGLDisplay dpy, EGLContext context,
2579 struct mesa_glinterop_device_info *out)
2580 {
2581 _EGLDisplay *disp;
2582 _EGLDriver *drv;
2583 _EGLContext *ctx;
2584 int ret;
2585
2586 ret = _eglLockDisplayInterop(dpy, context, &disp, &drv, &ctx);
2587 if (ret != MESA_GLINTEROP_SUCCESS)
2588 return ret;
2589
2590 if (drv->API.GLInteropQueryDeviceInfo)
2591 ret = drv->API.GLInteropQueryDeviceInfo(disp, ctx, out);
2592 else
2593 ret = MESA_GLINTEROP_UNSUPPORTED;
2594
2595 _eglUnlockDisplay(disp);
2596 return ret;
2597 }
2598
2599 PUBLIC int
2600 MesaGLInteropEGLExportObject(EGLDisplay dpy, EGLContext context,
2601 struct mesa_glinterop_export_in *in,
2602 struct mesa_glinterop_export_out *out)
2603 {
2604 _EGLDisplay *disp;
2605 _EGLDriver *drv;
2606 _EGLContext *ctx;
2607 int ret;
2608
2609 ret = _eglLockDisplayInterop(dpy, context, &disp, &drv, &ctx);
2610 if (ret != MESA_GLINTEROP_SUCCESS)
2611 return ret;
2612
2613 if (drv->API.GLInteropExportObject)
2614 ret = drv->API.GLInteropExportObject(disp, ctx, in, out);
2615 else
2616 ret = MESA_GLINTEROP_UNSUPPORTED;
2617
2618 _eglUnlockDisplay(disp);
2619 return ret;
2620 }