egl: Make eglGetDisplay atomic.
[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. Internal objects are linked to a display to
13 * create the handles.
14 *
15 * For each public API entry point, the opaque handles are looked up
16 * before being dispatched to the drivers. When it fails to look up
17 * a handle, one of
18 *
19 * EGL_BAD_DISPLAY
20 * EGL_BAD_CONFIG
21 * EGL_BAD_CONTEXT
22 * EGL_BAD_SURFACE
23 * EGL_BAD_SCREEN_MESA
24 * EGL_BAD_MODE_MESA
25 *
26 * is generated and the driver function is not called. An
27 * uninitialized EGLDisplay has no driver associated with it. When
28 * such display is detected,
29 *
30 * EGL_NOT_INITIALIZED
31 *
32 * is generated.
33 *
34 * Some of the entry points use current display, context, or surface
35 * implicitly. For such entry points, the implicit objects are also
36 * checked before calling the driver function. Other than the
37 * errors listed above,
38 *
39 * EGL_BAD_CURRENT_SURFACE
40 *
41 * may also be generated.
42 *
43 * Notes on naming conventions:
44 *
45 * eglFooBar - public EGL function
46 * EGL_FOO_BAR - public EGL token
47 * EGLDatatype - public EGL datatype
48 *
49 * _eglFooBar - private EGL function
50 * _EGLDatatype - private EGL datatype, typedef'd struct
51 * _egl_struct - private EGL struct, non-typedef'd
52 *
53 */
54
55
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include "eglcontext.h"
60 #include "egldisplay.h"
61 #include "egltypedefs.h"
62 #include "eglglobals.h"
63 #include "eglcurrent.h"
64 #include "egldriver.h"
65 #include "eglsurface.h"
66 #include "eglconfig.h"
67 #include "eglscreen.h"
68 #include "eglmode.h"
69 #include "eglimage.h"
70
71
72 /**
73 * Macros to help return an API entrypoint.
74 */
75 #define _EGL_ERROR(disp, err, ret) \
76 ({ \
77 /* EGL error codes are non-zero */ \
78 if (err) \
79 _eglError(err, __FUNCTION__); \
80 ret; \
81 })
82 #define _EGL_SUCCESS(disp, ret) _EGL_ERROR(disp, EGL_SUCCESS, ret)
83 /* record EGL_SUCCESS only when ret evaluates to true */
84 #define _EGL_EVAL(disp, ret) _EGL_ERROR(disp, (ret) ? EGL_SUCCESS : 0, ret)
85
86
87 /**
88 * A bunch of macros and checks to simplify error checking.
89 */
90 #define _EGL_CHECK_DISPLAY(disp, ret) \
91 ({ \
92 _EGLDriver *__drv = _eglCheckDisplay(disp, __FUNCTION__); \
93 if (!__drv) \
94 return _EGL_ERROR(disp, 0, ret); \
95 __drv; \
96 })
97
98
99 #define _EGL_CHECK_OBJECT(disp, type, obj, ret) \
100 ({ \
101 _EGLDriver *__drv = _eglCheck ## type(disp, obj, __FUNCTION__); \
102 if (!__drv) \
103 return _EGL_ERROR(disp, 0, ret); \
104 __drv; \
105 })
106 #define _EGL_CHECK_SURFACE(disp, surf, ret) \
107 _EGL_CHECK_OBJECT(disp, Surface, surf, ret)
108 #define _EGL_CHECK_CONTEXT(disp, context, ret) \
109 _EGL_CHECK_OBJECT(disp, Context, context, ret)
110 #define _EGL_CHECK_CONFIG(disp, conf, ret) \
111 _EGL_CHECK_OBJECT(disp, Config, conf, ret)
112 #define _EGL_CHECK_SCREEN(disp, scrn, ret) \
113 _EGL_CHECK_OBJECT(disp, Screen, scrn, ret)
114 #define _EGL_CHECK_MODE(disp, m, ret) \
115 _EGL_CHECK_OBJECT(disp, Mode, m, ret)
116
117
118 static INLINE _EGLDriver *
119 _eglCheckDisplay(_EGLDisplay *disp, const char *msg)
120 {
121 if (!disp) {
122 _eglError(EGL_BAD_DISPLAY, msg);
123 return NULL;
124 }
125 if (!disp->Initialized) {
126 _eglError(EGL_NOT_INITIALIZED, msg);
127 return NULL;
128 }
129 return disp->Driver;
130 }
131
132
133 static INLINE _EGLDriver *
134 _eglCheckSurface(_EGLDisplay *disp, _EGLSurface *surf, const char *msg)
135 {
136 _EGLDriver *drv = _eglCheckDisplay(disp, msg);
137 if (!drv)
138 return NULL;
139 if (!surf) {
140 _eglError(EGL_BAD_SURFACE, msg);
141 return NULL;
142 }
143 return drv;
144 }
145
146
147 static INLINE _EGLDriver *
148 _eglCheckContext(_EGLDisplay *disp, _EGLContext *context, const char *msg)
149 {
150 _EGLDriver *drv = _eglCheckDisplay(disp, msg);
151 if (!drv)
152 return NULL;
153 if (!context) {
154 _eglError(EGL_BAD_CONTEXT, msg);
155 return NULL;
156 }
157 return drv;
158 }
159
160
161 static INLINE _EGLDriver *
162 _eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg)
163 {
164 _EGLDriver *drv = _eglCheckDisplay(disp, msg);
165 if (!drv)
166 return NULL;
167 if (!conf) {
168 _eglError(EGL_BAD_CONFIG, msg);
169 return NULL;
170 }
171 return drv;
172 }
173
174
175 #ifdef EGL_MESA_screen_surface
176
177
178 static INLINE _EGLDriver *
179 _eglCheckScreen(_EGLDisplay *disp, _EGLScreen *scrn, const char *msg)
180 {
181 _EGLDriver *drv = _eglCheckDisplay(disp, msg);
182 if (!drv)
183 return NULL;
184 if (!scrn) {
185 _eglError(EGL_BAD_SCREEN_MESA, msg);
186 return NULL;
187 }
188 return drv;
189 }
190
191
192 static INLINE _EGLDriver *
193 _eglCheckMode(_EGLDisplay *disp, _EGLMode *m, const char *msg)
194 {
195 _EGLDriver *drv = _eglCheckDisplay(disp, msg);
196 if (!drv)
197 return NULL;
198 if (!m) {
199 _eglError(EGL_BAD_MODE_MESA, msg);
200 return NULL;
201 }
202 return drv;
203 }
204
205
206 #endif /* EGL_MESA_screen_surface */
207
208
209 /**
210 * This is typically the first EGL function that an application calls.
211 * It associates a private _EGLDisplay object to the native display.
212 */
213 EGLDisplay EGLAPIENTRY
214 eglGetDisplay(EGLNativeDisplayType nativeDisplay)
215 {
216 _EGLDisplay *dpy = _eglFindDisplay(nativeDisplay);
217 return _eglGetDisplayHandle(dpy);
218 }
219
220
221 /**
222 * This is typically the second EGL function that an application calls.
223 * Here we load/initialize the actual hardware driver.
224 */
225 EGLBoolean EGLAPIENTRY
226 eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
227 {
228 _EGLDisplay *disp = _eglLookupDisplay(dpy);
229 EGLint major_int, minor_int;
230
231 if (!disp)
232 return _EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
233
234 if (!disp->Initialized) {
235 _EGLDriver *drv = disp->Driver;
236
237 if (!drv) {
238 _eglPreloadDrivers();
239 drv = _eglMatchDriver(disp);
240 if (!drv)
241 return _EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
242 }
243
244 /* Initialize the particular display now */
245 if (!drv->API.Initialize(drv, disp, &major_int, &minor_int))
246 return _EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
247
248 disp->APImajor = major_int;
249 disp->APIminor = minor_int;
250 snprintf(disp->Version, sizeof(disp->Version),
251 "%d.%d (%s)", major_int, minor_int, drv->Name);
252
253 /* limit to APIs supported by core */
254 disp->ClientAPIsMask &= _EGL_API_ALL_BITS;
255
256 disp->Driver = drv;
257 disp->Initialized = EGL_TRUE;
258 } else {
259 major_int = disp->APImajor;
260 minor_int = disp->APIminor;
261 }
262
263 /* Update applications version of major and minor if not NULL */
264 if ((major != NULL) && (minor != NULL)) {
265 *major = major_int;
266 *minor = minor_int;
267 }
268
269 return _EGL_SUCCESS(disp, EGL_TRUE);
270 }
271
272
273 EGLBoolean EGLAPIENTRY
274 eglTerminate(EGLDisplay dpy)
275 {
276 _EGLDisplay *disp = _eglLookupDisplay(dpy);
277
278 if (!disp)
279 return _EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
280
281 if (disp->Initialized) {
282 _EGLDriver *drv = disp->Driver;
283
284 drv->API.Terminate(drv, disp);
285 /* do not reset disp->Driver */
286 disp->Initialized = EGL_FALSE;
287 }
288
289 return _EGL_SUCCESS(disp, EGL_TRUE);
290 }
291
292
293 const char * EGLAPIENTRY
294 eglQueryString(EGLDisplay dpy, EGLint name)
295 {
296 _EGLDisplay *disp = _eglLookupDisplay(dpy);
297 _EGLDriver *drv;
298 const char *ret;
299
300 drv = _EGL_CHECK_DISPLAY(disp, NULL);
301 ret = drv->API.QueryString(drv, disp, name);
302
303 return _EGL_EVAL(disp, ret);
304 }
305
306
307 EGLBoolean EGLAPIENTRY
308 eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
309 EGLint config_size, EGLint *num_config)
310 {
311 _EGLDisplay *disp = _eglLookupDisplay(dpy);
312 _EGLDriver *drv;
313 EGLBoolean ret;
314
315 drv = _EGL_CHECK_DISPLAY(disp, EGL_FALSE);
316 ret = drv->API.GetConfigs(drv, disp, configs, config_size, num_config);
317
318 return _EGL_EVAL(disp, ret);
319 }
320
321
322 EGLBoolean EGLAPIENTRY
323 eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs,
324 EGLint config_size, EGLint *num_config)
325 {
326 _EGLDisplay *disp = _eglLookupDisplay(dpy);
327 _EGLDriver *drv;
328 EGLBoolean ret;
329
330 drv = _EGL_CHECK_DISPLAY(disp, EGL_FALSE);
331 ret = drv->API.ChooseConfig(drv, disp, attrib_list, configs,
332 config_size, num_config);
333
334 return _EGL_EVAL(disp, ret);
335 }
336
337
338 EGLBoolean EGLAPIENTRY
339 eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
340 EGLint attribute, EGLint *value)
341 {
342 _EGLDisplay *disp = _eglLookupDisplay(dpy);
343 _EGLConfig *conf = _eglLookupConfig(config, disp);
344 _EGLDriver *drv;
345 EGLBoolean ret;
346
347 drv = _EGL_CHECK_CONFIG(disp, conf, EGL_FALSE);
348 ret = drv->API.GetConfigAttrib(drv, disp, conf, attribute, value);
349
350 return _EGL_EVAL(disp, ret);
351 }
352
353
354 EGLContext EGLAPIENTRY
355 eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list,
356 const EGLint *attrib_list)
357 {
358 _EGLDisplay *disp = _eglLookupDisplay(dpy);
359 _EGLConfig *conf = _eglLookupConfig(config, disp);
360 _EGLContext *share = _eglLookupContext(share_list, disp);
361 _EGLDriver *drv;
362 _EGLContext *context;
363 EGLContext ret;
364
365 drv = _EGL_CHECK_CONFIG(disp, conf, EGL_NO_CONTEXT);
366 if (!share && share_list != EGL_NO_CONTEXT)
367 return _EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
368
369 context = drv->API.CreateContext(drv, disp, conf, share, attrib_list);
370 ret = (context) ? _eglLinkContext(context, disp) : EGL_NO_CONTEXT;
371
372 return _EGL_EVAL(disp, ret);
373 }
374
375
376 EGLBoolean EGLAPIENTRY
377 eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
378 {
379 _EGLDisplay *disp = _eglLookupDisplay(dpy);
380 _EGLContext *context = _eglLookupContext(ctx, disp);
381 _EGLDriver *drv;
382 EGLBoolean ret;
383
384 drv = _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE);
385 _eglUnlinkContext(context);
386 ret = drv->API.DestroyContext(drv, disp, context);
387
388 return _EGL_EVAL(disp, ret);
389 }
390
391
392 EGLBoolean EGLAPIENTRY
393 eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
394 EGLContext ctx)
395 {
396 _EGLDisplay *disp = _eglLookupDisplay(dpy);
397 _EGLContext *context = _eglLookupContext(ctx, disp);
398 _EGLSurface *draw_surf = _eglLookupSurface(draw, disp);
399 _EGLSurface *read_surf = _eglLookupSurface(read, disp);
400 _EGLDriver *drv;
401 EGLBoolean ret;
402
403 if (!disp)
404 return _EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
405 drv = disp->Driver;
406
407 /* display is allowed to be uninitialized under certain condition */
408 if (!disp->Initialized) {
409 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE ||
410 ctx != EGL_NO_CONTEXT)
411 return _EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
412 }
413 if (!drv)
414 return _EGL_SUCCESS(disp, EGL_TRUE);
415
416 if (!context && ctx != EGL_NO_CONTEXT)
417 return _EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
418 if ((!draw_surf && draw != EGL_NO_SURFACE) ||
419 (!read_surf && read != EGL_NO_SURFACE))
420 return _EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
421
422 ret = drv->API.MakeCurrent(drv, disp, draw_surf, read_surf, context);
423
424 return _EGL_EVAL(disp, ret);
425 }
426
427
428 EGLBoolean EGLAPIENTRY
429 eglQueryContext(EGLDisplay dpy, EGLContext ctx,
430 EGLint attribute, EGLint *value)
431 {
432 _EGLDisplay *disp = _eglLookupDisplay(dpy);
433 _EGLContext *context = _eglLookupContext(ctx, disp);
434 _EGLDriver *drv;
435 EGLBoolean ret;
436
437 drv = _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE);
438 ret = drv->API.QueryContext(drv, disp, context, attribute, value);
439
440 return _EGL_EVAL(disp, ret);
441 }
442
443
444 EGLSurface EGLAPIENTRY
445 eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
446 EGLNativeWindowType window, const EGLint *attrib_list)
447 {
448 _EGLDisplay *disp = _eglLookupDisplay(dpy);
449 _EGLConfig *conf = _eglLookupConfig(config, disp);
450 _EGLDriver *drv;
451 _EGLSurface *surf;
452 EGLSurface ret;
453
454 drv = _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE);
455
456 surf = drv->API.CreateWindowSurface(drv, disp, conf, window, attrib_list);
457 ret = (surf) ? _eglLinkSurface(surf, disp) : EGL_NO_SURFACE;
458
459 return _EGL_EVAL(disp, ret);
460 }
461
462
463 EGLSurface EGLAPIENTRY
464 eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
465 EGLNativePixmapType pixmap, const EGLint *attrib_list)
466 {
467 _EGLDisplay *disp = _eglLookupDisplay(dpy);
468 _EGLConfig *conf = _eglLookupConfig(config, disp);
469 _EGLDriver *drv;
470 _EGLSurface *surf;
471 EGLSurface ret;
472
473 drv = _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE);
474
475 surf = drv->API.CreatePixmapSurface(drv, disp, conf, pixmap, attrib_list);
476 ret = (surf) ? _eglLinkSurface(surf, disp) : EGL_NO_SURFACE;
477
478 return _EGL_EVAL(disp, ret);
479 }
480
481
482 EGLSurface EGLAPIENTRY
483 eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
484 const EGLint *attrib_list)
485 {
486 _EGLDisplay *disp = _eglLookupDisplay(dpy);
487 _EGLConfig *conf = _eglLookupConfig(config, disp);
488 _EGLDriver *drv;
489 _EGLSurface *surf;
490 EGLSurface ret;
491
492 drv = _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE);
493
494 surf = drv->API.CreatePbufferSurface(drv, disp, conf, attrib_list);
495 ret = (surf) ? _eglLinkSurface(surf, disp) : EGL_NO_SURFACE;
496
497 return _EGL_EVAL(disp, ret);
498 }
499
500
501 EGLBoolean EGLAPIENTRY
502 eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
503 {
504 _EGLDisplay *disp = _eglLookupDisplay(dpy);
505 _EGLSurface *surf = _eglLookupSurface(surface, disp);
506 _EGLDriver *drv;
507 EGLBoolean ret;
508
509 drv = _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE);
510 _eglUnlinkSurface(surf);
511 ret = drv->API.DestroySurface(drv, disp, surf);
512
513 return _EGL_EVAL(disp, ret);
514 }
515
516 EGLBoolean EGLAPIENTRY
517 eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
518 EGLint attribute, EGLint *value)
519 {
520 _EGLDisplay *disp = _eglLookupDisplay(dpy);
521 _EGLSurface *surf = _eglLookupSurface(surface, disp);
522 _EGLDriver *drv;
523 EGLBoolean ret;
524
525 drv = _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE);
526 ret = drv->API.QuerySurface(drv, disp, surf, attribute, value);
527
528 return _EGL_EVAL(disp, ret);
529 }
530
531 EGLBoolean EGLAPIENTRY
532 eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
533 EGLint attribute, EGLint value)
534 {
535 _EGLDisplay *disp = _eglLookupDisplay(dpy);
536 _EGLSurface *surf = _eglLookupSurface(surface, disp);
537 _EGLDriver *drv;
538 EGLBoolean ret;
539
540 drv = _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE);
541 ret = drv->API.SurfaceAttrib(drv, disp, surf, attribute, value);
542
543 return _EGL_EVAL(disp, ret);
544 }
545
546
547 EGLBoolean EGLAPIENTRY
548 eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
549 {
550 _EGLDisplay *disp = _eglLookupDisplay(dpy);
551 _EGLSurface *surf = _eglLookupSurface(surface, disp);
552 _EGLDriver *drv;
553 EGLBoolean ret;
554
555 drv = _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE);
556 ret = drv->API.BindTexImage(drv, disp, surf, buffer);
557
558 return _EGL_EVAL(disp, ret);
559 }
560
561
562 EGLBoolean EGLAPIENTRY
563 eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
564 {
565 _EGLDisplay *disp = _eglLookupDisplay(dpy);
566 _EGLSurface *surf = _eglLookupSurface(surface, disp);
567 _EGLDriver *drv;
568 EGLBoolean ret;
569
570 drv = _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE);
571 ret = drv->API.ReleaseTexImage(drv, disp, surf, buffer);
572
573 return _EGL_EVAL(disp, ret);
574 }
575
576
577 EGLBoolean EGLAPIENTRY
578 eglSwapInterval(EGLDisplay dpy, EGLint interval)
579 {
580 _EGLDisplay *disp = _eglLookupDisplay(dpy);
581 _EGLContext *ctx = _eglGetCurrentContext();
582 _EGLSurface *surf;
583 _EGLDriver *drv;
584 EGLBoolean ret;
585
586 drv = _EGL_CHECK_DISPLAY(disp, EGL_FALSE);
587
588 if (!ctx || !_eglIsContextLinked(ctx) || ctx->Resource.Display != disp)
589 return _EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
590
591 surf = ctx->DrawSurface;
592 if (!_eglIsSurfaceLinked(surf))
593 return _EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
594
595 ret = drv->API.SwapInterval(drv, disp, surf, interval);
596
597 return _EGL_EVAL(disp, ret);
598 }
599
600
601 EGLBoolean EGLAPIENTRY
602 eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
603 {
604 _EGLContext *ctx = _eglGetCurrentContext();
605 _EGLDisplay *disp = _eglLookupDisplay(dpy);
606 _EGLSurface *surf = _eglLookupSurface(surface, disp);
607 _EGLDriver *drv;
608 EGLBoolean ret;
609
610 drv = _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE);
611
612 /* surface must be bound to current context in EGL 1.4 */
613 if (!ctx || !_eglIsContextLinked(ctx) || surf != ctx->DrawSurface)
614 return _EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
615
616 ret = drv->API.SwapBuffers(drv, disp, surf);
617
618 return _EGL_EVAL(disp, ret);
619 }
620
621
622 EGLBoolean EGLAPIENTRY
623 eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
624 {
625 _EGLDisplay *disp = _eglLookupDisplay(dpy);
626 _EGLSurface *surf = _eglLookupSurface(surface, disp);
627 _EGLDriver *drv;
628 EGLBoolean ret;
629
630 drv = _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE);
631 ret = drv->API.CopyBuffers(drv, disp, surf, target);
632
633 return _EGL_EVAL(disp, ret);
634 }
635
636
637 EGLBoolean EGLAPIENTRY
638 eglWaitClient(void)
639 {
640 _EGLContext *ctx = _eglGetCurrentContext();
641 _EGLDisplay *disp;
642 _EGLDriver *drv;
643 EGLBoolean ret;
644
645 if (!ctx)
646 return _EGL_SUCCESS(NULL, EGL_TRUE);
647 /* let bad current context imply bad current surface */
648 if (!_eglIsContextLinked(ctx) || !_eglIsSurfaceLinked(ctx->DrawSurface))
649 return _EGL_ERROR(NULL, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
650
651 disp = ctx->Resource.Display;
652
653 /* a valid current context implies an initialized current display */
654 assert(disp->Initialized);
655 drv = disp->Driver;
656 ret = drv->API.WaitClient(drv, disp, ctx);
657
658 return _EGL_EVAL(NULL, ret);
659 }
660
661
662 EGLBoolean EGLAPIENTRY
663 eglWaitGL(void)
664 {
665 #ifdef EGL_VERSION_1_2
666 _EGLThreadInfo *t = _eglGetCurrentThread();
667 EGLint api_index = t->CurrentAPIIndex;
668 EGLint es_index = _eglConvertApiToIndex(EGL_OPENGL_ES_API);
669 EGLBoolean ret;
670
671 if (api_index != es_index && _eglIsCurrentThreadDummy())
672 return _EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
673
674 t->CurrentAPIIndex = es_index;
675 ret = eglWaitClient();
676 t->CurrentAPIIndex = api_index;
677 return ret;
678 #else
679 return eglWaitClient();
680 #endif
681 }
682
683
684 EGLBoolean EGLAPIENTRY
685 eglWaitNative(EGLint engine)
686 {
687 _EGLContext *ctx = _eglGetCurrentContext();
688 _EGLDisplay *disp;
689 _EGLDriver *drv;
690 EGLBoolean ret;
691
692 if (!ctx)
693 return _EGL_SUCCESS(NULL, EGL_TRUE);
694
695 /* let bad current context imply bad current surface */
696 if (!_eglIsContextLinked(ctx) || !_eglIsSurfaceLinked(ctx->DrawSurface))
697 return _EGL_ERROR(NULL, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
698
699 disp = ctx->Resource.Display;
700
701 /* a valid current context implies an initialized current display */
702 assert(disp->Initialized);
703 drv = disp->Driver;
704 ret = drv->API.WaitNative(drv, disp, engine);
705
706 return _EGL_EVAL(NULL, ret);
707 }
708
709
710 EGLDisplay EGLAPIENTRY
711 eglGetCurrentDisplay(void)
712 {
713 _EGLContext *ctx = _eglGetCurrentContext();
714 EGLDisplay ret;
715
716 ret = (ctx) ? _eglGetDisplayHandle(ctx->Resource.Display) : EGL_NO_DISPLAY;
717
718 return _EGL_SUCCESS(NULL, ret);
719 }
720
721
722 EGLContext EGLAPIENTRY
723 eglGetCurrentContext(void)
724 {
725 _EGLContext *ctx = _eglGetCurrentContext();
726 EGLContext ret;
727
728 ret = _eglGetContextHandle(ctx);
729
730 return _EGL_SUCCESS(NULL, ret);
731 }
732
733
734 EGLSurface EGLAPIENTRY
735 eglGetCurrentSurface(EGLint readdraw)
736 {
737 _EGLContext *ctx = _eglGetCurrentContext();
738 EGLint err = EGL_SUCCESS;
739 _EGLSurface *surf;
740 EGLSurface ret;
741
742 if (!ctx)
743 return _EGL_SUCCESS(NULL, EGL_NO_SURFACE);
744
745 switch (readdraw) {
746 case EGL_DRAW:
747 surf = ctx->DrawSurface;
748 break;
749 case EGL_READ:
750 surf = ctx->ReadSurface;
751 break;
752 default:
753 surf = NULL;
754 err = EGL_BAD_PARAMETER;
755 break;
756 }
757
758 ret = _eglGetSurfaceHandle(surf);
759
760 return _EGL_ERROR(NULL, err, ret);
761 }
762
763
764 EGLint EGLAPIENTRY
765 eglGetError(void)
766 {
767 _EGLThreadInfo *t = _eglGetCurrentThread();
768 EGLint e = t->LastError;
769 if (!_eglIsCurrentThreadDummy())
770 t->LastError = EGL_SUCCESS;
771 return e;
772 }
773
774
775 __eglMustCastToProperFunctionPointerType EGLAPIENTRY
776 eglGetProcAddress(const char *procname)
777 {
778 static const struct {
779 const char *name;
780 _EGLProc function;
781 } egl_functions[] = {
782 /* extensions only */
783 #ifdef EGL_MESA_screen_surface
784 { "eglChooseModeMESA", (_EGLProc) eglChooseModeMESA },
785 { "eglGetModesMESA", (_EGLProc) eglGetModesMESA },
786 { "eglGetModeAttribMESA", (_EGLProc) eglGetModeAttribMESA },
787 { "eglCopyContextMESA", (_EGLProc) eglCopyContextMESA },
788 { "eglGetScreensMESA", (_EGLProc) eglGetScreensMESA },
789 { "eglCreateScreenSurfaceMESA", (_EGLProc) eglCreateScreenSurfaceMESA },
790 { "eglShowScreenSurfaceMESA", (_EGLProc) eglShowScreenSurfaceMESA },
791 { "eglScreenPositionMESA", (_EGLProc) eglScreenPositionMESA },
792 { "eglQueryScreenMESA", (_EGLProc) eglQueryScreenMESA },
793 { "eglQueryScreenSurfaceMESA", (_EGLProc) eglQueryScreenSurfaceMESA },
794 { "eglQueryScreenModeMESA", (_EGLProc) eglQueryScreenModeMESA },
795 { "eglQueryModeStringMESA", (_EGLProc) eglQueryModeStringMESA },
796 #endif /* EGL_MESA_screen_surface */
797 #ifdef EGL_KHR_image_base
798 { "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR },
799 { "eglDestroyImageKHR", (_EGLProc) eglDestroyImageKHR },
800 #endif /* EGL_KHR_image_base */
801 { NULL, NULL }
802 };
803 EGLint i;
804 _EGLProc ret;
805
806 if (!procname)
807 return _EGL_SUCCESS(NULL, NULL);
808
809 ret = NULL;
810 if (strncmp(procname, "egl", 3) == 0) {
811 for (i = 0; egl_functions[i].name; i++) {
812 if (strcmp(egl_functions[i].name, procname) == 0) {
813 ret = egl_functions[i].function;
814 break;
815 }
816 }
817 }
818 if (ret)
819 return _EGL_SUCCESS(NULL, ret);
820
821 _eglPreloadDrivers();
822
823 /* now loop over drivers to query their procs */
824 for (i = 0; i < _eglGlobal.NumDrivers; i++) {
825 _EGLDriver *drv = _eglGlobal.Drivers[i];
826 ret = drv->API.GetProcAddress(drv, procname);
827 if (ret)
828 break;
829 }
830
831 return _EGL_SUCCESS(NULL, ret);
832 }
833
834
835 #ifdef EGL_MESA_screen_surface
836
837
838 /*
839 * EGL_MESA_screen extension
840 */
841
842 EGLBoolean EGLAPIENTRY
843 eglChooseModeMESA(EGLDisplay dpy, EGLScreenMESA screen,
844 const EGLint *attrib_list, EGLModeMESA *modes,
845 EGLint modes_size, EGLint *num_modes)
846 {
847 _EGLDisplay *disp = _eglLookupDisplay(dpy);
848 _EGLScreen *scrn = _eglLookupScreen(screen, disp);
849 _EGLDriver *drv;
850 EGLBoolean ret;
851
852 drv = _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE);
853 ret = drv->API.ChooseModeMESA(drv, disp, scrn, attrib_list,
854 modes, modes_size, num_modes);
855
856 return _EGL_EVAL(disp, ret);
857 }
858
859
860 EGLBoolean EGLAPIENTRY
861 eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes,
862 EGLint mode_size, EGLint *num_mode)
863 {
864 _EGLDisplay *disp = _eglLookupDisplay(dpy);
865 _EGLScreen *scrn = _eglLookupScreen(screen, disp);
866 _EGLDriver *drv;
867 EGLBoolean ret;
868
869 drv = _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE);
870 ret = drv->API.GetModesMESA(drv, disp, scrn, modes, mode_size, num_mode);
871
872 return _EGL_EVAL(disp, ret);
873 }
874
875
876 EGLBoolean EGLAPIENTRY
877 eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode,
878 EGLint attribute, EGLint *value)
879 {
880 _EGLDisplay *disp = _eglLookupDisplay(dpy);
881 _EGLMode *m = _eglLookupMode(mode, disp);
882 _EGLDriver *drv;
883 EGLBoolean ret;
884
885 drv = _EGL_CHECK_MODE(disp, m, EGL_FALSE);
886 ret = drv->API.GetModeAttribMESA(drv, disp, m, attribute, value);
887
888 return _EGL_EVAL(disp, ret);
889 }
890
891
892 EGLBoolean EGLAPIENTRY
893 eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest,
894 EGLint mask)
895 {
896 _EGLDisplay *disp = _eglLookupDisplay(dpy);
897 _EGLContext *source_context = _eglLookupContext(source, disp);
898 _EGLContext *dest_context = _eglLookupContext(dest, disp);
899 _EGLDriver *drv;
900 EGLBoolean ret;
901
902 drv = _EGL_CHECK_CONTEXT(disp, source_context, EGL_FALSE);
903 if (!dest_context)
904 return _EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
905
906 ret = drv->API.CopyContextMESA(drv, disp,
907 source_context, dest_context, mask);
908
909 return _EGL_EVAL(disp, ret);
910 }
911
912
913 EGLBoolean
914 eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens,
915 EGLint max_screens, EGLint *num_screens)
916 {
917 _EGLDisplay *disp = _eglLookupDisplay(dpy);
918 _EGLDriver *drv;
919 EGLBoolean ret;
920
921 drv = _EGL_CHECK_DISPLAY(disp, EGL_FALSE);
922 ret = drv->API.GetScreensMESA(drv, disp, screens, max_screens, num_screens);
923
924 return _EGL_EVAL(disp, ret);
925 }
926
927
928 EGLSurface
929 eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config,
930 const EGLint *attrib_list)
931 {
932 _EGLDisplay *disp = _eglLookupDisplay(dpy);
933 _EGLConfig *conf = _eglLookupConfig(config, disp);
934 _EGLDriver *drv;
935 _EGLSurface *surf;
936 EGLSurface ret;
937
938 drv = _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE);
939
940 surf = drv->API.CreateScreenSurfaceMESA(drv, disp, conf, attrib_list);
941 ret = (surf) ? _eglLinkSurface(surf, disp) : EGL_NO_SURFACE;
942
943 return _EGL_EVAL(disp, ret);
944 }
945
946
947 EGLBoolean
948 eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen,
949 EGLSurface surface, EGLModeMESA mode)
950 {
951 _EGLDisplay *disp = _eglLookupDisplay(dpy);
952 _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
953 _EGLSurface *surf = _eglLookupSurface(surface, disp);
954 _EGLMode *m = _eglLookupMode(mode, disp);
955 _EGLDriver *drv;
956 EGLBoolean ret;
957
958 drv = _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE);
959 if (!surf && surface != EGL_NO_SURFACE)
960 return _EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
961 if (!m && mode != EGL_NO_MODE_MESA)
962 return _EGL_ERROR(disp, EGL_BAD_MODE_MESA, EGL_FALSE);
963
964 ret = drv->API.ShowScreenSurfaceMESA(drv, disp, scrn, surf, m);
965
966 return _EGL_EVAL(disp, ret);
967 }
968
969
970 EGLBoolean
971 eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y)
972 {
973 _EGLDisplay *disp = _eglLookupDisplay(dpy);
974 _EGLScreen *scrn = _eglLookupScreen(screen, disp);
975 _EGLDriver *drv;
976 EGLBoolean ret;
977
978 drv = _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE);
979 ret = drv->API.ScreenPositionMESA(drv, disp, scrn, x, y);
980
981 return _EGL_EVAL(disp, ret);
982 }
983
984
985 EGLBoolean
986 eglQueryScreenMESA(EGLDisplay dpy, EGLScreenMESA screen,
987 EGLint attribute, EGLint *value)
988 {
989 _EGLDisplay *disp = _eglLookupDisplay(dpy);
990 _EGLScreen *scrn = _eglLookupScreen(screen, disp);
991 _EGLDriver *drv;
992 EGLBoolean ret;
993
994 drv = _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE);
995 ret = drv->API.QueryScreenMESA(drv, disp, scrn, attribute, value);
996
997 return _EGL_EVAL(disp, ret);
998 }
999
1000
1001 EGLBoolean
1002 eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen,
1003 EGLSurface *surface)
1004 {
1005 _EGLDisplay *disp = _eglLookupDisplay(dpy);
1006 _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
1007 _EGLDriver *drv;
1008 _EGLSurface *surf;
1009 EGLBoolean ret;
1010
1011 drv = _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE);
1012 ret = drv->API.QueryScreenSurfaceMESA(drv, disp, scrn, &surf);
1013 if (ret && surface)
1014 *surface = _eglGetSurfaceHandle(surf);
1015
1016 return _EGL_EVAL(disp, ret);
1017 }
1018
1019
1020 EGLBoolean
1021 eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode)
1022 {
1023 _EGLDisplay *disp = _eglLookupDisplay(dpy);
1024 _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
1025 _EGLDriver *drv;
1026 _EGLMode *m;
1027 EGLBoolean ret;
1028
1029 drv = _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE);
1030 ret = drv->API.QueryScreenModeMESA(drv, disp, scrn, &m);
1031 if (ret && mode)
1032 *mode = m->Handle;
1033
1034 return _EGL_EVAL(disp, ret);
1035 }
1036
1037
1038 const char *
1039 eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode)
1040 {
1041 _EGLDisplay *disp = _eglLookupDisplay(dpy);
1042 _EGLMode *m = _eglLookupMode(mode, disp);
1043 _EGLDriver *drv;
1044 const char *ret;
1045
1046 drv = _EGL_CHECK_MODE(disp, m, NULL);
1047 ret = drv->API.QueryModeStringMESA(drv, disp, m);
1048
1049 return _EGL_EVAL(disp, ret);
1050 }
1051
1052
1053 #endif /* EGL_MESA_screen_surface */
1054
1055
1056 /**
1057 ** EGL 1.2
1058 **/
1059
1060 #ifdef EGL_VERSION_1_2
1061
1062
1063 /**
1064 * Specify the client API to use for subsequent calls including:
1065 * eglCreateContext()
1066 * eglGetCurrentContext()
1067 * eglGetCurrentDisplay()
1068 * eglGetCurrentSurface()
1069 * eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT)
1070 * eglWaitClient()
1071 * eglWaitNative()
1072 * See section 3.7 "Rendering Context" in the EGL specification for details.
1073 */
1074 EGLBoolean
1075 eglBindAPI(EGLenum api)
1076 {
1077 _EGLThreadInfo *t = _eglGetCurrentThread();
1078
1079 if (_eglIsCurrentThreadDummy())
1080 return _EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
1081
1082 if (!_eglIsApiValid(api))
1083 return _EGL_ERROR(NULL, EGL_BAD_PARAMETER, EGL_FALSE);
1084
1085 t->CurrentAPIIndex = _eglConvertApiToIndex(api);
1086
1087 return _EGL_SUCCESS(NULL, EGL_TRUE);
1088 }
1089
1090
1091 /**
1092 * Return the last value set with eglBindAPI().
1093 */
1094 EGLenum
1095 eglQueryAPI(void)
1096 {
1097 _EGLThreadInfo *t = _eglGetCurrentThread();
1098 EGLenum ret;
1099
1100 /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */
1101 ret = _eglConvertApiFromIndex(t->CurrentAPIIndex);
1102
1103 return _EGL_SUCCESS(NULL, ret);
1104 }
1105
1106
1107 EGLSurface
1108 eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
1109 EGLClientBuffer buffer, EGLConfig config,
1110 const EGLint *attrib_list)
1111 {
1112 _EGLDisplay *disp = _eglLookupDisplay(dpy);
1113 _EGLConfig *conf = _eglLookupConfig(config, disp);
1114 _EGLDriver *drv;
1115 _EGLSurface *surf;
1116 EGLSurface ret;
1117
1118 drv = _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE);
1119
1120 surf = drv->API.CreatePbufferFromClientBuffer(drv, disp, buftype, buffer,
1121 conf, attrib_list);
1122 ret = (surf) ? _eglLinkSurface(surf, disp) : EGL_NO_SURFACE;
1123
1124 return _EGL_EVAL(disp, ret);
1125 }
1126
1127
1128 EGLBoolean
1129 eglReleaseThread(void)
1130 {
1131 /* unbind current contexts */
1132 if (!_eglIsCurrentThreadDummy()) {
1133 _EGLThreadInfo *t = _eglGetCurrentThread();
1134 EGLint api_index = t->CurrentAPIIndex;
1135 EGLint i;
1136
1137 for (i = 0; i < _EGL_API_NUM_APIS; i++) {
1138 _EGLContext *ctx = t->CurrentContexts[i];
1139 if (ctx) {
1140 _EGLDisplay *disp = ctx->Resource.Display;
1141 _EGLDriver *drv = disp->Driver;
1142 t->CurrentAPIIndex = i;
1143 (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
1144 }
1145 }
1146
1147 t->CurrentAPIIndex = api_index;
1148 }
1149
1150 _eglDestroyCurrentThread();
1151
1152 return _EGL_SUCCESS(NULL, EGL_TRUE);
1153 }
1154
1155
1156 #endif /* EGL_VERSION_1_2 */
1157
1158
1159 #ifdef EGL_KHR_image_base
1160
1161
1162 EGLImageKHR
1163 eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1164 EGLClientBuffer buffer, const EGLint *attr_list)
1165 {
1166 _EGLDisplay *disp = _eglLookupDisplay(dpy);
1167 _EGLContext *context = _eglLookupContext(ctx, disp);
1168 _EGLDriver *drv;
1169 _EGLImage *img;
1170 EGLImageKHR ret;
1171
1172 drv = _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR);
1173 if (!context && ctx != EGL_NO_CONTEXT)
1174 return _EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1175
1176 img = drv->API.CreateImageKHR(drv,
1177 disp, context, target, buffer, attr_list);
1178 ret = (img) ? _eglLinkImage(img, disp) : EGL_NO_IMAGE_KHR;
1179
1180 return _EGL_EVAL(disp, ret);
1181 }
1182
1183
1184 EGLBoolean
1185 eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
1186 {
1187 _EGLDisplay *disp = _eglLookupDisplay(dpy);
1188 _EGLImage *img = _eglLookupImage(image, disp);
1189 _EGLDriver *drv;
1190 EGLBoolean ret;
1191
1192 drv = _EGL_CHECK_DISPLAY(disp, EGL_FALSE);
1193 if (!img)
1194 return _EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1195
1196 _eglUnlinkImage(img);
1197 ret = drv->API.DestroyImageKHR(drv, disp, img);
1198
1199 return _EGL_EVAL(disp, ret);
1200 }
1201
1202
1203 #endif /* EGL_KHR_image_base */