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