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