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