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