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