egl: Update headers.
[platform/upstream/mesa.git] / src / egl / main / eglapi.c
1 /**
2  * Public EGL API entrypoints
3  *
4  * Generally, we use the EGLDisplay parameter as a key to lookup the
5  * appropriate device driver handle, then jump though the driver's
6  * dispatch table to handle the function.
7  *
8  * That allows us the option of supporting multiple, simultaneous,
9  * heterogeneous hardware devices in the future.
10  *
11  * The EGLDisplay, EGLConfig, EGLContext and EGLSurface types are
12  * opaque handles. Internal objects are linked to a display to
13  * create the handles.
14  *
15  * For each public API entry point, the opaque handles are looked up
16  * before being dispatched to the drivers.  When it fails to look up
17  * a handle, one of
18  *
19  * EGL_BAD_DISPLAY
20  * EGL_BAD_CONFIG
21  * EGL_BAD_CONTEXT
22  * EGL_BAD_SURFACE
23  * EGL_BAD_SCREEN_MESA
24  * EGL_BAD_MODE_MESA
25  *
26  * is generated and the driver function is not called. An
27  * uninitialized EGLDisplay has no driver associated with it. When
28  * such display is detected,
29  *
30  * EGL_NOT_INITIALIZED
31  *
32  * is generated.
33  *
34  * Some of the entry points use current display, context, or surface
35  * implicitly.  For such entry points, the implicit objects are also
36  * checked before calling the driver function.  Other than the
37  * errors listed above,
38  *
39  * EGL_BAD_CURRENT_SURFACE
40  *
41  * may also be generated.
42  *
43  * Notes on naming conventions:
44  *
45  * eglFooBar    - public EGL function
46  * EGL_FOO_BAR  - public EGL token
47  * EGLDatatype  - public EGL datatype
48  *
49  * _eglFooBar   - private EGL function
50  * _EGLDatatype - private EGL datatype, typedef'd struct
51  * _egl_struct  - private EGL struct, non-typedef'd
52  *
53  */
54
55
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include "eglcontext.h"
60 #include "egldisplay.h"
61 #include "egltypedefs.h"
62 #include "eglglobals.h"
63 #include "egldriver.h"
64 #include "eglsurface.h"
65 #include "eglconfig.h"
66 #include "eglscreen.h"
67 #include "eglmode.h"
68
69
70 /**
71  * This is typically the first EGL function that an application calls.
72  * We initialize our global vars and create a private _EGLDisplay object.
73  */
74 EGLDisplay EGLAPIENTRY
75 eglGetDisplay(NativeDisplayType nativeDisplay)
76 {
77    _EGLDisplay *dpy;
78    dpy = _eglFindDisplay(nativeDisplay);
79    if (!dpy) {
80       dpy = _eglNewDisplay(nativeDisplay);
81       if (dpy)
82          _eglLinkDisplay(dpy);
83    }
84    return _eglGetDisplayHandle(dpy);
85 }
86
87
88 /**
89  * This is typically the second EGL function that an application calls.
90  * Here we load/initialize the actual hardware driver.
91  */
92 EGLBoolean EGLAPIENTRY
93 eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
94 {
95    _EGLDisplay *disp = _eglLookupDisplay(dpy);
96    _EGLDriver *drv;
97    EGLint major_int, minor_int;
98
99    if (!disp)
100       return _eglError(EGL_BAD_DISPLAY, __FUNCTION__);
101
102    drv = disp->Driver;
103    if (!drv) {
104       _eglPreloadDrivers();
105
106       drv = _eglOpenDriver(disp);
107       if (!drv)
108          return _eglError(EGL_NOT_INITIALIZED, __FUNCTION__);
109
110       /* Initialize the particular display now */
111       if (!drv->API.Initialize(drv, disp, &major_int, &minor_int)) {
112          _eglCloseDriver(drv, disp);
113          return _eglError(EGL_NOT_INITIALIZED, __FUNCTION__);
114       }
115
116       disp->APImajor = major_int;
117       disp->APIminor = minor_int;
118       snprintf(disp->Version, sizeof(disp->Version),
119                "%d.%d (%s)", major_int, minor_int, drv->Name);
120
121       /* limit to APIs supported by core */
122       disp->ClientAPIsMask &= _EGL_API_ALL_BITS;
123
124       disp->Driver = drv;
125    } else {
126       major_int = disp->APImajor;
127       minor_int = disp->APIminor;
128    }
129
130    /* Update applications version of major and minor if not NULL */
131    if ((major != NULL) && (minor != NULL)) {
132       *major = major_int;
133       *minor = minor_int;
134    }
135
136    return EGL_TRUE;
137 }
138
139
140 EGLBoolean EGLAPIENTRY
141 eglTerminate(EGLDisplay dpy)
142 {
143    _EGLDisplay *disp = _eglLookupDisplay(dpy);
144    _EGLDriver *drv;
145
146    if (!disp)
147       return _eglError(EGL_BAD_DISPLAY, __FUNCTION__);
148
149    drv = disp->Driver;
150    if (drv) {
151       drv->API.Terminate(drv, disp);
152       _eglCloseDriver(drv, disp);
153       disp->Driver = NULL;
154    }
155
156    return EGL_TRUE;
157 }
158
159
160 /**
161  * A bunch of check functions and declare macros to simply error checking.
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->Driver) {
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 #define _EGL_DECLARE_DD(dpy)                                   \
221    _EGLDisplay *disp = _eglLookupDisplay(dpy);                 \
222    _EGLDriver *drv;                                            \
223    do {                                                        \
224       drv = _eglCheckDisplay(disp, __FUNCTION__);              \
225       if (!drv)                                                \
226          return EGL_FALSE;                                     \
227    } while (0)
228
229
230 #define _EGL_DECLARE_DD_AND_SURFACE(dpy, surface)              \
231    _EGLDisplay *disp = _eglLookupDisplay(dpy);                 \
232    _EGLSurface *surf = _eglLookupSurface((surface), disp);     \
233    _EGLDriver *drv;                                            \
234    do {                                                        \
235       drv = _eglCheckSurface(disp, surf, __FUNCTION__);        \
236       if (!drv)                                                \
237          return EGL_FALSE;                                     \
238    } while (0)
239
240
241 #define _EGL_DECLARE_DD_AND_CONTEXT(dpy, ctx)                  \
242    _EGLDisplay *disp = _eglLookupDisplay(dpy);                 \
243    _EGLContext *context = _eglLookupContext((ctx), disp);      \
244    _EGLDriver *drv;                                            \
245    do {                                                        \
246       drv = _eglCheckContext(disp, context, __FUNCTION__);     \
247       if (!drv)                                                \
248          return EGL_FALSE;                                     \
249    } while (0)
250
251
252 #ifdef EGL_MESA_screen_surface
253
254
255 static INLINE _EGLDriver *
256 _eglCheckScreen(_EGLDisplay *disp, _EGLScreen *scrn, const char *msg)
257 {
258    _EGLDriver *drv = _eglCheckDisplay(disp, msg);
259    if (!drv)
260       return NULL;
261    if (!scrn) {
262       _eglError(EGL_BAD_SCREEN_MESA, msg);
263       return NULL;
264    }
265    return drv;
266 }
267
268
269 static INLINE _EGLDriver *
270 _eglCheckMode(_EGLDisplay *disp, _EGLMode *m, const char *msg)
271 {
272    _EGLDriver *drv = _eglCheckDisplay(disp, msg);
273    if (!drv)
274       return NULL;
275    if (!m) {
276       _eglError(EGL_BAD_MODE_MESA, msg);
277       return NULL;
278    }
279    return drv;
280 }
281
282
283 #define _EGL_DECLARE_DD_AND_SCREEN(dpy, screen)                \
284    _EGLDisplay *disp = _eglLookupDisplay(dpy);                 \
285    _EGLScreen *scrn = _eglLookupScreen((screen), disp);        \
286    _EGLDriver *drv;                                            \
287    do {                                                        \
288       drv = _eglCheckScreen(disp, scrn, __FUNCTION__);         \
289       if (!drv)                                                \
290          return EGL_FALSE;                                     \
291    } while (0)
292
293
294 #define _EGL_DECLARE_DD_AND_MODE(dpy, mode)                    \
295    _EGLDisplay *disp = _eglLookupDisplay(dpy);                 \
296    _EGLMode *m = _eglLookupMode((mode), disp);                 \
297    _EGLDriver *drv;                                            \
298    do {                                                        \
299       drv = _eglCheckMode(disp, m, __FUNCTION__);              \
300       if (!drv)                                                \
301          return EGL_FALSE;                                     \
302    } while (0)
303
304
305 #endif /* EGL_MESA_screen_surface */
306
307
308 const char * EGLAPIENTRY
309 eglQueryString(EGLDisplay dpy, EGLint name)
310 {
311    _EGL_DECLARE_DD(dpy);
312    return drv->API.QueryString(drv, disp, name);
313 }
314
315
316 EGLBoolean EGLAPIENTRY
317 eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
318               EGLint config_size, EGLint *num_config)
319 {
320    _EGL_DECLARE_DD(dpy);
321    return drv->API.GetConfigs(drv, disp, configs, config_size, num_config);
322 }
323
324
325 EGLBoolean EGLAPIENTRY
326 eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs,
327                 EGLint config_size, EGLint *num_config)
328 {
329    _EGL_DECLARE_DD(dpy);
330    return drv->API.ChooseConfig(drv, disp, attrib_list, configs,
331                                 config_size, num_config);
332 }
333
334
335 EGLBoolean EGLAPIENTRY
336 eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
337                    EGLint attribute, EGLint *value)
338 {
339    _EGLDisplay *disp = _eglLookupDisplay(dpy);
340    _EGLConfig *conf = _eglLookupConfig(config, disp);
341    _EGLDriver *drv;
342
343    drv = _eglCheckConfig(disp, conf, __FUNCTION__);
344    if (!drv)
345       return EGL_FALSE;
346
347    return drv->API.GetConfigAttrib(drv, disp, conf, attribute, value);
348 }
349
350
351 EGLContext EGLAPIENTRY
352 eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list,
353                  const EGLint *attrib_list)
354 {
355    _EGLDisplay *disp = _eglLookupDisplay(dpy);
356    _EGLConfig *conf = _eglLookupConfig(config, disp);
357    _EGLContext *share = _eglLookupContext(share_list, disp);
358    _EGLDriver *drv;
359    _EGLContext *context;
360
361    drv = _eglCheckConfig(disp, conf, __FUNCTION__);
362    if (!drv)
363       return EGL_NO_CONTEXT;
364    if (!share && share_list != EGL_NO_CONTEXT) {
365       _eglError(EGL_BAD_CONTEXT, __FUNCTION__);
366       return EGL_NO_CONTEXT;
367    }
368
369    context = drv->API.CreateContext(drv, disp, conf, share, attrib_list);
370    if (context)
371       return _eglLinkContext(context, disp);
372    else
373       return EGL_NO_CONTEXT;
374 }
375
376
377 EGLBoolean EGLAPIENTRY
378 eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
379 {
380    _EGL_DECLARE_DD_AND_CONTEXT(dpy, ctx);
381    _eglUnlinkContext(context);
382    return drv->API.DestroyContext(drv, disp, context);
383 }
384
385
386 EGLBoolean EGLAPIENTRY
387 eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
388                EGLContext ctx)
389 {
390    _EGLDisplay *disp = _eglLookupDisplay(dpy);
391    _EGLContext *context = _eglLookupContext(ctx, disp);
392    _EGLSurface *draw_surf = _eglLookupSurface(draw, disp);
393    _EGLSurface *read_surf = _eglLookupSurface(read, disp);
394    _EGLDriver *drv;
395
396    drv = _eglCheckDisplay(disp, __FUNCTION__);
397    if (!drv)
398       return EGL_FALSE;
399    if (!context && ctx != EGL_NO_CONTEXT)
400       return _eglError(EGL_BAD_CONTEXT, __FUNCTION__);
401    if ((!draw_surf && draw != EGL_NO_SURFACE) ||
402        (!read_surf && read != EGL_NO_SURFACE))
403       return _eglError(EGL_BAD_SURFACE, __FUNCTION__);
404
405    return drv->API.MakeCurrent(drv, disp, draw_surf, read_surf, context);
406 }
407
408
409 EGLBoolean EGLAPIENTRY
410 eglQueryContext(EGLDisplay dpy, EGLContext ctx,
411                 EGLint attribute, EGLint *value)
412 {
413    _EGL_DECLARE_DD_AND_CONTEXT(dpy, ctx);
414    return drv->API.QueryContext(drv, disp, context, attribute, value);
415 }
416
417
418 EGLSurface EGLAPIENTRY
419 eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
420                        NativeWindowType window, const EGLint *attrib_list)
421 {
422    _EGLDisplay *disp = _eglLookupDisplay(dpy);
423    _EGLConfig *conf = _eglLookupConfig(config, disp);
424    _EGLDriver *drv;
425    _EGLSurface *surf;
426
427    drv = _eglCheckConfig(disp, conf, __FUNCTION__);
428    if (!drv)
429       return EGL_NO_SURFACE;
430
431    surf = drv->API.CreateWindowSurface(drv, disp, conf, window, attrib_list);
432    if (surf)
433       return _eglLinkSurface(surf, disp);
434    else
435       return EGL_NO_SURFACE;
436 }
437
438
439 EGLSurface EGLAPIENTRY
440 eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
441                        NativePixmapType pixmap, const EGLint *attrib_list)
442 {
443    _EGLDisplay *disp = _eglLookupDisplay(dpy);
444    _EGLConfig *conf = _eglLookupConfig(config, disp);
445    _EGLDriver *drv;
446    _EGLSurface *surf;
447
448    drv = _eglCheckConfig(disp, conf, __FUNCTION__);
449    if (!drv)
450       return EGL_NO_SURFACE;
451
452    surf = drv->API.CreatePixmapSurface(drv, disp, conf, pixmap, attrib_list);
453    if (surf)
454       return _eglLinkSurface(surf, disp);
455    else
456       return EGL_NO_SURFACE;
457 }
458
459
460 EGLSurface EGLAPIENTRY
461 eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
462                         const EGLint *attrib_list)
463 {
464    _EGLDisplay *disp = _eglLookupDisplay(dpy);
465    _EGLConfig *conf = _eglLookupConfig(config, disp);
466    _EGLDriver *drv;
467    _EGLSurface *surf;
468
469    drv = _eglCheckConfig(disp, conf, __FUNCTION__);
470    if (!drv)
471       return EGL_NO_SURFACE;
472
473    surf = drv->API.CreatePbufferSurface(drv, disp, conf, attrib_list);
474    if (surf)
475       return _eglLinkSurface(surf, disp);
476    else
477       return EGL_NO_SURFACE;
478 }
479
480
481 EGLBoolean EGLAPIENTRY
482 eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
483 {
484    _EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
485    _eglUnlinkSurface(surf);
486    return drv->API.DestroySurface(drv, disp, surf);
487 }
488
489 EGLBoolean EGLAPIENTRY
490 eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
491                 EGLint attribute, EGLint *value)
492 {
493    _EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
494    return drv->API.QuerySurface(drv, disp, surf, attribute, value);
495 }
496
497 EGLBoolean EGLAPIENTRY
498 eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
499                  EGLint attribute, EGLint value)
500 {
501    _EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
502    return drv->API.SurfaceAttrib(drv, disp, surf, attribute, value);
503 }
504
505
506 EGLBoolean EGLAPIENTRY
507 eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
508 {
509    _EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
510    return drv->API.BindTexImage(drv, disp, surf, buffer);
511 }
512
513
514 EGLBoolean EGLAPIENTRY
515 eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
516 {
517    _EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
518    return drv->API.ReleaseTexImage(drv, disp, surf, buffer);
519 }
520
521
522 EGLBoolean EGLAPIENTRY
523 eglSwapInterval(EGLDisplay dpy, EGLint interval)
524 {
525    _EGLContext *ctx = _eglGetCurrentContext();
526    _EGLSurface *surf;
527    _EGL_DECLARE_DD(dpy);
528
529    if (!ctx || !_eglIsContextLinked(ctx) || ctx->Resource.Display != disp)
530       return _eglError(EGL_BAD_CONTEXT, __FUNCTION__);
531
532    surf = ctx->DrawSurface;
533    if (!_eglIsSurfaceLinked(surf))
534       return _eglError(EGL_BAD_SURFACE, __FUNCTION__);
535
536    return drv->API.SwapInterval(drv, disp, surf, interval);
537 }
538
539
540 EGLBoolean EGLAPIENTRY
541 eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
542 {
543    _EGLContext *ctx = _eglGetCurrentContext();
544    _EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
545
546    /* surface must be bound to current context in EGL 1.4 */
547    if (!ctx || !_eglIsContextLinked(ctx) || surf != ctx->DrawSurface)
548       return _eglError(EGL_BAD_SURFACE, __FUNCTION__);
549
550    return drv->API.SwapBuffers(drv, disp, surf);
551 }
552
553
554 EGLBoolean EGLAPIENTRY
555 eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, NativePixmapType target)
556 {
557    _EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
558    return drv->API.CopyBuffers(drv, disp, surf, target);
559 }
560
561
562 EGLBoolean EGLAPIENTRY
563 eglWaitClient(void)
564 {
565    _EGLContext *ctx = _eglGetCurrentContext();
566    _EGLDisplay *disp;
567    _EGLDriver *drv;
568
569    if (!ctx)
570       return EGL_TRUE;
571    /* let bad current context imply bad current surface */
572    if (!_eglIsContextLinked(ctx) || !_eglIsSurfaceLinked(ctx->DrawSurface))
573       return _eglError(EGL_BAD_CURRENT_SURFACE, __FUNCTION__);
574
575    /* a valid current context implies an initialized current display */
576    disp = ctx->Resource.Display;
577    drv = disp->Driver;
578    assert(drv);
579
580    return drv->API.WaitClient(drv, disp, ctx);
581 }
582
583
584 EGLBoolean EGLAPIENTRY
585 eglWaitGL(void)
586 {
587 #ifdef EGL_VERSION_1_2
588    _EGLThreadInfo *t = _eglGetCurrentThread();
589    EGLint api_index = t->CurrentAPIIndex;
590    EGLint es_index = _eglConvertApiToIndex(EGL_OPENGL_ES_API);
591    EGLBoolean ret;
592
593    if (api_index != es_index && _eglIsCurrentThreadDummy())
594       return _eglError(EGL_BAD_ALLOC, "eglWaitGL");
595
596    t->CurrentAPIIndex = es_index;
597    ret = eglWaitClient();
598    t->CurrentAPIIndex = api_index;
599    return ret;
600 #else
601    return eglWaitClient();
602 #endif
603 }
604
605
606 EGLBoolean EGLAPIENTRY
607 eglWaitNative(EGLint engine)
608 {
609    _EGLContext *ctx = _eglGetCurrentContext();
610    _EGLDisplay *disp;
611    _EGLDriver *drv;
612
613    if (!ctx)
614       return EGL_TRUE;
615    /* let bad current context imply bad current surface */
616    if (!_eglIsContextLinked(ctx) || !_eglIsSurfaceLinked(ctx->DrawSurface))
617       return _eglError(EGL_BAD_CURRENT_SURFACE, __FUNCTION__);
618
619    /* a valid current context implies an initialized current display */
620    disp = ctx->Resource.Display;
621    drv = disp->Driver;
622    assert(drv);
623
624    return drv->API.WaitNative(drv, disp, engine);
625 }
626
627
628 EGLDisplay EGLAPIENTRY
629 eglGetCurrentDisplay(void)
630 {
631    _EGLDisplay *dpy = _eglGetCurrentDisplay();
632    return _eglGetDisplayHandle(dpy);
633 }
634
635
636 EGLContext EGLAPIENTRY
637 eglGetCurrentContext(void)
638 {
639    _EGLContext *ctx = _eglGetCurrentContext();
640    return _eglGetContextHandle(ctx);
641 }
642
643
644 EGLSurface EGLAPIENTRY
645 eglGetCurrentSurface(EGLint readdraw)
646 {
647    _EGLContext *ctx = _eglGetCurrentContext();
648    _EGLSurface *surf;
649
650    if (!ctx)
651       return EGL_NO_SURFACE;
652
653    switch (readdraw) {
654    case EGL_DRAW:
655       surf = ctx->DrawSurface;
656       break;
657    case EGL_READ:
658       surf = ctx->ReadSurface;
659       break;
660    default:
661       _eglError(EGL_BAD_PARAMETER, __FUNCTION__);
662       surf = NULL;
663       break;
664    }
665
666    return _eglGetSurfaceHandle(surf);
667 }
668
669
670 EGLint EGLAPIENTRY
671 eglGetError(void)
672 {
673    _EGLThreadInfo *t = _eglGetCurrentThread();
674    EGLint e = t->LastError;
675    if (!_eglIsCurrentThreadDummy())
676       t->LastError = EGL_SUCCESS;
677    return e;
678 }
679
680
681 __eglMustCastToProperFunctionPointerType EGLAPIENTRY
682 eglGetProcAddress(const char *procname)
683 {
684    static const struct {
685       const char *name;
686       _EGLProc function;
687    } egl_functions[] = {
688       /* extensions only */
689 #ifdef EGL_MESA_screen_surface
690       { "eglChooseModeMESA", (_EGLProc) eglChooseModeMESA },
691       { "eglGetModesMESA", (_EGLProc) eglGetModesMESA },
692       { "eglGetModeAttribMESA", (_EGLProc) eglGetModeAttribMESA },
693       { "eglCopyContextMESA", (_EGLProc) eglCopyContextMESA },
694       { "eglGetScreensMESA", (_EGLProc) eglGetScreensMESA },
695       { "eglCreateScreenSurfaceMESA", (_EGLProc) eglCreateScreenSurfaceMESA },
696       { "eglShowScreenSurfaceMESA", (_EGLProc) eglShowScreenSurfaceMESA },
697       { "eglScreenPositionMESA", (_EGLProc) eglScreenPositionMESA },
698       { "eglQueryScreenMESA", (_EGLProc) eglQueryScreenMESA },
699       { "eglQueryScreenSurfaceMESA", (_EGLProc) eglQueryScreenSurfaceMESA },
700       { "eglQueryScreenModeMESA", (_EGLProc) eglQueryScreenModeMESA },
701       { "eglQueryModeStringMESA", (_EGLProc) eglQueryModeStringMESA },
702 #endif /* EGL_MESA_screen_surface */
703       { NULL, NULL }
704    };
705    EGLint i;
706
707    if (!procname)
708       return NULL;
709    if (strncmp(procname, "egl", 3) == 0) {
710       for (i = 0; egl_functions[i].name; i++) {
711          if (strcmp(egl_functions[i].name, procname) == 0)
712             return egl_functions[i].function;
713       }
714    }
715
716    _eglPreloadDrivers();
717
718    /* now loop over drivers to query their procs */
719    for (i = 0; i < _eglGlobal.NumDrivers; i++) {
720       _EGLDriver *drv = _eglGlobal.Drivers[i];
721       _EGLProc p = drv->API.GetProcAddress(drv, procname);
722       if (p)
723          return p;
724    }
725
726    return NULL;
727 }
728
729
730 #ifdef EGL_MESA_screen_surface
731
732
733 /*
734  * EGL_MESA_screen extension
735  */
736
737 EGLBoolean EGLAPIENTRY
738 eglChooseModeMESA(EGLDisplay dpy, EGLScreenMESA screen,
739                   const EGLint *attrib_list, EGLModeMESA *modes,
740                   EGLint modes_size, EGLint *num_modes)
741 {
742    _EGL_DECLARE_DD_AND_SCREEN(dpy, screen);
743    return drv->API.ChooseModeMESA(drv, disp, scrn, attrib_list,
744                                   modes, modes_size, num_modes);
745 }
746
747
748 EGLBoolean EGLAPIENTRY
749 eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes,
750                 EGLint mode_size, EGLint *num_mode)
751 {
752    _EGL_DECLARE_DD_AND_SCREEN(dpy, screen);
753    return drv->API.GetModesMESA(drv, disp, scrn, modes, mode_size, num_mode);
754 }
755
756
757 EGLBoolean EGLAPIENTRY
758 eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode,
759                      EGLint attribute, EGLint *value)
760 {
761    _EGL_DECLARE_DD_AND_MODE(dpy, mode);
762    return drv->API.GetModeAttribMESA(drv, disp, m, attribute, value);
763 }
764
765
766 EGLBoolean EGLAPIENTRY
767 eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest,
768                    EGLint mask)
769 {
770    _EGLDisplay *disp = _eglLookupDisplay(dpy);
771    _EGLContext *source_context = _eglLookupContext(source, disp);
772    _EGLContext *dest_context = _eglLookupContext(dest, disp);
773    _EGLDriver *drv;
774
775    drv = _eglCheckContext(disp, source_context, __FUNCTION__);
776    if (!drv || !dest_context) {
777       if (drv)
778          _eglError(EGL_BAD_CONTEXT, __FUNCTION__);
779       return EGL_FALSE;
780    }
781
782    return drv->API.CopyContextMESA(drv, disp, source_context, dest_context,
783                                    mask);
784 }
785
786
787 EGLBoolean
788 eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens,
789                   EGLint max_screens, EGLint *num_screens)
790 {
791    _EGL_DECLARE_DD(dpy);
792    return drv->API.GetScreensMESA(drv, disp, screens,
793                                   max_screens, num_screens);
794 }
795
796
797 EGLSurface
798 eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config,
799                            const EGLint *attrib_list)
800 {
801    _EGLDisplay *disp = _eglLookupDisplay(dpy);
802    _EGLConfig *conf = _eglLookupConfig(config, disp);
803    _EGLDriver *drv;
804    _EGLSurface *surf;
805
806    drv = _eglCheckConfig(disp, conf, __FUNCTION__);
807    if (!drv)
808       return EGL_NO_SURFACE;
809
810    surf = drv->API.CreateScreenSurfaceMESA(drv, disp, conf, attrib_list);
811    if (surf)
812       return _eglLinkSurface(surf, disp);
813    else
814       return EGL_NO_SURFACE;
815 }
816
817
818 EGLBoolean
819 eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen,
820                          EGLSurface surface, EGLModeMESA mode)
821 {
822    _EGLDisplay *disp = _eglLookupDisplay(dpy);
823    _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
824    _EGLSurface *surf = _eglLookupSurface(surface, disp);
825    _EGLMode *m = _eglLookupMode(mode, disp);
826    _EGLDriver *drv;
827
828    drv = _eglCheckScreen(disp, scrn, __FUNCTION__);
829    if (!drv)
830       return EGL_FALSE;
831    if (!surf && surface != EGL_NO_SURFACE)
832       return _eglError(EGL_BAD_SURFACE, __FUNCTION__);
833    if (!m && mode != EGL_NO_MODE_MESA)
834       return _eglError(EGL_BAD_MODE_MESA, __FUNCTION__);
835
836    return drv->API.ShowScreenSurfaceMESA(drv, disp, scrn, surf, m);
837 }
838
839
840 EGLBoolean
841 eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y)
842 {
843    _EGL_DECLARE_DD_AND_SCREEN(dpy, screen);
844    return drv->API.ScreenPositionMESA(drv, disp, scrn, x, y);
845 }
846
847
848 EGLBoolean
849 eglQueryScreenMESA(EGLDisplay dpy, EGLScreenMESA screen,
850                    EGLint attribute, EGLint *value)
851 {
852    _EGL_DECLARE_DD_AND_SCREEN(dpy, screen);
853    return drv->API.QueryScreenMESA(drv, disp, scrn, attribute, value);
854 }
855
856
857 EGLBoolean
858 eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen,
859                           EGLSurface *surface)
860 {
861    _EGLDisplay *disp = _eglLookupDisplay(dpy);
862    _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
863    _EGLDriver *drv;
864    _EGLSurface *surf;
865
866    drv = _eglCheckScreen(disp, scrn, __FUNCTION__);
867    if (!drv)
868       return EGL_FALSE;
869
870    if (drv->API.QueryScreenSurfaceMESA(drv, disp, scrn, &surf) != EGL_TRUE)
871       surf = NULL;
872    if (surface)
873       *surface = _eglGetSurfaceHandle(surf);
874    return (surf != NULL);
875 }
876
877
878 EGLBoolean
879 eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode)
880 {
881    _EGLDisplay *disp = _eglLookupDisplay(dpy);
882    _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
883    _EGLDriver *drv;
884    _EGLMode *m;
885
886    drv = _eglCheckScreen(disp, scrn, __FUNCTION__);
887    if (!drv)
888       return EGL_FALSE;
889
890    if (drv->API.QueryScreenModeMESA(drv, disp, scrn, &m) != EGL_TRUE)
891       m = NULL;
892    if (mode)
893       *mode = m->Handle;
894
895    return (m != NULL);
896 }
897
898
899 const char *
900 eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode)
901 {
902    _EGL_DECLARE_DD_AND_MODE(dpy, mode);
903    return drv->API.QueryModeStringMESA(drv, disp, m);
904 }
905
906
907 #endif /* EGL_MESA_screen_surface */
908
909
910 /**
911  ** EGL 1.2
912  **/
913
914 #ifdef EGL_VERSION_1_2
915
916
917 /**
918  * Specify the client API to use for subsequent calls including:
919  *  eglCreateContext()
920  *  eglGetCurrentContext()
921  *  eglGetCurrentDisplay()
922  *  eglGetCurrentSurface()
923  *  eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT)
924  *  eglWaitClient()
925  *  eglWaitNative()
926  * See section 3.7 "Rendering Context" in the EGL specification for details.
927  */
928 EGLBoolean
929 eglBindAPI(EGLenum api)
930 {
931    _EGLThreadInfo *t = _eglGetCurrentThread();
932
933    if (_eglIsCurrentThreadDummy())
934       return _eglError(EGL_BAD_ALLOC, "eglBindAPI");
935
936    if (!_eglIsApiValid(api))
937       return _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
938
939    t->CurrentAPIIndex = _eglConvertApiToIndex(api);
940    return EGL_TRUE;
941 }
942
943
944 /**
945  * Return the last value set with eglBindAPI().
946  */
947 EGLenum
948 eglQueryAPI(void)
949 {
950    /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */
951    _EGLThreadInfo *t = _eglGetCurrentThread();
952    return _eglConvertApiFromIndex(t->CurrentAPIIndex);
953 }
954
955
956 EGLSurface
957 eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
958                                  EGLClientBuffer buffer, EGLConfig config,
959                                  const EGLint *attrib_list)
960 {
961    _EGLDisplay *disp = _eglLookupDisplay(dpy);
962    _EGLConfig *conf = _eglLookupConfig(config, disp);
963    _EGLDriver *drv;
964    _EGLSurface *surf;
965
966    drv = _eglCheckConfig(disp, conf, __FUNCTION__);
967    if (!drv)
968       return EGL_NO_SURFACE;
969
970    surf = drv->API.CreatePbufferFromClientBuffer(drv, disp, buftype, buffer,
971                                                  conf, attrib_list);
972    if (surf)
973       return _eglLinkSurface(surf, disp);
974    else
975       return EGL_NO_SURFACE;
976 }
977
978
979 EGLBoolean
980 eglReleaseThread(void)
981 {
982    /* unbind current context */
983    if (!_eglIsCurrentThreadDummy()) {
984       _EGLDisplay *disp = _eglGetCurrentDisplay();
985       _EGLDriver *drv;
986       if (disp) {
987          drv = disp->Driver;
988          (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
989       }
990    }
991
992    _eglDestroyCurrentThread();
993    return EGL_TRUE;
994 }
995
996
997 #endif /* EGL_VERSION_1_2 */