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