eglapi.c revision a8617cc0428dcc8340cb85776e122c6534a0fa11
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 "eglcompiler.h"
92
93#include "eglglobals.h"
94#include "eglcontext.h"
95#include "egldisplay.h"
96#include "egltypedefs.h"
97#include "eglcurrent.h"
98#include "egldriver.h"
99#include "eglsurface.h"
100#include "eglconfig.h"
101#include "eglscreen.h"
102#include "eglmode.h"
103#include "eglimage.h"
104#include "eglsync.h"
105#include "eglstring.h"
106
107
108/**
109 * Macros to help return an API entrypoint.
110 *
111 * These macros will unlock the display and record the error code.
112 */
113#define RETURN_EGL_ERROR(disp, err, ret)        \
114   do {                                         \
115      if (disp)                                 \
116         _eglUnlockDisplay(disp);               \
117      /* EGL error codes are non-zero */        \
118      if (err)                                  \
119         _eglError(err, __func__);              \
120      return ret;                               \
121   } while (0)
122
123#define RETURN_EGL_SUCCESS(disp, ret) \
124   RETURN_EGL_ERROR(disp, EGL_SUCCESS, ret)
125
126/* record EGL_SUCCESS only when ret evaluates to true */
127#define RETURN_EGL_EVAL(disp, ret) \
128   RETURN_EGL_ERROR(disp, (ret) ? EGL_SUCCESS : 0, ret)
129
130
131/*
132 * A bunch of macros and checks to simplify error checking.
133 */
134
135#define _EGL_CHECK_DISPLAY(disp, ret, drv)         \
136   do {                                            \
137      drv = _eglCheckDisplay(disp, __func__);      \
138      if (!drv)                                    \
139         RETURN_EGL_ERROR(disp, 0, ret);           \
140   } while (0)
141
142#define _EGL_CHECK_OBJECT(disp, type, obj, ret, drv)      \
143   do {                                                   \
144      drv = _eglCheck ## type(disp, obj, __func__);       \
145      if (!drv)                                           \
146         RETURN_EGL_ERROR(disp, 0, ret);                  \
147   } while (0)
148
149#define _EGL_CHECK_SURFACE(disp, surf, ret, drv) \
150   _EGL_CHECK_OBJECT(disp, Surface, surf, ret, drv)
151
152#define _EGL_CHECK_CONTEXT(disp, context, ret, drv) \
153   _EGL_CHECK_OBJECT(disp, Context, context, ret, drv)
154
155#define _EGL_CHECK_CONFIG(disp, conf, ret, drv) \
156   _EGL_CHECK_OBJECT(disp, Config, conf, ret, drv)
157
158#define _EGL_CHECK_SCREEN(disp, scrn, ret, drv) \
159   _EGL_CHECK_OBJECT(disp, Screen, scrn, ret, drv)
160
161#define _EGL_CHECK_MODE(disp, m, ret, drv) \
162   _EGL_CHECK_OBJECT(disp, Mode, m, ret, drv)
163
164#define _EGL_CHECK_SYNC(disp, s, ret, drv) \
165   _EGL_CHECK_OBJECT(disp, Sync, s, ret, drv)
166
167
168static inline _EGLDriver *
169_eglCheckDisplay(_EGLDisplay *disp, const char *msg)
170{
171   if (!disp) {
172      _eglError(EGL_BAD_DISPLAY, msg);
173      return NULL;
174   }
175   if (!disp->Initialized) {
176      _eglError(EGL_NOT_INITIALIZED, msg);
177      return NULL;
178   }
179   return disp->Driver;
180}
181
182
183static inline _EGLDriver *
184_eglCheckSurface(_EGLDisplay *disp, _EGLSurface *surf, const char *msg)
185{
186   _EGLDriver *drv = _eglCheckDisplay(disp, msg);
187   if (!drv)
188      return NULL;
189   if (!surf) {
190      _eglError(EGL_BAD_SURFACE, msg);
191      return NULL;
192   }
193   return drv;
194}
195
196
197static inline _EGLDriver *
198_eglCheckContext(_EGLDisplay *disp, _EGLContext *context, const char *msg)
199{
200   _EGLDriver *drv = _eglCheckDisplay(disp, msg);
201   if (!drv)
202      return NULL;
203   if (!context) {
204      _eglError(EGL_BAD_CONTEXT, msg);
205      return NULL;
206   }
207   return drv;
208}
209
210
211static inline _EGLDriver *
212_eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg)
213{
214   _EGLDriver *drv = _eglCheckDisplay(disp, msg);
215   if (!drv)
216      return NULL;
217   if (!conf) {
218      _eglError(EGL_BAD_CONFIG, msg);
219      return NULL;
220   }
221   return drv;
222}
223
224
225static inline _EGLDriver *
226_eglCheckSync(_EGLDisplay *disp, _EGLSync *s, const char *msg)
227{
228   _EGLDriver *drv = _eglCheckDisplay(disp, msg);
229   if (!drv)
230      return NULL;
231   if (!s) {
232      _eglError(EGL_BAD_PARAMETER, msg);
233      return NULL;
234   }
235   return drv;
236}
237
238
239#ifdef EGL_MESA_screen_surface
240
241
242static inline _EGLDriver *
243_eglCheckScreen(_EGLDisplay *disp, _EGLScreen *scrn, const char *msg)
244{
245   _EGLDriver *drv = _eglCheckDisplay(disp, msg);
246   if (!drv)
247      return NULL;
248   if (!scrn) {
249      _eglError(EGL_BAD_SCREEN_MESA, msg);
250      return NULL;
251   }
252   return drv;
253}
254
255
256static inline _EGLDriver *
257_eglCheckMode(_EGLDisplay *disp, _EGLMode *m, const char *msg)
258{
259   _EGLDriver *drv = _eglCheckDisplay(disp, msg);
260   if (!drv)
261      return NULL;
262   if (!m) {
263      _eglError(EGL_BAD_MODE_MESA, msg);
264      return NULL;
265   }
266   return drv;
267}
268
269
270#endif /* EGL_MESA_screen_surface */
271
272
273/**
274 * Lookup and lock a display.
275 */
276static inline _EGLDisplay *
277_eglLockDisplay(EGLDisplay display)
278{
279   _EGLDisplay *dpy = _eglLookupDisplay(display);
280   if (dpy)
281      mtx_lock(&dpy->Mutex);
282   return dpy;
283}
284
285
286/**
287 * Unlock a display.
288 */
289static inline void
290_eglUnlockDisplay(_EGLDisplay *dpy)
291{
292   mtx_unlock(&dpy->Mutex);
293}
294
295
296/**
297 * This is typically the first EGL function that an application calls.
298 * It associates a private _EGLDisplay object to the native display.
299 */
300EGLDisplay EGLAPIENTRY
301eglGetDisplay(EGLNativeDisplayType nativeDisplay)
302{
303   _EGLPlatformType plat;
304   _EGLDisplay *dpy;
305   void *native_display_ptr;
306
307   STATIC_ASSERT(sizeof(void*) == sizeof(nativeDisplay));
308   native_display_ptr = (void*) nativeDisplay;
309
310   plat = _eglGetNativePlatform(native_display_ptr);
311   dpy = _eglFindDisplay(plat, native_display_ptr);
312   return _eglGetDisplayHandle(dpy);
313}
314
315EGLDisplay EGLAPIENTRY
316eglGetPlatformDisplayEXT(EGLenum platform, void *native_display,
317                         const EGLint *attrib_list)
318{
319   _EGLDisplay *dpy;
320
321   switch (platform) {
322#ifdef HAVE_X11_PLATFORM
323   case EGL_PLATFORM_X11_EXT:
324      dpy = _eglGetX11Display((Display*) native_display, attrib_list);
325      break;
326#endif
327#ifdef HAVE_DRM_PLATFORM
328   case EGL_PLATFORM_GBM_MESA:
329      dpy = _eglGetGbmDisplay((struct gbm_device*) native_display,
330                              attrib_list);
331      break;
332#endif
333#ifdef HAVE_WAYLAND_PLATFORM
334   case EGL_PLATFORM_WAYLAND_EXT:
335      dpy = _eglGetWaylandDisplay((struct wl_display*) native_display,
336                                  attrib_list);
337      break;
338#endif
339   default:
340      RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, NULL);
341   }
342
343   return _eglGetDisplayHandle(dpy);
344}
345
346/**
347 * Copy the extension into the string and update the string pointer.
348 */
349static EGLint
350_eglAppendExtension(char **str, const char *ext)
351{
352   char *s = *str;
353   size_t len = strlen(ext);
354
355   if (s) {
356      memcpy(s, ext, len);
357      s[len++] = ' ';
358      s[len] = '\0';
359
360      *str += len;
361   }
362   else {
363      len++;
364   }
365
366   return (EGLint) len;
367}
368
369/**
370 * Examine the individual extension enable/disable flags and recompute
371 * the driver's Extensions string.
372 */
373static void
374_eglCreateExtensionsString(_EGLDisplay *dpy)
375{
376#define _EGL_CHECK_EXTENSION(ext)                                          \
377   do {                                                                    \
378      if (dpy->Extensions.ext) {                                           \
379         _eglAppendExtension(&exts, "EGL_" #ext);                          \
380         assert(exts <= dpy->ExtensionsString + _EGL_MAX_EXTENSIONS_LEN);  \
381      }                                                                    \
382   } while (0)
383
384   char *exts = dpy->ExtensionsString;
385
386   _EGL_CHECK_EXTENSION(MESA_screen_surface);
387   _EGL_CHECK_EXTENSION(MESA_copy_context);
388   _EGL_CHECK_EXTENSION(MESA_drm_display);
389   _EGL_CHECK_EXTENSION(MESA_drm_image);
390   _EGL_CHECK_EXTENSION(MESA_configless_context);
391
392   _EGL_CHECK_EXTENSION(WL_bind_wayland_display);
393   _EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image);
394
395   _EGL_CHECK_EXTENSION(KHR_image_base);
396   _EGL_CHECK_EXTENSION(KHR_image_pixmap);
397   if (dpy->Extensions.KHR_image_base && dpy->Extensions.KHR_image_pixmap)
398      _eglAppendExtension(&exts, "EGL_KHR_image");
399
400   _EGL_CHECK_EXTENSION(KHR_vg_parent_image);
401   _EGL_CHECK_EXTENSION(KHR_get_all_proc_addresses);
402   _EGL_CHECK_EXTENSION(KHR_gl_texture_2D_image);
403   _EGL_CHECK_EXTENSION(KHR_gl_texture_cubemap_image);
404   _EGL_CHECK_EXTENSION(KHR_gl_texture_3D_image);
405   _EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_image);
406
407   _EGL_CHECK_EXTENSION(KHR_reusable_sync);
408   _EGL_CHECK_EXTENSION(KHR_fence_sync);
409   _EGL_CHECK_EXTENSION(KHR_wait_sync);
410
411   _EGL_CHECK_EXTENSION(KHR_surfaceless_context);
412   _EGL_CHECK_EXTENSION(KHR_create_context);
413
414   _EGL_CHECK_EXTENSION(NOK_swap_region);
415   _EGL_CHECK_EXTENSION(NOK_texture_from_pixmap);
416
417   _EGL_CHECK_EXTENSION(ANDROID_image_native_buffer);
418
419   _EGL_CHECK_EXTENSION(CHROMIUM_sync_control);
420
421   _EGL_CHECK_EXTENSION(EXT_create_context_robustness);
422   _EGL_CHECK_EXTENSION(EXT_buffer_age);
423   _EGL_CHECK_EXTENSION(EXT_swap_buffers_with_damage);
424   _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import);
425
426   _EGL_CHECK_EXTENSION(NV_post_sub_buffer);
427
428   _EGL_CHECK_EXTENSION(MESA_image_dma_buf_export);
429#undef _EGL_CHECK_EXTENSION
430}
431
432static void
433_eglCreateAPIsString(_EGLDisplay *dpy)
434{
435   if (dpy->ClientAPIs & EGL_OPENGL_BIT)
436      strcat(dpy->ClientAPIsString, "OpenGL ");
437
438   if (dpy->ClientAPIs & EGL_OPENGL_ES_BIT)
439      strcat(dpy->ClientAPIsString, "OpenGL_ES ");
440
441   if (dpy->ClientAPIs & EGL_OPENGL_ES2_BIT)
442      strcat(dpy->ClientAPIsString, "OpenGL_ES2 ");
443
444   if (dpy->ClientAPIs & EGL_OPENGL_ES3_BIT_KHR)
445      strcat(dpy->ClientAPIsString, "OpenGL_ES3 ");
446
447   if (dpy->ClientAPIs & EGL_OPENVG_BIT)
448      strcat(dpy->ClientAPIsString, "OpenVG ");
449
450   assert(strlen(dpy->ClientAPIsString) < sizeof(dpy->ClientAPIsString));
451}
452
453
454/**
455 * This is typically the second EGL function that an application calls.
456 * Here we load/initialize the actual hardware driver.
457 */
458EGLBoolean EGLAPIENTRY
459eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
460{
461   _EGLDisplay *disp = _eglLockDisplay(dpy);
462
463   if (!disp)
464      RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
465
466   if (!disp->Initialized) {
467      if (!_eglMatchDriver(disp, EGL_FALSE))
468         RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
469
470      /* limit to APIs supported by core */
471      disp->ClientAPIs &= _EGL_API_ALL_BITS;
472
473      /* EGL_KHR_get_all_proc_addresses is a corner-case extension. The spec
474       * classifies it as an EGL display extension, though conceptually it's an
475       * EGL client extension.
476       *
477       * From the EGL_KHR_get_all_proc_addresses spec:
478       *
479       *    The EGL implementation must expose the name
480       *    EGL_KHR_client_get_all_proc_addresses if and only if it exposes
481       *    EGL_KHR_get_all_proc_addresses and supports
482       *    EGL_EXT_client_extensions.
483       *
484       * Mesa unconditionally exposes both client extensions mentioned above,
485       * so the spec requires that each EGLDisplay unconditionally expose
486       * EGL_KHR_get_all_proc_addresses also.
487       */
488      disp->Extensions.KHR_get_all_proc_addresses = EGL_TRUE;
489
490      _eglCreateExtensionsString(disp);
491      _eglCreateAPIsString(disp);
492      _eglsnprintf(disp->VersionString, sizeof(disp->VersionString),
493              "%d.%d (%s)", disp->VersionMajor, disp->VersionMinor,
494              disp->Driver->Name);
495   }
496
497   /* Update applications version of major and minor if not NULL */
498   if ((major != NULL) && (minor != NULL)) {
499      *major = disp->VersionMajor;
500      *minor = disp->VersionMinor;
501   }
502
503   RETURN_EGL_SUCCESS(disp, EGL_TRUE);
504}
505
506
507EGLBoolean EGLAPIENTRY
508eglTerminate(EGLDisplay dpy)
509{
510   _EGLDisplay *disp = _eglLockDisplay(dpy);
511
512   if (!disp)
513      RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
514
515   if (disp->Initialized) {
516      _EGLDriver *drv = disp->Driver;
517
518      drv->API.Terminate(drv, disp);
519      /* do not reset disp->Driver */
520      disp->ClientAPIsString[0] = 0;
521      disp->Initialized = EGL_FALSE;
522   }
523
524   RETURN_EGL_SUCCESS(disp, EGL_TRUE);
525}
526
527
528const char * EGLAPIENTRY
529eglQueryString(EGLDisplay dpy, EGLint name)
530{
531   _EGLDisplay *disp;
532   _EGLDriver *drv;
533
534   if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) {
535      RETURN_EGL_SUCCESS(NULL, _eglGlobal.ClientExtensionString);
536   }
537
538   disp = _eglLockDisplay(dpy);
539   _EGL_CHECK_DISPLAY(disp, NULL, drv);
540
541   switch (name) {
542   case EGL_VENDOR:
543      RETURN_EGL_SUCCESS(disp, _EGL_VENDOR_STRING);
544   case EGL_VERSION:
545      RETURN_EGL_SUCCESS(disp, disp->VersionString);
546   case EGL_EXTENSIONS:
547      RETURN_EGL_SUCCESS(disp, disp->ExtensionsString);
548   case EGL_CLIENT_APIS:
549      RETURN_EGL_SUCCESS(disp, disp->ClientAPIsString);
550   default:
551      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL);
552   }
553}
554
555
556EGLBoolean EGLAPIENTRY
557eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
558              EGLint config_size, EGLint *num_config)
559{
560   _EGLDisplay *disp = _eglLockDisplay(dpy);
561   _EGLDriver *drv;
562   EGLBoolean ret;
563
564   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
565   ret = drv->API.GetConfigs(drv, disp, configs, config_size, num_config);
566
567   RETURN_EGL_EVAL(disp, ret);
568}
569
570
571EGLBoolean EGLAPIENTRY
572eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs,
573                EGLint config_size, EGLint *num_config)
574{
575   _EGLDisplay *disp = _eglLockDisplay(dpy);
576   _EGLDriver *drv;
577   EGLBoolean ret;
578
579   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
580   ret = drv->API.ChooseConfig(drv, disp, attrib_list, configs,
581                                config_size, num_config);
582
583   RETURN_EGL_EVAL(disp, ret);
584}
585
586
587EGLBoolean EGLAPIENTRY
588eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
589                   EGLint attribute, EGLint *value)
590{
591   _EGLDisplay *disp = _eglLockDisplay(dpy);
592   _EGLConfig *conf = _eglLookupConfig(config, disp);
593   _EGLDriver *drv;
594   EGLBoolean ret;
595
596   _EGL_CHECK_CONFIG(disp, conf, EGL_FALSE, drv);
597   ret = drv->API.GetConfigAttrib(drv, disp, conf, attribute, value);
598
599   RETURN_EGL_EVAL(disp, ret);
600}
601
602
603EGLContext EGLAPIENTRY
604eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list,
605                 const EGLint *attrib_list)
606{
607   _EGLDisplay *disp = _eglLockDisplay(dpy);
608   _EGLConfig *conf = _eglLookupConfig(config, disp);
609   _EGLContext *share = _eglLookupContext(share_list, disp);
610   _EGLDriver *drv;
611   _EGLContext *context;
612   EGLContext ret;
613
614   _EGL_CHECK_DISPLAY(disp, EGL_NO_CONTEXT, drv);
615
616   if (!config && !disp->Extensions.MESA_configless_context)
617      RETURN_EGL_ERROR(disp, EGL_BAD_CONFIG, EGL_NO_CONTEXT);
618
619   if (!share && share_list != EGL_NO_CONTEXT)
620      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
621
622   context = drv->API.CreateContext(drv, disp, conf, share, attrib_list);
623   ret = (context) ? _eglLinkContext(context) : EGL_NO_CONTEXT;
624
625   RETURN_EGL_EVAL(disp, ret);
626}
627
628
629EGLBoolean EGLAPIENTRY
630eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
631{
632   _EGLDisplay *disp = _eglLockDisplay(dpy);
633   _EGLContext *context = _eglLookupContext(ctx, disp);
634   _EGLDriver *drv;
635   EGLBoolean ret;
636
637   _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv);
638   _eglUnlinkContext(context);
639   ret = drv->API.DestroyContext(drv, disp, context);
640
641   RETURN_EGL_EVAL(disp, ret);
642}
643
644
645EGLBoolean EGLAPIENTRY
646eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
647               EGLContext ctx)
648{
649   _EGLDisplay *disp = _eglLockDisplay(dpy);
650   _EGLContext *context = _eglLookupContext(ctx, disp);
651   _EGLSurface *draw_surf = _eglLookupSurface(draw, disp);
652   _EGLSurface *read_surf = _eglLookupSurface(read, disp);
653   _EGLDriver *drv;
654   EGLBoolean ret;
655
656   if (!disp)
657      RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
658   drv = disp->Driver;
659
660   /* display is allowed to be uninitialized under certain condition */
661   if (!disp->Initialized) {
662      if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE ||
663          ctx != EGL_NO_CONTEXT)
664         RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
665   }
666   if (!drv)
667      RETURN_EGL_SUCCESS(disp, EGL_TRUE);
668
669   if (!context && ctx != EGL_NO_CONTEXT)
670      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
671   if (!draw_surf || !read_surf) {
672      /* From the EGL 1.4 (20130211) spec:
673       *
674       *    To release the current context without assigning a new one, set ctx
675       *    to EGL_NO_CONTEXT and set draw and read to EGL_NO_SURFACE.
676       */
677      if (!disp->Extensions.KHR_surfaceless_context && ctx != EGL_NO_CONTEXT)
678         RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
679
680      if ((!draw_surf && draw != EGL_NO_SURFACE) ||
681          (!read_surf && read != EGL_NO_SURFACE))
682         RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
683      if (draw_surf || read_surf)
684         RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
685   }
686
687   ret = drv->API.MakeCurrent(drv, disp, draw_surf, read_surf, context);
688
689   RETURN_EGL_EVAL(disp, ret);
690}
691
692
693EGLBoolean EGLAPIENTRY
694eglQueryContext(EGLDisplay dpy, EGLContext ctx,
695                EGLint attribute, EGLint *value)
696{
697   _EGLDisplay *disp = _eglLockDisplay(dpy);
698   _EGLContext *context = _eglLookupContext(ctx, disp);
699   _EGLDriver *drv;
700   EGLBoolean ret;
701
702   _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv);
703   ret = drv->API.QueryContext(drv, disp, context, attribute, value);
704
705   RETURN_EGL_EVAL(disp, ret);
706}
707
708
709static EGLSurface
710_eglCreateWindowSurfaceCommon(_EGLDisplay *disp, EGLConfig config,
711                              void *native_window, const EGLint *attrib_list)
712{
713   _EGLConfig *conf = _eglLookupConfig(config, disp);
714   _EGLDriver *drv;
715   _EGLSurface *surf;
716   EGLSurface ret;
717
718   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
719
720   if (native_window == NULL)
721      RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
722
723   surf = drv->API.CreateWindowSurface(drv, disp, conf, native_window,
724                                       attrib_list);
725   ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
726
727   RETURN_EGL_EVAL(disp, ret);
728}
729
730
731EGLSurface EGLAPIENTRY
732eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
733                       EGLNativeWindowType window, const EGLint *attrib_list)
734{
735   _EGLDisplay *disp = _eglLockDisplay(dpy);
736   STATIC_ASSERT(sizeof(void*) == sizeof(window));
737   return _eglCreateWindowSurfaceCommon(disp, config, (void*) window,
738                                        attrib_list);
739}
740
741
742EGLSurface EGLAPIENTRY
743eglCreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config,
744                                  void *native_window,
745                                  const EGLint *attrib_list)
746{
747   _EGLDisplay *disp = _eglLockDisplay(dpy);
748
749#ifdef HAVE_X11_PLATFORM
750   if (disp->Platform == _EGL_PLATFORM_X11 && native_window != NULL) {
751      /* The `native_window` parameter for the X11 platform differs between
752       * eglCreateWindowSurface() and eglCreatePlatformPixmapSurfaceEXT(). In
753       * eglCreateWindowSurface(), the type of `native_window` is an Xlib
754       * `Window`. In eglCreatePlatformWindowSurfaceEXT(), the type is
755       * `Window*`.  Convert `Window*` to `Window` because that's what
756       * dri2_x11_create_window_surface() expects.
757       */
758      native_window = (void*) (* (Window*) native_window);
759   }
760#endif
761
762   return _eglCreateWindowSurfaceCommon(disp, config, native_window,
763                                        attrib_list);
764}
765
766
767static EGLSurface
768_eglCreatePixmapSurfaceCommon(_EGLDisplay *disp, EGLConfig config,
769                              void *native_pixmap, const EGLint *attrib_list)
770{
771   _EGLConfig *conf = _eglLookupConfig(config, disp);
772   _EGLDriver *drv;
773   _EGLSurface *surf;
774   EGLSurface ret;
775
776   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
777   surf = drv->API.CreatePixmapSurface(drv, disp, conf, native_pixmap,
778                                       attrib_list);
779   ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
780
781   RETURN_EGL_EVAL(disp, ret);
782}
783
784
785EGLSurface EGLAPIENTRY
786eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
787                       EGLNativePixmapType pixmap, const EGLint *attrib_list)
788{
789   _EGLDisplay *disp = _eglLockDisplay(dpy);
790   STATIC_ASSERT(sizeof(void*) == sizeof(pixmap));
791   return _eglCreatePixmapSurfaceCommon(disp, config, (void*) pixmap,
792                                         attrib_list);
793}
794
795EGLSurface EGLAPIENTRY
796eglCreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config,
797                                   void *native_pixmap,
798                                   const EGLint *attrib_list)
799{
800   _EGLDisplay *disp = _eglLockDisplay(dpy);
801
802#ifdef HAVE_X11_PLATFORM
803      /* The `native_pixmap` parameter for the X11 platform differs between
804       * eglCreatePixmapSurface() and eglCreatePlatformPixmapSurfaceEXT(). In
805       * eglCreatePixmapSurface(), the type of `native_pixmap` is an Xlib
806       * `Pixmap`. In eglCreatePlatformPixmapSurfaceEXT(), the type is
807       * `Pixmap*`.  Convert `Pixmap*` to `Pixmap` because that's what
808       * dri2_x11_create_pixmap_surface() expects.
809       */
810   if (disp->Platform == _EGL_PLATFORM_X11 && native_pixmap != NULL) {
811      native_pixmap = (void*) (* (Pixmap*) native_pixmap);
812   }
813#endif
814
815   return _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap,
816                                        attrib_list);
817}
818
819
820EGLSurface EGLAPIENTRY
821eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
822                        const EGLint *attrib_list)
823{
824   _EGLDisplay *disp = _eglLockDisplay(dpy);
825   _EGLConfig *conf = _eglLookupConfig(config, disp);
826   _EGLDriver *drv;
827   _EGLSurface *surf;
828   EGLSurface ret;
829
830   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
831
832   surf = drv->API.CreatePbufferSurface(drv, disp, conf, attrib_list);
833   ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
834
835   RETURN_EGL_EVAL(disp, ret);
836}
837
838
839EGLBoolean EGLAPIENTRY
840eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
841{
842   _EGLDisplay *disp = _eglLockDisplay(dpy);
843   _EGLSurface *surf = _eglLookupSurface(surface, disp);
844   _EGLDriver *drv;
845   EGLBoolean ret;
846
847   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
848   _eglUnlinkSurface(surf);
849   ret = drv->API.DestroySurface(drv, disp, surf);
850
851   RETURN_EGL_EVAL(disp, ret);
852}
853
854EGLBoolean EGLAPIENTRY
855eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
856                EGLint attribute, EGLint *value)
857{
858   _EGLDisplay *disp = _eglLockDisplay(dpy);
859   _EGLSurface *surf = _eglLookupSurface(surface, disp);
860   _EGLDriver *drv;
861   EGLBoolean ret;
862
863   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
864   ret = drv->API.QuerySurface(drv, disp, surf, attribute, value);
865
866   RETURN_EGL_EVAL(disp, ret);
867}
868
869EGLBoolean EGLAPIENTRY
870eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
871                 EGLint attribute, EGLint value)
872{
873   _EGLDisplay *disp = _eglLockDisplay(dpy);
874   _EGLSurface *surf = _eglLookupSurface(surface, disp);
875   _EGLDriver *drv;
876   EGLBoolean ret;
877
878   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
879   ret = drv->API.SurfaceAttrib(drv, disp, surf, attribute, value);
880
881   RETURN_EGL_EVAL(disp, ret);
882}
883
884
885EGLBoolean EGLAPIENTRY
886eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
887{
888   _EGLDisplay *disp = _eglLockDisplay(dpy);
889   _EGLSurface *surf = _eglLookupSurface(surface, disp);
890   _EGLDriver *drv;
891   EGLBoolean ret;
892
893   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
894   ret = drv->API.BindTexImage(drv, disp, surf, buffer);
895
896   RETURN_EGL_EVAL(disp, ret);
897}
898
899
900EGLBoolean EGLAPIENTRY
901eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
902{
903   _EGLDisplay *disp = _eglLockDisplay(dpy);
904   _EGLSurface *surf = _eglLookupSurface(surface, disp);
905   _EGLDriver *drv;
906   EGLBoolean ret;
907
908   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
909   ret = drv->API.ReleaseTexImage(drv, disp, surf, buffer);
910
911   RETURN_EGL_EVAL(disp, ret);
912}
913
914
915EGLBoolean EGLAPIENTRY
916eglSwapInterval(EGLDisplay dpy, EGLint interval)
917{
918   _EGLDisplay *disp = _eglLockDisplay(dpy);
919   _EGLContext *ctx = _eglGetCurrentContext();
920   _EGLSurface *surf;
921   _EGLDriver *drv;
922   EGLBoolean ret;
923
924   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
925
926   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
927       ctx->Resource.Display != disp)
928      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
929
930   surf = ctx->DrawSurface;
931   if (_eglGetSurfaceHandle(surf) == EGL_NO_SURFACE)
932      RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
933
934   ret = drv->API.SwapInterval(drv, disp, surf, interval);
935
936   RETURN_EGL_EVAL(disp, ret);
937}
938
939
940EGLBoolean EGLAPIENTRY
941eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
942{
943   _EGLContext *ctx = _eglGetCurrentContext();
944   _EGLDisplay *disp = _eglLockDisplay(dpy);
945   _EGLSurface *surf = _eglLookupSurface(surface, disp);
946   _EGLDriver *drv;
947   EGLBoolean ret;
948
949   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
950
951   /* surface must be bound to current context in EGL 1.4 */
952   #ifndef _EGL_BUILT_IN_DRIVER_HAIKU
953   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
954       surf != ctx->DrawSurface)
955      RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
956   #endif
957
958   ret = drv->API.SwapBuffers(drv, disp, surf);
959
960   RETURN_EGL_EVAL(disp, ret);
961}
962
963
964#ifdef EGL_EXT_swap_buffers_with_damage
965
966EGLBoolean EGLAPIENTRY
967eglSwapBuffersWithDamageEXT(EGLDisplay dpy, EGLSurface surface,
968                            EGLint *rects, EGLint n_rects)
969{
970   _EGLContext *ctx = _eglGetCurrentContext();
971   _EGLDisplay *disp = _eglLockDisplay(dpy);
972   _EGLSurface *surf = _eglLookupSurface(surface, disp);
973   _EGLDriver *drv;
974   EGLBoolean ret;
975
976   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
977
978   /* surface must be bound to current context in EGL 1.4 */
979   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
980       surf != ctx->DrawSurface)
981      RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
982
983   if ((n_rects > 0 && rects == NULL) || n_rects < 0)
984      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
985
986   ret = drv->API.SwapBuffersWithDamageEXT(drv, disp, surf, rects, n_rects);
987
988   RETURN_EGL_EVAL(disp, ret);
989}
990
991#endif /* EGL_EXT_swap_buffers_with_damage */
992
993EGLBoolean EGLAPIENTRY
994eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
995{
996   _EGLDisplay *disp = _eglLockDisplay(dpy);
997   _EGLSurface *surf = _eglLookupSurface(surface, disp);
998   _EGLDriver *drv;
999   EGLBoolean ret;
1000   void *native_pixmap_ptr;
1001
1002   STATIC_ASSERT(sizeof(void*) == sizeof(target));
1003   native_pixmap_ptr = (void*) target;
1004
1005   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1006   if (disp->Platform != _eglGetNativePlatform(disp->PlatformDisplay))
1007      RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_FALSE);
1008   ret = drv->API.CopyBuffers(drv, disp, surf, native_pixmap_ptr);
1009
1010   RETURN_EGL_EVAL(disp, ret);
1011}
1012
1013
1014EGLBoolean EGLAPIENTRY
1015eglWaitClient(void)
1016{
1017   _EGLContext *ctx = _eglGetCurrentContext();
1018   _EGLDisplay *disp;
1019   _EGLDriver *drv;
1020   EGLBoolean ret;
1021
1022   if (!ctx)
1023      RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1024
1025   disp = ctx->Resource.Display;
1026   mtx_lock(&disp->Mutex);
1027
1028   /* let bad current context imply bad current surface */
1029   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1030       _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
1031      RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
1032
1033   /* a valid current context implies an initialized current display */
1034   assert(disp->Initialized);
1035   drv = disp->Driver;
1036   ret = drv->API.WaitClient(drv, disp, ctx);
1037
1038   RETURN_EGL_EVAL(disp, ret);
1039}
1040
1041
1042EGLBoolean EGLAPIENTRY
1043eglWaitGL(void)
1044{
1045   _EGLThreadInfo *t = _eglGetCurrentThread();
1046   EGLint api_index = t->CurrentAPIIndex;
1047   EGLint es_index = _eglConvertApiToIndex(EGL_OPENGL_ES_API);
1048   EGLBoolean ret;
1049
1050   if (api_index != es_index && _eglIsCurrentThreadDummy())
1051      RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
1052
1053   t->CurrentAPIIndex = es_index;
1054   ret = eglWaitClient();
1055   t->CurrentAPIIndex = api_index;
1056   return ret;
1057}
1058
1059
1060EGLBoolean EGLAPIENTRY
1061eglWaitNative(EGLint engine)
1062{
1063   _EGLContext *ctx = _eglGetCurrentContext();
1064   _EGLDisplay *disp;
1065   _EGLDriver *drv;
1066   EGLBoolean ret;
1067
1068   if (!ctx)
1069      RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1070
1071   disp = ctx->Resource.Display;
1072   mtx_lock(&disp->Mutex);
1073
1074   /* let bad current context imply bad current surface */
1075   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1076       _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
1077      RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
1078
1079   /* a valid current context implies an initialized current display */
1080   assert(disp->Initialized);
1081   drv = disp->Driver;
1082   ret = drv->API.WaitNative(drv, disp, engine);
1083
1084   RETURN_EGL_EVAL(disp, ret);
1085}
1086
1087
1088EGLDisplay EGLAPIENTRY
1089eglGetCurrentDisplay(void)
1090{
1091   _EGLContext *ctx = _eglGetCurrentContext();
1092   EGLDisplay ret;
1093
1094   ret = (ctx) ? _eglGetDisplayHandle(ctx->Resource.Display) : EGL_NO_DISPLAY;
1095
1096   RETURN_EGL_SUCCESS(NULL, ret);
1097}
1098
1099
1100EGLContext EGLAPIENTRY
1101eglGetCurrentContext(void)
1102{
1103   _EGLContext *ctx = _eglGetCurrentContext();
1104   EGLContext ret;
1105
1106   ret = _eglGetContextHandle(ctx);
1107
1108   RETURN_EGL_SUCCESS(NULL, ret);
1109}
1110
1111
1112EGLSurface EGLAPIENTRY
1113eglGetCurrentSurface(EGLint readdraw)
1114{
1115   _EGLContext *ctx = _eglGetCurrentContext();
1116   EGLint err = EGL_SUCCESS;
1117   _EGLSurface *surf;
1118   EGLSurface ret;
1119
1120   if (!ctx)
1121      RETURN_EGL_SUCCESS(NULL, EGL_NO_SURFACE);
1122
1123   switch (readdraw) {
1124   case EGL_DRAW:
1125      surf = ctx->DrawSurface;
1126      break;
1127   case EGL_READ:
1128      surf = ctx->ReadSurface;
1129      break;
1130   default:
1131      surf = NULL;
1132      err = EGL_BAD_PARAMETER;
1133      break;
1134   }
1135
1136   ret = _eglGetSurfaceHandle(surf);
1137
1138   RETURN_EGL_ERROR(NULL, err, ret);
1139}
1140
1141
1142EGLint EGLAPIENTRY
1143eglGetError(void)
1144{
1145   _EGLThreadInfo *t = _eglGetCurrentThread();
1146   EGLint e = t->LastError;
1147   if (!_eglIsCurrentThreadDummy())
1148      t->LastError = EGL_SUCCESS;
1149   return e;
1150}
1151
1152
1153__eglMustCastToProperFunctionPointerType EGLAPIENTRY
1154eglGetProcAddress(const char *procname)
1155{
1156   static const struct {
1157      const char *name;
1158      _EGLProc function;
1159   } egl_functions[] = {
1160      /* core functions should not be queryable, but, well... */
1161#ifdef _EGL_GET_CORE_ADDRESSES
1162      /* alphabetical order */
1163      { "eglBindAPI", (_EGLProc) eglBindAPI },
1164      { "eglBindTexImage", (_EGLProc) eglBindTexImage },
1165      { "eglChooseConfig", (_EGLProc) eglChooseConfig },
1166      { "eglCopyBuffers", (_EGLProc) eglCopyBuffers },
1167      { "eglCreateContext", (_EGLProc) eglCreateContext },
1168      { "eglCreatePbufferFromClientBuffer", (_EGLProc) eglCreatePbufferFromClientBuffer },
1169      { "eglCreatePbufferSurface", (_EGLProc) eglCreatePbufferSurface },
1170      { "eglCreatePixmapSurface", (_EGLProc) eglCreatePixmapSurface },
1171      { "eglCreateWindowSurface", (_EGLProc) eglCreateWindowSurface },
1172      { "eglDestroyContext", (_EGLProc) eglDestroyContext },
1173      { "eglDestroySurface", (_EGLProc) eglDestroySurface },
1174      { "eglGetConfigAttrib", (_EGLProc) eglGetConfigAttrib },
1175      { "eglGetConfigs", (_EGLProc) eglGetConfigs },
1176      { "eglGetCurrentContext", (_EGLProc) eglGetCurrentContext },
1177      { "eglGetCurrentDisplay", (_EGLProc) eglGetCurrentDisplay },
1178      { "eglGetCurrentSurface", (_EGLProc) eglGetCurrentSurface },
1179      { "eglGetDisplay", (_EGLProc) eglGetDisplay },
1180      { "eglGetError", (_EGLProc) eglGetError },
1181      { "eglGetProcAddress", (_EGLProc) eglGetProcAddress },
1182      { "eglInitialize", (_EGLProc) eglInitialize },
1183      { "eglMakeCurrent", (_EGLProc) eglMakeCurrent },
1184      { "eglQueryAPI", (_EGLProc) eglQueryAPI },
1185      { "eglQueryContext", (_EGLProc) eglQueryContext },
1186      { "eglQueryString", (_EGLProc) eglQueryString },
1187      { "eglQuerySurface", (_EGLProc) eglQuerySurface },
1188      { "eglReleaseTexImage", (_EGLProc) eglReleaseTexImage },
1189      { "eglReleaseThread", (_EGLProc) eglReleaseThread },
1190      { "eglSurfaceAttrib", (_EGLProc) eglSurfaceAttrib },
1191      { "eglSwapBuffers", (_EGLProc) eglSwapBuffers },
1192      { "eglSwapInterval", (_EGLProc) eglSwapInterval },
1193      { "eglTerminate", (_EGLProc) eglTerminate },
1194      { "eglWaitClient", (_EGLProc) eglWaitClient },
1195      { "eglWaitGL", (_EGLProc) eglWaitGL },
1196      { "eglWaitNative", (_EGLProc) eglWaitNative },
1197#endif /* _EGL_GET_CORE_ADDRESSES */
1198#ifdef EGL_MESA_screen_surface
1199      { "eglChooseModeMESA", (_EGLProc) eglChooseModeMESA },
1200      { "eglGetModesMESA", (_EGLProc) eglGetModesMESA },
1201      { "eglGetModeAttribMESA", (_EGLProc) eglGetModeAttribMESA },
1202      { "eglCopyContextMESA", (_EGLProc) eglCopyContextMESA },
1203      { "eglGetScreensMESA", (_EGLProc) eglGetScreensMESA },
1204      { "eglCreateScreenSurfaceMESA", (_EGLProc) eglCreateScreenSurfaceMESA },
1205      { "eglShowScreenSurfaceMESA", (_EGLProc) eglShowScreenSurfaceMESA },
1206      { "eglScreenPositionMESA", (_EGLProc) eglScreenPositionMESA },
1207      { "eglQueryScreenMESA", (_EGLProc) eglQueryScreenMESA },
1208      { "eglQueryScreenSurfaceMESA", (_EGLProc) eglQueryScreenSurfaceMESA },
1209      { "eglQueryScreenModeMESA", (_EGLProc) eglQueryScreenModeMESA },
1210      { "eglQueryModeStringMESA", (_EGLProc) eglQueryModeStringMESA },
1211#endif /* EGL_MESA_screen_surface */
1212#ifdef EGL_MESA_drm_display
1213      { "eglGetDRMDisplayMESA", (_EGLProc) eglGetDRMDisplayMESA },
1214#endif
1215      { "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR },
1216      { "eglDestroyImageKHR", (_EGLProc) eglDestroyImageKHR },
1217      { "eglCreateSyncKHR", (_EGLProc) eglCreateSyncKHR },
1218      { "eglDestroySyncKHR", (_EGLProc) eglDestroySyncKHR },
1219      { "eglClientWaitSyncKHR", (_EGLProc) eglClientWaitSyncKHR },
1220      { "eglWaitSyncKHR", (_EGLProc) eglWaitSyncKHR },
1221      { "eglSignalSyncKHR", (_EGLProc) eglSignalSyncKHR },
1222      { "eglGetSyncAttribKHR", (_EGLProc) eglGetSyncAttribKHR },
1223#ifdef EGL_NOK_swap_region
1224      { "eglSwapBuffersRegionNOK", (_EGLProc) eglSwapBuffersRegionNOK },
1225#endif
1226#ifdef EGL_MESA_drm_image
1227      { "eglCreateDRMImageMESA", (_EGLProc) eglCreateDRMImageMESA },
1228      { "eglExportDRMImageMESA", (_EGLProc) eglExportDRMImageMESA },
1229#endif
1230#ifdef EGL_WL_bind_wayland_display
1231      { "eglBindWaylandDisplayWL", (_EGLProc) eglBindWaylandDisplayWL },
1232      { "eglUnbindWaylandDisplayWL", (_EGLProc) eglUnbindWaylandDisplayWL },
1233      { "eglQueryWaylandBufferWL", (_EGLProc) eglQueryWaylandBufferWL },
1234#endif
1235#ifdef EGL_WL_create_wayland_buffer_from_image
1236      { "eglCreateWaylandBufferFromImageWL", (_EGLProc) eglCreateWaylandBufferFromImageWL },
1237#endif
1238      { "eglPostSubBufferNV", (_EGLProc) eglPostSubBufferNV },
1239#ifdef EGL_EXT_swap_buffers_with_damage
1240      { "eglSwapBuffersWithDamageEXT", (_EGLProc) eglSwapBuffersWithDamageEXT },
1241#endif
1242      { "eglGetPlatformDisplayEXT", (_EGLProc) eglGetPlatformDisplayEXT },
1243      { "eglCreatePlatformWindowSurfaceEXT", (_EGLProc) eglCreatePlatformWindowSurfaceEXT },
1244      { "eglCreatePlatformPixmapSurfaceEXT", (_EGLProc) eglCreatePlatformPixmapSurfaceEXT },
1245      { "eglGetSyncValuesCHROMIUM", (_EGLProc) eglGetSyncValuesCHROMIUM },
1246#ifdef EGL_MESA_dma_buf_image_export
1247      { "eglExportDMABUFImageQueryMESA", (_EGLProc) eglExportDMABUFImageQueryMESA },
1248      { "eglExportDMABUFImageMESA", (_EGLProc) eglExportDMABUFImageMESA },
1249#endif
1250      { NULL, NULL }
1251   };
1252   EGLint i;
1253   _EGLProc ret;
1254
1255   if (!procname)
1256      RETURN_EGL_SUCCESS(NULL, NULL);
1257
1258   ret = NULL;
1259   if (strncmp(procname, "egl", 3) == 0) {
1260      for (i = 0; egl_functions[i].name; i++) {
1261         if (strcmp(egl_functions[i].name, procname) == 0) {
1262            ret = egl_functions[i].function;
1263            break;
1264         }
1265      }
1266   }
1267   if (!ret)
1268      ret = _eglGetDriverProc(procname);
1269
1270   RETURN_EGL_SUCCESS(NULL, ret);
1271}
1272
1273
1274#ifdef EGL_MESA_screen_surface
1275
1276
1277/*
1278 * EGL_MESA_screen extension
1279 */
1280
1281EGLBoolean EGLAPIENTRY
1282eglChooseModeMESA(EGLDisplay dpy, EGLScreenMESA screen,
1283                  const EGLint *attrib_list, EGLModeMESA *modes,
1284                  EGLint modes_size, EGLint *num_modes)
1285{
1286   _EGLDisplay *disp = _eglLockDisplay(dpy);
1287   _EGLScreen *scrn = _eglLookupScreen(screen, disp);
1288   _EGLDriver *drv;
1289   EGLBoolean ret;
1290
1291   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
1292   ret = drv->API.ChooseModeMESA(drv, disp, scrn, attrib_list,
1293         modes, modes_size, num_modes);
1294
1295   RETURN_EGL_EVAL(disp, ret);
1296}
1297
1298
1299EGLBoolean EGLAPIENTRY
1300eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes,
1301                EGLint mode_size, EGLint *num_mode)
1302{
1303   _EGLDisplay *disp = _eglLockDisplay(dpy);
1304   _EGLScreen *scrn = _eglLookupScreen(screen, disp);
1305   _EGLDriver *drv;
1306   EGLBoolean ret;
1307
1308   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
1309   ret = drv->API.GetModesMESA(drv, disp, scrn, modes, mode_size, num_mode);
1310
1311   RETURN_EGL_EVAL(disp, ret);
1312}
1313
1314
1315EGLBoolean EGLAPIENTRY
1316eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode,
1317                     EGLint attribute, EGLint *value)
1318{
1319   _EGLDisplay *disp = _eglLockDisplay(dpy);
1320   _EGLMode *m = _eglLookupMode(mode, disp);
1321   _EGLDriver *drv;
1322   EGLBoolean ret;
1323
1324   _EGL_CHECK_MODE(disp, m, EGL_FALSE, drv);
1325   ret = drv->API.GetModeAttribMESA(drv, disp, m, attribute, value);
1326
1327   RETURN_EGL_EVAL(disp, ret);
1328}
1329
1330
1331EGLBoolean EGLAPIENTRY
1332eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest,
1333                   EGLint mask)
1334{
1335   _EGLDisplay *disp = _eglLockDisplay(dpy);
1336   _EGLContext *source_context = _eglLookupContext(source, disp);
1337   _EGLContext *dest_context = _eglLookupContext(dest, disp);
1338   _EGLDriver *drv;
1339   EGLBoolean ret;
1340
1341   _EGL_CHECK_CONTEXT(disp, source_context, EGL_FALSE, drv);
1342   if (!dest_context)
1343      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
1344
1345   ret = drv->API.CopyContextMESA(drv, disp,
1346         source_context, dest_context, mask);
1347
1348   RETURN_EGL_EVAL(disp, ret);
1349}
1350
1351
1352EGLBoolean EGLAPIENTRY
1353eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens,
1354                  EGLint max_screens, EGLint *num_screens)
1355{
1356   _EGLDisplay *disp = _eglLockDisplay(dpy);
1357   _EGLDriver *drv;
1358   EGLBoolean ret;
1359
1360   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1361   ret = drv->API.GetScreensMESA(drv, disp, screens, max_screens, num_screens);
1362
1363   RETURN_EGL_EVAL(disp, ret);
1364}
1365
1366
1367EGLSurface EGLAPIENTRY
1368eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config,
1369                           const EGLint *attrib_list)
1370{
1371   _EGLDisplay *disp = _eglLockDisplay(dpy);
1372   _EGLConfig *conf = _eglLookupConfig(config, disp);
1373   _EGLDriver *drv;
1374   _EGLSurface *surf;
1375   EGLSurface ret;
1376
1377   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
1378
1379   surf = drv->API.CreateScreenSurfaceMESA(drv, disp, conf, attrib_list);
1380   ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1381
1382   RETURN_EGL_EVAL(disp, ret);
1383}
1384
1385
1386EGLBoolean EGLAPIENTRY
1387eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen,
1388                         EGLSurface surface, EGLModeMESA mode)
1389{
1390   _EGLDisplay *disp = _eglLockDisplay(dpy);
1391   _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
1392   _EGLSurface *surf = _eglLookupSurface(surface, disp);
1393   _EGLMode *m = _eglLookupMode(mode, disp);
1394   _EGLDriver *drv;
1395   EGLBoolean ret;
1396
1397   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
1398   if (!surf && surface != EGL_NO_SURFACE)
1399      RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1400   if (!m && mode != EGL_NO_MODE_MESA)
1401      RETURN_EGL_ERROR(disp, EGL_BAD_MODE_MESA, EGL_FALSE);
1402
1403   ret = drv->API.ShowScreenSurfaceMESA(drv, disp, scrn, surf, m);
1404
1405   RETURN_EGL_EVAL(disp, ret);
1406}
1407
1408
1409EGLBoolean EGLAPIENTRY
1410eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y)
1411{
1412   _EGLDisplay *disp = _eglLockDisplay(dpy);
1413   _EGLScreen *scrn = _eglLookupScreen(screen, disp);
1414   _EGLDriver *drv;
1415   EGLBoolean ret;
1416
1417   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
1418   ret = drv->API.ScreenPositionMESA(drv, disp, scrn, x, y);
1419
1420   RETURN_EGL_EVAL(disp, ret);
1421}
1422
1423
1424EGLBoolean EGLAPIENTRY
1425eglQueryScreenMESA(EGLDisplay dpy, EGLScreenMESA screen,
1426                   EGLint attribute, EGLint *value)
1427{
1428   _EGLDisplay *disp = _eglLockDisplay(dpy);
1429   _EGLScreen *scrn = _eglLookupScreen(screen, disp);
1430   _EGLDriver *drv;
1431   EGLBoolean ret;
1432
1433   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
1434   ret = drv->API.QueryScreenMESA(drv, disp, scrn, attribute, value);
1435
1436   RETURN_EGL_EVAL(disp, ret);
1437}
1438
1439
1440EGLBoolean EGLAPIENTRY
1441eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen,
1442                          EGLSurface *surface)
1443{
1444   _EGLDisplay *disp = _eglLockDisplay(dpy);
1445   _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
1446   _EGLDriver *drv;
1447   _EGLSurface *surf;
1448   EGLBoolean ret;
1449
1450   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
1451   ret = drv->API.QueryScreenSurfaceMESA(drv, disp, scrn, &surf);
1452   if (ret && surface)
1453      *surface = _eglGetSurfaceHandle(surf);
1454
1455   RETURN_EGL_EVAL(disp, ret);
1456}
1457
1458
1459EGLBoolean EGLAPIENTRY
1460eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode)
1461{
1462   _EGLDisplay *disp = _eglLockDisplay(dpy);
1463   _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
1464   _EGLDriver *drv;
1465   _EGLMode *m;
1466   EGLBoolean ret;
1467
1468   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
1469   ret = drv->API.QueryScreenModeMESA(drv, disp, scrn, &m);
1470   if (ret && mode)
1471      *mode = m->Handle;
1472
1473   RETURN_EGL_EVAL(disp, ret);
1474}
1475
1476
1477const char * EGLAPIENTRY
1478eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode)
1479{
1480   _EGLDisplay *disp = _eglLockDisplay(dpy);
1481   _EGLMode *m = _eglLookupMode(mode, disp);
1482   _EGLDriver *drv;
1483   const char *ret;
1484
1485   _EGL_CHECK_MODE(disp, m, NULL, drv);
1486   ret = drv->API.QueryModeStringMESA(drv, disp, m);
1487
1488   RETURN_EGL_EVAL(disp, ret);
1489}
1490
1491
1492#endif /* EGL_MESA_screen_surface */
1493
1494
1495#ifdef EGL_MESA_drm_display
1496
1497EGLDisplay EGLAPIENTRY
1498eglGetDRMDisplayMESA(int fd)
1499{
1500   _EGLDisplay *dpy = _eglFindDisplay(_EGL_PLATFORM_DRM, (void *) (intptr_t) fd);
1501   return _eglGetDisplayHandle(dpy);
1502}
1503
1504#endif /* EGL_MESA_drm_display */
1505
1506/**
1507 ** EGL 1.2
1508 **/
1509
1510/**
1511 * Specify the client API to use for subsequent calls including:
1512 *  eglCreateContext()
1513 *  eglGetCurrentContext()
1514 *  eglGetCurrentDisplay()
1515 *  eglGetCurrentSurface()
1516 *  eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT)
1517 *  eglWaitClient()
1518 *  eglWaitNative()
1519 * See section 3.7 "Rendering Context" in the EGL specification for details.
1520 */
1521EGLBoolean EGLAPIENTRY
1522eglBindAPI(EGLenum api)
1523{
1524   _EGLThreadInfo *t = _eglGetCurrentThread();
1525
1526   if (_eglIsCurrentThreadDummy())
1527      RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
1528
1529   if (!_eglIsApiValid(api))
1530      RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, EGL_FALSE);
1531
1532   t->CurrentAPIIndex = _eglConvertApiToIndex(api);
1533
1534   RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1535}
1536
1537
1538/**
1539 * Return the last value set with eglBindAPI().
1540 */
1541EGLenum EGLAPIENTRY
1542eglQueryAPI(void)
1543{
1544   _EGLThreadInfo *t = _eglGetCurrentThread();
1545   EGLenum ret;
1546
1547   /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */
1548   ret = _eglConvertApiFromIndex(t->CurrentAPIIndex);
1549
1550   RETURN_EGL_SUCCESS(NULL, ret);
1551}
1552
1553
1554EGLSurface EGLAPIENTRY
1555eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
1556                                 EGLClientBuffer buffer, EGLConfig config,
1557                                 const EGLint *attrib_list)
1558{
1559   _EGLDisplay *disp = _eglLockDisplay(dpy);
1560   _EGLConfig *conf = _eglLookupConfig(config, disp);
1561   _EGLDriver *drv;
1562   _EGLSurface *surf;
1563   EGLSurface ret;
1564
1565   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
1566
1567   surf = drv->API.CreatePbufferFromClientBuffer(drv, disp, buftype, buffer,
1568                                                 conf, attrib_list);
1569   ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1570
1571   RETURN_EGL_EVAL(disp, ret);
1572}
1573
1574
1575EGLBoolean EGLAPIENTRY
1576eglReleaseThread(void)
1577{
1578   /* unbind current contexts */
1579   if (!_eglIsCurrentThreadDummy()) {
1580      _EGLThreadInfo *t = _eglGetCurrentThread();
1581      EGLint api_index = t->CurrentAPIIndex;
1582      EGLint i;
1583
1584      for (i = 0; i < _EGL_API_NUM_APIS; i++) {
1585         _EGLContext *ctx = t->CurrentContexts[i];
1586         if (ctx) {
1587            _EGLDisplay *disp = ctx->Resource.Display;
1588            _EGLDriver *drv;
1589
1590            t->CurrentAPIIndex = i;
1591
1592            mtx_lock(&disp->Mutex);
1593            drv = disp->Driver;
1594            (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
1595            mtx_unlock(&disp->Mutex);
1596         }
1597      }
1598
1599      t->CurrentAPIIndex = api_index;
1600   }
1601
1602   _eglDestroyCurrentThread();
1603
1604   RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1605}
1606
1607
1608EGLImageKHR EGLAPIENTRY
1609eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1610                  EGLClientBuffer buffer, const EGLint *attr_list)
1611{
1612   _EGLDisplay *disp = _eglLockDisplay(dpy);
1613   _EGLContext *context = _eglLookupContext(ctx, disp);
1614   _EGLDriver *drv;
1615   _EGLImage *img;
1616   EGLImageKHR ret;
1617
1618   _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
1619   if (!disp->Extensions.KHR_image_base)
1620      RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
1621   if (!context && ctx != EGL_NO_CONTEXT)
1622      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1623   /* "If <target> is EGL_LINUX_DMA_BUF_EXT, <dpy> must be a valid display,
1624    *  <ctx> must be EGL_NO_CONTEXT..."
1625    */
1626   if (ctx != EGL_NO_CONTEXT && target == EGL_LINUX_DMA_BUF_EXT)
1627      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1628
1629   img = drv->API.CreateImageKHR(drv,
1630         disp, context, target, buffer, attr_list);
1631   ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
1632
1633   RETURN_EGL_EVAL(disp, ret);
1634}
1635
1636
1637EGLBoolean EGLAPIENTRY
1638eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
1639{
1640   _EGLDisplay *disp = _eglLockDisplay(dpy);
1641   _EGLImage *img = _eglLookupImage(image, disp);
1642   _EGLDriver *drv;
1643   EGLBoolean ret;
1644
1645   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1646   if (!disp->Extensions.KHR_image_base)
1647      RETURN_EGL_EVAL(disp, EGL_FALSE);
1648   if (!img)
1649      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1650
1651   _eglUnlinkImage(img);
1652   ret = drv->API.DestroyImageKHR(drv, disp, img);
1653
1654   RETURN_EGL_EVAL(disp, ret);
1655}
1656
1657
1658EGLSyncKHR EGLAPIENTRY
1659eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1660{
1661   _EGLDisplay *disp = _eglLockDisplay(dpy);
1662   _EGLContext *ctx = _eglGetCurrentContext();
1663   _EGLDriver *drv;
1664   _EGLSync *sync;
1665   EGLSyncKHR ret;
1666
1667   _EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv);
1668
1669   /* return an error if the client API doesn't support GL_OES_EGL_sync */
1670   if (!ctx || ctx->Resource.Display != dpy ||
1671       ctx->ClientAPI != EGL_OPENGL_ES_API)
1672      RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1673
1674   switch (type) {
1675   case EGL_SYNC_FENCE_KHR:
1676      if (!disp->Extensions.KHR_fence_sync)
1677         RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1678      break;
1679   case EGL_SYNC_REUSABLE_KHR:
1680      if (!disp->Extensions.KHR_reusable_sync)
1681         RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1682      break;
1683   default:
1684      RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1685   }
1686
1687   sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list);
1688   ret = (sync) ? _eglLinkSync(sync) : EGL_NO_SYNC_KHR;
1689
1690   RETURN_EGL_EVAL(disp, ret);
1691}
1692
1693
1694EGLBoolean EGLAPIENTRY
1695eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1696{
1697   _EGLDisplay *disp = _eglLockDisplay(dpy);
1698   _EGLSync *s = _eglLookupSync(sync, disp);
1699   _EGLDriver *drv;
1700   EGLBoolean ret;
1701
1702   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1703   assert(disp->Extensions.KHR_reusable_sync ||
1704          disp->Extensions.KHR_fence_sync);
1705
1706   _eglUnlinkSync(s);
1707   ret = drv->API.DestroySyncKHR(drv, disp, s);
1708
1709   RETURN_EGL_EVAL(disp, ret);
1710}
1711
1712
1713EGLint EGLAPIENTRY
1714eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
1715{
1716   _EGLDisplay *disp = _eglLockDisplay(dpy);
1717   _EGLSync *s = _eglLookupSync(sync, disp);
1718   _EGLDriver *drv;
1719   EGLint ret;
1720
1721   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1722   assert(disp->Extensions.KHR_reusable_sync ||
1723          disp->Extensions.KHR_fence_sync);
1724
1725   if (s->SyncStatus == EGL_SIGNALED_KHR)
1726      RETURN_EGL_EVAL(disp, EGL_CONDITION_SATISFIED_KHR);
1727
1728   ret = drv->API.ClientWaitSyncKHR(drv, disp, s, flags, timeout);
1729
1730   RETURN_EGL_EVAL(disp, ret);
1731}
1732
1733
1734EGLint EGLAPIENTRY
1735eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags)
1736{
1737   _EGLDisplay *disp = _eglLockDisplay(dpy);
1738   _EGLSync *s = _eglLookupSync(sync, disp);
1739   _EGLContext *ctx = _eglGetCurrentContext();
1740   _EGLDriver *drv;
1741   EGLint ret;
1742
1743   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1744   assert(disp->Extensions.KHR_wait_sync);
1745
1746   /* return an error if the client API doesn't support GL_OES_EGL_sync */
1747   if (ctx == EGL_NO_CONTEXT || ctx->ClientAPI != EGL_OPENGL_ES_API)
1748      RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
1749
1750   /* the API doesn't allow any flags yet */
1751   if (flags != 0)
1752      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1753
1754   ret = drv->API.WaitSyncKHR(drv, disp, s);
1755
1756   RETURN_EGL_EVAL(disp, ret);
1757}
1758
1759
1760EGLBoolean EGLAPIENTRY
1761eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode)
1762{
1763   _EGLDisplay *disp = _eglLockDisplay(dpy);
1764   _EGLSync *s = _eglLookupSync(sync, disp);
1765   _EGLDriver *drv;
1766   EGLBoolean ret;
1767
1768   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1769   assert(disp->Extensions.KHR_reusable_sync);
1770   ret = drv->API.SignalSyncKHR(drv, disp, s, mode);
1771
1772   RETURN_EGL_EVAL(disp, ret);
1773}
1774
1775
1776EGLBoolean EGLAPIENTRY
1777eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
1778{
1779   _EGLDisplay *disp = _eglLockDisplay(dpy);
1780   _EGLSync *s = _eglLookupSync(sync, disp);
1781   _EGLDriver *drv;
1782   EGLBoolean ret;
1783
1784   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1785   assert(disp->Extensions.KHR_reusable_sync ||
1786          disp->Extensions.KHR_fence_sync);
1787   ret = drv->API.GetSyncAttribKHR(drv, disp, s, attribute, value);
1788
1789   RETURN_EGL_EVAL(disp, ret);
1790}
1791
1792
1793#ifdef EGL_NOK_swap_region
1794
1795EGLBoolean EGLAPIENTRY
1796eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface,
1797			EGLint numRects, const EGLint *rects)
1798{
1799   _EGLContext *ctx = _eglGetCurrentContext();
1800   _EGLDisplay *disp = _eglLockDisplay(dpy);
1801   _EGLSurface *surf = _eglLookupSurface(surface, disp);
1802   _EGLDriver *drv;
1803   EGLBoolean ret;
1804
1805   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1806
1807   if (!disp->Extensions.NOK_swap_region)
1808      RETURN_EGL_EVAL(disp, EGL_FALSE);
1809
1810   /* surface must be bound to current context in EGL 1.4 */
1811   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1812       surf != ctx->DrawSurface)
1813      RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1814
1815   ret = drv->API.SwapBuffersRegionNOK(drv, disp, surf, numRects, rects);
1816
1817   RETURN_EGL_EVAL(disp, ret);
1818}
1819
1820#endif /* EGL_NOK_swap_region */
1821
1822
1823#ifdef EGL_MESA_drm_image
1824
1825EGLImageKHR EGLAPIENTRY
1826eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list)
1827{
1828   _EGLDisplay *disp = _eglLockDisplay(dpy);
1829   _EGLDriver *drv;
1830   _EGLImage *img;
1831   EGLImageKHR ret;
1832
1833   _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
1834   if (!disp->Extensions.MESA_drm_image)
1835      RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
1836
1837   img = drv->API.CreateDRMImageMESA(drv, disp, attr_list);
1838   ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
1839
1840   RETURN_EGL_EVAL(disp, ret);
1841}
1842
1843EGLBoolean EGLAPIENTRY
1844eglExportDRMImageMESA(EGLDisplay dpy, EGLImageKHR image,
1845		      EGLint *name, EGLint *handle, EGLint *stride)
1846{
1847   _EGLDisplay *disp = _eglLockDisplay(dpy);
1848   _EGLImage *img = _eglLookupImage(image, disp);
1849   _EGLDriver *drv;
1850   EGLBoolean ret;
1851
1852   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1853   assert(disp->Extensions.MESA_drm_image);
1854
1855   if (!img)
1856      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1857
1858   ret = drv->API.ExportDRMImageMESA(drv, disp, img, name, handle, stride);
1859
1860   RETURN_EGL_EVAL(disp, ret);
1861}
1862
1863#endif
1864
1865#ifdef EGL_WL_bind_wayland_display
1866struct wl_display;
1867
1868EGLBoolean EGLAPIENTRY
1869eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
1870{
1871   _EGLDisplay *disp = _eglLockDisplay(dpy);
1872   _EGLDriver *drv;
1873   EGLBoolean ret;
1874
1875   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1876   assert(disp->Extensions.WL_bind_wayland_display);
1877
1878   if (!display)
1879      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1880
1881   ret = drv->API.BindWaylandDisplayWL(drv, disp, display);
1882
1883   RETURN_EGL_EVAL(disp, ret);
1884}
1885
1886EGLBoolean EGLAPIENTRY
1887eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
1888{
1889   _EGLDisplay *disp = _eglLockDisplay(dpy);
1890   _EGLDriver *drv;
1891   EGLBoolean ret;
1892
1893   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1894   assert(disp->Extensions.WL_bind_wayland_display);
1895
1896   if (!display)
1897      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1898
1899   ret = drv->API.UnbindWaylandDisplayWL(drv, disp, display);
1900
1901   RETURN_EGL_EVAL(disp, ret);
1902}
1903
1904EGLBoolean EGLAPIENTRY
1905eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer,
1906                        EGLint attribute, EGLint *value)
1907{
1908   _EGLDisplay *disp = _eglLockDisplay(dpy);
1909   _EGLDriver *drv;
1910   EGLBoolean ret;
1911
1912   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1913   assert(disp->Extensions.WL_bind_wayland_display);
1914
1915   if (!buffer)
1916      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1917
1918   ret = drv->API.QueryWaylandBufferWL(drv, disp, buffer, attribute, value);
1919
1920   RETURN_EGL_EVAL(disp, ret);
1921}
1922#endif
1923
1924#ifdef EGL_WL_create_wayland_buffer_from_image
1925struct wl_buffer * EGLAPIENTRY
1926eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImageKHR image)
1927{
1928   _EGLDisplay *disp = _eglLockDisplay(dpy);
1929   _EGLImage *img;
1930   _EGLDriver *drv;
1931   struct wl_buffer *ret;
1932
1933   _EGL_CHECK_DISPLAY(disp, NULL, drv);
1934   assert(disp->Extensions.WL_create_wayland_buffer_from_image);
1935
1936   img = _eglLookupImage(image, disp);
1937
1938   if (!img)
1939      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL);
1940
1941   ret = drv->API.CreateWaylandBufferFromImageWL(drv, disp, img);
1942
1943   RETURN_EGL_EVAL(disp, ret);
1944}
1945#endif
1946
1947EGLBoolean EGLAPIENTRY
1948eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface,
1949                   EGLint x, EGLint y, EGLint width, EGLint height)
1950{
1951   _EGLDisplay *disp = _eglLockDisplay(dpy);
1952   _EGLSurface *surf = _eglLookupSurface(surface, disp);
1953   _EGLDriver *drv;
1954   EGLBoolean ret;
1955
1956   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1957
1958   if (!disp->Extensions.NV_post_sub_buffer)
1959      RETURN_EGL_EVAL(disp, EGL_FALSE);
1960
1961   ret = drv->API.PostSubBufferNV(drv, disp, surf, x, y, width, height);
1962
1963   RETURN_EGL_EVAL(disp, ret);
1964}
1965
1966EGLBoolean EGLAPIENTRY
1967eglGetSyncValuesCHROMIUM(EGLDisplay display, EGLSurface surface,
1968                         EGLuint64KHR *ust, EGLuint64KHR *msc,
1969                         EGLuint64KHR *sbc)
1970{
1971   _EGLDisplay *disp = _eglLockDisplay(display);
1972   _EGLSurface *surf = _eglLookupSurface(surface, disp);
1973   _EGLDriver *drv;
1974   EGLBoolean ret;
1975
1976   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1977   if (!disp->Extensions.CHROMIUM_sync_control)
1978      RETURN_EGL_EVAL(disp, EGL_FALSE);
1979
1980   if (!ust || !msc || !sbc)
1981      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1982
1983   ret = drv->API.GetSyncValuesCHROMIUM(disp, surf, ust, msc, sbc);
1984
1985   RETURN_EGL_EVAL(disp, ret);
1986}
1987
1988#ifdef EGL_MESA_image_dma_buf_export
1989EGLBoolean EGLAPIENTRY
1990eglExportDMABUFImageQueryMESA(EGLDisplay dpy, EGLImageKHR image,
1991                              EGLint *fourcc, EGLint *nplanes,
1992                              EGLuint64MESA *modifiers)
1993{
1994   _EGLDisplay *disp = _eglLockDisplay(dpy);
1995   _EGLImage *img = _eglLookupImage(image, disp);
1996   _EGLDriver *drv;
1997   EGLBoolean ret;
1998
1999   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2000   assert(disp->Extensions.MESA_image_dma_buf_export);
2001
2002   if (!img)
2003      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2004
2005   ret = drv->API.ExportDMABUFImageQueryMESA(drv, disp, img, fourcc, nplanes,
2006                                             modifiers);
2007
2008   RETURN_EGL_EVAL(disp, ret);
2009}
2010
2011EGLBoolean EGLAPIENTRY
2012eglExportDMABUFImageMESA(EGLDisplay dpy, EGLImageKHR image,
2013                         int *fds, EGLint *strides, EGLint *offsets)
2014{
2015   _EGLDisplay *disp = _eglLockDisplay(dpy);
2016   _EGLImage *img = _eglLookupImage(image, disp);
2017   _EGLDriver *drv;
2018   EGLBoolean ret;
2019
2020   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2021   assert(disp->Extensions.MESA_image_dma_buf_export);
2022
2023   if (!img)
2024      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2025
2026   ret = drv->API.ExportDMABUFImageMESA(drv, disp, img, fds, strides, offsets);
2027
2028   RETURN_EGL_EVAL(disp, ret);
2029}
2030#endif
2031