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