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