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