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