17ec681f3Smrg/* 27ec681f3Smrg * Copyright © 2015 Intel Corporation 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 207ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 217ec681f3Smrg * IN THE SOFTWARE. 227ec681f3Smrg */ 237ec681f3Smrg 247ec681f3Smrg#include <assert.h> 257ec681f3Smrg#include <stdlib.h> 267ec681f3Smrg#include <stdio.h> 277ec681f3Smrg#include <string.h> 287ec681f3Smrg 297ec681f3Smrg#include "vk_instance.h" 307ec681f3Smrg#include "vk_physical_device.h" 317ec681f3Smrg#include "vk_util.h" 327ec681f3Smrg#include "wsi_common_entrypoints.h" 337ec681f3Smrg#include "wsi_common_private.h" 347ec681f3Smrg#include "wsi_common_win32.h" 357ec681f3Smrg 367ec681f3Smrg#if defined(__GNUC__) 377ec681f3Smrg#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size 387ec681f3Smrg#endif 397ec681f3Smrg 407ec681f3Smrgstruct wsi_win32; 417ec681f3Smrg 427ec681f3Smrgstruct wsi_win32 { 437ec681f3Smrg struct wsi_interface base; 447ec681f3Smrg 457ec681f3Smrg struct wsi_device *wsi; 467ec681f3Smrg 477ec681f3Smrg const VkAllocationCallbacks *alloc; 487ec681f3Smrg VkPhysicalDevice physical_device; 497ec681f3Smrg}; 507ec681f3Smrg 517ec681f3Smrgstruct wsi_win32_image { 527ec681f3Smrg struct wsi_image base; 537ec681f3Smrg struct wsi_win32_swapchain *chain; 547ec681f3Smrg HDC dc; 557ec681f3Smrg HBITMAP bmp; 567ec681f3Smrg int bmp_row_pitch; 577ec681f3Smrg void *ppvBits; 587ec681f3Smrg}; 597ec681f3Smrg 607ec681f3Smrg 617ec681f3Smrgstruct wsi_win32_swapchain { 627ec681f3Smrg struct wsi_swapchain base; 637ec681f3Smrg struct wsi_win32 *wsi; 647ec681f3Smrg VkIcdSurfaceWin32 *surface; 657ec681f3Smrg uint64_t flip_sequence; 667ec681f3Smrg VkResult status; 677ec681f3Smrg VkExtent2D extent; 687ec681f3Smrg HWND wnd; 697ec681f3Smrg HDC chain_dc; 707ec681f3Smrg struct wsi_win32_image images[0]; 717ec681f3Smrg}; 727ec681f3Smrg 737ec681f3SmrgVkBool32 747ec681f3Smrgwsi_win32_get_presentation_support(struct wsi_device *wsi_device) 757ec681f3Smrg{ 767ec681f3Smrg return TRUE; 777ec681f3Smrg} 787ec681f3Smrg 797ec681f3SmrgVKAPI_ATTR VkBool32 VKAPI_CALL 807ec681f3Smrgwsi_GetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice, 817ec681f3Smrg uint32_t queueFamilyIndex) 827ec681f3Smrg{ 837ec681f3Smrg VK_FROM_HANDLE(vk_physical_device, device, physicalDevice); 847ec681f3Smrg 857ec681f3Smrg return wsi_win32_get_presentation_support(device->wsi_device); 867ec681f3Smrg} 877ec681f3Smrg 887ec681f3SmrgVkResult 897ec681f3Smrgwsi_create_win32_surface(VkInstance instance, 907ec681f3Smrg const VkAllocationCallbacks *allocator, 917ec681f3Smrg const VkWin32SurfaceCreateInfoKHR *create_info, 927ec681f3Smrg VkSurfaceKHR *surface_khr) 937ec681f3Smrg{ 947ec681f3Smrg VkIcdSurfaceWin32 *surface = vk_zalloc(allocator, sizeof *surface, 8, 957ec681f3Smrg VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 967ec681f3Smrg 977ec681f3Smrg if (surface == NULL) 987ec681f3Smrg return VK_ERROR_OUT_OF_HOST_MEMORY; 997ec681f3Smrg 1007ec681f3Smrg surface->base.platform = VK_ICD_WSI_PLATFORM_WIN32; 1017ec681f3Smrg 1027ec681f3Smrg surface->hinstance = create_info->hinstance; 1037ec681f3Smrg surface->hwnd = create_info->hwnd; 1047ec681f3Smrg 1057ec681f3Smrg *surface_khr = VkIcdSurfaceBase_to_handle(&surface->base); 1067ec681f3Smrg return VK_SUCCESS; 1077ec681f3Smrg} 1087ec681f3Smrg 1097ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL 1107ec681f3Smrgwsi_CreateWin32SurfaceKHR(VkInstance _instance, 1117ec681f3Smrg const VkWin32SurfaceCreateInfoKHR *pCreateInfo, 1127ec681f3Smrg const VkAllocationCallbacks *pAllocator, 1137ec681f3Smrg VkSurfaceKHR *pSurface) 1147ec681f3Smrg{ 1157ec681f3Smrg VK_FROM_HANDLE(vk_instance, instance, _instance); 1167ec681f3Smrg const VkAllocationCallbacks *alloc; 1177ec681f3Smrg 1187ec681f3Smrg assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR); 1197ec681f3Smrg 1207ec681f3Smrg if (pAllocator) 1217ec681f3Smrg alloc = pAllocator; 1227ec681f3Smrg else 1237ec681f3Smrg alloc = &instance->alloc; 1247ec681f3Smrg 1257ec681f3Smrg return wsi_create_win32_surface(_instance, alloc, pCreateInfo, pSurface); 1267ec681f3Smrg} 1277ec681f3Smrg 1287ec681f3Smrgstatic VkResult 1297ec681f3Smrgwsi_win32_surface_get_support(VkIcdSurfaceBase *surface, 1307ec681f3Smrg struct wsi_device *wsi_device, 1317ec681f3Smrg uint32_t queueFamilyIndex, 1327ec681f3Smrg VkBool32* pSupported) 1337ec681f3Smrg{ 1347ec681f3Smrg *pSupported = true; 1357ec681f3Smrg 1367ec681f3Smrg return VK_SUCCESS; 1377ec681f3Smrg} 1387ec681f3Smrg 1397ec681f3Smrgstatic VkResult 1407ec681f3Smrgwsi_win32_surface_get_capabilities(VkIcdSurfaceBase *surface, 1417ec681f3Smrg struct wsi_device *wsi_device, 1427ec681f3Smrg VkSurfaceCapabilitiesKHR* caps) 1437ec681f3Smrg{ 1447ec681f3Smrg caps->minImageCount = 1; 1457ec681f3Smrg /* There is no real maximum */ 1467ec681f3Smrg caps->maxImageCount = 0; 1477ec681f3Smrg 1487ec681f3Smrg caps->currentExtent = (VkExtent2D) { UINT32_MAX, UINT32_MAX }; 1497ec681f3Smrg caps->minImageExtent = (VkExtent2D) { 1, 1 }; 1507ec681f3Smrg caps->maxImageExtent = (VkExtent2D) { 1517ec681f3Smrg wsi_device->maxImageDimension2D, 1527ec681f3Smrg wsi_device->maxImageDimension2D, 1537ec681f3Smrg }; 1547ec681f3Smrg 1557ec681f3Smrg caps->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; 1567ec681f3Smrg caps->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; 1577ec681f3Smrg caps->maxImageArrayLayers = 1; 1587ec681f3Smrg 1597ec681f3Smrg caps->supportedCompositeAlpha = 1607ec681f3Smrg VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR | 1617ec681f3Smrg VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR; 1627ec681f3Smrg 1637ec681f3Smrg caps->supportedUsageFlags = 1647ec681f3Smrg VK_IMAGE_USAGE_TRANSFER_SRC_BIT | 1657ec681f3Smrg VK_IMAGE_USAGE_SAMPLED_BIT | 1667ec681f3Smrg VK_IMAGE_USAGE_TRANSFER_DST_BIT | 1677ec681f3Smrg VK_IMAGE_USAGE_STORAGE_BIT | 1687ec681f3Smrg VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 1697ec681f3Smrg 1707ec681f3Smrg return VK_SUCCESS; 1717ec681f3Smrg} 1727ec681f3Smrg 1737ec681f3Smrgstatic VkResult 1747ec681f3Smrgwsi_win32_surface_get_capabilities2(VkIcdSurfaceBase *surface, 1757ec681f3Smrg struct wsi_device *wsi_device, 1767ec681f3Smrg const void *info_next, 1777ec681f3Smrg VkSurfaceCapabilities2KHR* caps) 1787ec681f3Smrg{ 1797ec681f3Smrg assert(caps->sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR); 1807ec681f3Smrg 1817ec681f3Smrg VkResult result = 1827ec681f3Smrg wsi_win32_surface_get_capabilities(surface, wsi_device, 1837ec681f3Smrg &caps->surfaceCapabilities); 1847ec681f3Smrg 1857ec681f3Smrg vk_foreach_struct(ext, caps->pNext) { 1867ec681f3Smrg switch (ext->sType) { 1877ec681f3Smrg case VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR: { 1887ec681f3Smrg VkSurfaceProtectedCapabilitiesKHR *protected = (void *)ext; 1897ec681f3Smrg protected->supportsProtected = VK_FALSE; 1907ec681f3Smrg break; 1917ec681f3Smrg } 1927ec681f3Smrg 1937ec681f3Smrg default: 1947ec681f3Smrg /* Ignored */ 1957ec681f3Smrg break; 1967ec681f3Smrg } 1977ec681f3Smrg } 1987ec681f3Smrg 1997ec681f3Smrg return result; 2007ec681f3Smrg} 2017ec681f3Smrg 2027ec681f3Smrg 2037ec681f3Smrgstatic const struct { 2047ec681f3Smrg VkFormat format; 2057ec681f3Smrg} available_surface_formats[] = { 2067ec681f3Smrg { .format = VK_FORMAT_B8G8R8A8_SRGB }, 2077ec681f3Smrg { .format = VK_FORMAT_B8G8R8A8_UNORM }, 2087ec681f3Smrg}; 2097ec681f3Smrg 2107ec681f3Smrg 2117ec681f3Smrgstatic void 2127ec681f3Smrgget_sorted_vk_formats(struct wsi_device *wsi_device, VkFormat *sorted_formats) 2137ec681f3Smrg{ 2147ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(available_surface_formats); i++) 2157ec681f3Smrg sorted_formats[i] = available_surface_formats[i].format; 2167ec681f3Smrg 2177ec681f3Smrg if (wsi_device->force_bgra8_unorm_first) { 2187ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(available_surface_formats); i++) { 2197ec681f3Smrg if (sorted_formats[i] == VK_FORMAT_B8G8R8A8_UNORM) { 2207ec681f3Smrg sorted_formats[i] = sorted_formats[0]; 2217ec681f3Smrg sorted_formats[0] = VK_FORMAT_B8G8R8A8_UNORM; 2227ec681f3Smrg break; 2237ec681f3Smrg } 2247ec681f3Smrg } 2257ec681f3Smrg } 2267ec681f3Smrg} 2277ec681f3Smrg 2287ec681f3Smrgstatic VkResult 2297ec681f3Smrgwsi_win32_surface_get_formats(VkIcdSurfaceBase *icd_surface, 2307ec681f3Smrg struct wsi_device *wsi_device, 2317ec681f3Smrg uint32_t* pSurfaceFormatCount, 2327ec681f3Smrg VkSurfaceFormatKHR* pSurfaceFormats) 2337ec681f3Smrg{ 2347ec681f3Smrg VK_OUTARRAY_MAKE_TYPED(VkSurfaceFormatKHR, out, pSurfaceFormats, pSurfaceFormatCount); 2357ec681f3Smrg 2367ec681f3Smrg VkFormat sorted_formats[ARRAY_SIZE(available_surface_formats)]; 2377ec681f3Smrg get_sorted_vk_formats(wsi_device, sorted_formats); 2387ec681f3Smrg 2397ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(sorted_formats); i++) { 2407ec681f3Smrg vk_outarray_append_typed(VkSurfaceFormatKHR, &out, f) { 2417ec681f3Smrg f->format = sorted_formats[i]; 2427ec681f3Smrg f->colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; 2437ec681f3Smrg } 2447ec681f3Smrg } 2457ec681f3Smrg 2467ec681f3Smrg return vk_outarray_status(&out); 2477ec681f3Smrg} 2487ec681f3Smrg 2497ec681f3Smrgstatic VkResult 2507ec681f3Smrgwsi_win32_surface_get_formats2(VkIcdSurfaceBase *icd_surface, 2517ec681f3Smrg struct wsi_device *wsi_device, 2527ec681f3Smrg const void *info_next, 2537ec681f3Smrg uint32_t* pSurfaceFormatCount, 2547ec681f3Smrg VkSurfaceFormat2KHR* pSurfaceFormats) 2557ec681f3Smrg{ 2567ec681f3Smrg VK_OUTARRAY_MAKE_TYPED(VkSurfaceFormat2KHR, out, pSurfaceFormats, pSurfaceFormatCount); 2577ec681f3Smrg 2587ec681f3Smrg VkFormat sorted_formats[ARRAY_SIZE(available_surface_formats)]; 2597ec681f3Smrg get_sorted_vk_formats(wsi_device, sorted_formats); 2607ec681f3Smrg 2617ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(sorted_formats); i++) { 2627ec681f3Smrg vk_outarray_append_typed(VkSurfaceFormat2KHR, &out, f) { 2637ec681f3Smrg assert(f->sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR); 2647ec681f3Smrg f->surfaceFormat.format = sorted_formats[i]; 2657ec681f3Smrg f->surfaceFormat.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; 2667ec681f3Smrg } 2677ec681f3Smrg } 2687ec681f3Smrg 2697ec681f3Smrg return vk_outarray_status(&out); 2707ec681f3Smrg} 2717ec681f3Smrg 2727ec681f3Smrgstatic const VkPresentModeKHR present_modes[] = { 2737ec681f3Smrg //VK_PRESENT_MODE_MAILBOX_KHR, 2747ec681f3Smrg VK_PRESENT_MODE_FIFO_KHR, 2757ec681f3Smrg}; 2767ec681f3Smrg 2777ec681f3Smrgstatic VkResult 2787ec681f3Smrgwsi_win32_surface_get_present_modes(VkIcdSurfaceBase *surface, 2797ec681f3Smrg uint32_t* pPresentModeCount, 2807ec681f3Smrg VkPresentModeKHR* pPresentModes) 2817ec681f3Smrg{ 2827ec681f3Smrg if (pPresentModes == NULL) { 2837ec681f3Smrg *pPresentModeCount = ARRAY_SIZE(present_modes); 2847ec681f3Smrg return VK_SUCCESS; 2857ec681f3Smrg } 2867ec681f3Smrg 2877ec681f3Smrg *pPresentModeCount = MIN2(*pPresentModeCount, ARRAY_SIZE(present_modes)); 2887ec681f3Smrg typed_memcpy(pPresentModes, present_modes, *pPresentModeCount); 2897ec681f3Smrg 2907ec681f3Smrg if (*pPresentModeCount < ARRAY_SIZE(present_modes)) 2917ec681f3Smrg return VK_INCOMPLETE; 2927ec681f3Smrg else 2937ec681f3Smrg return VK_SUCCESS; 2947ec681f3Smrg} 2957ec681f3Smrg 2967ec681f3Smrgstatic VkResult 2977ec681f3Smrgwsi_win32_surface_get_present_rectangles(VkIcdSurfaceBase *surface, 2987ec681f3Smrg struct wsi_device *wsi_device, 2997ec681f3Smrg uint32_t* pRectCount, 3007ec681f3Smrg VkRect2D* pRects) 3017ec681f3Smrg{ 3027ec681f3Smrg VK_OUTARRAY_MAKE_TYPED(VkRect2D, out, pRects, pRectCount); 3037ec681f3Smrg 3047ec681f3Smrg vk_outarray_append_typed(VkRect2D, &out, rect) { 3057ec681f3Smrg /* We don't know a size so just return the usual "I don't know." */ 3067ec681f3Smrg *rect = (VkRect2D) { 3077ec681f3Smrg .offset = { 0, 0 }, 3087ec681f3Smrg .extent = { UINT32_MAX, UINT32_MAX }, 3097ec681f3Smrg }; 3107ec681f3Smrg } 3117ec681f3Smrg 3127ec681f3Smrg return vk_outarray_status(&out); 3137ec681f3Smrg} 3147ec681f3Smrg 3157ec681f3Smrgstatic uint32_t 3167ec681f3Smrgselect_memory_type(const struct wsi_device *wsi, 3177ec681f3Smrg VkMemoryPropertyFlags props, 3187ec681f3Smrg uint32_t type_bits) 3197ec681f3Smrg{ 3207ec681f3Smrg for (uint32_t i = 0; i < wsi->memory_props.memoryTypeCount; i++) { 3217ec681f3Smrg const VkMemoryType type = wsi->memory_props.memoryTypes[i]; 3227ec681f3Smrg if ((type_bits & (1 << i)) && (type.propertyFlags & props) == props) 3237ec681f3Smrg return i; 3247ec681f3Smrg } 3257ec681f3Smrg 3267ec681f3Smrg unreachable("No memory type found"); 3277ec681f3Smrg} 3287ec681f3Smrg 3297ec681f3SmrgVkResult 3307ec681f3Smrgwsi_create_native_image(const struct wsi_swapchain *chain, 3317ec681f3Smrg const VkSwapchainCreateInfoKHR *pCreateInfo, 3327ec681f3Smrg uint32_t num_modifier_lists, 3337ec681f3Smrg const uint32_t *num_modifiers, 3347ec681f3Smrg const uint64_t *const *modifiers, 3357ec681f3Smrg uint8_t *(alloc_shm)(struct wsi_image *image, unsigned size), 3367ec681f3Smrg struct wsi_image *image) 3377ec681f3Smrg{ 3387ec681f3Smrg const struct wsi_device *wsi = chain->wsi; 3397ec681f3Smrg VkResult result; 3407ec681f3Smrg 3417ec681f3Smrg memset(image, 0, sizeof(*image)); 3427ec681f3Smrg for (int i = 0; i < ARRAY_SIZE(image->fds); i++) 3437ec681f3Smrg image->fds[i] = -1; 3447ec681f3Smrg 3457ec681f3Smrg const struct wsi_image_create_info image_wsi_info = { 3467ec681f3Smrg .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA, 3477ec681f3Smrg }; 3487ec681f3Smrg VkImageCreateInfo image_info = { 3497ec681f3Smrg .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 3507ec681f3Smrg .pNext = &image_wsi_info, 3517ec681f3Smrg .flags = 0, 3527ec681f3Smrg .imageType = VK_IMAGE_TYPE_2D, 3537ec681f3Smrg .format = pCreateInfo->imageFormat, 3547ec681f3Smrg .extent = { 3557ec681f3Smrg .width = pCreateInfo->imageExtent.width, 3567ec681f3Smrg .height = pCreateInfo->imageExtent.height, 3577ec681f3Smrg .depth = 1, 3587ec681f3Smrg }, 3597ec681f3Smrg .mipLevels = 1, 3607ec681f3Smrg .arrayLayers = 1, 3617ec681f3Smrg .samples = VK_SAMPLE_COUNT_1_BIT, 3627ec681f3Smrg .tiling = VK_IMAGE_TILING_OPTIMAL, 3637ec681f3Smrg .usage = pCreateInfo->imageUsage, 3647ec681f3Smrg .sharingMode = pCreateInfo->imageSharingMode, 3657ec681f3Smrg .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount, 3667ec681f3Smrg .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices, 3677ec681f3Smrg .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, 3687ec681f3Smrg }; 3697ec681f3Smrg 3707ec681f3Smrg VkImageFormatListCreateInfoKHR image_format_list; 3717ec681f3Smrg if (pCreateInfo->flags & VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR) { 3727ec681f3Smrg image_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | 3737ec681f3Smrg VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR; 3747ec681f3Smrg 3757ec681f3Smrg const VkImageFormatListCreateInfoKHR *format_list = 3767ec681f3Smrg vk_find_struct_const(pCreateInfo->pNext, 3777ec681f3Smrg IMAGE_FORMAT_LIST_CREATE_INFO_KHR); 3787ec681f3Smrg 3797ec681f3Smrg#ifndef NDEBUG 3807ec681f3Smrg assume(format_list && format_list->viewFormatCount > 0); 3817ec681f3Smrg bool format_found = false; 3827ec681f3Smrg for (int i = 0; i < format_list->viewFormatCount; i++) 3837ec681f3Smrg if (pCreateInfo->imageFormat == format_list->pViewFormats[i]) 3847ec681f3Smrg format_found = true; 3857ec681f3Smrg assert(format_found); 3867ec681f3Smrg#endif 3877ec681f3Smrg 3887ec681f3Smrg image_format_list = *format_list; 3897ec681f3Smrg image_format_list.pNext = NULL; 3907ec681f3Smrg __vk_append_struct(&image_info, &image_format_list); 3917ec681f3Smrg } 3927ec681f3Smrg 3937ec681f3Smrg 3947ec681f3Smrg result = wsi->CreateImage(chain->device, &image_info, 3957ec681f3Smrg &chain->alloc, &image->image); 3967ec681f3Smrg if (result != VK_SUCCESS) 3977ec681f3Smrg goto fail; 3987ec681f3Smrg 3997ec681f3Smrg VkMemoryRequirements reqs; 4007ec681f3Smrg wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs); 4017ec681f3Smrg 4027ec681f3Smrg const struct wsi_memory_allocate_info memory_wsi_info = { 4037ec681f3Smrg .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA, 4047ec681f3Smrg .pNext = NULL, 4057ec681f3Smrg .implicit_sync = true, 4067ec681f3Smrg }; 4077ec681f3Smrg const VkExportMemoryAllocateInfo memory_export_info = { 4087ec681f3Smrg .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO, 4097ec681f3Smrg .pNext = &memory_wsi_info, 4107ec681f3Smrg .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, 4117ec681f3Smrg }; 4127ec681f3Smrg const VkMemoryDedicatedAllocateInfo memory_dedicated_info = { 4137ec681f3Smrg .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, 4147ec681f3Smrg .pNext = &memory_export_info, 4157ec681f3Smrg .image = image->image, 4167ec681f3Smrg .buffer = VK_NULL_HANDLE, 4177ec681f3Smrg }; 4187ec681f3Smrg const VkMemoryAllocateInfo memory_info = { 4197ec681f3Smrg .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 4207ec681f3Smrg .pNext = &memory_dedicated_info, 4217ec681f3Smrg .allocationSize = reqs.size, 4227ec681f3Smrg .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, 4237ec681f3Smrg reqs.memoryTypeBits), 4247ec681f3Smrg }; 4257ec681f3Smrg result = wsi->AllocateMemory(chain->device, &memory_info, 4267ec681f3Smrg &chain->alloc, &image->memory); 4277ec681f3Smrg if (result != VK_SUCCESS) 4287ec681f3Smrg goto fail; 4297ec681f3Smrg 4307ec681f3Smrg result = wsi->BindImageMemory(chain->device, image->image, 4317ec681f3Smrg image->memory, 0); 4327ec681f3Smrg if (result != VK_SUCCESS) 4337ec681f3Smrg goto fail; 4347ec681f3Smrg 4357ec681f3Smrg const VkImageSubresource image_subresource = { 4367ec681f3Smrg .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 4377ec681f3Smrg .mipLevel = 0, 4387ec681f3Smrg .arrayLayer = 0, 4397ec681f3Smrg }; 4407ec681f3Smrg VkSubresourceLayout image_layout; 4417ec681f3Smrg wsi->GetImageSubresourceLayout(chain->device, image->image, 4427ec681f3Smrg &image_subresource, &image_layout); 4437ec681f3Smrg 4447ec681f3Smrg image->num_planes = 1; 4457ec681f3Smrg image->sizes[0] = reqs.size; 4467ec681f3Smrg image->row_pitches[0] = image_layout.rowPitch; 4477ec681f3Smrg image->offsets[0] = 0; 4487ec681f3Smrg 4497ec681f3Smrg return VK_SUCCESS; 4507ec681f3Smrg 4517ec681f3Smrgfail: 4527ec681f3Smrg wsi_destroy_image(chain, image); 4537ec681f3Smrg 4547ec681f3Smrg return result; 4557ec681f3Smrg} 4567ec681f3Smrg 4577ec681f3Smrgstatic VkResult 4587ec681f3Smrgwsi_win32_image_init(VkDevice device_h, 4597ec681f3Smrg struct wsi_swapchain *drv_chain, 4607ec681f3Smrg const VkSwapchainCreateInfoKHR *create_info, 4617ec681f3Smrg const VkAllocationCallbacks *allocator, 4627ec681f3Smrg struct wsi_win32_image *image) 4637ec681f3Smrg{ 4647ec681f3Smrg struct wsi_win32_swapchain *chain = (struct wsi_win32_swapchain *) drv_chain; 4657ec681f3Smrg 4667ec681f3Smrg VkResult result = wsi_create_native_image(&chain->base, create_info, 4677ec681f3Smrg 0, NULL, NULL, NULL, 4687ec681f3Smrg &image->base); 4697ec681f3Smrg if (result != VK_SUCCESS) 4707ec681f3Smrg return result; 4717ec681f3Smrg 4727ec681f3Smrg VkIcdSurfaceWin32 *win32_surface = (VkIcdSurfaceWin32 *)create_info->surface; 4737ec681f3Smrg chain->wnd = win32_surface->hwnd; 4747ec681f3Smrg chain->chain_dc = GetDC(chain->wnd); 4757ec681f3Smrg 4767ec681f3Smrg image->dc = CreateCompatibleDC(chain->chain_dc); 4777ec681f3Smrg HBITMAP bmp = NULL; 4787ec681f3Smrg 4797ec681f3Smrg BITMAPINFO info = { 0 }; 4807ec681f3Smrg info.bmiHeader.biSize = sizeof(BITMAPINFO); 4817ec681f3Smrg info.bmiHeader.biWidth = create_info->imageExtent.width; 4827ec681f3Smrg info.bmiHeader.biHeight = -create_info->imageExtent.height; 4837ec681f3Smrg info.bmiHeader.biPlanes = 1; 4847ec681f3Smrg info.bmiHeader.biBitCount = 32; 4857ec681f3Smrg info.bmiHeader.biCompression = BI_RGB; 4867ec681f3Smrg 4877ec681f3Smrg bmp = CreateDIBSection(image->dc, &info, DIB_RGB_COLORS, &image->ppvBits, NULL, 0); 4887ec681f3Smrg assert(bmp && image->ppvBits); 4897ec681f3Smrg 4907ec681f3Smrg SelectObject(image->dc, bmp); 4917ec681f3Smrg 4927ec681f3Smrg BITMAP header; 4937ec681f3Smrg int status = GetObject(bmp, sizeof(BITMAP), &header); 4947ec681f3Smrg (void)status; 4957ec681f3Smrg image->bmp_row_pitch = header.bmWidthBytes; 4967ec681f3Smrg image->bmp = bmp; 4977ec681f3Smrg image->chain = chain; 4987ec681f3Smrg 4997ec681f3Smrg return VK_SUCCESS; 5007ec681f3Smrg} 5017ec681f3Smrg 5027ec681f3Smrgstatic void 5037ec681f3Smrgwsi_win32_image_finish(struct wsi_swapchain *drv_chain, 5047ec681f3Smrg const VkAllocationCallbacks *allocator, 5057ec681f3Smrg struct wsi_win32_image *image) 5067ec681f3Smrg{ 5077ec681f3Smrg struct wsi_win32_swapchain *chain = 5087ec681f3Smrg (struct wsi_win32_swapchain *) drv_chain; 5097ec681f3Smrg 5107ec681f3Smrg DeleteDC(image->dc); 5117ec681f3Smrg if(image->bmp) 5127ec681f3Smrg DeleteObject(image->bmp); 5137ec681f3Smrg wsi_destroy_image(&chain->base, &image->base); 5147ec681f3Smrg} 5157ec681f3Smrg 5167ec681f3Smrgstatic VkResult 5177ec681f3Smrgwsi_win32_swapchain_destroy(struct wsi_swapchain *drv_chain, 5187ec681f3Smrg const VkAllocationCallbacks *allocator) 5197ec681f3Smrg{ 5207ec681f3Smrg struct wsi_win32_swapchain *chain = 5217ec681f3Smrg (struct wsi_win32_swapchain *) drv_chain; 5227ec681f3Smrg 5237ec681f3Smrg for (uint32_t i = 0; i < chain->base.image_count; i++) 5247ec681f3Smrg wsi_win32_image_finish(drv_chain, allocator, &chain->images[i]); 5257ec681f3Smrg 5267ec681f3Smrg DeleteDC(chain->chain_dc); 5277ec681f3Smrg 5287ec681f3Smrg wsi_swapchain_finish(&chain->base); 5297ec681f3Smrg vk_free(allocator, chain); 5307ec681f3Smrg return VK_SUCCESS; 5317ec681f3Smrg} 5327ec681f3Smrg 5337ec681f3Smrgstatic struct wsi_image * 5347ec681f3Smrgwsi_win32_get_wsi_image(struct wsi_swapchain *drv_chain, 5357ec681f3Smrg uint32_t image_index) 5367ec681f3Smrg{ 5377ec681f3Smrg struct wsi_win32_swapchain *chain = 5387ec681f3Smrg (struct wsi_win32_swapchain *) drv_chain; 5397ec681f3Smrg 5407ec681f3Smrg return &chain->images[image_index].base; 5417ec681f3Smrg} 5427ec681f3Smrg 5437ec681f3Smrgstatic VkResult 5447ec681f3Smrgwsi_win32_acquire_next_image(struct wsi_swapchain *drv_chain, 5457ec681f3Smrg const VkAcquireNextImageInfoKHR *info, 5467ec681f3Smrg uint32_t *image_index) 5477ec681f3Smrg{ 5487ec681f3Smrg struct wsi_win32_swapchain *chain = 5497ec681f3Smrg (struct wsi_win32_swapchain *)drv_chain; 5507ec681f3Smrg 5517ec681f3Smrg /* Bail early if the swapchain is broken */ 5527ec681f3Smrg if (chain->status != VK_SUCCESS) 5537ec681f3Smrg return chain->status; 5547ec681f3Smrg 5557ec681f3Smrg *image_index = 0; 5567ec681f3Smrg return VK_SUCCESS; 5577ec681f3Smrg} 5587ec681f3Smrg 5597ec681f3Smrgstatic VkResult 5607ec681f3Smrgwsi_win32_queue_present(struct wsi_swapchain *drv_chain, 5617ec681f3Smrg uint32_t image_index, 5627ec681f3Smrg const VkPresentRegionKHR *damage) 5637ec681f3Smrg{ 5647ec681f3Smrg struct wsi_win32_swapchain *chain = (struct wsi_win32_swapchain *) drv_chain; 5657ec681f3Smrg assert(image_index < chain->base.image_count); 5667ec681f3Smrg struct wsi_win32_image *image = &chain->images[image_index]; 5677ec681f3Smrg VkResult result; 5687ec681f3Smrg 5697ec681f3Smrg char *ptr; 5707ec681f3Smrg char *dptr = image->ppvBits; 5717ec681f3Smrg result = chain->base.wsi->MapMemory(chain->base.device, 5727ec681f3Smrg image->base.memory, 5737ec681f3Smrg 0, image->base.sizes[0], 0, (void**)&ptr); 5747ec681f3Smrg 5757ec681f3Smrg for (unsigned h = 0; h < chain->extent.height; h++) { 5767ec681f3Smrg memcpy(dptr, ptr, chain->extent.width * 4); 5777ec681f3Smrg dptr += image->bmp_row_pitch; 5787ec681f3Smrg ptr += image->base.row_pitches[0]; 5797ec681f3Smrg } 5807ec681f3Smrg if(StretchBlt(chain->chain_dc, 0, 0, chain->extent.width, chain->extent.height, image->dc, 0, 0, chain->extent.width, chain->extent.height, SRCCOPY)) 5817ec681f3Smrg result = VK_SUCCESS; 5827ec681f3Smrg else 5837ec681f3Smrg result = VK_ERROR_MEMORY_MAP_FAILED; 5847ec681f3Smrg 5857ec681f3Smrg chain->base.wsi->UnmapMemory(chain->base.device, image->base.memory); 5867ec681f3Smrg if (result != VK_SUCCESS) 5877ec681f3Smrg chain->status = result; 5887ec681f3Smrg 5897ec681f3Smrg if (result != VK_SUCCESS) 5907ec681f3Smrg return result; 5917ec681f3Smrg 5927ec681f3Smrg return chain->status; 5937ec681f3Smrg} 5947ec681f3Smrg 5957ec681f3Smrgstatic VkResult 5967ec681f3Smrgwsi_win32_surface_create_swapchain( 5977ec681f3Smrg VkIcdSurfaceBase *icd_surface, 5987ec681f3Smrg VkDevice device, 5997ec681f3Smrg struct wsi_device *wsi_device, 6007ec681f3Smrg const VkSwapchainCreateInfoKHR *create_info, 6017ec681f3Smrg const VkAllocationCallbacks *allocator, 6027ec681f3Smrg struct wsi_swapchain **swapchain_out) 6037ec681f3Smrg{ 6047ec681f3Smrg VkIcdSurfaceWin32 *surface = (VkIcdSurfaceWin32 *)icd_surface; 6057ec681f3Smrg struct wsi_win32 *wsi = 6067ec681f3Smrg (struct wsi_win32 *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_WIN32]; 6077ec681f3Smrg 6087ec681f3Smrg assert(create_info->sType == VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR); 6097ec681f3Smrg 6107ec681f3Smrg const unsigned num_images = create_info->minImageCount; 6117ec681f3Smrg struct wsi_win32_swapchain *chain; 6127ec681f3Smrg size_t size = sizeof(*chain) + num_images * sizeof(chain->images[0]); 6137ec681f3Smrg 6147ec681f3Smrg chain = vk_zalloc(allocator, size, 6157ec681f3Smrg 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 6167ec681f3Smrg 6177ec681f3Smrg if (chain == NULL) 6187ec681f3Smrg return VK_ERROR_OUT_OF_HOST_MEMORY; 6197ec681f3Smrg 6207ec681f3Smrg VkResult result = wsi_swapchain_init(wsi_device, &chain->base, device, 6217ec681f3Smrg create_info, allocator); 6227ec681f3Smrg if (result != VK_SUCCESS) { 6237ec681f3Smrg vk_free(allocator, chain); 6247ec681f3Smrg return result; 6257ec681f3Smrg } 6267ec681f3Smrg 6277ec681f3Smrg chain->base.destroy = wsi_win32_swapchain_destroy; 6287ec681f3Smrg chain->base.get_wsi_image = wsi_win32_get_wsi_image; 6297ec681f3Smrg chain->base.acquire_next_image = wsi_win32_acquire_next_image; 6307ec681f3Smrg chain->base.queue_present = wsi_win32_queue_present; 6317ec681f3Smrg chain->base.present_mode = wsi_swapchain_get_present_mode(wsi_device, create_info); 6327ec681f3Smrg chain->base.image_count = num_images; 6337ec681f3Smrg chain->extent = create_info->imageExtent; 6347ec681f3Smrg 6357ec681f3Smrg chain->wsi = wsi; 6367ec681f3Smrg chain->status = VK_SUCCESS; 6377ec681f3Smrg 6387ec681f3Smrg chain->surface = surface; 6397ec681f3Smrg 6407ec681f3Smrg for (uint32_t image = 0; image < chain->base.image_count; image++) { 6417ec681f3Smrg result = wsi_win32_image_init(device, &chain->base, 6427ec681f3Smrg create_info, allocator, 6437ec681f3Smrg &chain->images[image]); 6447ec681f3Smrg if (result != VK_SUCCESS) { 6457ec681f3Smrg while (image > 0) { 6467ec681f3Smrg --image; 6477ec681f3Smrg wsi_win32_image_finish(&chain->base, allocator, 6487ec681f3Smrg &chain->images[image]); 6497ec681f3Smrg } 6507ec681f3Smrg vk_free(allocator, chain); 6517ec681f3Smrg goto fail_init_images; 6527ec681f3Smrg } 6537ec681f3Smrg } 6547ec681f3Smrg 6557ec681f3Smrg *swapchain_out = &chain->base; 6567ec681f3Smrg 6577ec681f3Smrg return VK_SUCCESS; 6587ec681f3Smrg 6597ec681f3Smrgfail_init_images: 6607ec681f3Smrg return result; 6617ec681f3Smrg} 6627ec681f3Smrg 6637ec681f3Smrg 6647ec681f3SmrgVkResult 6657ec681f3Smrgwsi_win32_init_wsi(struct wsi_device *wsi_device, 6667ec681f3Smrg const VkAllocationCallbacks *alloc, 6677ec681f3Smrg VkPhysicalDevice physical_device) 6687ec681f3Smrg{ 6697ec681f3Smrg struct wsi_win32 *wsi; 6707ec681f3Smrg VkResult result; 6717ec681f3Smrg 6727ec681f3Smrg wsi = vk_alloc(alloc, sizeof(*wsi), 8, 6737ec681f3Smrg VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 6747ec681f3Smrg if (!wsi) { 6757ec681f3Smrg result = VK_ERROR_OUT_OF_HOST_MEMORY; 6767ec681f3Smrg goto fail; 6777ec681f3Smrg } 6787ec681f3Smrg 6797ec681f3Smrg wsi->physical_device = physical_device; 6807ec681f3Smrg wsi->alloc = alloc; 6817ec681f3Smrg wsi->wsi = wsi_device; 6827ec681f3Smrg 6837ec681f3Smrg wsi->base.get_support = wsi_win32_surface_get_support; 6847ec681f3Smrg wsi->base.get_capabilities2 = wsi_win32_surface_get_capabilities2; 6857ec681f3Smrg wsi->base.get_formats = wsi_win32_surface_get_formats; 6867ec681f3Smrg wsi->base.get_formats2 = wsi_win32_surface_get_formats2; 6877ec681f3Smrg wsi->base.get_present_modes = wsi_win32_surface_get_present_modes; 6887ec681f3Smrg wsi->base.get_present_rectangles = wsi_win32_surface_get_present_rectangles; 6897ec681f3Smrg wsi->base.create_swapchain = wsi_win32_surface_create_swapchain; 6907ec681f3Smrg 6917ec681f3Smrg wsi_device->wsi[VK_ICD_WSI_PLATFORM_WIN32] = &wsi->base; 6927ec681f3Smrg 6937ec681f3Smrg return VK_SUCCESS; 6947ec681f3Smrg 6957ec681f3Smrgfail: 6967ec681f3Smrg wsi_device->wsi[VK_ICD_WSI_PLATFORM_WIN32] = NULL; 6977ec681f3Smrg 6987ec681f3Smrg return result; 6997ec681f3Smrg} 7007ec681f3Smrg 7017ec681f3Smrgvoid 7027ec681f3Smrgwsi_win32_finish_wsi(struct wsi_device *wsi_device, 7037ec681f3Smrg const VkAllocationCallbacks *alloc) 7047ec681f3Smrg{ 7057ec681f3Smrg struct wsi_win32 *wsi = 7067ec681f3Smrg (struct wsi_win32 *)wsi_device->wsi[VK_ICD_WSI_PLATFORM_WIN32]; 7077ec681f3Smrg if (!wsi) 7087ec681f3Smrg return; 7097ec681f3Smrg 7107ec681f3Smrg vk_free(alloc, wsi); 7117ec681f3Smrg} 712