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