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 <assert.h> 25 #include <stdlib.h> 26 #include <stdio.h> 27 #include <string.h> 28 29 #include "vk_instance.h" 30 #include "vk_physical_device.h" 31 #include "vk_util.h" 32 #include "wsi_common_entrypoints.h" 33 #include "wsi_common_private.h" 34 #include "wsi_common_win32.h" 35 36 #if defined(__GNUC__) 37 #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size 38 #endif 39 40 struct wsi_win32; 41 42 struct wsi_win32 { 43 struct wsi_interface base; 44 45 struct wsi_device *wsi; 46 47 const VkAllocationCallbacks *alloc; 48 VkPhysicalDevice physical_device; 49 }; 50 51 struct wsi_win32_image { 52 struct wsi_image base; 53 struct wsi_win32_swapchain *chain; 54 HDC dc; 55 HBITMAP bmp; 56 int bmp_row_pitch; 57 void *ppvBits; 58 }; 59 60 61 struct wsi_win32_swapchain { 62 struct wsi_swapchain base; 63 struct wsi_win32 *wsi; 64 VkIcdSurfaceWin32 *surface; 65 uint64_t flip_sequence; 66 VkResult status; 67 VkExtent2D extent; 68 HWND wnd; 69 HDC chain_dc; 70 struct wsi_win32_image images[0]; 71 }; 72 73 VkBool32 74 wsi_win32_get_presentation_support(struct wsi_device *wsi_device) 75 { 76 return TRUE; 77 } 78 79 VKAPI_ATTR VkBool32 VKAPI_CALL 80 wsi_GetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice, 81 uint32_t queueFamilyIndex) 82 { 83 VK_FROM_HANDLE(vk_physical_device, device, physicalDevice); 84 85 return wsi_win32_get_presentation_support(device->wsi_device); 86 } 87 88 VkResult 89 wsi_create_win32_surface(VkInstance instance, 90 const VkAllocationCallbacks *allocator, 91 const VkWin32SurfaceCreateInfoKHR *create_info, 92 VkSurfaceKHR *surface_khr) 93 { 94 VkIcdSurfaceWin32 *surface = vk_zalloc(allocator, sizeof *surface, 8, 95 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 96 97 if (surface == NULL) 98 return VK_ERROR_OUT_OF_HOST_MEMORY; 99 100 surface->base.platform = VK_ICD_WSI_PLATFORM_WIN32; 101 102 surface->hinstance = create_info->hinstance; 103 surface->hwnd = create_info->hwnd; 104 105 *surface_khr = VkIcdSurfaceBase_to_handle(&surface->base); 106 return VK_SUCCESS; 107 } 108 109 VKAPI_ATTR VkResult VKAPI_CALL 110 wsi_CreateWin32SurfaceKHR(VkInstance _instance, 111 const VkWin32SurfaceCreateInfoKHR *pCreateInfo, 112 const VkAllocationCallbacks *pAllocator, 113 VkSurfaceKHR *pSurface) 114 { 115 VK_FROM_HANDLE(vk_instance, instance, _instance); 116 const VkAllocationCallbacks *alloc; 117 118 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR); 119 120 if (pAllocator) 121 alloc = pAllocator; 122 else 123 alloc = &instance->alloc; 124 125 return wsi_create_win32_surface(_instance, alloc, pCreateInfo, pSurface); 126 } 127 128 static VkResult 129 wsi_win32_surface_get_support(VkIcdSurfaceBase *surface, 130 struct wsi_device *wsi_device, 131 uint32_t queueFamilyIndex, 132 VkBool32* pSupported) 133 { 134 *pSupported = true; 135 136 return VK_SUCCESS; 137 } 138 139 static VkResult 140 wsi_win32_surface_get_capabilities(VkIcdSurfaceBase *surface, 141 struct wsi_device *wsi_device, 142 VkSurfaceCapabilitiesKHR* caps) 143 { 144 caps->minImageCount = 1; 145 /* There is no real maximum */ 146 caps->maxImageCount = 0; 147 148 caps->currentExtent = (VkExtent2D) { UINT32_MAX, UINT32_MAX }; 149 caps->minImageExtent = (VkExtent2D) { 1, 1 }; 150 caps->maxImageExtent = (VkExtent2D) { 151 wsi_device->maxImageDimension2D, 152 wsi_device->maxImageDimension2D, 153 }; 154 155 caps->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; 156 caps->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; 157 caps->maxImageArrayLayers = 1; 158 159 caps->supportedCompositeAlpha = 160 VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR | 161 VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR; 162 163 caps->supportedUsageFlags = 164 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | 165 VK_IMAGE_USAGE_SAMPLED_BIT | 166 VK_IMAGE_USAGE_TRANSFER_DST_BIT | 167 VK_IMAGE_USAGE_STORAGE_BIT | 168 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 169 170 return VK_SUCCESS; 171 } 172 173 static VkResult 174 wsi_win32_surface_get_capabilities2(VkIcdSurfaceBase *surface, 175 struct wsi_device *wsi_device, 176 const void *info_next, 177 VkSurfaceCapabilities2KHR* caps) 178 { 179 assert(caps->sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR); 180 181 VkResult result = 182 wsi_win32_surface_get_capabilities(surface, wsi_device, 183 &caps->surfaceCapabilities); 184 185 vk_foreach_struct(ext, caps->pNext) { 186 switch (ext->sType) { 187 case VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR: { 188 VkSurfaceProtectedCapabilitiesKHR *protected = (void *)ext; 189 protected->supportsProtected = VK_FALSE; 190 break; 191 } 192 193 default: 194 /* Ignored */ 195 break; 196 } 197 } 198 199 return result; 200 } 201 202 203 static const struct { 204 VkFormat format; 205 } available_surface_formats[] = { 206 { .format = VK_FORMAT_B8G8R8A8_SRGB }, 207 { .format = VK_FORMAT_B8G8R8A8_UNORM }, 208 }; 209 210 211 static void 212 get_sorted_vk_formats(struct wsi_device *wsi_device, VkFormat *sorted_formats) 213 { 214 for (unsigned i = 0; i < ARRAY_SIZE(available_surface_formats); i++) 215 sorted_formats[i] = available_surface_formats[i].format; 216 217 if (wsi_device->force_bgra8_unorm_first) { 218 for (unsigned i = 0; i < ARRAY_SIZE(available_surface_formats); i++) { 219 if (sorted_formats[i] == VK_FORMAT_B8G8R8A8_UNORM) { 220 sorted_formats[i] = sorted_formats[0]; 221 sorted_formats[0] = VK_FORMAT_B8G8R8A8_UNORM; 222 break; 223 } 224 } 225 } 226 } 227 228 static VkResult 229 wsi_win32_surface_get_formats(VkIcdSurfaceBase *icd_surface, 230 struct wsi_device *wsi_device, 231 uint32_t* pSurfaceFormatCount, 232 VkSurfaceFormatKHR* pSurfaceFormats) 233 { 234 VK_OUTARRAY_MAKE_TYPED(VkSurfaceFormatKHR, out, pSurfaceFormats, pSurfaceFormatCount); 235 236 VkFormat sorted_formats[ARRAY_SIZE(available_surface_formats)]; 237 get_sorted_vk_formats(wsi_device, sorted_formats); 238 239 for (unsigned i = 0; i < ARRAY_SIZE(sorted_formats); i++) { 240 vk_outarray_append_typed(VkSurfaceFormatKHR, &out, f) { 241 f->format = sorted_formats[i]; 242 f->colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; 243 } 244 } 245 246 return vk_outarray_status(&out); 247 } 248 249 static VkResult 250 wsi_win32_surface_get_formats2(VkIcdSurfaceBase *icd_surface, 251 struct wsi_device *wsi_device, 252 const void *info_next, 253 uint32_t* pSurfaceFormatCount, 254 VkSurfaceFormat2KHR* pSurfaceFormats) 255 { 256 VK_OUTARRAY_MAKE_TYPED(VkSurfaceFormat2KHR, out, pSurfaceFormats, pSurfaceFormatCount); 257 258 VkFormat sorted_formats[ARRAY_SIZE(available_surface_formats)]; 259 get_sorted_vk_formats(wsi_device, sorted_formats); 260 261 for (unsigned i = 0; i < ARRAY_SIZE(sorted_formats); i++) { 262 vk_outarray_append_typed(VkSurfaceFormat2KHR, &out, f) { 263 assert(f->sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR); 264 f->surfaceFormat.format = sorted_formats[i]; 265 f->surfaceFormat.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; 266 } 267 } 268 269 return vk_outarray_status(&out); 270 } 271 272 static const VkPresentModeKHR present_modes[] = { 273 //VK_PRESENT_MODE_MAILBOX_KHR, 274 VK_PRESENT_MODE_FIFO_KHR, 275 }; 276 277 static VkResult 278 wsi_win32_surface_get_present_modes(VkIcdSurfaceBase *surface, 279 uint32_t* pPresentModeCount, 280 VkPresentModeKHR* pPresentModes) 281 { 282 if (pPresentModes == NULL) { 283 *pPresentModeCount = ARRAY_SIZE(present_modes); 284 return VK_SUCCESS; 285 } 286 287 *pPresentModeCount = MIN2(*pPresentModeCount, ARRAY_SIZE(present_modes)); 288 typed_memcpy(pPresentModes, present_modes, *pPresentModeCount); 289 290 if (*pPresentModeCount < ARRAY_SIZE(present_modes)) 291 return VK_INCOMPLETE; 292 else 293 return VK_SUCCESS; 294 } 295 296 static VkResult 297 wsi_win32_surface_get_present_rectangles(VkIcdSurfaceBase *surface, 298 struct wsi_device *wsi_device, 299 uint32_t* pRectCount, 300 VkRect2D* pRects) 301 { 302 VK_OUTARRAY_MAKE_TYPED(VkRect2D, out, pRects, pRectCount); 303 304 vk_outarray_append_typed(VkRect2D, &out, rect) { 305 /* We don't know a size so just return the usual "I don't know." */ 306 *rect = (VkRect2D) { 307 .offset = { 0, 0 }, 308 .extent = { UINT32_MAX, UINT32_MAX }, 309 }; 310 } 311 312 return vk_outarray_status(&out); 313 } 314 315 static uint32_t 316 select_memory_type(const struct wsi_device *wsi, 317 VkMemoryPropertyFlags props, 318 uint32_t type_bits) 319 { 320 for (uint32_t i = 0; i < wsi->memory_props.memoryTypeCount; i++) { 321 const VkMemoryType type = wsi->memory_props.memoryTypes[i]; 322 if ((type_bits & (1 << i)) && (type.propertyFlags & props) == props) 323 return i; 324 } 325 326 unreachable("No memory type found"); 327 } 328 329 VkResult 330 wsi_create_native_image(const struct wsi_swapchain *chain, 331 const VkSwapchainCreateInfoKHR *pCreateInfo, 332 uint32_t num_modifier_lists, 333 const uint32_t *num_modifiers, 334 const uint64_t *const *modifiers, 335 uint8_t *(alloc_shm)(struct wsi_image *image, unsigned size), 336 struct wsi_image *image) 337 { 338 const struct wsi_device *wsi = chain->wsi; 339 VkResult result; 340 341 memset(image, 0, sizeof(*image)); 342 for (int i = 0; i < ARRAY_SIZE(image->fds); i++) 343 image->fds[i] = -1; 344 345 const struct wsi_image_create_info image_wsi_info = { 346 .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA, 347 }; 348 VkImageCreateInfo image_info = { 349 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 350 .pNext = &image_wsi_info, 351 .flags = 0, 352 .imageType = VK_IMAGE_TYPE_2D, 353 .format = pCreateInfo->imageFormat, 354 .extent = { 355 .width = pCreateInfo->imageExtent.width, 356 .height = pCreateInfo->imageExtent.height, 357 .depth = 1, 358 }, 359 .mipLevels = 1, 360 .arrayLayers = 1, 361 .samples = VK_SAMPLE_COUNT_1_BIT, 362 .tiling = VK_IMAGE_TILING_OPTIMAL, 363 .usage = pCreateInfo->imageUsage, 364 .sharingMode = pCreateInfo->imageSharingMode, 365 .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount, 366 .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices, 367 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, 368 }; 369 370 VkImageFormatListCreateInfoKHR image_format_list; 371 if (pCreateInfo->flags & VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR) { 372 image_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | 373 VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR; 374 375 const VkImageFormatListCreateInfoKHR *format_list = 376 vk_find_struct_const(pCreateInfo->pNext, 377 IMAGE_FORMAT_LIST_CREATE_INFO_KHR); 378 379 #ifndef NDEBUG 380 assume(format_list && format_list->viewFormatCount > 0); 381 bool format_found = false; 382 for (int i = 0; i < format_list->viewFormatCount; i++) 383 if (pCreateInfo->imageFormat == format_list->pViewFormats[i]) 384 format_found = true; 385 assert(format_found); 386 #endif 387 388 image_format_list = *format_list; 389 image_format_list.pNext = NULL; 390 __vk_append_struct(&image_info, &image_format_list); 391 } 392 393 394 result = wsi->CreateImage(chain->device, &image_info, 395 &chain->alloc, &image->image); 396 if (result != VK_SUCCESS) 397 goto fail; 398 399 VkMemoryRequirements reqs; 400 wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs); 401 402 const struct wsi_memory_allocate_info memory_wsi_info = { 403 .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA, 404 .pNext = NULL, 405 .implicit_sync = true, 406 }; 407 const VkExportMemoryAllocateInfo memory_export_info = { 408 .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO, 409 .pNext = &memory_wsi_info, 410 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, 411 }; 412 const VkMemoryDedicatedAllocateInfo memory_dedicated_info = { 413 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, 414 .pNext = &memory_export_info, 415 .image = image->image, 416 .buffer = VK_NULL_HANDLE, 417 }; 418 const VkMemoryAllocateInfo memory_info = { 419 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 420 .pNext = &memory_dedicated_info, 421 .allocationSize = reqs.size, 422 .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, 423 reqs.memoryTypeBits), 424 }; 425 result = wsi->AllocateMemory(chain->device, &memory_info, 426 &chain->alloc, &image->memory); 427 if (result != VK_SUCCESS) 428 goto fail; 429 430 result = wsi->BindImageMemory(chain->device, image->image, 431 image->memory, 0); 432 if (result != VK_SUCCESS) 433 goto fail; 434 435 const VkImageSubresource image_subresource = { 436 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 437 .mipLevel = 0, 438 .arrayLayer = 0, 439 }; 440 VkSubresourceLayout image_layout; 441 wsi->GetImageSubresourceLayout(chain->device, image->image, 442 &image_subresource, &image_layout); 443 444 image->num_planes = 1; 445 image->sizes[0] = reqs.size; 446 image->row_pitches[0] = image_layout.rowPitch; 447 image->offsets[0] = 0; 448 449 return VK_SUCCESS; 450 451 fail: 452 wsi_destroy_image(chain, image); 453 454 return result; 455 } 456 457 static VkResult 458 wsi_win32_image_init(VkDevice device_h, 459 struct wsi_swapchain *drv_chain, 460 const VkSwapchainCreateInfoKHR *create_info, 461 const VkAllocationCallbacks *allocator, 462 struct wsi_win32_image *image) 463 { 464 struct wsi_win32_swapchain *chain = (struct wsi_win32_swapchain *) drv_chain; 465 466 VkResult result = wsi_create_native_image(&chain->base, create_info, 467 0, NULL, NULL, NULL, 468 &image->base); 469 if (result != VK_SUCCESS) 470 return result; 471 472 VkIcdSurfaceWin32 *win32_surface = (VkIcdSurfaceWin32 *)create_info->surface; 473 chain->wnd = win32_surface->hwnd; 474 chain->chain_dc = GetDC(chain->wnd); 475 476 image->dc = CreateCompatibleDC(chain->chain_dc); 477 HBITMAP bmp = NULL; 478 479 BITMAPINFO info = { 0 }; 480 info.bmiHeader.biSize = sizeof(BITMAPINFO); 481 info.bmiHeader.biWidth = create_info->imageExtent.width; 482 info.bmiHeader.biHeight = -create_info->imageExtent.height; 483 info.bmiHeader.biPlanes = 1; 484 info.bmiHeader.biBitCount = 32; 485 info.bmiHeader.biCompression = BI_RGB; 486 487 bmp = CreateDIBSection(image->dc, &info, DIB_RGB_COLORS, &image->ppvBits, NULL, 0); 488 assert(bmp && image->ppvBits); 489 490 SelectObject(image->dc, bmp); 491 492 BITMAP header; 493 int status = GetObject(bmp, sizeof(BITMAP), &header); 494 (void)status; 495 image->bmp_row_pitch = header.bmWidthBytes; 496 image->bmp = bmp; 497 image->chain = chain; 498 499 return VK_SUCCESS; 500 } 501 502 static void 503 wsi_win32_image_finish(struct wsi_swapchain *drv_chain, 504 const VkAllocationCallbacks *allocator, 505 struct wsi_win32_image *image) 506 { 507 struct wsi_win32_swapchain *chain = 508 (struct wsi_win32_swapchain *) drv_chain; 509 510 DeleteDC(image->dc); 511 if(image->bmp) 512 DeleteObject(image->bmp); 513 wsi_destroy_image(&chain->base, &image->base); 514 } 515 516 static VkResult 517 wsi_win32_swapchain_destroy(struct wsi_swapchain *drv_chain, 518 const VkAllocationCallbacks *allocator) 519 { 520 struct wsi_win32_swapchain *chain = 521 (struct wsi_win32_swapchain *) drv_chain; 522 523 for (uint32_t i = 0; i < chain->base.image_count; i++) 524 wsi_win32_image_finish(drv_chain, allocator, &chain->images[i]); 525 526 DeleteDC(chain->chain_dc); 527 528 wsi_swapchain_finish(&chain->base); 529 vk_free(allocator, chain); 530 return VK_SUCCESS; 531 } 532 533 static struct wsi_image * 534 wsi_win32_get_wsi_image(struct wsi_swapchain *drv_chain, 535 uint32_t image_index) 536 { 537 struct wsi_win32_swapchain *chain = 538 (struct wsi_win32_swapchain *) drv_chain; 539 540 return &chain->images[image_index].base; 541 } 542 543 static VkResult 544 wsi_win32_acquire_next_image(struct wsi_swapchain *drv_chain, 545 const VkAcquireNextImageInfoKHR *info, 546 uint32_t *image_index) 547 { 548 struct wsi_win32_swapchain *chain = 549 (struct wsi_win32_swapchain *)drv_chain; 550 551 /* Bail early if the swapchain is broken */ 552 if (chain->status != VK_SUCCESS) 553 return chain->status; 554 555 *image_index = 0; 556 return VK_SUCCESS; 557 } 558 559 static VkResult 560 wsi_win32_queue_present(struct wsi_swapchain *drv_chain, 561 uint32_t image_index, 562 const VkPresentRegionKHR *damage) 563 { 564 struct wsi_win32_swapchain *chain = (struct wsi_win32_swapchain *) drv_chain; 565 assert(image_index < chain->base.image_count); 566 struct wsi_win32_image *image = &chain->images[image_index]; 567 VkResult result; 568 569 char *ptr; 570 char *dptr = image->ppvBits; 571 result = chain->base.wsi->MapMemory(chain->base.device, 572 image->base.memory, 573 0, image->base.sizes[0], 0, (void**)&ptr); 574 575 for (unsigned h = 0; h < chain->extent.height; h++) { 576 memcpy(dptr, ptr, chain->extent.width * 4); 577 dptr += image->bmp_row_pitch; 578 ptr += image->base.row_pitches[0]; 579 } 580 if(StretchBlt(chain->chain_dc, 0, 0, chain->extent.width, chain->extent.height, image->dc, 0, 0, chain->extent.width, chain->extent.height, SRCCOPY)) 581 result = VK_SUCCESS; 582 else 583 result = VK_ERROR_MEMORY_MAP_FAILED; 584 585 chain->base.wsi->UnmapMemory(chain->base.device, image->base.memory); 586 if (result != VK_SUCCESS) 587 chain->status = result; 588 589 if (result != VK_SUCCESS) 590 return result; 591 592 return chain->status; 593 } 594 595 static VkResult 596 wsi_win32_surface_create_swapchain( 597 VkIcdSurfaceBase *icd_surface, 598 VkDevice device, 599 struct wsi_device *wsi_device, 600 const VkSwapchainCreateInfoKHR *create_info, 601 const VkAllocationCallbacks *allocator, 602 struct wsi_swapchain **swapchain_out) 603 { 604 VkIcdSurfaceWin32 *surface = (VkIcdSurfaceWin32 *)icd_surface; 605 struct wsi_win32 *wsi = 606 (struct wsi_win32 *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_WIN32]; 607 608 assert(create_info->sType == VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR); 609 610 const unsigned num_images = create_info->minImageCount; 611 struct wsi_win32_swapchain *chain; 612 size_t size = sizeof(*chain) + num_images * sizeof(chain->images[0]); 613 614 chain = vk_zalloc(allocator, size, 615 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 616 617 if (chain == NULL) 618 return VK_ERROR_OUT_OF_HOST_MEMORY; 619 620 VkResult result = wsi_swapchain_init(wsi_device, &chain->base, device, 621 create_info, allocator); 622 if (result != VK_SUCCESS) { 623 vk_free(allocator, chain); 624 return result; 625 } 626 627 chain->base.destroy = wsi_win32_swapchain_destroy; 628 chain->base.get_wsi_image = wsi_win32_get_wsi_image; 629 chain->base.acquire_next_image = wsi_win32_acquire_next_image; 630 chain->base.queue_present = wsi_win32_queue_present; 631 chain->base.present_mode = wsi_swapchain_get_present_mode(wsi_device, create_info); 632 chain->base.image_count = num_images; 633 chain->extent = create_info->imageExtent; 634 635 chain->wsi = wsi; 636 chain->status = VK_SUCCESS; 637 638 chain->surface = surface; 639 640 for (uint32_t image = 0; image < chain->base.image_count; image++) { 641 result = wsi_win32_image_init(device, &chain->base, 642 create_info, allocator, 643 &chain->images[image]); 644 if (result != VK_SUCCESS) { 645 while (image > 0) { 646 --image; 647 wsi_win32_image_finish(&chain->base, allocator, 648 &chain->images[image]); 649 } 650 vk_free(allocator, chain); 651 goto fail_init_images; 652 } 653 } 654 655 *swapchain_out = &chain->base; 656 657 return VK_SUCCESS; 658 659 fail_init_images: 660 return result; 661 } 662 663 664 VkResult 665 wsi_win32_init_wsi(struct wsi_device *wsi_device, 666 const VkAllocationCallbacks *alloc, 667 VkPhysicalDevice physical_device) 668 { 669 struct wsi_win32 *wsi; 670 VkResult result; 671 672 wsi = vk_alloc(alloc, sizeof(*wsi), 8, 673 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 674 if (!wsi) { 675 result = VK_ERROR_OUT_OF_HOST_MEMORY; 676 goto fail; 677 } 678 679 wsi->physical_device = physical_device; 680 wsi->alloc = alloc; 681 wsi->wsi = wsi_device; 682 683 wsi->base.get_support = wsi_win32_surface_get_support; 684 wsi->base.get_capabilities2 = wsi_win32_surface_get_capabilities2; 685 wsi->base.get_formats = wsi_win32_surface_get_formats; 686 wsi->base.get_formats2 = wsi_win32_surface_get_formats2; 687 wsi->base.get_present_modes = wsi_win32_surface_get_present_modes; 688 wsi->base.get_present_rectangles = wsi_win32_surface_get_present_rectangles; 689 wsi->base.create_swapchain = wsi_win32_surface_create_swapchain; 690 691 wsi_device->wsi[VK_ICD_WSI_PLATFORM_WIN32] = &wsi->base; 692 693 return VK_SUCCESS; 694 695 fail: 696 wsi_device->wsi[VK_ICD_WSI_PLATFORM_WIN32] = NULL; 697 698 return result; 699 } 700 701 void 702 wsi_win32_finish_wsi(struct wsi_device *wsi_device, 703 const VkAllocationCallbacks *alloc) 704 { 705 struct wsi_win32 *wsi = 706 (struct wsi_win32 *)wsi_device->wsi[VK_ICD_WSI_PLATFORM_WIN32]; 707 if (!wsi) 708 return; 709 710 vk_free(alloc, wsi); 711 } 712