61a3220705d72a2a6adeebcef78b2abc5ea6d490
[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 /* In EGL specs 1.4 and 1.5, at the end of sections 3.5.1 and 3.5.4, it says
894 * that if native_surface was already used to create a window or pixmap, we
895 * can't create a new one. This is what this function checks for.
896 */
897 static bool
898 _eglNativeSurfaceAlreadyUsed(_EGLDisplay *disp, void *native_surface)
899 {
900 _EGLResource *list;
901
902 list = disp->ResourceLists[_EGL_RESOURCE_SURFACE];
903 while (list) {
904 _EGLSurface *surf = (_EGLSurface *) list;
905
906 list = list->Next;
907
908 if (surf->Type == EGL_PBUFFER_BIT)
909 continue;
910
911 if (surf->NativeSurface == native_surface)
912 return true;
913 }
914
915 return false;
916 }
917
918
919 static EGLSurface
920 _eglCreateWindowSurfaceCommon(_EGLDisplay *disp, EGLConfig config,
921 void *native_window, const EGLint *attrib_list)
922 {
923 _EGLConfig *conf = _eglLookupConfig(config, disp);
924 _EGLDriver *drv;
925 _EGLSurface *surf;
926 EGLSurface ret;
927
928
929 if (native_window == NULL)
930 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
931
932 #ifdef HAVE_SURFACELESS_PLATFORM
933 if (disp && disp->Platform == _EGL_PLATFORM_SURFACELESS) {
934 /* From the EGL_MESA_platform_surfaceless spec (v1):
935 *
936 * eglCreatePlatformWindowSurface fails when called with a <display>
937 * that belongs to the surfaceless platform. It returns
938 * EGL_NO_SURFACE and generates EGL_BAD_NATIVE_WINDOW. The
939 * justification for this unconditional failure is that the
940 * surfaceless platform has no native windows, and therefore the
941 * <native_window> parameter is always invalid.
942 *
943 * This check must occur before checking the EGLConfig, which emits
944 * EGL_BAD_CONFIG.
945 */
946 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
947 }
948 #endif
949
950 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
951
952 if ((conf->SurfaceType & EGL_WINDOW_BIT) == 0)
953 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE);
954
955 if (_eglNativeSurfaceAlreadyUsed(disp, native_window))
956 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
957
958 surf = drv->API.CreateWindowSurface(drv, disp, conf, native_window,
959 attrib_list);
960 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
961
962 RETURN_EGL_EVAL(disp, ret);
963 }
964
965
966 EGLSurface EGLAPIENTRY
967 eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
968 EGLNativeWindowType window, const EGLint *attrib_list)
969 {
970 _EGLDisplay *disp = _eglLockDisplay(dpy);
971
972 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
973 STATIC_ASSERT(sizeof(void*) == sizeof(window));
974 return _eglCreateWindowSurfaceCommon(disp, config, (void*) window,
975 attrib_list);
976 }
977
978 static void *
979 _fixupNativeWindow(_EGLDisplay *disp, void *native_window)
980 {
981 #ifdef HAVE_X11_PLATFORM
982 if (disp && disp->Platform == _EGL_PLATFORM_X11 && native_window != NULL) {
983 /* The `native_window` parameter for the X11 platform differs between
984 * eglCreateWindowSurface() and eglCreatePlatformPixmapSurfaceEXT(). In
985 * eglCreateWindowSurface(), the type of `native_window` is an Xlib
986 * `Window`. In eglCreatePlatformWindowSurfaceEXT(), the type is
987 * `Window*`. Convert `Window*` to `Window` because that's what
988 * dri2_x11_create_window_surface() expects.
989 */
990 return (void *)(* (Window*) native_window);
991 }
992 #endif
993 return native_window;
994 }
995
996 static EGLSurface EGLAPIENTRY
997 eglCreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config,
998 void *native_window,
999 const EGLint *attrib_list)
1000 {
1001 _EGLDisplay *disp = _eglLockDisplay(dpy);
1002
1003 native_window = _fixupNativeWindow(disp, native_window);
1004
1005 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1006 return _eglCreateWindowSurfaceCommon(disp, config, native_window,
1007 attrib_list);
1008 }
1009
1010
1011 EGLSurface EGLAPIENTRY
1012 eglCreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config,
1013 void *native_window,
1014 const EGLAttrib *attrib_list)
1015 {
1016 _EGLDisplay *disp = _eglLockDisplay(dpy);
1017 EGLSurface surface;
1018 EGLint *int_attribs;
1019
1020 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1021
1022 int_attribs = _eglConvertAttribsToInt(attrib_list);
1023 if (attrib_list && !int_attribs)
1024 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
1025
1026 native_window = _fixupNativeWindow(disp, native_window);
1027 surface = _eglCreateWindowSurfaceCommon(disp, config, native_window,
1028 int_attribs);
1029 free(int_attribs);
1030 return surface;
1031 }
1032
1033 static void *
1034 _fixupNativePixmap(_EGLDisplay *disp, void *native_pixmap)
1035 {
1036 #ifdef HAVE_X11_PLATFORM
1037 /* The `native_pixmap` parameter for the X11 platform differs between
1038 * eglCreatePixmapSurface() and eglCreatePlatformPixmapSurfaceEXT(). In
1039 * eglCreatePixmapSurface(), the type of `native_pixmap` is an Xlib
1040 * `Pixmap`. In eglCreatePlatformPixmapSurfaceEXT(), the type is
1041 * `Pixmap*`. Convert `Pixmap*` to `Pixmap` because that's what
1042 * dri2_x11_create_pixmap_surface() expects.
1043 */
1044 if (disp && disp->Platform == _EGL_PLATFORM_X11 && native_pixmap != NULL)
1045 return (void *)(* (Pixmap*) native_pixmap);
1046 #endif
1047 return native_pixmap;
1048 }
1049
1050 static EGLSurface
1051 _eglCreatePixmapSurfaceCommon(_EGLDisplay *disp, EGLConfig config,
1052 void *native_pixmap, const EGLint *attrib_list)
1053 {
1054 _EGLConfig *conf = _eglLookupConfig(config, disp);
1055 _EGLDriver *drv;
1056 _EGLSurface *surf;
1057 EGLSurface ret;
1058
1059 #if HAVE_SURFACELESS_PLATFORM
1060 if (disp && disp->Platform == _EGL_PLATFORM_SURFACELESS) {
1061 /* From the EGL_MESA_platform_surfaceless spec (v1):
1062 *
1063 * [Like eglCreatePlatformWindowSurface,] eglCreatePlatformPixmapSurface
1064 * also fails when called with a <display> that belongs to the
1065 * surfaceless platform. It returns EGL_NO_SURFACE and generates
1066 * EGL_BAD_NATIVE_PIXMAP.
1067 *
1068 * This check must occur before checking the EGLConfig, which emits
1069 * EGL_BAD_CONFIG.
1070 */
1071 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
1072 }
1073 #endif
1074
1075 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
1076
1077 if ((conf->SurfaceType & EGL_PIXMAP_BIT) == 0)
1078 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE);
1079
1080 if (native_pixmap == NULL)
1081 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
1082
1083 if (_eglNativeSurfaceAlreadyUsed(disp, native_pixmap))
1084 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
1085
1086 surf = drv->API.CreatePixmapSurface(drv, disp, conf, native_pixmap,
1087 attrib_list);
1088 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1089
1090 RETURN_EGL_EVAL(disp, ret);
1091 }
1092
1093
1094 EGLSurface EGLAPIENTRY
1095 eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
1096 EGLNativePixmapType pixmap, const EGLint *attrib_list)
1097 {
1098 _EGLDisplay *disp = _eglLockDisplay(dpy);
1099
1100 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1101 STATIC_ASSERT(sizeof(void*) == sizeof(pixmap));
1102 return _eglCreatePixmapSurfaceCommon(disp, config, (void*) pixmap,
1103 attrib_list);
1104 }
1105
1106 static EGLSurface EGLAPIENTRY
1107 eglCreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config,
1108 void *native_pixmap,
1109 const EGLint *attrib_list)
1110 {
1111 _EGLDisplay *disp = _eglLockDisplay(dpy);
1112
1113 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1114 native_pixmap = _fixupNativePixmap(disp, native_pixmap);
1115 return _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap,
1116 attrib_list);
1117 }
1118
1119
1120 EGLSurface EGLAPIENTRY
1121 eglCreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config,
1122 void *native_pixmap,
1123 const EGLAttrib *attrib_list)
1124 {
1125 _EGLDisplay *disp = _eglLockDisplay(dpy);
1126 EGLSurface surface;
1127 EGLint *int_attribs;
1128
1129 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1130
1131 int_attribs = _eglConvertAttribsToInt(attrib_list);
1132 if (attrib_list && !int_attribs)
1133 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
1134
1135 native_pixmap = _fixupNativePixmap(disp, native_pixmap);
1136 surface = _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap,
1137 int_attribs);
1138 free(int_attribs);
1139 return surface;
1140 }
1141
1142
1143 EGLSurface EGLAPIENTRY
1144 eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
1145 const EGLint *attrib_list)
1146 {
1147 _EGLDisplay *disp = _eglLockDisplay(dpy);
1148 _EGLConfig *conf = _eglLookupConfig(config, disp);
1149 _EGLDriver *drv;
1150 _EGLSurface *surf;
1151 EGLSurface ret;
1152
1153 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1154 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
1155
1156 if ((conf->SurfaceType & EGL_PBUFFER_BIT) == 0)
1157 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE);
1158
1159 surf = drv->API.CreatePbufferSurface(drv, disp, conf, attrib_list);
1160 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1161
1162 RETURN_EGL_EVAL(disp, ret);
1163 }
1164
1165
1166 EGLBoolean EGLAPIENTRY
1167 eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
1168 {
1169 _EGLDisplay *disp = _eglLockDisplay(dpy);
1170 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1171 _EGLDriver *drv;
1172 EGLBoolean ret;
1173
1174 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1175 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1176 _eglUnlinkSurface(surf);
1177 ret = drv->API.DestroySurface(drv, disp, surf);
1178
1179 RETURN_EGL_EVAL(disp, ret);
1180 }
1181
1182 EGLBoolean EGLAPIENTRY
1183 eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
1184 EGLint attribute, EGLint *value)
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.QuerySurface(drv, disp, surf, attribute, value);
1194
1195 RETURN_EGL_EVAL(disp, ret);
1196 }
1197
1198 EGLBoolean EGLAPIENTRY
1199 eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
1200 EGLint attribute, EGLint value)
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.SurfaceAttrib(drv, disp, surf, attribute, value);
1210
1211 RETURN_EGL_EVAL(disp, ret);
1212 }
1213
1214
1215 EGLBoolean EGLAPIENTRY
1216 eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1217 {
1218 _EGLDisplay *disp = _eglLockDisplay(dpy);
1219 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1220 _EGLDriver *drv;
1221 EGLBoolean ret;
1222
1223 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1224 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1225 ret = drv->API.BindTexImage(drv, disp, surf, buffer);
1226
1227 RETURN_EGL_EVAL(disp, ret);
1228 }
1229
1230
1231 EGLBoolean EGLAPIENTRY
1232 eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1233 {
1234 _EGLDisplay *disp = _eglLockDisplay(dpy);
1235 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1236 _EGLDriver *drv;
1237 EGLBoolean ret;
1238
1239 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1240 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1241 ret = drv->API.ReleaseTexImage(drv, disp, surf, buffer);
1242
1243 RETURN_EGL_EVAL(disp, ret);
1244 }
1245
1246
1247 EGLBoolean EGLAPIENTRY
1248 eglSwapInterval(EGLDisplay dpy, EGLint interval)
1249 {
1250 _EGLDisplay *disp = _eglLockDisplay(dpy);
1251 _EGLContext *ctx = _eglGetCurrentContext();
1252 _EGLSurface *surf = ctx ? ctx->DrawSurface : NULL;
1253 _EGLDriver *drv;
1254 EGLBoolean ret;
1255
1256 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1257 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1258
1259 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1260 ctx->Resource.Display != disp)
1261 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
1262
1263 if (_eglGetSurfaceHandle(surf) == EGL_NO_SURFACE)
1264 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1265
1266 if (surf->Type != EGL_WINDOW_BIT)
1267 RETURN_EGL_EVAL(disp, EGL_TRUE);
1268
1269 interval = CLAMP(interval,
1270 surf->Config->MinSwapInterval,
1271 surf->Config->MaxSwapInterval);
1272
1273 if (surf->SwapInterval != interval)
1274 ret = drv->API.SwapInterval(drv, disp, surf, interval);
1275 else
1276 ret = EGL_TRUE;
1277
1278 if (ret)
1279 surf->SwapInterval = interval;
1280
1281 RETURN_EGL_EVAL(disp, ret);
1282 }
1283
1284
1285 EGLBoolean EGLAPIENTRY
1286 eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1287 {
1288 _EGLContext *ctx = _eglGetCurrentContext();
1289 _EGLDisplay *disp = _eglLockDisplay(dpy);
1290 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1291 _EGLDriver *drv;
1292 EGLBoolean ret;
1293
1294 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1295 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1296
1297 /* surface must be bound to current context in EGL 1.4 */
1298 #ifndef _EGL_BUILT_IN_DRIVER_HAIKU
1299 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1300 surf != ctx->DrawSurface)
1301 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1302 #endif
1303
1304 if (surf->Type != EGL_WINDOW_BIT)
1305 RETURN_EGL_EVAL(disp, EGL_TRUE);
1306
1307 /* From the EGL 1.5 spec:
1308 *
1309 * If eglSwapBuffers is called and the native window associated with
1310 * surface is no longer valid, an EGL_BAD_NATIVE_WINDOW error is
1311 * generated.
1312 */
1313 if (surf->Lost)
1314 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE);
1315
1316 ret = drv->API.SwapBuffers(drv, disp, surf);
1317
1318 /* EGL_KHR_partial_update
1319 * Frame boundary successfully reached,
1320 * reset damage region and reset BufferAgeRead
1321 */
1322 if (ret) {
1323 surf->SetDamageRegionCalled = EGL_FALSE;
1324 surf->BufferAgeRead = EGL_FALSE;
1325 }
1326
1327 RETURN_EGL_EVAL(disp, ret);
1328 }
1329
1330
1331 static EGLBoolean
1332 _eglSwapBuffersWithDamageCommon(_EGLDisplay *disp, _EGLSurface *surf,
1333 EGLint *rects, EGLint n_rects)
1334 {
1335 _EGLContext *ctx = _eglGetCurrentContext();
1336 _EGLDriver *drv;
1337 EGLBoolean ret;
1338
1339 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1340
1341 /* surface must be bound to current context in EGL 1.4 */
1342 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1343 surf != ctx->DrawSurface)
1344 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1345
1346 if (surf->Type != EGL_WINDOW_BIT)
1347 RETURN_EGL_EVAL(disp, EGL_TRUE);
1348
1349 if ((n_rects > 0 && rects == NULL) || n_rects < 0)
1350 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1351
1352 ret = drv->API.SwapBuffersWithDamageEXT(drv, disp, surf, rects, n_rects);
1353
1354 /* EGL_KHR_partial_update
1355 * Frame boundary successfully reached,
1356 * reset damage region and reset BufferAgeRead
1357 */
1358 if (ret) {
1359 surf->SetDamageRegionCalled = EGL_FALSE;
1360 surf->BufferAgeRead = EGL_FALSE;
1361 }
1362
1363 RETURN_EGL_EVAL(disp, ret);
1364 }
1365
1366 static EGLBoolean EGLAPIENTRY
1367 eglSwapBuffersWithDamageEXT(EGLDisplay dpy, EGLSurface surface,
1368 EGLint *rects, EGLint n_rects)
1369 {
1370 _EGLDisplay *disp = _eglLockDisplay(dpy);
1371 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1372 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1373 return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects);
1374 }
1375
1376 static EGLBoolean EGLAPIENTRY
1377 eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface surface,
1378 EGLint *rects, EGLint n_rects)
1379 {
1380 _EGLDisplay *disp = _eglLockDisplay(dpy);
1381 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1382 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1383 return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects);
1384 }
1385
1386 /**
1387 * Clamp the rectangles so that they lie within the surface.
1388 */
1389
1390 static void
1391 _eglSetDamageRegionKHRClampRects(_EGLDisplay* disp, _EGLSurface* surf,
1392 EGLint *rects, EGLint n_rects)
1393 {
1394 EGLint i;
1395 EGLint surf_height = surf->Height;
1396 EGLint surf_width = surf->Width;
1397
1398 for (i = 0; i < (4 * n_rects); i += 4) {
1399 EGLint x1, y1, x2, y2;
1400 x1 = rects[i];
1401 y1 = rects[i + 1];
1402 x2 = rects[i + 2] + x1;
1403 y2 = rects[i + 3] + y1;
1404
1405 rects[i] = CLAMP(x1, 0, surf_width);
1406 rects[i + 1] = CLAMP(y1, 0, surf_height);
1407 rects[i + 2] = CLAMP(x2, 0, surf_width) - rects[i];
1408 rects[i + 3] = CLAMP(y2, 0, surf_height) - rects[i + 1];
1409 }
1410 }
1411
1412 static EGLBoolean EGLAPIENTRY
1413 eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
1414 EGLint *rects, EGLint n_rects)
1415 {
1416 _EGLDisplay *disp = _eglLockDisplay(dpy);
1417 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1418 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1419 _EGLContext *ctx = _eglGetCurrentContext();
1420 _EGLDriver *drv;
1421 EGLBoolean ret;
1422 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1423
1424 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1425 surf->Type != EGL_WINDOW_BIT ||
1426 ctx->DrawSurface != surf ||
1427 surf->SwapBehavior != EGL_BUFFER_DESTROYED)
1428 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
1429
1430 /* If the damage region is already set or
1431 * buffer age is not queried between
1432 * frame boundaries, throw bad access error
1433 */
1434
1435 if (surf->SetDamageRegionCalled || !surf->BufferAgeRead)
1436 RETURN_EGL_ERROR(disp, EGL_BAD_ACCESS, EGL_FALSE);
1437
1438 _eglSetDamageRegionKHRClampRects(disp, surf, rects, n_rects);
1439 ret = drv->API.SetDamageRegion(drv, disp, surf, rects, n_rects);
1440
1441 if (ret)
1442 surf->SetDamageRegionCalled = EGL_TRUE;
1443
1444 RETURN_EGL_EVAL(disp, ret);
1445 }
1446
1447 EGLBoolean EGLAPIENTRY
1448 eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1449 {
1450 _EGLDisplay *disp = _eglLockDisplay(dpy);
1451 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1452 _EGLDriver *drv;
1453 EGLBoolean ret;
1454 void *native_pixmap_ptr;
1455
1456 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1457 STATIC_ASSERT(sizeof(void*) == sizeof(target));
1458 native_pixmap_ptr = (void*) target;
1459
1460 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1461 ret = drv->API.CopyBuffers(drv, disp, surf, native_pixmap_ptr);
1462
1463 RETURN_EGL_EVAL(disp, ret);
1464 }
1465
1466
1467 static EGLBoolean
1468 _eglWaitClientCommon(void)
1469 {
1470 _EGLContext *ctx = _eglGetCurrentContext();
1471 _EGLDisplay *disp;
1472 _EGLDriver *drv;
1473 EGLBoolean ret;
1474
1475 if (!ctx)
1476 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1477
1478 disp = ctx->Resource.Display;
1479 mtx_lock(&disp->Mutex);
1480
1481 /* let bad current context imply bad current surface */
1482 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1483 _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
1484 RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
1485
1486 /* a valid current context implies an initialized current display */
1487 assert(disp->Initialized);
1488 drv = disp->Driver;
1489 ret = drv->API.WaitClient(drv, disp, ctx);
1490
1491 RETURN_EGL_EVAL(disp, ret);
1492 }
1493
1494 EGLBoolean EGLAPIENTRY
1495 eglWaitClient(void)
1496 {
1497 _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE);
1498 return _eglWaitClientCommon();
1499 }
1500
1501 EGLBoolean EGLAPIENTRY
1502 eglWaitGL(void)
1503 {
1504 /* Since we only support OpenGL and GLES, eglWaitGL is equivalent to eglWaitClient. */
1505 _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE);
1506 return _eglWaitClientCommon();
1507 }
1508
1509
1510 EGLBoolean EGLAPIENTRY
1511 eglWaitNative(EGLint engine)
1512 {
1513 _EGLContext *ctx = _eglGetCurrentContext();
1514 _EGLDisplay *disp;
1515 _EGLDriver *drv;
1516 EGLBoolean ret;
1517
1518 if (!ctx)
1519 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1520
1521 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
1522
1523 disp = ctx->Resource.Display;
1524 mtx_lock(&disp->Mutex);
1525
1526 /* let bad current context imply bad current surface */
1527 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1528 _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
1529 RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
1530
1531 /* a valid current context implies an initialized current display */
1532 assert(disp->Initialized);
1533 drv = disp->Driver;
1534 ret = drv->API.WaitNative(drv, disp, engine);
1535
1536 RETURN_EGL_EVAL(disp, ret);
1537 }
1538
1539
1540 EGLDisplay EGLAPIENTRY
1541 eglGetCurrentDisplay(void)
1542 {
1543 _EGLContext *ctx = _eglGetCurrentContext();
1544 EGLDisplay ret;
1545
1546 ret = (ctx) ? _eglGetDisplayHandle(ctx->Resource.Display) : EGL_NO_DISPLAY;
1547
1548 RETURN_EGL_SUCCESS(NULL, ret);
1549 }
1550
1551
1552 EGLContext EGLAPIENTRY
1553 eglGetCurrentContext(void)
1554 {
1555 _EGLContext *ctx = _eglGetCurrentContext();
1556 EGLContext ret;
1557
1558 ret = _eglGetContextHandle(ctx);
1559
1560 RETURN_EGL_SUCCESS(NULL, ret);
1561 }
1562
1563
1564 EGLSurface EGLAPIENTRY
1565 eglGetCurrentSurface(EGLint readdraw)
1566 {
1567 _EGLContext *ctx = _eglGetCurrentContext();
1568 EGLint err = EGL_SUCCESS;
1569 _EGLSurface *surf;
1570 EGLSurface ret;
1571
1572 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_NO_SURFACE);
1573
1574 if (!ctx)
1575 RETURN_EGL_SUCCESS(NULL, EGL_NO_SURFACE);
1576
1577 switch (readdraw) {
1578 case EGL_DRAW:
1579 surf = ctx->DrawSurface;
1580 break;
1581 case EGL_READ:
1582 surf = ctx->ReadSurface;
1583 break;
1584 default:
1585 surf = NULL;
1586 err = EGL_BAD_PARAMETER;
1587 break;
1588 }
1589
1590 ret = _eglGetSurfaceHandle(surf);
1591
1592 RETURN_EGL_ERROR(NULL, err, ret);
1593 }
1594
1595
1596 EGLint EGLAPIENTRY
1597 eglGetError(void)
1598 {
1599 _EGLThreadInfo *t = _eglGetCurrentThread();
1600 EGLint e = t->LastError;
1601 if (!_eglIsCurrentThreadDummy())
1602 t->LastError = EGL_SUCCESS;
1603 return e;
1604 }
1605
1606
1607 /**
1608 ** EGL 1.2
1609 **/
1610
1611 /**
1612 * Specify the client API to use for subsequent calls including:
1613 * eglCreateContext()
1614 * eglGetCurrentContext()
1615 * eglGetCurrentDisplay()
1616 * eglGetCurrentSurface()
1617 * eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT)
1618 * eglWaitClient()
1619 * eglWaitNative()
1620 * See section 3.7 "Rendering Context" in the EGL specification for details.
1621 */
1622 EGLBoolean EGLAPIENTRY
1623 eglBindAPI(EGLenum api)
1624 {
1625 _EGLThreadInfo *t;
1626
1627 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
1628
1629 t = _eglGetCurrentThread();
1630 if (_eglIsCurrentThreadDummy())
1631 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
1632
1633 if (!_eglIsApiValid(api))
1634 RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, EGL_FALSE);
1635
1636 t->CurrentAPI = api;
1637
1638 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1639 }
1640
1641
1642 /**
1643 * Return the last value set with eglBindAPI().
1644 */
1645 EGLenum EGLAPIENTRY
1646 eglQueryAPI(void)
1647 {
1648 _EGLThreadInfo *t = _eglGetCurrentThread();
1649 EGLenum ret;
1650
1651 /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */
1652 ret = t->CurrentAPI;
1653
1654 RETURN_EGL_SUCCESS(NULL, ret);
1655 }
1656
1657
1658 EGLSurface EGLAPIENTRY
1659 eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
1660 EGLClientBuffer buffer, EGLConfig config,
1661 const EGLint *attrib_list)
1662 {
1663 _EGLDisplay *disp = _eglLockDisplay(dpy);
1664 _EGLConfig *conf = _eglLookupConfig(config, disp);
1665 _EGLDriver *drv;
1666 _EGLSurface *surf;
1667 EGLSurface ret;
1668
1669 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1670
1671 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
1672
1673 surf = drv->API.CreatePbufferFromClientBuffer(drv, disp, buftype, buffer,
1674 conf, attrib_list);
1675 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1676
1677 RETURN_EGL_EVAL(disp, ret);
1678 }
1679
1680
1681 EGLBoolean EGLAPIENTRY
1682 eglReleaseThread(void)
1683 {
1684 /* unbind current contexts */
1685 if (!_eglIsCurrentThreadDummy()) {
1686 _EGLThreadInfo *t = _eglGetCurrentThread();
1687 _EGLContext *ctx = t->CurrentContext;
1688
1689 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
1690
1691 if (ctx) {
1692 _EGLDisplay *disp = ctx->Resource.Display;
1693 _EGLDriver *drv;
1694
1695 mtx_lock(&disp->Mutex);
1696 drv = disp->Driver;
1697 (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
1698 mtx_unlock(&disp->Mutex);
1699 }
1700 }
1701
1702 _eglDestroyCurrentThread();
1703
1704 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1705 }
1706
1707
1708 static EGLImage
1709 _eglCreateImageCommon(_EGLDisplay *disp, EGLContext ctx, EGLenum target,
1710 EGLClientBuffer buffer, const EGLint *attr_list)
1711 {
1712 _EGLContext *context = _eglLookupContext(ctx, disp);
1713 _EGLDriver *drv;
1714 _EGLImage *img;
1715 EGLImage ret;
1716
1717 _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
1718 if (!disp->Extensions.KHR_image_base)
1719 RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
1720 if (!context && ctx != EGL_NO_CONTEXT)
1721 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1722 /* "If <target> is EGL_LINUX_DMA_BUF_EXT, <dpy> must be a valid display,
1723 * <ctx> must be EGL_NO_CONTEXT..."
1724 */
1725 if (ctx != EGL_NO_CONTEXT && target == EGL_LINUX_DMA_BUF_EXT)
1726 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1727
1728 img = drv->API.CreateImageKHR(drv, disp, context, target,
1729 buffer, attr_list);
1730 ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
1731
1732 RETURN_EGL_EVAL(disp, ret);
1733 }
1734
1735 static EGLImage EGLAPIENTRY
1736 eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1737 EGLClientBuffer buffer, const EGLint *attr_list)
1738 {
1739 _EGLDisplay *disp = _eglLockDisplay(dpy);
1740 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR);
1741 return _eglCreateImageCommon(disp, ctx, target, buffer, attr_list);
1742 }
1743
1744
1745 EGLImage EGLAPIENTRY
1746 eglCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1747 EGLClientBuffer buffer, const EGLAttrib *attr_list)
1748 {
1749 _EGLDisplay *disp = _eglLockDisplay(dpy);
1750 EGLImage image;
1751 EGLint *int_attribs;
1752
1753 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR);
1754
1755 int_attribs = _eglConvertAttribsToInt(attr_list);
1756 if (attr_list && !int_attribs)
1757 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_IMAGE);
1758
1759 image = _eglCreateImageCommon(disp, ctx, target, buffer, int_attribs);
1760 free(int_attribs);
1761 return image;
1762 }
1763
1764
1765 static EGLBoolean
1766 _eglDestroyImageCommon(_EGLDisplay *disp, _EGLImage *img)
1767 {
1768 _EGLDriver *drv;
1769 EGLBoolean ret;
1770
1771 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1772 if (!disp->Extensions.KHR_image_base)
1773 RETURN_EGL_EVAL(disp, EGL_FALSE);
1774 if (!img)
1775 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1776
1777 _eglUnlinkImage(img);
1778 ret = drv->API.DestroyImageKHR(drv, disp, img);
1779
1780 RETURN_EGL_EVAL(disp, ret);
1781 }
1782
1783 EGLBoolean EGLAPIENTRY
1784 eglDestroyImage(EGLDisplay dpy, EGLImage image)
1785 {
1786 _EGLDisplay *disp = _eglLockDisplay(dpy);
1787 _EGLImage *img = _eglLookupImage(image, disp);
1788 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
1789 return _eglDestroyImageCommon(disp, img);
1790 }
1791
1792 static EGLBoolean EGLAPIENTRY
1793 eglDestroyImageKHR(EGLDisplay dpy, EGLImage image)
1794 {
1795 _EGLDisplay *disp = _eglLockDisplay(dpy);
1796 _EGLImage *img = _eglLookupImage(image, disp);
1797 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
1798 return _eglDestroyImageCommon(disp, img);
1799 }
1800
1801
1802 static EGLSync
1803 _eglCreateSync(_EGLDisplay *disp, EGLenum type, const EGLAttrib *attrib_list,
1804 EGLBoolean orig_is_EGLAttrib,
1805 EGLenum invalid_type_error)
1806 {
1807 _EGLContext *ctx = _eglGetCurrentContext();
1808 _EGLDriver *drv;
1809 _EGLSync *sync;
1810 EGLSync ret;
1811
1812 _EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv);
1813
1814 if (!disp->Extensions.KHR_cl_event2 && orig_is_EGLAttrib) {
1815 /* There exist two EGLAttrib variants of eglCreateSync*:
1816 * eglCreateSync64KHR which requires EGL_KHR_cl_event2, and eglCreateSync
1817 * which requires EGL 1.5. Here we use the presence of EGL_KHR_cl_event2
1818 * support as a proxy for EGL 1.5 support, even though that's not
1819 * entirely correct (though _eglComputeVersion does the same).
1820 *
1821 * The EGL spec provides no guidance on how to handle unsupported
1822 * functions. EGL_BAD_MATCH seems reasonable.
1823 */
1824 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1825 }
1826
1827 /* If type is EGL_SYNC_FENCE and no context is current for the bound API
1828 * (i.e., eglGetCurrentContext returns EGL_NO_CONTEXT ), an EGL_BAD_MATCH
1829 * error is generated.
1830 */
1831 if (!ctx &&
1832 (type == EGL_SYNC_FENCE_KHR || type == EGL_SYNC_NATIVE_FENCE_ANDROID))
1833 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1834
1835 /* return an error if the client API doesn't support GL_OES_EGL_sync */
1836 if (ctx && (ctx->Resource.Display != disp ||
1837 ctx->ClientAPI != EGL_OPENGL_ES_API))
1838 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1839
1840 switch (type) {
1841 case EGL_SYNC_FENCE_KHR:
1842 if (!disp->Extensions.KHR_fence_sync)
1843 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1844 break;
1845 case EGL_SYNC_REUSABLE_KHR:
1846 if (!disp->Extensions.KHR_reusable_sync)
1847 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1848 break;
1849 case EGL_SYNC_CL_EVENT_KHR:
1850 if (!disp->Extensions.KHR_cl_event2)
1851 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1852 break;
1853 case EGL_SYNC_NATIVE_FENCE_ANDROID:
1854 if (!disp->Extensions.ANDROID_native_fence_sync)
1855 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1856 break;
1857 default:
1858 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1859 }
1860
1861 sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list);
1862 ret = (sync) ? _eglLinkSync(sync) : EGL_NO_SYNC_KHR;
1863
1864 RETURN_EGL_EVAL(disp, ret);
1865 }
1866
1867
1868 static EGLSync EGLAPIENTRY
1869 eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *int_list)
1870 {
1871 _EGLDisplay *disp = _eglLockDisplay(dpy);
1872 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
1873
1874 EGLSync sync;
1875 EGLAttrib *attrib_list;
1876 EGLint err;
1877
1878 if (sizeof(int_list[0]) == sizeof(attrib_list[0])) {
1879 attrib_list = (EGLAttrib *) int_list;
1880 } else {
1881 err = _eglConvertIntsToAttribs(int_list, &attrib_list);
1882 if (err != EGL_SUCCESS)
1883 RETURN_EGL_ERROR(disp, err, EGL_NO_SYNC);
1884 }
1885
1886 sync = _eglCreateSync(disp, type, attrib_list, EGL_FALSE,
1887 EGL_BAD_ATTRIBUTE);
1888
1889 if (sizeof(int_list[0]) != sizeof(attrib_list[0]))
1890 free(attrib_list);
1891
1892 /* Don't double-unlock the display. _eglCreateSync already unlocked it. */
1893 return sync;
1894 }
1895
1896
1897 static EGLSync EGLAPIENTRY
1898 eglCreateSync64KHR(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
1899 {
1900 _EGLDisplay *disp = _eglLockDisplay(dpy);
1901 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
1902 return _eglCreateSync(disp, type, attrib_list, EGL_TRUE,
1903 EGL_BAD_ATTRIBUTE);
1904 }
1905
1906
1907 EGLSync EGLAPIENTRY
1908 eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
1909 {
1910 _EGLDisplay *disp = _eglLockDisplay(dpy);
1911 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
1912 return _eglCreateSync(disp, type, attrib_list, EGL_TRUE,
1913 EGL_BAD_PARAMETER);
1914 }
1915
1916
1917 static EGLBoolean
1918 _eglDestroySync(_EGLDisplay *disp, _EGLSync *s)
1919 {
1920 _EGLDriver *drv;
1921 EGLBoolean ret;
1922
1923 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1924 assert(disp->Extensions.KHR_reusable_sync ||
1925 disp->Extensions.KHR_fence_sync ||
1926 disp->Extensions.ANDROID_native_fence_sync);
1927
1928 _eglUnlinkSync(s);
1929 ret = drv->API.DestroySyncKHR(drv, disp, s);
1930
1931 RETURN_EGL_EVAL(disp, ret);
1932 }
1933
1934 EGLBoolean EGLAPIENTRY
1935 eglDestroySync(EGLDisplay dpy, EGLSync sync)
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 _eglDestroySync(disp, s);
1941 }
1942
1943 static EGLBoolean EGLAPIENTRY
1944 eglDestroySyncKHR(EGLDisplay dpy, EGLSync sync)
1945 {
1946 _EGLDisplay *disp = _eglLockDisplay(dpy);
1947 _EGLSync *s = _eglLookupSync(sync, disp);
1948 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
1949 return _eglDestroySync(disp, s);
1950 }
1951
1952
1953 static EGLint
1954 _eglClientWaitSyncCommon(_EGLDisplay *disp, EGLDisplay dpy,
1955 _EGLSync *s, EGLint flags, EGLTime timeout)
1956 {
1957 _EGLDriver *drv;
1958 EGLint ret;
1959
1960 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1961 assert(disp->Extensions.KHR_reusable_sync ||
1962 disp->Extensions.KHR_fence_sync ||
1963 disp->Extensions.ANDROID_native_fence_sync);
1964
1965 if (s->SyncStatus == EGL_SIGNALED_KHR)
1966 RETURN_EGL_EVAL(disp, EGL_CONDITION_SATISFIED_KHR);
1967
1968 /* if sync type is EGL_SYNC_REUSABLE_KHR, dpy should be
1969 * unlocked here to allow other threads also to be able to
1970 * go into waiting state.
1971 */
1972
1973 if (s->Type == EGL_SYNC_REUSABLE_KHR)
1974 _eglUnlockDisplay(dpy);
1975
1976 ret = drv->API.ClientWaitSyncKHR(drv, disp, s, flags, timeout);
1977
1978 /*
1979 * 'disp' is already unlocked for reusable sync type,
1980 * so passing 'NULL' to bypass unlocking display.
1981 */
1982 if (s->Type == EGL_SYNC_REUSABLE_KHR)
1983 RETURN_EGL_EVAL(NULL, ret);
1984 else
1985 RETURN_EGL_EVAL(disp, ret);
1986 }
1987
1988 EGLint EGLAPIENTRY
1989 eglClientWaitSync(EGLDisplay dpy, EGLSync sync,
1990 EGLint flags, EGLTime timeout)
1991 {
1992 _EGLDisplay *disp = _eglLockDisplay(dpy);
1993 _EGLSync *s = _eglLookupSync(sync, disp);
1994 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
1995 return _eglClientWaitSyncCommon(disp, dpy, s, flags, timeout);
1996 }
1997
1998 static EGLint EGLAPIENTRY
1999 eglClientWaitSyncKHR(EGLDisplay dpy, EGLSync sync,
2000 EGLint flags, EGLTime timeout)
2001 {
2002 _EGLDisplay *disp = _eglLockDisplay(dpy);
2003 _EGLSync *s = _eglLookupSync(sync, disp);
2004 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2005 return _eglClientWaitSyncCommon(disp, dpy, s, flags, timeout);
2006 }
2007
2008
2009 static EGLint
2010 _eglWaitSyncCommon(_EGLDisplay *disp, _EGLSync *s, EGLint flags)
2011 {
2012 _EGLContext *ctx = _eglGetCurrentContext();
2013 _EGLDriver *drv;
2014 EGLint ret;
2015
2016 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
2017 assert(disp->Extensions.KHR_wait_sync);
2018
2019 /* return an error if the client API doesn't support GL_OES_EGL_sync */
2020 if (ctx == EGL_NO_CONTEXT || ctx->ClientAPI != EGL_OPENGL_ES_API)
2021 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
2022
2023 /* the API doesn't allow any flags yet */
2024 if (flags != 0)
2025 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2026
2027 ret = drv->API.WaitSyncKHR(drv, disp, s);
2028
2029 RETURN_EGL_EVAL(disp, ret);
2030 }
2031
2032 static EGLint EGLAPIENTRY
2033 eglWaitSyncKHR(EGLDisplay dpy, EGLSync sync, EGLint flags)
2034 {
2035 _EGLDisplay *disp = _eglLockDisplay(dpy);
2036 _EGLSync *s = _eglLookupSync(sync, disp);
2037 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2038 return _eglWaitSyncCommon(disp, s, flags);
2039 }
2040
2041
2042 EGLBoolean EGLAPIENTRY
2043 eglWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags)
2044 {
2045 /* The KHR version returns EGLint, while the core version returns
2046 * EGLBoolean. In both cases, the return values can only be EGL_FALSE and
2047 * EGL_TRUE.
2048 */
2049 _EGLDisplay *disp = _eglLockDisplay(dpy);
2050 _EGLSync *s = _eglLookupSync(sync, disp);
2051 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2052 return _eglWaitSyncCommon(disp, s, flags);
2053 }
2054
2055
2056 static EGLBoolean EGLAPIENTRY
2057 eglSignalSyncKHR(EGLDisplay dpy, EGLSync sync, EGLenum mode)
2058 {
2059 _EGLDisplay *disp = _eglLockDisplay(dpy);
2060 _EGLSync *s = _eglLookupSync(sync, disp);
2061 _EGLDriver *drv;
2062 EGLBoolean ret;
2063
2064 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2065
2066 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
2067 assert(disp->Extensions.KHR_reusable_sync);
2068 ret = drv->API.SignalSyncKHR(drv, disp, s, mode);
2069
2070 RETURN_EGL_EVAL(disp, ret);
2071 }
2072
2073
2074 static EGLBoolean
2075 _eglGetSyncAttribCommon(_EGLDisplay *disp, _EGLSync *s, EGLint attribute, EGLAttrib *value)
2076 {
2077 _EGLDriver *drv;
2078 EGLBoolean ret;
2079
2080 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
2081 assert(disp->Extensions.KHR_reusable_sync ||
2082 disp->Extensions.KHR_fence_sync ||
2083 disp->Extensions.ANDROID_native_fence_sync);
2084 ret = drv->API.GetSyncAttrib(drv, disp, s, attribute, value);
2085
2086 RETURN_EGL_EVAL(disp, ret);
2087 }
2088
2089 EGLBoolean EGLAPIENTRY
2090 eglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value)
2091 {
2092 _EGLDisplay *disp = _eglLockDisplay(dpy);
2093 _EGLSync *s = _eglLookupSync(sync, disp);
2094 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2095 return _eglGetSyncAttribCommon(disp, s, attribute, value);
2096 }
2097
2098
2099 static EGLBoolean EGLAPIENTRY
2100 eglGetSyncAttribKHR(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint *value)
2101 {
2102 _EGLDisplay *disp = _eglLockDisplay(dpy);
2103 _EGLSync *s = _eglLookupSync(sync, disp);
2104 EGLAttrib attrib;
2105 EGLBoolean result;
2106
2107 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2108
2109 if (!value)
2110 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2111
2112 attrib = *value;
2113 result = _eglGetSyncAttribCommon(disp, s, attribute, &attrib);
2114
2115 /* The EGL_KHR_fence_sync spec says this about eglGetSyncAttribKHR:
2116 *
2117 * If any error occurs, <*value> is not modified.
2118 */
2119 if (result == EGL_FALSE)
2120 return result;
2121
2122 *value = attrib;
2123 return result;
2124 }
2125
2126 static EGLint EGLAPIENTRY
2127 eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync)
2128 {
2129 _EGLDisplay *disp = _eglLockDisplay(dpy);
2130 _EGLSync *s = _eglLookupSync(sync, disp);
2131 _EGLDriver *drv;
2132 EGLBoolean ret;
2133
2134 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2135
2136 /* the spec doesn't seem to specify what happens if the fence
2137 * type is not EGL_SYNC_NATIVE_FENCE_ANDROID, but this seems
2138 * sensible:
2139 */
2140 if (!(s && (s->Type == EGL_SYNC_NATIVE_FENCE_ANDROID)))
2141 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_NATIVE_FENCE_FD_ANDROID);
2142
2143 _EGL_CHECK_SYNC(disp, s, EGL_NO_NATIVE_FENCE_FD_ANDROID, drv);
2144 assert(disp->Extensions.ANDROID_native_fence_sync);
2145 ret = drv->API.DupNativeFenceFDANDROID(drv, disp, s);
2146
2147 RETURN_EGL_EVAL(disp, ret);
2148 }
2149
2150 static EGLBoolean EGLAPIENTRY
2151 eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface,
2152 EGLint numRects, const EGLint *rects)
2153 {
2154 _EGLContext *ctx = _eglGetCurrentContext();
2155 _EGLDisplay *disp = _eglLockDisplay(dpy);
2156 _EGLSurface *surf = _eglLookupSurface(surface, disp);
2157 _EGLDriver *drv;
2158 EGLBoolean ret;
2159
2160 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
2161
2162 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
2163
2164 if (!disp->Extensions.NOK_swap_region)
2165 RETURN_EGL_EVAL(disp, EGL_FALSE);
2166
2167 /* surface must be bound to current context in EGL 1.4 */
2168 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
2169 surf != ctx->DrawSurface)
2170 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
2171
2172 ret = drv->API.SwapBuffersRegionNOK(drv, disp, surf, numRects, rects);
2173
2174 RETURN_EGL_EVAL(disp, ret);
2175 }
2176
2177
2178 static EGLImage EGLAPIENTRY
2179 eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list)
2180 {
2181 _EGLDisplay *disp = _eglLockDisplay(dpy);
2182 _EGLDriver *drv;
2183 _EGLImage *img;
2184 EGLImage ret;
2185
2186 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2187
2188 _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
2189 if (!disp->Extensions.MESA_drm_image)
2190 RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
2191
2192 img = drv->API.CreateDRMImageMESA(drv, disp, attr_list);
2193 ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
2194
2195 RETURN_EGL_EVAL(disp, ret);
2196 }
2197
2198 static EGLBoolean EGLAPIENTRY
2199 eglExportDRMImageMESA(EGLDisplay dpy, EGLImage image,
2200 EGLint *name, EGLint *handle, EGLint *stride)
2201 {
2202 _EGLDisplay *disp = _eglLockDisplay(dpy);
2203 _EGLImage *img = _eglLookupImage(image, disp);
2204 _EGLDriver *drv;
2205 EGLBoolean ret;
2206
2207 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
2208
2209 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2210 assert(disp->Extensions.MESA_drm_image);
2211
2212 if (!img)
2213 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2214
2215 ret = drv->API.ExportDRMImageMESA(drv, disp, img, name, handle, stride);
2216
2217 RETURN_EGL_EVAL(disp, ret);
2218 }
2219
2220
2221 struct wl_display;
2222
2223 static EGLBoolean EGLAPIENTRY
2224 eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
2225 {
2226 _EGLDisplay *disp = _eglLockDisplay(dpy);
2227 _EGLDriver *drv;
2228 EGLBoolean ret;
2229
2230 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2231
2232 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2233 assert(disp->Extensions.WL_bind_wayland_display);
2234
2235 if (!display)
2236 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2237
2238 ret = drv->API.BindWaylandDisplayWL(drv, disp, display);
2239
2240 RETURN_EGL_EVAL(disp, ret);
2241 }
2242
2243 static EGLBoolean EGLAPIENTRY
2244 eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
2245 {
2246 _EGLDisplay *disp = _eglLockDisplay(dpy);
2247 _EGLDriver *drv;
2248 EGLBoolean ret;
2249
2250 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2251
2252 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2253 assert(disp->Extensions.WL_bind_wayland_display);
2254
2255 if (!display)
2256 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2257
2258 ret = drv->API.UnbindWaylandDisplayWL(drv, disp, display);
2259
2260 RETURN_EGL_EVAL(disp, ret);
2261 }
2262
2263 static EGLBoolean EGLAPIENTRY
2264 eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer,
2265 EGLint attribute, EGLint *value)
2266 {
2267 _EGLDisplay *disp = _eglLockDisplay(dpy);
2268 _EGLDriver *drv;
2269 EGLBoolean ret;
2270
2271 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2272
2273 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2274 assert(disp->Extensions.WL_bind_wayland_display);
2275
2276 if (!buffer)
2277 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2278
2279 ret = drv->API.QueryWaylandBufferWL(drv, disp, buffer, attribute, value);
2280
2281 RETURN_EGL_EVAL(disp, ret);
2282 }
2283
2284
2285 static struct wl_buffer * EGLAPIENTRY
2286 eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImage image)
2287 {
2288 _EGLDisplay *disp = _eglLockDisplay(dpy);
2289 _EGLImage *img;
2290 _EGLDriver *drv;
2291 struct wl_buffer *ret;
2292
2293 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2294
2295 _EGL_CHECK_DISPLAY(disp, NULL, drv);
2296 if (!disp->Extensions.WL_create_wayland_buffer_from_image)
2297 RETURN_EGL_EVAL(disp, NULL);
2298
2299 img = _eglLookupImage(image, disp);
2300
2301 if (!img)
2302 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL);
2303
2304 ret = drv->API.CreateWaylandBufferFromImageWL(drv, disp, img);
2305
2306 RETURN_EGL_EVAL(disp, ret);
2307 }
2308
2309 static EGLBoolean EGLAPIENTRY
2310 eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface,
2311 EGLint x, EGLint y, EGLint width, EGLint height)
2312 {
2313 _EGLDisplay *disp = _eglLockDisplay(dpy);
2314 _EGLSurface *surf = _eglLookupSurface(surface, disp);
2315 _EGLDriver *drv;
2316 EGLBoolean ret;
2317
2318 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
2319
2320 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
2321
2322 if (!disp->Extensions.NV_post_sub_buffer)
2323 RETURN_EGL_EVAL(disp, EGL_FALSE);
2324
2325 ret = drv->API.PostSubBufferNV(drv, disp, surf, x, y, width, height);
2326
2327 RETURN_EGL_EVAL(disp, ret);
2328 }
2329
2330 static EGLBoolean EGLAPIENTRY
2331 eglGetSyncValuesCHROMIUM(EGLDisplay dpy, EGLSurface surface,
2332 EGLuint64KHR *ust, EGLuint64KHR *msc,
2333 EGLuint64KHR *sbc)
2334 {
2335 _EGLDisplay *disp = _eglLockDisplay(dpy);
2336 _EGLSurface *surf = _eglLookupSurface(surface, disp);
2337 _EGLDriver *drv;
2338 EGLBoolean ret;
2339
2340 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
2341
2342 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
2343 if (!disp->Extensions.CHROMIUM_sync_control)
2344 RETURN_EGL_EVAL(disp, EGL_FALSE);
2345
2346 if (!ust || !msc || !sbc)
2347 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2348
2349 ret = drv->API.GetSyncValuesCHROMIUM(disp, surf, ust, msc, sbc);
2350
2351 RETURN_EGL_EVAL(disp, ret);
2352 }
2353
2354 static EGLBoolean EGLAPIENTRY
2355 eglExportDMABUFImageQueryMESA(EGLDisplay dpy, EGLImage image,
2356 EGLint *fourcc, EGLint *nplanes,
2357 EGLuint64KHR *modifiers)
2358 {
2359 _EGLDisplay *disp = _eglLockDisplay(dpy);
2360 _EGLImage *img = _eglLookupImage(image, disp);
2361 _EGLDriver *drv;
2362 EGLBoolean ret;
2363
2364 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
2365
2366 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2367 assert(disp->Extensions.MESA_image_dma_buf_export);
2368
2369 if (!img)
2370 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2371
2372 ret = drv->API.ExportDMABUFImageQueryMESA(drv, disp, img, fourcc, nplanes,
2373 modifiers);
2374
2375 RETURN_EGL_EVAL(disp, ret);
2376 }
2377
2378 static EGLBoolean EGLAPIENTRY
2379 eglExportDMABUFImageMESA(EGLDisplay dpy, EGLImage image,
2380 int *fds, EGLint *strides, EGLint *offsets)
2381 {
2382 _EGLDisplay *disp = _eglLockDisplay(dpy);
2383 _EGLImage *img = _eglLookupImage(image, disp);
2384 _EGLDriver *drv;
2385 EGLBoolean ret;
2386
2387 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
2388
2389 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2390 assert(disp->Extensions.MESA_image_dma_buf_export);
2391
2392 if (!img)
2393 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2394
2395 ret = drv->API.ExportDMABUFImageMESA(drv, disp, img, fds, strides, offsets);
2396
2397 RETURN_EGL_EVAL(disp, ret);
2398 }
2399
2400 static EGLint EGLAPIENTRY
2401 eglLabelObjectKHR(EGLDisplay dpy, EGLenum objectType, EGLObjectKHR object,
2402 EGLLabelKHR label)
2403 {
2404 _EGLDisplay *disp = NULL;
2405 _EGLResourceType type;
2406
2407 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
2408
2409 if (objectType == EGL_OBJECT_THREAD_KHR) {
2410 _EGLThreadInfo *t = _eglGetCurrentThread();
2411
2412 if (!_eglIsCurrentThreadDummy()) {
2413 t->Label = label;
2414 return EGL_SUCCESS;
2415 }
2416
2417 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_BAD_ALLOC);
2418 }
2419
2420 disp = _eglLockDisplay(dpy);
2421 if (disp == NULL)
2422 RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_BAD_DISPLAY);
2423
2424 if (objectType == EGL_OBJECT_DISPLAY_KHR) {
2425 if (dpy != (EGLDisplay) object)
2426 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
2427
2428 disp->Label = label;
2429 RETURN_EGL_EVAL(disp, EGL_SUCCESS);
2430 }
2431
2432 switch (objectType) {
2433 case EGL_OBJECT_CONTEXT_KHR:
2434 type = _EGL_RESOURCE_CONTEXT;
2435 break;
2436 case EGL_OBJECT_SURFACE_KHR:
2437 type = _EGL_RESOURCE_SURFACE;
2438 break;
2439 case EGL_OBJECT_IMAGE_KHR:
2440 type = _EGL_RESOURCE_IMAGE;
2441 break;
2442 case EGL_OBJECT_SYNC_KHR:
2443 type = _EGL_RESOURCE_SYNC;
2444 break;
2445 case EGL_OBJECT_STREAM_KHR:
2446 default:
2447 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
2448 }
2449
2450 if (_eglCheckResource(object, type, disp)) {
2451 _EGLResource *res = (_EGLResource *) object;
2452
2453 res->Label = label;
2454 RETURN_EGL_EVAL(disp, EGL_SUCCESS);
2455 }
2456
2457 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
2458 }
2459
2460 static EGLint EGLAPIENTRY
2461 eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback,
2462 const EGLAttrib *attrib_list)
2463 {
2464 unsigned int newEnabled;
2465
2466 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
2467
2468 mtx_lock(_eglGlobal.Mutex);
2469
2470 newEnabled = _eglGlobal.debugTypesEnabled;
2471 if (attrib_list != NULL) {
2472 int i;
2473
2474 for (i = 0; attrib_list[i] != EGL_NONE; i += 2) {
2475 switch (attrib_list[i]) {
2476 case EGL_DEBUG_MSG_CRITICAL_KHR:
2477 case EGL_DEBUG_MSG_ERROR_KHR:
2478 case EGL_DEBUG_MSG_WARN_KHR:
2479 case EGL_DEBUG_MSG_INFO_KHR:
2480 if (attrib_list[i + 1])
2481 newEnabled |= DebugBitFromType(attrib_list[i]);
2482 else
2483 newEnabled &= ~DebugBitFromType(attrib_list[i]);
2484 break;
2485 default:
2486 // On error, set the last error code, call the current
2487 // debug callback, and return the error code.
2488 mtx_unlock(_eglGlobal.Mutex);
2489 _eglReportError(EGL_BAD_ATTRIBUTE, NULL,
2490 "Invalid attribute 0x%04lx", (unsigned long) attrib_list[i]);
2491 return EGL_BAD_ATTRIBUTE;
2492 }
2493 }
2494 }
2495
2496 if (callback != NULL) {
2497 _eglGlobal.debugCallback = callback;
2498 _eglGlobal.debugTypesEnabled = newEnabled;
2499 } else {
2500 _eglGlobal.debugCallback = NULL;
2501 _eglGlobal.debugTypesEnabled = _EGL_DEBUG_BIT_CRITICAL | _EGL_DEBUG_BIT_ERROR;
2502 }
2503
2504 mtx_unlock(_eglGlobal.Mutex);
2505 return EGL_SUCCESS;
2506 }
2507
2508 static EGLBoolean EGLAPIENTRY
2509 eglQueryDebugKHR(EGLint attribute, EGLAttrib *value)
2510 {
2511 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
2512
2513 mtx_lock(_eglGlobal.Mutex);
2514
2515 switch (attribute) {
2516 case EGL_DEBUG_MSG_CRITICAL_KHR:
2517 case EGL_DEBUG_MSG_ERROR_KHR:
2518 case EGL_DEBUG_MSG_WARN_KHR:
2519 case EGL_DEBUG_MSG_INFO_KHR:
2520 if (_eglGlobal.debugTypesEnabled & DebugBitFromType(attribute))
2521 *value = EGL_TRUE;
2522 else
2523 *value = EGL_FALSE;
2524 break;
2525 case EGL_DEBUG_CALLBACK_KHR:
2526 *value = (EGLAttrib) _eglGlobal.debugCallback;
2527 break;
2528 default:
2529 mtx_unlock(_eglGlobal.Mutex);
2530 _eglReportError(EGL_BAD_ATTRIBUTE, NULL,
2531 "Invalid attribute 0x%04lx", (unsigned long) attribute);
2532 return EGL_FALSE;
2533 }
2534
2535 mtx_unlock(_eglGlobal.Mutex);
2536 return EGL_TRUE;
2537 }
2538
2539 static int
2540 _eglFunctionCompare(const void *key, const void *elem)
2541 {
2542 const char *procname = key;
2543 const struct _egl_entrypoint *entrypoint = elem;
2544 return strcmp(procname, entrypoint->name);
2545 }
2546
2547 static EGLBoolean EGLAPIENTRY
2548 eglQueryDmaBufFormatsEXT(EGLDisplay dpy, EGLint max_formats,
2549 EGLint *formats, EGLint *num_formats)
2550 {
2551 _EGLDisplay *disp = _eglLockDisplay(dpy);
2552 _EGLDriver *drv;
2553 EGLBoolean ret;
2554
2555 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2556
2557 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2558
2559 ret = drv->API.QueryDmaBufFormatsEXT(drv, disp, max_formats, formats,
2560 num_formats);
2561
2562 RETURN_EGL_EVAL(disp, ret);
2563 }
2564
2565 static EGLBoolean EGLAPIENTRY
2566 eglQueryDmaBufModifiersEXT(EGLDisplay dpy, EGLint format, EGLint max_modifiers,
2567 EGLuint64KHR *modifiers, EGLBoolean *external_only,
2568 EGLint *num_modifiers)
2569 {
2570 _EGLDisplay *disp = _eglLockDisplay(dpy);
2571 _EGLDriver *drv;
2572 EGLBoolean ret;
2573
2574 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2575
2576 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2577
2578 ret = drv->API.QueryDmaBufModifiersEXT(drv, disp, format, max_modifiers,
2579 modifiers, external_only,
2580 num_modifiers);
2581
2582 RETURN_EGL_EVAL(disp, ret);
2583 }
2584
2585 static void EGLAPIENTRY
2586 eglSetBlobCacheFuncsANDROID(EGLDisplay *dpy, EGLSetBlobFuncANDROID set,
2587 EGLGetBlobFuncANDROID get)
2588 {
2589 /* This function does not return anything so we cannot
2590 * utilize the helper macros _EGL_FUNC_START or _EGL_CHECK_DISPLAY.
2591 */
2592 _EGLDisplay *disp = _eglLockDisplay(dpy);
2593 if (!_eglSetFuncName(__func__, disp, EGL_OBJECT_DISPLAY_KHR, NULL)) {
2594 if (disp)
2595 _eglUnlockDisplay(disp);
2596 return;
2597 }
2598
2599 _EGLDriver *drv = _eglCheckDisplay(disp, __func__);
2600 if (!drv) {
2601 if (disp)
2602 _eglUnlockDisplay(disp);
2603 return;
2604 }
2605
2606 if (!set || !get) {
2607 _eglError(EGL_BAD_PARAMETER,
2608 "eglSetBlobCacheFuncsANDROID: NULL handler given");
2609 _eglUnlockDisplay(disp);
2610 return;
2611 }
2612
2613 if (disp->BlobCacheSet) {
2614 _eglError(EGL_BAD_PARAMETER,
2615 "eglSetBlobCacheFuncsANDROID: functions already set");
2616 _eglUnlockDisplay(disp);
2617 return;
2618 }
2619
2620 disp->BlobCacheSet = set;
2621 disp->BlobCacheGet = get;
2622
2623 drv->API.SetBlobCacheFuncsANDROID(drv, disp, set, get);
2624
2625 _eglUnlockDisplay(disp);
2626 }
2627
2628 static EGLBoolean EGLAPIENTRY
2629 eglQueryDeviceAttribEXT(EGLDeviceEXT device,
2630 EGLint attribute,
2631 EGLAttrib *value)
2632 {
2633 _EGLDevice *dev = _eglLookupDevice(device);
2634 EGLBoolean ret;
2635
2636 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2637 if (!dev)
2638 RETURN_EGL_ERROR(NULL, EGL_BAD_DEVICE_EXT, EGL_FALSE);
2639
2640 ret = _eglQueryDeviceAttribEXT(dev, attribute, value);
2641 RETURN_EGL_EVAL(NULL, ret);
2642 }
2643
2644 static const char * EGLAPIENTRY
2645 eglQueryDeviceStringEXT(EGLDeviceEXT device,
2646 EGLint name)
2647 {
2648 _EGLDevice *dev = _eglLookupDevice(device);
2649
2650 _EGL_FUNC_START(NULL, EGL_NONE, NULL, NULL);
2651 if (!dev)
2652 RETURN_EGL_ERROR(NULL, EGL_BAD_DEVICE_EXT, NULL);
2653
2654 RETURN_EGL_EVAL(NULL, _eglQueryDeviceStringEXT(dev, name));
2655 }
2656
2657 static EGLBoolean EGLAPIENTRY
2658 eglQueryDevicesEXT(EGLint max_devices,
2659 EGLDeviceEXT *devices,
2660 EGLint *num_devices)
2661 {
2662 EGLBoolean ret;
2663
2664 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2665 ret = _eglQueryDevicesEXT(max_devices, (_EGLDevice **) devices,
2666 num_devices);
2667 RETURN_EGL_EVAL(NULL, ret);
2668 }
2669
2670 static EGLBoolean EGLAPIENTRY
2671 eglQueryDisplayAttribEXT(EGLDisplay dpy,
2672 EGLint attribute,
2673 EGLAttrib *value)
2674 {
2675 _EGLDisplay *disp = _eglLockDisplay(dpy);
2676 _EGLDriver *drv;
2677
2678 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2679 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2680
2681 switch (attribute) {
2682 case EGL_DEVICE_EXT:
2683 *value = (EGLAttrib) disp->Device;
2684 break;
2685 default:
2686 RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_FALSE);
2687 }
2688 RETURN_EGL_SUCCESS(disp, EGL_TRUE);
2689 }
2690
2691 static char * EGLAPIENTRY
2692 eglGetDisplayDriverConfig(EGLDisplay dpy)
2693 {
2694 _EGLDisplay *disp = _eglLockDisplay(dpy);
2695 _EGLDriver *drv;
2696 char *ret;
2697
2698 _EGL_FUNC_START(disp, EGL_NONE, NULL, NULL);
2699 _EGL_CHECK_DISPLAY(disp, NULL, drv);
2700
2701 assert(disp->Extensions.MESA_query_driver);
2702
2703 ret = drv->API.QueryDriverConfig(disp);
2704 RETURN_EGL_EVAL(disp, ret);
2705 }
2706
2707 static const char * EGLAPIENTRY
2708 eglGetDisplayDriverName(EGLDisplay dpy)
2709 {
2710 _EGLDisplay *disp = _eglLockDisplay(dpy);
2711 _EGLDriver *drv;
2712 const char *ret;
2713
2714 _EGL_FUNC_START(disp, EGL_NONE, NULL, NULL);
2715 _EGL_CHECK_DISPLAY(disp, NULL, drv);
2716
2717 assert(disp->Extensions.MESA_query_driver);
2718
2719 ret = drv->API.QueryDriverName(disp);
2720 RETURN_EGL_EVAL(disp, ret);
2721 }
2722
2723 __eglMustCastToProperFunctionPointerType EGLAPIENTRY
2724 eglGetProcAddress(const char *procname)
2725 {
2726 static const struct _egl_entrypoint egl_functions[] = {
2727 #define EGL_ENTRYPOINT(f) { .name = #f, .function = (_EGLProc) f },
2728 #include "eglentrypoint.h"
2729 #undef EGL_ENTRYPOINT
2730 };
2731 _EGLProc ret = NULL;
2732
2733 if (!procname)
2734 RETURN_EGL_SUCCESS(NULL, NULL);
2735
2736 _EGL_FUNC_START(NULL, EGL_NONE, NULL, NULL);
2737
2738 if (strncmp(procname, "egl", 3) == 0) {
2739 const struct _egl_entrypoint *entrypoint =
2740 bsearch(procname,
2741 egl_functions, ARRAY_SIZE(egl_functions),
2742 sizeof(egl_functions[0]),
2743 _eglFunctionCompare);
2744 if (entrypoint)
2745 ret = entrypoint->function;
2746 }
2747
2748 if (!ret)
2749 ret = _eglGetDriverProc(procname);
2750
2751 RETURN_EGL_SUCCESS(NULL, ret);
2752 }
2753
2754 static int
2755 _eglLockDisplayInterop(EGLDisplay dpy, EGLContext context,
2756 _EGLDisplay **disp, _EGLDriver **drv,
2757 _EGLContext **ctx)
2758 {
2759
2760 *disp = _eglLockDisplay(dpy);
2761 if (!*disp || !(*disp)->Initialized || !(*disp)->Driver) {
2762 if (*disp)
2763 _eglUnlockDisplay(*disp);
2764 return MESA_GLINTEROP_INVALID_DISPLAY;
2765 }
2766
2767 *drv = (*disp)->Driver;
2768
2769 *ctx = _eglLookupContext(context, *disp);
2770 if (!*ctx ||
2771 ((*ctx)->ClientAPI != EGL_OPENGL_API &&
2772 (*ctx)->ClientAPI != EGL_OPENGL_ES_API)) {
2773 _eglUnlockDisplay(*disp);
2774 return MESA_GLINTEROP_INVALID_CONTEXT;
2775 }
2776
2777 return MESA_GLINTEROP_SUCCESS;
2778 }
2779
2780 PUBLIC int
2781 MesaGLInteropEGLQueryDeviceInfo(EGLDisplay dpy, EGLContext context,
2782 struct mesa_glinterop_device_info *out)
2783 {
2784 _EGLDisplay *disp;
2785 _EGLDriver *drv;
2786 _EGLContext *ctx;
2787 int ret;
2788
2789 ret = _eglLockDisplayInterop(dpy, context, &disp, &drv, &ctx);
2790 if (ret != MESA_GLINTEROP_SUCCESS)
2791 return ret;
2792
2793 if (drv->API.GLInteropQueryDeviceInfo)
2794 ret = drv->API.GLInteropQueryDeviceInfo(disp, ctx, out);
2795 else
2796 ret = MESA_GLINTEROP_UNSUPPORTED;
2797
2798 _eglUnlockDisplay(disp);
2799 return ret;
2800 }
2801
2802 PUBLIC int
2803 MesaGLInteropEGLExportObject(EGLDisplay dpy, EGLContext context,
2804 struct mesa_glinterop_export_in *in,
2805 struct mesa_glinterop_export_out *out)
2806 {
2807 _EGLDisplay *disp;
2808 _EGLDriver *drv;
2809 _EGLContext *ctx;
2810 int ret;
2811
2812 ret = _eglLockDisplayInterop(dpy, context, &disp, &drv, &ctx);
2813 if (ret != MESA_GLINTEROP_SUCCESS)
2814 return ret;
2815
2816 if (drv->API.GLInteropExportObject)
2817 ret = drv->API.GLInteropExportObject(disp, ctx, in, out);
2818 else
2819 ret = MESA_GLINTEROP_UNSUPPORTED;
2820
2821 _eglUnlockDisplay(disp);
2822 return ret;
2823 }