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