eglapi.c revision 3464ebd5
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
220#ifdef EGL_KHR_reusable_sync
221
222
223static INLINE _EGLDriver *
224_eglCheckSync(_EGLDisplay *disp, _EGLSync *s, const char *msg)
225{
226   _EGLDriver *drv = _eglCheckDisplay(disp, msg);
227   if (!drv)
228      return NULL;
229   if (!s) {
230      _eglError(EGL_BAD_PARAMETER, msg);
231      return NULL;
232   }
233   return drv;
234}
235
236
237#endif /* EGL_KHR_reusable_sync */
238
239
240#ifdef EGL_MESA_screen_surface
241
242
243static INLINE _EGLDriver *
244_eglCheckScreen(_EGLDisplay *disp, _EGLScreen *scrn, const char *msg)
245{
246   _EGLDriver *drv = _eglCheckDisplay(disp, msg);
247   if (!drv)
248      return NULL;
249   if (!scrn) {
250      _eglError(EGL_BAD_SCREEN_MESA, msg);
251      return NULL;
252   }
253   return drv;
254}
255
256
257static INLINE _EGLDriver *
258_eglCheckMode(_EGLDisplay *disp, _EGLMode *m, const char *msg)
259{
260   _EGLDriver *drv = _eglCheckDisplay(disp, msg);
261   if (!drv)
262      return NULL;
263   if (!m) {
264      _eglError(EGL_BAD_MODE_MESA, msg);
265      return NULL;
266   }
267   return drv;
268}
269
270
271#endif /* EGL_MESA_screen_surface */
272
273
274/**
275 * Lookup and lock a display.
276 */
277static INLINE _EGLDisplay *
278_eglLockDisplay(EGLDisplay display)
279{
280   _EGLDisplay *dpy = _eglLookupDisplay(display);
281   if (dpy)
282      _eglLockMutex(&dpy->Mutex);
283   return dpy;
284}
285
286
287/**
288 * Unlock a display.
289 */
290static INLINE void
291_eglUnlockDisplay(_EGLDisplay *dpy)
292{
293   _eglUnlockMutex(&dpy->Mutex);
294}
295
296
297/**
298 * This is typically the first EGL function that an application calls.
299 * It associates a private _EGLDisplay object to the native display.
300 */
301EGLDisplay EGLAPIENTRY
302eglGetDisplay(EGLNativeDisplayType nativeDisplay)
303{
304   _EGLPlatformType plat = _eglGetNativePlatform();
305   _EGLDisplay *dpy = _eglFindDisplay(plat, (void *) nativeDisplay);
306   return _eglGetDisplayHandle(dpy);
307}
308
309
310/**
311 * This is typically the second EGL function that an application calls.
312 * Here we load/initialize the actual hardware driver.
313 */
314EGLBoolean EGLAPIENTRY
315eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
316{
317   _EGLDisplay *disp = _eglLockDisplay(dpy);
318
319   if (!disp)
320      RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
321
322   if (!disp->Initialized) {
323      if (!_eglMatchDriver(disp, EGL_FALSE))
324         RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
325
326      /* limit to APIs supported by core */
327      disp->ClientAPIs &= _EGL_API_ALL_BITS;
328   }
329
330   /* Update applications version of major and minor if not NULL */
331   if ((major != NULL) && (minor != NULL)) {
332      *major = disp->VersionMajor;
333      *minor = disp->VersionMinor;
334   }
335
336   RETURN_EGL_SUCCESS(disp, EGL_TRUE);
337}
338
339
340EGLBoolean EGLAPIENTRY
341eglTerminate(EGLDisplay dpy)
342{
343   _EGLDisplay *disp = _eglLockDisplay(dpy);
344
345   if (!disp)
346      RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
347
348   if (disp->Initialized) {
349      _EGLDriver *drv = disp->Driver;
350
351      drv->API.Terminate(drv, disp);
352      /* do not reset disp->Driver */
353      disp->Initialized = EGL_FALSE;
354   }
355
356   RETURN_EGL_SUCCESS(disp, EGL_TRUE);
357}
358
359
360const char * EGLAPIENTRY
361eglQueryString(EGLDisplay dpy, EGLint name)
362{
363   _EGLDisplay *disp = _eglLockDisplay(dpy);
364   _EGLDriver *drv;
365   const char *ret;
366
367   _EGL_CHECK_DISPLAY(disp, NULL, drv);
368   ret = drv->API.QueryString(drv, disp, name);
369
370   RETURN_EGL_EVAL(disp, ret);
371}
372
373
374EGLBoolean EGLAPIENTRY
375eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
376              EGLint config_size, EGLint *num_config)
377{
378   _EGLDisplay *disp = _eglLockDisplay(dpy);
379   _EGLDriver *drv;
380   EGLBoolean ret;
381
382   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
383   ret = drv->API.GetConfigs(drv, disp, configs, config_size, num_config);
384
385   RETURN_EGL_EVAL(disp, ret);
386}
387
388
389EGLBoolean EGLAPIENTRY
390eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs,
391                EGLint config_size, EGLint *num_config)
392{
393   _EGLDisplay *disp = _eglLockDisplay(dpy);
394   _EGLDriver *drv;
395   EGLBoolean ret;
396
397   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
398   ret = drv->API.ChooseConfig(drv, disp, attrib_list, configs,
399                                config_size, num_config);
400
401   RETURN_EGL_EVAL(disp, ret);
402}
403
404
405EGLBoolean EGLAPIENTRY
406eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
407                   EGLint attribute, EGLint *value)
408{
409   _EGLDisplay *disp = _eglLockDisplay(dpy);
410   _EGLConfig *conf = _eglLookupConfig(config, disp);
411   _EGLDriver *drv;
412   EGLBoolean ret;
413
414   _EGL_CHECK_CONFIG(disp, conf, EGL_FALSE, drv);
415   ret = drv->API.GetConfigAttrib(drv, disp, conf, attribute, value);
416
417   RETURN_EGL_EVAL(disp, ret);
418}
419
420
421EGLContext EGLAPIENTRY
422eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list,
423                 const EGLint *attrib_list)
424{
425   _EGLDisplay *disp = _eglLockDisplay(dpy);
426   _EGLConfig *conf = _eglLookupConfig(config, disp);
427   _EGLContext *share = _eglLookupContext(share_list, disp);
428   _EGLDriver *drv;
429   _EGLContext *context;
430   EGLContext ret;
431
432   _EGL_CHECK_DISPLAY(disp, EGL_NO_CONTEXT, drv);
433
434   if (!config) {
435      /* config may be NULL if surfaceless */
436      if (!disp->Extensions.KHR_surfaceless_gles1 &&
437          !disp->Extensions.KHR_surfaceless_gles2 &&
438          !disp->Extensions.KHR_surfaceless_opengl)
439         RETURN_EGL_ERROR(disp, EGL_BAD_CONFIG, EGL_NO_CONTEXT);
440   }
441
442   if (!share && share_list != EGL_NO_CONTEXT)
443      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
444
445   context = drv->API.CreateContext(drv, disp, conf, share, attrib_list);
446   ret = (context) ? _eglLinkContext(context) : EGL_NO_CONTEXT;
447
448   RETURN_EGL_EVAL(disp, ret);
449}
450
451
452EGLBoolean EGLAPIENTRY
453eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
454{
455   _EGLDisplay *disp = _eglLockDisplay(dpy);
456   _EGLContext *context = _eglLookupContext(ctx, disp);
457   _EGLDriver *drv;
458   EGLBoolean ret;
459
460   _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv);
461   _eglUnlinkContext(context);
462   ret = drv->API.DestroyContext(drv, disp, context);
463
464   RETURN_EGL_EVAL(disp, ret);
465}
466
467
468EGLBoolean EGLAPIENTRY
469eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
470               EGLContext ctx)
471{
472   _EGLDisplay *disp = _eglLockDisplay(dpy);
473   _EGLContext *context = _eglLookupContext(ctx, disp);
474   _EGLSurface *draw_surf = _eglLookupSurface(draw, disp);
475   _EGLSurface *read_surf = _eglLookupSurface(read, disp);
476   _EGLDriver *drv;
477   EGLBoolean ret;
478
479   if (!disp)
480      RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
481   drv = disp->Driver;
482
483   /* display is allowed to be uninitialized under certain condition */
484   if (!disp->Initialized) {
485      if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE ||
486          ctx != EGL_NO_CONTEXT)
487         RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
488   }
489   if (!drv)
490      RETURN_EGL_SUCCESS(disp, EGL_TRUE);
491
492   if (!context && ctx != EGL_NO_CONTEXT)
493      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
494   if (!draw_surf || !read_surf) {
495      /* surfaces may be NULL if surfaceless */
496      if (!disp->Extensions.KHR_surfaceless_gles1 &&
497          !disp->Extensions.KHR_surfaceless_gles2 &&
498          !disp->Extensions.KHR_surfaceless_opengl)
499         RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
500
501      if ((!draw_surf && draw != EGL_NO_SURFACE) ||
502          (!read_surf && read != EGL_NO_SURFACE))
503         RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
504      if (draw_surf || read_surf)
505         RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
506   }
507
508   ret = drv->API.MakeCurrent(drv, disp, draw_surf, read_surf, context);
509
510   RETURN_EGL_EVAL(disp, ret);
511}
512
513
514EGLBoolean EGLAPIENTRY
515eglQueryContext(EGLDisplay dpy, EGLContext ctx,
516                EGLint attribute, EGLint *value)
517{
518   _EGLDisplay *disp = _eglLockDisplay(dpy);
519   _EGLContext *context = _eglLookupContext(ctx, disp);
520   _EGLDriver *drv;
521   EGLBoolean ret;
522
523   _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv);
524   ret = drv->API.QueryContext(drv, disp, context, attribute, value);
525
526   RETURN_EGL_EVAL(disp, ret);
527}
528
529
530EGLSurface EGLAPIENTRY
531eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
532                       EGLNativeWindowType window, const EGLint *attrib_list)
533{
534   _EGLDisplay *disp = _eglLockDisplay(dpy);
535   _EGLConfig *conf = _eglLookupConfig(config, disp);
536   _EGLDriver *drv;
537   _EGLSurface *surf;
538   EGLSurface ret;
539
540   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
541   if (disp->Platform != _eglGetNativePlatform())
542      RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
543
544   surf = drv->API.CreateWindowSurface(drv, disp, conf, window, attrib_list);
545   ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
546
547   RETURN_EGL_EVAL(disp, ret);
548}
549
550
551EGLSurface EGLAPIENTRY
552eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
553                       EGLNativePixmapType pixmap, const EGLint *attrib_list)
554{
555   _EGLDisplay *disp = _eglLockDisplay(dpy);
556   _EGLConfig *conf = _eglLookupConfig(config, disp);
557   _EGLDriver *drv;
558   _EGLSurface *surf;
559   EGLSurface ret;
560
561   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
562   if (disp->Platform != _eglGetNativePlatform())
563      RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
564
565   surf = drv->API.CreatePixmapSurface(drv, disp, conf, pixmap, attrib_list);
566   ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
567
568   RETURN_EGL_EVAL(disp, ret);
569}
570
571
572EGLSurface EGLAPIENTRY
573eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
574                        const EGLint *attrib_list)
575{
576   _EGLDisplay *disp = _eglLockDisplay(dpy);
577   _EGLConfig *conf = _eglLookupConfig(config, disp);
578   _EGLDriver *drv;
579   _EGLSurface *surf;
580   EGLSurface ret;
581
582   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
583
584   surf = drv->API.CreatePbufferSurface(drv, disp, conf, attrib_list);
585   ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
586
587   RETURN_EGL_EVAL(disp, ret);
588}
589
590
591EGLBoolean EGLAPIENTRY
592eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
593{
594   _EGLDisplay *disp = _eglLockDisplay(dpy);
595   _EGLSurface *surf = _eglLookupSurface(surface, disp);
596   _EGLDriver *drv;
597   EGLBoolean ret;
598
599   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
600   _eglUnlinkSurface(surf);
601   ret = drv->API.DestroySurface(drv, disp, surf);
602
603   RETURN_EGL_EVAL(disp, ret);
604}
605
606EGLBoolean EGLAPIENTRY
607eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
608                EGLint attribute, EGLint *value)
609{
610   _EGLDisplay *disp = _eglLockDisplay(dpy);
611   _EGLSurface *surf = _eglLookupSurface(surface, disp);
612   _EGLDriver *drv;
613   EGLBoolean ret;
614
615   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
616   ret = drv->API.QuerySurface(drv, disp, surf, attribute, value);
617
618   RETURN_EGL_EVAL(disp, ret);
619}
620
621EGLBoolean EGLAPIENTRY
622eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
623                 EGLint attribute, EGLint value)
624{
625   _EGLDisplay *disp = _eglLockDisplay(dpy);
626   _EGLSurface *surf = _eglLookupSurface(surface, disp);
627   _EGLDriver *drv;
628   EGLBoolean ret;
629
630   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
631   ret = drv->API.SurfaceAttrib(drv, disp, surf, attribute, value);
632
633   RETURN_EGL_EVAL(disp, ret);
634}
635
636
637EGLBoolean EGLAPIENTRY
638eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
639{
640   _EGLDisplay *disp = _eglLockDisplay(dpy);
641   _EGLSurface *surf = _eglLookupSurface(surface, disp);
642   _EGLDriver *drv;
643   EGLBoolean ret;
644
645   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
646   ret = drv->API.BindTexImage(drv, disp, surf, buffer);
647
648   RETURN_EGL_EVAL(disp, ret);
649}
650
651
652EGLBoolean EGLAPIENTRY
653eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
654{
655   _EGLDisplay *disp = _eglLockDisplay(dpy);
656   _EGLSurface *surf = _eglLookupSurface(surface, disp);
657   _EGLDriver *drv;
658   EGLBoolean ret;
659
660   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
661   ret = drv->API.ReleaseTexImage(drv, disp, surf, buffer);
662
663   RETURN_EGL_EVAL(disp, ret);
664}
665
666
667EGLBoolean EGLAPIENTRY
668eglSwapInterval(EGLDisplay dpy, EGLint interval)
669{
670   _EGLDisplay *disp = _eglLockDisplay(dpy);
671   _EGLContext *ctx = _eglGetCurrentContext();
672   _EGLSurface *surf;
673   _EGLDriver *drv;
674   EGLBoolean ret;
675
676   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
677
678   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
679       ctx->Resource.Display != disp)
680      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
681
682   surf = ctx->DrawSurface;
683   if (_eglGetSurfaceHandle(surf) == EGL_NO_SURFACE)
684      RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
685
686   ret = drv->API.SwapInterval(drv, disp, surf, interval);
687
688   RETURN_EGL_EVAL(disp, ret);
689}
690
691
692EGLBoolean EGLAPIENTRY
693eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
694{
695   _EGLContext *ctx = _eglGetCurrentContext();
696   _EGLDisplay *disp = _eglLockDisplay(dpy);
697   _EGLSurface *surf = _eglLookupSurface(surface, disp);
698   _EGLDriver *drv;
699   EGLBoolean ret;
700
701   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
702
703   /* surface must be bound to current context in EGL 1.4 */
704   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
705       surf != ctx->DrawSurface)
706      RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
707
708   ret = drv->API.SwapBuffers(drv, disp, surf);
709
710   RETURN_EGL_EVAL(disp, ret);
711}
712
713
714EGLBoolean EGLAPIENTRY
715eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
716{
717   _EGLDisplay *disp = _eglLockDisplay(dpy);
718   _EGLSurface *surf = _eglLookupSurface(surface, disp);
719   _EGLDriver *drv;
720   EGLBoolean ret;
721
722   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
723   if (disp->Platform != _eglGetNativePlatform())
724      RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_FALSE);
725   ret = drv->API.CopyBuffers(drv, disp, surf, target);
726
727   RETURN_EGL_EVAL(disp, ret);
728}
729
730
731EGLBoolean EGLAPIENTRY
732eglWaitClient(void)
733{
734   _EGLContext *ctx = _eglGetCurrentContext();
735   _EGLDisplay *disp;
736   _EGLDriver *drv;
737   EGLBoolean ret;
738
739   if (!ctx)
740      RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
741
742   disp = ctx->Resource.Display;
743   _eglLockMutex(&disp->Mutex);
744
745   /* let bad current context imply bad current surface */
746   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
747       _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
748      RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
749
750   /* a valid current context implies an initialized current display */
751   assert(disp->Initialized);
752   drv = disp->Driver;
753   ret = drv->API.WaitClient(drv, disp, ctx);
754
755   RETURN_EGL_EVAL(disp, ret);
756}
757
758
759EGLBoolean EGLAPIENTRY
760eglWaitGL(void)
761{
762#ifdef EGL_VERSION_1_2
763   _EGLThreadInfo *t = _eglGetCurrentThread();
764   EGLint api_index = t->CurrentAPIIndex;
765   EGLint es_index = _eglConvertApiToIndex(EGL_OPENGL_ES_API);
766   EGLBoolean ret;
767
768   if (api_index != es_index && _eglIsCurrentThreadDummy())
769      RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
770
771   t->CurrentAPIIndex = es_index;
772   ret = eglWaitClient();
773   t->CurrentAPIIndex = api_index;
774   return ret;
775#else
776   return eglWaitClient();
777#endif
778}
779
780
781EGLBoolean EGLAPIENTRY
782eglWaitNative(EGLint engine)
783{
784   _EGLContext *ctx = _eglGetCurrentContext();
785   _EGLDisplay *disp;
786   _EGLDriver *drv;
787   EGLBoolean ret;
788
789   if (!ctx)
790      RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
791
792   disp = ctx->Resource.Display;
793   _eglLockMutex(&disp->Mutex);
794
795   /* let bad current context imply bad current surface */
796   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
797       _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
798      RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
799
800   /* a valid current context implies an initialized current display */
801   assert(disp->Initialized);
802   drv = disp->Driver;
803   ret = drv->API.WaitNative(drv, disp, engine);
804
805   RETURN_EGL_EVAL(disp, ret);
806}
807
808
809EGLDisplay EGLAPIENTRY
810eglGetCurrentDisplay(void)
811{
812   _EGLContext *ctx = _eglGetCurrentContext();
813   EGLDisplay ret;
814
815   ret = (ctx) ? _eglGetDisplayHandle(ctx->Resource.Display) : EGL_NO_DISPLAY;
816
817   RETURN_EGL_SUCCESS(NULL, ret);
818}
819
820
821EGLContext EGLAPIENTRY
822eglGetCurrentContext(void)
823{
824   _EGLContext *ctx = _eglGetCurrentContext();
825   EGLContext ret;
826
827   ret = _eglGetContextHandle(ctx);
828
829   RETURN_EGL_SUCCESS(NULL, ret);
830}
831
832
833EGLSurface EGLAPIENTRY
834eglGetCurrentSurface(EGLint readdraw)
835{
836   _EGLContext *ctx = _eglGetCurrentContext();
837   EGLint err = EGL_SUCCESS;
838   _EGLSurface *surf;
839   EGLSurface ret;
840
841   if (!ctx)
842      RETURN_EGL_SUCCESS(NULL, EGL_NO_SURFACE);
843
844   switch (readdraw) {
845   case EGL_DRAW:
846      surf = ctx->DrawSurface;
847      break;
848   case EGL_READ:
849      surf = ctx->ReadSurface;
850      break;
851   default:
852      surf = NULL;
853      err = EGL_BAD_PARAMETER;
854      break;
855   }
856
857   ret = _eglGetSurfaceHandle(surf);
858
859   RETURN_EGL_ERROR(NULL, err, ret);
860}
861
862
863EGLint EGLAPIENTRY
864eglGetError(void)
865{
866   _EGLThreadInfo *t = _eglGetCurrentThread();
867   EGLint e = t->LastError;
868   if (!_eglIsCurrentThreadDummy())
869      t->LastError = EGL_SUCCESS;
870   return e;
871}
872
873
874__eglMustCastToProperFunctionPointerType EGLAPIENTRY
875eglGetProcAddress(const char *procname)
876{
877   static const struct {
878      const char *name;
879      _EGLProc function;
880   } egl_functions[] = {
881      /* core functions should not be queryable, but, well... */
882#ifdef _EGL_GET_CORE_ADDRESSES
883      /* alphabetical order */
884      { "eglBindAPI", (_EGLProc) eglBindAPI },
885      { "eglBindTexImage", (_EGLProc) eglBindTexImage },
886      { "eglChooseConfig", (_EGLProc) eglChooseConfig },
887      { "eglCopyBuffers", (_EGLProc) eglCopyBuffers },
888      { "eglCreateContext", (_EGLProc) eglCreateContext },
889      { "eglCreatePbufferFromClientBuffer", (_EGLProc) eglCreatePbufferFromClientBuffer },
890      { "eglCreatePbufferSurface", (_EGLProc) eglCreatePbufferSurface },
891      { "eglCreatePixmapSurface", (_EGLProc) eglCreatePixmapSurface },
892      { "eglCreateWindowSurface", (_EGLProc) eglCreateWindowSurface },
893      { "eglDestroyContext", (_EGLProc) eglDestroyContext },
894      { "eglDestroySurface", (_EGLProc) eglDestroySurface },
895      { "eglGetConfigAttrib", (_EGLProc) eglGetConfigAttrib },
896      { "eglGetConfigs", (_EGLProc) eglGetConfigs },
897      { "eglGetCurrentContext", (_EGLProc) eglGetCurrentContext },
898      { "eglGetCurrentDisplay", (_EGLProc) eglGetCurrentDisplay },
899      { "eglGetCurrentSurface", (_EGLProc) eglGetCurrentSurface },
900      { "eglGetDisplay", (_EGLProc) eglGetDisplay },
901      { "eglGetError", (_EGLProc) eglGetError },
902      { "eglGetProcAddress", (_EGLProc) eglGetProcAddress },
903      { "eglInitialize", (_EGLProc) eglInitialize },
904      { "eglMakeCurrent", (_EGLProc) eglMakeCurrent },
905      { "eglQueryAPI", (_EGLProc) eglQueryAPI },
906      { "eglQueryContext", (_EGLProc) eglQueryContext },
907      { "eglQueryString", (_EGLProc) eglQueryString },
908      { "eglQuerySurface", (_EGLProc) eglQuerySurface },
909      { "eglReleaseTexImage", (_EGLProc) eglReleaseTexImage },
910      { "eglReleaseThread", (_EGLProc) eglReleaseThread },
911      { "eglSurfaceAttrib", (_EGLProc) eglSurfaceAttrib },
912      { "eglSwapBuffers", (_EGLProc) eglSwapBuffers },
913      { "eglSwapInterval", (_EGLProc) eglSwapInterval },
914      { "eglTerminate", (_EGLProc) eglTerminate },
915      { "eglWaitClient", (_EGLProc) eglWaitClient },
916      { "eglWaitGL", (_EGLProc) eglWaitGL },
917      { "eglWaitNative", (_EGLProc) eglWaitNative },
918#endif /* _EGL_GET_CORE_ADDRESSES */
919#ifdef EGL_MESA_screen_surface
920      { "eglChooseModeMESA", (_EGLProc) eglChooseModeMESA },
921      { "eglGetModesMESA", (_EGLProc) eglGetModesMESA },
922      { "eglGetModeAttribMESA", (_EGLProc) eglGetModeAttribMESA },
923      { "eglCopyContextMESA", (_EGLProc) eglCopyContextMESA },
924      { "eglGetScreensMESA", (_EGLProc) eglGetScreensMESA },
925      { "eglCreateScreenSurfaceMESA", (_EGLProc) eglCreateScreenSurfaceMESA },
926      { "eglShowScreenSurfaceMESA", (_EGLProc) eglShowScreenSurfaceMESA },
927      { "eglScreenPositionMESA", (_EGLProc) eglScreenPositionMESA },
928      { "eglQueryScreenMESA", (_EGLProc) eglQueryScreenMESA },
929      { "eglQueryScreenSurfaceMESA", (_EGLProc) eglQueryScreenSurfaceMESA },
930      { "eglQueryScreenModeMESA", (_EGLProc) eglQueryScreenModeMESA },
931      { "eglQueryModeStringMESA", (_EGLProc) eglQueryModeStringMESA },
932#endif /* EGL_MESA_screen_surface */
933#ifdef EGL_MESA_drm_display
934      { "eglGetDRMDisplayMESA", (_EGLProc) eglGetDRMDisplayMESA },
935#endif
936#ifdef EGL_KHR_image_base
937      { "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR },
938      { "eglDestroyImageKHR", (_EGLProc) eglDestroyImageKHR },
939#endif /* EGL_KHR_image_base */
940#ifdef EGL_NOK_swap_region
941      { "eglSwapBuffersRegionNOK", (_EGLProc) eglSwapBuffersRegionNOK },
942#endif
943#ifdef EGL_MESA_drm_image
944      { "eglCreateDRMImageMESA", (_EGLProc) eglCreateDRMImageMESA },
945      { "eglExportDRMImageMESA", (_EGLProc) eglExportDRMImageMESA },
946#endif
947#ifdef EGL_WL_bind_wayland_display
948      { "eglBindWaylandDisplayWL", (_EGLProc) eglBindWaylandDisplayWL },
949      { "eglUnbindWaylandDisplayWL", (_EGLProc) eglUnbindWaylandDisplayWL },
950#endif
951      { NULL, NULL }
952   };
953   EGLint i;
954   _EGLProc ret;
955
956   if (!procname)
957      RETURN_EGL_SUCCESS(NULL, NULL);
958
959   ret = NULL;
960   if (strncmp(procname, "egl", 3) == 0) {
961      for (i = 0; egl_functions[i].name; i++) {
962         if (strcmp(egl_functions[i].name, procname) == 0) {
963            ret = egl_functions[i].function;
964            break;
965         }
966      }
967   }
968   if (!ret)
969      ret = _eglGetDriverProc(procname);
970
971   RETURN_EGL_SUCCESS(NULL, ret);
972}
973
974
975#ifdef EGL_MESA_screen_surface
976
977
978/*
979 * EGL_MESA_screen extension
980 */
981
982EGLBoolean EGLAPIENTRY
983eglChooseModeMESA(EGLDisplay dpy, EGLScreenMESA screen,
984                  const EGLint *attrib_list, EGLModeMESA *modes,
985                  EGLint modes_size, EGLint *num_modes)
986{
987   _EGLDisplay *disp = _eglLockDisplay(dpy);
988   _EGLScreen *scrn = _eglLookupScreen(screen, disp);
989   _EGLDriver *drv;
990   EGLBoolean ret;
991
992   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
993   ret = drv->API.ChooseModeMESA(drv, disp, scrn, attrib_list,
994         modes, modes_size, num_modes);
995
996   RETURN_EGL_EVAL(disp, ret);
997}
998
999
1000EGLBoolean EGLAPIENTRY
1001eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes,
1002                EGLint mode_size, EGLint *num_mode)
1003{
1004   _EGLDisplay *disp = _eglLockDisplay(dpy);
1005   _EGLScreen *scrn = _eglLookupScreen(screen, disp);
1006   _EGLDriver *drv;
1007   EGLBoolean ret;
1008
1009   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
1010   ret = drv->API.GetModesMESA(drv, disp, scrn, modes, mode_size, num_mode);
1011
1012   RETURN_EGL_EVAL(disp, ret);
1013}
1014
1015
1016EGLBoolean EGLAPIENTRY
1017eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode,
1018                     EGLint attribute, EGLint *value)
1019{
1020   _EGLDisplay *disp = _eglLockDisplay(dpy);
1021   _EGLMode *m = _eglLookupMode(mode, disp);
1022   _EGLDriver *drv;
1023   EGLBoolean ret;
1024
1025   _EGL_CHECK_MODE(disp, m, EGL_FALSE, drv);
1026   ret = drv->API.GetModeAttribMESA(drv, disp, m, attribute, value);
1027
1028   RETURN_EGL_EVAL(disp, ret);
1029}
1030
1031
1032EGLBoolean EGLAPIENTRY
1033eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest,
1034                   EGLint mask)
1035{
1036   _EGLDisplay *disp = _eglLockDisplay(dpy);
1037   _EGLContext *source_context = _eglLookupContext(source, disp);
1038   _EGLContext *dest_context = _eglLookupContext(dest, disp);
1039   _EGLDriver *drv;
1040   EGLBoolean ret;
1041
1042   _EGL_CHECK_CONTEXT(disp, source_context, EGL_FALSE, drv);
1043   if (!dest_context)
1044      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
1045
1046   ret = drv->API.CopyContextMESA(drv, disp,
1047         source_context, dest_context, mask);
1048
1049   RETURN_EGL_EVAL(disp, ret);
1050}
1051
1052
1053EGLBoolean EGLAPIENTRY
1054eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens,
1055                  EGLint max_screens, EGLint *num_screens)
1056{
1057   _EGLDisplay *disp = _eglLockDisplay(dpy);
1058   _EGLDriver *drv;
1059   EGLBoolean ret;
1060
1061   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1062   ret = drv->API.GetScreensMESA(drv, disp, screens, max_screens, num_screens);
1063
1064   RETURN_EGL_EVAL(disp, ret);
1065}
1066
1067
1068EGLSurface EGLAPIENTRY
1069eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config,
1070                           const EGLint *attrib_list)
1071{
1072   _EGLDisplay *disp = _eglLockDisplay(dpy);
1073   _EGLConfig *conf = _eglLookupConfig(config, disp);
1074   _EGLDriver *drv;
1075   _EGLSurface *surf;
1076   EGLSurface ret;
1077
1078   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
1079
1080   surf = drv->API.CreateScreenSurfaceMESA(drv, disp, conf, attrib_list);
1081   ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1082
1083   RETURN_EGL_EVAL(disp, ret);
1084}
1085
1086
1087EGLBoolean EGLAPIENTRY
1088eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen,
1089                         EGLSurface surface, EGLModeMESA mode)
1090{
1091   _EGLDisplay *disp = _eglLockDisplay(dpy);
1092   _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
1093   _EGLSurface *surf = _eglLookupSurface(surface, disp);
1094   _EGLMode *m = _eglLookupMode(mode, disp);
1095   _EGLDriver *drv;
1096   EGLBoolean ret;
1097
1098   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
1099   if (!surf && surface != EGL_NO_SURFACE)
1100      RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1101   if (!m && mode != EGL_NO_MODE_MESA)
1102      RETURN_EGL_ERROR(disp, EGL_BAD_MODE_MESA, EGL_FALSE);
1103
1104   ret = drv->API.ShowScreenSurfaceMESA(drv, disp, scrn, surf, m);
1105
1106   RETURN_EGL_EVAL(disp, ret);
1107}
1108
1109
1110EGLBoolean EGLAPIENTRY
1111eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y)
1112{
1113   _EGLDisplay *disp = _eglLockDisplay(dpy);
1114   _EGLScreen *scrn = _eglLookupScreen(screen, disp);
1115   _EGLDriver *drv;
1116   EGLBoolean ret;
1117
1118   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
1119   ret = drv->API.ScreenPositionMESA(drv, disp, scrn, x, y);
1120
1121   RETURN_EGL_EVAL(disp, ret);
1122}
1123
1124
1125EGLBoolean EGLAPIENTRY
1126eglQueryScreenMESA(EGLDisplay dpy, EGLScreenMESA screen,
1127                   EGLint attribute, EGLint *value)
1128{
1129   _EGLDisplay *disp = _eglLockDisplay(dpy);
1130   _EGLScreen *scrn = _eglLookupScreen(screen, disp);
1131   _EGLDriver *drv;
1132   EGLBoolean ret;
1133
1134   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
1135   ret = drv->API.QueryScreenMESA(drv, disp, scrn, attribute, value);
1136
1137   RETURN_EGL_EVAL(disp, ret);
1138}
1139
1140
1141EGLBoolean EGLAPIENTRY
1142eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen,
1143                          EGLSurface *surface)
1144{
1145   _EGLDisplay *disp = _eglLockDisplay(dpy);
1146   _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
1147   _EGLDriver *drv;
1148   _EGLSurface *surf;
1149   EGLBoolean ret;
1150
1151   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
1152   ret = drv->API.QueryScreenSurfaceMESA(drv, disp, scrn, &surf);
1153   if (ret && surface)
1154      *surface = _eglGetSurfaceHandle(surf);
1155
1156   RETURN_EGL_EVAL(disp, ret);
1157}
1158
1159
1160EGLBoolean EGLAPIENTRY
1161eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode)
1162{
1163   _EGLDisplay *disp = _eglLockDisplay(dpy);
1164   _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
1165   _EGLDriver *drv;
1166   _EGLMode *m;
1167   EGLBoolean ret;
1168
1169   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
1170   ret = drv->API.QueryScreenModeMESA(drv, disp, scrn, &m);
1171   if (ret && mode)
1172      *mode = m->Handle;
1173
1174   RETURN_EGL_EVAL(disp, ret);
1175}
1176
1177
1178const char * EGLAPIENTRY
1179eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode)
1180{
1181   _EGLDisplay *disp = _eglLockDisplay(dpy);
1182   _EGLMode *m = _eglLookupMode(mode, disp);
1183   _EGLDriver *drv;
1184   const char *ret;
1185
1186   _EGL_CHECK_MODE(disp, m, NULL, drv);
1187   ret = drv->API.QueryModeStringMESA(drv, disp, m);
1188
1189   RETURN_EGL_EVAL(disp, ret);
1190}
1191
1192
1193#endif /* EGL_MESA_screen_surface */
1194
1195
1196#ifdef EGL_MESA_drm_display
1197
1198EGLDisplay EGLAPIENTRY
1199eglGetDRMDisplayMESA(int fd)
1200{
1201   _EGLDisplay *dpy = _eglFindDisplay(_EGL_PLATFORM_DRM, (void *) (intptr_t) fd);
1202   return _eglGetDisplayHandle(dpy);
1203}
1204
1205#endif /* EGL_MESA_drm_display */
1206
1207/**
1208 ** EGL 1.2
1209 **/
1210
1211#ifdef EGL_VERSION_1_2
1212
1213
1214/**
1215 * Specify the client API to use for subsequent calls including:
1216 *  eglCreateContext()
1217 *  eglGetCurrentContext()
1218 *  eglGetCurrentDisplay()
1219 *  eglGetCurrentSurface()
1220 *  eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT)
1221 *  eglWaitClient()
1222 *  eglWaitNative()
1223 * See section 3.7 "Rendering Context" in the EGL specification for details.
1224 */
1225EGLBoolean EGLAPIENTRY
1226eglBindAPI(EGLenum api)
1227{
1228   _EGLThreadInfo *t = _eglGetCurrentThread();
1229
1230   if (_eglIsCurrentThreadDummy())
1231      RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
1232
1233   if (!_eglIsApiValid(api))
1234      RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, EGL_FALSE);
1235
1236   t->CurrentAPIIndex = _eglConvertApiToIndex(api);
1237
1238   RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1239}
1240
1241
1242/**
1243 * Return the last value set with eglBindAPI().
1244 */
1245EGLenum EGLAPIENTRY
1246eglQueryAPI(void)
1247{
1248   _EGLThreadInfo *t = _eglGetCurrentThread();
1249   EGLenum ret;
1250
1251   /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */
1252   ret = _eglConvertApiFromIndex(t->CurrentAPIIndex);
1253
1254   RETURN_EGL_SUCCESS(NULL, ret);
1255}
1256
1257
1258EGLSurface EGLAPIENTRY
1259eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
1260                                 EGLClientBuffer buffer, EGLConfig config,
1261                                 const EGLint *attrib_list)
1262{
1263   _EGLDisplay *disp = _eglLockDisplay(dpy);
1264   _EGLConfig *conf = _eglLookupConfig(config, disp);
1265   _EGLDriver *drv;
1266   _EGLSurface *surf;
1267   EGLSurface ret;
1268
1269   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
1270
1271   surf = drv->API.CreatePbufferFromClientBuffer(drv, disp, buftype, buffer,
1272                                                 conf, attrib_list);
1273   ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1274
1275   RETURN_EGL_EVAL(disp, ret);
1276}
1277
1278
1279EGLBoolean EGLAPIENTRY
1280eglReleaseThread(void)
1281{
1282   /* unbind current contexts */
1283   if (!_eglIsCurrentThreadDummy()) {
1284      _EGLThreadInfo *t = _eglGetCurrentThread();
1285      EGLint api_index = t->CurrentAPIIndex;
1286      EGLint i;
1287
1288      for (i = 0; i < _EGL_API_NUM_APIS; i++) {
1289         _EGLContext *ctx = t->CurrentContexts[i];
1290         if (ctx) {
1291            _EGLDisplay *disp = ctx->Resource.Display;
1292            _EGLDriver *drv;
1293
1294            t->CurrentAPIIndex = i;
1295
1296            _eglLockMutex(&disp->Mutex);
1297            drv = disp->Driver;
1298            (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
1299            _eglUnlockMutex(&disp->Mutex);
1300         }
1301      }
1302
1303      t->CurrentAPIIndex = api_index;
1304   }
1305
1306   _eglDestroyCurrentThread();
1307
1308   RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1309}
1310
1311
1312#endif /* EGL_VERSION_1_2 */
1313
1314
1315#ifdef EGL_KHR_image_base
1316
1317
1318EGLImageKHR EGLAPIENTRY
1319eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1320                  EGLClientBuffer buffer, const EGLint *attr_list)
1321{
1322   _EGLDisplay *disp = _eglLockDisplay(dpy);
1323   _EGLContext *context = _eglLookupContext(ctx, disp);
1324   _EGLDriver *drv;
1325   _EGLImage *img;
1326   EGLImageKHR ret;
1327
1328   _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
1329   if (!disp->Extensions.KHR_image_base)
1330      RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
1331   if (!context && ctx != EGL_NO_CONTEXT)
1332      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1333
1334   img = drv->API.CreateImageKHR(drv,
1335         disp, context, target, buffer, attr_list);
1336   ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
1337
1338   RETURN_EGL_EVAL(disp, ret);
1339}
1340
1341
1342EGLBoolean EGLAPIENTRY
1343eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
1344{
1345   _EGLDisplay *disp = _eglLockDisplay(dpy);
1346   _EGLImage *img = _eglLookupImage(image, disp);
1347   _EGLDriver *drv;
1348   EGLBoolean ret;
1349
1350   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1351   if (!disp->Extensions.KHR_image_base)
1352      RETURN_EGL_EVAL(disp, EGL_FALSE);
1353   if (!img)
1354      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1355
1356   _eglUnlinkImage(img);
1357   ret = drv->API.DestroyImageKHR(drv, disp, img);
1358
1359   RETURN_EGL_EVAL(disp, ret);
1360}
1361
1362
1363#endif /* EGL_KHR_image_base */
1364
1365
1366#ifdef EGL_KHR_reusable_sync
1367
1368
1369EGLSyncKHR EGLAPIENTRY
1370eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1371{
1372   _EGLDisplay *disp = _eglLockDisplay(dpy);
1373   _EGLDriver *drv;
1374   _EGLSync *sync;
1375   EGLSyncKHR ret;
1376
1377   _EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv);
1378   if (!disp->Extensions.KHR_reusable_sync)
1379      RETURN_EGL_EVAL(disp, EGL_NO_SYNC_KHR);
1380
1381   sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list);
1382   ret = (sync) ? _eglLinkSync(sync) : EGL_NO_SYNC_KHR;
1383
1384   RETURN_EGL_EVAL(disp, ret);
1385}
1386
1387
1388EGLBoolean EGLAPIENTRY
1389eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1390{
1391   _EGLDisplay *disp = _eglLockDisplay(dpy);
1392   _EGLSync *s = _eglLookupSync(sync, disp);
1393   _EGLDriver *drv;
1394   EGLBoolean ret;
1395
1396   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1397   assert(disp->Extensions.KHR_reusable_sync);
1398
1399   _eglUnlinkSync(s);
1400   ret = drv->API.DestroySyncKHR(drv, disp, s);
1401
1402   RETURN_EGL_EVAL(disp, ret);
1403}
1404
1405
1406EGLint EGLAPIENTRY
1407eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
1408{
1409   _EGLDisplay *disp = _eglLockDisplay(dpy);
1410   _EGLSync *s = _eglLookupSync(sync, disp);
1411   _EGLDriver *drv;
1412   EGLint ret;
1413
1414   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1415   assert(disp->Extensions.KHR_reusable_sync);
1416   ret = drv->API.ClientWaitSyncKHR(drv, disp, s, flags, timeout);
1417
1418   RETURN_EGL_EVAL(disp, ret);
1419}
1420
1421
1422EGLBoolean EGLAPIENTRY
1423eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode)
1424{
1425   _EGLDisplay *disp = _eglLockDisplay(dpy);
1426   _EGLSync *s = _eglLookupSync(sync, disp);
1427   _EGLDriver *drv;
1428   EGLBoolean ret;
1429
1430   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1431   assert(disp->Extensions.KHR_reusable_sync);
1432   ret = drv->API.SignalSyncKHR(drv, disp, s, mode);
1433
1434   RETURN_EGL_EVAL(disp, ret);
1435}
1436
1437
1438EGLBoolean EGLAPIENTRY
1439eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
1440{
1441   _EGLDisplay *disp = _eglLockDisplay(dpy);
1442   _EGLSync *s = _eglLookupSync(sync, disp);
1443   _EGLDriver *drv;
1444   EGLBoolean ret;
1445
1446   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1447   assert(disp->Extensions.KHR_reusable_sync);
1448   ret = drv->API.GetSyncAttribKHR(drv, disp, s, attribute, value);
1449
1450   RETURN_EGL_EVAL(disp, ret);
1451}
1452
1453
1454#endif /* EGL_KHR_reusable_sync */
1455
1456
1457#ifdef EGL_NOK_swap_region
1458
1459EGLBoolean EGLAPIENTRY
1460eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface,
1461			EGLint numRects, const EGLint *rects)
1462{
1463   _EGLContext *ctx = _eglGetCurrentContext();
1464   _EGLDisplay *disp = _eglLockDisplay(dpy);
1465   _EGLSurface *surf = _eglLookupSurface(surface, disp);
1466   _EGLDriver *drv;
1467   EGLBoolean ret;
1468
1469   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1470
1471   if (!disp->Extensions.NOK_swap_region)
1472      RETURN_EGL_EVAL(disp, EGL_FALSE);
1473
1474   /* surface must be bound to current context in EGL 1.4 */
1475   if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1476       surf != ctx->DrawSurface)
1477      RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1478
1479   ret = drv->API.SwapBuffersRegionNOK(drv, disp, surf, numRects, rects);
1480
1481   RETURN_EGL_EVAL(disp, ret);
1482}
1483
1484#endif /* EGL_NOK_swap_region */
1485
1486
1487#ifdef EGL_MESA_drm_image
1488
1489EGLImageKHR EGLAPIENTRY
1490eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list)
1491{
1492   _EGLDisplay *disp = _eglLockDisplay(dpy);
1493   _EGLDriver *drv;
1494   _EGLImage *img;
1495   EGLImageKHR ret;
1496
1497   _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
1498   if (!disp->Extensions.MESA_drm_image)
1499      RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
1500
1501   img = drv->API.CreateDRMImageMESA(drv, disp, attr_list);
1502   ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
1503
1504   RETURN_EGL_EVAL(disp, ret);
1505}
1506
1507EGLBoolean EGLAPIENTRY
1508eglExportDRMImageMESA(EGLDisplay dpy, EGLImageKHR image,
1509		      EGLint *name, EGLint *handle, EGLint *stride)
1510{
1511   _EGLDisplay *disp = _eglLockDisplay(dpy);
1512   _EGLImage *img = _eglLookupImage(image, disp);
1513   _EGLDriver *drv;
1514   EGLBoolean ret;
1515
1516   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1517   assert(disp->Extensions.MESA_drm_image);
1518
1519   if (!img)
1520      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1521
1522   ret = drv->API.ExportDRMImageMESA(drv, disp, img, name, handle, stride);
1523
1524   RETURN_EGL_EVAL(disp, ret);
1525}
1526
1527#endif
1528
1529#ifdef EGL_WL_bind_wayland_display
1530struct wl_display;
1531
1532EGLBoolean EGLAPIENTRY
1533eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
1534{
1535   _EGLDisplay *disp = _eglLockDisplay(dpy);
1536   _EGLDriver *drv;
1537   EGLBoolean ret;
1538
1539   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1540   assert(disp->Extensions.WL_bind_wayland_display);
1541
1542   if (!display)
1543      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1544
1545   ret = drv->API.BindWaylandDisplayWL(drv, disp, display);
1546
1547   RETURN_EGL_EVAL(disp, ret);
1548}
1549
1550EGLBoolean EGLAPIENTRY
1551eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
1552{
1553   _EGLDisplay *disp = _eglLockDisplay(dpy);
1554   _EGLDriver *drv;
1555   EGLBoolean ret;
1556
1557   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1558   assert(disp->Extensions.WL_bind_wayland_display);
1559
1560   if (!display)
1561      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1562
1563   ret = drv->API.UnbindWaylandDisplayWL(drv, disp, display);
1564
1565   RETURN_EGL_EVAL(disp, ret);
1566}
1567#endif
1568