1/************************************************************************** 2 * 3 * Copyright 2008 VMware, Inc. 4 * Copyright 2009-2010 Chia-I Wu <olvaffe@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#ifdef USE_LIBGLVND 87#define EGLAPI 88#undef PUBLIC 89#define PUBLIC 90#endif 91 92#include <stdio.h> 93#include <stdlib.h> 94#include <string.h> 95#include "c99_compat.h" 96#include "c11/threads.h" 97#include "util/macros.h" 98 99#include "eglapi.h" 100#include "egldefines.h" 101#include "eglglobals.h" 102#include "eglcontext.h" 103#include "egldisplay.h" 104#include "egltypedefs.h" 105#include "eglcurrent.h" 106#include "egldevice.h" 107#include "egldriver.h" 108#include "eglsurface.h" 109#include "eglconfig.h" 110#include "eglimage.h" 111#include "eglsync.h" 112 113#include "GL/mesa_glinterop.h" 114 115/** 116 * Macros to help return an API entrypoint. 117 * 118 * These macros will unlock the display and record the error code. 119 */ 120#define RETURN_EGL_ERROR(disp, err, ret) \ 121 do { \ 122 if (disp) \ 123 _eglUnlockDisplay(disp); \ 124 /* EGL error codes are non-zero */ \ 125 if (err) \ 126 _eglError(err, __func__); \ 127 return ret; \ 128 } while (0) 129 130#define RETURN_EGL_SUCCESS(disp, ret) \ 131 RETURN_EGL_ERROR(disp, EGL_SUCCESS, ret) 132 133/* record EGL_SUCCESS only when ret evaluates to true */ 134#define RETURN_EGL_EVAL(disp, ret) \ 135 RETURN_EGL_ERROR(disp, (ret) ? EGL_SUCCESS : 0, ret) 136 137 138/* 139 * A bunch of macros and checks to simplify error checking. 140 */ 141 142#define _EGL_CHECK_DISPLAY(disp, ret, drv) \ 143 do { \ 144 drv = _eglCheckDisplay(disp, __func__); \ 145 if (!drv) \ 146 RETURN_EGL_ERROR(disp, 0, ret); \ 147 } while (0) 148 149#define _EGL_CHECK_OBJECT(disp, type, obj, ret, drv) \ 150 do { \ 151 drv = _eglCheck ## type(disp, obj, __func__); \ 152 if (!drv) \ 153 RETURN_EGL_ERROR(disp, 0, ret); \ 154 } while (0) 155 156#define _EGL_CHECK_SURFACE(disp, surf, ret, drv) \ 157 _EGL_CHECK_OBJECT(disp, Surface, surf, ret, drv) 158 159#define _EGL_CHECK_CONTEXT(disp, context, ret, drv) \ 160 _EGL_CHECK_OBJECT(disp, Context, context, ret, drv) 161 162#define _EGL_CHECK_CONFIG(disp, conf, ret, drv) \ 163 _EGL_CHECK_OBJECT(disp, Config, conf, ret, drv) 164 165#define _EGL_CHECK_SYNC(disp, s, ret, drv) \ 166 _EGL_CHECK_OBJECT(disp, Sync, s, ret, drv) 167 168 169struct _egl_entrypoint { 170 const char *name; 171 _EGLProc function; 172}; 173 174 175static inline _EGLDriver * 176_eglCheckDisplay(_EGLDisplay *disp, const char *msg) 177{ 178 if (!disp) { 179 _eglError(EGL_BAD_DISPLAY, msg); 180 return NULL; 181 } 182 if (!disp->Initialized) { 183 _eglError(EGL_NOT_INITIALIZED, msg); 184 return NULL; 185 } 186 return disp->Driver; 187} 188 189 190static inline _EGLDriver * 191_eglCheckSurface(_EGLDisplay *disp, _EGLSurface *surf, const char *msg) 192{ 193 _EGLDriver *drv = _eglCheckDisplay(disp, msg); 194 if (!drv) 195 return NULL; 196 if (!surf) { 197 _eglError(EGL_BAD_SURFACE, msg); 198 return NULL; 199 } 200 return drv; 201} 202 203 204static inline _EGLDriver * 205_eglCheckContext(_EGLDisplay *disp, _EGLContext *context, const char *msg) 206{ 207 _EGLDriver *drv = _eglCheckDisplay(disp, msg); 208 if (!drv) 209 return NULL; 210 if (!context) { 211 _eglError(EGL_BAD_CONTEXT, msg); 212 return NULL; 213 } 214 return drv; 215} 216 217 218static inline _EGLDriver * 219_eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg) 220{ 221 _EGLDriver *drv = _eglCheckDisplay(disp, msg); 222 if (!drv) 223 return NULL; 224 if (!conf) { 225 _eglError(EGL_BAD_CONFIG, msg); 226 return NULL; 227 } 228 return drv; 229} 230 231 232static inline _EGLDriver * 233_eglCheckSync(_EGLDisplay *disp, _EGLSync *s, const char *msg) 234{ 235 _EGLDriver *drv = _eglCheckDisplay(disp, msg); 236 if (!drv) 237 return NULL; 238 if (!s) { 239 _eglError(EGL_BAD_PARAMETER, msg); 240 return NULL; 241 } 242 return drv; 243} 244 245 246/** 247 * Lookup and lock a display. 248 */ 249static inline _EGLDisplay * 250_eglLockDisplay(EGLDisplay dpy) 251{ 252 _EGLDisplay *disp = _eglLookupDisplay(dpy); 253 if (disp) 254 mtx_lock(&disp->Mutex); 255 return disp; 256} 257 258 259/** 260 * Unlock a display. 261 */ 262static inline void 263_eglUnlockDisplay(_EGLDisplay *disp) 264{ 265 mtx_unlock(&disp->Mutex); 266} 267 268static EGLBoolean 269_eglSetFuncName(const char *funcName, _EGLDisplay *disp, EGLenum objectType, _EGLResource *object) 270{ 271 _EGLThreadInfo *thr = _eglGetCurrentThread(); 272 if (!_eglIsCurrentThreadDummy()) { 273 thr->CurrentFuncName = funcName; 274 thr->CurrentObjectLabel = NULL; 275 276 if (objectType == EGL_OBJECT_THREAD_KHR) 277 thr->CurrentObjectLabel = thr->Label; 278 else if (objectType == EGL_OBJECT_DISPLAY_KHR && disp) 279 thr->CurrentObjectLabel = disp->Label; 280 else if (object) 281 thr->CurrentObjectLabel = object->Label; 282 283 return EGL_TRUE; 284 } 285 286 _eglDebugReport(EGL_BAD_ALLOC, funcName, EGL_DEBUG_MSG_CRITICAL_KHR, NULL); 287 return EGL_FALSE; 288} 289 290#define _EGL_FUNC_START(disp, objectType, object, ret) \ 291 do { \ 292 if (!_eglSetFuncName(__func__, disp, objectType, (_EGLResource *) object)) { \ 293 if (disp) \ 294 _eglUnlockDisplay(disp); \ 295 return ret; \ 296 } \ 297 } while(0) 298 299/** 300 * Convert an attribute list from EGLint[] to EGLAttrib[]. 301 * 302 * Return an EGL error code. The output parameter out_attrib_list is modified 303 * only on success. 304 */ 305static EGLint 306_eglConvertIntsToAttribs(const EGLint *int_list, EGLAttrib **out_attrib_list) 307{ 308 size_t len = 0; 309 EGLAttrib *attrib_list; 310 311 if (int_list) { 312 while (int_list[2*len] != EGL_NONE) 313 ++len; 314 } 315 316 if (len == 0) { 317 *out_attrib_list = NULL; 318 return EGL_SUCCESS; 319 } 320 321 if (2*len + 1 > SIZE_MAX / sizeof(EGLAttrib)) 322 return EGL_BAD_ALLOC; 323 324 attrib_list = malloc((2*len + 1) * sizeof(EGLAttrib)); 325 if (!attrib_list) 326 return EGL_BAD_ALLOC; 327 328 for (size_t i = 0; i < len; ++i) { 329 attrib_list[2*i + 0] = int_list[2*i + 0]; 330 attrib_list[2*i + 1] = int_list[2*i + 1]; 331 } 332 333 attrib_list[2*len] = EGL_NONE; 334 335 *out_attrib_list = attrib_list; 336 return EGL_SUCCESS; 337} 338 339 340static EGLint * 341_eglConvertAttribsToInt(const EGLAttrib *attr_list) 342{ 343 EGLint *int_attribs = NULL; 344 345 /* Convert attributes from EGLAttrib[] to EGLint[] */ 346 if (attr_list) { 347 int i, size = 0; 348 349 while (attr_list[size] != EGL_NONE) 350 size += 2; 351 352 size += 1; /* add space for EGL_NONE */ 353 354 int_attribs = calloc(size, sizeof(int_attribs[0])); 355 if (!int_attribs) 356 return NULL; 357 358 for (i = 0; i < size; i++) 359 int_attribs[i] = attr_list[i]; 360 } 361 return int_attribs; 362} 363 364 365/** 366 * This is typically the first EGL function that an application calls. 367 * It associates a private _EGLDisplay object to the native display. 368 */ 369EGLDisplay EGLAPIENTRY 370eglGetDisplay(EGLNativeDisplayType nativeDisplay) 371{ 372 _EGLPlatformType plat; 373 _EGLDisplay *disp; 374 void *native_display_ptr; 375 376 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY); 377 378 STATIC_ASSERT(sizeof(void*) == sizeof(nativeDisplay)); 379 native_display_ptr = (void*) nativeDisplay; 380 381 plat = _eglGetNativePlatform(native_display_ptr); 382 disp = _eglFindDisplay(plat, native_display_ptr); 383 return _eglGetDisplayHandle(disp); 384} 385 386static EGLDisplay 387_eglGetPlatformDisplayCommon(EGLenum platform, void *native_display, 388 const EGLAttrib *attrib_list) 389{ 390 _EGLDisplay *disp; 391 392 switch (platform) { 393#ifdef HAVE_X11_PLATFORM 394 case EGL_PLATFORM_X11_EXT: 395 disp = _eglGetX11Display((Display*) native_display, attrib_list); 396 break; 397#endif 398#ifdef HAVE_DRM_PLATFORM 399 case EGL_PLATFORM_GBM_MESA: 400 disp = _eglGetGbmDisplay((struct gbm_device*) native_display, 401 attrib_list); 402 break; 403#endif 404#ifdef HAVE_WAYLAND_PLATFORM 405 case EGL_PLATFORM_WAYLAND_EXT: 406 disp = _eglGetWaylandDisplay((struct wl_display*) native_display, 407 attrib_list); 408 break; 409#endif 410#ifdef HAVE_SURFACELESS_PLATFORM 411 case EGL_PLATFORM_SURFACELESS_MESA: 412 disp = _eglGetSurfacelessDisplay(native_display, attrib_list); 413 break; 414#endif 415 default: 416 RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, NULL); 417 } 418 419 return _eglGetDisplayHandle(disp); 420} 421 422static EGLDisplay EGLAPIENTRY 423eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, 424 const EGLint *int_attribs) 425{ 426 EGLAttrib *attrib_list; 427 EGLDisplay disp; 428 429 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY); 430 431 if (_eglConvertIntsToAttribs(int_attribs, &attrib_list) != EGL_SUCCESS) 432 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, NULL); 433 434 disp = _eglGetPlatformDisplayCommon(platform, native_display, attrib_list); 435 free(attrib_list); 436 return disp; 437} 438 439EGLDisplay EGLAPIENTRY 440eglGetPlatformDisplay(EGLenum platform, void *native_display, 441 const EGLAttrib *attrib_list) 442{ 443 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY); 444 return _eglGetPlatformDisplayCommon(platform, native_display, attrib_list); 445} 446 447/** 448 * Copy the extension into the string and update the string pointer. 449 */ 450static EGLint 451_eglAppendExtension(char **str, const char *ext) 452{ 453 char *s = *str; 454 size_t len = strlen(ext); 455 456 if (s) { 457 memcpy(s, ext, len); 458 s[len++] = ' '; 459 s[len] = '\0'; 460 461 *str += len; 462 } 463 else { 464 len++; 465 } 466 467 return (EGLint) len; 468} 469 470/** 471 * Examine the individual extension enable/disable flags and recompute 472 * the driver's Extensions string. 473 */ 474static void 475_eglCreateExtensionsString(_EGLDisplay *disp) 476{ 477#define _EGL_CHECK_EXTENSION(ext) \ 478 do { \ 479 if (disp->Extensions.ext) { \ 480 _eglAppendExtension(&exts, "EGL_" #ext); \ 481 assert(exts <= disp->ExtensionsString + _EGL_MAX_EXTENSIONS_LEN); \ 482 } \ 483 } while (0) 484 485 char *exts = disp->ExtensionsString; 486 487 /* Please keep these sorted alphabetically. */ 488 _EGL_CHECK_EXTENSION(ANDROID_blob_cache); 489 _EGL_CHECK_EXTENSION(ANDROID_framebuffer_target); 490 _EGL_CHECK_EXTENSION(ANDROID_image_native_buffer); 491 _EGL_CHECK_EXTENSION(ANDROID_native_fence_sync); 492 _EGL_CHECK_EXTENSION(ANDROID_recordable); 493 494 _EGL_CHECK_EXTENSION(CHROMIUM_sync_control); 495 496 _EGL_CHECK_EXTENSION(EXT_buffer_age); 497 _EGL_CHECK_EXTENSION(EXT_create_context_robustness); 498 _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import); 499 _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import_modifiers); 500 _EGL_CHECK_EXTENSION(EXT_surface_CTA861_3_metadata); 501 _EGL_CHECK_EXTENSION(EXT_surface_SMPTE2086_metadata); 502 _EGL_CHECK_EXTENSION(EXT_swap_buffers_with_damage); 503 504 _EGL_CHECK_EXTENSION(IMG_context_priority); 505 506 _EGL_CHECK_EXTENSION(KHR_cl_event2); 507 _EGL_CHECK_EXTENSION(KHR_config_attribs); 508 _EGL_CHECK_EXTENSION(KHR_context_flush_control); 509 _EGL_CHECK_EXTENSION(KHR_create_context); 510 _EGL_CHECK_EXTENSION(KHR_create_context_no_error); 511 _EGL_CHECK_EXTENSION(KHR_fence_sync); 512 _EGL_CHECK_EXTENSION(KHR_get_all_proc_addresses); 513 _EGL_CHECK_EXTENSION(KHR_gl_colorspace); 514 _EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_image); 515 _EGL_CHECK_EXTENSION(KHR_gl_texture_2D_image); 516 _EGL_CHECK_EXTENSION(KHR_gl_texture_3D_image); 517 _EGL_CHECK_EXTENSION(KHR_gl_texture_cubemap_image); 518 if (disp->Extensions.KHR_image_base && disp->Extensions.KHR_image_pixmap) 519 disp->Extensions.KHR_image = EGL_TRUE; 520 _EGL_CHECK_EXTENSION(KHR_image); 521 _EGL_CHECK_EXTENSION(KHR_image_base); 522 _EGL_CHECK_EXTENSION(KHR_image_pixmap); 523 _EGL_CHECK_EXTENSION(KHR_mutable_render_buffer); 524 _EGL_CHECK_EXTENSION(KHR_no_config_context); 525 _EGL_CHECK_EXTENSION(KHR_partial_update); 526 _EGL_CHECK_EXTENSION(KHR_reusable_sync); 527 _EGL_CHECK_EXTENSION(KHR_surfaceless_context); 528 if (disp->Extensions.EXT_swap_buffers_with_damage) 529 _eglAppendExtension(&exts, "EGL_KHR_swap_buffers_with_damage"); 530 _EGL_CHECK_EXTENSION(EXT_pixel_format_float); 531 _EGL_CHECK_EXTENSION(KHR_wait_sync); 532 533 if (disp->Extensions.KHR_no_config_context) 534 _eglAppendExtension(&exts, "EGL_MESA_configless_context"); 535 _EGL_CHECK_EXTENSION(MESA_drm_image); 536 _EGL_CHECK_EXTENSION(MESA_image_dma_buf_export); 537 _EGL_CHECK_EXTENSION(MESA_query_driver); 538 539 _EGL_CHECK_EXTENSION(NOK_swap_region); 540 _EGL_CHECK_EXTENSION(NOK_texture_from_pixmap); 541 542 _EGL_CHECK_EXTENSION(NV_post_sub_buffer); 543 544 _EGL_CHECK_EXTENSION(WL_bind_wayland_display); 545 _EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image); 546 547#undef _EGL_CHECK_EXTENSION 548} 549 550static void 551_eglCreateAPIsString(_EGLDisplay *disp) 552{ 553#define addstr(str) \ 554 { \ 555 const size_t old_len = strlen(disp->ClientAPIsString); \ 556 const size_t add_len = sizeof(str); \ 557 const size_t max_len = sizeof(disp->ClientAPIsString) - 1; \ 558 if (old_len + add_len <= max_len) \ 559 strcat(disp->ClientAPIsString, str " "); \ 560 else \ 561 assert(!"disp->ClientAPIsString is not large enough"); \ 562 } 563 564 if (disp->ClientAPIs & EGL_OPENGL_BIT) 565 addstr("OpenGL"); 566 567 if (disp->ClientAPIs & EGL_OPENGL_ES_BIT || 568 disp->ClientAPIs & EGL_OPENGL_ES2_BIT || 569 disp->ClientAPIs & EGL_OPENGL_ES3_BIT_KHR) { 570 addstr("OpenGL_ES"); 571 } 572 573 if (disp->ClientAPIs & EGL_OPENVG_BIT) 574 addstr("OpenVG"); 575 576#undef addstr 577} 578 579static void 580_eglComputeVersion(_EGLDisplay *disp) 581{ 582 disp->Version = 14; 583 584 if (disp->Extensions.KHR_fence_sync && 585 disp->Extensions.KHR_cl_event2 && 586 disp->Extensions.KHR_wait_sync && 587 disp->Extensions.KHR_image_base && 588 disp->Extensions.KHR_gl_texture_2D_image && 589 disp->Extensions.KHR_gl_texture_3D_image && 590 disp->Extensions.KHR_gl_texture_cubemap_image && 591 disp->Extensions.KHR_gl_renderbuffer_image && 592 disp->Extensions.KHR_create_context && 593 disp->Extensions.EXT_create_context_robustness && 594 disp->Extensions.KHR_get_all_proc_addresses && 595 disp->Extensions.KHR_gl_colorspace && 596 disp->Extensions.KHR_surfaceless_context) 597 disp->Version = 15; 598} 599 600/** 601 * This is typically the second EGL function that an application calls. 602 * Here we load/initialize the actual hardware driver. 603 */ 604EGLBoolean EGLAPIENTRY 605eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) 606{ 607 _EGLDisplay *disp = _eglLockDisplay(dpy); 608 609 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 610 611 if (!disp) 612 RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE); 613 614 if (!disp->Initialized) { 615 if (!_eglMatchDriver(disp)) 616 RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE); 617 618 /* limit to APIs supported by core */ 619 disp->ClientAPIs &= _EGL_API_ALL_BITS; 620 621 /* EGL_KHR_get_all_proc_addresses is a corner-case extension. The spec 622 * classifies it as an EGL display extension, though conceptually it's an 623 * EGL client extension. 624 * 625 * From the EGL_KHR_get_all_proc_addresses spec: 626 * 627 * The EGL implementation must expose the name 628 * EGL_KHR_client_get_all_proc_addresses if and only if it exposes 629 * EGL_KHR_get_all_proc_addresses and supports 630 * EGL_EXT_client_extensions. 631 * 632 * Mesa unconditionally exposes both client extensions mentioned above, 633 * so the spec requires that each EGLDisplay unconditionally expose 634 * EGL_KHR_get_all_proc_addresses also. 635 */ 636 disp->Extensions.KHR_get_all_proc_addresses = EGL_TRUE; 637 638 /* Extensions is used to provide EGL 1.3 functionality for 1.2 aware 639 * programs. It is driver agnostic and handled in the main EGL code. 640 */ 641 disp->Extensions.KHR_config_attribs = EGL_TRUE; 642 643 _eglComputeVersion(disp); 644 _eglCreateExtensionsString(disp); 645 _eglCreateAPIsString(disp); 646 snprintf(disp->VersionString, sizeof(disp->VersionString), 647 "%d.%d", disp->Version / 10, disp->Version % 10); 648 } 649 650 /* Update applications version of major and minor if not NULL */ 651 if ((major != NULL) && (minor != NULL)) { 652 *major = disp->Version / 10; 653 *minor = disp->Version % 10; 654 } 655 656 RETURN_EGL_SUCCESS(disp, EGL_TRUE); 657} 658 659 660EGLBoolean EGLAPIENTRY 661eglTerminate(EGLDisplay dpy) 662{ 663 _EGLDisplay *disp = _eglLockDisplay(dpy); 664 665 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 666 667 if (!disp) 668 RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE); 669 670 if (disp->Initialized) { 671 _EGLDriver *drv = disp->Driver; 672 673 drv->API.Terminate(drv, disp); 674 /* do not reset disp->Driver */ 675 disp->ClientAPIsString[0] = 0; 676 disp->Initialized = EGL_FALSE; 677 678 /* Reset blob cache funcs on terminate. */ 679 disp->BlobCacheSet = NULL; 680 disp->BlobCacheGet = NULL; 681 } 682 683 RETURN_EGL_SUCCESS(disp, EGL_TRUE); 684} 685 686 687const char * EGLAPIENTRY 688eglQueryString(EGLDisplay dpy, EGLint name) 689{ 690 _EGLDisplay *disp; 691 _EGLDriver *drv; 692 693 if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) { 694 const char *ret = _eglGetClientExtensionString(); 695 if (ret != NULL) 696 RETURN_EGL_SUCCESS(NULL, ret); 697 else 698 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, NULL); 699 } 700 701 disp = _eglLockDisplay(dpy); 702 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, NULL); 703 _EGL_CHECK_DISPLAY(disp, NULL, drv); 704 705 switch (name) { 706 case EGL_VENDOR: 707 RETURN_EGL_SUCCESS(disp, _EGL_VENDOR_STRING); 708 case EGL_VERSION: 709 RETURN_EGL_SUCCESS(disp, disp->VersionString); 710 case EGL_EXTENSIONS: 711 RETURN_EGL_SUCCESS(disp, disp->ExtensionsString); 712 case EGL_CLIENT_APIS: 713 RETURN_EGL_SUCCESS(disp, disp->ClientAPIsString); 714 default: 715 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL); 716 } 717} 718 719 720EGLBoolean EGLAPIENTRY 721eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, 722 EGLint config_size, EGLint *num_config) 723{ 724 _EGLDisplay *disp = _eglLockDisplay(dpy); 725 _EGLDriver *drv; 726 EGLBoolean ret; 727 728 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 729 730 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 731 ret = drv->API.GetConfigs(drv, disp, configs, config_size, num_config); 732 733 RETURN_EGL_EVAL(disp, ret); 734} 735 736 737EGLBoolean EGLAPIENTRY 738eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, 739 EGLint config_size, EGLint *num_config) 740{ 741 _EGLDisplay *disp = _eglLockDisplay(dpy); 742 _EGLDriver *drv; 743 EGLBoolean ret; 744 745 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 746 747 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 748 ret = drv->API.ChooseConfig(drv, disp, attrib_list, configs, 749 config_size, num_config); 750 751 RETURN_EGL_EVAL(disp, ret); 752} 753 754 755EGLBoolean EGLAPIENTRY 756eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, 757 EGLint attribute, EGLint *value) 758{ 759 _EGLDisplay *disp = _eglLockDisplay(dpy); 760 _EGLConfig *conf = _eglLookupConfig(config, disp); 761 _EGLDriver *drv; 762 EGLBoolean ret; 763 764 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 765 766 _EGL_CHECK_CONFIG(disp, conf, EGL_FALSE, drv); 767 ret = drv->API.GetConfigAttrib(drv, disp, conf, attribute, value); 768 769 RETURN_EGL_EVAL(disp, ret); 770} 771 772 773EGLContext EGLAPIENTRY 774eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, 775 const EGLint *attrib_list) 776{ 777 _EGLDisplay *disp = _eglLockDisplay(dpy); 778 _EGLConfig *conf = _eglLookupConfig(config, disp); 779 _EGLContext *share = _eglLookupContext(share_list, disp); 780 _EGLDriver *drv; 781 _EGLContext *context; 782 EGLContext ret; 783 784 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_CONTEXT); 785 786 _EGL_CHECK_DISPLAY(disp, EGL_NO_CONTEXT, drv); 787 788 if (config != EGL_NO_CONFIG_KHR) 789 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_CONTEXT, drv); 790 else if (!disp->Extensions.KHR_no_config_context) 791 RETURN_EGL_ERROR(disp, EGL_BAD_CONFIG, EGL_NO_CONTEXT); 792 793 if (!share && share_list != EGL_NO_CONTEXT) 794 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_CONTEXT); 795 796 context = drv->API.CreateContext(drv, disp, conf, share, attrib_list); 797 ret = (context) ? _eglLinkContext(context) : EGL_NO_CONTEXT; 798 799 RETURN_EGL_EVAL(disp, ret); 800} 801 802 803EGLBoolean EGLAPIENTRY 804eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 805{ 806 _EGLDisplay *disp = _eglLockDisplay(dpy); 807 _EGLContext *context = _eglLookupContext(ctx, disp); 808 _EGLDriver *drv; 809 EGLBoolean ret; 810 811 _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE); 812 813 _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv); 814 _eglUnlinkContext(context); 815 ret = drv->API.DestroyContext(drv, disp, context); 816 817 RETURN_EGL_EVAL(disp, ret); 818} 819 820 821EGLBoolean EGLAPIENTRY 822eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, 823 EGLContext ctx) 824{ 825 _EGLDisplay *disp = _eglLockDisplay(dpy); 826 _EGLContext *context = _eglLookupContext(ctx, disp); 827 _EGLSurface *draw_surf = _eglLookupSurface(draw, disp); 828 _EGLSurface *read_surf = _eglLookupSurface(read, disp); 829 _EGLDriver *drv; 830 EGLBoolean ret; 831 832 _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE); 833 834 if (!disp) 835 RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE); 836 drv = disp->Driver; 837 838 /* display is allowed to be uninitialized under certain condition */ 839 if (!disp->Initialized) { 840 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE || 841 ctx != EGL_NO_CONTEXT) 842 RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE); 843 } 844 if (!drv) 845 RETURN_EGL_SUCCESS(disp, EGL_TRUE); 846 847 if (!context && ctx != EGL_NO_CONTEXT) 848 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE); 849 if (!draw_surf || !read_surf) { 850 /* From the EGL 1.4 (20130211) spec: 851 * 852 * To release the current context without assigning a new one, set ctx 853 * to EGL_NO_CONTEXT and set draw and read to EGL_NO_SURFACE. 854 */ 855 if (!disp->Extensions.KHR_surfaceless_context && ctx != EGL_NO_CONTEXT) 856 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 857 858 if ((!draw_surf && draw != EGL_NO_SURFACE) || 859 (!read_surf && read != EGL_NO_SURFACE)) 860 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 861 if (draw_surf || read_surf) 862 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE); 863 } 864 865 /* If a native window underlying either draw or read is no longer valid, 866 * an EGL_BAD_NATIVE_WINDOW error is generated. 867 */ 868 if (draw_surf && draw_surf->Lost) 869 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE); 870 if (read_surf && read_surf->Lost) 871 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE); 872 873 ret = drv->API.MakeCurrent(drv, disp, draw_surf, read_surf, context); 874 875 RETURN_EGL_EVAL(disp, ret); 876} 877 878 879EGLBoolean EGLAPIENTRY 880eglQueryContext(EGLDisplay dpy, EGLContext ctx, 881 EGLint attribute, EGLint *value) 882{ 883 _EGLDisplay *disp = _eglLockDisplay(dpy); 884 _EGLContext *context = _eglLookupContext(ctx, disp); 885 _EGLDriver *drv; 886 EGLBoolean ret; 887 888 _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE); 889 890 _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv); 891 ret = drv->API.QueryContext(drv, disp, context, attribute, value); 892 893 RETURN_EGL_EVAL(disp, ret); 894} 895 896 897static EGLSurface 898_eglCreateWindowSurfaceCommon(_EGLDisplay *disp, EGLConfig config, 899 void *native_window, const EGLint *attrib_list) 900{ 901 _EGLConfig *conf = _eglLookupConfig(config, disp); 902 _EGLDriver *drv; 903 _EGLSurface *surf; 904 EGLSurface ret; 905 906 907 if (native_window == NULL) 908 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 909 910#ifdef HAVE_SURFACELESS_PLATFORM 911 if (disp && disp->Platform == _EGL_PLATFORM_SURFACELESS) { 912 /* From the EGL_MESA_platform_surfaceless spec (v1): 913 * 914 * eglCreatePlatformWindowSurface fails when called with a <display> 915 * that belongs to the surfaceless platform. It returns 916 * EGL_NO_SURFACE and generates EGL_BAD_NATIVE_WINDOW. The 917 * justification for this unconditional failure is that the 918 * surfaceless platform has no native windows, and therefore the 919 * <native_window> parameter is always invalid. 920 * 921 * This check must occur before checking the EGLConfig, which emits 922 * EGL_BAD_CONFIG. 923 */ 924 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 925 } 926#endif 927 928 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); 929 930 if ((conf->SurfaceType & EGL_WINDOW_BIT) == 0) 931 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE); 932 933 surf = drv->API.CreateWindowSurface(drv, disp, conf, native_window, 934 attrib_list); 935 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE; 936 937 RETURN_EGL_EVAL(disp, ret); 938} 939 940 941EGLSurface EGLAPIENTRY 942eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, 943 EGLNativeWindowType window, const EGLint *attrib_list) 944{ 945 _EGLDisplay *disp = _eglLockDisplay(dpy); 946 947 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 948 STATIC_ASSERT(sizeof(void*) == sizeof(window)); 949 return _eglCreateWindowSurfaceCommon(disp, config, (void*) window, 950 attrib_list); 951} 952 953static void * 954_fixupNativeWindow(_EGLDisplay *disp, void *native_window) 955{ 956#ifdef HAVE_X11_PLATFORM 957 if (disp && disp->Platform == _EGL_PLATFORM_X11 && native_window != NULL) { 958 /* The `native_window` parameter for the X11 platform differs between 959 * eglCreateWindowSurface() and eglCreatePlatformPixmapSurfaceEXT(). In 960 * eglCreateWindowSurface(), the type of `native_window` is an Xlib 961 * `Window`. In eglCreatePlatformWindowSurfaceEXT(), the type is 962 * `Window*`. Convert `Window*` to `Window` because that's what 963 * dri2_x11_create_window_surface() expects. 964 */ 965 return (void *)(* (Window*) native_window); 966 } 967#endif 968 return native_window; 969} 970 971static EGLSurface EGLAPIENTRY 972eglCreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config, 973 void *native_window, 974 const EGLint *attrib_list) 975{ 976 _EGLDisplay *disp = _eglLockDisplay(dpy); 977 978 native_window = _fixupNativeWindow(disp, native_window); 979 980 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 981 return _eglCreateWindowSurfaceCommon(disp, config, native_window, 982 attrib_list); 983} 984 985 986EGLSurface EGLAPIENTRY 987eglCreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, 988 void *native_window, 989 const EGLAttrib *attrib_list) 990{ 991 _EGLDisplay *disp = _eglLockDisplay(dpy); 992 EGLSurface surface; 993 EGLint *int_attribs; 994 995 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 996 997 int_attribs = _eglConvertAttribsToInt(attrib_list); 998 if (attrib_list && !int_attribs) 999 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE); 1000 1001 native_window = _fixupNativeWindow(disp, native_window); 1002 surface = _eglCreateWindowSurfaceCommon(disp, config, native_window, 1003 int_attribs); 1004 free(int_attribs); 1005 return surface; 1006} 1007 1008static void * 1009_fixupNativePixmap(_EGLDisplay *disp, void *native_pixmap) 1010{ 1011#ifdef HAVE_X11_PLATFORM 1012 /* The `native_pixmap` parameter for the X11 platform differs between 1013 * eglCreatePixmapSurface() and eglCreatePlatformPixmapSurfaceEXT(). In 1014 * eglCreatePixmapSurface(), the type of `native_pixmap` is an Xlib 1015 * `Pixmap`. In eglCreatePlatformPixmapSurfaceEXT(), the type is 1016 * `Pixmap*`. Convert `Pixmap*` to `Pixmap` because that's what 1017 * dri2_x11_create_pixmap_surface() expects. 1018 */ 1019 if (disp && disp->Platform == _EGL_PLATFORM_X11 && native_pixmap != NULL) 1020 return (void *)(* (Pixmap*) native_pixmap); 1021#endif 1022 return native_pixmap; 1023} 1024 1025static EGLSurface 1026_eglCreatePixmapSurfaceCommon(_EGLDisplay *disp, EGLConfig config, 1027 void *native_pixmap, const EGLint *attrib_list) 1028{ 1029 _EGLConfig *conf = _eglLookupConfig(config, disp); 1030 _EGLDriver *drv; 1031 _EGLSurface *surf; 1032 EGLSurface ret; 1033 1034#if HAVE_SURFACELESS_PLATFORM 1035 if (disp && disp->Platform == _EGL_PLATFORM_SURFACELESS) { 1036 /* From the EGL_MESA_platform_surfaceless spec (v1): 1037 * 1038 * [Like eglCreatePlatformWindowSurface,] eglCreatePlatformPixmapSurface 1039 * also fails when called with a <display> that belongs to the 1040 * surfaceless platform. It returns EGL_NO_SURFACE and generates 1041 * EGL_BAD_NATIVE_PIXMAP. 1042 * 1043 * This check must occur before checking the EGLConfig, which emits 1044 * EGL_BAD_CONFIG. 1045 */ 1046 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE); 1047 } 1048#endif 1049 1050 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); 1051 1052 if ((conf->SurfaceType & EGL_PIXMAP_BIT) == 0) 1053 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE); 1054 1055 if (native_pixmap == NULL) 1056 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE); 1057 1058 surf = drv->API.CreatePixmapSurface(drv, disp, conf, native_pixmap, 1059 attrib_list); 1060 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE; 1061 1062 RETURN_EGL_EVAL(disp, ret); 1063} 1064 1065 1066EGLSurface EGLAPIENTRY 1067eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, 1068 EGLNativePixmapType pixmap, const EGLint *attrib_list) 1069{ 1070 _EGLDisplay *disp = _eglLockDisplay(dpy); 1071 1072 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 1073 STATIC_ASSERT(sizeof(void*) == sizeof(pixmap)); 1074 return _eglCreatePixmapSurfaceCommon(disp, config, (void*) pixmap, 1075 attrib_list); 1076} 1077 1078static EGLSurface EGLAPIENTRY 1079eglCreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config, 1080 void *native_pixmap, 1081 const EGLint *attrib_list) 1082{ 1083 _EGLDisplay *disp = _eglLockDisplay(dpy); 1084 1085 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 1086 native_pixmap = _fixupNativePixmap(disp, native_pixmap); 1087 return _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap, 1088 attrib_list); 1089} 1090 1091 1092EGLSurface EGLAPIENTRY 1093eglCreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, 1094 void *native_pixmap, 1095 const EGLAttrib *attrib_list) 1096{ 1097 _EGLDisplay *disp = _eglLockDisplay(dpy); 1098 EGLSurface surface; 1099 EGLint *int_attribs; 1100 1101 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 1102 1103 int_attribs = _eglConvertAttribsToInt(attrib_list); 1104 if (attrib_list && !int_attribs) 1105 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE); 1106 1107 native_pixmap = _fixupNativePixmap(disp, native_pixmap); 1108 surface = _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap, 1109 int_attribs); 1110 free(int_attribs); 1111 return surface; 1112} 1113 1114 1115EGLSurface EGLAPIENTRY 1116eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, 1117 const EGLint *attrib_list) 1118{ 1119 _EGLDisplay *disp = _eglLockDisplay(dpy); 1120 _EGLConfig *conf = _eglLookupConfig(config, disp); 1121 _EGLDriver *drv; 1122 _EGLSurface *surf; 1123 EGLSurface ret; 1124 1125 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 1126 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); 1127 1128 if ((conf->SurfaceType & EGL_PBUFFER_BIT) == 0) 1129 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE); 1130 1131 surf = drv->API.CreatePbufferSurface(drv, disp, conf, attrib_list); 1132 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE; 1133 1134 RETURN_EGL_EVAL(disp, ret); 1135} 1136 1137 1138EGLBoolean EGLAPIENTRY 1139eglDestroySurface(EGLDisplay dpy, EGLSurface surface) 1140{ 1141 _EGLDisplay *disp = _eglLockDisplay(dpy); 1142 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1143 _EGLDriver *drv; 1144 EGLBoolean ret; 1145 1146 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1147 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1148 _eglUnlinkSurface(surf); 1149 ret = drv->API.DestroySurface(drv, disp, surf); 1150 1151 RETURN_EGL_EVAL(disp, ret); 1152} 1153 1154EGLBoolean EGLAPIENTRY 1155eglQuerySurface(EGLDisplay dpy, EGLSurface surface, 1156 EGLint attribute, EGLint *value) 1157{ 1158 _EGLDisplay *disp = _eglLockDisplay(dpy); 1159 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1160 _EGLDriver *drv; 1161 EGLBoolean ret; 1162 1163 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1164 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1165 ret = drv->API.QuerySurface(drv, disp, surf, attribute, value); 1166 1167 RETURN_EGL_EVAL(disp, ret); 1168} 1169 1170EGLBoolean EGLAPIENTRY 1171eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, 1172 EGLint attribute, EGLint value) 1173{ 1174 _EGLDisplay *disp = _eglLockDisplay(dpy); 1175 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1176 _EGLDriver *drv; 1177 EGLBoolean ret; 1178 1179 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1180 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1181 ret = drv->API.SurfaceAttrib(drv, disp, surf, attribute, value); 1182 1183 RETURN_EGL_EVAL(disp, ret); 1184} 1185 1186 1187EGLBoolean EGLAPIENTRY 1188eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1189{ 1190 _EGLDisplay *disp = _eglLockDisplay(dpy); 1191 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1192 _EGLDriver *drv; 1193 EGLBoolean ret; 1194 1195 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1196 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1197 ret = drv->API.BindTexImage(drv, disp, surf, buffer); 1198 1199 RETURN_EGL_EVAL(disp, ret); 1200} 1201 1202 1203EGLBoolean EGLAPIENTRY 1204eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1205{ 1206 _EGLDisplay *disp = _eglLockDisplay(dpy); 1207 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1208 _EGLDriver *drv; 1209 EGLBoolean ret; 1210 1211 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1212 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1213 ret = drv->API.ReleaseTexImage(drv, disp, surf, buffer); 1214 1215 RETURN_EGL_EVAL(disp, ret); 1216} 1217 1218 1219EGLBoolean EGLAPIENTRY 1220eglSwapInterval(EGLDisplay dpy, EGLint interval) 1221{ 1222 _EGLDisplay *disp = _eglLockDisplay(dpy); 1223 _EGLContext *ctx = _eglGetCurrentContext(); 1224 _EGLSurface *surf = ctx ? ctx->DrawSurface : NULL; 1225 _EGLDriver *drv; 1226 EGLBoolean ret; 1227 1228 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1229 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 1230 1231 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1232 ctx->Resource.Display != disp) 1233 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE); 1234 1235 if (_eglGetSurfaceHandle(surf) == EGL_NO_SURFACE) 1236 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 1237 1238 if (surf->Type != EGL_WINDOW_BIT) 1239 RETURN_EGL_EVAL(disp, EGL_TRUE); 1240 1241 interval = CLAMP(interval, 1242 surf->Config->MinSwapInterval, 1243 surf->Config->MaxSwapInterval); 1244 1245 if (surf->SwapInterval != interval) 1246 ret = drv->API.SwapInterval(drv, disp, surf, interval); 1247 else 1248 ret = EGL_TRUE; 1249 1250 if (ret) 1251 surf->SwapInterval = interval; 1252 1253 RETURN_EGL_EVAL(disp, ret); 1254} 1255 1256 1257EGLBoolean EGLAPIENTRY 1258eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) 1259{ 1260 _EGLContext *ctx = _eglGetCurrentContext(); 1261 _EGLDisplay *disp = _eglLockDisplay(dpy); 1262 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1263 _EGLDriver *drv; 1264 EGLBoolean ret; 1265 1266 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1267 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1268 1269 /* surface must be bound to current context in EGL 1.4 */ 1270 #ifndef _EGL_BUILT_IN_DRIVER_HAIKU 1271 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1272 surf != ctx->DrawSurface) 1273 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 1274 #endif 1275 1276 if (surf->Type != EGL_WINDOW_BIT) 1277 RETURN_EGL_EVAL(disp, EGL_TRUE); 1278 1279 /* From the EGL 1.5 spec: 1280 * 1281 * If eglSwapBuffers is called and the native window associated with 1282 * surface is no longer valid, an EGL_BAD_NATIVE_WINDOW error is 1283 * generated. 1284 */ 1285 if (surf->Lost) 1286 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE); 1287 1288 ret = drv->API.SwapBuffers(drv, disp, surf); 1289 1290 /* EGL_KHR_partial_update 1291 * Frame boundary successfully reached, 1292 * reset damage region and reset BufferAgeRead 1293 */ 1294 if (ret) { 1295 surf->SetDamageRegionCalled = EGL_FALSE; 1296 surf->BufferAgeRead = EGL_FALSE; 1297 } 1298 1299 RETURN_EGL_EVAL(disp, ret); 1300} 1301 1302 1303static EGLBoolean 1304_eglSwapBuffersWithDamageCommon(_EGLDisplay *disp, _EGLSurface *surf, 1305 EGLint *rects, EGLint n_rects) 1306{ 1307 _EGLContext *ctx = _eglGetCurrentContext(); 1308 _EGLDriver *drv; 1309 EGLBoolean ret; 1310 1311 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1312 1313 /* surface must be bound to current context in EGL 1.4 */ 1314 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1315 surf != ctx->DrawSurface) 1316 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 1317 1318 if (surf->Type != EGL_WINDOW_BIT) 1319 RETURN_EGL_EVAL(disp, EGL_TRUE); 1320 1321 if ((n_rects > 0 && rects == NULL) || n_rects < 0) 1322 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 1323 1324 ret = drv->API.SwapBuffersWithDamageEXT(drv, disp, surf, rects, n_rects); 1325 1326 /* EGL_KHR_partial_update 1327 * Frame boundary successfully reached, 1328 * reset damage region and reset BufferAgeRead 1329 */ 1330 if (ret) { 1331 surf->SetDamageRegionCalled = EGL_FALSE; 1332 surf->BufferAgeRead = EGL_FALSE; 1333 } 1334 1335 RETURN_EGL_EVAL(disp, ret); 1336} 1337 1338static EGLBoolean EGLAPIENTRY 1339eglSwapBuffersWithDamageEXT(EGLDisplay dpy, EGLSurface surface, 1340 EGLint *rects, EGLint n_rects) 1341{ 1342 _EGLDisplay *disp = _eglLockDisplay(dpy); 1343 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1344 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1345 return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects); 1346} 1347 1348static EGLBoolean EGLAPIENTRY 1349eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface surface, 1350 EGLint *rects, EGLint n_rects) 1351{ 1352 _EGLDisplay *disp = _eglLockDisplay(dpy); 1353 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1354 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1355 return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects); 1356} 1357 1358/** 1359 * Clamp the rectangles so that they lie within the surface. 1360 */ 1361 1362static void 1363_eglSetDamageRegionKHRClampRects(_EGLDisplay* disp, _EGLSurface* surf, 1364 EGLint *rects, EGLint n_rects) 1365{ 1366 EGLint i; 1367 EGLint surf_height = surf->Height; 1368 EGLint surf_width = surf->Width; 1369 1370 for (i = 0; i < (4 * n_rects); i += 4) { 1371 EGLint x1, y1, x2, y2; 1372 x1 = rects[i]; 1373 y1 = rects[i + 1]; 1374 x2 = rects[i + 2] + x1; 1375 y2 = rects[i + 3] + y1; 1376 1377 rects[i] = CLAMP(x1, 0, surf_width); 1378 rects[i + 1] = CLAMP(y1, 0, surf_height); 1379 rects[i + 2] = CLAMP(x2, 0, surf_width) - rects[i]; 1380 rects[i + 3] = CLAMP(y2, 0, surf_height) - rects[i + 1]; 1381 } 1382} 1383 1384static EGLBoolean EGLAPIENTRY 1385eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface, 1386 EGLint *rects, EGLint n_rects) 1387{ 1388 _EGLDisplay *disp = _eglLockDisplay(dpy); 1389 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1390 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1391 _EGLContext *ctx = _eglGetCurrentContext(); 1392 _EGLDriver *drv; 1393 EGLBoolean ret; 1394 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1395 1396 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1397 surf->Type != EGL_WINDOW_BIT || 1398 ctx->DrawSurface != surf || 1399 surf->SwapBehavior != EGL_BUFFER_DESTROYED) 1400 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE); 1401 1402 /* If the damage region is already set or 1403 * buffer age is not queried between 1404 * frame boundaries, throw bad access error 1405 */ 1406 1407 if (surf->SetDamageRegionCalled || !surf->BufferAgeRead) 1408 RETURN_EGL_ERROR(disp, EGL_BAD_ACCESS, EGL_FALSE); 1409 1410 _eglSetDamageRegionKHRClampRects(disp, surf, rects, n_rects); 1411 ret = drv->API.SetDamageRegion(drv, disp, surf, rects, n_rects); 1412 1413 if (ret) 1414 surf->SetDamageRegionCalled = EGL_TRUE; 1415 1416 RETURN_EGL_EVAL(disp, ret); 1417} 1418 1419EGLBoolean EGLAPIENTRY 1420eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) 1421{ 1422 _EGLDisplay *disp = _eglLockDisplay(dpy); 1423 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1424 _EGLDriver *drv; 1425 EGLBoolean ret; 1426 void *native_pixmap_ptr; 1427 1428 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1429 STATIC_ASSERT(sizeof(void*) == sizeof(target)); 1430 native_pixmap_ptr = (void*) target; 1431 1432 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1433 ret = drv->API.CopyBuffers(drv, disp, surf, native_pixmap_ptr); 1434 1435 RETURN_EGL_EVAL(disp, ret); 1436} 1437 1438 1439static EGLBoolean 1440_eglWaitClientCommon(void) 1441{ 1442 _EGLContext *ctx = _eglGetCurrentContext(); 1443 _EGLDisplay *disp; 1444 _EGLDriver *drv; 1445 EGLBoolean ret; 1446 1447 if (!ctx) 1448 RETURN_EGL_SUCCESS(NULL, EGL_TRUE); 1449 1450 disp = ctx->Resource.Display; 1451 mtx_lock(&disp->Mutex); 1452 1453 /* let bad current context imply bad current surface */ 1454 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1455 _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE) 1456 RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE); 1457 1458 /* a valid current context implies an initialized current display */ 1459 assert(disp->Initialized); 1460 drv = disp->Driver; 1461 ret = drv->API.WaitClient(drv, disp, ctx); 1462 1463 RETURN_EGL_EVAL(disp, ret); 1464} 1465 1466EGLBoolean EGLAPIENTRY 1467eglWaitClient(void) 1468{ 1469 _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE); 1470 return _eglWaitClientCommon(); 1471} 1472 1473EGLBoolean EGLAPIENTRY 1474eglWaitGL(void) 1475{ 1476 /* Since we only support OpenGL and GLES, eglWaitGL is equivalent to eglWaitClient. */ 1477 _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE); 1478 return _eglWaitClientCommon(); 1479} 1480 1481 1482EGLBoolean EGLAPIENTRY 1483eglWaitNative(EGLint engine) 1484{ 1485 _EGLContext *ctx = _eglGetCurrentContext(); 1486 _EGLDisplay *disp; 1487 _EGLDriver *drv; 1488 EGLBoolean ret; 1489 1490 if (!ctx) 1491 RETURN_EGL_SUCCESS(NULL, EGL_TRUE); 1492 1493 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE); 1494 1495 disp = ctx->Resource.Display; 1496 mtx_lock(&disp->Mutex); 1497 1498 /* let bad current context imply bad current surface */ 1499 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1500 _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE) 1501 RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE); 1502 1503 /* a valid current context implies an initialized current display */ 1504 assert(disp->Initialized); 1505 drv = disp->Driver; 1506 ret = drv->API.WaitNative(drv, disp, engine); 1507 1508 RETURN_EGL_EVAL(disp, ret); 1509} 1510 1511 1512EGLDisplay EGLAPIENTRY 1513eglGetCurrentDisplay(void) 1514{ 1515 _EGLContext *ctx = _eglGetCurrentContext(); 1516 EGLDisplay ret; 1517 1518 ret = (ctx) ? _eglGetDisplayHandle(ctx->Resource.Display) : EGL_NO_DISPLAY; 1519 1520 RETURN_EGL_SUCCESS(NULL, ret); 1521} 1522 1523 1524EGLContext EGLAPIENTRY 1525eglGetCurrentContext(void) 1526{ 1527 _EGLContext *ctx = _eglGetCurrentContext(); 1528 EGLContext ret; 1529 1530 ret = _eglGetContextHandle(ctx); 1531 1532 RETURN_EGL_SUCCESS(NULL, ret); 1533} 1534 1535 1536EGLSurface EGLAPIENTRY 1537eglGetCurrentSurface(EGLint readdraw) 1538{ 1539 _EGLContext *ctx = _eglGetCurrentContext(); 1540 EGLint err = EGL_SUCCESS; 1541 _EGLSurface *surf; 1542 EGLSurface ret; 1543 1544 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_NO_SURFACE); 1545 1546 if (!ctx) 1547 RETURN_EGL_SUCCESS(NULL, EGL_NO_SURFACE); 1548 1549 switch (readdraw) { 1550 case EGL_DRAW: 1551 surf = ctx->DrawSurface; 1552 break; 1553 case EGL_READ: 1554 surf = ctx->ReadSurface; 1555 break; 1556 default: 1557 surf = NULL; 1558 err = EGL_BAD_PARAMETER; 1559 break; 1560 } 1561 1562 ret = _eglGetSurfaceHandle(surf); 1563 1564 RETURN_EGL_ERROR(NULL, err, ret); 1565} 1566 1567 1568EGLint EGLAPIENTRY 1569eglGetError(void) 1570{ 1571 _EGLThreadInfo *t = _eglGetCurrentThread(); 1572 EGLint e = t->LastError; 1573 if (!_eglIsCurrentThreadDummy()) 1574 t->LastError = EGL_SUCCESS; 1575 return e; 1576} 1577 1578 1579/** 1580 ** EGL 1.2 1581 **/ 1582 1583/** 1584 * Specify the client API to use for subsequent calls including: 1585 * eglCreateContext() 1586 * eglGetCurrentContext() 1587 * eglGetCurrentDisplay() 1588 * eglGetCurrentSurface() 1589 * eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT) 1590 * eglWaitClient() 1591 * eglWaitNative() 1592 * See section 3.7 "Rendering Context" in the EGL specification for details. 1593 */ 1594EGLBoolean EGLAPIENTRY 1595eglBindAPI(EGLenum api) 1596{ 1597 _EGLThreadInfo *t; 1598 1599 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE); 1600 1601 t = _eglGetCurrentThread(); 1602 if (_eglIsCurrentThreadDummy()) 1603 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE); 1604 1605 if (!_eglIsApiValid(api)) 1606 RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, EGL_FALSE); 1607 1608 t->CurrentAPI = api; 1609 1610 RETURN_EGL_SUCCESS(NULL, EGL_TRUE); 1611} 1612 1613 1614/** 1615 * Return the last value set with eglBindAPI(). 1616 */ 1617EGLenum EGLAPIENTRY 1618eglQueryAPI(void) 1619{ 1620 _EGLThreadInfo *t = _eglGetCurrentThread(); 1621 EGLenum ret; 1622 1623 /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */ 1624 ret = t->CurrentAPI; 1625 1626 RETURN_EGL_SUCCESS(NULL, ret); 1627} 1628 1629 1630EGLSurface EGLAPIENTRY 1631eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, 1632 EGLClientBuffer buffer, EGLConfig config, 1633 const EGLint *attrib_list) 1634{ 1635 _EGLDisplay *disp = _eglLockDisplay(dpy); 1636 _EGLConfig *conf = _eglLookupConfig(config, disp); 1637 _EGLDriver *drv; 1638 _EGLSurface *surf; 1639 EGLSurface ret; 1640 1641 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 1642 1643 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); 1644 1645 surf = drv->API.CreatePbufferFromClientBuffer(drv, disp, buftype, buffer, 1646 conf, attrib_list); 1647 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE; 1648 1649 RETURN_EGL_EVAL(disp, ret); 1650} 1651 1652 1653EGLBoolean EGLAPIENTRY 1654eglReleaseThread(void) 1655{ 1656 /* unbind current contexts */ 1657 if (!_eglIsCurrentThreadDummy()) { 1658 _EGLThreadInfo *t = _eglGetCurrentThread(); 1659 _EGLContext *ctx = t->CurrentContext; 1660 1661 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE); 1662 1663 if (ctx) { 1664 _EGLDisplay *disp = ctx->Resource.Display; 1665 _EGLDriver *drv; 1666 1667 mtx_lock(&disp->Mutex); 1668 drv = disp->Driver; 1669 (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL); 1670 mtx_unlock(&disp->Mutex); 1671 } 1672 } 1673 1674 _eglDestroyCurrentThread(); 1675 1676 RETURN_EGL_SUCCESS(NULL, EGL_TRUE); 1677} 1678 1679 1680static EGLImage 1681_eglCreateImageCommon(_EGLDisplay *disp, EGLContext ctx, EGLenum target, 1682 EGLClientBuffer buffer, const EGLint *attr_list) 1683{ 1684 _EGLContext *context = _eglLookupContext(ctx, disp); 1685 _EGLDriver *drv; 1686 _EGLImage *img; 1687 EGLImage ret; 1688 1689 _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv); 1690 if (!disp->Extensions.KHR_image_base) 1691 RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR); 1692 if (!context && ctx != EGL_NO_CONTEXT) 1693 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); 1694 /* "If <target> is EGL_LINUX_DMA_BUF_EXT, <dpy> must be a valid display, 1695 * <ctx> must be EGL_NO_CONTEXT..." 1696 */ 1697 if (ctx != EGL_NO_CONTEXT && target == EGL_LINUX_DMA_BUF_EXT) 1698 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); 1699 1700 img = drv->API.CreateImageKHR(drv, disp, context, target, 1701 buffer, attr_list); 1702 ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR; 1703 1704 RETURN_EGL_EVAL(disp, ret); 1705} 1706 1707static EGLImage EGLAPIENTRY 1708eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1709 EGLClientBuffer buffer, const EGLint *attr_list) 1710{ 1711 _EGLDisplay *disp = _eglLockDisplay(dpy); 1712 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR); 1713 return _eglCreateImageCommon(disp, ctx, target, buffer, attr_list); 1714} 1715 1716 1717EGLImage EGLAPIENTRY 1718eglCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1719 EGLClientBuffer buffer, const EGLAttrib *attr_list) 1720{ 1721 _EGLDisplay *disp = _eglLockDisplay(dpy); 1722 EGLImage image; 1723 EGLint *int_attribs; 1724 1725 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR); 1726 1727 int_attribs = _eglConvertAttribsToInt(attr_list); 1728 if (attr_list && !int_attribs) 1729 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_IMAGE); 1730 1731 image = _eglCreateImageCommon(disp, ctx, target, buffer, int_attribs); 1732 free(int_attribs); 1733 return image; 1734} 1735 1736 1737static EGLBoolean 1738_eglDestroyImageCommon(_EGLDisplay *disp, _EGLImage *img) 1739{ 1740 _EGLDriver *drv; 1741 EGLBoolean ret; 1742 1743 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 1744 if (!disp->Extensions.KHR_image_base) 1745 RETURN_EGL_EVAL(disp, EGL_FALSE); 1746 if (!img) 1747 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 1748 1749 _eglUnlinkImage(img); 1750 ret = drv->API.DestroyImageKHR(drv, disp, img); 1751 1752 RETURN_EGL_EVAL(disp, ret); 1753} 1754 1755EGLBoolean EGLAPIENTRY 1756eglDestroyImage(EGLDisplay dpy, EGLImage image) 1757{ 1758 _EGLDisplay *disp = _eglLockDisplay(dpy); 1759 _EGLImage *img = _eglLookupImage(image, disp); 1760 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); 1761 return _eglDestroyImageCommon(disp, img); 1762} 1763 1764static EGLBoolean EGLAPIENTRY 1765eglDestroyImageKHR(EGLDisplay dpy, EGLImage image) 1766{ 1767 _EGLDisplay *disp = _eglLockDisplay(dpy); 1768 _EGLImage *img = _eglLookupImage(image, disp); 1769 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); 1770 return _eglDestroyImageCommon(disp, img); 1771} 1772 1773 1774static EGLSync 1775_eglCreateSync(_EGLDisplay *disp, EGLenum type, const EGLAttrib *attrib_list, 1776 EGLBoolean orig_is_EGLAttrib, 1777 EGLenum invalid_type_error) 1778{ 1779 _EGLContext *ctx = _eglGetCurrentContext(); 1780 _EGLDriver *drv; 1781 _EGLSync *sync; 1782 EGLSync ret; 1783 1784 _EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv); 1785 1786 if (!disp->Extensions.KHR_cl_event2 && orig_is_EGLAttrib) { 1787 /* There exist two EGLAttrib variants of eglCreateSync*: 1788 * eglCreateSync64KHR which requires EGL_KHR_cl_event2, and eglCreateSync 1789 * which requires EGL 1.5. Here we use the presence of EGL_KHR_cl_event2 1790 * support as a proxy for EGL 1.5 support, even though that's not 1791 * entirely correct (though _eglComputeVersion does the same). 1792 * 1793 * The EGL spec provides no guidance on how to handle unsupported 1794 * functions. EGL_BAD_MATCH seems reasonable. 1795 */ 1796 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR); 1797 } 1798 1799 /* If type is EGL_SYNC_FENCE and no context is current for the bound API 1800 * (i.e., eglGetCurrentContext returns EGL_NO_CONTEXT ), an EGL_BAD_MATCH 1801 * error is generated. 1802 */ 1803 if (!ctx && 1804 (type == EGL_SYNC_FENCE_KHR || type == EGL_SYNC_NATIVE_FENCE_ANDROID)) 1805 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR); 1806 1807 /* return an error if the client API doesn't support GL_OES_EGL_sync */ 1808 if (ctx && (ctx->Resource.Display != disp || 1809 ctx->ClientAPI != EGL_OPENGL_ES_API)) 1810 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR); 1811 1812 switch (type) { 1813 case EGL_SYNC_FENCE_KHR: 1814 if (!disp->Extensions.KHR_fence_sync) 1815 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR); 1816 break; 1817 case EGL_SYNC_REUSABLE_KHR: 1818 if (!disp->Extensions.KHR_reusable_sync) 1819 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR); 1820 break; 1821 case EGL_SYNC_CL_EVENT_KHR: 1822 if (!disp->Extensions.KHR_cl_event2) 1823 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR); 1824 break; 1825 case EGL_SYNC_NATIVE_FENCE_ANDROID: 1826 if (!disp->Extensions.ANDROID_native_fence_sync) 1827 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR); 1828 break; 1829 default: 1830 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR); 1831 } 1832 1833 sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list); 1834 ret = (sync) ? _eglLinkSync(sync) : EGL_NO_SYNC_KHR; 1835 1836 RETURN_EGL_EVAL(disp, ret); 1837} 1838 1839 1840static EGLSync EGLAPIENTRY 1841eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *int_list) 1842{ 1843 _EGLDisplay *disp = _eglLockDisplay(dpy); 1844 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 1845 1846 EGLSync sync; 1847 EGLAttrib *attrib_list; 1848 EGLint err; 1849 1850 if (sizeof(int_list[0]) == sizeof(attrib_list[0])) { 1851 attrib_list = (EGLAttrib *) int_list; 1852 } else { 1853 err = _eglConvertIntsToAttribs(int_list, &attrib_list); 1854 if (err != EGL_SUCCESS) 1855 RETURN_EGL_ERROR(disp, err, EGL_NO_SYNC); 1856 } 1857 1858 sync = _eglCreateSync(disp, type, attrib_list, EGL_FALSE, 1859 EGL_BAD_ATTRIBUTE); 1860 1861 if (sizeof(int_list[0]) != sizeof(attrib_list[0])) 1862 free(attrib_list); 1863 1864 /* Don't double-unlock the display. _eglCreateSync already unlocked it. */ 1865 return sync; 1866} 1867 1868 1869static EGLSync EGLAPIENTRY 1870eglCreateSync64KHR(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list) 1871{ 1872 _EGLDisplay *disp = _eglLockDisplay(dpy); 1873 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 1874 return _eglCreateSync(disp, type, attrib_list, EGL_TRUE, 1875 EGL_BAD_ATTRIBUTE); 1876} 1877 1878 1879EGLSync EGLAPIENTRY 1880eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list) 1881{ 1882 _EGLDisplay *disp = _eglLockDisplay(dpy); 1883 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 1884 return _eglCreateSync(disp, type, attrib_list, EGL_TRUE, 1885 EGL_BAD_PARAMETER); 1886} 1887 1888 1889static EGLBoolean 1890_eglDestroySync(_EGLDisplay *disp, _EGLSync *s) 1891{ 1892 _EGLDriver *drv; 1893 EGLBoolean ret; 1894 1895 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); 1896 assert(disp->Extensions.KHR_reusable_sync || 1897 disp->Extensions.KHR_fence_sync || 1898 disp->Extensions.ANDROID_native_fence_sync); 1899 1900 _eglUnlinkSync(s); 1901 ret = drv->API.DestroySyncKHR(drv, disp, s); 1902 1903 RETURN_EGL_EVAL(disp, ret); 1904} 1905 1906EGLBoolean EGLAPIENTRY 1907eglDestroySync(EGLDisplay dpy, EGLSync sync) 1908{ 1909 _EGLDisplay *disp = _eglLockDisplay(dpy); 1910 _EGLSync *s = _eglLookupSync(sync, disp); 1911 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1912 return _eglDestroySync(disp, s); 1913} 1914 1915static EGLBoolean EGLAPIENTRY 1916eglDestroySyncKHR(EGLDisplay dpy, EGLSync sync) 1917{ 1918 _EGLDisplay *disp = _eglLockDisplay(dpy); 1919 _EGLSync *s = _eglLookupSync(sync, disp); 1920 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1921 return _eglDestroySync(disp, s); 1922} 1923 1924 1925static EGLint 1926_eglClientWaitSyncCommon(_EGLDisplay *disp, EGLDisplay dpy, 1927 _EGLSync *s, EGLint flags, EGLTime timeout) 1928{ 1929 _EGLDriver *drv; 1930 EGLint ret; 1931 1932 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); 1933 assert(disp->Extensions.KHR_reusable_sync || 1934 disp->Extensions.KHR_fence_sync || 1935 disp->Extensions.ANDROID_native_fence_sync); 1936 1937 if (s->SyncStatus == EGL_SIGNALED_KHR) 1938 RETURN_EGL_EVAL(disp, EGL_CONDITION_SATISFIED_KHR); 1939 1940 /* if sync type is EGL_SYNC_REUSABLE_KHR, dpy should be 1941 * unlocked here to allow other threads also to be able to 1942 * go into waiting state. 1943 */ 1944 1945 if (s->Type == EGL_SYNC_REUSABLE_KHR) 1946 _eglUnlockDisplay(dpy); 1947 1948 ret = drv->API.ClientWaitSyncKHR(drv, disp, s, flags, timeout); 1949 1950 /* 1951 * 'disp' is already unlocked for reusable sync type, 1952 * so passing 'NULL' to bypass unlocking display. 1953 */ 1954 if (s->Type == EGL_SYNC_REUSABLE_KHR) 1955 RETURN_EGL_EVAL(NULL, ret); 1956 else 1957 RETURN_EGL_EVAL(disp, ret); 1958} 1959 1960EGLint EGLAPIENTRY 1961eglClientWaitSync(EGLDisplay dpy, EGLSync sync, 1962 EGLint flags, EGLTime timeout) 1963{ 1964 _EGLDisplay *disp = _eglLockDisplay(dpy); 1965 _EGLSync *s = _eglLookupSync(sync, disp); 1966 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1967 return _eglClientWaitSyncCommon(disp, dpy, s, flags, timeout); 1968} 1969 1970static EGLint EGLAPIENTRY 1971eglClientWaitSyncKHR(EGLDisplay dpy, EGLSync sync, 1972 EGLint flags, EGLTime timeout) 1973{ 1974 _EGLDisplay *disp = _eglLockDisplay(dpy); 1975 _EGLSync *s = _eglLookupSync(sync, disp); 1976 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1977 return _eglClientWaitSyncCommon(disp, dpy, s, flags, timeout); 1978} 1979 1980 1981static EGLint 1982_eglWaitSyncCommon(_EGLDisplay *disp, _EGLSync *s, EGLint flags) 1983{ 1984 _EGLContext *ctx = _eglGetCurrentContext(); 1985 _EGLDriver *drv; 1986 EGLint ret; 1987 1988 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); 1989 assert(disp->Extensions.KHR_wait_sync); 1990 1991 /* return an error if the client API doesn't support GL_OES_EGL_sync */ 1992 if (ctx == EGL_NO_CONTEXT || ctx->ClientAPI != EGL_OPENGL_ES_API) 1993 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE); 1994 1995 /* the API doesn't allow any flags yet */ 1996 if (flags != 0) 1997 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 1998 1999 ret = drv->API.WaitSyncKHR(drv, disp, s); 2000 2001 RETURN_EGL_EVAL(disp, ret); 2002} 2003 2004static EGLint EGLAPIENTRY 2005eglWaitSyncKHR(EGLDisplay dpy, EGLSync sync, EGLint flags) 2006{ 2007 _EGLDisplay *disp = _eglLockDisplay(dpy); 2008 _EGLSync *s = _eglLookupSync(sync, disp); 2009 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 2010 return _eglWaitSyncCommon(disp, s, flags); 2011} 2012 2013 2014EGLBoolean EGLAPIENTRY 2015eglWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags) 2016{ 2017 /* The KHR version returns EGLint, while the core version returns 2018 * EGLBoolean. In both cases, the return values can only be EGL_FALSE and 2019 * EGL_TRUE. 2020 */ 2021 _EGLDisplay *disp = _eglLockDisplay(dpy); 2022 _EGLSync *s = _eglLookupSync(sync, disp); 2023 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 2024 return _eglWaitSyncCommon(disp, s, flags); 2025} 2026 2027 2028static EGLBoolean EGLAPIENTRY 2029eglSignalSyncKHR(EGLDisplay dpy, EGLSync sync, EGLenum mode) 2030{ 2031 _EGLDisplay *disp = _eglLockDisplay(dpy); 2032 _EGLSync *s = _eglLookupSync(sync, disp); 2033 _EGLDriver *drv; 2034 EGLBoolean ret; 2035 2036 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 2037 2038 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); 2039 assert(disp->Extensions.KHR_reusable_sync); 2040 ret = drv->API.SignalSyncKHR(drv, disp, s, mode); 2041 2042 RETURN_EGL_EVAL(disp, ret); 2043} 2044 2045 2046static EGLBoolean 2047_eglGetSyncAttribCommon(_EGLDisplay *disp, _EGLSync *s, EGLint attribute, EGLAttrib *value) 2048{ 2049 _EGLDriver *drv; 2050 EGLBoolean ret; 2051 2052 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); 2053 assert(disp->Extensions.KHR_reusable_sync || 2054 disp->Extensions.KHR_fence_sync || 2055 disp->Extensions.ANDROID_native_fence_sync); 2056 ret = drv->API.GetSyncAttrib(drv, disp, s, attribute, value); 2057 2058 RETURN_EGL_EVAL(disp, ret); 2059} 2060 2061EGLBoolean EGLAPIENTRY 2062eglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value) 2063{ 2064 _EGLDisplay *disp = _eglLockDisplay(dpy); 2065 _EGLSync *s = _eglLookupSync(sync, disp); 2066 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 2067 return _eglGetSyncAttribCommon(disp, s, attribute, value); 2068} 2069 2070 2071static EGLBoolean EGLAPIENTRY 2072eglGetSyncAttribKHR(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint *value) 2073{ 2074 _EGLDisplay *disp = _eglLockDisplay(dpy); 2075 _EGLSync *s = _eglLookupSync(sync, disp); 2076 EGLAttrib attrib; 2077 EGLBoolean result; 2078 2079 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 2080 2081 if (!value) 2082 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2083 2084 attrib = *value; 2085 result = _eglGetSyncAttribCommon(disp, s, attribute, &attrib); 2086 2087 /* The EGL_KHR_fence_sync spec says this about eglGetSyncAttribKHR: 2088 * 2089 * If any error occurs, <*value> is not modified. 2090 */ 2091 if (result == EGL_FALSE) 2092 return result; 2093 2094 *value = attrib; 2095 return result; 2096} 2097 2098static EGLint EGLAPIENTRY 2099eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync) 2100{ 2101 _EGLDisplay *disp = _eglLockDisplay(dpy); 2102 _EGLSync *s = _eglLookupSync(sync, disp); 2103 _EGLDriver *drv; 2104 EGLBoolean ret; 2105 2106 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 2107 2108 /* the spec doesn't seem to specify what happens if the fence 2109 * type is not EGL_SYNC_NATIVE_FENCE_ANDROID, but this seems 2110 * sensible: 2111 */ 2112 if (!(s && (s->Type == EGL_SYNC_NATIVE_FENCE_ANDROID))) 2113 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_NATIVE_FENCE_FD_ANDROID); 2114 2115 _EGL_CHECK_SYNC(disp, s, EGL_NO_NATIVE_FENCE_FD_ANDROID, drv); 2116 assert(disp->Extensions.ANDROID_native_fence_sync); 2117 ret = drv->API.DupNativeFenceFDANDROID(drv, disp, s); 2118 2119 RETURN_EGL_EVAL(disp, ret); 2120} 2121 2122static EGLBoolean EGLAPIENTRY 2123eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface, 2124 EGLint numRects, const EGLint *rects) 2125{ 2126 _EGLContext *ctx = _eglGetCurrentContext(); 2127 _EGLDisplay *disp = _eglLockDisplay(dpy); 2128 _EGLSurface *surf = _eglLookupSurface(surface, disp); 2129 _EGLDriver *drv; 2130 EGLBoolean ret; 2131 2132 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 2133 2134 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 2135 2136 if (!disp->Extensions.NOK_swap_region) 2137 RETURN_EGL_EVAL(disp, EGL_FALSE); 2138 2139 /* surface must be bound to current context in EGL 1.4 */ 2140 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 2141 surf != ctx->DrawSurface) 2142 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 2143 2144 ret = drv->API.SwapBuffersRegionNOK(drv, disp, surf, numRects, rects); 2145 2146 RETURN_EGL_EVAL(disp, ret); 2147} 2148 2149 2150static EGLImage EGLAPIENTRY 2151eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list) 2152{ 2153 _EGLDisplay *disp = _eglLockDisplay(dpy); 2154 _EGLDriver *drv; 2155 _EGLImage *img; 2156 EGLImage ret; 2157 2158 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 2159 2160 _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv); 2161 if (!disp->Extensions.MESA_drm_image) 2162 RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR); 2163 2164 img = drv->API.CreateDRMImageMESA(drv, disp, attr_list); 2165 ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR; 2166 2167 RETURN_EGL_EVAL(disp, ret); 2168} 2169 2170static EGLBoolean EGLAPIENTRY 2171eglExportDRMImageMESA(EGLDisplay dpy, EGLImage image, 2172 EGLint *name, EGLint *handle, EGLint *stride) 2173{ 2174 _EGLDisplay *disp = _eglLockDisplay(dpy); 2175 _EGLImage *img = _eglLookupImage(image, disp); 2176 _EGLDriver *drv; 2177 EGLBoolean ret; 2178 2179 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); 2180 2181 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2182 assert(disp->Extensions.MESA_drm_image); 2183 2184 if (!img) 2185 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2186 2187 ret = drv->API.ExportDRMImageMESA(drv, disp, img, name, handle, stride); 2188 2189 RETURN_EGL_EVAL(disp, ret); 2190} 2191 2192 2193struct wl_display; 2194 2195static EGLBoolean EGLAPIENTRY 2196eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display) 2197{ 2198 _EGLDisplay *disp = _eglLockDisplay(dpy); 2199 _EGLDriver *drv; 2200 EGLBoolean ret; 2201 2202 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 2203 2204 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2205 assert(disp->Extensions.WL_bind_wayland_display); 2206 2207 if (!display) 2208 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2209 2210 ret = drv->API.BindWaylandDisplayWL(drv, disp, display); 2211 2212 RETURN_EGL_EVAL(disp, ret); 2213} 2214 2215static EGLBoolean EGLAPIENTRY 2216eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display) 2217{ 2218 _EGLDisplay *disp = _eglLockDisplay(dpy); 2219 _EGLDriver *drv; 2220 EGLBoolean ret; 2221 2222 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 2223 2224 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2225 assert(disp->Extensions.WL_bind_wayland_display); 2226 2227 if (!display) 2228 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2229 2230 ret = drv->API.UnbindWaylandDisplayWL(drv, disp, display); 2231 2232 RETURN_EGL_EVAL(disp, ret); 2233} 2234 2235static EGLBoolean EGLAPIENTRY 2236eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer, 2237 EGLint attribute, EGLint *value) 2238{ 2239 _EGLDisplay *disp = _eglLockDisplay(dpy); 2240 _EGLDriver *drv; 2241 EGLBoolean ret; 2242 2243 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 2244 2245 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2246 assert(disp->Extensions.WL_bind_wayland_display); 2247 2248 if (!buffer) 2249 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2250 2251 ret = drv->API.QueryWaylandBufferWL(drv, disp, buffer, attribute, value); 2252 2253 RETURN_EGL_EVAL(disp, ret); 2254} 2255 2256 2257static struct wl_buffer * EGLAPIENTRY 2258eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImage image) 2259{ 2260 _EGLDisplay *disp = _eglLockDisplay(dpy); 2261 _EGLImage *img; 2262 _EGLDriver *drv; 2263 struct wl_buffer *ret; 2264 2265 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 2266 2267 _EGL_CHECK_DISPLAY(disp, NULL, drv); 2268 if (!disp->Extensions.WL_create_wayland_buffer_from_image) 2269 RETURN_EGL_EVAL(disp, NULL); 2270 2271 img = _eglLookupImage(image, disp); 2272 2273 if (!img) 2274 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL); 2275 2276 ret = drv->API.CreateWaylandBufferFromImageWL(drv, disp, img); 2277 2278 RETURN_EGL_EVAL(disp, ret); 2279} 2280 2281static EGLBoolean EGLAPIENTRY 2282eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, 2283 EGLint x, EGLint y, EGLint width, EGLint height) 2284{ 2285 _EGLDisplay *disp = _eglLockDisplay(dpy); 2286 _EGLSurface *surf = _eglLookupSurface(surface, disp); 2287 _EGLDriver *drv; 2288 EGLBoolean ret; 2289 2290 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 2291 2292 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 2293 2294 if (!disp->Extensions.NV_post_sub_buffer) 2295 RETURN_EGL_EVAL(disp, EGL_FALSE); 2296 2297 ret = drv->API.PostSubBufferNV(drv, disp, surf, x, y, width, height); 2298 2299 RETURN_EGL_EVAL(disp, ret); 2300} 2301 2302static EGLBoolean EGLAPIENTRY 2303eglGetSyncValuesCHROMIUM(EGLDisplay dpy, EGLSurface surface, 2304 EGLuint64KHR *ust, EGLuint64KHR *msc, 2305 EGLuint64KHR *sbc) 2306{ 2307 _EGLDisplay *disp = _eglLockDisplay(dpy); 2308 _EGLSurface *surf = _eglLookupSurface(surface, disp); 2309 _EGLDriver *drv; 2310 EGLBoolean ret; 2311 2312 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 2313 2314 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 2315 if (!disp->Extensions.CHROMIUM_sync_control) 2316 RETURN_EGL_EVAL(disp, EGL_FALSE); 2317 2318 if (!ust || !msc || !sbc) 2319 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2320 2321 ret = drv->API.GetSyncValuesCHROMIUM(disp, surf, ust, msc, sbc); 2322 2323 RETURN_EGL_EVAL(disp, ret); 2324} 2325 2326static EGLBoolean EGLAPIENTRY 2327eglExportDMABUFImageQueryMESA(EGLDisplay dpy, EGLImage image, 2328 EGLint *fourcc, EGLint *nplanes, 2329 EGLuint64KHR *modifiers) 2330{ 2331 _EGLDisplay *disp = _eglLockDisplay(dpy); 2332 _EGLImage *img = _eglLookupImage(image, disp); 2333 _EGLDriver *drv; 2334 EGLBoolean ret; 2335 2336 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); 2337 2338 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2339 assert(disp->Extensions.MESA_image_dma_buf_export); 2340 2341 if (!img) 2342 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2343 2344 ret = drv->API.ExportDMABUFImageQueryMESA(drv, disp, img, fourcc, nplanes, 2345 modifiers); 2346 2347 RETURN_EGL_EVAL(disp, ret); 2348} 2349 2350static EGLBoolean EGLAPIENTRY 2351eglExportDMABUFImageMESA(EGLDisplay dpy, EGLImage image, 2352 int *fds, EGLint *strides, EGLint *offsets) 2353{ 2354 _EGLDisplay *disp = _eglLockDisplay(dpy); 2355 _EGLImage *img = _eglLookupImage(image, disp); 2356 _EGLDriver *drv; 2357 EGLBoolean ret; 2358 2359 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); 2360 2361 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2362 assert(disp->Extensions.MESA_image_dma_buf_export); 2363 2364 if (!img) 2365 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2366 2367 ret = drv->API.ExportDMABUFImageMESA(drv, disp, img, fds, strides, offsets); 2368 2369 RETURN_EGL_EVAL(disp, ret); 2370} 2371 2372static EGLint EGLAPIENTRY 2373eglLabelObjectKHR(EGLDisplay dpy, EGLenum objectType, EGLObjectKHR object, 2374 EGLLabelKHR label) 2375{ 2376 _EGLDisplay *disp = NULL; 2377 _EGLResourceType type; 2378 2379 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC); 2380 2381 if (objectType == EGL_OBJECT_THREAD_KHR) { 2382 _EGLThreadInfo *t = _eglGetCurrentThread(); 2383 2384 if (!_eglIsCurrentThreadDummy()) { 2385 t->Label = label; 2386 return EGL_SUCCESS; 2387 } 2388 2389 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_BAD_ALLOC); 2390 } 2391 2392 disp = _eglLockDisplay(dpy); 2393 if (disp == NULL) 2394 RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_BAD_DISPLAY); 2395 2396 if (objectType == EGL_OBJECT_DISPLAY_KHR) { 2397 if (dpy != (EGLDisplay) object) 2398 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER); 2399 2400 disp->Label = label; 2401 RETURN_EGL_EVAL(disp, EGL_SUCCESS); 2402 } 2403 2404 switch (objectType) { 2405 case EGL_OBJECT_CONTEXT_KHR: 2406 type = _EGL_RESOURCE_CONTEXT; 2407 break; 2408 case EGL_OBJECT_SURFACE_KHR: 2409 type = _EGL_RESOURCE_SURFACE; 2410 break; 2411 case EGL_OBJECT_IMAGE_KHR: 2412 type = _EGL_RESOURCE_IMAGE; 2413 break; 2414 case EGL_OBJECT_SYNC_KHR: 2415 type = _EGL_RESOURCE_SYNC; 2416 break; 2417 case EGL_OBJECT_STREAM_KHR: 2418 default: 2419 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER); 2420 } 2421 2422 if (_eglCheckResource(object, type, disp)) { 2423 _EGLResource *res = (_EGLResource *) object; 2424 2425 res->Label = label; 2426 RETURN_EGL_EVAL(disp, EGL_SUCCESS); 2427 } 2428 2429 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER); 2430} 2431 2432static EGLint EGLAPIENTRY 2433eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback, 2434 const EGLAttrib *attrib_list) 2435{ 2436 unsigned int newEnabled; 2437 2438 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC); 2439 2440 mtx_lock(_eglGlobal.Mutex); 2441 2442 newEnabled = _eglGlobal.debugTypesEnabled; 2443 if (attrib_list != NULL) { 2444 int i; 2445 2446 for (i = 0; attrib_list[i] != EGL_NONE; i += 2) { 2447 switch (attrib_list[i]) { 2448 case EGL_DEBUG_MSG_CRITICAL_KHR: 2449 case EGL_DEBUG_MSG_ERROR_KHR: 2450 case EGL_DEBUG_MSG_WARN_KHR: 2451 case EGL_DEBUG_MSG_INFO_KHR: 2452 if (attrib_list[i + 1]) 2453 newEnabled |= DebugBitFromType(attrib_list[i]); 2454 else 2455 newEnabled &= ~DebugBitFromType(attrib_list[i]); 2456 break; 2457 default: 2458 // On error, set the last error code, call the current 2459 // debug callback, and return the error code. 2460 mtx_unlock(_eglGlobal.Mutex); 2461 _eglReportError(EGL_BAD_ATTRIBUTE, NULL, 2462 "Invalid attribute 0x%04lx", (unsigned long) attrib_list[i]); 2463 return EGL_BAD_ATTRIBUTE; 2464 } 2465 } 2466 } 2467 2468 if (callback != NULL) { 2469 _eglGlobal.debugCallback = callback; 2470 _eglGlobal.debugTypesEnabled = newEnabled; 2471 } else { 2472 _eglGlobal.debugCallback = NULL; 2473 _eglGlobal.debugTypesEnabled = _EGL_DEBUG_BIT_CRITICAL | _EGL_DEBUG_BIT_ERROR; 2474 } 2475 2476 mtx_unlock(_eglGlobal.Mutex); 2477 return EGL_SUCCESS; 2478} 2479 2480static EGLBoolean EGLAPIENTRY 2481eglQueryDebugKHR(EGLint attribute, EGLAttrib *value) 2482{ 2483 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC); 2484 2485 mtx_lock(_eglGlobal.Mutex); 2486 2487 switch (attribute) { 2488 case EGL_DEBUG_MSG_CRITICAL_KHR: 2489 case EGL_DEBUG_MSG_ERROR_KHR: 2490 case EGL_DEBUG_MSG_WARN_KHR: 2491 case EGL_DEBUG_MSG_INFO_KHR: 2492 if (_eglGlobal.debugTypesEnabled & DebugBitFromType(attribute)) 2493 *value = EGL_TRUE; 2494 else 2495 *value = EGL_FALSE; 2496 break; 2497 case EGL_DEBUG_CALLBACK_KHR: 2498 *value = (EGLAttrib) _eglGlobal.debugCallback; 2499 break; 2500 default: 2501 mtx_unlock(_eglGlobal.Mutex); 2502 _eglReportError(EGL_BAD_ATTRIBUTE, NULL, 2503 "Invalid attribute 0x%04lx", (unsigned long) attribute); 2504 return EGL_FALSE; 2505 } 2506 2507 mtx_unlock(_eglGlobal.Mutex); 2508 return EGL_TRUE; 2509} 2510 2511static int 2512_eglFunctionCompare(const void *key, const void *elem) 2513{ 2514 const char *procname = key; 2515 const struct _egl_entrypoint *entrypoint = elem; 2516 return strcmp(procname, entrypoint->name); 2517} 2518 2519static EGLBoolean EGLAPIENTRY 2520eglQueryDmaBufFormatsEXT(EGLDisplay dpy, EGLint max_formats, 2521 EGLint *formats, EGLint *num_formats) 2522{ 2523 _EGLDisplay *disp = _eglLockDisplay(dpy); 2524 _EGLDriver *drv; 2525 EGLBoolean ret; 2526 2527 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE); 2528 2529 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2530 2531 ret = drv->API.QueryDmaBufFormatsEXT(drv, disp, max_formats, formats, 2532 num_formats); 2533 2534 RETURN_EGL_EVAL(disp, ret); 2535} 2536 2537static EGLBoolean EGLAPIENTRY 2538eglQueryDmaBufModifiersEXT(EGLDisplay dpy, EGLint format, EGLint max_modifiers, 2539 EGLuint64KHR *modifiers, EGLBoolean *external_only, 2540 EGLint *num_modifiers) 2541{ 2542 _EGLDisplay *disp = _eglLockDisplay(dpy); 2543 _EGLDriver *drv; 2544 EGLBoolean ret; 2545 2546 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE); 2547 2548 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2549 2550 ret = drv->API.QueryDmaBufModifiersEXT(drv, disp, format, max_modifiers, 2551 modifiers, external_only, 2552 num_modifiers); 2553 2554 RETURN_EGL_EVAL(disp, ret); 2555} 2556 2557static void EGLAPIENTRY 2558eglSetBlobCacheFuncsANDROID(EGLDisplay *dpy, EGLSetBlobFuncANDROID set, 2559 EGLGetBlobFuncANDROID get) 2560{ 2561 /* This function does not return anything so we cannot 2562 * utilize the helper macros _EGL_FUNC_START or _EGL_CHECK_DISPLAY. 2563 */ 2564 _EGLDisplay *disp = _eglLockDisplay(dpy); 2565 if (!_eglSetFuncName(__func__, disp, EGL_OBJECT_DISPLAY_KHR, NULL)) { 2566 if (disp) 2567 _eglUnlockDisplay(disp); 2568 return; 2569 } 2570 2571 _EGLDriver *drv = _eglCheckDisplay(disp, __func__); 2572 if (!drv) { 2573 if (disp) 2574 _eglUnlockDisplay(disp); 2575 return; 2576 } 2577 2578 if (!set || !get) { 2579 _eglError(EGL_BAD_PARAMETER, 2580 "eglSetBlobCacheFuncsANDROID: NULL handler given"); 2581 _eglUnlockDisplay(disp); 2582 return; 2583 } 2584 2585 if (disp->BlobCacheSet) { 2586 _eglError(EGL_BAD_PARAMETER, 2587 "eglSetBlobCacheFuncsANDROID: functions already set"); 2588 _eglUnlockDisplay(disp); 2589 return; 2590 } 2591 2592 disp->BlobCacheSet = set; 2593 disp->BlobCacheGet = get; 2594 2595 drv->API.SetBlobCacheFuncsANDROID(drv, disp, set, get); 2596 2597 _eglUnlockDisplay(disp); 2598} 2599 2600static EGLBoolean EGLAPIENTRY 2601eglQueryDeviceAttribEXT(EGLDeviceEXT device, 2602 EGLint attribute, 2603 EGLAttrib *value) 2604{ 2605 _EGLDevice *dev = _eglLookupDevice(device); 2606 EGLBoolean ret; 2607 2608 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE); 2609 if (!dev) 2610 RETURN_EGL_ERROR(NULL, EGL_BAD_DEVICE_EXT, EGL_FALSE); 2611 2612 ret = _eglQueryDeviceAttribEXT(dev, attribute, value); 2613 RETURN_EGL_EVAL(NULL, ret); 2614} 2615 2616static const char * EGLAPIENTRY 2617eglQueryDeviceStringEXT(EGLDeviceEXT device, 2618 EGLint name) 2619{ 2620 _EGLDevice *dev = _eglLookupDevice(device); 2621 2622 _EGL_FUNC_START(NULL, EGL_NONE, NULL, NULL); 2623 if (!dev) 2624 RETURN_EGL_ERROR(NULL, EGL_BAD_DEVICE_EXT, NULL); 2625 2626 RETURN_EGL_EVAL(NULL, _eglQueryDeviceStringEXT(dev, name)); 2627} 2628 2629static EGLBoolean EGLAPIENTRY 2630eglQueryDevicesEXT(EGLint max_devices, 2631 EGLDeviceEXT *devices, 2632 EGLint *num_devices) 2633{ 2634 EGLBoolean ret; 2635 2636 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE); 2637 ret = _eglQueryDevicesEXT(max_devices, (_EGLDevice **) devices, 2638 num_devices); 2639 RETURN_EGL_EVAL(NULL, ret); 2640} 2641 2642static EGLBoolean EGLAPIENTRY 2643eglQueryDisplayAttribEXT(EGLDisplay dpy, 2644 EGLint attribute, 2645 EGLAttrib *value) 2646{ 2647 _EGLDisplay *disp = _eglLockDisplay(dpy); 2648 _EGLDriver *drv; 2649 2650 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE); 2651 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2652 2653 switch (attribute) { 2654 case EGL_DEVICE_EXT: 2655 *value = (EGLAttrib) disp->Device; 2656 break; 2657 default: 2658 RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_FALSE); 2659 } 2660 RETURN_EGL_SUCCESS(disp, EGL_TRUE); 2661} 2662 2663static char * EGLAPIENTRY 2664eglGetDisplayDriverConfig(EGLDisplay dpy) 2665{ 2666 _EGLDisplay *disp = _eglLockDisplay(dpy); 2667 _EGLDriver *drv; 2668 char *ret; 2669 2670 _EGL_FUNC_START(disp, EGL_NONE, NULL, NULL); 2671 _EGL_CHECK_DISPLAY(disp, NULL, drv); 2672 2673 assert(disp->Extensions.MESA_query_driver); 2674 2675 ret = drv->API.QueryDriverConfig(disp); 2676 RETURN_EGL_EVAL(disp, ret); 2677} 2678 2679static const char * EGLAPIENTRY 2680eglGetDisplayDriverName(EGLDisplay dpy) 2681{ 2682 _EGLDisplay *disp = _eglLockDisplay(dpy); 2683 _EGLDriver *drv; 2684 const char *ret; 2685 2686 _EGL_FUNC_START(disp, EGL_NONE, NULL, NULL); 2687 _EGL_CHECK_DISPLAY(disp, NULL, drv); 2688 2689 assert(disp->Extensions.MESA_query_driver); 2690 2691 ret = drv->API.QueryDriverName(disp); 2692 RETURN_EGL_EVAL(disp, ret); 2693} 2694 2695__eglMustCastToProperFunctionPointerType EGLAPIENTRY 2696eglGetProcAddress(const char *procname) 2697{ 2698 static const struct _egl_entrypoint egl_functions[] = { 2699#define EGL_ENTRYPOINT(f) { .name = #f, .function = (_EGLProc) f }, 2700#include "eglentrypoint.h" 2701#undef EGL_ENTRYPOINT 2702 }; 2703 _EGLProc ret = NULL; 2704 2705 if (!procname) 2706 RETURN_EGL_SUCCESS(NULL, NULL); 2707 2708 _EGL_FUNC_START(NULL, EGL_NONE, NULL, NULL); 2709 2710 if (strncmp(procname, "egl", 3) == 0) { 2711 const struct _egl_entrypoint *entrypoint = 2712 bsearch(procname, 2713 egl_functions, ARRAY_SIZE(egl_functions), 2714 sizeof(egl_functions[0]), 2715 _eglFunctionCompare); 2716 if (entrypoint) 2717 ret = entrypoint->function; 2718 } 2719 2720 if (!ret) 2721 ret = _eglGetDriverProc(procname); 2722 2723 RETURN_EGL_SUCCESS(NULL, ret); 2724} 2725 2726static int 2727_eglLockDisplayInterop(EGLDisplay dpy, EGLContext context, 2728 _EGLDisplay **disp, _EGLDriver **drv, 2729 _EGLContext **ctx) 2730{ 2731 2732 *disp = _eglLockDisplay(dpy); 2733 if (!*disp || !(*disp)->Initialized || !(*disp)->Driver) { 2734 if (*disp) 2735 _eglUnlockDisplay(*disp); 2736 return MESA_GLINTEROP_INVALID_DISPLAY; 2737 } 2738 2739 *drv = (*disp)->Driver; 2740 2741 *ctx = _eglLookupContext(context, *disp); 2742 if (!*ctx || 2743 ((*ctx)->ClientAPI != EGL_OPENGL_API && 2744 (*ctx)->ClientAPI != EGL_OPENGL_ES_API)) { 2745 _eglUnlockDisplay(*disp); 2746 return MESA_GLINTEROP_INVALID_CONTEXT; 2747 } 2748 2749 return MESA_GLINTEROP_SUCCESS; 2750} 2751 2752PUBLIC int 2753MesaGLInteropEGLQueryDeviceInfo(EGLDisplay dpy, EGLContext context, 2754 struct mesa_glinterop_device_info *out) 2755{ 2756 _EGLDisplay *disp; 2757 _EGLDriver *drv; 2758 _EGLContext *ctx; 2759 int ret; 2760 2761 ret = _eglLockDisplayInterop(dpy, context, &disp, &drv, &ctx); 2762 if (ret != MESA_GLINTEROP_SUCCESS) 2763 return ret; 2764 2765 if (drv->API.GLInteropQueryDeviceInfo) 2766 ret = drv->API.GLInteropQueryDeviceInfo(disp, ctx, out); 2767 else 2768 ret = MESA_GLINTEROP_UNSUPPORTED; 2769 2770 _eglUnlockDisplay(disp); 2771 return ret; 2772} 2773 2774PUBLIC int 2775MesaGLInteropEGLExportObject(EGLDisplay dpy, EGLContext context, 2776 struct mesa_glinterop_export_in *in, 2777 struct mesa_glinterop_export_out *out) 2778{ 2779 _EGLDisplay *disp; 2780 _EGLDriver *drv; 2781 _EGLContext *ctx; 2782 int ret; 2783 2784 ret = _eglLockDisplayInterop(dpy, context, &disp, &drv, &ctx); 2785 if (ret != MESA_GLINTEROP_SUCCESS) 2786 return ret; 2787 2788 if (drv->API.GLInteropExportObject) 2789 ret = drv->API.GLInteropExportObject(disp, ctx, in, out); 2790 else 2791 ret = MESA_GLINTEROP_UNSUPPORTED; 2792 2793 _eglUnlockDisplay(disp); 2794 return ret; 2795} 2796