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