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