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