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