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