OSDN Git Service

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