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