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