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