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