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