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