eglapi.c revision d5078b94323241a6482f54797756116b1c864327
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
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include "eglcontext.h"
37#include "egldisplay.h"
38#include "egltypedefs.h"
39#include "eglglobals.h"
40#include "egldriver.h"
41#include "eglsurface.h"
42
43
44
45/**
46 * This is typically the first EGL function that an application calls.
47 * We initialize our global vars and create a private _EGLDisplay object.
48 */
49EGLDisplay EGLAPIENTRY
50eglGetDisplay(NativeDisplayType nativeDisplay)
51{
52   _EGLDisplay *dpy;
53   _eglInitGlobals();
54   dpy = _eglNewDisplay(nativeDisplay);
55   return _eglGetDisplayHandle(dpy);
56}
57
58
59/**
60 * This is typically the second EGL function that an application calls.
61 * Here we load/initialize the actual hardware driver.
62 */
63EGLBoolean EGLAPIENTRY
64eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
65{
66   if (dpy) {
67      EGLBoolean retVal;
68      _EGLDisplay *dpyPriv = _eglLookupDisplay(dpy);
69      if (!dpyPriv) {
70         return EGL_FALSE;
71      }
72      dpyPriv->Driver = _eglOpenDriver(dpyPriv,
73                                       dpyPriv->DriverName,
74                                       dpyPriv->DriverArgs);
75      if (!dpyPriv->Driver) {
76         return EGL_FALSE;
77      }
78      /* Initialize the particular driver now */
79      retVal = dpyPriv->Driver->API.Initialize(dpyPriv->Driver, dpy,
80                                               major, minor);
81
82      dpyPriv->Driver->APImajor = *major;
83      dpyPriv->Driver->APIminor = *minor;
84      snprintf(dpyPriv->Driver->Version, sizeof(dpyPriv->Driver->Version),
85               "%d.%d (%s)", *major, *minor, dpyPriv->Driver->Name);
86
87      return retVal;
88   }
89   return EGL_FALSE;
90}
91
92
93EGLBoolean EGLAPIENTRY
94eglTerminate(EGLDisplay dpy)
95{
96   _EGLDriver *drv = _eglLookupDriver(dpy);
97   if (drv)
98      return _eglCloseDriver(drv, dpy);
99   else
100      return EGL_FALSE;
101}
102
103
104const char * EGLAPIENTRY
105eglQueryString(EGLDisplay dpy, EGLint name)
106{
107   _EGLDriver *drv = _eglLookupDriver(dpy);
108   if (drv)
109      return drv->API.QueryString(drv, dpy, name);
110   else
111      return NULL;
112}
113
114
115EGLBoolean EGLAPIENTRY
116eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
117{
118   _EGLDriver *drv = _eglLookupDriver(dpy);
119   /* XXX check drv for null in remaining functions */
120   return drv->API.GetConfigs(drv, dpy, configs, config_size, num_config);
121}
122
123
124EGLBoolean EGLAPIENTRY
125eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
126{
127   _EGLDriver *drv = _eglLookupDriver(dpy);
128   return drv->API.ChooseConfig(drv, dpy, attrib_list, configs, config_size, num_config);
129}
130
131
132EGLBoolean EGLAPIENTRY
133eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
134{
135   _EGLDriver *drv = _eglLookupDriver(dpy);
136   return drv->API.GetConfigAttrib(drv, dpy, config, attribute, value);
137}
138
139
140EGLContext EGLAPIENTRY
141eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list)
142{
143   _EGLDriver *drv = _eglLookupDriver(dpy);
144   return drv->API.CreateContext(drv, dpy, config, share_list, attrib_list);
145}
146
147
148EGLBoolean EGLAPIENTRY
149eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
150{
151   _EGLDriver *drv = _eglLookupDriver(dpy);
152   return drv->API.DestroyContext(drv, dpy, ctx);
153}
154
155
156EGLBoolean EGLAPIENTRY
157eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
158{
159   _EGLDriver *drv = _eglLookupDriver(dpy);
160   return drv->API.MakeCurrent(drv, dpy, draw, read, ctx);
161}
162
163
164EGLBoolean EGLAPIENTRY
165eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
166{
167   _EGLDriver *drv = _eglLookupDriver(dpy);
168   return drv->API.QueryContext(drv, dpy, ctx, attribute, value);
169}
170
171
172EGLSurface EGLAPIENTRY
173eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list)
174{
175   _EGLDriver *drv = _eglLookupDriver(dpy);
176   return drv->API.CreateWindowSurface(drv, dpy, config, window, attrib_list);
177}
178
179
180EGLSurface EGLAPIENTRY
181eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list)
182{
183   _EGLDriver *drv = _eglLookupDriver(dpy);
184   return drv->API.CreatePixmapSurface(drv, dpy, config, pixmap, attrib_list);
185}
186
187
188EGLSurface EGLAPIENTRY
189eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
190{
191   _EGLDriver *drv = _eglLookupDriver(dpy);
192   return drv->API.CreatePbufferSurface(drv, dpy, config, attrib_list);
193}
194
195
196EGLBoolean EGLAPIENTRY
197eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
198{
199   _EGLDriver *drv = _eglLookupDriver(dpy);
200   return drv->API.DestroySurface(drv, dpy, surface);
201}
202
203
204EGLBoolean EGLAPIENTRY
205eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
206{
207   _EGLDriver *drv = _eglLookupDriver(dpy);
208   return drv->API.QuerySurface(drv, dpy, surface, attribute, value);
209}
210
211
212EGLBoolean EGLAPIENTRY
213eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
214{
215   _EGLDriver *drv = _eglLookupDriver(dpy);
216   return drv->API.SurfaceAttrib(drv, dpy, surface, attribute, value);
217}
218
219
220EGLBoolean EGLAPIENTRY
221eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
222{
223   _EGLDriver *drv = _eglLookupDriver(dpy);
224   return drv->API.BindTexImage(drv, dpy, surface, buffer);
225}
226
227
228EGLBoolean EGLAPIENTRY
229eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
230{
231   _EGLDriver *drv = _eglLookupDriver(dpy);
232   return drv->API.ReleaseTexImage(drv, dpy, surface, buffer);
233}
234
235
236EGLBoolean EGLAPIENTRY
237eglSwapInterval(EGLDisplay dpy, EGLint interval)
238{
239   _EGLDriver *drv = _eglLookupDriver(dpy);
240   return drv->API.SwapInterval(drv, dpy, interval);
241}
242
243
244EGLBoolean EGLAPIENTRY
245eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
246{
247   _EGLDriver *drv = _eglLookupDriver(dpy);
248   return drv->API.SwapBuffers(drv, dpy, draw);
249}
250
251
252EGLBoolean EGLAPIENTRY
253eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, NativePixmapType target)
254{
255   _EGLDriver *drv = _eglLookupDriver(dpy);
256   return drv->API.CopyBuffers(drv, dpy, surface, target);
257}
258
259
260EGLBoolean EGLAPIENTRY
261eglWaitGL(void)
262{
263   EGLDisplay dpy = eglGetCurrentDisplay();
264   if (dpy != EGL_NO_DISPLAY) {
265      _EGLDriver *drv = _eglLookupDriver(dpy);
266      return drv->API.WaitGL(drv, dpy);
267   }
268   else
269      return EGL_FALSE;
270}
271
272
273EGLBoolean EGLAPIENTRY
274eglWaitNative(EGLint engine)
275{
276   EGLDisplay dpy = eglGetCurrentDisplay();
277   if (dpy != EGL_NO_DISPLAY) {
278      _EGLDriver *drv = _eglLookupDriver(dpy);
279      return drv->API.WaitNative(drv, dpy, engine);
280   }
281   else
282      return EGL_FALSE;
283}
284
285
286EGLDisplay EGLAPIENTRY
287eglGetCurrentDisplay(void)
288{
289   _EGLDisplay *dpy = _eglGetCurrentDisplay();
290   return _eglGetDisplayHandle(dpy);
291}
292
293
294EGLContext EGLAPIENTRY
295eglGetCurrentContext(void)
296{
297   _EGLContext *ctx = _eglGetCurrentContext();
298   return _eglGetContextHandle(ctx);
299}
300
301
302EGLSurface EGLAPIENTRY
303eglGetCurrentSurface(EGLint readdraw)
304{
305   _EGLSurface *s = _eglGetCurrentSurface(readdraw);
306   return _eglGetSurfaceHandle(s);
307}
308
309
310EGLint EGLAPIENTRY
311eglGetError(void)
312{
313   _EGLThreadInfo *t = _eglGetCurrentThread();
314   EGLint e = t->LastError;
315   t->LastError = EGL_SUCCESS;
316   return e;
317}
318
319
320void (* EGLAPIENTRY eglGetProcAddress(const char *procname))()
321{
322   typedef void (*genericFunc)();
323   struct name_function {
324      const char *name;
325      _EGLProc function;
326   };
327   static struct name_function egl_functions[] = {
328      /* alphabetical order */
329      { "eglBindTexImage", (_EGLProc) eglBindTexImage },
330      { "eglChooseConfig", (_EGLProc) eglChooseConfig },
331      { "eglCopyBuffers", (_EGLProc) eglCopyBuffers },
332      { "eglCreateContext", (_EGLProc) eglCreateContext },
333      { "eglCreatePbufferSurface", (_EGLProc) eglCreatePbufferSurface },
334      { "eglCreatePixmapSurface", (_EGLProc) eglCreatePixmapSurface },
335      { "eglCreateWindowSurface", (_EGLProc) eglCreateWindowSurface },
336      { "eglDestroyContext", (_EGLProc) eglDestroyContext },
337      { "eglDestroySurface", (_EGLProc) eglDestroySurface },
338      { "eglGetConfigAttrib", (_EGLProc) eglGetConfigAttrib },
339      { "eglGetConfigs", (_EGLProc) eglGetConfigs },
340      { "eglGetCurrentContext", (_EGLProc) eglGetCurrentContext },
341      { "eglGetCurrentDisplay", (_EGLProc) eglGetCurrentDisplay },
342      { "eglGetCurrentSurface", (_EGLProc) eglGetCurrentSurface },
343      { "eglGetDisplay", (_EGLProc) eglGetDisplay },
344      { "eglGetError", (_EGLProc) eglGetError },
345      { "eglGetProcAddress", (_EGLProc) eglGetProcAddress },
346      { "eglInitialize", (_EGLProc) eglInitialize },
347      { "eglMakeCurrent", (_EGLProc) eglMakeCurrent },
348      { "eglQueryContext", (_EGLProc) eglQueryContext },
349      { "eglQueryString", (_EGLProc) eglQueryString },
350      { "eglQuerySurface", (_EGLProc) eglQuerySurface },
351      { "eglReleaseTexImage", (_EGLProc) eglReleaseTexImage },
352      { "eglSurfaceAttrib", (_EGLProc) eglSurfaceAttrib },
353      { "eglSwapBuffers", (_EGLProc) eglSwapBuffers },
354      { "eglSwapInterval", (_EGLProc) eglSwapInterval },
355      { "eglTerminate", (_EGLProc) eglTerminate },
356      { "eglWaitGL", (_EGLProc) eglWaitGL },
357      { "eglWaitNative", (_EGLProc) eglWaitNative },
358      /* Extensions */
359#ifdef EGL_MESA_screen_surface
360      { "eglChooseModeMESA", (_EGLProc) eglChooseModeMESA },
361      { "eglGetModesMESA", (_EGLProc) eglGetModesMESA },
362      { "eglGetModeAttribMESA", (_EGLProc) eglGetModeAttribMESA },
363      { "eglCopyContextMESA", (_EGLProc) eglCopyContextMESA },
364      { "eglGetScreensMESA", (_EGLProc) eglGetScreensMESA },
365      { "eglCreateScreenSurfaceMESA", (_EGLProc) eglCreateScreenSurfaceMESA },
366      { "eglShowScreenSurfaceMESA", (_EGLProc) eglShowScreenSurfaceMESA },
367      { "eglScreenPositionMESA", (_EGLProc) eglScreenPositionMESA },
368      { "eglQueryScreenMESA", (_EGLProc) eglQueryScreenMESA },
369      { "eglQueryScreenSurfaceMESA", (_EGLProc) eglQueryScreenSurfaceMESA },
370      { "eglQueryScreenModeMESA", (_EGLProc) eglQueryScreenModeMESA },
371      { "eglQueryModeStringMESA", (_EGLProc) eglQueryModeStringMESA },
372#endif /* EGL_MESA_screen_surface */
373#ifdef EGL_VERSION_1_2
374      { "eglBindAPI", (_EGLProc) eglBindAPI },
375      { "eglCreatePbufferFromClientBuffer", (_EGLProc) eglCreatePbufferFromClientBuffer },
376      { "eglQueryAPI", (_EGLProc) eglQueryAPI },
377      { "eglReleaseThread", (_EGLProc) eglReleaseThread },
378      { "eglWaitClient", (_EGLProc) eglWaitClient },
379#endif /* EGL_VERSION_1_2 */
380      { NULL, NULL }
381   };
382   EGLint i;
383   for (i = 0; egl_functions[i].name; i++) {
384      if (strcmp(egl_functions[i].name, procname) == 0) {
385         return (genericFunc) egl_functions[i].function;
386      }
387   }
388#if 0
389   /* XXX enable this code someday */
390   return (genericFunc) _glapi_get_proc_address(procname);
391#else
392   return NULL;
393#endif
394}
395
396
397/*
398 * EGL_MESA_screen extension
399 */
400
401EGLBoolean EGLAPIENTRY
402eglChooseModeMESA(EGLDisplay dpy, EGLScreenMESA screen,
403                  const EGLint *attrib_list, EGLModeMESA *modes,
404                  EGLint modes_size, EGLint *num_modes)
405{
406   _EGLDriver *drv = _eglLookupDriver(dpy);
407   if (drv)
408      return drv->API.ChooseModeMESA(drv, dpy, screen, attrib_list, modes, modes_size, num_modes);
409   else
410      return EGL_FALSE;
411}
412
413
414EGLBoolean EGLAPIENTRY
415eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes, EGLint mode_size, EGLint *num_mode)
416{
417   _EGLDriver *drv = _eglLookupDriver(dpy);
418   if (drv)
419      return drv->API.GetModesMESA(drv, dpy, screen, modes, mode_size, num_mode);
420   else
421      return EGL_FALSE;
422}
423
424
425EGLBoolean EGLAPIENTRY
426eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode, EGLint attribute, EGLint *value)
427{
428   _EGLDriver *drv = _eglLookupDriver(dpy);
429   if (drv)
430      return drv->API.GetModeAttribMESA(drv, dpy, mode, attribute, value);
431   else
432      return EGL_FALSE;
433}
434
435
436EGLBoolean EGLAPIENTRY
437eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask)
438{
439   _EGLDriver *drv = _eglLookupDriver(dpy);
440   if (drv)
441      return drv->API.CopyContextMESA(drv, dpy, source, dest, mask);
442   else
443      return EGL_FALSE;
444}
445
446
447EGLBoolean
448eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens)
449{
450   _EGLDriver *drv = _eglLookupDriver(dpy);
451   if (drv)
452      return drv->API.GetScreensMESA(drv, dpy, screens, max_screens, num_screens);
453   else
454      return EGL_FALSE;
455}
456
457
458EGLSurface
459eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
460{
461   _EGLDriver *drv = _eglLookupDriver(dpy);
462   return drv->API.CreateScreenSurfaceMESA(drv, dpy, config, attrib_list);
463}
464
465
466EGLBoolean
467eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen, EGLSurface surface, EGLModeMESA mode)
468{
469   _EGLDriver *drv = _eglLookupDriver(dpy);
470   return drv->API.ShowScreenSurfaceMESA(drv, dpy, screen, surface, mode);
471}
472
473
474EGLBoolean
475eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y)
476{
477   _EGLDriver *drv = _eglLookupDriver(dpy);
478   return drv->API.ScreenPositionMESA(drv, dpy, screen, x, y);
479}
480
481
482EGLBoolean
483eglQueryScreenMESA( EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value)
484{
485   _EGLDriver *drv = _eglLookupDriver(dpy);
486   return drv->API.QueryScreenMESA(drv, dpy, screen, attribute, value);
487}
488
489
490EGLBoolean
491eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLSurface *surface)
492{
493   _EGLDriver *drv = _eglLookupDriver(dpy);
494   return drv->API.QueryScreenSurfaceMESA(drv, dpy, screen, surface);
495}
496
497
498EGLBoolean
499eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode)
500{
501   _EGLDriver *drv = _eglLookupDriver(dpy);
502   return drv->API.QueryScreenModeMESA(drv, dpy, screen, mode);
503}
504
505
506const char *
507eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode)
508{
509   _EGLDriver *drv = _eglLookupDriver(dpy);
510   return drv->API.QueryModeStringMESA(drv, dpy, mode);
511}
512
513
514/**
515 ** EGL 1.2
516 **/
517
518#ifdef EGL_VERSION_1_2
519
520
521/**
522 * Specify the client API to use for subsequent calls including:
523 *  eglCreateContext()
524 *  eglGetCurrentContext()
525 *  eglGetCurrentDisplay()
526 *  eglGetCurrentSurface()
527 *  eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT)
528 *  eglWaitClient()
529 *  eglWaitNative()
530 * See section 3.7 "Rendering Context" in the EGL specification for details.
531 */
532EGLBoolean
533eglBindAPI(EGLenum api)
534{
535   _EGLThreadInfo *t = _eglGetCurrentThread();
536
537   switch (api) {
538#ifdef EGL_VERSION_1_4
539   case EGL_OPENGL_API:
540      if (_eglGlobal.ClientAPIsMask & EGL_OPENGL_BIT) {
541         t->CurrentAPI = api;
542         return EGL_TRUE;
543      }
544      _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
545      return EGL_FALSE;
546#endif
547   case EGL_OPENGL_ES_API:
548      if (_eglGlobal.ClientAPIsMask & (EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT)) {
549         t->CurrentAPI = api;
550         return EGL_TRUE;
551      }
552      _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
553      return EGL_FALSE;
554   case EGL_OPENVG_API:
555      if (_eglGlobal.ClientAPIsMask & EGL_OPENVG_BIT) {
556         t->CurrentAPI = api;
557         return EGL_TRUE;
558      }
559      _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
560      return EGL_FALSE;
561   default:
562      return EGL_FALSE;
563   }
564   return EGL_TRUE;
565}
566
567
568/**
569 * Return the last value set with eglBindAPI().
570 */
571EGLenum
572eglQueryAPI(void)
573{
574   /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */
575   _EGLThreadInfo *t = _eglGetCurrentThread();
576   return t->CurrentAPI;
577}
578
579
580EGLSurface
581eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
582                                 EGLClientBuffer buffer, EGLConfig config,
583                                 const EGLint *attrib_list)
584{
585   _EGLDriver *drv = _eglLookupDriver(dpy);
586   return drv->API.CreatePbufferFromClientBuffer(drv, dpy, buftype, buffer,
587                                                 config, attrib_list);
588}
589
590
591EGLBoolean
592eglReleaseThread(void)
593{
594   _EGLThreadInfo *t = _eglGetCurrentThread();
595   EGLDisplay dpy = eglGetCurrentDisplay();
596   if (dpy) {
597      _EGLDriver *drv = _eglLookupDriver(dpy);
598      /* unbind context */
599      (void) drv->API.MakeCurrent(drv, dpy, EGL_NO_SURFACE,
600                                  EGL_NO_SURFACE, EGL_NO_CONTEXT);
601   }
602   _eglDeleteThreadData(t);
603   return EGL_TRUE;
604}
605
606
607EGLBoolean
608eglWaitClient(void)
609{
610   EGLDisplay dpy = eglGetCurrentDisplay();
611   if (dpy != EGL_NO_DISPLAY) {
612      _EGLDriver *drv = _eglLookupDriver(dpy);
613      return drv->API.WaitClient(drv, dpy);
614   }
615   else
616      return EGL_FALSE;
617}
618
619#endif /* EGL_VERSION_1_2 */
620