Some initial per-thread support.
[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 <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
42
43
44 /**
45  * NOTE: displayName is treated as a string in _eglChooseDriver()!!!
46  * This will probably change!
47  * See _eglChooseDriver() for details!
48  */
49 EGLDisplay APIENTRY
50 eglGetDisplay(NativeDisplayType displayName)
51 {
52    _EGLDisplay *dpy;
53    _eglInitGlobals();
54    dpy = _eglNewDisplay(displayName);
55    if (dpy)
56       return dpy->Handle;
57    else
58       return EGL_NO_DISPLAY;
59 }
60
61
62 EGLBoolean APIENTRY
63 eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
64 {
65    if (dpy) {
66       _EGLDriver *drv = _eglChooseDriver(dpy);
67       if (drv)
68          return drv->API.Initialize(drv, dpy, major, minor);
69    }
70    return EGL_FALSE;
71 }
72
73
74 EGLBoolean APIENTRY
75 eglTerminate(EGLDisplay dpy)
76 {
77    _EGLDriver *drv = _eglLookupDriver(dpy);
78    if (drv)
79       return _eglCloseDriver(drv, dpy);
80    else
81       return EGL_FALSE;
82 }
83
84
85 const char * APIENTRY
86 eglQueryString(EGLDisplay dpy, EGLint name)
87 {
88    _EGLDriver *drv = _eglLookupDriver(dpy);
89    if (drv)
90       return drv->API.QueryString(drv, dpy, name);
91    else
92       return NULL;
93 }
94
95
96 EGLBoolean APIENTRY
97 eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
98 {
99    _EGLDriver *drv = _eglLookupDriver(dpy);
100    /* XXX check drv for null in remaining functions */
101    return drv->API.GetConfigs(drv, dpy, configs, config_size, num_config);
102 }
103
104
105 EGLBoolean APIENTRY
106 eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
107 {
108    _EGLDriver *drv = _eglLookupDriver(dpy);
109    return drv->API.ChooseConfig(drv, dpy, attrib_list, configs, config_size, num_config);
110 }
111
112
113 EGLBoolean APIENTRY
114 eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
115 {
116    _EGLDriver *drv = _eglLookupDriver(dpy);
117    return drv->API.GetConfigAttrib(drv, dpy, config, attribute, value);
118 }
119
120
121 EGLContext APIENTRY
122 eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list)
123 {
124    _EGLDriver *drv = _eglLookupDriver(dpy);
125    return drv->API.CreateContext(drv, dpy, config, share_list, attrib_list);
126 }
127
128
129 EGLBoolean APIENTRY
130 eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
131 {
132    _EGLDriver *drv = _eglLookupDriver(dpy);
133    return drv->API.DestroyContext(drv, dpy, ctx);
134 }
135
136
137 EGLBoolean APIENTRY
138 eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
139 {
140    _EGLDriver *drv = _eglLookupDriver(dpy);
141    return drv->API.MakeCurrent(drv, dpy, draw, read, ctx);
142 }
143
144
145 EGLBoolean APIENTRY
146 eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
147 {
148    _EGLDriver *drv = _eglLookupDriver(dpy);
149    return drv->API.QueryContext(drv, dpy, ctx, attribute, value);
150 }
151
152
153 EGLSurface APIENTRY
154 eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list)
155 {
156    _EGLDriver *drv = _eglLookupDriver(dpy);
157    return drv->API.CreateWindowSurface(drv, dpy, config, window, attrib_list);
158 }
159
160
161 EGLSurface APIENTRY
162 eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list)
163 {
164    _EGLDriver *drv = _eglLookupDriver(dpy);
165    return drv->API.CreatePixmapSurface(drv, dpy, config, pixmap, attrib_list);
166 }
167
168
169 EGLSurface APIENTRY
170 eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
171 {
172    _EGLDriver *drv = _eglLookupDriver(dpy);
173    return drv->API.CreatePbufferSurface(drv, dpy, config, attrib_list);
174 }
175
176
177 EGLBoolean APIENTRY
178 eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
179 {
180    _EGLDriver *drv = _eglLookupDriver(dpy);
181    return drv->API.DestroySurface(drv, dpy, surface);
182 }
183
184
185 EGLBoolean APIENTRY
186 eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
187 {
188    _EGLDriver *drv = _eglLookupDriver(dpy);
189    return drv->API.QuerySurface(drv, dpy, surface, attribute, value);
190 }
191
192
193 EGLBoolean APIENTRY
194 eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
195 {
196    _EGLDriver *drv = _eglLookupDriver(dpy);
197    return drv->API.SurfaceAttrib(drv, dpy, surface, attribute, value);
198 }
199
200
201 EGLBoolean APIENTRY
202 eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
203 {
204    _EGLDriver *drv = _eglLookupDriver(dpy);
205    return drv->API.BindTexImage(drv, dpy, surface, buffer);
206 }
207
208
209 EGLBoolean APIENTRY
210 eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
211 {
212    _EGLDriver *drv = _eglLookupDriver(dpy);
213    return drv->API.ReleaseTexImage(drv, dpy, surface, buffer);
214 }
215
216
217 EGLBoolean APIENTRY
218 eglSwapInterval(EGLDisplay dpy, EGLint interval)
219 {
220    _EGLDriver *drv = _eglLookupDriver(dpy);
221    return drv->API.SwapInterval(drv, dpy, interval);
222 }
223
224
225 EGLBoolean APIENTRY
226 eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
227 {
228    _EGLDriver *drv = _eglLookupDriver(dpy);
229    return drv->API.SwapBuffers(drv, dpy, draw);
230 }
231
232
233 EGLBoolean APIENTRY
234 eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, NativePixmapType target)
235 {
236    _EGLDriver *drv = _eglLookupDriver(dpy);
237    return drv->API.CopyBuffers(drv, dpy, surface, target);
238 }
239
240
241 EGLBoolean APIENTRY
242 eglWaitGL(void)
243 {
244    EGLDisplay dpy = eglGetCurrentDisplay();
245    if (dpy != EGL_NO_DISPLAY) {
246       _EGLDriver *drv = _eglLookupDriver(dpy);
247       return drv->API.WaitGL(drv, dpy);
248    }
249    else
250       return EGL_FALSE;
251 }
252
253
254 EGLBoolean APIENTRY
255 eglWaitNative(EGLint engine)
256 {
257    EGLDisplay dpy = eglGetCurrentDisplay();
258    if (dpy != EGL_NO_DISPLAY) {
259       _EGLDriver *drv = _eglLookupDriver(dpy);
260       return drv->API.WaitNative(drv, dpy, engine);
261    }
262    else
263       return EGL_FALSE;
264 }
265
266
267 EGLDisplay APIENTRY
268 eglGetCurrentDisplay(void)
269 {
270    _EGLDisplay *dpy = _eglGetCurrentDisplay();
271    if (dpy)
272       return dpy->Handle;
273    else
274       return EGL_NO_DISPLAY;
275 }
276
277
278 EGLContext APIENTRY
279 eglGetCurrentContext(void)
280 {
281    _EGLContext *ctx = _eglGetCurrentContext();
282    if (ctx)
283       return ctx->Handle;
284    else
285       return EGL_NO_CONTEXT;
286 }
287
288
289 EGLSurface APIENTRY
290 eglGetCurrentSurface(EGLint readdraw)
291 {
292    _EGLSurface *s = _eglGetCurrentSurface(readdraw);
293    if (s)
294       return s->Handle;
295    else
296       return EGL_NO_SURFACE;
297 }
298
299
300 EGLint APIENTRY
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 (* APIENTRY 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       { "eglChooseModeMESA", (_EGLProc) eglChooseModeMESA },
350       { "eglGetModesMESA", (_EGLProc) eglGetModesMESA },
351       { "eglGetModeAttribMESA", (_EGLProc) eglGetModeAttribMESA },
352       { "eglCopyContextMESA", (_EGLProc) eglCopyContextMESA },
353       { "eglGetScreensMESA", (_EGLProc) eglGetScreensMESA },
354       { "eglCreateScreenSurfaceMESA", (_EGLProc) eglCreateScreenSurfaceMESA },
355       { "eglShowScreenSurfaceMESA", (_EGLProc) eglShowScreenSurfaceMESA },
356       { "eglScreenPositionMESA", (_EGLProc) eglScreenPositionMESA },
357       { "eglQueryScreenMESA", (_EGLProc) eglQueryScreenMESA },
358       { "eglQueryScreenSurfaceMESA", (_EGLProc) eglQueryScreenSurfaceMESA },
359       { "eglQueryScreenModeMESA", (_EGLProc) eglQueryScreenModeMESA },
360       { "eglQueryModeStringMESA", (_EGLProc) eglQueryModeStringMESA },
361       { NULL, NULL }
362    };
363    EGLint i;
364    for (i = 0; egl_functions[i].name; i++) {
365       if (strcmp(egl_functions[i].name, procname) == 0) {
366          return (genericFunc) egl_functions[i].function;
367       }
368    }
369 #if 0
370    /* XXX enable this code someday */
371    return (genericFunc) _glapi_get_proc_address(procname);
372 #else
373    return NULL;
374 #endif
375 }
376
377
378 /*
379  * EGL_MESA_screen extension
380  */
381
382 EGLBoolean APIENTRY
383 eglChooseModeMESA(EGLDisplay dpy, EGLScreenMESA screen,
384                   const EGLint *attrib_list, EGLModeMESA *modes,
385                   EGLint modes_size, EGLint *num_modes)
386 {
387    _EGLDriver *drv = _eglLookupDriver(dpy);
388    if (drv)
389       return drv->API.ChooseModeMESA(drv, dpy, screen, attrib_list, modes, modes_size, num_modes);
390    else
391       return EGL_FALSE;
392 }
393
394
395 EGLBoolean APIENTRY
396 eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes, EGLint mode_size, EGLint *num_mode)
397 {
398    _EGLDriver *drv = _eglLookupDriver(dpy);
399    if (drv)
400       return drv->API.GetModesMESA(drv, dpy, screen, modes, mode_size, num_mode);
401    else
402       return EGL_FALSE;
403 }
404
405
406 EGLBoolean APIENTRY
407 eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode, EGLint attribute, EGLint *value)
408 {
409    _EGLDriver *drv = _eglLookupDriver(dpy);
410    if (drv)
411       return drv->API.GetModeAttribMESA(drv, dpy, mode, attribute, value);
412    else
413       return EGL_FALSE;
414 }
415
416
417 EGLBoolean APIENTRY
418 eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask)
419 {
420    _EGLDriver *drv = _eglLookupDriver(dpy);
421    if (drv)
422       return drv->API.CopyContextMESA(drv, dpy, source, dest, mask);
423    else
424       return EGL_FALSE;
425 }
426
427
428 EGLBoolean
429 eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens)
430 {
431    _EGLDriver *drv = _eglLookupDriver(dpy);
432    if (drv)
433       return drv->API.GetScreensMESA(drv, dpy, screens, max_screens, num_screens);
434    else
435       return EGL_FALSE;
436 }
437
438
439 EGLSurface
440 eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
441 {
442    _EGLDriver *drv = _eglLookupDriver(dpy);
443    return drv->API.CreateScreenSurfaceMESA(drv, dpy, config, attrib_list);
444 }
445
446
447 EGLBoolean
448 eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen, EGLSurface surface, EGLModeMESA mode)
449 {
450    _EGLDriver *drv = _eglLookupDriver(dpy);
451    return drv->API.ShowScreenSurfaceMESA(drv, dpy, screen, surface, mode);
452 }
453
454
455 EGLBoolean
456 eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y)
457 {
458    _EGLDriver *drv = _eglLookupDriver(dpy);
459    return drv->API.ScreenPositionMESA(drv, dpy, screen, x, y);
460 }
461
462
463 EGLBoolean
464 eglQueryScreenMESA( EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value)
465 {
466    _EGLDriver *drv = _eglLookupDriver(dpy);
467    return drv->API.QueryScreenMESA(drv, dpy, screen, attribute, value);
468 }
469
470
471 EGLBoolean
472 eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLSurface *surface)
473 {
474    _EGLDriver *drv = _eglLookupDriver(dpy);
475    return drv->API.QueryScreenSurfaceMESA(drv, dpy, screen, surface);
476 }
477
478
479 EGLBoolean
480 eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode)
481 {
482    _EGLDriver *drv = _eglLookupDriver(dpy);
483    return drv->API.QueryScreenModeMESA(drv, dpy, screen, mode);
484 }
485
486
487 const char *
488 eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode)
489 {
490    _EGLDriver *drv = _eglLookupDriver(dpy);
491    return drv->API.QueryModeStringMESA(drv, dpy, mode);
492 }
493
494
495
496
497