1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2015 Intel Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include <assert.h> 25bf215546Sopenharmony_ci#include <stdlib.h> 26bf215546Sopenharmony_ci#include <stdio.h> 27bf215546Sopenharmony_ci#include <string.h> 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include "vk_format.h" 30bf215546Sopenharmony_ci#include "vk_instance.h" 31bf215546Sopenharmony_ci#include "vk_physical_device.h" 32bf215546Sopenharmony_ci#include "vk_util.h" 33bf215546Sopenharmony_ci#include "wsi_common_entrypoints.h" 34bf215546Sopenharmony_ci#include "wsi_common_private.h" 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci#if defined(__GNUC__) 37bf215546Sopenharmony_ci#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size 38bf215546Sopenharmony_ci#endif 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_cistruct wsi_win32; 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_cistruct wsi_win32 { 43bf215546Sopenharmony_ci struct wsi_interface base; 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci struct wsi_device *wsi; 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc; 48bf215546Sopenharmony_ci VkPhysicalDevice physical_device; 49bf215546Sopenharmony_ci}; 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_cistruct wsi_win32_image { 52bf215546Sopenharmony_ci struct wsi_image base; 53bf215546Sopenharmony_ci struct wsi_win32_swapchain *chain; 54bf215546Sopenharmony_ci HDC dc; 55bf215546Sopenharmony_ci HBITMAP bmp; 56bf215546Sopenharmony_ci int bmp_row_pitch; 57bf215546Sopenharmony_ci void *ppvBits; 58bf215546Sopenharmony_ci}; 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_cistruct wsi_win32_swapchain { 62bf215546Sopenharmony_ci struct wsi_swapchain base; 63bf215546Sopenharmony_ci struct wsi_win32 *wsi; 64bf215546Sopenharmony_ci VkIcdSurfaceWin32 *surface; 65bf215546Sopenharmony_ci uint64_t flip_sequence; 66bf215546Sopenharmony_ci VkResult status; 67bf215546Sopenharmony_ci VkExtent2D extent; 68bf215546Sopenharmony_ci HWND wnd; 69bf215546Sopenharmony_ci HDC chain_dc; 70bf215546Sopenharmony_ci struct wsi_win32_image images[0]; 71bf215546Sopenharmony_ci}; 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ciVKAPI_ATTR VkBool32 VKAPI_CALL 74bf215546Sopenharmony_ciwsi_GetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice, 75bf215546Sopenharmony_ci uint32_t queueFamilyIndex) 76bf215546Sopenharmony_ci{ 77bf215546Sopenharmony_ci return TRUE; 78bf215546Sopenharmony_ci} 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 81bf215546Sopenharmony_ciwsi_CreateWin32SurfaceKHR(VkInstance _instance, 82bf215546Sopenharmony_ci const VkWin32SurfaceCreateInfoKHR *pCreateInfo, 83bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 84bf215546Sopenharmony_ci VkSurfaceKHR *pSurface) 85bf215546Sopenharmony_ci{ 86bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_instance, instance, _instance); 87bf215546Sopenharmony_ci VkIcdSurfaceWin32 *surface; 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR); 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci surface = vk_zalloc2(&instance->alloc, pAllocator, sizeof(*surface), 8, 92bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci if (surface == NULL) 95bf215546Sopenharmony_ci return VK_ERROR_OUT_OF_HOST_MEMORY; 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci surface->base.platform = VK_ICD_WSI_PLATFORM_WIN32; 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci surface->hinstance = pCreateInfo->hinstance; 100bf215546Sopenharmony_ci surface->hwnd = pCreateInfo->hwnd; 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci *pSurface = VkIcdSurfaceBase_to_handle(&surface->base); 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_ci return VK_SUCCESS; 105bf215546Sopenharmony_ci} 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_cistatic VkResult 108bf215546Sopenharmony_ciwsi_win32_surface_get_support(VkIcdSurfaceBase *surface, 109bf215546Sopenharmony_ci struct wsi_device *wsi_device, 110bf215546Sopenharmony_ci uint32_t queueFamilyIndex, 111bf215546Sopenharmony_ci VkBool32* pSupported) 112bf215546Sopenharmony_ci{ 113bf215546Sopenharmony_ci *pSupported = true; 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci return VK_SUCCESS; 116bf215546Sopenharmony_ci} 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_cistatic VkResult 119bf215546Sopenharmony_ciwsi_win32_surface_get_capabilities(VkIcdSurfaceBase *surf, 120bf215546Sopenharmony_ci struct wsi_device *wsi_device, 121bf215546Sopenharmony_ci VkSurfaceCapabilitiesKHR* caps) 122bf215546Sopenharmony_ci{ 123bf215546Sopenharmony_ci VkIcdSurfaceWin32 *surface = (VkIcdSurfaceWin32 *)surf; 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci RECT win_rect; 126bf215546Sopenharmony_ci if (!GetClientRect(surface->hwnd, &win_rect)) 127bf215546Sopenharmony_ci return VK_ERROR_SURFACE_LOST_KHR; 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci caps->minImageCount = 1; 130bf215546Sopenharmony_ci /* There is no real maximum */ 131bf215546Sopenharmony_ci caps->maxImageCount = 0; 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci caps->currentExtent = (VkExtent2D) { 134bf215546Sopenharmony_ci win_rect.right - win_rect.left, 135bf215546Sopenharmony_ci win_rect.bottom - win_rect.top 136bf215546Sopenharmony_ci }; 137bf215546Sopenharmony_ci caps->minImageExtent = (VkExtent2D) { 1, 1 }; 138bf215546Sopenharmony_ci caps->maxImageExtent = (VkExtent2D) { 139bf215546Sopenharmony_ci wsi_device->maxImageDimension2D, 140bf215546Sopenharmony_ci wsi_device->maxImageDimension2D, 141bf215546Sopenharmony_ci }; 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ci caps->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; 144bf215546Sopenharmony_ci caps->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; 145bf215546Sopenharmony_ci caps->maxImageArrayLayers = 1; 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci caps->supportedCompositeAlpha = 148bf215546Sopenharmony_ci VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR | 149bf215546Sopenharmony_ci VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR; 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci caps->supportedUsageFlags = 152bf215546Sopenharmony_ci VK_IMAGE_USAGE_TRANSFER_SRC_BIT | 153bf215546Sopenharmony_ci VK_IMAGE_USAGE_SAMPLED_BIT | 154bf215546Sopenharmony_ci VK_IMAGE_USAGE_TRANSFER_DST_BIT | 155bf215546Sopenharmony_ci VK_IMAGE_USAGE_STORAGE_BIT | 156bf215546Sopenharmony_ci VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | 157bf215546Sopenharmony_ci VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_ci return VK_SUCCESS; 160bf215546Sopenharmony_ci} 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_cistatic VkResult 163bf215546Sopenharmony_ciwsi_win32_surface_get_capabilities2(VkIcdSurfaceBase *surface, 164bf215546Sopenharmony_ci struct wsi_device *wsi_device, 165bf215546Sopenharmony_ci const void *info_next, 166bf215546Sopenharmony_ci VkSurfaceCapabilities2KHR* caps) 167bf215546Sopenharmony_ci{ 168bf215546Sopenharmony_ci assert(caps->sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR); 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci VkResult result = 171bf215546Sopenharmony_ci wsi_win32_surface_get_capabilities(surface, wsi_device, 172bf215546Sopenharmony_ci &caps->surfaceCapabilities); 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci vk_foreach_struct(ext, caps->pNext) { 175bf215546Sopenharmony_ci switch (ext->sType) { 176bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR: { 177bf215546Sopenharmony_ci VkSurfaceProtectedCapabilitiesKHR *protected = (void *)ext; 178bf215546Sopenharmony_ci protected->supportsProtected = VK_FALSE; 179bf215546Sopenharmony_ci break; 180bf215546Sopenharmony_ci } 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci default: 183bf215546Sopenharmony_ci /* Ignored */ 184bf215546Sopenharmony_ci break; 185bf215546Sopenharmony_ci } 186bf215546Sopenharmony_ci } 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci return result; 189bf215546Sopenharmony_ci} 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_cistatic const struct { 193bf215546Sopenharmony_ci VkFormat format; 194bf215546Sopenharmony_ci} available_surface_formats[] = { 195bf215546Sopenharmony_ci { .format = VK_FORMAT_B8G8R8A8_SRGB }, 196bf215546Sopenharmony_ci { .format = VK_FORMAT_B8G8R8A8_UNORM }, 197bf215546Sopenharmony_ci}; 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_cistatic void 201bf215546Sopenharmony_ciget_sorted_vk_formats(struct wsi_device *wsi_device, VkFormat *sorted_formats) 202bf215546Sopenharmony_ci{ 203bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(available_surface_formats); i++) 204bf215546Sopenharmony_ci sorted_formats[i] = available_surface_formats[i].format; 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci if (wsi_device->force_bgra8_unorm_first) { 207bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(available_surface_formats); i++) { 208bf215546Sopenharmony_ci if (sorted_formats[i] == VK_FORMAT_B8G8R8A8_UNORM) { 209bf215546Sopenharmony_ci sorted_formats[i] = sorted_formats[0]; 210bf215546Sopenharmony_ci sorted_formats[0] = VK_FORMAT_B8G8R8A8_UNORM; 211bf215546Sopenharmony_ci break; 212bf215546Sopenharmony_ci } 213bf215546Sopenharmony_ci } 214bf215546Sopenharmony_ci } 215bf215546Sopenharmony_ci} 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_cistatic VkResult 218bf215546Sopenharmony_ciwsi_win32_surface_get_formats(VkIcdSurfaceBase *icd_surface, 219bf215546Sopenharmony_ci struct wsi_device *wsi_device, 220bf215546Sopenharmony_ci uint32_t* pSurfaceFormatCount, 221bf215546Sopenharmony_ci VkSurfaceFormatKHR* pSurfaceFormats) 222bf215546Sopenharmony_ci{ 223bf215546Sopenharmony_ci VK_OUTARRAY_MAKE_TYPED(VkSurfaceFormatKHR, out, pSurfaceFormats, pSurfaceFormatCount); 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_ci VkFormat sorted_formats[ARRAY_SIZE(available_surface_formats)]; 226bf215546Sopenharmony_ci get_sorted_vk_formats(wsi_device, sorted_formats); 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(sorted_formats); i++) { 229bf215546Sopenharmony_ci vk_outarray_append_typed(VkSurfaceFormatKHR, &out, f) { 230bf215546Sopenharmony_ci f->format = sorted_formats[i]; 231bf215546Sopenharmony_ci f->colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; 232bf215546Sopenharmony_ci } 233bf215546Sopenharmony_ci } 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ci return vk_outarray_status(&out); 236bf215546Sopenharmony_ci} 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_cistatic VkResult 239bf215546Sopenharmony_ciwsi_win32_surface_get_formats2(VkIcdSurfaceBase *icd_surface, 240bf215546Sopenharmony_ci struct wsi_device *wsi_device, 241bf215546Sopenharmony_ci const void *info_next, 242bf215546Sopenharmony_ci uint32_t* pSurfaceFormatCount, 243bf215546Sopenharmony_ci VkSurfaceFormat2KHR* pSurfaceFormats) 244bf215546Sopenharmony_ci{ 245bf215546Sopenharmony_ci VK_OUTARRAY_MAKE_TYPED(VkSurfaceFormat2KHR, out, pSurfaceFormats, pSurfaceFormatCount); 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_ci VkFormat sorted_formats[ARRAY_SIZE(available_surface_formats)]; 248bf215546Sopenharmony_ci get_sorted_vk_formats(wsi_device, sorted_formats); 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(sorted_formats); i++) { 251bf215546Sopenharmony_ci vk_outarray_append_typed(VkSurfaceFormat2KHR, &out, f) { 252bf215546Sopenharmony_ci assert(f->sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR); 253bf215546Sopenharmony_ci f->surfaceFormat.format = sorted_formats[i]; 254bf215546Sopenharmony_ci f->surfaceFormat.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; 255bf215546Sopenharmony_ci } 256bf215546Sopenharmony_ci } 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci return vk_outarray_status(&out); 259bf215546Sopenharmony_ci} 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_cistatic const VkPresentModeKHR present_modes[] = { 262bf215546Sopenharmony_ci //VK_PRESENT_MODE_MAILBOX_KHR, 263bf215546Sopenharmony_ci VK_PRESENT_MODE_FIFO_KHR, 264bf215546Sopenharmony_ci}; 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_cistatic VkResult 267bf215546Sopenharmony_ciwsi_win32_surface_get_present_modes(VkIcdSurfaceBase *surface, 268bf215546Sopenharmony_ci uint32_t* pPresentModeCount, 269bf215546Sopenharmony_ci VkPresentModeKHR* pPresentModes) 270bf215546Sopenharmony_ci{ 271bf215546Sopenharmony_ci if (pPresentModes == NULL) { 272bf215546Sopenharmony_ci *pPresentModeCount = ARRAY_SIZE(present_modes); 273bf215546Sopenharmony_ci return VK_SUCCESS; 274bf215546Sopenharmony_ci } 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ci *pPresentModeCount = MIN2(*pPresentModeCount, ARRAY_SIZE(present_modes)); 277bf215546Sopenharmony_ci typed_memcpy(pPresentModes, present_modes, *pPresentModeCount); 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_ci if (*pPresentModeCount < ARRAY_SIZE(present_modes)) 280bf215546Sopenharmony_ci return VK_INCOMPLETE; 281bf215546Sopenharmony_ci else 282bf215546Sopenharmony_ci return VK_SUCCESS; 283bf215546Sopenharmony_ci} 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_cistatic VkResult 286bf215546Sopenharmony_ciwsi_win32_surface_get_present_rectangles(VkIcdSurfaceBase *surface, 287bf215546Sopenharmony_ci struct wsi_device *wsi_device, 288bf215546Sopenharmony_ci uint32_t* pRectCount, 289bf215546Sopenharmony_ci VkRect2D* pRects) 290bf215546Sopenharmony_ci{ 291bf215546Sopenharmony_ci VK_OUTARRAY_MAKE_TYPED(VkRect2D, out, pRects, pRectCount); 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ci vk_outarray_append_typed(VkRect2D, &out, rect) { 294bf215546Sopenharmony_ci /* We don't know a size so just return the usual "I don't know." */ 295bf215546Sopenharmony_ci *rect = (VkRect2D) { 296bf215546Sopenharmony_ci .offset = { 0, 0 }, 297bf215546Sopenharmony_ci .extent = { UINT32_MAX, UINT32_MAX }, 298bf215546Sopenharmony_ci }; 299bf215546Sopenharmony_ci } 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci return vk_outarray_status(&out); 302bf215546Sopenharmony_ci} 303bf215546Sopenharmony_ci 304bf215546Sopenharmony_cistatic VkResult 305bf215546Sopenharmony_ciwsi_win32_image_init(VkDevice device_h, 306bf215546Sopenharmony_ci struct wsi_win32_swapchain *chain, 307bf215546Sopenharmony_ci const VkSwapchainCreateInfoKHR *create_info, 308bf215546Sopenharmony_ci const VkAllocationCallbacks *allocator, 309bf215546Sopenharmony_ci struct wsi_win32_image *image) 310bf215546Sopenharmony_ci{ 311bf215546Sopenharmony_ci assert(chain->base.use_buffer_blit); 312bf215546Sopenharmony_ci VkResult result = wsi_create_image(&chain->base, &chain->base.image_info, 313bf215546Sopenharmony_ci &image->base); 314bf215546Sopenharmony_ci if (result != VK_SUCCESS) 315bf215546Sopenharmony_ci return result; 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_ci VkIcdSurfaceWin32 *win32_surface = (VkIcdSurfaceWin32 *)create_info->surface; 318bf215546Sopenharmony_ci chain->wnd = win32_surface->hwnd; 319bf215546Sopenharmony_ci chain->chain_dc = GetDC(chain->wnd); 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci image->dc = CreateCompatibleDC(chain->chain_dc); 322bf215546Sopenharmony_ci HBITMAP bmp = NULL; 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ci BITMAPINFO info = { 0 }; 325bf215546Sopenharmony_ci info.bmiHeader.biSize = sizeof(BITMAPINFO); 326bf215546Sopenharmony_ci info.bmiHeader.biWidth = create_info->imageExtent.width; 327bf215546Sopenharmony_ci info.bmiHeader.biHeight = -create_info->imageExtent.height; 328bf215546Sopenharmony_ci info.bmiHeader.biPlanes = 1; 329bf215546Sopenharmony_ci info.bmiHeader.biBitCount = 32; 330bf215546Sopenharmony_ci info.bmiHeader.biCompression = BI_RGB; 331bf215546Sopenharmony_ci 332bf215546Sopenharmony_ci bmp = CreateDIBSection(image->dc, &info, DIB_RGB_COLORS, &image->ppvBits, NULL, 0); 333bf215546Sopenharmony_ci assert(bmp && image->ppvBits); 334bf215546Sopenharmony_ci 335bf215546Sopenharmony_ci SelectObject(image->dc, bmp); 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_ci BITMAP header; 338bf215546Sopenharmony_ci int status = GetObject(bmp, sizeof(BITMAP), &header); 339bf215546Sopenharmony_ci (void)status; 340bf215546Sopenharmony_ci image->bmp_row_pitch = header.bmWidthBytes; 341bf215546Sopenharmony_ci image->bmp = bmp; 342bf215546Sopenharmony_ci image->chain = chain; 343bf215546Sopenharmony_ci 344bf215546Sopenharmony_ci return VK_SUCCESS; 345bf215546Sopenharmony_ci} 346bf215546Sopenharmony_ci 347bf215546Sopenharmony_cistatic void 348bf215546Sopenharmony_ciwsi_win32_image_finish(struct wsi_win32_swapchain *chain, 349bf215546Sopenharmony_ci const VkAllocationCallbacks *allocator, 350bf215546Sopenharmony_ci struct wsi_win32_image *image) 351bf215546Sopenharmony_ci{ 352bf215546Sopenharmony_ci DeleteDC(image->dc); 353bf215546Sopenharmony_ci if(image->bmp) 354bf215546Sopenharmony_ci DeleteObject(image->bmp); 355bf215546Sopenharmony_ci wsi_destroy_image(&chain->base, &image->base); 356bf215546Sopenharmony_ci} 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_cistatic VkResult 359bf215546Sopenharmony_ciwsi_win32_swapchain_destroy(struct wsi_swapchain *drv_chain, 360bf215546Sopenharmony_ci const VkAllocationCallbacks *allocator) 361bf215546Sopenharmony_ci{ 362bf215546Sopenharmony_ci struct wsi_win32_swapchain *chain = 363bf215546Sopenharmony_ci (struct wsi_win32_swapchain *) drv_chain; 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_ci for (uint32_t i = 0; i < chain->base.image_count; i++) 366bf215546Sopenharmony_ci wsi_win32_image_finish(chain, allocator, &chain->images[i]); 367bf215546Sopenharmony_ci 368bf215546Sopenharmony_ci DeleteDC(chain->chain_dc); 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci wsi_swapchain_finish(&chain->base); 371bf215546Sopenharmony_ci vk_free(allocator, chain); 372bf215546Sopenharmony_ci return VK_SUCCESS; 373bf215546Sopenharmony_ci} 374bf215546Sopenharmony_ci 375bf215546Sopenharmony_cistatic struct wsi_image * 376bf215546Sopenharmony_ciwsi_win32_get_wsi_image(struct wsi_swapchain *drv_chain, 377bf215546Sopenharmony_ci uint32_t image_index) 378bf215546Sopenharmony_ci{ 379bf215546Sopenharmony_ci struct wsi_win32_swapchain *chain = 380bf215546Sopenharmony_ci (struct wsi_win32_swapchain *) drv_chain; 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_ci return &chain->images[image_index].base; 383bf215546Sopenharmony_ci} 384bf215546Sopenharmony_ci 385bf215546Sopenharmony_cistatic VkResult 386bf215546Sopenharmony_ciwsi_win32_acquire_next_image(struct wsi_swapchain *drv_chain, 387bf215546Sopenharmony_ci const VkAcquireNextImageInfoKHR *info, 388bf215546Sopenharmony_ci uint32_t *image_index) 389bf215546Sopenharmony_ci{ 390bf215546Sopenharmony_ci struct wsi_win32_swapchain *chain = 391bf215546Sopenharmony_ci (struct wsi_win32_swapchain *)drv_chain; 392bf215546Sopenharmony_ci 393bf215546Sopenharmony_ci /* Bail early if the swapchain is broken */ 394bf215546Sopenharmony_ci if (chain->status != VK_SUCCESS) 395bf215546Sopenharmony_ci return chain->status; 396bf215546Sopenharmony_ci 397bf215546Sopenharmony_ci *image_index = 0; 398bf215546Sopenharmony_ci return VK_SUCCESS; 399bf215546Sopenharmony_ci} 400bf215546Sopenharmony_ci 401bf215546Sopenharmony_cistatic VkResult 402bf215546Sopenharmony_ciwsi_win32_queue_present(struct wsi_swapchain *drv_chain, 403bf215546Sopenharmony_ci uint32_t image_index, 404bf215546Sopenharmony_ci const VkPresentRegionKHR *damage) 405bf215546Sopenharmony_ci{ 406bf215546Sopenharmony_ci struct wsi_win32_swapchain *chain = (struct wsi_win32_swapchain *) drv_chain; 407bf215546Sopenharmony_ci assert(image_index < chain->base.image_count); 408bf215546Sopenharmony_ci struct wsi_win32_image *image = &chain->images[image_index]; 409bf215546Sopenharmony_ci 410bf215546Sopenharmony_ci assert(chain->base.use_buffer_blit); 411bf215546Sopenharmony_ci 412bf215546Sopenharmony_ci char *ptr = image->base.cpu_map; 413bf215546Sopenharmony_ci char *dptr = image->ppvBits; 414bf215546Sopenharmony_ci 415bf215546Sopenharmony_ci for (unsigned h = 0; h < chain->extent.height; h++) { 416bf215546Sopenharmony_ci memcpy(dptr, ptr, chain->extent.width * 4); 417bf215546Sopenharmony_ci dptr += image->bmp_row_pitch; 418bf215546Sopenharmony_ci ptr += image->base.row_pitches[0]; 419bf215546Sopenharmony_ci } 420bf215546Sopenharmony_ci if (!StretchBlt(chain->chain_dc, 0, 0, chain->extent.width, chain->extent.height, image->dc, 0, 0, chain->extent.width, chain->extent.height, SRCCOPY)) 421bf215546Sopenharmony_ci chain->status = VK_ERROR_MEMORY_MAP_FAILED; 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci return chain->status; 424bf215546Sopenharmony_ci} 425bf215546Sopenharmony_ci 426bf215546Sopenharmony_cistatic VkResult 427bf215546Sopenharmony_ciwsi_win32_surface_create_swapchain( 428bf215546Sopenharmony_ci VkIcdSurfaceBase *icd_surface, 429bf215546Sopenharmony_ci VkDevice device, 430bf215546Sopenharmony_ci struct wsi_device *wsi_device, 431bf215546Sopenharmony_ci const VkSwapchainCreateInfoKHR *create_info, 432bf215546Sopenharmony_ci const VkAllocationCallbacks *allocator, 433bf215546Sopenharmony_ci struct wsi_swapchain **swapchain_out) 434bf215546Sopenharmony_ci{ 435bf215546Sopenharmony_ci VkIcdSurfaceWin32 *surface = (VkIcdSurfaceWin32 *)icd_surface; 436bf215546Sopenharmony_ci struct wsi_win32 *wsi = 437bf215546Sopenharmony_ci (struct wsi_win32 *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_WIN32]; 438bf215546Sopenharmony_ci 439bf215546Sopenharmony_ci assert(create_info->sType == VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR); 440bf215546Sopenharmony_ci 441bf215546Sopenharmony_ci const unsigned num_images = create_info->minImageCount; 442bf215546Sopenharmony_ci struct wsi_win32_swapchain *chain; 443bf215546Sopenharmony_ci size_t size = sizeof(*chain) + num_images * sizeof(chain->images[0]); 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_ci chain = vk_zalloc(allocator, size, 446bf215546Sopenharmony_ci 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 447bf215546Sopenharmony_ci 448bf215546Sopenharmony_ci if (chain == NULL) 449bf215546Sopenharmony_ci return VK_ERROR_OUT_OF_HOST_MEMORY; 450bf215546Sopenharmony_ci 451bf215546Sopenharmony_ci VkResult result = wsi_swapchain_init(wsi_device, &chain->base, device, 452bf215546Sopenharmony_ci create_info, allocator, false); 453bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 454bf215546Sopenharmony_ci vk_free(allocator, chain); 455bf215546Sopenharmony_ci return result; 456bf215546Sopenharmony_ci } 457bf215546Sopenharmony_ci 458bf215546Sopenharmony_ci chain->base.destroy = wsi_win32_swapchain_destroy; 459bf215546Sopenharmony_ci chain->base.get_wsi_image = wsi_win32_get_wsi_image; 460bf215546Sopenharmony_ci chain->base.acquire_next_image = wsi_win32_acquire_next_image; 461bf215546Sopenharmony_ci chain->base.queue_present = wsi_win32_queue_present; 462bf215546Sopenharmony_ci chain->base.present_mode = wsi_swapchain_get_present_mode(wsi_device, create_info); 463bf215546Sopenharmony_ci chain->base.image_count = num_images; 464bf215546Sopenharmony_ci chain->extent = create_info->imageExtent; 465bf215546Sopenharmony_ci 466bf215546Sopenharmony_ci chain->wsi = wsi; 467bf215546Sopenharmony_ci chain->status = VK_SUCCESS; 468bf215546Sopenharmony_ci 469bf215546Sopenharmony_ci chain->surface = surface; 470bf215546Sopenharmony_ci 471bf215546Sopenharmony_ci assert(wsi_device->sw); 472bf215546Sopenharmony_ci chain->base.use_buffer_blit = true; 473bf215546Sopenharmony_ci 474bf215546Sopenharmony_ci result = wsi_configure_cpu_image(&chain->base, create_info, NULL /*alloc_shm*/, &chain->base.image_info); 475bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 476bf215546Sopenharmony_ci vk_free(allocator, chain); 477bf215546Sopenharmony_ci goto fail_init_images; 478bf215546Sopenharmony_ci } 479bf215546Sopenharmony_ci 480bf215546Sopenharmony_ci for (uint32_t image = 0; image < chain->base.image_count; image++) { 481bf215546Sopenharmony_ci result = wsi_win32_image_init(device, chain, 482bf215546Sopenharmony_ci create_info, allocator, 483bf215546Sopenharmony_ci &chain->images[image]); 484bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 485bf215546Sopenharmony_ci while (image > 0) { 486bf215546Sopenharmony_ci --image; 487bf215546Sopenharmony_ci wsi_win32_image_finish(chain, allocator, 488bf215546Sopenharmony_ci &chain->images[image]); 489bf215546Sopenharmony_ci } 490bf215546Sopenharmony_ci wsi_destroy_image_info(&chain->base, &chain->base.image_info); 491bf215546Sopenharmony_ci vk_free(allocator, chain); 492bf215546Sopenharmony_ci goto fail_init_images; 493bf215546Sopenharmony_ci } 494bf215546Sopenharmony_ci } 495bf215546Sopenharmony_ci 496bf215546Sopenharmony_ci *swapchain_out = &chain->base; 497bf215546Sopenharmony_ci 498bf215546Sopenharmony_ci return VK_SUCCESS; 499bf215546Sopenharmony_ci 500bf215546Sopenharmony_cifail_init_images: 501bf215546Sopenharmony_ci return result; 502bf215546Sopenharmony_ci} 503bf215546Sopenharmony_ci 504bf215546Sopenharmony_ci 505bf215546Sopenharmony_ciVkResult 506bf215546Sopenharmony_ciwsi_win32_init_wsi(struct wsi_device *wsi_device, 507bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc, 508bf215546Sopenharmony_ci VkPhysicalDevice physical_device) 509bf215546Sopenharmony_ci{ 510bf215546Sopenharmony_ci struct wsi_win32 *wsi; 511bf215546Sopenharmony_ci VkResult result; 512bf215546Sopenharmony_ci 513bf215546Sopenharmony_ci wsi = vk_alloc(alloc, sizeof(*wsi), 8, 514bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 515bf215546Sopenharmony_ci if (!wsi) { 516bf215546Sopenharmony_ci result = VK_ERROR_OUT_OF_HOST_MEMORY; 517bf215546Sopenharmony_ci goto fail; 518bf215546Sopenharmony_ci } 519bf215546Sopenharmony_ci 520bf215546Sopenharmony_ci wsi->physical_device = physical_device; 521bf215546Sopenharmony_ci wsi->alloc = alloc; 522bf215546Sopenharmony_ci wsi->wsi = wsi_device; 523bf215546Sopenharmony_ci 524bf215546Sopenharmony_ci wsi->base.get_support = wsi_win32_surface_get_support; 525bf215546Sopenharmony_ci wsi->base.get_capabilities2 = wsi_win32_surface_get_capabilities2; 526bf215546Sopenharmony_ci wsi->base.get_formats = wsi_win32_surface_get_formats; 527bf215546Sopenharmony_ci wsi->base.get_formats2 = wsi_win32_surface_get_formats2; 528bf215546Sopenharmony_ci wsi->base.get_present_modes = wsi_win32_surface_get_present_modes; 529bf215546Sopenharmony_ci wsi->base.get_present_rectangles = wsi_win32_surface_get_present_rectangles; 530bf215546Sopenharmony_ci wsi->base.create_swapchain = wsi_win32_surface_create_swapchain; 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci wsi_device->wsi[VK_ICD_WSI_PLATFORM_WIN32] = &wsi->base; 533bf215546Sopenharmony_ci 534bf215546Sopenharmony_ci return VK_SUCCESS; 535bf215546Sopenharmony_ci 536bf215546Sopenharmony_cifail: 537bf215546Sopenharmony_ci wsi_device->wsi[VK_ICD_WSI_PLATFORM_WIN32] = NULL; 538bf215546Sopenharmony_ci 539bf215546Sopenharmony_ci return result; 540bf215546Sopenharmony_ci} 541bf215546Sopenharmony_ci 542bf215546Sopenharmony_civoid 543bf215546Sopenharmony_ciwsi_win32_finish_wsi(struct wsi_device *wsi_device, 544bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc) 545bf215546Sopenharmony_ci{ 546bf215546Sopenharmony_ci struct wsi_win32 *wsi = 547bf215546Sopenharmony_ci (struct wsi_win32 *)wsi_device->wsi[VK_ICD_WSI_PLATFORM_WIN32]; 548bf215546Sopenharmony_ci if (!wsi) 549bf215546Sopenharmony_ci return; 550bf215546Sopenharmony_ci 551bf215546Sopenharmony_ci vk_free(alloc, wsi); 552bf215546Sopenharmony_ci} 553