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