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