1 /* 2 * Copyright 2015 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24 #include <wayland-client.h> 25 26 #include <assert.h> 27 #include <stdlib.h> 28 #include <stdio.h> 29 #include <unistd.h> 30 #include <errno.h> 31 #include <string.h> 32 #include <pthread.h> 33 #include <poll.h> 34 #include <sys/mman.h> 35 36 #include "drm-uapi/drm_fourcc.h" 37 38 #include "vk_instance.h" 39 #include "vk_physical_device.h" 40 #include "vk_util.h" 41 #include "wsi_common_entrypoints.h" 42 #include "wsi_common_private.h" 43 #include "linux-dmabuf-unstable-v1-client-protocol.h" 44 45 #include <util/compiler.h> 46 #include <util/hash_table.h> 47 #include <util/timespec.h> 48 #include <util/u_vector.h> 49 #include <util/anon_file.h> 50 51 struct wsi_wayland; 52 53 struct wsi_wl_format { 54 VkFormat vk_format; 55 uint32_t has_alpha_format; 56 uint32_t has_opaque_format; 57 struct u_vector modifiers; 58 }; 59 60 struct wsi_wl_display { 61 /* The real wl_display */ 62 struct wl_display * wl_display; 63 /* Actually a proxy wrapper around the event queue */ 64 struct wl_display * wl_display_wrapper; 65 struct wl_event_queue * queue; 66 67 struct wl_shm * wl_shm; 68 struct zwp_linux_dmabuf_v1 * wl_dmabuf; 69 70 struct wsi_wayland *wsi_wl; 71 72 /* Formats populated by zwp_linux_dmabuf_v1 or wl_shm interfaces */ 73 struct u_vector formats; 74 75 /* Only used for displays created by wsi_wl_display_create */ 76 uint32_t refcount; 77 78 bool sw; 79 }; 80 81 struct wsi_wayland { 82 struct wsi_interface base; 83 84 struct wsi_device *wsi; 85 86 const VkAllocationCallbacks *alloc; 87 VkPhysicalDevice physical_device; 88 }; 89 90 static struct wsi_wl_format * 91 find_format(struct u_vector *formats, VkFormat format) 92 { 93 struct wsi_wl_format *f; 94 95 u_vector_foreach(f, formats) 96 if (f->vk_format == format) 97 return f; 98 99 return NULL; 100 } 101 102 static struct wsi_wl_format * 103 wsi_wl_display_add_vk_format(struct wsi_wl_display *display, 104 struct u_vector *formats, 105 VkFormat format, 106 bool has_alpha_format, 107 bool has_opaque_format) 108 { 109 /* Don't add a format that's already in the list */ 110 struct wsi_wl_format *f = find_format(formats, format); 111 if (f) { 112 if (has_alpha_format) 113 f->has_alpha_format = true; 114 if (has_opaque_format) 115 f->has_opaque_format = true; 116 return f; 117 } 118 119 /* Don't add formats that aren't renderable. */ 120 VkFormatProperties props; 121 122 display->wsi_wl->wsi->GetPhysicalDeviceFormatProperties(display->wsi_wl->physical_device, 123 format, &props); 124 if (!(props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) 125 return NULL; 126 127 struct u_vector modifiers; 128 if (!u_vector_init_pow2(&modifiers, 4, sizeof(uint64_t))) 129 return NULL; 130 131 f = u_vector_add(formats); 132 if (!f) { 133 u_vector_finish(&modifiers); 134 return NULL; 135 } 136 137 f->vk_format = format; 138 f->has_alpha_format = has_alpha_format; 139 f->has_opaque_format = has_opaque_format; 140 f->modifiers = modifiers; 141 142 return f; 143 } 144 145 static void 146 wsi_wl_format_add_modifier(struct wsi_wl_format *format, uint64_t modifier) 147 { 148 uint64_t *mod; 149 150 if (modifier == DRM_FORMAT_MOD_INVALID) 151 return; 152 153 u_vector_foreach(mod, &format->modifiers) 154 if (*mod == modifier) 155 return; 156 157 mod = u_vector_add(&format->modifiers); 158 if (mod) 159 *mod = modifier; 160 } 161 162 static void 163 wsi_wl_display_add_drm_format_modifier(struct wsi_wl_display *display, 164 struct u_vector *formats, 165 uint32_t drm_format, uint64_t modifier) 166 { 167 struct wsi_wl_format *format = NULL, *srgb_format = NULL; 168 169 switch (drm_format) { 170 #if 0 171 /* TODO: These are only available when VK_EXT_4444_formats is enabled, so 172 * we probably need to make their use conditional on this extension. */ 173 case DRM_FORMAT_ARGB4444: 174 format = wsi_wl_display_add_vk_format(display, formats, 175 VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, 176 true, false); 177 break; 178 case DRM_FORMAT_XRGB4444: 179 format = wsi_wl_display_add_vk_format(display, formats, 180 VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, 181 false, true); 182 break; 183 case DRM_FORMAT_ABGR4444: 184 format = wsi_wl_display_add_vk_format(display, formats, 185 VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT, 186 true, false); 187 break; 188 case DRM_FORMAT_XBGR4444: 189 format = wsi_wl_display_add_vk_format(display, formats, 190 VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT, 191 false, true); 192 break; 193 #endif 194 195 /* Vulkan _PACKN formats have the same component order as DRM formats 196 * on little endian systems, on big endian there exists no analog. */ 197 #if MESA_LITTLE_ENDIAN 198 case DRM_FORMAT_RGBA4444: 199 format = wsi_wl_display_add_vk_format(display, formats, 200 VK_FORMAT_R4G4B4A4_UNORM_PACK16, 201 true, false); 202 break; 203 case DRM_FORMAT_RGBX4444: 204 format = wsi_wl_display_add_vk_format(display, formats, 205 VK_FORMAT_R4G4B4A4_UNORM_PACK16, 206 false, true); 207 break; 208 case DRM_FORMAT_BGRA4444: 209 format = wsi_wl_display_add_vk_format(display, formats, 210 VK_FORMAT_B4G4R4A4_UNORM_PACK16, 211 true, false); 212 break; 213 case DRM_FORMAT_BGRX4444: 214 format = wsi_wl_display_add_vk_format(display, formats, 215 VK_FORMAT_B4G4R4A4_UNORM_PACK16, 216 false, true); 217 break; 218 case DRM_FORMAT_RGB565: 219 format = wsi_wl_display_add_vk_format(display, formats, 220 VK_FORMAT_R5G6B5_UNORM_PACK16, 221 true, true); 222 break; 223 case DRM_FORMAT_BGR565: 224 format = wsi_wl_display_add_vk_format(display, formats, 225 VK_FORMAT_B5G6R5_UNORM_PACK16, 226 true, true); 227 break; 228 case DRM_FORMAT_ARGB1555: 229 format = wsi_wl_display_add_vk_format(display, formats, 230 VK_FORMAT_A1R5G5B5_UNORM_PACK16, 231 true, false); 232 break; 233 case DRM_FORMAT_XRGB1555: 234 format = wsi_wl_display_add_vk_format(display, formats, 235 VK_FORMAT_A1R5G5B5_UNORM_PACK16, 236 false, true); 237 break; 238 case DRM_FORMAT_RGBA5551: 239 format = wsi_wl_display_add_vk_format(display, formats, 240 VK_FORMAT_R5G5B5A1_UNORM_PACK16, 241 true, false); 242 break; 243 case DRM_FORMAT_RGBX5551: 244 format = wsi_wl_display_add_vk_format(display, formats, 245 VK_FORMAT_R5G5B5A1_UNORM_PACK16, 246 false, true); 247 break; 248 case DRM_FORMAT_BGRA5551: 249 format = wsi_wl_display_add_vk_format(display, formats, 250 VK_FORMAT_B5G5R5A1_UNORM_PACK16, 251 true, false); 252 break; 253 case DRM_FORMAT_BGRX5551: 254 format = wsi_wl_display_add_vk_format(display, formats, 255 VK_FORMAT_B5G5R5A1_UNORM_PACK16, 256 false, true); 257 break; 258 case DRM_FORMAT_ARGB2101010: 259 format = wsi_wl_display_add_vk_format(display, formats, 260 VK_FORMAT_A2R10G10B10_UNORM_PACK32, 261 true, false); 262 break; 263 case DRM_FORMAT_XRGB2101010: 264 format = wsi_wl_display_add_vk_format(display, formats, 265 VK_FORMAT_A2R10G10B10_UNORM_PACK32, 266 false, true); 267 break; 268 case DRM_FORMAT_ABGR2101010: 269 format = wsi_wl_display_add_vk_format(display, formats, 270 VK_FORMAT_A2B10G10R10_UNORM_PACK32, 271 true, false); 272 break; 273 case DRM_FORMAT_XBGR2101010: 274 format = wsi_wl_display_add_vk_format(display, formats, 275 VK_FORMAT_A2B10G10R10_UNORM_PACK32, 276 false, true); 277 break; 278 #endif 279 280 /* Non-packed 8-bit formats have an inverted channel order compared to the 281 * little endian DRM formats, because the DRM channel ordering is high->low 282 * but the vulkan channel ordering is in memory byte order 283 * 284 * For all UNORM formats which have a SRGB variant, we must support both if 285 * we can. SRGB in this context means that rendering to it will result in a 286 * linear -> nonlinear SRGB colorspace conversion before the data is stored. 287 * The inverse function is applied when sampling from SRGB images. 288 * From Wayland's perspective nothing changes, the difference is just how 289 * Vulkan interprets the pixel data. */ 290 case DRM_FORMAT_XBGR8888: 291 srgb_format = wsi_wl_display_add_vk_format(display, formats, 292 VK_FORMAT_R8G8B8_SRGB, 293 true, true); 294 format = wsi_wl_display_add_vk_format(display, formats, 295 VK_FORMAT_R8G8B8_UNORM, 296 true, true); 297 if (format) 298 wsi_wl_format_add_modifier(format, modifier); 299 if (srgb_format) 300 wsi_wl_format_add_modifier(srgb_format, modifier); 301 302 srgb_format = wsi_wl_display_add_vk_format(display, formats, 303 VK_FORMAT_R8G8B8A8_SRGB, 304 false, true); 305 format = wsi_wl_display_add_vk_format(display, formats, 306 VK_FORMAT_R8G8B8A8_UNORM, 307 false, true); 308 break; 309 case DRM_FORMAT_ABGR8888: 310 srgb_format = wsi_wl_display_add_vk_format(display, formats, 311 VK_FORMAT_R8G8B8A8_SRGB, 312 true, false); 313 format = wsi_wl_display_add_vk_format(display, formats, 314 VK_FORMAT_R8G8B8A8_UNORM, 315 true, false); 316 break; 317 case DRM_FORMAT_XRGB8888: 318 srgb_format = wsi_wl_display_add_vk_format(display, formats, 319 VK_FORMAT_B8G8R8_SRGB, 320 true, true); 321 format = wsi_wl_display_add_vk_format(display, formats, 322 VK_FORMAT_B8G8R8_UNORM, 323 true, true); 324 if (format) 325 wsi_wl_format_add_modifier(format, modifier); 326 if (srgb_format) 327 wsi_wl_format_add_modifier(srgb_format, modifier); 328 329 srgb_format = wsi_wl_display_add_vk_format(display, formats, 330 VK_FORMAT_B8G8R8A8_SRGB, 331 false, true); 332 format = wsi_wl_display_add_vk_format(display, formats, 333 VK_FORMAT_B8G8R8A8_UNORM, 334 false, true); 335 break; 336 case DRM_FORMAT_ARGB8888: 337 srgb_format = wsi_wl_display_add_vk_format(display, formats, 338 VK_FORMAT_B8G8R8A8_SRGB, 339 true, false); 340 format = wsi_wl_display_add_vk_format(display, formats, 341 VK_FORMAT_B8G8R8A8_UNORM, 342 true, false); 343 break; 344 } 345 346 if (format) 347 wsi_wl_format_add_modifier(format, modifier); 348 if (srgb_format) 349 wsi_wl_format_add_modifier(srgb_format, modifier); 350 } 351 352 static void 353 wsi_wl_display_add_wl_shm_format(struct wsi_wl_display *display, 354 struct u_vector *formats, 355 uint32_t wl_shm_format) 356 { 357 switch (wl_shm_format) { 358 case WL_SHM_FORMAT_XBGR8888: 359 wsi_wl_display_add_vk_format(display, formats, 360 VK_FORMAT_R8G8B8_SRGB, 361 true, true); 362 wsi_wl_display_add_vk_format(display, formats, 363 VK_FORMAT_R8G8B8_UNORM, 364 true, true); 365 wsi_wl_display_add_vk_format(display, formats, 366 VK_FORMAT_R8G8B8A8_SRGB, 367 false, true); 368 wsi_wl_display_add_vk_format(display, formats, 369 VK_FORMAT_R8G8B8A8_UNORM, 370 false, true); 371 break; 372 case WL_SHM_FORMAT_ABGR8888: 373 wsi_wl_display_add_vk_format(display, formats, 374 VK_FORMAT_R8G8B8A8_SRGB, 375 true, false); 376 wsi_wl_display_add_vk_format(display, formats, 377 VK_FORMAT_R8G8B8A8_UNORM, 378 true, false); 379 break; 380 case WL_SHM_FORMAT_XRGB8888: 381 wsi_wl_display_add_vk_format(display, formats, 382 VK_FORMAT_B8G8R8_SRGB, 383 true, true); 384 wsi_wl_display_add_vk_format(display, formats, 385 VK_FORMAT_B8G8R8_UNORM, 386 true, true); 387 wsi_wl_display_add_vk_format(display, formats, 388 VK_FORMAT_B8G8R8A8_SRGB, 389 false, true); 390 wsi_wl_display_add_vk_format(display, formats, 391 VK_FORMAT_B8G8R8A8_UNORM, 392 false, true); 393 break; 394 case WL_SHM_FORMAT_ARGB8888: 395 wsi_wl_display_add_vk_format(display, formats, 396 VK_FORMAT_B8G8R8A8_SRGB, 397 true, false); 398 wsi_wl_display_add_vk_format(display, formats, 399 VK_FORMAT_B8G8R8A8_UNORM, 400 true, false); 401 break; 402 } 403 } 404 405 static uint32_t 406 wl_drm_format_for_vk_format(VkFormat vk_format, bool alpha) 407 { 408 switch (vk_format) { 409 #if 0 410 case VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT: 411 return alpha ? DRM_FORMAT_ARGB4444 : DRM_FORMAT_XRGB4444; 412 case VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT: 413 return alpha ? DRM_FORMAT_ABGR4444 : DRM_FORMAT_XBGR4444; 414 #endif 415 #if MESA_LITTLE_ENDIAN 416 case VK_FORMAT_R4G4B4A4_UNORM_PACK16: 417 return alpha ? DRM_FORMAT_RGBA4444 : DRM_FORMAT_RGBX4444; 418 case VK_FORMAT_B4G4R4A4_UNORM_PACK16: 419 return alpha ? DRM_FORMAT_BGRA4444 : DRM_FORMAT_BGRX4444; 420 case VK_FORMAT_R5G6B5_UNORM_PACK16: 421 return DRM_FORMAT_RGB565; 422 case VK_FORMAT_B5G6R5_UNORM_PACK16: 423 return DRM_FORMAT_BGR565; 424 case VK_FORMAT_A1R5G5B5_UNORM_PACK16: 425 return alpha ? DRM_FORMAT_ARGB1555 : DRM_FORMAT_XRGB1555; 426 case VK_FORMAT_R5G5B5A1_UNORM_PACK16: 427 return alpha ? DRM_FORMAT_RGBA5551 : DRM_FORMAT_RGBX5551; 428 case VK_FORMAT_B5G5R5A1_UNORM_PACK16: 429 return alpha ? DRM_FORMAT_BGRA5551 : DRM_FORMAT_BGRX5551; 430 case VK_FORMAT_A2R10G10B10_UNORM_PACK32: 431 return alpha ? DRM_FORMAT_ARGB2101010 : DRM_FORMAT_XRGB2101010; 432 case VK_FORMAT_A2B10G10R10_UNORM_PACK32: 433 return alpha ? DRM_FORMAT_ABGR2101010 : DRM_FORMAT_XBGR2101010; 434 #endif 435 case VK_FORMAT_R8G8B8_UNORM: 436 case VK_FORMAT_R8G8B8_SRGB: 437 return DRM_FORMAT_XBGR8888; 438 case VK_FORMAT_R8G8B8A8_UNORM: 439 case VK_FORMAT_R8G8B8A8_SRGB: 440 return alpha ? DRM_FORMAT_ABGR8888 : DRM_FORMAT_XBGR8888; 441 case VK_FORMAT_B8G8R8_UNORM: 442 case VK_FORMAT_B8G8R8_SRGB: 443 return DRM_FORMAT_BGRX8888; 444 case VK_FORMAT_B8G8R8A8_UNORM: 445 case VK_FORMAT_B8G8R8A8_SRGB: 446 return alpha ? DRM_FORMAT_ARGB8888 : DRM_FORMAT_XRGB8888; 447 448 default: 449 assert(!"Unsupported Vulkan format"); 450 return 0; 451 } 452 } 453 454 static uint32_t 455 wl_shm_format_for_vk_format(VkFormat vk_format, bool alpha) 456 { 457 switch (vk_format) { 458 case VK_FORMAT_R8G8B8A8_UNORM: 459 case VK_FORMAT_R8G8B8A8_SRGB: 460 return alpha ? WL_SHM_FORMAT_ABGR8888 : WL_SHM_FORMAT_XBGR8888; 461 case VK_FORMAT_B8G8R8A8_UNORM: 462 case VK_FORMAT_B8G8R8A8_SRGB: 463 return alpha ? WL_SHM_FORMAT_ARGB8888 : WL_SHM_FORMAT_XRGB8888; 464 case VK_FORMAT_R8G8B8_UNORM: 465 case VK_FORMAT_R8G8B8_SRGB: 466 return WL_SHM_FORMAT_XBGR8888; 467 case VK_FORMAT_B8G8R8_UNORM: 468 case VK_FORMAT_B8G8R8_SRGB: 469 return WL_SHM_FORMAT_XRGB8888; 470 471 default: 472 assert(!"Unsupported Vulkan format"); 473 return 0; 474 } 475 } 476 477 static void 478 dmabuf_handle_format(void *data, struct zwp_linux_dmabuf_v1 *dmabuf, 479 uint32_t format) 480 { 481 /* Formats are implicitly advertised by the modifier event, so we ignore 482 * them here. */ 483 } 484 485 static void 486 dmabuf_handle_modifier(void *data, struct zwp_linux_dmabuf_v1 *dmabuf, 487 uint32_t format, uint32_t modifier_hi, 488 uint32_t modifier_lo) 489 { 490 struct wsi_wl_display *display = data; 491 uint64_t modifier; 492 493 modifier = ((uint64_t) modifier_hi << 32) | modifier_lo; 494 wsi_wl_display_add_drm_format_modifier(display, &display->formats, 495 format, modifier); 496 } 497 498 static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = { 499 dmabuf_handle_format, 500 dmabuf_handle_modifier, 501 }; 502 503 static void 504 shm_handle_format(void *data, struct wl_shm *shm, uint32_t format) 505 { 506 struct wsi_wl_display *display = data; 507 508 wsi_wl_display_add_wl_shm_format(display, &display->formats, format); 509 } 510 511 static const struct wl_shm_listener shm_listener = { 512 .format = shm_handle_format 513 }; 514 515 static void 516 registry_handle_global(void *data, struct wl_registry *registry, 517 uint32_t name, const char *interface, uint32_t version) 518 { 519 struct wsi_wl_display *display = data; 520 521 if (display->sw) { 522 if (strcmp(interface, "wl_shm") == 0) { 523 display->wl_shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); 524 wl_shm_add_listener(display->wl_shm, &shm_listener, display); 525 } 526 return; 527 } 528 529 if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0 && version >= 3) { 530 display->wl_dmabuf = 531 wl_registry_bind(registry, name, &zwp_linux_dmabuf_v1_interface, 3); 532 zwp_linux_dmabuf_v1_add_listener(display->wl_dmabuf, 533 &dmabuf_listener, display); 534 } 535 } 536 537 static void 538 registry_handle_global_remove(void *data, struct wl_registry *registry, 539 uint32_t name) 540 { /* No-op */ } 541 542 static const struct wl_registry_listener registry_listener = { 543 registry_handle_global, 544 registry_handle_global_remove 545 }; 546 547 static void 548 wsi_wl_display_finish(struct wsi_wl_display *display) 549 { 550 assert(display->refcount == 0); 551 552 struct wsi_wl_format *f; 553 u_vector_foreach(f, &display->formats) 554 u_vector_finish(&f->modifiers); 555 u_vector_finish(&display->formats); 556 if (display->wl_shm) 557 wl_shm_destroy(display->wl_shm); 558 if (display->wl_dmabuf) 559 zwp_linux_dmabuf_v1_destroy(display->wl_dmabuf); 560 if (display->wl_display_wrapper) 561 wl_proxy_wrapper_destroy(display->wl_display_wrapper); 562 if (display->queue) 563 wl_event_queue_destroy(display->queue); 564 } 565 566 static VkResult 567 wsi_wl_display_init(struct wsi_wayland *wsi_wl, 568 struct wsi_wl_display *display, 569 struct wl_display *wl_display, 570 bool get_format_list, bool sw) 571 { 572 VkResult result = VK_SUCCESS; 573 memset(display, 0, sizeof(*display)); 574 575 if (!u_vector_init(&display->formats, 8, sizeof(struct wsi_wl_format))) 576 return VK_ERROR_OUT_OF_HOST_MEMORY; 577 578 display->wsi_wl = wsi_wl; 579 display->wl_display = wl_display; 580 display->sw = sw; 581 582 display->queue = wl_display_create_queue(wl_display); 583 if (!display->queue) { 584 result = VK_ERROR_OUT_OF_HOST_MEMORY; 585 goto fail; 586 } 587 588 display->wl_display_wrapper = wl_proxy_create_wrapper(wl_display); 589 if (!display->wl_display_wrapper) { 590 result = VK_ERROR_OUT_OF_HOST_MEMORY; 591 goto fail; 592 } 593 594 wl_proxy_set_queue((struct wl_proxy *) display->wl_display_wrapper, 595 display->queue); 596 597 struct wl_registry *registry = 598 wl_display_get_registry(display->wl_display_wrapper); 599 if (!registry) { 600 result = VK_ERROR_OUT_OF_HOST_MEMORY; 601 goto fail; 602 } 603 604 wl_registry_add_listener(registry, ®istry_listener, display); 605 606 /* Round-trip to get wl_shm and zwp_linux_dmabuf_v1 globals */ 607 wl_display_roundtrip_queue(display->wl_display, display->queue); 608 if (!display->wl_dmabuf && !display->wl_shm) { 609 result = VK_ERROR_SURFACE_LOST_KHR; 610 goto fail_registry; 611 } 612 613 /* Caller doesn't expect us to query formats/modifiers, so return */ 614 if (!get_format_list) 615 goto out; 616 617 /* Round-trip again to get formats and modifiers */ 618 wl_display_roundtrip_queue(display->wl_display, display->queue); 619 620 if (wsi_wl->wsi->force_bgra8_unorm_first) { 621 /* Find BGRA8_UNORM in the list and swap it to the first position if we 622 * can find it. Some apps get confused if SRGB is first in the list. 623 */ 624 struct wsi_wl_format *first_fmt = u_vector_head(&display->formats); 625 struct wsi_wl_format *f, tmp_fmt; 626 f = find_format(&display->formats, VK_FORMAT_B8G8R8A8_UNORM); 627 if (f) { 628 tmp_fmt = *f; 629 *f = *first_fmt; 630 *first_fmt = tmp_fmt; 631 } 632 } 633 634 out: 635 /* We don't need this anymore */ 636 wl_registry_destroy(registry); 637 638 display->refcount = 0; 639 640 return VK_SUCCESS; 641 642 fail_registry: 643 if (registry) 644 wl_registry_destroy(registry); 645 646 fail: 647 wsi_wl_display_finish(display); 648 return result; 649 } 650 651 static VkResult 652 wsi_wl_display_create(struct wsi_wayland *wsi, struct wl_display *wl_display, 653 bool sw, 654 struct wsi_wl_display **display_out) 655 { 656 struct wsi_wl_display *display = 657 vk_alloc(wsi->alloc, sizeof(*display), 8, 658 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 659 if (!display) 660 return VK_ERROR_OUT_OF_HOST_MEMORY; 661 662 VkResult result = wsi_wl_display_init(wsi, display, wl_display, true, 663 sw); 664 if (result != VK_SUCCESS) { 665 vk_free(wsi->alloc, display); 666 return result; 667 } 668 669 display->refcount++; 670 *display_out = display; 671 672 return result; 673 } 674 675 static struct wsi_wl_display * 676 wsi_wl_display_ref(struct wsi_wl_display *display) 677 { 678 display->refcount++; 679 return display; 680 } 681 682 static void 683 wsi_wl_display_unref(struct wsi_wl_display *display) 684 { 685 if (display->refcount-- > 1) 686 return; 687 688 struct wsi_wayland *wsi = display->wsi_wl; 689 wsi_wl_display_finish(display); 690 vk_free(wsi->alloc, display); 691 } 692 693 VKAPI_ATTR VkBool32 VKAPI_CALL 694 wsi_GetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice, 695 uint32_t queueFamilyIndex, 696 struct wl_display *wl_display) 697 { 698 VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice); 699 struct wsi_device *wsi_device = pdevice->wsi_device; 700 struct wsi_wayland *wsi = 701 (struct wsi_wayland *)wsi_device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND]; 702 703 struct wsi_wl_display display; 704 VkResult ret = wsi_wl_display_init(wsi, &display, wl_display, false, 705 wsi_device->sw); 706 if (ret == VK_SUCCESS) 707 wsi_wl_display_finish(&display); 708 709 return ret == VK_SUCCESS; 710 } 711 712 static VkResult 713 wsi_wl_surface_get_support(VkIcdSurfaceBase *surface, 714 struct wsi_device *wsi_device, 715 uint32_t queueFamilyIndex, 716 VkBool32* pSupported) 717 { 718 *pSupported = true; 719 720 return VK_SUCCESS; 721 } 722 723 static const VkPresentModeKHR present_modes[] = { 724 VK_PRESENT_MODE_MAILBOX_KHR, 725 VK_PRESENT_MODE_FIFO_KHR, 726 }; 727 728 static VkResult 729 wsi_wl_surface_get_capabilities(VkIcdSurfaceBase *surface, 730 struct wsi_device *wsi_device, 731 VkSurfaceCapabilitiesKHR* caps) 732 { 733 /* For true mailbox mode, we need at least 4 images: 734 * 1) One to scan out from 735 * 2) One to have queued for scan-out 736 * 3) One to be currently held by the Wayland compositor 737 * 4) One to render to 738 */ 739 caps->minImageCount = 4; 740 /* There is no real maximum */ 741 caps->maxImageCount = 0; 742 743 caps->currentExtent = (VkExtent2D) { UINT32_MAX, UINT32_MAX }; 744 caps->minImageExtent = (VkExtent2D) { 1, 1 }; 745 caps->maxImageExtent = (VkExtent2D) { 746 wsi_device->maxImageDimension2D, 747 wsi_device->maxImageDimension2D, 748 }; 749 750 caps->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; 751 caps->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; 752 caps->maxImageArrayLayers = 1; 753 754 caps->supportedCompositeAlpha = 755 VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR | 756 VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR; 757 758 caps->supportedUsageFlags = 759 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | 760 VK_IMAGE_USAGE_SAMPLED_BIT | 761 VK_IMAGE_USAGE_TRANSFER_DST_BIT | 762 VK_IMAGE_USAGE_STORAGE_BIT | 763 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 764 765 return VK_SUCCESS; 766 } 767 768 static VkResult 769 wsi_wl_surface_get_capabilities2(VkIcdSurfaceBase *surface, 770 struct wsi_device *wsi_device, 771 const void *info_next, 772 VkSurfaceCapabilities2KHR* caps) 773 { 774 assert(caps->sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR); 775 776 VkResult result = 777 wsi_wl_surface_get_capabilities(surface, wsi_device, 778 &caps->surfaceCapabilities); 779 780 vk_foreach_struct(ext, caps->pNext) { 781 switch (ext->sType) { 782 case VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR: { 783 VkSurfaceProtectedCapabilitiesKHR *protected = (void *)ext; 784 protected->supportsProtected = VK_FALSE; 785 break; 786 } 787 788 default: 789 /* Ignored */ 790 break; 791 } 792 } 793 794 return result; 795 } 796 797 static VkResult 798 wsi_wl_surface_get_formats(VkIcdSurfaceBase *icd_surface, 799 struct wsi_device *wsi_device, 800 uint32_t* pSurfaceFormatCount, 801 VkSurfaceFormatKHR* pSurfaceFormats) 802 { 803 VkIcdSurfaceWayland *surface = (VkIcdSurfaceWayland *)icd_surface; 804 struct wsi_wayland *wsi = 805 (struct wsi_wayland *)wsi_device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND]; 806 807 struct wsi_wl_display display; 808 if (wsi_wl_display_init(wsi, &display, surface->display, true, 809 wsi_device->sw)) 810 return VK_ERROR_SURFACE_LOST_KHR; 811 812 VK_OUTARRAY_MAKE(out, pSurfaceFormats, pSurfaceFormatCount); 813 814 struct wsi_wl_format *disp_fmt; 815 u_vector_foreach(disp_fmt, &display.formats) { 816 /* Skip formats for which we can't support both alpha & opaque 817 * formats. 818 */ 819 if (!disp_fmt->has_opaque_format || 820 !disp_fmt->has_alpha_format) 821 continue; 822 823 vk_outarray_append(&out, out_fmt) { 824 out_fmt->format = disp_fmt->vk_format; 825 out_fmt->colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; 826 } 827 } 828 829 wsi_wl_display_finish(&display); 830 831 return vk_outarray_status(&out); 832 } 833 834 static VkResult 835 wsi_wl_surface_get_formats2(VkIcdSurfaceBase *icd_surface, 836 struct wsi_device *wsi_device, 837 const void *info_next, 838 uint32_t* pSurfaceFormatCount, 839 VkSurfaceFormat2KHR* pSurfaceFormats) 840 { 841 VkIcdSurfaceWayland *surface = (VkIcdSurfaceWayland *)icd_surface; 842 struct wsi_wayland *wsi = 843 (struct wsi_wayland *)wsi_device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND]; 844 845 struct wsi_wl_display display; 846 if (wsi_wl_display_init(wsi, &display, surface->display, true, 847 wsi_device->sw)) 848 return VK_ERROR_SURFACE_LOST_KHR; 849 850 VK_OUTARRAY_MAKE(out, pSurfaceFormats, pSurfaceFormatCount); 851 852 struct wsi_wl_format *disp_fmt; 853 u_vector_foreach(disp_fmt, &display.formats) { 854 /* Skip formats for which we can't support both alpha & opaque 855 * formats. 856 */ 857 if (!disp_fmt->has_opaque_format || 858 !disp_fmt->has_alpha_format) 859 continue; 860 861 vk_outarray_append(&out, out_fmt) { 862 out_fmt->surfaceFormat.format = disp_fmt->vk_format; 863 out_fmt->surfaceFormat.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; 864 } 865 } 866 867 wsi_wl_display_finish(&display); 868 869 return vk_outarray_status(&out); 870 } 871 872 static VkResult 873 wsi_wl_surface_get_present_modes(VkIcdSurfaceBase *surface, 874 uint32_t* pPresentModeCount, 875 VkPresentModeKHR* pPresentModes) 876 { 877 if (pPresentModes == NULL) { 878 *pPresentModeCount = ARRAY_SIZE(present_modes); 879 return VK_SUCCESS; 880 } 881 882 *pPresentModeCount = MIN2(*pPresentModeCount, ARRAY_SIZE(present_modes)); 883 typed_memcpy(pPresentModes, present_modes, *pPresentModeCount); 884 885 if (*pPresentModeCount < ARRAY_SIZE(present_modes)) 886 return VK_INCOMPLETE; 887 else 888 return VK_SUCCESS; 889 } 890 891 static VkResult 892 wsi_wl_surface_get_present_rectangles(VkIcdSurfaceBase *surface, 893 struct wsi_device *wsi_device, 894 uint32_t* pRectCount, 895 VkRect2D* pRects) 896 { 897 VK_OUTARRAY_MAKE(out, pRects, pRectCount); 898 899 vk_outarray_append(&out, rect) { 900 /* We don't know a size so just return the usual "I don't know." */ 901 *rect = (VkRect2D) { 902 .offset = { 0, 0 }, 903 .extent = { UINT32_MAX, UINT32_MAX }, 904 }; 905 } 906 907 return vk_outarray_status(&out); 908 } 909 910 VKAPI_ATTR VkResult VKAPI_CALL 911 wsi_CreateWaylandSurfaceKHR(VkInstance _instance, 912 const VkWaylandSurfaceCreateInfoKHR *pCreateInfo, 913 const VkAllocationCallbacks *pAllocator, 914 VkSurfaceKHR *pSurface) 915 { 916 VK_FROM_HANDLE(vk_instance, instance, _instance); 917 VkIcdSurfaceWayland *surface; 918 919 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR); 920 921 surface = vk_alloc2(&instance->alloc, pAllocator, sizeof *surface, 8, 922 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 923 if (surface == NULL) 924 return VK_ERROR_OUT_OF_HOST_MEMORY; 925 926 surface->base.platform = VK_ICD_WSI_PLATFORM_WAYLAND; 927 surface->display = pCreateInfo->display; 928 surface->surface = pCreateInfo->surface; 929 930 *pSurface = VkIcdSurfaceBase_to_handle(&surface->base); 931 932 return VK_SUCCESS; 933 } 934 935 struct wsi_wl_image { 936 struct wsi_image base; 937 struct wl_buffer * buffer; 938 bool busy; 939 void * data_ptr; 940 uint32_t data_size; 941 }; 942 943 struct wsi_wl_swapchain { 944 struct wsi_swapchain base; 945 946 struct wsi_wl_display *display; 947 948 struct wl_surface * surface; 949 950 struct wl_callback * frame; 951 952 VkExtent2D extent; 953 VkFormat vk_format; 954 uint32_t drm_format; 955 uint32_t shm_format; 956 957 uint32_t num_drm_modifiers; 958 const uint64_t * drm_modifiers; 959 960 VkPresentModeKHR present_mode; 961 bool fifo_ready; 962 963 struct wsi_wl_image images[0]; 964 }; 965 VK_DEFINE_NONDISP_HANDLE_CASTS(wsi_wl_swapchain, base.base, VkSwapchainKHR, 966 VK_OBJECT_TYPE_SWAPCHAIN_KHR) 967 968 static struct wsi_image * 969 wsi_wl_swapchain_get_wsi_image(struct wsi_swapchain *wsi_chain, 970 uint32_t image_index) 971 { 972 struct wsi_wl_swapchain *chain = (struct wsi_wl_swapchain *)wsi_chain; 973 return &chain->images[image_index].base; 974 } 975 976 static VkResult 977 wsi_wl_swapchain_acquire_next_image(struct wsi_swapchain *wsi_chain, 978 const VkAcquireNextImageInfoKHR *info, 979 uint32_t *image_index) 980 { 981 struct wsi_wl_swapchain *chain = (struct wsi_wl_swapchain *)wsi_chain; 982 struct timespec start_time, end_time; 983 struct timespec rel_timeout; 984 int wl_fd = wl_display_get_fd(chain->display->wl_display); 985 986 timespec_from_nsec(&rel_timeout, info->timeout); 987 988 clock_gettime(CLOCK_MONOTONIC, &start_time); 989 timespec_add(&end_time, &rel_timeout, &start_time); 990 991 while (1) { 992 /* Try to dispatch potential events. */ 993 int ret = wl_display_dispatch_queue_pending(chain->display->wl_display, 994 chain->display->queue); 995 if (ret < 0) 996 return VK_ERROR_OUT_OF_DATE_KHR; 997 998 /* Try to find a free image. */ 999 for (uint32_t i = 0; i < chain->base.image_count; i++) { 1000 if (!chain->images[i].busy) { 1001 /* We found a non-busy image */ 1002 *image_index = i; 1003 chain->images[i].busy = true; 1004 return VK_SUCCESS; 1005 } 1006 } 1007 1008 /* Check for timeout. */ 1009 struct timespec current_time; 1010 clock_gettime(CLOCK_MONOTONIC, ¤t_time); 1011 if (timespec_after(¤t_time, &end_time)) 1012 return VK_NOT_READY; 1013 1014 /* Try to read events from the server. */ 1015 ret = wl_display_prepare_read_queue(chain->display->wl_display, 1016 chain->display->queue); 1017 if (ret < 0) { 1018 /* Another thread might have read events for our queue already. Go 1019 * back to dispatch them. 1020 */ 1021 if (errno == EAGAIN) 1022 continue; 1023 return VK_ERROR_OUT_OF_DATE_KHR; 1024 } 1025 1026 struct pollfd pollfd = { 1027 .fd = wl_fd, 1028 .events = POLLIN 1029 }; 1030 timespec_sub(&rel_timeout, &end_time, ¤t_time); 1031 ret = ppoll(&pollfd, 1, &rel_timeout, NULL); 1032 if (ret <= 0) { 1033 int lerrno = errno; 1034 wl_display_cancel_read(chain->display->wl_display); 1035 if (ret < 0) { 1036 /* If ppoll() was interrupted, try again. */ 1037 if (lerrno == EINTR || lerrno == EAGAIN) 1038 continue; 1039 return VK_ERROR_OUT_OF_DATE_KHR; 1040 } 1041 assert(ret == 0); 1042 continue; 1043 } 1044 1045 ret = wl_display_read_events(chain->display->wl_display); 1046 if (ret < 0) 1047 return VK_ERROR_OUT_OF_DATE_KHR; 1048 } 1049 } 1050 1051 static void 1052 frame_handle_done(void *data, struct wl_callback *callback, uint32_t serial) 1053 { 1054 struct wsi_wl_swapchain *chain = data; 1055 1056 chain->frame = NULL; 1057 chain->fifo_ready = true; 1058 1059 wl_callback_destroy(callback); 1060 } 1061 1062 static const struct wl_callback_listener frame_listener = { 1063 frame_handle_done, 1064 }; 1065 1066 static VkResult 1067 wsi_wl_swapchain_queue_present(struct wsi_swapchain *wsi_chain, 1068 uint32_t image_index, 1069 const VkPresentRegionKHR *damage) 1070 { 1071 struct wsi_wl_swapchain *chain = (struct wsi_wl_swapchain *)wsi_chain; 1072 1073 if (chain->display->sw) { 1074 struct wsi_wl_image *image = &chain->images[image_index]; 1075 void *dptr = image->data_ptr; 1076 void *sptr; 1077 chain->base.wsi->MapMemory(chain->base.device, 1078 image->base.memory, 1079 0, 0, 0, &sptr); 1080 1081 for (unsigned r = 0; r < chain->extent.height; r++) { 1082 memcpy(dptr, sptr, image->base.row_pitches[0]); 1083 dptr += image->base.row_pitches[0]; 1084 sptr += image->base.row_pitches[0]; 1085 } 1086 chain->base.wsi->UnmapMemory(chain->base.device, 1087 image->base.memory); 1088 1089 } 1090 if (chain->base.present_mode == VK_PRESENT_MODE_FIFO_KHR) { 1091 while (!chain->fifo_ready) { 1092 int ret = wl_display_dispatch_queue(chain->display->wl_display, 1093 chain->display->queue); 1094 if (ret < 0) 1095 return VK_ERROR_OUT_OF_DATE_KHR; 1096 } 1097 } 1098 1099 assert(image_index < chain->base.image_count); 1100 wl_surface_attach(chain->surface, chain->images[image_index].buffer, 0, 0); 1101 1102 if (wl_surface_get_version(chain->surface) >= 4 && damage && 1103 damage->pRectangles && damage->rectangleCount > 0) { 1104 for (unsigned i = 0; i < damage->rectangleCount; i++) { 1105 const VkRectLayerKHR *rect = &damage->pRectangles[i]; 1106 assert(rect->layer == 0); 1107 wl_surface_damage_buffer(chain->surface, 1108 rect->offset.x, rect->offset.y, 1109 rect->extent.width, rect->extent.height); 1110 } 1111 } else { 1112 wl_surface_damage(chain->surface, 0, 0, INT32_MAX, INT32_MAX); 1113 } 1114 1115 if (chain->base.present_mode == VK_PRESENT_MODE_FIFO_KHR) { 1116 chain->frame = wl_surface_frame(chain->surface); 1117 wl_callback_add_listener(chain->frame, &frame_listener, chain); 1118 chain->fifo_ready = false; 1119 } 1120 1121 chain->images[image_index].busy = true; 1122 wl_surface_commit(chain->surface); 1123 wl_display_flush(chain->display->wl_display); 1124 1125 return VK_SUCCESS; 1126 } 1127 1128 static void 1129 buffer_handle_release(void *data, struct wl_buffer *buffer) 1130 { 1131 struct wsi_wl_image *image = data; 1132 1133 assert(image->buffer == buffer); 1134 1135 image->busy = false; 1136 } 1137 1138 static const struct wl_buffer_listener buffer_listener = { 1139 buffer_handle_release, 1140 }; 1141 1142 static VkResult 1143 wsi_wl_image_init(struct wsi_wl_swapchain *chain, 1144 struct wsi_wl_image *image, 1145 const VkSwapchainCreateInfoKHR *pCreateInfo, 1146 const VkAllocationCallbacks* pAllocator) 1147 { 1148 struct wsi_wl_display *display = chain->display; 1149 VkResult result; 1150 1151 memset(image, 0, sizeof(*image)); 1152 1153 result = wsi_create_native_image(&chain->base, pCreateInfo, 1154 chain->num_drm_modifiers > 0 ? 1 : 0, 1155 &chain->num_drm_modifiers, 1156 &chain->drm_modifiers, NULL, &image->base); 1157 1158 if (result != VK_SUCCESS) 1159 return result; 1160 1161 if (display->sw) { 1162 int fd, stride; 1163 1164 stride = image->base.row_pitches[0]; 1165 image->data_size = stride * chain->extent.height; 1166 1167 /* Create a shareable buffer */ 1168 fd = os_create_anonymous_file(image->data_size, NULL); 1169 if (fd < 0) 1170 goto fail_image; 1171 1172 image->data_ptr = mmap(NULL, image->data_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 1173 if (image->data_ptr == MAP_FAILED) { 1174 close(fd); 1175 goto fail_image; 1176 } 1177 /* Share it in a wl_buffer */ 1178 struct wl_shm_pool *pool = wl_shm_create_pool(display->wl_shm, fd, image->data_size); 1179 wl_proxy_set_queue((struct wl_proxy *)pool, display->queue); 1180 image->buffer = wl_shm_pool_create_buffer(pool, 0, chain->extent.width, 1181 chain->extent.height, stride, 1182 chain->shm_format); 1183 wl_shm_pool_destroy(pool); 1184 close(fd); 1185 } else { 1186 assert(display->wl_dmabuf); 1187 1188 struct zwp_linux_buffer_params_v1 *params = 1189 zwp_linux_dmabuf_v1_create_params(display->wl_dmabuf); 1190 if (!params) 1191 goto fail_image; 1192 1193 for (int i = 0; i < image->base.num_planes; i++) { 1194 zwp_linux_buffer_params_v1_add(params, 1195 image->base.fds[i], 1196 i, 1197 image->base.offsets[i], 1198 image->base.row_pitches[i], 1199 image->base.drm_modifier >> 32, 1200 image->base.drm_modifier & 0xffffffff); 1201 close(image->base.fds[i]); 1202 } 1203 1204 image->buffer = 1205 zwp_linux_buffer_params_v1_create_immed(params, 1206 chain->extent.width, 1207 chain->extent.height, 1208 chain->drm_format, 1209 0); 1210 zwp_linux_buffer_params_v1_destroy(params); 1211 } 1212 1213 if (!image->buffer) 1214 goto fail_image; 1215 1216 wl_buffer_add_listener(image->buffer, &buffer_listener, image); 1217 1218 return VK_SUCCESS; 1219 1220 fail_image: 1221 wsi_destroy_image(&chain->base, &image->base); 1222 1223 return VK_ERROR_OUT_OF_HOST_MEMORY; 1224 } 1225 1226 static VkResult 1227 wsi_wl_swapchain_destroy(struct wsi_swapchain *wsi_chain, 1228 const VkAllocationCallbacks *pAllocator) 1229 { 1230 struct wsi_wl_swapchain *chain = (struct wsi_wl_swapchain *)wsi_chain; 1231 1232 for (uint32_t i = 0; i < chain->base.image_count; i++) { 1233 if (chain->images[i].buffer) { 1234 wl_buffer_destroy(chain->images[i].buffer); 1235 wsi_destroy_image(&chain->base, &chain->images[i].base); 1236 if (chain->images[i].data_ptr) 1237 munmap(chain->images[i].data_ptr, chain->images[i].data_size); 1238 } 1239 } 1240 1241 if (chain->frame) 1242 wl_callback_destroy(chain->frame); 1243 if (chain->surface) 1244 wl_proxy_wrapper_destroy(chain->surface); 1245 1246 if (chain->display) 1247 wsi_wl_display_unref(chain->display); 1248 1249 wsi_swapchain_finish(&chain->base); 1250 1251 vk_free(pAllocator, chain); 1252 1253 return VK_SUCCESS; 1254 } 1255 1256 static VkResult 1257 wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface, 1258 VkDevice device, 1259 struct wsi_device *wsi_device, 1260 const VkSwapchainCreateInfoKHR* pCreateInfo, 1261 const VkAllocationCallbacks* pAllocator, 1262 struct wsi_swapchain **swapchain_out) 1263 { 1264 VkIcdSurfaceWayland *surface = (VkIcdSurfaceWayland *)icd_surface; 1265 struct wsi_wayland *wsi = 1266 (struct wsi_wayland *)wsi_device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND]; 1267 struct wsi_wl_swapchain *chain; 1268 VkResult result; 1269 1270 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR); 1271 1272 int num_images = pCreateInfo->minImageCount; 1273 1274 size_t size = sizeof(*chain) + num_images * sizeof(chain->images[0]); 1275 chain = vk_zalloc(pAllocator, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 1276 if (chain == NULL) 1277 return VK_ERROR_OUT_OF_HOST_MEMORY; 1278 1279 result = wsi_swapchain_init(wsi_device, &chain->base, device, 1280 pCreateInfo, pAllocator); 1281 if (result != VK_SUCCESS) { 1282 vk_free(pAllocator, chain); 1283 return result; 1284 } 1285 1286 bool alpha = pCreateInfo->compositeAlpha == 1287 VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR; 1288 1289 chain->base.destroy = wsi_wl_swapchain_destroy; 1290 chain->base.get_wsi_image = wsi_wl_swapchain_get_wsi_image; 1291 chain->base.acquire_next_image = wsi_wl_swapchain_acquire_next_image; 1292 chain->base.queue_present = wsi_wl_swapchain_queue_present; 1293 chain->base.present_mode = wsi_swapchain_get_present_mode(wsi_device, pCreateInfo); 1294 chain->base.image_count = num_images; 1295 chain->extent = pCreateInfo->imageExtent; 1296 chain->vk_format = pCreateInfo->imageFormat; 1297 if (wsi_device->sw) 1298 chain->shm_format = wl_shm_format_for_vk_format(chain->vk_format, alpha); 1299 else 1300 chain->drm_format = wl_drm_format_for_vk_format(chain->vk_format, alpha); 1301 1302 if (pCreateInfo->oldSwapchain) { 1303 /* If we have an oldSwapchain parameter, copy the display struct over 1304 * from the old one so we don't have to fully re-initialize it. 1305 */ 1306 VK_FROM_HANDLE(wsi_wl_swapchain, old_chain, pCreateInfo->oldSwapchain); 1307 chain->display = wsi_wl_display_ref(old_chain->display); 1308 } else { 1309 chain->display = NULL; 1310 result = wsi_wl_display_create(wsi, surface->display, 1311 wsi_device->sw, &chain->display); 1312 if (result != VK_SUCCESS) 1313 goto fail; 1314 } 1315 1316 chain->surface = wl_proxy_create_wrapper(surface->surface); 1317 if (!chain->surface) { 1318 result = VK_ERROR_OUT_OF_HOST_MEMORY; 1319 goto fail; 1320 } 1321 wl_proxy_set_queue((struct wl_proxy *) chain->surface, 1322 chain->display->queue); 1323 1324 chain->num_drm_modifiers = 0; 1325 chain->drm_modifiers = 0; 1326 1327 /* Use explicit DRM format modifiers when both the server and the driver 1328 * support them. 1329 */ 1330 if (chain->display->wl_dmabuf && chain->base.wsi->supports_modifiers) { 1331 struct wsi_wl_format *f = find_format(&chain->display->formats, chain->vk_format); 1332 if (f) { 1333 chain->drm_modifiers = u_vector_tail(&f->modifiers); 1334 chain->num_drm_modifiers = u_vector_length(&f->modifiers); 1335 } 1336 } 1337 1338 chain->fifo_ready = true; 1339 1340 for (uint32_t i = 0; i < chain->base.image_count; i++) { 1341 result = wsi_wl_image_init(chain, &chain->images[i], 1342 pCreateInfo, pAllocator); 1343 if (result != VK_SUCCESS) 1344 goto fail; 1345 chain->images[i].busy = false; 1346 } 1347 1348 *swapchain_out = &chain->base; 1349 1350 return VK_SUCCESS; 1351 1352 fail: 1353 wsi_wl_swapchain_destroy(&chain->base, pAllocator); 1354 1355 return result; 1356 } 1357 1358 VkResult 1359 wsi_wl_init_wsi(struct wsi_device *wsi_device, 1360 const VkAllocationCallbacks *alloc, 1361 VkPhysicalDevice physical_device) 1362 { 1363 struct wsi_wayland *wsi; 1364 VkResult result; 1365 1366 wsi = vk_alloc(alloc, sizeof(*wsi), 8, 1367 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1368 if (!wsi) { 1369 result = VK_ERROR_OUT_OF_HOST_MEMORY; 1370 goto fail; 1371 } 1372 1373 wsi->physical_device = physical_device; 1374 wsi->alloc = alloc; 1375 wsi->wsi = wsi_device; 1376 1377 wsi->base.get_support = wsi_wl_surface_get_support; 1378 wsi->base.get_capabilities2 = wsi_wl_surface_get_capabilities2; 1379 wsi->base.get_formats = wsi_wl_surface_get_formats; 1380 wsi->base.get_formats2 = wsi_wl_surface_get_formats2; 1381 wsi->base.get_present_modes = wsi_wl_surface_get_present_modes; 1382 wsi->base.get_present_rectangles = wsi_wl_surface_get_present_rectangles; 1383 wsi->base.create_swapchain = wsi_wl_surface_create_swapchain; 1384 1385 wsi_device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND] = &wsi->base; 1386 1387 return VK_SUCCESS; 1388 1389 fail: 1390 wsi_device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND] = NULL; 1391 1392 return result; 1393 } 1394 1395 void 1396 wsi_wl_finish_wsi(struct wsi_device *wsi_device, 1397 const VkAllocationCallbacks *alloc) 1398 { 1399 struct wsi_wayland *wsi = 1400 (struct wsi_wayland *)wsi_device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND]; 1401 if (!wsi) 1402 return; 1403 1404 vk_free(alloc, wsi); 1405 } 1406