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