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