1848b8605Smrg/**************************************************************************
2848b8605Smrg *
3848b8605Smrg * Copyright 2008 VMware, Inc.
4848b8605Smrg * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
5848b8605Smrg * Copyright 2010-2011 LunarG, Inc.
6848b8605Smrg * All Rights Reserved.
7848b8605Smrg *
8848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
9848b8605Smrg * copy of this software and associated documentation files (the
10848b8605Smrg * "Software"), to deal in the Software without restriction, including
11848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish,
12848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to
13848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to
14848b8605Smrg * the following conditions:
15848b8605Smrg *
16848b8605Smrg * The above copyright notice and this permission notice (including the
17848b8605Smrg * next paragraph) shall be included in all copies or substantial portions
18848b8605Smrg * of the Software.
19848b8605Smrg *
20848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24848b8605Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25848b8605Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26848b8605Smrg * DEALINGS IN THE SOFTWARE.
27848b8605Smrg *
28848b8605Smrg **************************************************************************/
29848b8605Smrg
30848b8605Smrg
31848b8605Smrg/**
32848b8605Smrg * Public EGL API entrypoints
33848b8605Smrg *
34848b8605Smrg * Generally, we use the EGLDisplay parameter as a key to lookup the
35848b8605Smrg * appropriate device driver handle, then jump though the driver's
36848b8605Smrg * dispatch table to handle the function.
37848b8605Smrg *
38848b8605Smrg * That allows us the option of supporting multiple, simultaneous,
39848b8605Smrg * heterogeneous hardware devices in the future.
40848b8605Smrg *
41848b8605Smrg * The EGLDisplay, EGLConfig, EGLContext and EGLSurface types are
42848b8605Smrg * opaque handles. Internal objects are linked to a display to
43848b8605Smrg * create the handles.
44848b8605Smrg *
45848b8605Smrg * For each public API entry point, the opaque handles are looked up
46848b8605Smrg * before being dispatched to the drivers.  When it fails to look up
47848b8605Smrg * a handle, one of
48848b8605Smrg *
49848b8605Smrg * EGL_BAD_DISPLAY
50848b8605Smrg * EGL_BAD_CONFIG
51848b8605Smrg * EGL_BAD_CONTEXT
52848b8605Smrg * EGL_BAD_SURFACE
53848b8605Smrg * EGL_BAD_SCREEN_MESA
54848b8605Smrg * EGL_BAD_MODE_MESA
55848b8605Smrg *
56848b8605Smrg * is generated and the driver function is not called. An
57848b8605Smrg * uninitialized EGLDisplay has no driver associated with it. When
58848b8605Smrg * such display is detected,
59848b8605Smrg *
60848b8605Smrg * EGL_NOT_INITIALIZED
61848b8605Smrg *
62848b8605Smrg * is generated.
63848b8605Smrg *
64848b8605Smrg * Some of the entry points use current display, context, or surface
65848b8605Smrg * implicitly.  For such entry points, the implicit objects are also
66848b8605Smrg * checked before calling the driver function.  Other than the
67848b8605Smrg * errors listed above,
68848b8605Smrg *
69848b8605Smrg * EGL_BAD_CURRENT_SURFACE
70848b8605Smrg *
71848b8605Smrg * may also be generated.
72848b8605Smrg *
73848b8605Smrg * Notes on naming conventions:
74848b8605Smrg *
75848b8605Smrg * eglFooBar    - public EGL function
76848b8605Smrg * EGL_FOO_BAR  - public EGL token
77848b8605Smrg * EGLDatatype  - public EGL datatype
78848b8605Smrg *
79848b8605Smrg * _eglFooBar   - private EGL function
80848b8605Smrg * _EGLDatatype - private EGL datatype, typedef'd struct
81848b8605Smrg * _egl_struct  - private EGL struct, non-typedef'd
82848b8605Smrg *
83848b8605Smrg */
84848b8605Smrg
85848b8605Smrg
86b8e80941Smrg#ifdef USE_LIBGLVND
87b8e80941Smrg#define EGLAPI
88b8e80941Smrg#undef PUBLIC
89b8e80941Smrg#define PUBLIC
90b8e80941Smrg#endif
91b8e80941Smrg
92848b8605Smrg#include <stdio.h>
93848b8605Smrg#include <stdlib.h>
94848b8605Smrg#include <string.h>
95b8e80941Smrg#include "c99_compat.h"
96b8e80941Smrg#include "c11/threads.h"
97b8e80941Smrg#include "util/macros.h"
98848b8605Smrg
99b8e80941Smrg#include "eglapi.h"
100b8e80941Smrg#include "egldefines.h"
101848b8605Smrg#include "eglglobals.h"
102848b8605Smrg#include "eglcontext.h"
103848b8605Smrg#include "egldisplay.h"
104848b8605Smrg#include "egltypedefs.h"
105848b8605Smrg#include "eglcurrent.h"
106b8e80941Smrg#include "egldevice.h"
107848b8605Smrg#include "egldriver.h"
108848b8605Smrg#include "eglsurface.h"
109848b8605Smrg#include "eglconfig.h"
110848b8605Smrg#include "eglimage.h"
111848b8605Smrg#include "eglsync.h"
112848b8605Smrg
113b8e80941Smrg#include "GL/mesa_glinterop.h"
114848b8605Smrg
115848b8605Smrg/**
116848b8605Smrg * Macros to help return an API entrypoint.
117848b8605Smrg *
118848b8605Smrg * These macros will unlock the display and record the error code.
119848b8605Smrg */
120848b8605Smrg#define RETURN_EGL_ERROR(disp, err, ret)        \
121848b8605Smrg   do {                                         \
122848b8605Smrg      if (disp)                                 \
123848b8605Smrg         _eglUnlockDisplay(disp);               \
124848b8605Smrg      /* EGL error codes are non-zero */        \
125848b8605Smrg      if (err)                                  \
126b8e80941Smrg         _eglError(err, __func__);              \
127848b8605Smrg      return ret;                               \
128848b8605Smrg   } while (0)
129848b8605Smrg
130848b8605Smrg#define RETURN_EGL_SUCCESS(disp, ret) \
131848b8605Smrg   RETURN_EGL_ERROR(disp, EGL_SUCCESS, ret)
132848b8605Smrg
133848b8605Smrg/* record EGL_SUCCESS only when ret evaluates to true */
134848b8605Smrg#define RETURN_EGL_EVAL(disp, ret) \
135848b8605Smrg   RETURN_EGL_ERROR(disp, (ret) ? EGL_SUCCESS : 0, ret)
136848b8605Smrg
137848b8605Smrg
138848b8605Smrg/*
139848b8605Smrg * A bunch of macros and checks to simplify error checking.
140848b8605Smrg */
141848b8605Smrg
142848b8605Smrg#define _EGL_CHECK_DISPLAY(disp, ret, drv)         \
143848b8605Smrg   do {                                            \
144b8e80941Smrg      drv = _eglCheckDisplay(disp, __func__);      \
145848b8605Smrg      if (!drv)                                    \
146848b8605Smrg         RETURN_EGL_ERROR(disp, 0, ret);           \
147848b8605Smrg   } while (0)
148848b8605Smrg
149848b8605Smrg#define _EGL_CHECK_OBJECT(disp, type, obj, ret, drv)      \
150848b8605Smrg   do {                                                   \
151b8e80941Smrg      drv = _eglCheck ## type(disp, obj, __func__);       \
152848b8605Smrg      if (!drv)                                           \
153848b8605Smrg         RETURN_EGL_ERROR(disp, 0, ret);                  \
154848b8605Smrg   } while (0)
155848b8605Smrg
156848b8605Smrg#define _EGL_CHECK_SURFACE(disp, surf, ret, drv) \
157848b8605Smrg   _EGL_CHECK_OBJECT(disp, Surface, surf, ret, drv)
158848b8605Smrg
159848b8605Smrg#define _EGL_CHECK_CONTEXT(disp, context, ret, drv) \
160848b8605Smrg   _EGL_CHECK_OBJECT(disp, Context, context, ret, drv)
161848b8605Smrg
162848b8605Smrg#define _EGL_CHECK_CONFIG(disp, conf, ret, drv) \
163848b8605Smrg   _EGL_CHECK_OBJECT(disp, Config, conf, ret, drv)
164848b8605Smrg
165848b8605Smrg#define _EGL_CHECK_SYNC(disp, s, ret, drv) \
166848b8605Smrg   _EGL_CHECK_OBJECT(disp, Sync, s, ret, drv)
167848b8605Smrg
168848b8605Smrg
169b8e80941Smrgstruct _egl_entrypoint {
170b8e80941Smrg   const char *name;
171b8e80941Smrg   _EGLProc function;
172b8e80941Smrg};
173b8e80941Smrg
174b8e80941Smrg
175b8e80941Smrgstatic inline _EGLDriver *
176848b8605Smrg_eglCheckDisplay(_EGLDisplay *disp, const char *msg)
177848b8605Smrg{
178848b8605Smrg   if (!disp) {
179848b8605Smrg      _eglError(EGL_BAD_DISPLAY, msg);
180848b8605Smrg      return NULL;
181848b8605Smrg   }
182848b8605Smrg   if (!disp->Initialized) {
183848b8605Smrg      _eglError(EGL_NOT_INITIALIZED, msg);
184848b8605Smrg      return NULL;
185848b8605Smrg   }
186848b8605Smrg   return disp->Driver;
187848b8605Smrg}
188848b8605Smrg
189848b8605Smrg
190b8e80941Smrgstatic inline _EGLDriver *
191848b8605Smrg_eglCheckSurface(_EGLDisplay *disp, _EGLSurface *surf, const char *msg)
192848b8605Smrg{
193848b8605Smrg   _EGLDriver *drv = _eglCheckDisplay(disp, msg);
194848b8605Smrg   if (!drv)
195848b8605Smrg      return NULL;
196848b8605Smrg   if (!surf) {
197848b8605Smrg      _eglError(EGL_BAD_SURFACE, msg);
198848b8605Smrg      return NULL;
199848b8605Smrg   }
200848b8605Smrg   return drv;
201848b8605Smrg}
202848b8605Smrg
203848b8605Smrg
204b8e80941Smrgstatic inline _EGLDriver *
205848b8605Smrg_eglCheckContext(_EGLDisplay *disp, _EGLContext *context, const char *msg)
206848b8605Smrg{
207848b8605Smrg   _EGLDriver *drv = _eglCheckDisplay(disp, msg);
208848b8605Smrg   if (!drv)
209848b8605Smrg      return NULL;
210848b8605Smrg   if (!context) {
211848b8605Smrg      _eglError(EGL_BAD_CONTEXT, msg);
212848b8605Smrg      return NULL;
213848b8605Smrg   }
214848b8605Smrg   return drv;
215848b8605Smrg}
216848b8605Smrg
217848b8605Smrg
218b8e80941Smrgstatic inline _EGLDriver *
219848b8605Smrg_eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg)
220848b8605Smrg{
221848b8605Smrg   _EGLDriver *drv = _eglCheckDisplay(disp, msg);
222848b8605Smrg   if (!drv)
223848b8605Smrg      return NULL;
224848b8605Smrg   if (!conf) {
225848b8605Smrg      _eglError(EGL_BAD_CONFIG, msg);
226848b8605Smrg      return NULL;
227848b8605Smrg   }
228848b8605Smrg   return drv;
229848b8605Smrg}
230848b8605Smrg
231848b8605Smrg
232b8e80941Smrgstatic inline _EGLDriver *
233848b8605Smrg_eglCheckSync(_EGLDisplay *disp, _EGLSync *s, const char *msg)
234848b8605Smrg{
235848b8605Smrg   _EGLDriver *drv = _eglCheckDisplay(disp, msg);
236848b8605Smrg   if (!drv)
237848b8605Smrg      return NULL;
238848b8605Smrg   if (!s) {
239848b8605Smrg      _eglError(EGL_BAD_PARAMETER, msg);
240848b8605Smrg      return NULL;
241848b8605Smrg   }
242848b8605Smrg   return drv;
243848b8605Smrg}
244848b8605Smrg
245848b8605Smrg
246b8e80941Smrg/**
247b8e80941Smrg * Lookup and lock a display.
248b8e80941Smrg */
249b8e80941Smrgstatic inline _EGLDisplay *
250b8e80941Smrg_eglLockDisplay(EGLDisplay dpy)
251848b8605Smrg{
252b8e80941Smrg   _EGLDisplay *disp = _eglLookupDisplay(dpy);
253b8e80941Smrg   if (disp)
254b8e80941Smrg      mtx_lock(&disp->Mutex);
255b8e80941Smrg   return disp;
256848b8605Smrg}
257848b8605Smrg
258848b8605Smrg
259b8e80941Smrg/**
260b8e80941Smrg * Unlock a display.
261b8e80941Smrg */
262b8e80941Smrgstatic inline void
263b8e80941Smrg_eglUnlockDisplay(_EGLDisplay *disp)
264848b8605Smrg{
265b8e80941Smrg   mtx_unlock(&disp->Mutex);
266848b8605Smrg}
267848b8605Smrg
268b8e80941Smrgstatic EGLBoolean
269b8e80941Smrg_eglSetFuncName(const char *funcName, _EGLDisplay *disp, EGLenum objectType, _EGLResource *object)
270b8e80941Smrg{
271b8e80941Smrg   _EGLThreadInfo *thr = _eglGetCurrentThread();
272b8e80941Smrg   if (!_eglIsCurrentThreadDummy()) {
273b8e80941Smrg      thr->CurrentFuncName = funcName;
274b8e80941Smrg      thr->CurrentObjectLabel = NULL;
275b8e80941Smrg
276b8e80941Smrg      if (objectType == EGL_OBJECT_THREAD_KHR)
277b8e80941Smrg         thr->CurrentObjectLabel = thr->Label;
278b8e80941Smrg      else if (objectType == EGL_OBJECT_DISPLAY_KHR && disp)
279b8e80941Smrg         thr->CurrentObjectLabel = disp->Label;
280b8e80941Smrg      else if (object)
281b8e80941Smrg         thr->CurrentObjectLabel = object->Label;
282b8e80941Smrg
283b8e80941Smrg      return EGL_TRUE;
284b8e80941Smrg   }
285848b8605Smrg
286b8e80941Smrg   _eglDebugReport(EGL_BAD_ALLOC, funcName, EGL_DEBUG_MSG_CRITICAL_KHR, NULL);
287b8e80941Smrg   return EGL_FALSE;
288b8e80941Smrg}
289848b8605Smrg
290b8e80941Smrg#define _EGL_FUNC_START(disp, objectType, object, ret) \
291b8e80941Smrg   do { \
292b8e80941Smrg      if (!_eglSetFuncName(__func__, disp, objectType, (_EGLResource *) object)) { \
293b8e80941Smrg         if (disp)                                 \
294b8e80941Smrg            _eglUnlockDisplay(disp);               \
295b8e80941Smrg         return ret; \
296b8e80941Smrg      } \
297b8e80941Smrg   } while(0)
298848b8605Smrg
299848b8605Smrg/**
300b8e80941Smrg * Convert an attribute list from EGLint[] to EGLAttrib[].
301b8e80941Smrg *
302b8e80941Smrg * Return an EGL error code. The output parameter out_attrib_list is modified
303b8e80941Smrg * only on success.
304848b8605Smrg */
305b8e80941Smrgstatic EGLint
306b8e80941Smrg_eglConvertIntsToAttribs(const EGLint *int_list, EGLAttrib **out_attrib_list)
307848b8605Smrg{
308b8e80941Smrg   size_t len = 0;
309b8e80941Smrg   EGLAttrib *attrib_list;
310b8e80941Smrg
311b8e80941Smrg   if (int_list) {
312b8e80941Smrg      while (int_list[2*len] != EGL_NONE)
313b8e80941Smrg         ++len;
314b8e80941Smrg   }
315b8e80941Smrg
316b8e80941Smrg   if (len == 0) {
317b8e80941Smrg      *out_attrib_list = NULL;
318b8e80941Smrg      return EGL_SUCCESS;
319b8e80941Smrg   }
320b8e80941Smrg
321b8e80941Smrg   if (2*len + 1 > SIZE_MAX / sizeof(EGLAttrib))
322b8e80941Smrg      return EGL_BAD_ALLOC;
323b8e80941Smrg
324b8e80941Smrg   attrib_list = malloc((2*len + 1) * sizeof(EGLAttrib));
325b8e80941Smrg   if (!attrib_list)
326b8e80941Smrg      return EGL_BAD_ALLOC;
327b8e80941Smrg
328b8e80941Smrg   for (size_t i = 0; i < len; ++i) {
329b8e80941Smrg      attrib_list[2*i + 0] = int_list[2*i + 0];
330b8e80941Smrg      attrib_list[2*i + 1] = int_list[2*i + 1];
331b8e80941Smrg   }
332b8e80941Smrg
333b8e80941Smrg   attrib_list[2*len] = EGL_NONE;
334b8e80941Smrg
335b8e80941Smrg   *out_attrib_list = attrib_list;
336b8e80941Smrg   return EGL_SUCCESS;
337848b8605Smrg}
338848b8605Smrg
339848b8605Smrg
340b8e80941Smrgstatic EGLint *
341b8e80941Smrg_eglConvertAttribsToInt(const EGLAttrib *attr_list)
342848b8605Smrg{
343b8e80941Smrg   EGLint *int_attribs = NULL;
344b8e80941Smrg
345b8e80941Smrg   /* Convert attributes from EGLAttrib[] to EGLint[] */
346b8e80941Smrg   if (attr_list) {
347b8e80941Smrg      int i, size = 0;
348b8e80941Smrg
349b8e80941Smrg      while (attr_list[size] != EGL_NONE)
350b8e80941Smrg         size += 2;
351b8e80941Smrg
352b8e80941Smrg      size += 1; /* add space for EGL_NONE */
353b8e80941Smrg
354b8e80941Smrg      int_attribs = calloc(size, sizeof(int_attribs[0]));
355b8e80941Smrg      if (!int_attribs)
356b8e80941Smrg         return NULL;
357b8e80941Smrg
358b8e80941Smrg      for (i = 0; i < size; i++)
359b8e80941Smrg         int_attribs[i] = attr_list[i];
360b8e80941Smrg   }
361b8e80941Smrg   return int_attribs;
362848b8605Smrg}
363848b8605Smrg
364848b8605Smrg
365848b8605Smrg/**
366848b8605Smrg * This is typically the first EGL function that an application calls.
367848b8605Smrg * It associates a private _EGLDisplay object to the native display.
368848b8605Smrg */
369848b8605SmrgEGLDisplay EGLAPIENTRY
370848b8605SmrgeglGetDisplay(EGLNativeDisplayType nativeDisplay)
371848b8605Smrg{
372848b8605Smrg   _EGLPlatformType plat;
373b8e80941Smrg   _EGLDisplay *disp;
374848b8605Smrg   void *native_display_ptr;
375848b8605Smrg
376b8e80941Smrg   _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY);
377b8e80941Smrg
378848b8605Smrg   STATIC_ASSERT(sizeof(void*) == sizeof(nativeDisplay));
379848b8605Smrg   native_display_ptr = (void*) nativeDisplay;
380848b8605Smrg
381848b8605Smrg   plat = _eglGetNativePlatform(native_display_ptr);
382b8e80941Smrg   disp = _eglFindDisplay(plat, native_display_ptr);
383b8e80941Smrg   return _eglGetDisplayHandle(disp);
384848b8605Smrg}
385848b8605Smrg
386b8e80941Smrgstatic EGLDisplay
387b8e80941Smrg_eglGetPlatformDisplayCommon(EGLenum platform, void *native_display,
388b8e80941Smrg                             const EGLAttrib *attrib_list)
389848b8605Smrg{
390b8e80941Smrg   _EGLDisplay *disp;
391848b8605Smrg
392848b8605Smrg   switch (platform) {
393848b8605Smrg#ifdef HAVE_X11_PLATFORM
394848b8605Smrg   case EGL_PLATFORM_X11_EXT:
395b8e80941Smrg      disp = _eglGetX11Display((Display*) native_display, attrib_list);
396848b8605Smrg      break;
397848b8605Smrg#endif
398848b8605Smrg#ifdef HAVE_DRM_PLATFORM
399848b8605Smrg   case EGL_PLATFORM_GBM_MESA:
400b8e80941Smrg      disp = _eglGetGbmDisplay((struct gbm_device*) native_display,
401848b8605Smrg                              attrib_list);
402848b8605Smrg      break;
403848b8605Smrg#endif
404848b8605Smrg#ifdef HAVE_WAYLAND_PLATFORM
405848b8605Smrg   case EGL_PLATFORM_WAYLAND_EXT:
406b8e80941Smrg      disp = _eglGetWaylandDisplay((struct wl_display*) native_display,
407848b8605Smrg                                  attrib_list);
408848b8605Smrg      break;
409b8e80941Smrg#endif
410b8e80941Smrg#ifdef HAVE_SURFACELESS_PLATFORM
411b8e80941Smrg   case EGL_PLATFORM_SURFACELESS_MESA:
412b8e80941Smrg      disp = _eglGetSurfacelessDisplay(native_display, attrib_list);
413b8e80941Smrg      break;
414848b8605Smrg#endif
415848b8605Smrg   default:
416848b8605Smrg      RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, NULL);
417848b8605Smrg   }
418848b8605Smrg
419b8e80941Smrg   return _eglGetDisplayHandle(disp);
420b8e80941Smrg}
421b8e80941Smrg
422b8e80941Smrgstatic EGLDisplay EGLAPIENTRY
423b8e80941SmrgeglGetPlatformDisplayEXT(EGLenum platform, void *native_display,
424b8e80941Smrg                         const EGLint *int_attribs)
425b8e80941Smrg{
426b8e80941Smrg   EGLAttrib *attrib_list;
427b8e80941Smrg   EGLDisplay disp;
428b8e80941Smrg
429b8e80941Smrg   _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY);
430b8e80941Smrg
431b8e80941Smrg   if (_eglConvertIntsToAttribs(int_attribs, &attrib_list) != EGL_SUCCESS)
432b8e80941Smrg      RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, NULL);
433b8e80941Smrg
434b8e80941Smrg   disp = _eglGetPlatformDisplayCommon(platform, native_display, attrib_list);
435b8e80941Smrg   free(attrib_list);
436b8e80941Smrg   return disp;
437b8e80941Smrg}
438b8e80941Smrg
439b8e80941SmrgEGLDisplay EGLAPIENTRY
440b8e80941SmrgeglGetPlatformDisplay(EGLenum platform, void *native_display,
441b8e80941Smrg                      const EGLAttrib *attrib_list)
442b8e80941Smrg{
443b8e80941Smrg   _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY);
444b8e80941Smrg   return _eglGetPlatformDisplayCommon(platform, native_display, attrib_list);
445b8e80941Smrg}
446b8e80941Smrg
447b8e80941Smrg/**
448b8e80941Smrg * Copy the extension into the string and update the string pointer.
449b8e80941Smrg */
450b8e80941Smrgstatic EGLint
451b8e80941Smrg_eglAppendExtension(char **str, const char *ext)
452b8e80941Smrg{
453b8e80941Smrg   char *s = *str;
454b8e80941Smrg   size_t len = strlen(ext);
455b8e80941Smrg
456b8e80941Smrg   if (s) {
457b8e80941Smrg      memcpy(s, ext, len);
458b8e80941Smrg      s[len++] = ' ';
459b8e80941Smrg      s[len] = '\0';
460b8e80941Smrg
461b8e80941Smrg      *str += len;
462b8e80941Smrg   }
463b8e80941Smrg   else {
464b8e80941Smrg      len++;
465b8e80941Smrg   }
466b8e80941Smrg
467b8e80941Smrg   return (EGLint) len;
468b8e80941Smrg}
469b8e80941Smrg
470b8e80941Smrg/**
471b8e80941Smrg * Examine the individual extension enable/disable flags and recompute
472b8e80941Smrg * the driver's Extensions string.
473b8e80941Smrg */
474b8e80941Smrgstatic void
475b8e80941Smrg_eglCreateExtensionsString(_EGLDisplay *disp)
476b8e80941Smrg{
477b8e80941Smrg#define _EGL_CHECK_EXTENSION(ext)                                          \
478b8e80941Smrg   do {                                                                    \
479b8e80941Smrg      if (disp->Extensions.ext) {                                           \
480b8e80941Smrg         _eglAppendExtension(&exts, "EGL_" #ext);                          \
481b8e80941Smrg         assert(exts <= disp->ExtensionsString + _EGL_MAX_EXTENSIONS_LEN);  \
482b8e80941Smrg      }                                                                    \
483b8e80941Smrg   } while (0)
484b8e80941Smrg
485b8e80941Smrg   char *exts = disp->ExtensionsString;
486b8e80941Smrg
487b8e80941Smrg   /* Please keep these sorted alphabetically. */
488b8e80941Smrg   _EGL_CHECK_EXTENSION(ANDROID_blob_cache);
489b8e80941Smrg   _EGL_CHECK_EXTENSION(ANDROID_framebuffer_target);
490b8e80941Smrg   _EGL_CHECK_EXTENSION(ANDROID_image_native_buffer);
491b8e80941Smrg   _EGL_CHECK_EXTENSION(ANDROID_native_fence_sync);
492b8e80941Smrg   _EGL_CHECK_EXTENSION(ANDROID_recordable);
493b8e80941Smrg
494b8e80941Smrg   _EGL_CHECK_EXTENSION(CHROMIUM_sync_control);
495b8e80941Smrg
496b8e80941Smrg   _EGL_CHECK_EXTENSION(EXT_buffer_age);
497b8e80941Smrg   _EGL_CHECK_EXTENSION(EXT_create_context_robustness);
498b8e80941Smrg   _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import);
499b8e80941Smrg   _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import_modifiers);
500b8e80941Smrg   _EGL_CHECK_EXTENSION(EXT_surface_CTA861_3_metadata);
501b8e80941Smrg   _EGL_CHECK_EXTENSION(EXT_surface_SMPTE2086_metadata);
502b8e80941Smrg   _EGL_CHECK_EXTENSION(EXT_swap_buffers_with_damage);
503b8e80941Smrg
504b8e80941Smrg   _EGL_CHECK_EXTENSION(IMG_context_priority);
505b8e80941Smrg
506b8e80941Smrg   _EGL_CHECK_EXTENSION(KHR_cl_event2);
507b8e80941Smrg   _EGL_CHECK_EXTENSION(KHR_config_attribs);
508b8e80941Smrg   _EGL_CHECK_EXTENSION(KHR_context_flush_control);
509b8e80941Smrg   _EGL_CHECK_EXTENSION(KHR_create_context);
510b8e80941Smrg   _EGL_CHECK_EXTENSION(KHR_create_context_no_error);
511b8e80941Smrg   _EGL_CHECK_EXTENSION(KHR_fence_sync);
512b8e80941Smrg   _EGL_CHECK_EXTENSION(KHR_get_all_proc_addresses);
513b8e80941Smrg   _EGL_CHECK_EXTENSION(KHR_gl_colorspace);
514b8e80941Smrg   _EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_image);
515b8e80941Smrg   _EGL_CHECK_EXTENSION(KHR_gl_texture_2D_image);
516b8e80941Smrg   _EGL_CHECK_EXTENSION(KHR_gl_texture_3D_image);
517b8e80941Smrg   _EGL_CHECK_EXTENSION(KHR_gl_texture_cubemap_image);
518b8e80941Smrg   if (disp->Extensions.KHR_image_base && disp->Extensions.KHR_image_pixmap)
519b8e80941Smrg      disp->Extensions.KHR_image = EGL_TRUE;
520b8e80941Smrg   _EGL_CHECK_EXTENSION(KHR_image);
521b8e80941Smrg   _EGL_CHECK_EXTENSION(KHR_image_base);
522b8e80941Smrg   _EGL_CHECK_EXTENSION(KHR_image_pixmap);
523b8e80941Smrg   _EGL_CHECK_EXTENSION(KHR_mutable_render_buffer);
524b8e80941Smrg   _EGL_CHECK_EXTENSION(KHR_no_config_context);
525b8e80941Smrg   _EGL_CHECK_EXTENSION(KHR_partial_update);
526b8e80941Smrg   _EGL_CHECK_EXTENSION(KHR_reusable_sync);
527b8e80941Smrg   _EGL_CHECK_EXTENSION(KHR_surfaceless_context);
528b8e80941Smrg   if (disp->Extensions.EXT_swap_buffers_with_damage)
529b8e80941Smrg      _eglAppendExtension(&exts, "EGL_KHR_swap_buffers_with_damage");
530b8e80941Smrg   _EGL_CHECK_EXTENSION(EXT_pixel_format_float);
531b8e80941Smrg   _EGL_CHECK_EXTENSION(KHR_wait_sync);
532b8e80941Smrg
533b8e80941Smrg   if (disp->Extensions.KHR_no_config_context)
534b8e80941Smrg      _eglAppendExtension(&exts, "EGL_MESA_configless_context");
535b8e80941Smrg   _EGL_CHECK_EXTENSION(MESA_drm_image);
536b8e80941Smrg   _EGL_CHECK_EXTENSION(MESA_image_dma_buf_export);
537b8e80941Smrg   _EGL_CHECK_EXTENSION(MESA_query_driver);
538b8e80941Smrg
539b8e80941Smrg   _EGL_CHECK_EXTENSION(NOK_swap_region);
540b8e80941Smrg   _EGL_CHECK_EXTENSION(NOK_texture_from_pixmap);
541b8e80941Smrg
542b8e80941Smrg   _EGL_CHECK_EXTENSION(NV_post_sub_buffer);
543b8e80941Smrg
544b8e80941Smrg   _EGL_CHECK_EXTENSION(WL_bind_wayland_display);
545b8e80941Smrg   _EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image);
546b8e80941Smrg
547b8e80941Smrg#undef _EGL_CHECK_EXTENSION
548b8e80941Smrg}
549b8e80941Smrg
550b8e80941Smrgstatic void
551b8e80941Smrg_eglCreateAPIsString(_EGLDisplay *disp)
552b8e80941Smrg{
553b8e80941Smrg#define addstr(str) \
554b8e80941Smrg   { \
555b8e80941Smrg      const size_t old_len = strlen(disp->ClientAPIsString); \
556b8e80941Smrg      const size_t add_len = sizeof(str); \
557b8e80941Smrg      const size_t max_len = sizeof(disp->ClientAPIsString) - 1; \
558b8e80941Smrg      if (old_len + add_len <= max_len) \
559b8e80941Smrg         strcat(disp->ClientAPIsString, str " "); \
560b8e80941Smrg      else \
561b8e80941Smrg         assert(!"disp->ClientAPIsString is not large enough"); \
562b8e80941Smrg   }
563b8e80941Smrg
564b8e80941Smrg   if (disp->ClientAPIs & EGL_OPENGL_BIT)
565b8e80941Smrg      addstr("OpenGL");
566b8e80941Smrg
567b8e80941Smrg   if (disp->ClientAPIs & EGL_OPENGL_ES_BIT ||
568b8e80941Smrg       disp->ClientAPIs & EGL_OPENGL_ES2_BIT ||
569b8e80941Smrg       disp->ClientAPIs & EGL_OPENGL_ES3_BIT_KHR) {
570b8e80941Smrg      addstr("OpenGL_ES");
571b8e80941Smrg   }
572b8e80941Smrg
573b8e80941Smrg   if (disp->ClientAPIs & EGL_OPENVG_BIT)
574b8e80941Smrg      addstr("OpenVG");
575b8e80941Smrg
576b8e80941Smrg#undef addstr
577b8e80941Smrg}
578b8e80941Smrg
579b8e80941Smrgstatic void
580b8e80941Smrg_eglComputeVersion(_EGLDisplay *disp)
581b8e80941Smrg{
582b8e80941Smrg   disp->Version = 14;
583b8e80941Smrg
584b8e80941Smrg   if (disp->Extensions.KHR_fence_sync &&
585b8e80941Smrg       disp->Extensions.KHR_cl_event2 &&
586b8e80941Smrg       disp->Extensions.KHR_wait_sync &&
587b8e80941Smrg       disp->Extensions.KHR_image_base &&
588b8e80941Smrg       disp->Extensions.KHR_gl_texture_2D_image &&
589b8e80941Smrg       disp->Extensions.KHR_gl_texture_3D_image &&
590b8e80941Smrg       disp->Extensions.KHR_gl_texture_cubemap_image &&
591b8e80941Smrg       disp->Extensions.KHR_gl_renderbuffer_image &&
592b8e80941Smrg       disp->Extensions.KHR_create_context &&
593b8e80941Smrg       disp->Extensions.EXT_create_context_robustness &&
594b8e80941Smrg       disp->Extensions.KHR_get_all_proc_addresses &&
595b8e80941Smrg       disp->Extensions.KHR_gl_colorspace &&
596b8e80941Smrg       disp->Extensions.KHR_surfaceless_context)
597b8e80941Smrg      disp->Version = 15;
598848b8605Smrg}
599848b8605Smrg
600848b8605Smrg/**
601848b8605Smrg * This is typically the second EGL function that an application calls.
602848b8605Smrg * Here we load/initialize the actual hardware driver.
603848b8605Smrg */
604848b8605SmrgEGLBoolean EGLAPIENTRY
605848b8605SmrgeglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
606848b8605Smrg{
607848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
608848b8605Smrg
609b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
610b8e80941Smrg
611848b8605Smrg   if (!disp)
612848b8605Smrg      RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
613848b8605Smrg
614848b8605Smrg   if (!disp->Initialized) {
615b8e80941Smrg      if (!_eglMatchDriver(disp))
616848b8605Smrg         RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
617848b8605Smrg
618848b8605Smrg      /* limit to APIs supported by core */
619848b8605Smrg      disp->ClientAPIs &= _EGL_API_ALL_BITS;
620b8e80941Smrg
621b8e80941Smrg      /* EGL_KHR_get_all_proc_addresses is a corner-case extension. The spec
622b8e80941Smrg       * classifies it as an EGL display extension, though conceptually it's an
623b8e80941Smrg       * EGL client extension.
624b8e80941Smrg       *
625b8e80941Smrg       * From the EGL_KHR_get_all_proc_addresses spec:
626b8e80941Smrg       *
627b8e80941Smrg       *    The EGL implementation must expose the name
628b8e80941Smrg       *    EGL_KHR_client_get_all_proc_addresses if and only if it exposes
629b8e80941Smrg       *    EGL_KHR_get_all_proc_addresses and supports
630b8e80941Smrg       *    EGL_EXT_client_extensions.
631b8e80941Smrg       *
632b8e80941Smrg       * Mesa unconditionally exposes both client extensions mentioned above,
633b8e80941Smrg       * so the spec requires that each EGLDisplay unconditionally expose
634b8e80941Smrg       * EGL_KHR_get_all_proc_addresses also.
635b8e80941Smrg       */
636b8e80941Smrg      disp->Extensions.KHR_get_all_proc_addresses = EGL_TRUE;
637b8e80941Smrg
638b8e80941Smrg      /* Extensions is used to provide EGL 1.3 functionality for 1.2 aware
639b8e80941Smrg       * programs. It is driver agnostic and handled in the main EGL code.
640b8e80941Smrg       */
641b8e80941Smrg      disp->Extensions.KHR_config_attribs = EGL_TRUE;
642b8e80941Smrg
643b8e80941Smrg      _eglComputeVersion(disp);
644b8e80941Smrg      _eglCreateExtensionsString(disp);
645b8e80941Smrg      _eglCreateAPIsString(disp);
646b8e80941Smrg      snprintf(disp->VersionString, sizeof(disp->VersionString),
647b8e80941Smrg               "%d.%d", disp->Version / 10, disp->Version % 10);
648848b8605Smrg   }
649848b8605Smrg
650848b8605Smrg   /* Update applications version of major and minor if not NULL */
651848b8605Smrg   if ((major != NULL) && (minor != NULL)) {
652b8e80941Smrg      *major = disp->Version / 10;
653b8e80941Smrg      *minor = disp->Version % 10;
654848b8605Smrg   }
655848b8605Smrg
656848b8605Smrg   RETURN_EGL_SUCCESS(disp, EGL_TRUE);
657848b8605Smrg}
658848b8605Smrg
659848b8605Smrg
660848b8605SmrgEGLBoolean EGLAPIENTRY
661848b8605SmrgeglTerminate(EGLDisplay dpy)
662848b8605Smrg{
663848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
664848b8605Smrg
665b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
666b8e80941Smrg
667848b8605Smrg   if (!disp)
668848b8605Smrg      RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
669848b8605Smrg
670848b8605Smrg   if (disp->Initialized) {
671848b8605Smrg      _EGLDriver *drv = disp->Driver;
672848b8605Smrg
673848b8605Smrg      drv->API.Terminate(drv, disp);
674848b8605Smrg      /* do not reset disp->Driver */
675b8e80941Smrg      disp->ClientAPIsString[0] = 0;
676848b8605Smrg      disp->Initialized = EGL_FALSE;
677b8e80941Smrg
678b8e80941Smrg      /* Reset blob cache funcs on terminate. */
679b8e80941Smrg      disp->BlobCacheSet = NULL;
680b8e80941Smrg      disp->BlobCacheGet = NULL;
681848b8605Smrg   }
682848b8605Smrg
683848b8605Smrg   RETURN_EGL_SUCCESS(disp, EGL_TRUE);
684848b8605Smrg}
685848b8605Smrg
686848b8605Smrg
687848b8605Smrgconst char * EGLAPIENTRY
688848b8605SmrgeglQueryString(EGLDisplay dpy, EGLint name)
689848b8605Smrg{
690848b8605Smrg   _EGLDisplay *disp;
691848b8605Smrg   _EGLDriver *drv;
692848b8605Smrg
693848b8605Smrg   if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) {
694b8e80941Smrg      const char *ret = _eglGetClientExtensionString();
695b8e80941Smrg      if (ret != NULL)
696b8e80941Smrg         RETURN_EGL_SUCCESS(NULL, ret);
697b8e80941Smrg      else
698b8e80941Smrg         RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, NULL);
699848b8605Smrg   }
700848b8605Smrg
701848b8605Smrg   disp = _eglLockDisplay(dpy);
702b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, NULL);
703848b8605Smrg   _EGL_CHECK_DISPLAY(disp, NULL, drv);
704848b8605Smrg
705b8e80941Smrg   switch (name) {
706b8e80941Smrg   case EGL_VENDOR:
707b8e80941Smrg      RETURN_EGL_SUCCESS(disp, _EGL_VENDOR_STRING);
708b8e80941Smrg   case EGL_VERSION:
709b8e80941Smrg      RETURN_EGL_SUCCESS(disp, disp->VersionString);
710b8e80941Smrg   case EGL_EXTENSIONS:
711b8e80941Smrg      RETURN_EGL_SUCCESS(disp, disp->ExtensionsString);
712b8e80941Smrg   case EGL_CLIENT_APIS:
713b8e80941Smrg      RETURN_EGL_SUCCESS(disp, disp->ClientAPIsString);
714b8e80941Smrg   default:
715b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL);
716b8e80941Smrg   }
717848b8605Smrg}
718848b8605Smrg
719848b8605Smrg
720848b8605SmrgEGLBoolean EGLAPIENTRY
721848b8605SmrgeglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
722848b8605Smrg              EGLint config_size, EGLint *num_config)
723848b8605Smrg{
724848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
725848b8605Smrg   _EGLDriver *drv;
726848b8605Smrg   EGLBoolean ret;
727848b8605Smrg
728b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
729b8e80941Smrg
730848b8605Smrg   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
731848b8605Smrg   ret = drv->API.GetConfigs(drv, disp, configs, config_size, num_config);
732848b8605Smrg
733848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
734848b8605Smrg}
735848b8605Smrg
736848b8605Smrg
737848b8605SmrgEGLBoolean EGLAPIENTRY
738848b8605SmrgeglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs,
739848b8605Smrg                EGLint config_size, EGLint *num_config)
740848b8605Smrg{
741848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
742848b8605Smrg   _EGLDriver *drv;
743848b8605Smrg   EGLBoolean ret;
744848b8605Smrg
745b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
746b8e80941Smrg
747848b8605Smrg   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
748848b8605Smrg   ret = drv->API.ChooseConfig(drv, disp, attrib_list, configs,
749b8e80941Smrg                               config_size, num_config);
750848b8605Smrg
751848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
752848b8605Smrg}
753848b8605Smrg
754848b8605Smrg
755848b8605SmrgEGLBoolean EGLAPIENTRY
756848b8605SmrgeglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
757848b8605Smrg                   EGLint attribute, EGLint *value)
758848b8605Smrg{
759848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
760848b8605Smrg   _EGLConfig *conf = _eglLookupConfig(config, disp);
761848b8605Smrg   _EGLDriver *drv;
762848b8605Smrg   EGLBoolean ret;
763848b8605Smrg
764b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
765b8e80941Smrg
766848b8605Smrg   _EGL_CHECK_CONFIG(disp, conf, EGL_FALSE, drv);
767848b8605Smrg   ret = drv->API.GetConfigAttrib(drv, disp, conf, attribute, value);
768848b8605Smrg
769848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
770848b8605Smrg}
771848b8605Smrg
772848b8605Smrg
773848b8605SmrgEGLContext EGLAPIENTRY
774848b8605SmrgeglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list,
775848b8605Smrg                 const EGLint *attrib_list)
776848b8605Smrg{
777848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
778848b8605Smrg   _EGLConfig *conf = _eglLookupConfig(config, disp);
779848b8605Smrg   _EGLContext *share = _eglLookupContext(share_list, disp);
780848b8605Smrg   _EGLDriver *drv;
781848b8605Smrg   _EGLContext *context;
782848b8605Smrg   EGLContext ret;
783848b8605Smrg
784b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_CONTEXT);
785b8e80941Smrg
786848b8605Smrg   _EGL_CHECK_DISPLAY(disp, EGL_NO_CONTEXT, drv);
787848b8605Smrg
788b8e80941Smrg   if (config != EGL_NO_CONFIG_KHR)
789b8e80941Smrg      _EGL_CHECK_CONFIG(disp, conf, EGL_NO_CONTEXT, drv);
790b8e80941Smrg   else if (!disp->Extensions.KHR_no_config_context)
791848b8605Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_CONFIG, EGL_NO_CONTEXT);
792848b8605Smrg
793848b8605Smrg   if (!share && share_list != EGL_NO_CONTEXT)
794848b8605Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
795848b8605Smrg
796848b8605Smrg   context = drv->API.CreateContext(drv, disp, conf, share, attrib_list);
797848b8605Smrg   ret = (context) ? _eglLinkContext(context) : EGL_NO_CONTEXT;
798848b8605Smrg
799848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
800848b8605Smrg}
801848b8605Smrg
802848b8605Smrg
803848b8605SmrgEGLBoolean EGLAPIENTRY
804848b8605SmrgeglDestroyContext(EGLDisplay dpy, EGLContext ctx)
805848b8605Smrg{
806848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
807848b8605Smrg   _EGLContext *context = _eglLookupContext(ctx, disp);
808848b8605Smrg   _EGLDriver *drv;
809848b8605Smrg   EGLBoolean ret;
810848b8605Smrg
811b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE);
812b8e80941Smrg
813848b8605Smrg   _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv);
814848b8605Smrg   _eglUnlinkContext(context);
815848b8605Smrg   ret = drv->API.DestroyContext(drv, disp, context);
816848b8605Smrg
817848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
818848b8605Smrg}
819848b8605Smrg
820848b8605Smrg
821848b8605SmrgEGLBoolean EGLAPIENTRY
822848b8605SmrgeglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
823848b8605Smrg               EGLContext ctx)
824848b8605Smrg{
825848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
826848b8605Smrg   _EGLContext *context = _eglLookupContext(ctx, disp);
827848b8605Smrg   _EGLSurface *draw_surf = _eglLookupSurface(draw, disp);
828848b8605Smrg   _EGLSurface *read_surf = _eglLookupSurface(read, disp);
829848b8605Smrg   _EGLDriver *drv;
830848b8605Smrg   EGLBoolean ret;
831848b8605Smrg
832b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE);
833b8e80941Smrg
834848b8605Smrg   if (!disp)
835848b8605Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
836848b8605Smrg   drv = disp->Driver;
837848b8605Smrg
838848b8605Smrg   /* display is allowed to be uninitialized under certain condition */
839848b8605Smrg   if (!disp->Initialized) {
840848b8605Smrg      if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE ||
841848b8605Smrg          ctx != EGL_NO_CONTEXT)
842848b8605Smrg         RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
843848b8605Smrg   }
844848b8605Smrg   if (!drv)
845848b8605Smrg      RETURN_EGL_SUCCESS(disp, EGL_TRUE);
846848b8605Smrg
847848b8605Smrg   if (!context && ctx != EGL_NO_CONTEXT)
848848b8605Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
849848b8605Smrg   if (!draw_surf || !read_surf) {
850848b8605Smrg      /* From the EGL 1.4 (20130211) spec:
851848b8605Smrg       *
852848b8605Smrg       *    To release the current context without assigning a new one, set ctx
853848b8605Smrg       *    to EGL_NO_CONTEXT and set draw and read to EGL_NO_SURFACE.
854848b8605Smrg       */
855848b8605Smrg      if (!disp->Extensions.KHR_surfaceless_context && ctx != EGL_NO_CONTEXT)
856848b8605Smrg         RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
857848b8605Smrg
858848b8605Smrg      if ((!draw_surf && draw != EGL_NO_SURFACE) ||
859848b8605Smrg          (!read_surf && read != EGL_NO_SURFACE))
860848b8605Smrg         RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
861848b8605Smrg      if (draw_surf || read_surf)
862848b8605Smrg         RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
863848b8605Smrg   }
864848b8605Smrg
865b8e80941Smrg   /*    If a native window underlying either draw or read is no longer valid,
866b8e80941Smrg    *    an EGL_BAD_NATIVE_WINDOW error is generated.
867b8e80941Smrg    */
868b8e80941Smrg   if (draw_surf && draw_surf->Lost)
869b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE);
870b8e80941Smrg   if (read_surf && read_surf->Lost)
871b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE);
872b8e80941Smrg
873848b8605Smrg   ret = drv->API.MakeCurrent(drv, disp, draw_surf, read_surf, context);
874848b8605Smrg
875848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
876848b8605Smrg}
877848b8605Smrg
878848b8605Smrg
879848b8605SmrgEGLBoolean EGLAPIENTRY
880848b8605SmrgeglQueryContext(EGLDisplay dpy, EGLContext ctx,
881848b8605Smrg                EGLint attribute, EGLint *value)
882848b8605Smrg{
883848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
884848b8605Smrg   _EGLContext *context = _eglLookupContext(ctx, disp);
885848b8605Smrg   _EGLDriver *drv;
886848b8605Smrg   EGLBoolean ret;
887848b8605Smrg
888b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE);
889b8e80941Smrg
890848b8605Smrg   _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv);
891848b8605Smrg   ret = drv->API.QueryContext(drv, disp, context, attribute, value);
892848b8605Smrg
893848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
894848b8605Smrg}
895848b8605Smrg
896848b8605Smrg
897848b8605Smrgstatic EGLSurface
898848b8605Smrg_eglCreateWindowSurfaceCommon(_EGLDisplay *disp, EGLConfig config,
899848b8605Smrg                              void *native_window, const EGLint *attrib_list)
900848b8605Smrg{
901848b8605Smrg   _EGLConfig *conf = _eglLookupConfig(config, disp);
902848b8605Smrg   _EGLDriver *drv;
903848b8605Smrg   _EGLSurface *surf;
904848b8605Smrg   EGLSurface ret;
905848b8605Smrg
906848b8605Smrg
907848b8605Smrg   if (native_window == NULL)
908848b8605Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
909848b8605Smrg
910b8e80941Smrg#ifdef HAVE_SURFACELESS_PLATFORM
911b8e80941Smrg   if (disp && disp->Platform == _EGL_PLATFORM_SURFACELESS) {
912b8e80941Smrg      /* From the EGL_MESA_platform_surfaceless spec (v1):
913b8e80941Smrg       *
914b8e80941Smrg       *    eglCreatePlatformWindowSurface fails when called with a <display>
915b8e80941Smrg       *    that belongs to the surfaceless platform. It returns
916b8e80941Smrg       *    EGL_NO_SURFACE and generates EGL_BAD_NATIVE_WINDOW. The
917b8e80941Smrg       *    justification for this unconditional failure is that the
918b8e80941Smrg       *    surfaceless platform has no native windows, and therefore the
919b8e80941Smrg       *    <native_window> parameter is always invalid.
920b8e80941Smrg       *
921b8e80941Smrg       * This check must occur before checking the EGLConfig, which emits
922b8e80941Smrg       * EGL_BAD_CONFIG.
923b8e80941Smrg       */
924b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
925b8e80941Smrg   }
926b8e80941Smrg#endif
927b8e80941Smrg
928b8e80941Smrg   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
929b8e80941Smrg
930b8e80941Smrg   if ((conf->SurfaceType & EGL_WINDOW_BIT) == 0)
931b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE);
932b8e80941Smrg
933848b8605Smrg   surf = drv->API.CreateWindowSurface(drv, disp, conf, native_window,
934848b8605Smrg                                       attrib_list);
935848b8605Smrg   ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
936848b8605Smrg
937848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
938848b8605Smrg}
939848b8605Smrg
940848b8605Smrg
941848b8605SmrgEGLSurface EGLAPIENTRY
942848b8605SmrgeglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
943848b8605Smrg                       EGLNativeWindowType window, const EGLint *attrib_list)
944848b8605Smrg{
945848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
946b8e80941Smrg
947b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
948848b8605Smrg   STATIC_ASSERT(sizeof(void*) == sizeof(window));
949848b8605Smrg   return _eglCreateWindowSurfaceCommon(disp, config, (void*) window,
950848b8605Smrg                                        attrib_list);
951848b8605Smrg}
952848b8605Smrg
953b8e80941Smrgstatic void *
954b8e80941Smrg_fixupNativeWindow(_EGLDisplay *disp, void *native_window)
955848b8605Smrg{
956848b8605Smrg#ifdef HAVE_X11_PLATFORM
957b8e80941Smrg   if (disp && disp->Platform == _EGL_PLATFORM_X11 && native_window != NULL) {
958848b8605Smrg      /* The `native_window` parameter for the X11 platform differs between
959848b8605Smrg       * eglCreateWindowSurface() and eglCreatePlatformPixmapSurfaceEXT(). In
960848b8605Smrg       * eglCreateWindowSurface(), the type of `native_window` is an Xlib
961848b8605Smrg       * `Window`. In eglCreatePlatformWindowSurfaceEXT(), the type is
962848b8605Smrg       * `Window*`.  Convert `Window*` to `Window` because that's what
963848b8605Smrg       * dri2_x11_create_window_surface() expects.
964848b8605Smrg       */
965b8e80941Smrg      return (void *)(* (Window*) native_window);
966848b8605Smrg   }
967848b8605Smrg#endif
968b8e80941Smrg   return native_window;
969b8e80941Smrg}
970b8e80941Smrg
971b8e80941Smrgstatic EGLSurface EGLAPIENTRY
972b8e80941SmrgeglCreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config,
973b8e80941Smrg                                  void *native_window,
974b8e80941Smrg                                  const EGLint *attrib_list)
975b8e80941Smrg{
976b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
977b8e80941Smrg
978b8e80941Smrg   native_window = _fixupNativeWindow(disp, native_window);
979848b8605Smrg
980b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
981848b8605Smrg   return _eglCreateWindowSurfaceCommon(disp, config, native_window,
982848b8605Smrg                                        attrib_list);
983848b8605Smrg}
984848b8605Smrg
985848b8605Smrg
986b8e80941SmrgEGLSurface EGLAPIENTRY
987b8e80941SmrgeglCreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config,
988b8e80941Smrg                               void *native_window,
989b8e80941Smrg                               const EGLAttrib *attrib_list)
990b8e80941Smrg{
991b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
992b8e80941Smrg   EGLSurface surface;
993b8e80941Smrg   EGLint *int_attribs;
994b8e80941Smrg
995b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
996b8e80941Smrg
997b8e80941Smrg   int_attribs = _eglConvertAttribsToInt(attrib_list);
998b8e80941Smrg   if (attrib_list && !int_attribs)
999b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
1000b8e80941Smrg
1001b8e80941Smrg   native_window = _fixupNativeWindow(disp, native_window);
1002b8e80941Smrg   surface = _eglCreateWindowSurfaceCommon(disp, config, native_window,
1003b8e80941Smrg                                           int_attribs);
1004b8e80941Smrg   free(int_attribs);
1005b8e80941Smrg   return surface;
1006b8e80941Smrg}
1007b8e80941Smrg
1008b8e80941Smrgstatic void *
1009b8e80941Smrg_fixupNativePixmap(_EGLDisplay *disp, void *native_pixmap)
1010b8e80941Smrg{
1011b8e80941Smrg#ifdef HAVE_X11_PLATFORM
1012b8e80941Smrg   /* The `native_pixmap` parameter for the X11 platform differs between
1013b8e80941Smrg    * eglCreatePixmapSurface() and eglCreatePlatformPixmapSurfaceEXT(). In
1014b8e80941Smrg    * eglCreatePixmapSurface(), the type of `native_pixmap` is an Xlib
1015b8e80941Smrg    * `Pixmap`. In eglCreatePlatformPixmapSurfaceEXT(), the type is
1016b8e80941Smrg    * `Pixmap*`.  Convert `Pixmap*` to `Pixmap` because that's what
1017b8e80941Smrg    * dri2_x11_create_pixmap_surface() expects.
1018b8e80941Smrg    */
1019b8e80941Smrg   if (disp && disp->Platform == _EGL_PLATFORM_X11 && native_pixmap != NULL)
1020b8e80941Smrg      return (void *)(* (Pixmap*) native_pixmap);
1021b8e80941Smrg#endif
1022b8e80941Smrg   return native_pixmap;
1023b8e80941Smrg}
1024b8e80941Smrg
1025848b8605Smrgstatic EGLSurface
1026848b8605Smrg_eglCreatePixmapSurfaceCommon(_EGLDisplay *disp, EGLConfig config,
1027848b8605Smrg                              void *native_pixmap, const EGLint *attrib_list)
1028848b8605Smrg{
1029848b8605Smrg   _EGLConfig *conf = _eglLookupConfig(config, disp);
1030848b8605Smrg   _EGLDriver *drv;
1031848b8605Smrg   _EGLSurface *surf;
1032848b8605Smrg   EGLSurface ret;
1033848b8605Smrg
1034b8e80941Smrg#if HAVE_SURFACELESS_PLATFORM
1035b8e80941Smrg   if (disp && disp->Platform == _EGL_PLATFORM_SURFACELESS) {
1036b8e80941Smrg      /* From the EGL_MESA_platform_surfaceless spec (v1):
1037b8e80941Smrg       *
1038b8e80941Smrg       *   [Like eglCreatePlatformWindowSurface,] eglCreatePlatformPixmapSurface
1039b8e80941Smrg       *   also fails when called with a <display> that belongs to the
1040b8e80941Smrg       *   surfaceless platform.  It returns EGL_NO_SURFACE and generates
1041b8e80941Smrg       *   EGL_BAD_NATIVE_PIXMAP.
1042b8e80941Smrg       *
1043b8e80941Smrg       * This check must occur before checking the EGLConfig, which emits
1044b8e80941Smrg       * EGL_BAD_CONFIG.
1045b8e80941Smrg       */
1046b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
1047b8e80941Smrg   }
1048b8e80941Smrg#endif
1049b8e80941Smrg
1050848b8605Smrg   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
1051b8e80941Smrg
1052b8e80941Smrg   if ((conf->SurfaceType & EGL_PIXMAP_BIT) == 0)
1053b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE);
1054b8e80941Smrg
1055b8e80941Smrg   if (native_pixmap == NULL)
1056b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
1057b8e80941Smrg
1058848b8605Smrg   surf = drv->API.CreatePixmapSurface(drv, disp, conf, native_pixmap,
1059848b8605Smrg                                       attrib_list);
1060848b8605Smrg   ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1061848b8605Smrg
1062848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
1063848b8605Smrg}
1064848b8605Smrg
1065848b8605Smrg
1066848b8605SmrgEGLSurface EGLAPIENTRY
1067848b8605SmrgeglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
1068848b8605Smrg                       EGLNativePixmapType pixmap, const EGLint *attrib_list)
1069848b8605Smrg{
1070848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1071b8e80941Smrg
1072b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1073848b8605Smrg   STATIC_ASSERT(sizeof(void*) == sizeof(pixmap));
1074848b8605Smrg   return _eglCreatePixmapSurfaceCommon(disp, config, (void*) pixmap,
1075b8e80941Smrg                                        attrib_list);
1076848b8605Smrg}
1077848b8605Smrg
1078b8e80941Smrgstatic EGLSurface EGLAPIENTRY
1079848b8605SmrgeglCreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config,
1080b8e80941Smrg                                  void *native_pixmap,
1081b8e80941Smrg                                  const EGLint *attrib_list)
1082848b8605Smrg{
1083848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1084848b8605Smrg
1085b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1086b8e80941Smrg   native_pixmap = _fixupNativePixmap(disp, native_pixmap);
1087848b8605Smrg   return _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap,
1088848b8605Smrg                                        attrib_list);
1089848b8605Smrg}
1090848b8605Smrg
1091848b8605Smrg
1092b8e80941SmrgEGLSurface EGLAPIENTRY
1093b8e80941SmrgeglCreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config,
1094b8e80941Smrg                               void *native_pixmap,
1095b8e80941Smrg                               const EGLAttrib *attrib_list)
1096b8e80941Smrg{
1097b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1098b8e80941Smrg   EGLSurface surface;
1099b8e80941Smrg   EGLint *int_attribs;
1100b8e80941Smrg
1101b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1102b8e80941Smrg
1103b8e80941Smrg   int_attribs = _eglConvertAttribsToInt(attrib_list);
1104b8e80941Smrg   if (attrib_list && !int_attribs)
1105b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
1106b8e80941Smrg
1107b8e80941Smrg   native_pixmap = _fixupNativePixmap(disp, native_pixmap);
1108b8e80941Smrg   surface = _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap,
1109b8e80941Smrg                                           int_attribs);
1110b8e80941Smrg   free(int_attribs);
1111b8e80941Smrg   return surface;
1112b8e80941Smrg}
1113b8e80941Smrg
1114b8e80941Smrg
1115848b8605SmrgEGLSurface EGLAPIENTRY
1116848b8605SmrgeglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
1117848b8605Smrg                        const EGLint *attrib_list)
1118848b8605Smrg{
1119848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1120848b8605Smrg   _EGLConfig *conf = _eglLookupConfig(config, disp);
1121848b8605Smrg   _EGLDriver *drv;
1122848b8605Smrg   _EGLSurface *surf;
1123848b8605Smrg   EGLSurface ret;
1124848b8605Smrg
1125b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1126848b8605Smrg   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
1127848b8605Smrg
1128b8e80941Smrg   if ((conf->SurfaceType & EGL_PBUFFER_BIT) == 0)
1129b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE);
1130b8e80941Smrg
1131848b8605Smrg   surf = drv->API.CreatePbufferSurface(drv, disp, conf, attrib_list);
1132848b8605Smrg   ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1133848b8605Smrg
1134848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
1135848b8605Smrg}
1136848b8605Smrg
1137848b8605Smrg
1138848b8605SmrgEGLBoolean EGLAPIENTRY
1139848b8605SmrgeglDestroySurface(EGLDisplay dpy, EGLSurface surface)
1140848b8605Smrg{
1141848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1142848b8605Smrg   _EGLSurface *surf = _eglLookupSurface(surface, disp);
1143848b8605Smrg   _EGLDriver *drv;
1144848b8605Smrg   EGLBoolean ret;
1145848b8605Smrg
1146b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1147848b8605Smrg   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1148848b8605Smrg   _eglUnlinkSurface(surf);
1149848b8605Smrg   ret = drv->API.DestroySurface(drv, disp, surf);
1150848b8605Smrg
1151848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
1152848b8605Smrg}
1153848b8605Smrg
1154848b8605SmrgEGLBoolean EGLAPIENTRY
1155848b8605SmrgeglQuerySurface(EGLDisplay dpy, EGLSurface surface,
1156848b8605Smrg                EGLint attribute, EGLint *value)
1157848b8605Smrg{
1158848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1159848b8605Smrg   _EGLSurface *surf = _eglLookupSurface(surface, disp);
1160848b8605Smrg   _EGLDriver *drv;
1161848b8605Smrg   EGLBoolean ret;
1162848b8605Smrg
1163b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1164848b8605Smrg   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1165848b8605Smrg   ret = drv->API.QuerySurface(drv, disp, surf, attribute, value);
1166848b8605Smrg
1167848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
1168848b8605Smrg}
1169848b8605Smrg
1170848b8605SmrgEGLBoolean EGLAPIENTRY
1171848b8605SmrgeglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
1172848b8605Smrg                 EGLint attribute, EGLint value)
1173848b8605Smrg{
1174848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1175848b8605Smrg   _EGLSurface *surf = _eglLookupSurface(surface, disp);
1176848b8605Smrg   _EGLDriver *drv;
1177848b8605Smrg   EGLBoolean ret;
1178848b8605Smrg
1179b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1180848b8605Smrg   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1181848b8605Smrg   ret = drv->API.SurfaceAttrib(drv, disp, surf, attribute, value);
1182848b8605Smrg
1183848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
1184848b8605Smrg}
1185848b8605Smrg
1186848b8605Smrg
1187848b8605SmrgEGLBoolean EGLAPIENTRY
1188848b8605SmrgeglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1189848b8605Smrg{
1190848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1191848b8605Smrg   _EGLSurface *surf = _eglLookupSurface(surface, disp);
1192848b8605Smrg   _EGLDriver *drv;
1193848b8605Smrg   EGLBoolean ret;
1194848b8605Smrg
1195b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1196848b8605Smrg   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1197848b8605Smrg   ret = drv->API.BindTexImage(drv, disp, surf, buffer);
1198848b8605Smrg
1199848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
1200848b8605Smrg}
1201848b8605Smrg
1202848b8605Smrg
1203848b8605SmrgEGLBoolean EGLAPIENTRY
1204848b8605SmrgeglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1205848b8605Smrg{
1206848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1207848b8605Smrg   _EGLSurface *surf = _eglLookupSurface(surface, disp);
1208848b8605Smrg   _EGLDriver *drv;
1209848b8605Smrg   EGLBoolean ret;
1210848b8605Smrg
1211b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1212848b8605Smrg   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1213848b8605Smrg   ret = drv->API.ReleaseTexImage(drv, disp, surf, buffer);
1214848b8605Smrg
1215848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
1216848b8605Smrg}
1217848b8605Smrg
1218848b8605Smrg
1219848b8605SmrgEGLBoolean EGLAPIENTRY
1220848b8605SmrgeglSwapInterval(EGLDisplay dpy, EGLint interval)
1221848b8605Smrg{
1222848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1223848b8605Smrg   _EGLContext *ctx = _eglGetCurrentContext();
1224b8e80941Smrg   _EGLSurface *surf = ctx ? ctx->DrawSurface : NULL;
1225848b8605Smrg   _EGLDriver *drv;
1226848b8605Smrg   EGLBoolean ret;
1227848b8605Smrg
1228b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1229848b8605Smrg   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1230848b8605Smrg
1231848b8605Smrg   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1232848b8605Smrg       ctx->Resource.Display != disp)
1233848b8605Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
1234848b8605Smrg
1235848b8605Smrg   if (_eglGetSurfaceHandle(surf) == EGL_NO_SURFACE)
1236848b8605Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1237848b8605Smrg
1238b8e80941Smrg   if (surf->Type != EGL_WINDOW_BIT)
1239b8e80941Smrg      RETURN_EGL_EVAL(disp, EGL_TRUE);
1240b8e80941Smrg
1241b8e80941Smrg   interval = CLAMP(interval,
1242b8e80941Smrg                    surf->Config->MinSwapInterval,
1243b8e80941Smrg                    surf->Config->MaxSwapInterval);
1244b8e80941Smrg
1245b8e80941Smrg   if (surf->SwapInterval != interval)
1246b8e80941Smrg      ret = drv->API.SwapInterval(drv, disp, surf, interval);
1247b8e80941Smrg   else
1248b8e80941Smrg      ret = EGL_TRUE;
1249b8e80941Smrg
1250b8e80941Smrg   if (ret)
1251b8e80941Smrg      surf->SwapInterval = interval;
1252848b8605Smrg
1253848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
1254848b8605Smrg}
1255848b8605Smrg
1256848b8605Smrg
1257848b8605SmrgEGLBoolean EGLAPIENTRY
1258848b8605SmrgeglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1259848b8605Smrg{
1260848b8605Smrg   _EGLContext *ctx = _eglGetCurrentContext();
1261848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1262848b8605Smrg   _EGLSurface *surf = _eglLookupSurface(surface, disp);
1263848b8605Smrg   _EGLDriver *drv;
1264848b8605Smrg   EGLBoolean ret;
1265848b8605Smrg
1266b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1267848b8605Smrg   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1268848b8605Smrg
1269848b8605Smrg   /* surface must be bound to current context in EGL 1.4 */
1270b8e80941Smrg   #ifndef _EGL_BUILT_IN_DRIVER_HAIKU
1271848b8605Smrg   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1272848b8605Smrg       surf != ctx->DrawSurface)
1273848b8605Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1274b8e80941Smrg   #endif
1275b8e80941Smrg
1276b8e80941Smrg   if (surf->Type != EGL_WINDOW_BIT)
1277b8e80941Smrg      RETURN_EGL_EVAL(disp, EGL_TRUE);
1278b8e80941Smrg
1279b8e80941Smrg   /* From the EGL 1.5 spec:
1280b8e80941Smrg    *
1281b8e80941Smrg    *    If eglSwapBuffers is called and the native window associated with
1282b8e80941Smrg    *    surface is no longer valid, an EGL_BAD_NATIVE_WINDOW error is
1283b8e80941Smrg    *    generated.
1284b8e80941Smrg    */
1285b8e80941Smrg   if (surf->Lost)
1286b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE);
1287848b8605Smrg
1288848b8605Smrg   ret = drv->API.SwapBuffers(drv, disp, surf);
1289848b8605Smrg
1290b8e80941Smrg   /* EGL_KHR_partial_update
1291b8e80941Smrg    * Frame boundary successfully reached,
1292b8e80941Smrg    * reset damage region and reset BufferAgeRead
1293b8e80941Smrg    */
1294b8e80941Smrg   if (ret) {
1295b8e80941Smrg      surf->SetDamageRegionCalled = EGL_FALSE;
1296b8e80941Smrg      surf->BufferAgeRead = EGL_FALSE;
1297b8e80941Smrg   }
1298b8e80941Smrg
1299848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
1300848b8605Smrg}
1301848b8605Smrg
1302848b8605Smrg
1303b8e80941Smrgstatic EGLBoolean
1304b8e80941Smrg_eglSwapBuffersWithDamageCommon(_EGLDisplay *disp, _EGLSurface *surf,
1305b8e80941Smrg                                EGLint *rects, EGLint n_rects)
1306848b8605Smrg{
1307848b8605Smrg   _EGLContext *ctx = _eglGetCurrentContext();
1308848b8605Smrg   _EGLDriver *drv;
1309848b8605Smrg   EGLBoolean ret;
1310848b8605Smrg
1311848b8605Smrg   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1312848b8605Smrg
1313848b8605Smrg   /* surface must be bound to current context in EGL 1.4 */
1314848b8605Smrg   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1315848b8605Smrg       surf != ctx->DrawSurface)
1316848b8605Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1317848b8605Smrg
1318b8e80941Smrg   if (surf->Type != EGL_WINDOW_BIT)
1319b8e80941Smrg      RETURN_EGL_EVAL(disp, EGL_TRUE);
1320b8e80941Smrg
1321848b8605Smrg   if ((n_rects > 0 && rects == NULL) || n_rects < 0)
1322848b8605Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1323848b8605Smrg
1324848b8605Smrg   ret = drv->API.SwapBuffersWithDamageEXT(drv, disp, surf, rects, n_rects);
1325848b8605Smrg
1326b8e80941Smrg   /* EGL_KHR_partial_update
1327b8e80941Smrg    * Frame boundary successfully reached,
1328b8e80941Smrg    * reset damage region and reset BufferAgeRead
1329b8e80941Smrg    */
1330b8e80941Smrg   if (ret) {
1331b8e80941Smrg      surf->SetDamageRegionCalled = EGL_FALSE;
1332b8e80941Smrg      surf->BufferAgeRead = EGL_FALSE;
1333b8e80941Smrg   }
1334b8e80941Smrg
1335848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
1336848b8605Smrg}
1337848b8605Smrg
1338b8e80941Smrgstatic EGLBoolean EGLAPIENTRY
1339b8e80941SmrgeglSwapBuffersWithDamageEXT(EGLDisplay dpy, EGLSurface surface,
1340b8e80941Smrg                            EGLint *rects, EGLint n_rects)
1341b8e80941Smrg{
1342b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1343b8e80941Smrg   _EGLSurface *surf = _eglLookupSurface(surface, disp);
1344b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1345b8e80941Smrg   return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects);
1346b8e80941Smrg}
1347b8e80941Smrg
1348b8e80941Smrgstatic EGLBoolean EGLAPIENTRY
1349b8e80941SmrgeglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface surface,
1350b8e80941Smrg                            EGLint *rects, EGLint n_rects)
1351b8e80941Smrg{
1352b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1353b8e80941Smrg   _EGLSurface *surf = _eglLookupSurface(surface, disp);
1354b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1355b8e80941Smrg   return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects);
1356b8e80941Smrg}
1357b8e80941Smrg
1358b8e80941Smrg/**
1359b8e80941Smrg * Clamp the rectangles so that they lie within the surface.
1360b8e80941Smrg */
1361b8e80941Smrg
1362b8e80941Smrgstatic void
1363b8e80941Smrg_eglSetDamageRegionKHRClampRects(_EGLDisplay* disp, _EGLSurface* surf,
1364b8e80941Smrg                                 EGLint *rects, EGLint n_rects)
1365b8e80941Smrg{
1366b8e80941Smrg   EGLint i;
1367b8e80941Smrg   EGLint surf_height = surf->Height;
1368b8e80941Smrg   EGLint surf_width = surf->Width;
1369b8e80941Smrg
1370b8e80941Smrg   for (i = 0; i < (4 * n_rects); i += 4) {
1371b8e80941Smrg      EGLint x1, y1, x2, y2;
1372b8e80941Smrg      x1 = rects[i];
1373b8e80941Smrg      y1 = rects[i + 1];
1374b8e80941Smrg      x2 = rects[i + 2] + x1;
1375b8e80941Smrg      y2 = rects[i + 3] + y1;
1376b8e80941Smrg
1377b8e80941Smrg      rects[i] = CLAMP(x1, 0, surf_width);
1378b8e80941Smrg      rects[i + 1] = CLAMP(y1, 0, surf_height);
1379b8e80941Smrg      rects[i + 2] = CLAMP(x2, 0, surf_width) - rects[i];
1380b8e80941Smrg      rects[i + 3] = CLAMP(y2, 0, surf_height) - rects[i + 1];
1381b8e80941Smrg   }
1382b8e80941Smrg}
1383b8e80941Smrg
1384b8e80941Smrgstatic EGLBoolean EGLAPIENTRY
1385b8e80941SmrgeglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
1386b8e80941Smrg                      EGLint *rects, EGLint n_rects)
1387b8e80941Smrg{
1388b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1389b8e80941Smrg   _EGLSurface *surf = _eglLookupSurface(surface, disp);
1390b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1391b8e80941Smrg   _EGLContext *ctx = _eglGetCurrentContext();
1392b8e80941Smrg   _EGLDriver *drv;
1393b8e80941Smrg   EGLBoolean ret;
1394b8e80941Smrg   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1395b8e80941Smrg
1396b8e80941Smrg   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1397b8e80941Smrg       surf->Type != EGL_WINDOW_BIT ||
1398b8e80941Smrg       ctx->DrawSurface != surf ||
1399b8e80941Smrg       surf->SwapBehavior != EGL_BUFFER_DESTROYED)
1400b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
1401b8e80941Smrg
1402b8e80941Smrg   /* If the damage region is already set or
1403b8e80941Smrg    * buffer age is not queried between
1404b8e80941Smrg    * frame boundaries, throw bad access error
1405b8e80941Smrg    */
1406b8e80941Smrg
1407b8e80941Smrg   if (surf->SetDamageRegionCalled || !surf->BufferAgeRead)
1408b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_ACCESS, EGL_FALSE);
1409b8e80941Smrg
1410b8e80941Smrg   _eglSetDamageRegionKHRClampRects(disp, surf, rects, n_rects);
1411b8e80941Smrg   ret = drv->API.SetDamageRegion(drv, disp, surf, rects, n_rects);
1412b8e80941Smrg
1413b8e80941Smrg   if (ret)
1414b8e80941Smrg      surf->SetDamageRegionCalled = EGL_TRUE;
1415b8e80941Smrg
1416b8e80941Smrg   RETURN_EGL_EVAL(disp, ret);
1417b8e80941Smrg}
1418848b8605Smrg
1419848b8605SmrgEGLBoolean EGLAPIENTRY
1420848b8605SmrgeglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1421848b8605Smrg{
1422848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1423848b8605Smrg   _EGLSurface *surf = _eglLookupSurface(surface, disp);
1424848b8605Smrg   _EGLDriver *drv;
1425848b8605Smrg   EGLBoolean ret;
1426848b8605Smrg   void *native_pixmap_ptr;
1427848b8605Smrg
1428b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1429848b8605Smrg   STATIC_ASSERT(sizeof(void*) == sizeof(target));
1430848b8605Smrg   native_pixmap_ptr = (void*) target;
1431848b8605Smrg
1432848b8605Smrg   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1433848b8605Smrg   ret = drv->API.CopyBuffers(drv, disp, surf, native_pixmap_ptr);
1434848b8605Smrg
1435848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
1436848b8605Smrg}
1437848b8605Smrg
1438848b8605Smrg
1439b8e80941Smrgstatic EGLBoolean
1440b8e80941Smrg_eglWaitClientCommon(void)
1441848b8605Smrg{
1442848b8605Smrg   _EGLContext *ctx = _eglGetCurrentContext();
1443848b8605Smrg   _EGLDisplay *disp;
1444848b8605Smrg   _EGLDriver *drv;
1445848b8605Smrg   EGLBoolean ret;
1446848b8605Smrg
1447848b8605Smrg   if (!ctx)
1448848b8605Smrg      RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1449848b8605Smrg
1450848b8605Smrg   disp = ctx->Resource.Display;
1451b8e80941Smrg   mtx_lock(&disp->Mutex);
1452848b8605Smrg
1453848b8605Smrg   /* let bad current context imply bad current surface */
1454848b8605Smrg   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1455848b8605Smrg       _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
1456848b8605Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
1457848b8605Smrg
1458848b8605Smrg   /* a valid current context implies an initialized current display */
1459848b8605Smrg   assert(disp->Initialized);
1460848b8605Smrg   drv = disp->Driver;
1461848b8605Smrg   ret = drv->API.WaitClient(drv, disp, ctx);
1462848b8605Smrg
1463848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
1464848b8605Smrg}
1465848b8605Smrg
1466b8e80941SmrgEGLBoolean EGLAPIENTRY
1467b8e80941SmrgeglWaitClient(void)
1468b8e80941Smrg{
1469b8e80941Smrg   _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE);
1470b8e80941Smrg   return _eglWaitClientCommon();
1471b8e80941Smrg}
1472848b8605Smrg
1473848b8605SmrgEGLBoolean EGLAPIENTRY
1474848b8605SmrgeglWaitGL(void)
1475848b8605Smrg{
1476b8e80941Smrg   /* Since we only support OpenGL and GLES, eglWaitGL is equivalent to eglWaitClient. */
1477b8e80941Smrg   _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE);
1478b8e80941Smrg   return _eglWaitClientCommon();
1479b8e80941Smrg}
1480848b8605Smrg
1481848b8605Smrg
1482848b8605SmrgEGLBoolean EGLAPIENTRY
1483848b8605SmrgeglWaitNative(EGLint engine)
1484848b8605Smrg{
1485848b8605Smrg   _EGLContext *ctx = _eglGetCurrentContext();
1486848b8605Smrg   _EGLDisplay *disp;
1487848b8605Smrg   _EGLDriver *drv;
1488848b8605Smrg   EGLBoolean ret;
1489848b8605Smrg
1490848b8605Smrg   if (!ctx)
1491848b8605Smrg      RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1492848b8605Smrg
1493b8e80941Smrg   _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
1494b8e80941Smrg
1495848b8605Smrg   disp = ctx->Resource.Display;
1496b8e80941Smrg   mtx_lock(&disp->Mutex);
1497848b8605Smrg
1498848b8605Smrg   /* let bad current context imply bad current surface */
1499848b8605Smrg   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1500848b8605Smrg       _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
1501848b8605Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
1502848b8605Smrg
1503848b8605Smrg   /* a valid current context implies an initialized current display */
1504848b8605Smrg   assert(disp->Initialized);
1505848b8605Smrg   drv = disp->Driver;
1506848b8605Smrg   ret = drv->API.WaitNative(drv, disp, engine);
1507848b8605Smrg
1508848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
1509848b8605Smrg}
1510848b8605Smrg
1511848b8605Smrg
1512848b8605SmrgEGLDisplay EGLAPIENTRY
1513848b8605SmrgeglGetCurrentDisplay(void)
1514848b8605Smrg{
1515848b8605Smrg   _EGLContext *ctx = _eglGetCurrentContext();
1516848b8605Smrg   EGLDisplay ret;
1517848b8605Smrg
1518848b8605Smrg   ret = (ctx) ? _eglGetDisplayHandle(ctx->Resource.Display) : EGL_NO_DISPLAY;
1519848b8605Smrg
1520848b8605Smrg   RETURN_EGL_SUCCESS(NULL, ret);
1521848b8605Smrg}
1522848b8605Smrg
1523848b8605Smrg
1524848b8605SmrgEGLContext EGLAPIENTRY
1525848b8605SmrgeglGetCurrentContext(void)
1526848b8605Smrg{
1527848b8605Smrg   _EGLContext *ctx = _eglGetCurrentContext();
1528848b8605Smrg   EGLContext ret;
1529848b8605Smrg
1530848b8605Smrg   ret = _eglGetContextHandle(ctx);
1531848b8605Smrg
1532848b8605Smrg   RETURN_EGL_SUCCESS(NULL, ret);
1533848b8605Smrg}
1534848b8605Smrg
1535848b8605Smrg
1536848b8605SmrgEGLSurface EGLAPIENTRY
1537848b8605SmrgeglGetCurrentSurface(EGLint readdraw)
1538848b8605Smrg{
1539848b8605Smrg   _EGLContext *ctx = _eglGetCurrentContext();
1540848b8605Smrg   EGLint err = EGL_SUCCESS;
1541848b8605Smrg   _EGLSurface *surf;
1542848b8605Smrg   EGLSurface ret;
1543848b8605Smrg
1544b8e80941Smrg   _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_NO_SURFACE);
1545b8e80941Smrg
1546848b8605Smrg   if (!ctx)
1547848b8605Smrg      RETURN_EGL_SUCCESS(NULL, EGL_NO_SURFACE);
1548848b8605Smrg
1549848b8605Smrg   switch (readdraw) {
1550848b8605Smrg   case EGL_DRAW:
1551848b8605Smrg      surf = ctx->DrawSurface;
1552848b8605Smrg      break;
1553848b8605Smrg   case EGL_READ:
1554848b8605Smrg      surf = ctx->ReadSurface;
1555848b8605Smrg      break;
1556848b8605Smrg   default:
1557848b8605Smrg      surf = NULL;
1558848b8605Smrg      err = EGL_BAD_PARAMETER;
1559848b8605Smrg      break;
1560848b8605Smrg   }
1561848b8605Smrg
1562848b8605Smrg   ret = _eglGetSurfaceHandle(surf);
1563848b8605Smrg
1564848b8605Smrg   RETURN_EGL_ERROR(NULL, err, ret);
1565848b8605Smrg}
1566848b8605Smrg
1567848b8605Smrg
1568848b8605SmrgEGLint EGLAPIENTRY
1569848b8605SmrgeglGetError(void)
1570848b8605Smrg{
1571848b8605Smrg   _EGLThreadInfo *t = _eglGetCurrentThread();
1572848b8605Smrg   EGLint e = t->LastError;
1573848b8605Smrg   if (!_eglIsCurrentThreadDummy())
1574848b8605Smrg      t->LastError = EGL_SUCCESS;
1575848b8605Smrg   return e;
1576848b8605Smrg}
1577848b8605Smrg
1578848b8605Smrg
1579848b8605Smrg/**
1580848b8605Smrg ** EGL 1.2
1581848b8605Smrg **/
1582848b8605Smrg
1583848b8605Smrg/**
1584848b8605Smrg * Specify the client API to use for subsequent calls including:
1585848b8605Smrg *  eglCreateContext()
1586848b8605Smrg *  eglGetCurrentContext()
1587848b8605Smrg *  eglGetCurrentDisplay()
1588848b8605Smrg *  eglGetCurrentSurface()
1589848b8605Smrg *  eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT)
1590848b8605Smrg *  eglWaitClient()
1591848b8605Smrg *  eglWaitNative()
1592848b8605Smrg * See section 3.7 "Rendering Context" in the EGL specification for details.
1593848b8605Smrg */
1594848b8605SmrgEGLBoolean EGLAPIENTRY
1595848b8605SmrgeglBindAPI(EGLenum api)
1596848b8605Smrg{
1597b8e80941Smrg   _EGLThreadInfo *t;
1598848b8605Smrg
1599b8e80941Smrg   _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
1600b8e80941Smrg
1601b8e80941Smrg   t = _eglGetCurrentThread();
1602848b8605Smrg   if (_eglIsCurrentThreadDummy())
1603848b8605Smrg      RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
1604848b8605Smrg
1605848b8605Smrg   if (!_eglIsApiValid(api))
1606848b8605Smrg      RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, EGL_FALSE);
1607848b8605Smrg
1608b8e80941Smrg   t->CurrentAPI = api;
1609848b8605Smrg
1610848b8605Smrg   RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1611848b8605Smrg}
1612848b8605Smrg
1613848b8605Smrg
1614848b8605Smrg/**
1615848b8605Smrg * Return the last value set with eglBindAPI().
1616848b8605Smrg */
1617848b8605SmrgEGLenum EGLAPIENTRY
1618848b8605SmrgeglQueryAPI(void)
1619848b8605Smrg{
1620848b8605Smrg   _EGLThreadInfo *t = _eglGetCurrentThread();
1621848b8605Smrg   EGLenum ret;
1622848b8605Smrg
1623848b8605Smrg   /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */
1624b8e80941Smrg   ret = t->CurrentAPI;
1625848b8605Smrg
1626848b8605Smrg   RETURN_EGL_SUCCESS(NULL, ret);
1627848b8605Smrg}
1628848b8605Smrg
1629848b8605Smrg
1630848b8605SmrgEGLSurface EGLAPIENTRY
1631848b8605SmrgeglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
1632848b8605Smrg                                 EGLClientBuffer buffer, EGLConfig config,
1633848b8605Smrg                                 const EGLint *attrib_list)
1634848b8605Smrg{
1635848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1636848b8605Smrg   _EGLConfig *conf = _eglLookupConfig(config, disp);
1637848b8605Smrg   _EGLDriver *drv;
1638848b8605Smrg   _EGLSurface *surf;
1639848b8605Smrg   EGLSurface ret;
1640848b8605Smrg
1641b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1642b8e80941Smrg
1643848b8605Smrg   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
1644848b8605Smrg
1645848b8605Smrg   surf = drv->API.CreatePbufferFromClientBuffer(drv, disp, buftype, buffer,
1646848b8605Smrg                                                 conf, attrib_list);
1647848b8605Smrg   ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1648848b8605Smrg
1649848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
1650848b8605Smrg}
1651848b8605Smrg
1652848b8605Smrg
1653848b8605SmrgEGLBoolean EGLAPIENTRY
1654848b8605SmrgeglReleaseThread(void)
1655848b8605Smrg{
1656848b8605Smrg   /* unbind current contexts */
1657848b8605Smrg   if (!_eglIsCurrentThreadDummy()) {
1658848b8605Smrg      _EGLThreadInfo *t = _eglGetCurrentThread();
1659b8e80941Smrg      _EGLContext *ctx = t->CurrentContext;
1660848b8605Smrg
1661b8e80941Smrg      _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
1662848b8605Smrg
1663b8e80941Smrg      if (ctx) {
1664b8e80941Smrg         _EGLDisplay *disp = ctx->Resource.Display;
1665b8e80941Smrg         _EGLDriver *drv;
1666848b8605Smrg
1667b8e80941Smrg         mtx_lock(&disp->Mutex);
1668b8e80941Smrg         drv = disp->Driver;
1669b8e80941Smrg         (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
1670b8e80941Smrg         mtx_unlock(&disp->Mutex);
1671848b8605Smrg      }
1672848b8605Smrg   }
1673848b8605Smrg
1674848b8605Smrg   _eglDestroyCurrentThread();
1675848b8605Smrg
1676848b8605Smrg   RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1677848b8605Smrg}
1678848b8605Smrg
1679848b8605Smrg
1680b8e80941Smrgstatic EGLImage
1681b8e80941Smrg_eglCreateImageCommon(_EGLDisplay *disp, EGLContext ctx, EGLenum target,
1682b8e80941Smrg                      EGLClientBuffer buffer, const EGLint *attr_list)
1683848b8605Smrg{
1684848b8605Smrg   _EGLContext *context = _eglLookupContext(ctx, disp);
1685848b8605Smrg   _EGLDriver *drv;
1686848b8605Smrg   _EGLImage *img;
1687b8e80941Smrg   EGLImage ret;
1688848b8605Smrg
1689848b8605Smrg   _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
1690848b8605Smrg   if (!disp->Extensions.KHR_image_base)
1691848b8605Smrg      RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
1692848b8605Smrg   if (!context && ctx != EGL_NO_CONTEXT)
1693848b8605Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1694848b8605Smrg   /* "If <target> is EGL_LINUX_DMA_BUF_EXT, <dpy> must be a valid display,
1695848b8605Smrg    *  <ctx> must be EGL_NO_CONTEXT..."
1696848b8605Smrg    */
1697848b8605Smrg   if (ctx != EGL_NO_CONTEXT && target == EGL_LINUX_DMA_BUF_EXT)
1698848b8605Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1699848b8605Smrg
1700b8e80941Smrg   img = drv->API.CreateImageKHR(drv, disp, context, target,
1701b8e80941Smrg                                 buffer, attr_list);
1702848b8605Smrg   ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
1703848b8605Smrg
1704848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
1705848b8605Smrg}
1706848b8605Smrg
1707b8e80941Smrgstatic EGLImage EGLAPIENTRY
1708b8e80941SmrgeglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1709b8e80941Smrg                  EGLClientBuffer buffer, const EGLint *attr_list)
1710b8e80941Smrg{
1711b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1712b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR);
1713b8e80941Smrg   return _eglCreateImageCommon(disp, ctx, target, buffer, attr_list);
1714b8e80941Smrg}
1715b8e80941Smrg
1716848b8605Smrg
1717b8e80941SmrgEGLImage EGLAPIENTRY
1718b8e80941SmrgeglCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1719b8e80941Smrg               EGLClientBuffer buffer, const EGLAttrib *attr_list)
1720848b8605Smrg{
1721848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1722b8e80941Smrg   EGLImage image;
1723b8e80941Smrg   EGLint *int_attribs;
1724b8e80941Smrg
1725b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR);
1726b8e80941Smrg
1727b8e80941Smrg   int_attribs = _eglConvertAttribsToInt(attr_list);
1728b8e80941Smrg   if (attr_list && !int_attribs)
1729b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_IMAGE);
1730b8e80941Smrg
1731b8e80941Smrg   image = _eglCreateImageCommon(disp, ctx, target, buffer, int_attribs);
1732b8e80941Smrg   free(int_attribs);
1733b8e80941Smrg   return image;
1734b8e80941Smrg}
1735b8e80941Smrg
1736b8e80941Smrg
1737b8e80941Smrgstatic EGLBoolean
1738b8e80941Smrg_eglDestroyImageCommon(_EGLDisplay *disp, _EGLImage *img)
1739b8e80941Smrg{
1740848b8605Smrg   _EGLDriver *drv;
1741848b8605Smrg   EGLBoolean ret;
1742848b8605Smrg
1743848b8605Smrg   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1744848b8605Smrg   if (!disp->Extensions.KHR_image_base)
1745848b8605Smrg      RETURN_EGL_EVAL(disp, EGL_FALSE);
1746848b8605Smrg   if (!img)
1747848b8605Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1748848b8605Smrg
1749848b8605Smrg   _eglUnlinkImage(img);
1750848b8605Smrg   ret = drv->API.DestroyImageKHR(drv, disp, img);
1751848b8605Smrg
1752848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
1753848b8605Smrg}
1754848b8605Smrg
1755b8e80941SmrgEGLBoolean EGLAPIENTRY
1756b8e80941SmrgeglDestroyImage(EGLDisplay dpy, EGLImage image)
1757b8e80941Smrg{
1758b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1759b8e80941Smrg   _EGLImage *img = _eglLookupImage(image, disp);
1760b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
1761b8e80941Smrg   return _eglDestroyImageCommon(disp, img);
1762b8e80941Smrg}
1763848b8605Smrg
1764b8e80941Smrgstatic EGLBoolean EGLAPIENTRY
1765b8e80941SmrgeglDestroyImageKHR(EGLDisplay dpy, EGLImage image)
1766848b8605Smrg{
1767848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1768b8e80941Smrg   _EGLImage *img = _eglLookupImage(image, disp);
1769b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
1770b8e80941Smrg   return _eglDestroyImageCommon(disp, img);
1771b8e80941Smrg}
1772b8e80941Smrg
1773b8e80941Smrg
1774b8e80941Smrgstatic EGLSync
1775b8e80941Smrg_eglCreateSync(_EGLDisplay *disp, EGLenum type, const EGLAttrib *attrib_list,
1776b8e80941Smrg               EGLBoolean orig_is_EGLAttrib,
1777b8e80941Smrg               EGLenum invalid_type_error)
1778b8e80941Smrg{
1779b8e80941Smrg   _EGLContext *ctx = _eglGetCurrentContext();
1780848b8605Smrg   _EGLDriver *drv;
1781848b8605Smrg   _EGLSync *sync;
1782b8e80941Smrg   EGLSync ret;
1783848b8605Smrg
1784848b8605Smrg   _EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv);
1785b8e80941Smrg
1786b8e80941Smrg   if (!disp->Extensions.KHR_cl_event2 && orig_is_EGLAttrib) {
1787b8e80941Smrg      /* There exist two EGLAttrib variants of eglCreateSync*:
1788b8e80941Smrg       * eglCreateSync64KHR which requires EGL_KHR_cl_event2, and eglCreateSync
1789b8e80941Smrg       * which requires EGL 1.5. Here we use the presence of EGL_KHR_cl_event2
1790b8e80941Smrg       * support as a proxy for EGL 1.5 support, even though that's not
1791b8e80941Smrg       * entirely correct (though _eglComputeVersion does the same).
1792b8e80941Smrg       *
1793b8e80941Smrg       * The EGL spec provides no guidance on how to handle unsupported
1794b8e80941Smrg       * functions. EGL_BAD_MATCH seems reasonable.
1795b8e80941Smrg       */
1796b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1797b8e80941Smrg   }
1798b8e80941Smrg
1799b8e80941Smrg   /* If type is EGL_SYNC_FENCE and no context is current for the bound API
1800b8e80941Smrg    * (i.e., eglGetCurrentContext returns EGL_NO_CONTEXT ), an EGL_BAD_MATCH
1801b8e80941Smrg    * error is generated.
1802b8e80941Smrg    */
1803b8e80941Smrg   if (!ctx &&
1804b8e80941Smrg       (type == EGL_SYNC_FENCE_KHR || type == EGL_SYNC_NATIVE_FENCE_ANDROID))
1805b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1806b8e80941Smrg
1807b8e80941Smrg   /* return an error if the client API doesn't support GL_OES_EGL_sync */
1808b8e80941Smrg   if (ctx && (ctx->Resource.Display != disp ||
1809b8e80941Smrg               ctx->ClientAPI != EGL_OPENGL_ES_API))
1810b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1811b8e80941Smrg
1812b8e80941Smrg   switch (type) {
1813b8e80941Smrg   case EGL_SYNC_FENCE_KHR:
1814b8e80941Smrg      if (!disp->Extensions.KHR_fence_sync)
1815b8e80941Smrg         RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1816b8e80941Smrg      break;
1817b8e80941Smrg   case EGL_SYNC_REUSABLE_KHR:
1818b8e80941Smrg      if (!disp->Extensions.KHR_reusable_sync)
1819b8e80941Smrg         RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1820b8e80941Smrg      break;
1821b8e80941Smrg   case EGL_SYNC_CL_EVENT_KHR:
1822b8e80941Smrg      if (!disp->Extensions.KHR_cl_event2)
1823b8e80941Smrg         RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1824b8e80941Smrg      break;
1825b8e80941Smrg   case EGL_SYNC_NATIVE_FENCE_ANDROID:
1826b8e80941Smrg      if (!disp->Extensions.ANDROID_native_fence_sync)
1827b8e80941Smrg         RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1828b8e80941Smrg      break;
1829b8e80941Smrg   default:
1830b8e80941Smrg      RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1831b8e80941Smrg   }
1832848b8605Smrg
1833848b8605Smrg   sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list);
1834848b8605Smrg   ret = (sync) ? _eglLinkSync(sync) : EGL_NO_SYNC_KHR;
1835848b8605Smrg
1836848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
1837848b8605Smrg}
1838848b8605Smrg
1839848b8605Smrg
1840b8e80941Smrgstatic EGLSync EGLAPIENTRY
1841b8e80941SmrgeglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *int_list)
1842848b8605Smrg{
1843848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1844b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
1845b8e80941Smrg
1846b8e80941Smrg   EGLSync sync;
1847b8e80941Smrg   EGLAttrib *attrib_list;
1848b8e80941Smrg   EGLint err;
1849b8e80941Smrg
1850b8e80941Smrg   if (sizeof(int_list[0]) == sizeof(attrib_list[0])) {
1851b8e80941Smrg      attrib_list = (EGLAttrib *) int_list;
1852b8e80941Smrg   } else {
1853b8e80941Smrg      err = _eglConvertIntsToAttribs(int_list, &attrib_list);
1854b8e80941Smrg      if (err != EGL_SUCCESS)
1855b8e80941Smrg         RETURN_EGL_ERROR(disp, err, EGL_NO_SYNC);
1856b8e80941Smrg   }
1857848b8605Smrg
1858b8e80941Smrg   sync = _eglCreateSync(disp, type, attrib_list, EGL_FALSE,
1859b8e80941Smrg                         EGL_BAD_ATTRIBUTE);
1860848b8605Smrg
1861b8e80941Smrg   if (sizeof(int_list[0]) != sizeof(attrib_list[0]))
1862b8e80941Smrg      free(attrib_list);
1863848b8605Smrg
1864b8e80941Smrg   /* Don't double-unlock the display. _eglCreateSync already unlocked it. */
1865b8e80941Smrg   return sync;
1866848b8605Smrg}
1867848b8605Smrg
1868848b8605Smrg
1869b8e80941Smrgstatic EGLSync EGLAPIENTRY
1870b8e80941SmrgeglCreateSync64KHR(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
1871848b8605Smrg{
1872848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1873b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
1874b8e80941Smrg   return _eglCreateSync(disp, type, attrib_list, EGL_TRUE,
1875b8e80941Smrg                         EGL_BAD_ATTRIBUTE);
1876b8e80941Smrg}
1877848b8605Smrg
1878848b8605Smrg
1879b8e80941SmrgEGLSync EGLAPIENTRY
1880b8e80941SmrgeglCreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
1881b8e80941Smrg{
1882b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1883b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
1884b8e80941Smrg   return _eglCreateSync(disp, type, attrib_list, EGL_TRUE,
1885b8e80941Smrg                         EGL_BAD_PARAMETER);
1886848b8605Smrg}
1887848b8605Smrg
1888848b8605Smrg
1889b8e80941Smrgstatic EGLBoolean
1890b8e80941Smrg_eglDestroySync(_EGLDisplay *disp, _EGLSync *s)
1891b8e80941Smrg{
1892b8e80941Smrg   _EGLDriver *drv;
1893b8e80941Smrg   EGLBoolean ret;
1894b8e80941Smrg
1895b8e80941Smrg   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1896b8e80941Smrg   assert(disp->Extensions.KHR_reusable_sync ||
1897b8e80941Smrg          disp->Extensions.KHR_fence_sync ||
1898b8e80941Smrg          disp->Extensions.ANDROID_native_fence_sync);
1899b8e80941Smrg
1900b8e80941Smrg   _eglUnlinkSync(s);
1901b8e80941Smrg   ret = drv->API.DestroySyncKHR(drv, disp, s);
1902b8e80941Smrg
1903b8e80941Smrg   RETURN_EGL_EVAL(disp, ret);
1904b8e80941Smrg}
1905b8e80941Smrg
1906848b8605SmrgEGLBoolean EGLAPIENTRY
1907b8e80941SmrgeglDestroySync(EGLDisplay dpy, EGLSync sync)
1908848b8605Smrg{
1909848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1910848b8605Smrg   _EGLSync *s = _eglLookupSync(sync, disp);
1911b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
1912b8e80941Smrg   return _eglDestroySync(disp, s);
1913b8e80941Smrg}
1914b8e80941Smrg
1915b8e80941Smrgstatic EGLBoolean EGLAPIENTRY
1916b8e80941SmrgeglDestroySyncKHR(EGLDisplay dpy, EGLSync sync)
1917b8e80941Smrg{
1918b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1919b8e80941Smrg   _EGLSync *s = _eglLookupSync(sync, disp);
1920b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
1921b8e80941Smrg   return _eglDestroySync(disp, s);
1922b8e80941Smrg}
1923b8e80941Smrg
1924b8e80941Smrg
1925b8e80941Smrgstatic EGLint
1926b8e80941Smrg_eglClientWaitSyncCommon(_EGLDisplay *disp, EGLDisplay dpy,
1927b8e80941Smrg                         _EGLSync *s, EGLint flags, EGLTime timeout)
1928b8e80941Smrg{
1929848b8605Smrg   _EGLDriver *drv;
1930b8e80941Smrg   EGLint ret;
1931848b8605Smrg
1932848b8605Smrg   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1933b8e80941Smrg   assert(disp->Extensions.KHR_reusable_sync ||
1934b8e80941Smrg          disp->Extensions.KHR_fence_sync ||
1935b8e80941Smrg          disp->Extensions.ANDROID_native_fence_sync);
1936b8e80941Smrg
1937b8e80941Smrg   if (s->SyncStatus == EGL_SIGNALED_KHR)
1938b8e80941Smrg      RETURN_EGL_EVAL(disp, EGL_CONDITION_SATISFIED_KHR);
1939b8e80941Smrg
1940b8e80941Smrg   /* if sync type is EGL_SYNC_REUSABLE_KHR, dpy should be
1941b8e80941Smrg    * unlocked here to allow other threads also to be able to
1942b8e80941Smrg    * go into waiting state.
1943b8e80941Smrg    */
1944b8e80941Smrg
1945b8e80941Smrg   if (s->Type == EGL_SYNC_REUSABLE_KHR)
1946b8e80941Smrg      _eglUnlockDisplay(dpy);
1947b8e80941Smrg
1948b8e80941Smrg   ret = drv->API.ClientWaitSyncKHR(drv, disp, s, flags, timeout);
1949b8e80941Smrg
1950b8e80941Smrg   /*
1951b8e80941Smrg    * 'disp' is already unlocked for reusable sync type,
1952b8e80941Smrg    * so passing 'NULL' to bypass unlocking display.
1953b8e80941Smrg    */
1954b8e80941Smrg   if (s->Type == EGL_SYNC_REUSABLE_KHR)
1955b8e80941Smrg      RETURN_EGL_EVAL(NULL, ret);
1956b8e80941Smrg   else
1957b8e80941Smrg      RETURN_EGL_EVAL(disp, ret);
1958b8e80941Smrg}
1959b8e80941Smrg
1960b8e80941SmrgEGLint EGLAPIENTRY
1961b8e80941SmrgeglClientWaitSync(EGLDisplay dpy, EGLSync sync,
1962b8e80941Smrg                  EGLint flags, EGLTime timeout)
1963b8e80941Smrg{
1964b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1965b8e80941Smrg   _EGLSync *s = _eglLookupSync(sync, disp);
1966b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
1967b8e80941Smrg   return _eglClientWaitSyncCommon(disp, dpy, s, flags, timeout);
1968b8e80941Smrg}
1969b8e80941Smrg
1970b8e80941Smrgstatic EGLint EGLAPIENTRY
1971b8e80941SmrgeglClientWaitSyncKHR(EGLDisplay dpy, EGLSync sync,
1972b8e80941Smrg                     EGLint flags, EGLTime timeout)
1973b8e80941Smrg{
1974b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
1975b8e80941Smrg   _EGLSync *s = _eglLookupSync(sync, disp);
1976b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
1977b8e80941Smrg   return _eglClientWaitSyncCommon(disp, dpy, s, flags, timeout);
1978b8e80941Smrg}
1979b8e80941Smrg
1980b8e80941Smrg
1981b8e80941Smrgstatic EGLint
1982b8e80941Smrg_eglWaitSyncCommon(_EGLDisplay *disp, _EGLSync *s, EGLint flags)
1983b8e80941Smrg{
1984b8e80941Smrg   _EGLContext *ctx = _eglGetCurrentContext();
1985b8e80941Smrg   _EGLDriver *drv;
1986b8e80941Smrg   EGLint ret;
1987b8e80941Smrg
1988b8e80941Smrg   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1989b8e80941Smrg   assert(disp->Extensions.KHR_wait_sync);
1990b8e80941Smrg
1991b8e80941Smrg   /* return an error if the client API doesn't support GL_OES_EGL_sync */
1992b8e80941Smrg   if (ctx == EGL_NO_CONTEXT || ctx->ClientAPI != EGL_OPENGL_ES_API)
1993b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
1994b8e80941Smrg
1995b8e80941Smrg   /* the API doesn't allow any flags yet */
1996b8e80941Smrg   if (flags != 0)
1997b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1998b8e80941Smrg
1999b8e80941Smrg   ret = drv->API.WaitSyncKHR(drv, disp, s);
2000848b8605Smrg
2001848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
2002848b8605Smrg}
2003848b8605Smrg
2004b8e80941Smrgstatic EGLint EGLAPIENTRY
2005b8e80941SmrgeglWaitSyncKHR(EGLDisplay dpy, EGLSync sync, EGLint flags)
2006b8e80941Smrg{
2007b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
2008b8e80941Smrg   _EGLSync *s = _eglLookupSync(sync, disp);
2009b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2010b8e80941Smrg   return _eglWaitSyncCommon(disp, s, flags);
2011b8e80941Smrg}
2012b8e80941Smrg
2013848b8605Smrg
2014848b8605SmrgEGLBoolean EGLAPIENTRY
2015b8e80941SmrgeglWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags)
2016b8e80941Smrg{
2017b8e80941Smrg   /* The KHR version returns EGLint, while the core version returns
2018b8e80941Smrg    * EGLBoolean. In both cases, the return values can only be EGL_FALSE and
2019b8e80941Smrg    * EGL_TRUE.
2020b8e80941Smrg    */
2021b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
2022b8e80941Smrg   _EGLSync *s = _eglLookupSync(sync, disp);
2023b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2024b8e80941Smrg   return _eglWaitSyncCommon(disp, s, flags);
2025b8e80941Smrg}
2026b8e80941Smrg
2027b8e80941Smrg
2028b8e80941Smrgstatic EGLBoolean EGLAPIENTRY
2029b8e80941SmrgeglSignalSyncKHR(EGLDisplay dpy, EGLSync sync, EGLenum mode)
2030848b8605Smrg{
2031848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
2032848b8605Smrg   _EGLSync *s = _eglLookupSync(sync, disp);
2033848b8605Smrg   _EGLDriver *drv;
2034848b8605Smrg   EGLBoolean ret;
2035848b8605Smrg
2036b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2037b8e80941Smrg
2038848b8605Smrg   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
2039848b8605Smrg   assert(disp->Extensions.KHR_reusable_sync);
2040b8e80941Smrg   ret = drv->API.SignalSyncKHR(drv, disp, s, mode);
2041848b8605Smrg
2042848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
2043848b8605Smrg}
2044848b8605Smrg
2045848b8605Smrg
2046b8e80941Smrgstatic EGLBoolean
2047b8e80941Smrg_eglGetSyncAttribCommon(_EGLDisplay *disp, _EGLSync *s, EGLint attribute, EGLAttrib *value)
2048b8e80941Smrg{
2049b8e80941Smrg   _EGLDriver *drv;
2050b8e80941Smrg   EGLBoolean ret;
2051b8e80941Smrg
2052b8e80941Smrg   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
2053b8e80941Smrg   assert(disp->Extensions.KHR_reusable_sync ||
2054b8e80941Smrg          disp->Extensions.KHR_fence_sync ||
2055b8e80941Smrg          disp->Extensions.ANDROID_native_fence_sync);
2056b8e80941Smrg   ret = drv->API.GetSyncAttrib(drv, disp, s, attribute, value);
2057b8e80941Smrg
2058b8e80941Smrg   RETURN_EGL_EVAL(disp, ret);
2059b8e80941Smrg}
2060848b8605Smrg
2061848b8605SmrgEGLBoolean EGLAPIENTRY
2062b8e80941SmrgeglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value)
2063b8e80941Smrg{
2064b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
2065b8e80941Smrg   _EGLSync *s = _eglLookupSync(sync, disp);
2066b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2067b8e80941Smrg   return _eglGetSyncAttribCommon(disp, s, attribute, value);
2068b8e80941Smrg}
2069b8e80941Smrg
2070b8e80941Smrg
2071b8e80941Smrgstatic EGLBoolean EGLAPIENTRY
2072b8e80941SmrgeglGetSyncAttribKHR(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint *value)
2073b8e80941Smrg{
2074b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
2075b8e80941Smrg   _EGLSync *s = _eglLookupSync(sync, disp);
2076b8e80941Smrg   EGLAttrib attrib;
2077b8e80941Smrg   EGLBoolean result;
2078b8e80941Smrg
2079b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2080b8e80941Smrg
2081b8e80941Smrg   if (!value)
2082b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2083b8e80941Smrg
2084b8e80941Smrg   attrib = *value;
2085b8e80941Smrg   result = _eglGetSyncAttribCommon(disp, s, attribute, &attrib);
2086b8e80941Smrg
2087b8e80941Smrg   /* The EGL_KHR_fence_sync spec says this about eglGetSyncAttribKHR:
2088b8e80941Smrg    *
2089b8e80941Smrg    *    If any error occurs, <*value> is not modified.
2090b8e80941Smrg    */
2091b8e80941Smrg   if (result == EGL_FALSE)
2092b8e80941Smrg      return result;
2093b8e80941Smrg
2094b8e80941Smrg   *value = attrib;
2095b8e80941Smrg   return result;
2096b8e80941Smrg}
2097b8e80941Smrg
2098b8e80941Smrgstatic EGLint EGLAPIENTRY
2099b8e80941SmrgeglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync)
2100b8e80941Smrg{
2101b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
2102b8e80941Smrg   _EGLSync *s = _eglLookupSync(sync, disp);
2103b8e80941Smrg   _EGLDriver *drv;
2104b8e80941Smrg   EGLBoolean ret;
2105b8e80941Smrg
2106b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2107b8e80941Smrg
2108b8e80941Smrg   /* the spec doesn't seem to specify what happens if the fence
2109b8e80941Smrg    * type is not EGL_SYNC_NATIVE_FENCE_ANDROID, but this seems
2110b8e80941Smrg    * sensible:
2111b8e80941Smrg    */
2112b8e80941Smrg   if (!(s && (s->Type == EGL_SYNC_NATIVE_FENCE_ANDROID)))
2113b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_NATIVE_FENCE_FD_ANDROID);
2114b8e80941Smrg
2115b8e80941Smrg   _EGL_CHECK_SYNC(disp, s, EGL_NO_NATIVE_FENCE_FD_ANDROID, drv);
2116b8e80941Smrg   assert(disp->Extensions.ANDROID_native_fence_sync);
2117b8e80941Smrg   ret = drv->API.DupNativeFenceFDANDROID(drv, disp, s);
2118b8e80941Smrg
2119b8e80941Smrg   RETURN_EGL_EVAL(disp, ret);
2120b8e80941Smrg}
2121b8e80941Smrg
2122b8e80941Smrgstatic EGLBoolean EGLAPIENTRY
2123848b8605SmrgeglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface,
2124b8e80941Smrg                        EGLint numRects, const EGLint *rects)
2125848b8605Smrg{
2126848b8605Smrg   _EGLContext *ctx = _eglGetCurrentContext();
2127848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
2128848b8605Smrg   _EGLSurface *surf = _eglLookupSurface(surface, disp);
2129848b8605Smrg   _EGLDriver *drv;
2130848b8605Smrg   EGLBoolean ret;
2131848b8605Smrg
2132b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
2133b8e80941Smrg
2134848b8605Smrg   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
2135848b8605Smrg
2136848b8605Smrg   if (!disp->Extensions.NOK_swap_region)
2137848b8605Smrg      RETURN_EGL_EVAL(disp, EGL_FALSE);
2138848b8605Smrg
2139848b8605Smrg   /* surface must be bound to current context in EGL 1.4 */
2140848b8605Smrg   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
2141848b8605Smrg       surf != ctx->DrawSurface)
2142848b8605Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
2143848b8605Smrg
2144848b8605Smrg   ret = drv->API.SwapBuffersRegionNOK(drv, disp, surf, numRects, rects);
2145848b8605Smrg
2146848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
2147848b8605Smrg}
2148848b8605Smrg
2149848b8605Smrg
2150b8e80941Smrgstatic EGLImage EGLAPIENTRY
2151848b8605SmrgeglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list)
2152848b8605Smrg{
2153848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
2154848b8605Smrg   _EGLDriver *drv;
2155848b8605Smrg   _EGLImage *img;
2156b8e80941Smrg   EGLImage ret;
2157b8e80941Smrg
2158b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2159848b8605Smrg
2160848b8605Smrg   _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
2161848b8605Smrg   if (!disp->Extensions.MESA_drm_image)
2162848b8605Smrg      RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
2163848b8605Smrg
2164848b8605Smrg   img = drv->API.CreateDRMImageMESA(drv, disp, attr_list);
2165848b8605Smrg   ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
2166848b8605Smrg
2167848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
2168848b8605Smrg}
2169848b8605Smrg
2170b8e80941Smrgstatic EGLBoolean EGLAPIENTRY
2171b8e80941SmrgeglExportDRMImageMESA(EGLDisplay dpy, EGLImage image,
2172b8e80941Smrg                      EGLint *name, EGLint *handle, EGLint *stride)
2173848b8605Smrg{
2174848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
2175848b8605Smrg   _EGLImage *img = _eglLookupImage(image, disp);
2176848b8605Smrg   _EGLDriver *drv;
2177848b8605Smrg   EGLBoolean ret;
2178848b8605Smrg
2179b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
2180b8e80941Smrg
2181848b8605Smrg   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2182848b8605Smrg   assert(disp->Extensions.MESA_drm_image);
2183848b8605Smrg
2184848b8605Smrg   if (!img)
2185848b8605Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2186848b8605Smrg
2187848b8605Smrg   ret = drv->API.ExportDRMImageMESA(drv, disp, img, name, handle, stride);
2188848b8605Smrg
2189848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
2190848b8605Smrg}
2191848b8605Smrg
2192848b8605Smrg
2193848b8605Smrgstruct wl_display;
2194848b8605Smrg
2195b8e80941Smrgstatic EGLBoolean EGLAPIENTRY
2196848b8605SmrgeglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
2197848b8605Smrg{
2198848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
2199848b8605Smrg   _EGLDriver *drv;
2200848b8605Smrg   EGLBoolean ret;
2201848b8605Smrg
2202b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2203b8e80941Smrg
2204848b8605Smrg   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2205848b8605Smrg   assert(disp->Extensions.WL_bind_wayland_display);
2206848b8605Smrg
2207848b8605Smrg   if (!display)
2208848b8605Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2209848b8605Smrg
2210848b8605Smrg   ret = drv->API.BindWaylandDisplayWL(drv, disp, display);
2211848b8605Smrg
2212848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
2213848b8605Smrg}
2214848b8605Smrg
2215b8e80941Smrgstatic EGLBoolean EGLAPIENTRY
2216848b8605SmrgeglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
2217848b8605Smrg{
2218848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
2219848b8605Smrg   _EGLDriver *drv;
2220848b8605Smrg   EGLBoolean ret;
2221848b8605Smrg
2222b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2223b8e80941Smrg
2224848b8605Smrg   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2225848b8605Smrg   assert(disp->Extensions.WL_bind_wayland_display);
2226848b8605Smrg
2227848b8605Smrg   if (!display)
2228848b8605Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2229848b8605Smrg
2230848b8605Smrg   ret = drv->API.UnbindWaylandDisplayWL(drv, disp, display);
2231848b8605Smrg
2232848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
2233848b8605Smrg}
2234848b8605Smrg
2235b8e80941Smrgstatic EGLBoolean EGLAPIENTRY
2236848b8605SmrgeglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer,
2237848b8605Smrg                        EGLint attribute, EGLint *value)
2238848b8605Smrg{
2239848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
2240848b8605Smrg   _EGLDriver *drv;
2241848b8605Smrg   EGLBoolean ret;
2242848b8605Smrg
2243b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2244b8e80941Smrg
2245848b8605Smrg   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2246848b8605Smrg   assert(disp->Extensions.WL_bind_wayland_display);
2247848b8605Smrg
2248848b8605Smrg   if (!buffer)
2249848b8605Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2250848b8605Smrg
2251848b8605Smrg   ret = drv->API.QueryWaylandBufferWL(drv, disp, buffer, attribute, value);
2252848b8605Smrg
2253848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
2254848b8605Smrg}
2255848b8605Smrg
2256b8e80941Smrg
2257b8e80941Smrgstatic struct wl_buffer * EGLAPIENTRY
2258b8e80941SmrgeglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImage image)
2259848b8605Smrg{
2260848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
2261848b8605Smrg   _EGLImage *img;
2262848b8605Smrg   _EGLDriver *drv;
2263848b8605Smrg   struct wl_buffer *ret;
2264848b8605Smrg
2265b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2266b8e80941Smrg
2267848b8605Smrg   _EGL_CHECK_DISPLAY(disp, NULL, drv);
2268b8e80941Smrg   if (!disp->Extensions.WL_create_wayland_buffer_from_image)
2269b8e80941Smrg      RETURN_EGL_EVAL(disp, NULL);
2270848b8605Smrg
2271848b8605Smrg   img = _eglLookupImage(image, disp);
2272848b8605Smrg
2273848b8605Smrg   if (!img)
2274848b8605Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL);
2275848b8605Smrg
2276848b8605Smrg   ret = drv->API.CreateWaylandBufferFromImageWL(drv, disp, img);
2277848b8605Smrg
2278848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
2279848b8605Smrg}
2280848b8605Smrg
2281b8e80941Smrgstatic EGLBoolean EGLAPIENTRY
2282848b8605SmrgeglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface,
2283848b8605Smrg                   EGLint x, EGLint y, EGLint width, EGLint height)
2284848b8605Smrg{
2285848b8605Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
2286848b8605Smrg   _EGLSurface *surf = _eglLookupSurface(surface, disp);
2287848b8605Smrg   _EGLDriver *drv;
2288848b8605Smrg   EGLBoolean ret;
2289848b8605Smrg
2290b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
2291b8e80941Smrg
2292848b8605Smrg   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
2293848b8605Smrg
2294848b8605Smrg   if (!disp->Extensions.NV_post_sub_buffer)
2295848b8605Smrg      RETURN_EGL_EVAL(disp, EGL_FALSE);
2296848b8605Smrg
2297848b8605Smrg   ret = drv->API.PostSubBufferNV(drv, disp, surf, x, y, width, height);
2298848b8605Smrg
2299848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
2300848b8605Smrg}
2301848b8605Smrg
2302b8e80941Smrgstatic EGLBoolean EGLAPIENTRY
2303b8e80941SmrgeglGetSyncValuesCHROMIUM(EGLDisplay dpy, EGLSurface surface,
2304848b8605Smrg                         EGLuint64KHR *ust, EGLuint64KHR *msc,
2305848b8605Smrg                         EGLuint64KHR *sbc)
2306848b8605Smrg{
2307b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
2308848b8605Smrg   _EGLSurface *surf = _eglLookupSurface(surface, disp);
2309848b8605Smrg   _EGLDriver *drv;
2310848b8605Smrg   EGLBoolean ret;
2311848b8605Smrg
2312b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
2313b8e80941Smrg
2314848b8605Smrg   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
2315848b8605Smrg   if (!disp->Extensions.CHROMIUM_sync_control)
2316848b8605Smrg      RETURN_EGL_EVAL(disp, EGL_FALSE);
2317848b8605Smrg
2318848b8605Smrg   if (!ust || !msc || !sbc)
2319848b8605Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2320848b8605Smrg
2321848b8605Smrg   ret = drv->API.GetSyncValuesCHROMIUM(disp, surf, ust, msc, sbc);
2322848b8605Smrg
2323848b8605Smrg   RETURN_EGL_EVAL(disp, ret);
2324848b8605Smrg}
2325b8e80941Smrg
2326b8e80941Smrgstatic EGLBoolean EGLAPIENTRY
2327b8e80941SmrgeglExportDMABUFImageQueryMESA(EGLDisplay dpy, EGLImage image,
2328b8e80941Smrg                              EGLint *fourcc, EGLint *nplanes,
2329b8e80941Smrg                              EGLuint64KHR *modifiers)
2330b8e80941Smrg{
2331b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
2332b8e80941Smrg   _EGLImage *img = _eglLookupImage(image, disp);
2333b8e80941Smrg   _EGLDriver *drv;
2334b8e80941Smrg   EGLBoolean ret;
2335b8e80941Smrg
2336b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
2337b8e80941Smrg
2338b8e80941Smrg   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2339b8e80941Smrg   assert(disp->Extensions.MESA_image_dma_buf_export);
2340b8e80941Smrg
2341b8e80941Smrg   if (!img)
2342b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2343b8e80941Smrg
2344b8e80941Smrg   ret = drv->API.ExportDMABUFImageQueryMESA(drv, disp, img, fourcc, nplanes,
2345b8e80941Smrg                                             modifiers);
2346b8e80941Smrg
2347b8e80941Smrg   RETURN_EGL_EVAL(disp, ret);
2348b8e80941Smrg}
2349b8e80941Smrg
2350b8e80941Smrgstatic EGLBoolean EGLAPIENTRY
2351b8e80941SmrgeglExportDMABUFImageMESA(EGLDisplay dpy, EGLImage image,
2352b8e80941Smrg                         int *fds, EGLint *strides, EGLint *offsets)
2353b8e80941Smrg{
2354b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
2355b8e80941Smrg   _EGLImage *img = _eglLookupImage(image, disp);
2356b8e80941Smrg   _EGLDriver *drv;
2357b8e80941Smrg   EGLBoolean ret;
2358b8e80941Smrg
2359b8e80941Smrg   _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
2360b8e80941Smrg
2361b8e80941Smrg   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2362b8e80941Smrg   assert(disp->Extensions.MESA_image_dma_buf_export);
2363b8e80941Smrg
2364b8e80941Smrg   if (!img)
2365b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2366b8e80941Smrg
2367b8e80941Smrg   ret = drv->API.ExportDMABUFImageMESA(drv, disp, img, fds, strides, offsets);
2368b8e80941Smrg
2369b8e80941Smrg   RETURN_EGL_EVAL(disp, ret);
2370b8e80941Smrg}
2371b8e80941Smrg
2372b8e80941Smrgstatic EGLint EGLAPIENTRY
2373b8e80941SmrgeglLabelObjectKHR(EGLDisplay dpy, EGLenum objectType, EGLObjectKHR object,
2374b8e80941Smrg                  EGLLabelKHR label)
2375b8e80941Smrg{
2376b8e80941Smrg   _EGLDisplay *disp = NULL;
2377b8e80941Smrg   _EGLResourceType type;
2378b8e80941Smrg
2379b8e80941Smrg   _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
2380b8e80941Smrg
2381b8e80941Smrg   if (objectType == EGL_OBJECT_THREAD_KHR) {
2382b8e80941Smrg      _EGLThreadInfo *t = _eglGetCurrentThread();
2383b8e80941Smrg
2384b8e80941Smrg      if (!_eglIsCurrentThreadDummy()) {
2385b8e80941Smrg         t->Label = label;
2386b8e80941Smrg         return EGL_SUCCESS;
2387b8e80941Smrg      }
2388b8e80941Smrg
2389b8e80941Smrg      RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_BAD_ALLOC);
2390b8e80941Smrg   }
2391b8e80941Smrg
2392b8e80941Smrg   disp = _eglLockDisplay(dpy);
2393b8e80941Smrg   if (disp == NULL)
2394b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_BAD_DISPLAY);
2395b8e80941Smrg
2396b8e80941Smrg   if (objectType == EGL_OBJECT_DISPLAY_KHR) {
2397b8e80941Smrg      if (dpy != (EGLDisplay) object)
2398b8e80941Smrg         RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
2399b8e80941Smrg
2400b8e80941Smrg      disp->Label = label;
2401b8e80941Smrg      RETURN_EGL_EVAL(disp, EGL_SUCCESS);
2402b8e80941Smrg   }
2403b8e80941Smrg
2404b8e80941Smrg   switch (objectType) {
2405b8e80941Smrg      case EGL_OBJECT_CONTEXT_KHR:
2406b8e80941Smrg         type = _EGL_RESOURCE_CONTEXT;
2407b8e80941Smrg         break;
2408b8e80941Smrg      case EGL_OBJECT_SURFACE_KHR:
2409b8e80941Smrg         type = _EGL_RESOURCE_SURFACE;
2410b8e80941Smrg         break;
2411b8e80941Smrg      case EGL_OBJECT_IMAGE_KHR:
2412b8e80941Smrg         type = _EGL_RESOURCE_IMAGE;
2413b8e80941Smrg         break;
2414b8e80941Smrg      case EGL_OBJECT_SYNC_KHR:
2415b8e80941Smrg         type = _EGL_RESOURCE_SYNC;
2416b8e80941Smrg         break;
2417b8e80941Smrg      case EGL_OBJECT_STREAM_KHR:
2418b8e80941Smrg      default:
2419b8e80941Smrg         RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
2420b8e80941Smrg   }
2421b8e80941Smrg
2422b8e80941Smrg   if (_eglCheckResource(object, type, disp)) {
2423b8e80941Smrg      _EGLResource *res = (_EGLResource *) object;
2424b8e80941Smrg
2425b8e80941Smrg      res->Label = label;
2426b8e80941Smrg      RETURN_EGL_EVAL(disp, EGL_SUCCESS);
2427b8e80941Smrg   }
2428b8e80941Smrg
2429b8e80941Smrg   RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
2430b8e80941Smrg}
2431b8e80941Smrg
2432b8e80941Smrgstatic EGLint EGLAPIENTRY
2433b8e80941SmrgeglDebugMessageControlKHR(EGLDEBUGPROCKHR callback,
2434b8e80941Smrg                          const EGLAttrib *attrib_list)
2435b8e80941Smrg{
2436b8e80941Smrg   unsigned int newEnabled;
2437b8e80941Smrg
2438b8e80941Smrg   _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
2439b8e80941Smrg
2440b8e80941Smrg   mtx_lock(_eglGlobal.Mutex);
2441b8e80941Smrg
2442b8e80941Smrg   newEnabled = _eglGlobal.debugTypesEnabled;
2443b8e80941Smrg   if (attrib_list != NULL) {
2444b8e80941Smrg      int i;
2445b8e80941Smrg
2446b8e80941Smrg      for (i = 0; attrib_list[i] != EGL_NONE; i += 2) {
2447b8e80941Smrg         switch (attrib_list[i]) {
2448b8e80941Smrg         case EGL_DEBUG_MSG_CRITICAL_KHR:
2449b8e80941Smrg         case EGL_DEBUG_MSG_ERROR_KHR:
2450b8e80941Smrg         case EGL_DEBUG_MSG_WARN_KHR:
2451b8e80941Smrg         case EGL_DEBUG_MSG_INFO_KHR:
2452b8e80941Smrg            if (attrib_list[i + 1])
2453b8e80941Smrg               newEnabled |= DebugBitFromType(attrib_list[i]);
2454b8e80941Smrg            else
2455b8e80941Smrg               newEnabled &= ~DebugBitFromType(attrib_list[i]);
2456b8e80941Smrg            break;
2457b8e80941Smrg         default:
2458b8e80941Smrg            // On error, set the last error code, call the current
2459b8e80941Smrg            // debug callback, and return the error code.
2460b8e80941Smrg            mtx_unlock(_eglGlobal.Mutex);
2461b8e80941Smrg            _eglReportError(EGL_BAD_ATTRIBUTE, NULL,
2462b8e80941Smrg                  "Invalid attribute 0x%04lx", (unsigned long) attrib_list[i]);
2463b8e80941Smrg            return EGL_BAD_ATTRIBUTE;
2464b8e80941Smrg         }
2465b8e80941Smrg      }
2466b8e80941Smrg   }
2467b8e80941Smrg
2468b8e80941Smrg   if (callback != NULL) {
2469b8e80941Smrg      _eglGlobal.debugCallback = callback;
2470b8e80941Smrg      _eglGlobal.debugTypesEnabled = newEnabled;
2471b8e80941Smrg   } else {
2472b8e80941Smrg      _eglGlobal.debugCallback = NULL;
2473b8e80941Smrg      _eglGlobal.debugTypesEnabled = _EGL_DEBUG_BIT_CRITICAL | _EGL_DEBUG_BIT_ERROR;
2474b8e80941Smrg   }
2475b8e80941Smrg
2476b8e80941Smrg   mtx_unlock(_eglGlobal.Mutex);
2477b8e80941Smrg   return EGL_SUCCESS;
2478b8e80941Smrg}
2479b8e80941Smrg
2480b8e80941Smrgstatic EGLBoolean EGLAPIENTRY
2481b8e80941SmrgeglQueryDebugKHR(EGLint attribute, EGLAttrib *value)
2482b8e80941Smrg{
2483b8e80941Smrg   _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
2484b8e80941Smrg
2485b8e80941Smrg   mtx_lock(_eglGlobal.Mutex);
2486b8e80941Smrg
2487b8e80941Smrg   switch (attribute) {
2488b8e80941Smrg   case EGL_DEBUG_MSG_CRITICAL_KHR:
2489b8e80941Smrg   case EGL_DEBUG_MSG_ERROR_KHR:
2490b8e80941Smrg   case EGL_DEBUG_MSG_WARN_KHR:
2491b8e80941Smrg   case EGL_DEBUG_MSG_INFO_KHR:
2492b8e80941Smrg      if (_eglGlobal.debugTypesEnabled & DebugBitFromType(attribute))
2493b8e80941Smrg         *value = EGL_TRUE;
2494b8e80941Smrg      else
2495b8e80941Smrg         *value = EGL_FALSE;
2496b8e80941Smrg      break;
2497b8e80941Smrg   case EGL_DEBUG_CALLBACK_KHR:
2498b8e80941Smrg      *value = (EGLAttrib) _eglGlobal.debugCallback;
2499b8e80941Smrg      break;
2500b8e80941Smrg   default:
2501b8e80941Smrg      mtx_unlock(_eglGlobal.Mutex);
2502b8e80941Smrg      _eglReportError(EGL_BAD_ATTRIBUTE, NULL,
2503b8e80941Smrg                      "Invalid attribute 0x%04lx", (unsigned long) attribute);
2504b8e80941Smrg      return EGL_FALSE;
2505b8e80941Smrg   }
2506b8e80941Smrg
2507b8e80941Smrg   mtx_unlock(_eglGlobal.Mutex);
2508b8e80941Smrg   return EGL_TRUE;
2509b8e80941Smrg}
2510b8e80941Smrg
2511b8e80941Smrgstatic int
2512b8e80941Smrg_eglFunctionCompare(const void *key, const void *elem)
2513b8e80941Smrg{
2514b8e80941Smrg   const char *procname = key;
2515b8e80941Smrg   const struct _egl_entrypoint *entrypoint = elem;
2516b8e80941Smrg   return strcmp(procname, entrypoint->name);
2517b8e80941Smrg}
2518b8e80941Smrg
2519b8e80941Smrgstatic EGLBoolean EGLAPIENTRY
2520b8e80941SmrgeglQueryDmaBufFormatsEXT(EGLDisplay dpy, EGLint max_formats,
2521b8e80941Smrg                         EGLint *formats, EGLint *num_formats)
2522b8e80941Smrg{
2523b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
2524b8e80941Smrg   _EGLDriver *drv;
2525b8e80941Smrg   EGLBoolean ret;
2526b8e80941Smrg
2527b8e80941Smrg   _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2528b8e80941Smrg
2529b8e80941Smrg   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2530b8e80941Smrg
2531b8e80941Smrg   ret = drv->API.QueryDmaBufFormatsEXT(drv, disp, max_formats, formats,
2532b8e80941Smrg                                        num_formats);
2533b8e80941Smrg
2534b8e80941Smrg   RETURN_EGL_EVAL(disp, ret);
2535b8e80941Smrg}
2536b8e80941Smrg
2537b8e80941Smrgstatic EGLBoolean EGLAPIENTRY
2538b8e80941SmrgeglQueryDmaBufModifiersEXT(EGLDisplay dpy, EGLint format, EGLint max_modifiers,
2539b8e80941Smrg                           EGLuint64KHR *modifiers, EGLBoolean *external_only,
2540b8e80941Smrg                           EGLint *num_modifiers)
2541b8e80941Smrg{
2542b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
2543b8e80941Smrg   _EGLDriver *drv;
2544b8e80941Smrg   EGLBoolean ret;
2545b8e80941Smrg
2546b8e80941Smrg   _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2547b8e80941Smrg
2548b8e80941Smrg   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2549b8e80941Smrg
2550b8e80941Smrg   ret = drv->API.QueryDmaBufModifiersEXT(drv, disp, format, max_modifiers,
2551b8e80941Smrg                                          modifiers, external_only,
2552b8e80941Smrg                                          num_modifiers);
2553b8e80941Smrg
2554b8e80941Smrg   RETURN_EGL_EVAL(disp, ret);
2555b8e80941Smrg}
2556b8e80941Smrg
2557b8e80941Smrgstatic void EGLAPIENTRY
2558b8e80941SmrgeglSetBlobCacheFuncsANDROID(EGLDisplay *dpy, EGLSetBlobFuncANDROID set,
2559b8e80941Smrg                            EGLGetBlobFuncANDROID get)
2560b8e80941Smrg{
2561b8e80941Smrg   /* This function does not return anything so we cannot
2562b8e80941Smrg    * utilize the helper macros _EGL_FUNC_START or _EGL_CHECK_DISPLAY.
2563b8e80941Smrg    */
2564b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
2565b8e80941Smrg   if (!_eglSetFuncName(__func__, disp, EGL_OBJECT_DISPLAY_KHR, NULL)) {
2566b8e80941Smrg      if (disp)
2567b8e80941Smrg         _eglUnlockDisplay(disp);
2568b8e80941Smrg      return;
2569b8e80941Smrg   }
2570b8e80941Smrg
2571b8e80941Smrg   _EGLDriver *drv = _eglCheckDisplay(disp, __func__);
2572b8e80941Smrg   if (!drv) {
2573b8e80941Smrg      if (disp)
2574b8e80941Smrg         _eglUnlockDisplay(disp);
2575b8e80941Smrg      return;
2576b8e80941Smrg   }
2577b8e80941Smrg
2578b8e80941Smrg   if (!set || !get) {
2579b8e80941Smrg      _eglError(EGL_BAD_PARAMETER,
2580b8e80941Smrg                "eglSetBlobCacheFuncsANDROID: NULL handler given");
2581b8e80941Smrg      _eglUnlockDisplay(disp);
2582b8e80941Smrg      return;
2583b8e80941Smrg   }
2584b8e80941Smrg
2585b8e80941Smrg   if (disp->BlobCacheSet) {
2586b8e80941Smrg      _eglError(EGL_BAD_PARAMETER,
2587b8e80941Smrg                "eglSetBlobCacheFuncsANDROID: functions already set");
2588b8e80941Smrg      _eglUnlockDisplay(disp);
2589b8e80941Smrg      return;
2590b8e80941Smrg   }
2591b8e80941Smrg
2592b8e80941Smrg   disp->BlobCacheSet = set;
2593b8e80941Smrg   disp->BlobCacheGet = get;
2594b8e80941Smrg
2595b8e80941Smrg   drv->API.SetBlobCacheFuncsANDROID(drv, disp, set, get);
2596b8e80941Smrg
2597b8e80941Smrg   _eglUnlockDisplay(disp);
2598b8e80941Smrg}
2599b8e80941Smrg
2600b8e80941Smrgstatic EGLBoolean EGLAPIENTRY
2601b8e80941SmrgeglQueryDeviceAttribEXT(EGLDeviceEXT device,
2602b8e80941Smrg                        EGLint attribute,
2603b8e80941Smrg                        EGLAttrib *value)
2604b8e80941Smrg{
2605b8e80941Smrg   _EGLDevice *dev = _eglLookupDevice(device);
2606b8e80941Smrg   EGLBoolean ret;
2607b8e80941Smrg
2608b8e80941Smrg   _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2609b8e80941Smrg   if (!dev)
2610b8e80941Smrg      RETURN_EGL_ERROR(NULL, EGL_BAD_DEVICE_EXT, EGL_FALSE);
2611b8e80941Smrg
2612b8e80941Smrg   ret = _eglQueryDeviceAttribEXT(dev, attribute, value);
2613b8e80941Smrg   RETURN_EGL_EVAL(NULL, ret);
2614b8e80941Smrg}
2615b8e80941Smrg
2616b8e80941Smrgstatic const char * EGLAPIENTRY
2617b8e80941SmrgeglQueryDeviceStringEXT(EGLDeviceEXT device,
2618b8e80941Smrg                        EGLint name)
2619b8e80941Smrg{
2620b8e80941Smrg   _EGLDevice *dev = _eglLookupDevice(device);
2621b8e80941Smrg
2622b8e80941Smrg   _EGL_FUNC_START(NULL, EGL_NONE, NULL, NULL);
2623b8e80941Smrg   if (!dev)
2624b8e80941Smrg      RETURN_EGL_ERROR(NULL, EGL_BAD_DEVICE_EXT, NULL);
2625b8e80941Smrg
2626b8e80941Smrg   RETURN_EGL_EVAL(NULL, _eglQueryDeviceStringEXT(dev, name));
2627b8e80941Smrg}
2628b8e80941Smrg
2629b8e80941Smrgstatic EGLBoolean EGLAPIENTRY
2630b8e80941SmrgeglQueryDevicesEXT(EGLint max_devices,
2631b8e80941Smrg                   EGLDeviceEXT *devices,
2632b8e80941Smrg                   EGLint *num_devices)
2633b8e80941Smrg{
2634b8e80941Smrg   EGLBoolean ret;
2635b8e80941Smrg
2636b8e80941Smrg   _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2637b8e80941Smrg   ret = _eglQueryDevicesEXT(max_devices, (_EGLDevice **) devices,
2638b8e80941Smrg                             num_devices);
2639b8e80941Smrg   RETURN_EGL_EVAL(NULL, ret);
2640b8e80941Smrg}
2641b8e80941Smrg
2642b8e80941Smrgstatic EGLBoolean EGLAPIENTRY
2643b8e80941SmrgeglQueryDisplayAttribEXT(EGLDisplay dpy,
2644b8e80941Smrg                         EGLint attribute,
2645b8e80941Smrg                         EGLAttrib *value)
2646b8e80941Smrg{
2647b8e80941Smrg   _EGLDisplay *disp = _eglLockDisplay(dpy);
2648b8e80941Smrg   _EGLDriver *drv;
2649b8e80941Smrg
2650b8e80941Smrg   _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2651b8e80941Smrg   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2652b8e80941Smrg
2653b8e80941Smrg   switch (attribute) {
2654b8e80941Smrg   case EGL_DEVICE_EXT:
2655b8e80941Smrg      *value = (EGLAttrib) disp->Device;
2656b8e80941Smrg      break;
2657b8e80941Smrg   default:
2658b8e80941Smrg      RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_FALSE);
2659b8e80941Smrg   }
2660b8e80941Smrg   RETURN_EGL_SUCCESS(disp, EGL_TRUE);
2661b8e80941Smrg}
2662b8e80941Smrg
2663b8e80941Smrgstatic char * EGLAPIENTRY
2664b8e80941SmrgeglGetDisplayDriverConfig(EGLDisplay dpy)
2665b8e80941Smrg{
2666b8e80941Smrg    _EGLDisplay *disp = _eglLockDisplay(dpy);
2667b8e80941Smrg    _EGLDriver *drv;
2668b8e80941Smrg    char *ret;
2669b8e80941Smrg
2670b8e80941Smrg    _EGL_FUNC_START(disp, EGL_NONE, NULL, NULL);
2671b8e80941Smrg    _EGL_CHECK_DISPLAY(disp, NULL, drv);
2672b8e80941Smrg
2673b8e80941Smrg    assert(disp->Extensions.MESA_query_driver);
2674b8e80941Smrg
2675b8e80941Smrg    ret = drv->API.QueryDriverConfig(disp);
2676b8e80941Smrg    RETURN_EGL_EVAL(disp, ret);
2677b8e80941Smrg}
2678b8e80941Smrg
2679b8e80941Smrgstatic const char * EGLAPIENTRY
2680b8e80941SmrgeglGetDisplayDriverName(EGLDisplay dpy)
2681b8e80941Smrg{
2682b8e80941Smrg    _EGLDisplay *disp = _eglLockDisplay(dpy);
2683b8e80941Smrg    _EGLDriver *drv;
2684b8e80941Smrg    const char *ret;
2685b8e80941Smrg
2686b8e80941Smrg    _EGL_FUNC_START(disp, EGL_NONE, NULL, NULL);
2687b8e80941Smrg    _EGL_CHECK_DISPLAY(disp, NULL, drv);
2688b8e80941Smrg
2689b8e80941Smrg    assert(disp->Extensions.MESA_query_driver);
2690b8e80941Smrg
2691b8e80941Smrg    ret = drv->API.QueryDriverName(disp);
2692b8e80941Smrg    RETURN_EGL_EVAL(disp, ret);
2693b8e80941Smrg}
2694b8e80941Smrg
2695b8e80941Smrg__eglMustCastToProperFunctionPointerType EGLAPIENTRY
2696b8e80941SmrgeglGetProcAddress(const char *procname)
2697b8e80941Smrg{
2698b8e80941Smrg   static const struct _egl_entrypoint egl_functions[] = {
2699b8e80941Smrg#define EGL_ENTRYPOINT(f) { .name = #f, .function = (_EGLProc) f },
2700b8e80941Smrg#include "eglentrypoint.h"
2701b8e80941Smrg#undef EGL_ENTRYPOINT
2702b8e80941Smrg   };
2703b8e80941Smrg   _EGLProc ret = NULL;
2704b8e80941Smrg
2705b8e80941Smrg   if (!procname)
2706b8e80941Smrg      RETURN_EGL_SUCCESS(NULL, NULL);
2707b8e80941Smrg
2708b8e80941Smrg   _EGL_FUNC_START(NULL, EGL_NONE, NULL, NULL);
2709b8e80941Smrg
2710b8e80941Smrg   if (strncmp(procname, "egl", 3) == 0) {
2711b8e80941Smrg      const struct _egl_entrypoint *entrypoint =
2712b8e80941Smrg         bsearch(procname,
2713b8e80941Smrg                 egl_functions, ARRAY_SIZE(egl_functions),
2714b8e80941Smrg                 sizeof(egl_functions[0]),
2715b8e80941Smrg                 _eglFunctionCompare);
2716b8e80941Smrg      if (entrypoint)
2717b8e80941Smrg         ret = entrypoint->function;
2718b8e80941Smrg   }
2719b8e80941Smrg
2720b8e80941Smrg   if (!ret)
2721b8e80941Smrg      ret = _eglGetDriverProc(procname);
2722b8e80941Smrg
2723b8e80941Smrg   RETURN_EGL_SUCCESS(NULL, ret);
2724b8e80941Smrg}
2725b8e80941Smrg
2726b8e80941Smrgstatic int
2727b8e80941Smrg_eglLockDisplayInterop(EGLDisplay dpy, EGLContext context,
2728b8e80941Smrg                       _EGLDisplay **disp, _EGLDriver **drv,
2729b8e80941Smrg                       _EGLContext **ctx)
2730b8e80941Smrg{
2731b8e80941Smrg
2732b8e80941Smrg   *disp = _eglLockDisplay(dpy);
2733b8e80941Smrg   if (!*disp || !(*disp)->Initialized || !(*disp)->Driver) {
2734b8e80941Smrg      if (*disp)
2735b8e80941Smrg         _eglUnlockDisplay(*disp);
2736b8e80941Smrg      return MESA_GLINTEROP_INVALID_DISPLAY;
2737b8e80941Smrg   }
2738b8e80941Smrg
2739b8e80941Smrg   *drv = (*disp)->Driver;
2740b8e80941Smrg
2741b8e80941Smrg   *ctx = _eglLookupContext(context, *disp);
2742b8e80941Smrg   if (!*ctx ||
2743b8e80941Smrg       ((*ctx)->ClientAPI != EGL_OPENGL_API &&
2744b8e80941Smrg        (*ctx)->ClientAPI != EGL_OPENGL_ES_API)) {
2745b8e80941Smrg      _eglUnlockDisplay(*disp);
2746b8e80941Smrg      return MESA_GLINTEROP_INVALID_CONTEXT;
2747b8e80941Smrg   }
2748b8e80941Smrg
2749b8e80941Smrg   return MESA_GLINTEROP_SUCCESS;
2750b8e80941Smrg}
2751b8e80941Smrg
2752b8e80941SmrgPUBLIC int
2753b8e80941SmrgMesaGLInteropEGLQueryDeviceInfo(EGLDisplay dpy, EGLContext context,
2754b8e80941Smrg                                struct mesa_glinterop_device_info *out)
2755b8e80941Smrg{
2756b8e80941Smrg   _EGLDisplay *disp;
2757b8e80941Smrg   _EGLDriver *drv;
2758b8e80941Smrg   _EGLContext *ctx;
2759b8e80941Smrg   int ret;
2760b8e80941Smrg
2761b8e80941Smrg   ret = _eglLockDisplayInterop(dpy, context, &disp, &drv, &ctx);
2762b8e80941Smrg   if (ret != MESA_GLINTEROP_SUCCESS)
2763b8e80941Smrg      return ret;
2764b8e80941Smrg
2765b8e80941Smrg   if (drv->API.GLInteropQueryDeviceInfo)
2766b8e80941Smrg      ret = drv->API.GLInteropQueryDeviceInfo(disp, ctx, out);
2767b8e80941Smrg   else
2768b8e80941Smrg      ret = MESA_GLINTEROP_UNSUPPORTED;
2769b8e80941Smrg
2770b8e80941Smrg   _eglUnlockDisplay(disp);
2771b8e80941Smrg   return ret;
2772b8e80941Smrg}
2773b8e80941Smrg
2774b8e80941SmrgPUBLIC int
2775b8e80941SmrgMesaGLInteropEGLExportObject(EGLDisplay dpy, EGLContext context,
2776b8e80941Smrg                             struct mesa_glinterop_export_in *in,
2777b8e80941Smrg                             struct mesa_glinterop_export_out *out)
2778b8e80941Smrg{
2779b8e80941Smrg   _EGLDisplay *disp;
2780b8e80941Smrg   _EGLDriver *drv;
2781b8e80941Smrg   _EGLContext *ctx;
2782b8e80941Smrg   int ret;
2783b8e80941Smrg
2784b8e80941Smrg   ret = _eglLockDisplayInterop(dpy, context, &disp, &drv, &ctx);
2785b8e80941Smrg   if (ret != MESA_GLINTEROP_SUCCESS)
2786b8e80941Smrg      return ret;
2787b8e80941Smrg
2788b8e80941Smrg   if (drv->API.GLInteropExportObject)
2789b8e80941Smrg      ret = drv->API.GLInteropExportObject(disp, ctx, in, out);
2790b8e80941Smrg   else
2791b8e80941Smrg      ret = MESA_GLINTEROP_UNSUPPORTED;
2792b8e80941Smrg
2793b8e80941Smrg   _eglUnlockDisplay(disp);
2794b8e80941Smrg   return ret;
2795b8e80941Smrg}
2796