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