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