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