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