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