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