eglapi.c revision b50703aea55450e04bcd8154335774786e0f253b
1/**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
5 * Copyright 2010-2011 LunarG, Inc.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sub license, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
18 * of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 *
28 **************************************************************************/
29
30
31/**
32 * Public EGL API entrypoints
33 *
34 * Generally, we use the EGLDisplay parameter as a key to lookup the
35 * appropriate device driver handle, then jump though the driver's
36 * dispatch table to handle the function.
37 *
38 * That allows us the option of supporting multiple, simultaneous,
39 * heterogeneous hardware devices in the future.
40 *
41 * The EGLDisplay, EGLConfig, EGLContext and EGLSurface types are
42 * opaque handles. Internal objects are linked to a display to
43 * create the handles.
44 *
45 * For each public API entry point, the opaque handles are looked up
46 * before being dispatched to the drivers.  When it fails to look up
47 * a handle, one of
48 *
49 * EGL_BAD_DISPLAY
50 * EGL_BAD_CONFIG
51 * EGL_BAD_CONTEXT
52 * EGL_BAD_SURFACE
53 * EGL_BAD_SCREEN_MESA
54 * EGL_BAD_MODE_MESA
55 *
56 * is generated and the driver function is not called. An
57 * uninitialized EGLDisplay has no driver associated with it. When
58 * such display is detected,
59 *
60 * EGL_NOT_INITIALIZED
61 *
62 * is generated.
63 *
64 * Some of the entry points use current display, context, or surface
65 * implicitly.  For such entry points, the implicit objects are also
66 * checked before calling the driver function.  Other than the
67 * errors listed above,
68 *
69 * EGL_BAD_CURRENT_SURFACE
70 *
71 * may also be generated.
72 *
73 * Notes on naming conventions:
74 *
75 * eglFooBar    - public EGL function
76 * EGL_FOO_BAR  - public EGL token
77 * EGLDatatype  - public EGL datatype
78 *
79 * _eglFooBar   - private EGL function
80 * _EGLDatatype - private EGL datatype, typedef'd struct
81 * _egl_struct  - private EGL struct, non-typedef'd
82 *
83 */
84
85
86#include <stdio.h>
87#include <stdlib.h>
88#include <string.h>
89
90#include "eglcontext.h"
91#include "egldisplay.h"
92#include "egltypedefs.h"
93#include "eglcurrent.h"
94#include "egldriver.h"
95#include "eglsurface.h"
96#include "eglconfig.h"
97#include "eglscreen.h"
98#include "eglmode.h"
99#include "eglimage.h"
100#include "eglsync.h"
101
102
103/**
104 * Macros to help return an API entrypoint.
105 *
106 * These macros will unlock the display and record the error code.
107 */
108#define RETURN_EGL_ERROR(disp, err, ret)        \
109   do {                                         \
110      if (disp)                                 \
111         _eglUnlockDisplay(disp);               \
112      /* EGL error codes are non-zero */        \
113      if (err)                                  \
114         _eglError(err, __FUNCTION__);          \
115      return ret;                               \
116   } while (0)
117
118#define RETURN_EGL_SUCCESS(disp, ret) \
119   RETURN_EGL_ERROR(disp, EGL_SUCCESS, ret)
120
121/* record EGL_SUCCESS only when ret evaluates to true */
122#define RETURN_EGL_EVAL(disp, ret) \
123   RETURN_EGL_ERROR(disp, (ret) ? EGL_SUCCESS : 0, ret)
124
125
126/*
127 * A bunch of macros and checks to simplify error checking.
128 */
129
130#define _EGL_CHECK_DISPLAY(disp, ret, drv)         \
131   do {                                            \
132      drv = _eglCheckDisplay(disp, __FUNCTION__);  \
133      if (!drv)                                    \
134         RETURN_EGL_ERROR(disp, 0, ret);           \
135   } while (0)
136
137#define _EGL_CHECK_OBJECT(disp, type, obj, ret, drv)      \
138   do {                                                   \
139      drv = _eglCheck ## type(disp, obj, __FUNCTION__);   \
140      if (!drv)                                           \
141         RETURN_EGL_ERROR(disp, 0, ret);                  \
142   } while (0)
143
144#define _EGL_CHECK_SURFACE(disp, surf, ret, drv) \
145   _EGL_CHECK_OBJECT(disp, Surface, surf, ret, drv)
146
147#define _EGL_CHECK_CONTEXT(disp, context, ret, drv) \
148   _EGL_CHECK_OBJECT(disp, Context, context, ret, drv)
149
150#define _EGL_CHECK_CONFIG(disp, conf, ret, drv) \
151   _EGL_CHECK_OBJECT(disp, Config, conf, ret, drv)
152
153#define _EGL_CHECK_SCREEN(disp, scrn, ret, drv) \
154   _EGL_CHECK_OBJECT(disp, Screen, scrn, ret, drv)
155
156#define _EGL_CHECK_MODE(disp, m, ret, drv) \
157   _EGL_CHECK_OBJECT(disp, Mode, m, ret, drv)
158
159#define _EGL_CHECK_SYNC(disp, s, ret, drv) \
160   _EGL_CHECK_OBJECT(disp, Sync, s, ret, drv)
161
162
163static INLINE _EGLDriver *
164_eglCheckDisplay(_EGLDisplay *disp, const char *msg)
165{
166   if (!disp) {
167      _eglError(EGL_BAD_DISPLAY, msg);
168      return NULL;
169   }
170   if (!disp->Initialized) {
171      _eglError(EGL_NOT_INITIALIZED, msg);
172      return NULL;
173   }
174   return disp->Driver;
175}
176
177
178static INLINE _EGLDriver *
179_eglCheckSurface(_EGLDisplay *disp, _EGLSurface *surf, const char *msg)
180{
181   _EGLDriver *drv = _eglCheckDisplay(disp, msg);
182   if (!drv)
183      return NULL;
184   if (!surf) {
185      _eglError(EGL_BAD_SURFACE, msg);
186      return NULL;
187   }
188   return drv;
189}
190
191
192static INLINE _EGLDriver *
193_eglCheckContext(_EGLDisplay *disp, _EGLContext *context, const char *msg)
194{
195   _EGLDriver *drv = _eglCheckDisplay(disp, msg);
196   if (!drv)
197      return NULL;
198   if (!context) {
199      _eglError(EGL_BAD_CONTEXT, msg);
200      return NULL;
201   }
202   return drv;
203}
204
205
206static INLINE _EGLDriver *
207_eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg)
208{
209   _EGLDriver *drv = _eglCheckDisplay(disp, msg);
210   if (!drv)
211      return NULL;
212   if (!conf) {
213      _eglError(EGL_BAD_CONFIG, msg);
214      return NULL;
215   }
216   return drv;
217}
218
219
220static INLINE _EGLDriver *
221_eglCheckSync(_EGLDisplay *disp, _EGLSync *s, const char *msg)
222{
223   _EGLDriver *drv = _eglCheckDisplay(disp, msg);
224   if (!drv)
225      return NULL;
226   if (!s) {
227      _eglError(EGL_BAD_PARAMETER, msg);
228      return NULL;
229   }
230   return drv;
231}
232
233
234#ifdef EGL_MESA_screen_surface
235
236
237static INLINE _EGLDriver *
238_eglCheckScreen(_EGLDisplay *disp, _EGLScreen *scrn, const char *msg)
239{
240   _EGLDriver *drv = _eglCheckDisplay(disp, msg);
241   if (!drv)
242      return NULL;
243   if (!scrn) {
244      _eglError(EGL_BAD_SCREEN_MESA, msg);
245      return NULL;
246   }
247   return drv;
248}
249
250
251static INLINE _EGLDriver *
252_eglCheckMode(_EGLDisplay *disp, _EGLMode *m, const char *msg)
253{
254   _EGLDriver *drv = _eglCheckDisplay(disp, msg);
255   if (!drv)
256      return NULL;
257   if (!m) {
258      _eglError(EGL_BAD_MODE_MESA, msg);
259      return NULL;
260   }
261   return drv;
262}
263
264
265#endif /* EGL_MESA_screen_surface */
266
267
268/**
269 * Lookup and lock a display.
270 */
271static INLINE _EGLDisplay *
272_eglLockDisplay(EGLDisplay display)
273{
274   _EGLDisplay *dpy = _eglLookupDisplay(display);
275   if (dpy)
276      _eglLockMutex(&dpy->Mutex);
277   return dpy;
278}
279
280
281/**
282 * Unlock a display.
283 */
284static INLINE void
285_eglUnlockDisplay(_EGLDisplay *dpy)
286{
287   _eglUnlockMutex(&dpy->Mutex);
288}
289
290
291/**
292 * This is typically the first EGL function that an application calls.
293 * It associates a private _EGLDisplay object to the native display.
294 */
295EGLDisplay EGLAPIENTRY
296eglGetDisplay(EGLNativeDisplayType nativeDisplay)
297{
298   _EGLPlatformType plat = _eglGetNativePlatform(nativeDisplay);
299   _EGLDisplay *dpy = _eglFindDisplay(plat, (void *) nativeDisplay);
300   return _eglGetDisplayHandle(dpy);
301}
302
303
304/**
305 * This is typically the second EGL function that an application calls.
306 * Here we load/initialize the actual hardware driver.
307 */
308EGLBoolean EGLAPIENTRY
309eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
310{
311   _EGLDisplay *disp = _eglLockDisplay(dpy);
312
313   if (!disp)
314      RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
315
316   if (!disp->Initialized) {
317      if (!_eglMatchDriver(disp, EGL_FALSE))
318         RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
319
320      /* limit to APIs supported by core */
321      disp->ClientAPIs &= _EGL_API_ALL_BITS;
322   }
323
324   /* Update applications version of major and minor if not NULL */
325   if ((major != NULL) && (minor != NULL)) {
326      *major = disp->VersionMajor;
327      *minor = disp->VersionMinor;
328   }
329
330   RETURN_EGL_SUCCESS(disp, EGL_TRUE);
331}
332
333
334EGLBoolean EGLAPIENTRY
335eglTerminate(EGLDisplay dpy)
336{
337   _EGLDisplay *disp = _eglLockDisplay(dpy);
338
339   if (!disp)
340      RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
341
342   if (disp->Initialized) {
343      _EGLDriver *drv = disp->Driver;
344
345      drv->API.Terminate(drv, disp);
346      /* do not reset disp->Driver */
347      disp->Initialized = EGL_FALSE;
348   }
349
350   RETURN_EGL_SUCCESS(disp, EGL_TRUE);
351}
352
353
354const char * EGLAPIENTRY
355eglQueryString(EGLDisplay dpy, EGLint name)
356{
357   _EGLDisplay *disp = _eglLockDisplay(dpy);
358   _EGLDriver *drv;
359   const char *ret;
360
361   _EGL_CHECK_DISPLAY(disp, NULL, drv);
362   ret = drv->API.QueryString(drv, disp, name);
363
364   RETURN_EGL_EVAL(disp, ret);
365}
366
367
368EGLBoolean EGLAPIENTRY
369eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
370              EGLint config_size, EGLint *num_config)
371{
372   _EGLDisplay *disp = _eglLockDisplay(dpy);
373   _EGLDriver *drv;
374   EGLBoolean ret;
375
376   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
377   ret = drv->API.GetConfigs(drv, disp, configs, config_size, num_config);
378
379   RETURN_EGL_EVAL(disp, ret);
380}
381
382
383EGLBoolean EGLAPIENTRY
384eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs,
385                EGLint config_size, EGLint *num_config)
386{
387   _EGLDisplay *disp = _eglLockDisplay(dpy);
388   _EGLDriver *drv;
389   EGLBoolean ret;
390
391   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
392   ret = drv->API.ChooseConfig(drv, disp, attrib_list, configs,
393                                config_size, num_config);
394
395   RETURN_EGL_EVAL(disp, ret);
396}
397
398
399EGLBoolean EGLAPIENTRY
400eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
401                   EGLint attribute, EGLint *value)
402{
403   _EGLDisplay *disp = _eglLockDisplay(dpy);
404   _EGLConfig *conf = _eglLookupConfig(config, disp);
405   _EGLDriver *drv;
406   EGLBoolean ret;
407
408   _EGL_CHECK_CONFIG(disp, conf, EGL_FALSE, drv);
409   ret = drv->API.GetConfigAttrib(drv, disp, conf, attribute, value);
410
411   RETURN_EGL_EVAL(disp, ret);
412}
413
414
415EGLContext EGLAPIENTRY
416eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list,
417                 const EGLint *attrib_list)
418{
419   _EGLDisplay *disp = _eglLockDisplay(dpy);
420   _EGLConfig *conf = _eglLookupConfig(config, disp);
421   _EGLContext *share = _eglLookupContext(share_list, disp);
422   _EGLDriver *drv;
423   _EGLContext *context;
424   EGLContext ret;
425
426   _EGL_CHECK_DISPLAY(disp, EGL_NO_CONTEXT, drv);
427
428   if (!config) {
429      /* config may be NULL if surfaceless */
430      if (!disp->Extensions.KHR_surfaceless_context)
431         RETURN_EGL_ERROR(disp, EGL_BAD_CONFIG, EGL_NO_CONTEXT);
432   }
433
434   if (!share && share_list != EGL_NO_CONTEXT)
435      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
436
437   context = drv->API.CreateContext(drv, disp, conf, share, attrib_list);
438   ret = (context) ? _eglLinkContext(context) : EGL_NO_CONTEXT;
439
440   RETURN_EGL_EVAL(disp, ret);
441}
442
443
444EGLBoolean EGLAPIENTRY
445eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
446{
447   _EGLDisplay *disp = _eglLockDisplay(dpy);
448   _EGLContext *context = _eglLookupContext(ctx, disp);
449   _EGLDriver *drv;
450   EGLBoolean ret;
451
452   _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv);
453   _eglUnlinkContext(context);
454   ret = drv->API.DestroyContext(drv, disp, context);
455
456   RETURN_EGL_EVAL(disp, ret);
457}
458
459
460EGLBoolean EGLAPIENTRY
461eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
462               EGLContext ctx)
463{
464   _EGLDisplay *disp = _eglLockDisplay(dpy);
465   _EGLContext *context = _eglLookupContext(ctx, disp);
466   _EGLSurface *draw_surf = _eglLookupSurface(draw, disp);
467   _EGLSurface *read_surf = _eglLookupSurface(read, disp);
468   _EGLDriver *drv;
469   EGLBoolean ret;
470
471   if (!disp)
472      RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
473   drv = disp->Driver;
474
475   /* display is allowed to be uninitialized under certain condition */
476   if (!disp->Initialized) {
477      if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE ||
478          ctx != EGL_NO_CONTEXT)
479         RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
480   }
481   if (!drv)
482      RETURN_EGL_SUCCESS(disp, EGL_TRUE);
483
484   if (!context && ctx != EGL_NO_CONTEXT)
485      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
486   if (!draw_surf || !read_surf) {
487      /* surfaces may be NULL if surfaceless */
488      if (!disp->Extensions.KHR_surfaceless_context)
489         RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
490
491      if ((!draw_surf && draw != EGL_NO_SURFACE) ||
492          (!read_surf && read != EGL_NO_SURFACE))
493         RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
494      if (draw_surf || read_surf)
495         RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
496   }
497
498   ret = drv->API.MakeCurrent(drv, disp, draw_surf, read_surf, context);
499
500   RETURN_EGL_EVAL(disp, ret);
501}
502
503
504EGLBoolean EGLAPIENTRY
505eglQueryContext(EGLDisplay dpy, EGLContext ctx,
506                EGLint attribute, EGLint *value)
507{
508   _EGLDisplay *disp = _eglLockDisplay(dpy);
509   _EGLContext *context = _eglLookupContext(ctx, disp);
510   _EGLDriver *drv;
511   EGLBoolean ret;
512
513   _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv);
514   ret = drv->API.QueryContext(drv, disp, context, attribute, value);
515
516   RETURN_EGL_EVAL(disp, ret);
517}
518
519
520EGLSurface EGLAPIENTRY
521eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
522                       EGLNativeWindowType window, const EGLint *attrib_list)
523{
524   _EGLDisplay *disp = _eglLockDisplay(dpy);
525   _EGLConfig *conf = _eglLookupConfig(config, disp);
526   _EGLDriver *drv;
527   _EGLSurface *surf;
528   EGLSurface ret;
529
530   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
531   if (disp->Platform != _eglGetNativePlatform(disp->PlatformDisplay))
532      RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
533
534   surf = drv->API.CreateWindowSurface(drv, disp, conf, window, attrib_list);
535   ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
536
537   RETURN_EGL_EVAL(disp, ret);
538}
539
540
541EGLSurface EGLAPIENTRY
542eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
543                       EGLNativePixmapType pixmap, const EGLint *attrib_list)
544{
545   _EGLDisplay *disp = _eglLockDisplay(dpy);
546   _EGLConfig *conf = _eglLookupConfig(config, disp);
547   _EGLDriver *drv;
548   _EGLSurface *surf;
549   EGLSurface ret;
550
551   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
552   if (disp->Platform != _eglGetNativePlatform(disp->PlatformDisplay))
553      RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
554
555   surf = drv->API.CreatePixmapSurface(drv, disp, conf, pixmap, attrib_list);
556   ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
557
558   RETURN_EGL_EVAL(disp, ret);
559}
560
561
562EGLSurface EGLAPIENTRY
563eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
564                        const EGLint *attrib_list)
565{
566   _EGLDisplay *disp = _eglLockDisplay(dpy);
567   _EGLConfig *conf = _eglLookupConfig(config, disp);
568   _EGLDriver *drv;
569   _EGLSurface *surf;
570   EGLSurface ret;
571
572   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
573
574   surf = drv->API.CreatePbufferSurface(drv, disp, conf, attrib_list);
575   ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
576
577   RETURN_EGL_EVAL(disp, ret);
578}
579
580
581EGLBoolean EGLAPIENTRY
582eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
583{
584   _EGLDisplay *disp = _eglLockDisplay(dpy);
585   _EGLSurface *surf = _eglLookupSurface(surface, disp);
586   _EGLDriver *drv;
587   EGLBoolean ret;
588
589   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
590   _eglUnlinkSurface(surf);
591   ret = drv->API.DestroySurface(drv, disp, surf);
592
593   RETURN_EGL_EVAL(disp, ret);
594}
595
596EGLBoolean EGLAPIENTRY
597eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
598                EGLint attribute, EGLint *value)
599{
600   _EGLDisplay *disp = _eglLockDisplay(dpy);
601   _EGLSurface *surf = _eglLookupSurface(surface, disp);
602   _EGLDriver *drv;
603   EGLBoolean ret;
604
605   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
606   ret = drv->API.QuerySurface(drv, disp, surf, attribute, value);
607
608   RETURN_EGL_EVAL(disp, ret);
609}
610
611EGLBoolean EGLAPIENTRY
612eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
613                 EGLint attribute, EGLint value)
614{
615   _EGLDisplay *disp = _eglLockDisplay(dpy);
616   _EGLSurface *surf = _eglLookupSurface(surface, disp);
617   _EGLDriver *drv;
618   EGLBoolean ret;
619
620   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
621   ret = drv->API.SurfaceAttrib(drv, disp, surf, attribute, value);
622
623   RETURN_EGL_EVAL(disp, ret);
624}
625
626
627EGLBoolean EGLAPIENTRY
628eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
629{
630   _EGLDisplay *disp = _eglLockDisplay(dpy);
631   _EGLSurface *surf = _eglLookupSurface(surface, disp);
632   _EGLDriver *drv;
633   EGLBoolean ret;
634
635   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
636   ret = drv->API.BindTexImage(drv, disp, surf, buffer);
637
638   RETURN_EGL_EVAL(disp, ret);
639}
640
641
642EGLBoolean EGLAPIENTRY
643eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
644{
645   _EGLDisplay *disp = _eglLockDisplay(dpy);
646   _EGLSurface *surf = _eglLookupSurface(surface, disp);
647   _EGLDriver *drv;
648   EGLBoolean ret;
649
650   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
651   ret = drv->API.ReleaseTexImage(drv, disp, surf, buffer);
652
653   RETURN_EGL_EVAL(disp, ret);
654}
655
656
657EGLBoolean EGLAPIENTRY
658eglSwapInterval(EGLDisplay dpy, EGLint interval)
659{
660   _EGLDisplay *disp = _eglLockDisplay(dpy);
661   _EGLContext *ctx = _eglGetCurrentContext();
662   _EGLSurface *surf;
663   _EGLDriver *drv;
664   EGLBoolean ret;
665
666   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
667
668   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
669       ctx->Resource.Display != disp)
670      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
671
672   surf = ctx->DrawSurface;
673   if (_eglGetSurfaceHandle(surf) == EGL_NO_SURFACE)
674      RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
675
676   ret = drv->API.SwapInterval(drv, disp, surf, interval);
677
678   RETURN_EGL_EVAL(disp, ret);
679}
680
681
682EGLBoolean EGLAPIENTRY
683eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
684{
685   _EGLContext *ctx = _eglGetCurrentContext();
686   _EGLDisplay *disp = _eglLockDisplay(dpy);
687   _EGLSurface *surf = _eglLookupSurface(surface, disp);
688   _EGLDriver *drv;
689   EGLBoolean ret;
690
691   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
692
693   /* surface must be bound to current context in EGL 1.4 */
694   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
695       surf != ctx->DrawSurface)
696      RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
697
698   ret = drv->API.SwapBuffers(drv, disp, surf);
699
700   RETURN_EGL_EVAL(disp, ret);
701}
702
703
704EGLBoolean EGLAPIENTRY
705eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
706{
707   _EGLDisplay *disp = _eglLockDisplay(dpy);
708   _EGLSurface *surf = _eglLookupSurface(surface, disp);
709   _EGLDriver *drv;
710   EGLBoolean ret;
711
712   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
713   if (disp->Platform != _eglGetNativePlatform(disp->PlatformDisplay))
714      RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_FALSE);
715   ret = drv->API.CopyBuffers(drv, disp, surf, target);
716
717   RETURN_EGL_EVAL(disp, ret);
718}
719
720
721EGLBoolean EGLAPIENTRY
722eglWaitClient(void)
723{
724   _EGLContext *ctx = _eglGetCurrentContext();
725   _EGLDisplay *disp;
726   _EGLDriver *drv;
727   EGLBoolean ret;
728
729   if (!ctx)
730      RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
731
732   disp = ctx->Resource.Display;
733   _eglLockMutex(&disp->Mutex);
734
735   /* let bad current context imply bad current surface */
736   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
737       _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
738      RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
739
740   /* a valid current context implies an initialized current display */
741   assert(disp->Initialized);
742   drv = disp->Driver;
743   ret = drv->API.WaitClient(drv, disp, ctx);
744
745   RETURN_EGL_EVAL(disp, ret);
746}
747
748
749EGLBoolean EGLAPIENTRY
750eglWaitGL(void)
751{
752   _EGLThreadInfo *t = _eglGetCurrentThread();
753   EGLint api_index = t->CurrentAPIIndex;
754   EGLint es_index = _eglConvertApiToIndex(EGL_OPENGL_ES_API);
755   EGLBoolean ret;
756
757   if (api_index != es_index && _eglIsCurrentThreadDummy())
758      RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
759
760   t->CurrentAPIIndex = es_index;
761   ret = eglWaitClient();
762   t->CurrentAPIIndex = api_index;
763   return ret;
764}
765
766
767EGLBoolean EGLAPIENTRY
768eglWaitNative(EGLint engine)
769{
770   _EGLContext *ctx = _eglGetCurrentContext();
771   _EGLDisplay *disp;
772   _EGLDriver *drv;
773   EGLBoolean ret;
774
775   if (!ctx)
776      RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
777
778   disp = ctx->Resource.Display;
779   _eglLockMutex(&disp->Mutex);
780
781   /* let bad current context imply bad current surface */
782   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
783       _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
784      RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
785
786   /* a valid current context implies an initialized current display */
787   assert(disp->Initialized);
788   drv = disp->Driver;
789   ret = drv->API.WaitNative(drv, disp, engine);
790
791   RETURN_EGL_EVAL(disp, ret);
792}
793
794
795EGLDisplay EGLAPIENTRY
796eglGetCurrentDisplay(void)
797{
798   _EGLContext *ctx = _eglGetCurrentContext();
799   EGLDisplay ret;
800
801   ret = (ctx) ? _eglGetDisplayHandle(ctx->Resource.Display) : EGL_NO_DISPLAY;
802
803   RETURN_EGL_SUCCESS(NULL, ret);
804}
805
806
807EGLContext EGLAPIENTRY
808eglGetCurrentContext(void)
809{
810   _EGLContext *ctx = _eglGetCurrentContext();
811   EGLContext ret;
812
813   ret = _eglGetContextHandle(ctx);
814
815   RETURN_EGL_SUCCESS(NULL, ret);
816}
817
818
819EGLSurface EGLAPIENTRY
820eglGetCurrentSurface(EGLint readdraw)
821{
822   _EGLContext *ctx = _eglGetCurrentContext();
823   EGLint err = EGL_SUCCESS;
824   _EGLSurface *surf;
825   EGLSurface ret;
826
827   if (!ctx)
828      RETURN_EGL_SUCCESS(NULL, EGL_NO_SURFACE);
829
830   switch (readdraw) {
831   case EGL_DRAW:
832      surf = ctx->DrawSurface;
833      break;
834   case EGL_READ:
835      surf = ctx->ReadSurface;
836      break;
837   default:
838      surf = NULL;
839      err = EGL_BAD_PARAMETER;
840      break;
841   }
842
843   ret = _eglGetSurfaceHandle(surf);
844
845   RETURN_EGL_ERROR(NULL, err, ret);
846}
847
848
849EGLint EGLAPIENTRY
850eglGetError(void)
851{
852   _EGLThreadInfo *t = _eglGetCurrentThread();
853   EGLint e = t->LastError;
854   if (!_eglIsCurrentThreadDummy())
855      t->LastError = EGL_SUCCESS;
856   return e;
857}
858
859
860__eglMustCastToProperFunctionPointerType EGLAPIENTRY
861eglGetProcAddress(const char *procname)
862{
863   static const struct {
864      const char *name;
865      _EGLProc function;
866   } egl_functions[] = {
867      /* core functions should not be queryable, but, well... */
868#ifdef _EGL_GET_CORE_ADDRESSES
869      /* alphabetical order */
870      { "eglBindAPI", (_EGLProc) eglBindAPI },
871      { "eglBindTexImage", (_EGLProc) eglBindTexImage },
872      { "eglChooseConfig", (_EGLProc) eglChooseConfig },
873      { "eglCopyBuffers", (_EGLProc) eglCopyBuffers },
874      { "eglCreateContext", (_EGLProc) eglCreateContext },
875      { "eglCreatePbufferFromClientBuffer", (_EGLProc) eglCreatePbufferFromClientBuffer },
876      { "eglCreatePbufferSurface", (_EGLProc) eglCreatePbufferSurface },
877      { "eglCreatePixmapSurface", (_EGLProc) eglCreatePixmapSurface },
878      { "eglCreateWindowSurface", (_EGLProc) eglCreateWindowSurface },
879      { "eglDestroyContext", (_EGLProc) eglDestroyContext },
880      { "eglDestroySurface", (_EGLProc) eglDestroySurface },
881      { "eglGetConfigAttrib", (_EGLProc) eglGetConfigAttrib },
882      { "eglGetConfigs", (_EGLProc) eglGetConfigs },
883      { "eglGetCurrentContext", (_EGLProc) eglGetCurrentContext },
884      { "eglGetCurrentDisplay", (_EGLProc) eglGetCurrentDisplay },
885      { "eglGetCurrentSurface", (_EGLProc) eglGetCurrentSurface },
886      { "eglGetDisplay", (_EGLProc) eglGetDisplay },
887      { "eglGetError", (_EGLProc) eglGetError },
888      { "eglGetProcAddress", (_EGLProc) eglGetProcAddress },
889      { "eglInitialize", (_EGLProc) eglInitialize },
890      { "eglMakeCurrent", (_EGLProc) eglMakeCurrent },
891      { "eglQueryAPI", (_EGLProc) eglQueryAPI },
892      { "eglQueryContext", (_EGLProc) eglQueryContext },
893      { "eglQueryString", (_EGLProc) eglQueryString },
894      { "eglQuerySurface", (_EGLProc) eglQuerySurface },
895      { "eglReleaseTexImage", (_EGLProc) eglReleaseTexImage },
896      { "eglReleaseThread", (_EGLProc) eglReleaseThread },
897      { "eglSurfaceAttrib", (_EGLProc) eglSurfaceAttrib },
898      { "eglSwapBuffers", (_EGLProc) eglSwapBuffers },
899      { "eglSwapInterval", (_EGLProc) eglSwapInterval },
900      { "eglTerminate", (_EGLProc) eglTerminate },
901      { "eglWaitClient", (_EGLProc) eglWaitClient },
902      { "eglWaitGL", (_EGLProc) eglWaitGL },
903      { "eglWaitNative", (_EGLProc) eglWaitNative },
904#endif /* _EGL_GET_CORE_ADDRESSES */
905#ifdef EGL_MESA_screen_surface
906      { "eglChooseModeMESA", (_EGLProc) eglChooseModeMESA },
907      { "eglGetModesMESA", (_EGLProc) eglGetModesMESA },
908      { "eglGetModeAttribMESA", (_EGLProc) eglGetModeAttribMESA },
909      { "eglCopyContextMESA", (_EGLProc) eglCopyContextMESA },
910      { "eglGetScreensMESA", (_EGLProc) eglGetScreensMESA },
911      { "eglCreateScreenSurfaceMESA", (_EGLProc) eglCreateScreenSurfaceMESA },
912      { "eglShowScreenSurfaceMESA", (_EGLProc) eglShowScreenSurfaceMESA },
913      { "eglScreenPositionMESA", (_EGLProc) eglScreenPositionMESA },
914      { "eglQueryScreenMESA", (_EGLProc) eglQueryScreenMESA },
915      { "eglQueryScreenSurfaceMESA", (_EGLProc) eglQueryScreenSurfaceMESA },
916      { "eglQueryScreenModeMESA", (_EGLProc) eglQueryScreenModeMESA },
917      { "eglQueryModeStringMESA", (_EGLProc) eglQueryModeStringMESA },
918#endif /* EGL_MESA_screen_surface */
919#ifdef EGL_MESA_drm_display
920      { "eglGetDRMDisplayMESA", (_EGLProc) eglGetDRMDisplayMESA },
921#endif
922      { "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR },
923      { "eglDestroyImageKHR", (_EGLProc) eglDestroyImageKHR },
924      { "eglCreateSyncKHR", (_EGLProc) eglCreateSyncKHR },
925      { "eglDestroySyncKHR", (_EGLProc) eglDestroySyncKHR },
926      { "eglClientWaitSyncKHR", (_EGLProc) eglClientWaitSyncKHR },
927      { "eglSignalSyncKHR", (_EGLProc) eglSignalSyncKHR },
928      { "eglGetSyncAttribKHR", (_EGLProc) eglGetSyncAttribKHR },
929#ifdef EGL_NOK_swap_region
930      { "eglSwapBuffersRegionNOK", (_EGLProc) eglSwapBuffersRegionNOK },
931#endif
932#ifdef EGL_MESA_drm_image
933      { "eglCreateDRMImageMESA", (_EGLProc) eglCreateDRMImageMESA },
934      { "eglExportDRMImageMESA", (_EGLProc) eglExportDRMImageMESA },
935#endif
936#ifdef EGL_WL_bind_wayland_display
937      { "eglBindWaylandDisplayWL", (_EGLProc) eglBindWaylandDisplayWL },
938      { "eglUnbindWaylandDisplayWL", (_EGLProc) eglUnbindWaylandDisplayWL },
939      { "eglQueryWaylandBufferWL", (_EGLProc) eglQueryWaylandBufferWL },
940#endif
941      { "eglPostSubBufferNV", (_EGLProc) eglPostSubBufferNV },
942      { NULL, NULL }
943   };
944   EGLint i;
945   _EGLProc ret;
946
947   if (!procname)
948      RETURN_EGL_SUCCESS(NULL, NULL);
949
950   ret = NULL;
951   if (strncmp(procname, "egl", 3) == 0) {
952      for (i = 0; egl_functions[i].name; i++) {
953         if (strcmp(egl_functions[i].name, procname) == 0) {
954            ret = egl_functions[i].function;
955            break;
956         }
957      }
958   }
959   if (!ret)
960      ret = _eglGetDriverProc(procname);
961
962   RETURN_EGL_SUCCESS(NULL, ret);
963}
964
965
966#ifdef EGL_MESA_screen_surface
967
968
969/*
970 * EGL_MESA_screen extension
971 */
972
973EGLBoolean EGLAPIENTRY
974eglChooseModeMESA(EGLDisplay dpy, EGLScreenMESA screen,
975                  const EGLint *attrib_list, EGLModeMESA *modes,
976                  EGLint modes_size, EGLint *num_modes)
977{
978   _EGLDisplay *disp = _eglLockDisplay(dpy);
979   _EGLScreen *scrn = _eglLookupScreen(screen, disp);
980   _EGLDriver *drv;
981   EGLBoolean ret;
982
983   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
984   ret = drv->API.ChooseModeMESA(drv, disp, scrn, attrib_list,
985         modes, modes_size, num_modes);
986
987   RETURN_EGL_EVAL(disp, ret);
988}
989
990
991EGLBoolean EGLAPIENTRY
992eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes,
993                EGLint mode_size, EGLint *num_mode)
994{
995   _EGLDisplay *disp = _eglLockDisplay(dpy);
996   _EGLScreen *scrn = _eglLookupScreen(screen, disp);
997   _EGLDriver *drv;
998   EGLBoolean ret;
999
1000   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
1001   ret = drv->API.GetModesMESA(drv, disp, scrn, modes, mode_size, num_mode);
1002
1003   RETURN_EGL_EVAL(disp, ret);
1004}
1005
1006
1007EGLBoolean EGLAPIENTRY
1008eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode,
1009                     EGLint attribute, EGLint *value)
1010{
1011   _EGLDisplay *disp = _eglLockDisplay(dpy);
1012   _EGLMode *m = _eglLookupMode(mode, disp);
1013   _EGLDriver *drv;
1014   EGLBoolean ret;
1015
1016   _EGL_CHECK_MODE(disp, m, EGL_FALSE, drv);
1017   ret = drv->API.GetModeAttribMESA(drv, disp, m, attribute, value);
1018
1019   RETURN_EGL_EVAL(disp, ret);
1020}
1021
1022
1023EGLBoolean EGLAPIENTRY
1024eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest,
1025                   EGLint mask)
1026{
1027   _EGLDisplay *disp = _eglLockDisplay(dpy);
1028   _EGLContext *source_context = _eglLookupContext(source, disp);
1029   _EGLContext *dest_context = _eglLookupContext(dest, disp);
1030   _EGLDriver *drv;
1031   EGLBoolean ret;
1032
1033   _EGL_CHECK_CONTEXT(disp, source_context, EGL_FALSE, drv);
1034   if (!dest_context)
1035      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
1036
1037   ret = drv->API.CopyContextMESA(drv, disp,
1038         source_context, dest_context, mask);
1039
1040   RETURN_EGL_EVAL(disp, ret);
1041}
1042
1043
1044EGLBoolean EGLAPIENTRY
1045eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens,
1046                  EGLint max_screens, EGLint *num_screens)
1047{
1048   _EGLDisplay *disp = _eglLockDisplay(dpy);
1049   _EGLDriver *drv;
1050   EGLBoolean ret;
1051
1052   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1053   ret = drv->API.GetScreensMESA(drv, disp, screens, max_screens, num_screens);
1054
1055   RETURN_EGL_EVAL(disp, ret);
1056}
1057
1058
1059EGLSurface EGLAPIENTRY
1060eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config,
1061                           const EGLint *attrib_list)
1062{
1063   _EGLDisplay *disp = _eglLockDisplay(dpy);
1064   _EGLConfig *conf = _eglLookupConfig(config, disp);
1065   _EGLDriver *drv;
1066   _EGLSurface *surf;
1067   EGLSurface ret;
1068
1069   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
1070
1071   surf = drv->API.CreateScreenSurfaceMESA(drv, disp, conf, attrib_list);
1072   ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1073
1074   RETURN_EGL_EVAL(disp, ret);
1075}
1076
1077
1078EGLBoolean EGLAPIENTRY
1079eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen,
1080                         EGLSurface surface, EGLModeMESA mode)
1081{
1082   _EGLDisplay *disp = _eglLockDisplay(dpy);
1083   _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
1084   _EGLSurface *surf = _eglLookupSurface(surface, disp);
1085   _EGLMode *m = _eglLookupMode(mode, disp);
1086   _EGLDriver *drv;
1087   EGLBoolean ret;
1088
1089   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
1090   if (!surf && surface != EGL_NO_SURFACE)
1091      RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1092   if (!m && mode != EGL_NO_MODE_MESA)
1093      RETURN_EGL_ERROR(disp, EGL_BAD_MODE_MESA, EGL_FALSE);
1094
1095   ret = drv->API.ShowScreenSurfaceMESA(drv, disp, scrn, surf, m);
1096
1097   RETURN_EGL_EVAL(disp, ret);
1098}
1099
1100
1101EGLBoolean EGLAPIENTRY
1102eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y)
1103{
1104   _EGLDisplay *disp = _eglLockDisplay(dpy);
1105   _EGLScreen *scrn = _eglLookupScreen(screen, disp);
1106   _EGLDriver *drv;
1107   EGLBoolean ret;
1108
1109   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
1110   ret = drv->API.ScreenPositionMESA(drv, disp, scrn, x, y);
1111
1112   RETURN_EGL_EVAL(disp, ret);
1113}
1114
1115
1116EGLBoolean EGLAPIENTRY
1117eglQueryScreenMESA(EGLDisplay dpy, EGLScreenMESA screen,
1118                   EGLint attribute, EGLint *value)
1119{
1120   _EGLDisplay *disp = _eglLockDisplay(dpy);
1121   _EGLScreen *scrn = _eglLookupScreen(screen, disp);
1122   _EGLDriver *drv;
1123   EGLBoolean ret;
1124
1125   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
1126   ret = drv->API.QueryScreenMESA(drv, disp, scrn, attribute, value);
1127
1128   RETURN_EGL_EVAL(disp, ret);
1129}
1130
1131
1132EGLBoolean EGLAPIENTRY
1133eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen,
1134                          EGLSurface *surface)
1135{
1136   _EGLDisplay *disp = _eglLockDisplay(dpy);
1137   _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
1138   _EGLDriver *drv;
1139   _EGLSurface *surf;
1140   EGLBoolean ret;
1141
1142   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
1143   ret = drv->API.QueryScreenSurfaceMESA(drv, disp, scrn, &surf);
1144   if (ret && surface)
1145      *surface = _eglGetSurfaceHandle(surf);
1146
1147   RETURN_EGL_EVAL(disp, ret);
1148}
1149
1150
1151EGLBoolean EGLAPIENTRY
1152eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode)
1153{
1154   _EGLDisplay *disp = _eglLockDisplay(dpy);
1155   _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
1156   _EGLDriver *drv;
1157   _EGLMode *m;
1158   EGLBoolean ret;
1159
1160   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
1161   ret = drv->API.QueryScreenModeMESA(drv, disp, scrn, &m);
1162   if (ret && mode)
1163      *mode = m->Handle;
1164
1165   RETURN_EGL_EVAL(disp, ret);
1166}
1167
1168
1169const char * EGLAPIENTRY
1170eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode)
1171{
1172   _EGLDisplay *disp = _eglLockDisplay(dpy);
1173   _EGLMode *m = _eglLookupMode(mode, disp);
1174   _EGLDriver *drv;
1175   const char *ret;
1176
1177   _EGL_CHECK_MODE(disp, m, NULL, drv);
1178   ret = drv->API.QueryModeStringMESA(drv, disp, m);
1179
1180   RETURN_EGL_EVAL(disp, ret);
1181}
1182
1183
1184#endif /* EGL_MESA_screen_surface */
1185
1186
1187#ifdef EGL_MESA_drm_display
1188
1189EGLDisplay EGLAPIENTRY
1190eglGetDRMDisplayMESA(int fd)
1191{
1192   _EGLDisplay *dpy = _eglFindDisplay(_EGL_PLATFORM_DRM, (void *) (intptr_t) fd);
1193   return _eglGetDisplayHandle(dpy);
1194}
1195
1196#endif /* EGL_MESA_drm_display */
1197
1198/**
1199 ** EGL 1.2
1200 **/
1201
1202/**
1203 * Specify the client API to use for subsequent calls including:
1204 *  eglCreateContext()
1205 *  eglGetCurrentContext()
1206 *  eglGetCurrentDisplay()
1207 *  eglGetCurrentSurface()
1208 *  eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT)
1209 *  eglWaitClient()
1210 *  eglWaitNative()
1211 * See section 3.7 "Rendering Context" in the EGL specification for details.
1212 */
1213EGLBoolean EGLAPIENTRY
1214eglBindAPI(EGLenum api)
1215{
1216   _EGLThreadInfo *t = _eglGetCurrentThread();
1217
1218   if (_eglIsCurrentThreadDummy())
1219      RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
1220
1221   if (!_eglIsApiValid(api))
1222      RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, EGL_FALSE);
1223
1224   t->CurrentAPIIndex = _eglConvertApiToIndex(api);
1225
1226   RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1227}
1228
1229
1230/**
1231 * Return the last value set with eglBindAPI().
1232 */
1233EGLenum EGLAPIENTRY
1234eglQueryAPI(void)
1235{
1236   _EGLThreadInfo *t = _eglGetCurrentThread();
1237   EGLenum ret;
1238
1239   /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */
1240   ret = _eglConvertApiFromIndex(t->CurrentAPIIndex);
1241
1242   RETURN_EGL_SUCCESS(NULL, ret);
1243}
1244
1245
1246EGLSurface EGLAPIENTRY
1247eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
1248                                 EGLClientBuffer buffer, EGLConfig config,
1249                                 const EGLint *attrib_list)
1250{
1251   _EGLDisplay *disp = _eglLockDisplay(dpy);
1252   _EGLConfig *conf = _eglLookupConfig(config, disp);
1253   _EGLDriver *drv;
1254   _EGLSurface *surf;
1255   EGLSurface ret;
1256
1257   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
1258
1259   surf = drv->API.CreatePbufferFromClientBuffer(drv, disp, buftype, buffer,
1260                                                 conf, attrib_list);
1261   ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1262
1263   RETURN_EGL_EVAL(disp, ret);
1264}
1265
1266
1267EGLBoolean EGLAPIENTRY
1268eglReleaseThread(void)
1269{
1270   /* unbind current contexts */
1271   if (!_eglIsCurrentThreadDummy()) {
1272      _EGLThreadInfo *t = _eglGetCurrentThread();
1273      EGLint api_index = t->CurrentAPIIndex;
1274      EGLint i;
1275
1276      for (i = 0; i < _EGL_API_NUM_APIS; i++) {
1277         _EGLContext *ctx = t->CurrentContexts[i];
1278         if (ctx) {
1279            _EGLDisplay *disp = ctx->Resource.Display;
1280            _EGLDriver *drv;
1281
1282            t->CurrentAPIIndex = i;
1283
1284            _eglLockMutex(&disp->Mutex);
1285            drv = disp->Driver;
1286            (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
1287            _eglUnlockMutex(&disp->Mutex);
1288         }
1289      }
1290
1291      t->CurrentAPIIndex = api_index;
1292   }
1293
1294   _eglDestroyCurrentThread();
1295
1296   RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1297}
1298
1299
1300EGLImageKHR EGLAPIENTRY
1301eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1302                  EGLClientBuffer buffer, const EGLint *attr_list)
1303{
1304   _EGLDisplay *disp = _eglLockDisplay(dpy);
1305   _EGLContext *context = _eglLookupContext(ctx, disp);
1306   _EGLDriver *drv;
1307   _EGLImage *img;
1308   EGLImageKHR ret;
1309
1310   _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
1311   if (!disp->Extensions.KHR_image_base)
1312      RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
1313   if (!context && ctx != EGL_NO_CONTEXT)
1314      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1315
1316   img = drv->API.CreateImageKHR(drv,
1317         disp, context, target, buffer, attr_list);
1318   ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
1319
1320   RETURN_EGL_EVAL(disp, ret);
1321}
1322
1323
1324EGLBoolean EGLAPIENTRY
1325eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
1326{
1327   _EGLDisplay *disp = _eglLockDisplay(dpy);
1328   _EGLImage *img = _eglLookupImage(image, disp);
1329   _EGLDriver *drv;
1330   EGLBoolean ret;
1331
1332   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1333   if (!disp->Extensions.KHR_image_base)
1334      RETURN_EGL_EVAL(disp, EGL_FALSE);
1335   if (!img)
1336      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1337
1338   _eglUnlinkImage(img);
1339   ret = drv->API.DestroyImageKHR(drv, disp, img);
1340
1341   RETURN_EGL_EVAL(disp, ret);
1342}
1343
1344
1345EGLSyncKHR EGLAPIENTRY
1346eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1347{
1348   _EGLDisplay *disp = _eglLockDisplay(dpy);
1349   _EGLDriver *drv;
1350   _EGLSync *sync;
1351   EGLSyncKHR ret;
1352
1353   _EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv);
1354   if (!disp->Extensions.KHR_reusable_sync)
1355      RETURN_EGL_EVAL(disp, EGL_NO_SYNC_KHR);
1356
1357   sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list);
1358   ret = (sync) ? _eglLinkSync(sync) : EGL_NO_SYNC_KHR;
1359
1360   RETURN_EGL_EVAL(disp, ret);
1361}
1362
1363
1364EGLBoolean EGLAPIENTRY
1365eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1366{
1367   _EGLDisplay *disp = _eglLockDisplay(dpy);
1368   _EGLSync *s = _eglLookupSync(sync, disp);
1369   _EGLDriver *drv;
1370   EGLBoolean ret;
1371
1372   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1373   assert(disp->Extensions.KHR_reusable_sync);
1374
1375   _eglUnlinkSync(s);
1376   ret = drv->API.DestroySyncKHR(drv, disp, s);
1377
1378   RETURN_EGL_EVAL(disp, ret);
1379}
1380
1381
1382EGLint EGLAPIENTRY
1383eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
1384{
1385   _EGLDisplay *disp = _eglLockDisplay(dpy);
1386   _EGLSync *s = _eglLookupSync(sync, disp);
1387   _EGLDriver *drv;
1388   EGLint ret;
1389
1390   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1391   assert(disp->Extensions.KHR_reusable_sync);
1392   ret = drv->API.ClientWaitSyncKHR(drv, disp, s, flags, timeout);
1393
1394   RETURN_EGL_EVAL(disp, ret);
1395}
1396
1397
1398EGLBoolean EGLAPIENTRY
1399eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode)
1400{
1401   _EGLDisplay *disp = _eglLockDisplay(dpy);
1402   _EGLSync *s = _eglLookupSync(sync, disp);
1403   _EGLDriver *drv;
1404   EGLBoolean ret;
1405
1406   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1407   assert(disp->Extensions.KHR_reusable_sync);
1408   ret = drv->API.SignalSyncKHR(drv, disp, s, mode);
1409
1410   RETURN_EGL_EVAL(disp, ret);
1411}
1412
1413
1414EGLBoolean EGLAPIENTRY
1415eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
1416{
1417   _EGLDisplay *disp = _eglLockDisplay(dpy);
1418   _EGLSync *s = _eglLookupSync(sync, disp);
1419   _EGLDriver *drv;
1420   EGLBoolean ret;
1421
1422   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1423   assert(disp->Extensions.KHR_reusable_sync);
1424   ret = drv->API.GetSyncAttribKHR(drv, disp, s, attribute, value);
1425
1426   RETURN_EGL_EVAL(disp, ret);
1427}
1428
1429
1430#ifdef EGL_NOK_swap_region
1431
1432EGLBoolean EGLAPIENTRY
1433eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface,
1434			EGLint numRects, const EGLint *rects)
1435{
1436   _EGLContext *ctx = _eglGetCurrentContext();
1437   _EGLDisplay *disp = _eglLockDisplay(dpy);
1438   _EGLSurface *surf = _eglLookupSurface(surface, disp);
1439   _EGLDriver *drv;
1440   EGLBoolean ret;
1441
1442   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1443
1444   if (!disp->Extensions.NOK_swap_region)
1445      RETURN_EGL_EVAL(disp, EGL_FALSE);
1446
1447   /* surface must be bound to current context in EGL 1.4 */
1448   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1449       surf != ctx->DrawSurface)
1450      RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1451
1452   ret = drv->API.SwapBuffersRegionNOK(drv, disp, surf, numRects, rects);
1453
1454   RETURN_EGL_EVAL(disp, ret);
1455}
1456
1457#endif /* EGL_NOK_swap_region */
1458
1459
1460#ifdef EGL_MESA_drm_image
1461
1462EGLImageKHR EGLAPIENTRY
1463eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list)
1464{
1465   _EGLDisplay *disp = _eglLockDisplay(dpy);
1466   _EGLDriver *drv;
1467   _EGLImage *img;
1468   EGLImageKHR ret;
1469
1470   _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
1471   if (!disp->Extensions.MESA_drm_image)
1472      RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
1473
1474   img = drv->API.CreateDRMImageMESA(drv, disp, attr_list);
1475   ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
1476
1477   RETURN_EGL_EVAL(disp, ret);
1478}
1479
1480EGLBoolean EGLAPIENTRY
1481eglExportDRMImageMESA(EGLDisplay dpy, EGLImageKHR image,
1482		      EGLint *name, EGLint *handle, EGLint *stride)
1483{
1484   _EGLDisplay *disp = _eglLockDisplay(dpy);
1485   _EGLImage *img = _eglLookupImage(image, disp);
1486   _EGLDriver *drv;
1487   EGLBoolean ret;
1488
1489   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1490   assert(disp->Extensions.MESA_drm_image);
1491
1492   if (!img)
1493      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1494
1495   ret = drv->API.ExportDRMImageMESA(drv, disp, img, name, handle, stride);
1496
1497   RETURN_EGL_EVAL(disp, ret);
1498}
1499
1500#endif
1501
1502#ifdef EGL_WL_bind_wayland_display
1503struct wl_display;
1504
1505EGLBoolean EGLAPIENTRY
1506eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
1507{
1508   _EGLDisplay *disp = _eglLockDisplay(dpy);
1509   _EGLDriver *drv;
1510   EGLBoolean ret;
1511
1512   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1513   assert(disp->Extensions.WL_bind_wayland_display);
1514
1515   if (!display)
1516      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1517
1518   ret = drv->API.BindWaylandDisplayWL(drv, disp, display);
1519
1520   RETURN_EGL_EVAL(disp, ret);
1521}
1522
1523EGLBoolean EGLAPIENTRY
1524eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
1525{
1526   _EGLDisplay *disp = _eglLockDisplay(dpy);
1527   _EGLDriver *drv;
1528   EGLBoolean ret;
1529
1530   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1531   assert(disp->Extensions.WL_bind_wayland_display);
1532
1533   if (!display)
1534      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1535
1536   ret = drv->API.UnbindWaylandDisplayWL(drv, disp, display);
1537
1538   RETURN_EGL_EVAL(disp, ret);
1539}
1540
1541EGLBoolean EGLAPIENTRY
1542eglQueryWaylandBufferWL(EGLDisplay dpy,struct wl_buffer *buffer,
1543                        EGLint attribute, EGLint *value)
1544{
1545   _EGLDisplay *disp = _eglLockDisplay(dpy);
1546   _EGLDriver *drv;
1547   EGLBoolean ret;
1548
1549   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1550   assert(disp->Extensions.WL_bind_wayland_display);
1551
1552   if (!buffer)
1553      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1554
1555   ret = drv->API.QueryWaylandBufferWL(drv, disp, buffer, attribute, value);
1556
1557   RETURN_EGL_EVAL(disp, ret);
1558}
1559#endif
1560
1561
1562EGLBoolean EGLAPIENTRY
1563eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface,
1564                   EGLint x, EGLint y, EGLint width, EGLint height)
1565{
1566   _EGLDisplay *disp = _eglLockDisplay(dpy);
1567   _EGLSurface *surf = _eglLookupSurface(surface, disp);
1568   _EGLDriver *drv;
1569   EGLBoolean ret;
1570
1571   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1572
1573   if (!disp->Extensions.NV_post_sub_buffer)
1574      RETURN_EGL_EVAL(disp, EGL_FALSE);
1575
1576   ret = drv->API.PostSubBufferNV(drv, disp, surf, x, y, width, height);
1577
1578   RETURN_EGL_EVAL(disp, ret);
1579}
1580