Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / egl / main / eglapi.c
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
163 static 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
178 static 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
192 static 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
206 static 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
223 static 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
243 static 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
257 static 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  */
277 static 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  */
290 static 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  */
301 EGLDisplay EGLAPIENTRY
302 eglGetDisplay(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  */
314 EGLBoolean EGLAPIENTRY
315 eglInitialize(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
340 EGLBoolean EGLAPIENTRY
341 eglTerminate(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
360 const char * EGLAPIENTRY
361 eglQueryString(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
374 EGLBoolean EGLAPIENTRY
375 eglGetConfigs(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
389 EGLBoolean EGLAPIENTRY
390 eglChooseConfig(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
405 EGLBoolean EGLAPIENTRY
406 eglGetConfigAttrib(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
421 EGLContext EGLAPIENTRY
422 eglCreateContext(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
452 EGLBoolean EGLAPIENTRY
453 eglDestroyContext(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
468 EGLBoolean EGLAPIENTRY
469 eglMakeCurrent(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
514 EGLBoolean EGLAPIENTRY
515 eglQueryContext(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
530 EGLSurface EGLAPIENTRY
531 eglCreateWindowSurface(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
551 EGLSurface EGLAPIENTRY
552 eglCreatePixmapSurface(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
572 EGLSurface EGLAPIENTRY
573 eglCreatePbufferSurface(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
591 EGLBoolean EGLAPIENTRY
592 eglDestroySurface(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
606 EGLBoolean EGLAPIENTRY
607 eglQuerySurface(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
621 EGLBoolean EGLAPIENTRY
622 eglSurfaceAttrib(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
637 EGLBoolean EGLAPIENTRY
638 eglBindTexImage(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
652 EGLBoolean EGLAPIENTRY
653 eglReleaseTexImage(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
667 EGLBoolean EGLAPIENTRY
668 eglSwapInterval(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
692 EGLBoolean EGLAPIENTRY
693 eglSwapBuffers(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
714 EGLBoolean EGLAPIENTRY
715 eglCopyBuffers(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
731 EGLBoolean EGLAPIENTRY
732 eglWaitClient(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
759 EGLBoolean EGLAPIENTRY
760 eglWaitGL(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
781 EGLBoolean EGLAPIENTRY
782 eglWaitNative(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
809 EGLDisplay EGLAPIENTRY
810 eglGetCurrentDisplay(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
821 EGLContext EGLAPIENTRY
822 eglGetCurrentContext(void)
823 {
824    _EGLContext *ctx = _eglGetCurrentContext();
825    EGLContext ret;
826
827    ret = _eglGetContextHandle(ctx);
828
829    RETURN_EGL_SUCCESS(NULL, ret);
830 }
831
832
833 EGLSurface EGLAPIENTRY
834 eglGetCurrentSurface(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
863 EGLint EGLAPIENTRY
864 eglGetError(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
875 eglGetProcAddress(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
982 EGLBoolean EGLAPIENTRY
983 eglChooseModeMESA(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
1000 EGLBoolean EGLAPIENTRY
1001 eglGetModesMESA(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
1016 EGLBoolean EGLAPIENTRY
1017 eglGetModeAttribMESA(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
1032 EGLBoolean EGLAPIENTRY
1033 eglCopyContextMESA(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
1053 EGLBoolean EGLAPIENTRY
1054 eglGetScreensMESA(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
1068 EGLSurface EGLAPIENTRY
1069 eglCreateScreenSurfaceMESA(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
1087 EGLBoolean EGLAPIENTRY
1088 eglShowScreenSurfaceMESA(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
1110 EGLBoolean EGLAPIENTRY
1111 eglScreenPositionMESA(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
1125 EGLBoolean EGLAPIENTRY
1126 eglQueryScreenMESA(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
1141 EGLBoolean EGLAPIENTRY
1142 eglQueryScreenSurfaceMESA(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
1160 EGLBoolean EGLAPIENTRY
1161 eglQueryScreenModeMESA(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
1178 const char * EGLAPIENTRY
1179 eglQueryModeStringMESA(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
1198 EGLDisplay EGLAPIENTRY
1199 eglGetDRMDisplayMESA(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  */
1225 EGLBoolean EGLAPIENTRY
1226 eglBindAPI(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  */
1245 EGLenum EGLAPIENTRY
1246 eglQueryAPI(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
1258 EGLSurface EGLAPIENTRY
1259 eglCreatePbufferFromClientBuffer(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
1279 EGLBoolean EGLAPIENTRY
1280 eglReleaseThread(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
1318 EGLImageKHR EGLAPIENTRY
1319 eglCreateImageKHR(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
1342 EGLBoolean EGLAPIENTRY
1343 eglDestroyImageKHR(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
1369 EGLSyncKHR EGLAPIENTRY
1370 eglCreateSyncKHR(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
1388 EGLBoolean EGLAPIENTRY
1389 eglDestroySyncKHR(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
1406 EGLint EGLAPIENTRY
1407 eglClientWaitSyncKHR(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
1422 EGLBoolean EGLAPIENTRY
1423 eglSignalSyncKHR(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
1438 EGLBoolean EGLAPIENTRY
1439 eglGetSyncAttribKHR(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
1459 EGLBoolean EGLAPIENTRY
1460 eglSwapBuffersRegionNOK(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
1489 EGLImageKHR EGLAPIENTRY
1490 eglCreateDRMImageMESA(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
1507 EGLBoolean EGLAPIENTRY
1508 eglExportDRMImageMESA(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
1530 struct wl_display;
1531
1532 EGLBoolean EGLAPIENTRY
1533 eglBindWaylandDisplayWL(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
1550 EGLBoolean EGLAPIENTRY
1551 eglUnbindWaylandDisplayWL(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