From a29df71dd2e73ce4b9aa664b2a5aee64d19b3ea9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 15 May 2015 22:04:52 -0700 Subject: [PATCH] vk: Add WSI implementation --- include/vulkan/vk_wsi_lunarg.h | 197 +++++++++++++++++++++++ src/vulkan/Makefile.am | 10 +- src/vulkan/device.c | 44 ++++- src/vulkan/image.c | 30 +++- src/vulkan/private.h | 12 ++ src/vulkan/x11.c | 282 +++++++++++++++++++++++++++++++++ 6 files changed, 557 insertions(+), 18 deletions(-) create mode 100644 include/vulkan/vk_wsi_lunarg.h create mode 100644 src/vulkan/x11.c diff --git a/include/vulkan/vk_wsi_lunarg.h b/include/vulkan/vk_wsi_lunarg.h new file mode 100644 index 00000000000..84de8d2c6d1 --- /dev/null +++ b/include/vulkan/vk_wsi_lunarg.h @@ -0,0 +1,197 @@ +// +// File: vk_wsi_display.h +// +/* +** Copyright (c) 2014 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +#ifndef __VK_WSI_LUNARG_H__ +#define __VK_WSI_LUNARG_H__ + +#include "vulkan.h" + +#define VK_WSI_LUNARG_REVISION 3 +#define VK_WSI_LUNARG_EXTENSION_NUMBER 1 + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +// ------------------------------------------------------------------------------------------------ +// Objects + +VK_DEFINE_DISP_SUBCLASS_HANDLE(VkDisplayWSI, VkObject) +VK_DEFINE_DISP_SUBCLASS_HANDLE(VkSwapChainWSI, VkObject) + +// ------------------------------------------------------------------------------------------------ +// Enumeration constants + +#define VK_WSI_LUNARG_ENUM(type,id) ((type)(VK_WSI_LUNARG_EXTENSION_NUMBER * -1000 + (id))) + +// Extend VkPhysicalDeviceInfoType enum with extension specific constants +#define VK_PHYSICAL_DEVICE_INFO_TYPE_DISPLAY_PROPERTIES_WSI VK_WSI_LUNARG_ENUM(VkPhysicalDeviceInfoType, 0) +#define VK_PHYSICAL_DEVICE_INFO_TYPE_QUEUE_PRESENT_PROPERTIES_WSI VK_WSI_LUNARG_ENUM(VkPhysicalDeviceInfoType, 1) + +// Extend VkStructureType enum with extension specific constants +#define VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI VK_WSI_LUNARG_ENUM(VkStructureType, 0) +#define VK_STRUCTURE_TYPE_PRESENT_INFO_WSI VK_WSI_LUNARG_ENUM(VkStructureType, 1) + +// Extend VkImageLayout enum with extension specific constants +#define VK_IMAGE_LAYOUT_PRESENT_SOURCE_WSI VK_WSI_LUNARG_ENUM(VkImageLayout, 0) + +// Extend VkObjectType enum for new objects +#define VK_OBJECT_TYPE_DISPLAY_WSI VK_WSI_LUNARG_ENUM(VkObjectType, 0) +#define VK_OBJECT_TYPE_SWAP_CHAIN_WSI VK_WSI_LUNARG_ENUM(VkObjectType, 1) + +// ------------------------------------------------------------------------------------------------ +// Enumerations + +typedef enum VkDisplayInfoTypeWSI_ +{ + // Info type for vkGetDisplayInfo() + VK_DISPLAY_INFO_TYPE_FORMAT_PROPERTIES_WSI = 0x00000003, // Return the VkFormat(s) supported for swap chains with the display + + VK_ENUM_RANGE(DISPLAY_INFO_TYPE, FORMAT_PROPERTIES_WSI, FORMAT_PROPERTIES_WSI) +} VkDisplayInfoTypeWSI; + +typedef enum VkSwapChainInfoTypeWSI_ +{ + // Info type for vkGetSwapChainInfo() + VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI = 0x00000000, // Return information about the persistent images of the swapchain + + VK_ENUM_RANGE(SWAP_CHAIN_INFO_TYPE, PERSISTENT_IMAGES_WSI, PERSISTENT_IMAGES_WSI) +} VkSwapChainInfoTypeWSI; + +// ------------------------------------------------------------------------------------------------ +// Flags + +typedef VkFlags VkSwapModeFlagsWSI; +typedef enum VkSwapModeFlagBitsWSI_ +{ + VK_SWAP_MODE_FLIP_BIT_WSI = VK_BIT(0), + VK_SWAP_MODE_BLIT_BIT_WSI = VK_BIT(1), +} VkSwapModeFlagBitsWSI; + +// ------------------------------------------------------------------------------------------------ +// Structures + +typedef struct VkDisplayPropertiesWSI_ +{ + VkDisplayWSI display; // Handle of the display object + VkExtent2D physicalResolution; // Max resolution for CRT? +} VkDisplayPropertiesWSI; + +typedef struct VkDisplayFormatPropertiesWSI_ +{ + VkFormat swapChainFormat; // Format of the images of the swap chain +} VkDisplayFormatPropertiesWSI; + +typedef struct VkSwapChainCreateInfoWSI_ +{ + VkStructureType sType; // Must be VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI + const void* pNext; // Pointer to next structure + + // TBD: It is not yet clear what the use will be for the following two + // values. It seems to be needed for more-global window-system handles + // (e.g. X11 display). If not needed for the SDK, we will drop it from + // this extension, and from a future version of this header. + const void* pNativeWindowSystemHandle; // Pointer to native window system handle + const void* pNativeWindowHandle; // Pointer to native window handle + + uint32_t displayCount; // Number of displays the swap chain is created for + const VkDisplayWSI* pDisplays; // displayCount number of display objects the swap chain is created for + + uint32_t imageCount; // Number of images in the swap chain + + VkFormat imageFormat; // Format of the images of the swap chain + VkExtent2D imageExtent; // Width and height of the images of the swap chain + uint32_t imageArraySize; // Number of layers of the images of the swap chain (needed for multi-view rendering) + VkFlags imageUsageFlags; // Usage flags for the images of the swap chain (see VkImageUsageFlags) + + VkFlags swapModeFlags; // Allowed swap modes (see VkSwapModeFlagsWSI) +} VkSwapChainCreateInfoWSI; + +typedef struct VkSwapChainImageInfoWSI_ +{ + VkImage image; // Persistent swap chain image handle + VkDeviceMemory memory; // Persistent swap chain image's memory handle +} VkSwapChainImageInfoWSI; + +typedef struct VkPhysicalDeviceQueuePresentPropertiesWSI_ +{ + bool32_t supportsPresent; // Tells whether the queue supports presenting +} VkPhysicalDeviceQueuePresentPropertiesWSI; + +typedef struct VkPresentInfoWSI_ +{ + VkStructureType sType; // Must be VK_STRUCTURE_TYPE_PRESENT_INFO_WSI + const void* pNext; // Pointer to next structure + VkImage image; // Image to present + uint32_t flipInterval; // Flip interval +} VkPresentInfoWSI; + +// ------------------------------------------------------------------------------------------------ +// Function types + +typedef VkResult (VKAPI *PFN_vkGetDisplayInfoWSI)(VkDisplayWSI display, VkDisplayInfoTypeWSI infoType, size_t* pDataSize, void* pData); +typedef VkResult (VKAPI *PFN_vkCreateSwapChainWSI)(VkDevice device, const VkSwapChainCreateInfoWSI* pCreateInfo, VkSwapChainWSI* pSwapChain); +typedef VkResult (VKAPI *PFN_vkDestroySwapChainWSI)(VkSwapChainWSI swapChain); +typedef VkResult (VKAPI *PFN_vkGetSwapChainInfoWSI)(VkSwapChainWSI swapChain, VkSwapChainInfoTypeWSI infoType, size_t* pDataSize, void* pData); +typedef VkResult (VKAPI *PFN_vkQueuePresentWSI)(VkQueue queue, const VkPresentInfoWSI* pPresentInfo); + +// ------------------------------------------------------------------------------------------------ +// Function prototypes + +#ifdef VK_PROTOTYPES + +VkResult VKAPI vkGetDisplayInfoWSI( + VkDisplayWSI display, + VkDisplayInfoTypeWSI infoType, + size_t* pDataSize, + void* pData); + +VkResult VKAPI vkCreateSwapChainWSI( + VkDevice device, + const VkSwapChainCreateInfoWSI* pCreateInfo, + VkSwapChainWSI* pSwapChain); + +VkResult VKAPI vkDestroySwapChainWSI( + VkSwapChainWSI swapChain); + +VkResult VKAPI vkGetSwapChainInfoWSI( + VkSwapChainWSI swapChain, + VkSwapChainInfoTypeWSI infoType, + size_t* pDataSize, + void* pData); + +VkResult VKAPI vkQueuePresentWSI( + VkQueue queue, + const VkPresentInfoWSI* pPresentInfo); + +#endif // VK_PROTOTYPES + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // __VK_WSI_LUNARG_H__ diff --git a/src/vulkan/Makefile.am b/src/vulkan/Makefile.am index 8c05c5139fc..404af61bcb1 100644 --- a/src/vulkan/Makefile.am +++ b/src/vulkan/Makefile.am @@ -22,10 +22,11 @@ vulkan_includedir = $(includedir)/vulkan -vulkan_include_HEADERS = \ - $(top_srcdir)/include/vulkan/vk_platform.h \ - $(top_srcdir)/include/vulkan/vulkan.h \ - $(top_srcdir)/include/vulkan/vulkan_intel.h +vulkan_include_HEADERS = \ + $(top_srcdir)/include/vulkan/vk_platform.h \ + $(top_srcdir)/include/vulkan/vulkan.h \ + $(top_srcdir)/include/vulkan/vulkan_intel.h \ + $(top_srcdir)/include/vulkan/vk_wsi_lunarg.h lib_LTLIBRARIES = libvulkan.la @@ -64,6 +65,7 @@ libvulkan_la_SOURCES = \ intel.c \ entrypoints.c \ entrypoints.h \ + x11.c \ formats.c \ compiler.cpp diff --git a/src/vulkan/device.c b/src/vulkan/device.c index cad85bf5ec3..7cce0a1a394 100644 --- a/src/vulkan/device.c +++ b/src/vulkan/device.c @@ -187,9 +187,10 @@ VkResult anv_GetPhysicalDeviceInfo( VkPhysicalDevicePerformance *performance; VkPhysicalDeviceQueueProperties *queue_properties; VkPhysicalDeviceMemoryProperties *memory_properties; + VkDisplayPropertiesWSI *display_properties; uint64_t ns_per_tick = 80; - switch (infoType) { + switch ((uint32_t) infoType) { case VK_PHYSICAL_DEVICE_INFO_TYPE_PROPERTIES: properties = pData; @@ -252,6 +253,23 @@ VkResult anv_GetPhysicalDeviceInfo( memory_properties->supportsPinning = false; return VK_SUCCESS; + case VK_PHYSICAL_DEVICE_INFO_TYPE_DISPLAY_PROPERTIES_WSI: + anv_finishme("VK_PHYSICAL_DEVICE_INFO_TYPE_DISPLAY_PROPERTIES_WSI"); + + *pDataSize = sizeof(*display_properties); + if (pData == NULL) + return VK_SUCCESS; + + display_properties = pData; + display_properties->display = 0; + display_properties->physicalResolution = (VkExtent2D) { 0, 0 }; + return VK_SUCCESS; + + case VK_PHYSICAL_DEVICE_INFO_TYPE_QUEUE_PRESENT_PROPERTIES_WSI: + anv_finishme("VK_PHYSICAL_DEVICE_INFO_TYPE_QUEUE_PRESENT_PROPERTIES_WSI"); + return VK_SUCCESS; + + default: return VK_UNSUPPORTED; } @@ -383,18 +401,28 @@ VkResult anv_GetGlobalExtensionInfo( size_t* pDataSize, void* pData) { - uint32_t *count; + static const VkExtensionProperties extensions[] = { + { + .extName = "VK_WSI_LunarG", + .version = 3 + } + }; + uint32_t count = ARRAY_SIZE(extensions); switch (infoType) { case VK_EXTENSION_INFO_TYPE_COUNT: - count = pData; - assert(*pDataSize == 4); - *count = 0; + memcpy(pData, &count, sizeof(count)); + *pDataSize = sizeof(count); return VK_SUCCESS; - + case VK_EXTENSION_INFO_TYPE_PROPERTIES: - return vk_error(VK_ERROR_INVALID_EXTENSION); - + if (extensionIndex >= count) + return vk_error(VK_ERROR_INVALID_EXTENSION); + + memcpy(pData, &extensions[extensionIndex], sizeof(extensions[0])); + *pDataSize = sizeof(extensions[0]); + return VK_SUCCESS; + default: return VK_UNSUPPORTED; } diff --git a/src/vulkan/image.c b/src/vulkan/image.c index cf658e969da..a7dc243b2a2 100644 --- a/src/vulkan/image.c +++ b/src/vulkan/image.c @@ -41,9 +41,10 @@ static const struct anv_tile_mode_info { [WMAJOR] = { 128, 32 } }; -VkResult anv_CreateImage( +VkResult anv_image_create( VkDevice _device, const VkImageCreateInfo* pCreateInfo, + const struct anv_image_create_info * extra, VkImage* pImage) { struct anv_device *device = (struct anv_device *) _device; @@ -63,6 +64,7 @@ VkResult anv_CreateImage( image->type = pCreateInfo->imageType; image->format = pCreateInfo->format; image->extent = pCreateInfo->extent; + image->swap_chain = NULL; assert(image->extent.width > 0); assert(image->extent.height > 0); @@ -71,20 +73,28 @@ VkResult anv_CreateImage( switch (pCreateInfo->tiling) { case VK_IMAGE_TILING_LINEAR: image->tile_mode = LINEAR; - /* Linear depth buffers must be 64 byte aligned, which is the strictest - * requirement for all kinds of linear surfaces. - */ - image->alignment = 64; break; case VK_IMAGE_TILING_OPTIMAL: image->tile_mode = YMAJOR; - image->alignment = 4096; break; default: break; } + if (extra) + image->tile_mode = extra->tile_mode; + + if (image->tile_mode == LINEAR) { + /* Linear depth buffers must be 64 byte aligned, which is the strictest + * requirement for all kinds of linear surfaces. + */ + image->alignment = 64; + } else { + image->alignment = 4096; + } + format = anv_format_for_vk_format(pCreateInfo->format); + assert(format->cpp > 0); image->stride = ALIGN_I32(image->extent.width * format->cpp, tile_mode_info[image->tile_mode].tile_width); aligned_height = ALIGN_I32(image->extent.height, @@ -96,6 +106,14 @@ VkResult anv_CreateImage( return VK_SUCCESS; } +VkResult anv_CreateImage( + VkDevice device, + const VkImageCreateInfo* pCreateInfo, + VkImage* pImage) +{ + return anv_image_create(device, pCreateInfo, NULL, pImage); +} + VkResult anv_GetImageSubresourceInfo( VkDevice device, VkImage image, diff --git a/src/vulkan/private.h b/src/vulkan/private.h index e4534f26e8c..f15856387d8 100644 --- a/src/vulkan/private.h +++ b/src/vulkan/private.h @@ -36,6 +36,7 @@ #define VK_PROTOTYPES #include #include +#include #include "entrypoints.h" @@ -661,6 +662,8 @@ struct anv_image { /* Set when bound */ struct anv_bo * bo; VkDeviceSize offset; + + struct anv_swap_chain * swap_chain; }; struct anv_surface_view { @@ -671,6 +674,15 @@ struct anv_surface_view { VkFormat format; }; +struct anv_image_create_info { + uint32_t tile_mode; +}; + +VkResult anv_image_create(VkDevice _device, + const VkImageCreateInfo *pCreateInfo, + const struct anv_image_create_info *extra, + VkImage *pImage); + void anv_image_view_init(struct anv_surface_view *view, struct anv_device *device, const VkImageViewCreateInfo* pCreateInfo, diff --git a/src/vulkan/x11.c b/src/vulkan/x11.c new file mode 100644 index 00000000000..898aba056c7 --- /dev/null +++ b/src/vulkan/x11.c @@ -0,0 +1,282 @@ +/* + * Copyright © 2015 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "private.h" + +#include +#include +#include + +static const VkFormat formats[] = { + VK_FORMAT_B5G6R5_UNORM, + VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_B8G8R8A8_SRGB, +}; + +VkResult anv_GetDisplayInfoWSI( + VkDisplayWSI display, + VkDisplayInfoTypeWSI infoType, + size_t* pDataSize, + void* pData) +{ + VkDisplayFormatPropertiesWSI *properties = pData; + size_t size; + + if (pDataSize == NULL) + return VK_ERROR_INVALID_POINTER; + + switch (infoType) { + case VK_DISPLAY_INFO_TYPE_FORMAT_PROPERTIES_WSI: + size = sizeof(properties[0]) * ARRAY_SIZE(formats); + if (pData && *pDataSize < size) + return vk_error(VK_ERROR_INVALID_VALUE); + + *pDataSize = size; + for (uint32_t i = 0; i < ARRAY_SIZE(formats); i++) + properties[i].swapChainFormat = formats[i]; + + return VK_SUCCESS; + + default: + return VK_UNSUPPORTED; + } +} + +struct anv_swap_chain { + struct anv_device * device; + xcb_connection_t * conn; + xcb_window_t window; + xcb_gc_t gc; + VkExtent2D extent; + uint32_t count; + struct { + struct anv_image * image; + struct anv_device_memory * memory; + xcb_pixmap_t pixmap; + } images[0]; +}; + +VkResult anv_CreateSwapChainWSI( + VkDevice _device, + const VkSwapChainCreateInfoWSI* pCreateInfo, + VkSwapChainWSI* pSwapChain) +{ + struct anv_device *device = (struct anv_device *) _device; + struct anv_swap_chain *chain; + xcb_void_cookie_t cookie; + VkResult result; + size_t size; + int ret; + + assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI); + + size = sizeof(*chain) + pCreateInfo->imageCount * sizeof(chain->images[0]); + chain = anv_device_alloc(device, size, 8, + VK_SYSTEM_ALLOC_TYPE_API_OBJECT); + if (chain == NULL) + return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + + chain->device = device; + chain->conn = (xcb_connection_t *) pCreateInfo->pNativeWindowSystemHandle; + chain->window = (xcb_window_t) (uintptr_t) pCreateInfo->pNativeWindowHandle; + chain->count = pCreateInfo->imageCount; + chain->extent = pCreateInfo->imageExtent; + + for (uint32_t i = 0; i < chain->count; i++) { + struct anv_image *image; + struct anv_device_memory *memory; + + anv_image_create((VkDevice) device, + &(VkImageCreateInfo) { + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .imageType = VK_IMAGE_TYPE_2D, + .format = pCreateInfo->imageFormat, + .extent = { + .width = pCreateInfo->imageExtent.width, + .height = pCreateInfo->imageExtent.height, + .depth = 1 + }, + .mipLevels = 1, + .arraySize = 1, + .samples = 1, + /* FIXME: Need a way to use X tiling to allow scanout */ + .tiling = VK_IMAGE_TILING_OPTIMAL, + .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + .flags = 0, + }, + &(struct anv_image_create_info) { + .tile_mode = XMAJOR + }, + (VkImage *) &image); + + anv_AllocMemory((VkDevice) device, + &(VkMemoryAllocInfo) { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO, + .allocationSize = image->size, + }, + (VkDeviceMemory *) &memory); + + anv_QueueBindObjectMemory(VK_NULL_HANDLE, + VK_OBJECT_TYPE_IMAGE, + (VkImage) image, 0, + (VkDeviceMemory) memory, 0); + + ret = anv_gem_set_tiling(device, memory->bo.gem_handle, + image->stride, I915_TILING_X); + if (ret) { + result = vk_error(VK_ERROR_UNKNOWN); + goto fail; + } + + int fd = anv_gem_handle_to_fd(device, memory->bo.gem_handle); + if (fd == -1) { + result = vk_error(VK_ERROR_UNKNOWN); + goto fail; + } + + uint32_t bpp = 32; + uint32_t depth = 24; + xcb_pixmap_t pixmap = xcb_generate_id(chain->conn); + + cookie = + xcb_dri3_pixmap_from_buffer_checked(chain->conn, + pixmap, + chain->window, + image->size, + pCreateInfo->imageExtent.width, + pCreateInfo->imageExtent.height, + image->stride, + depth, bpp, fd); + + chain->images[i].image = image; + chain->images[i].memory = memory; + chain->images[i].pixmap = pixmap; + image->swap_chain = chain; + + xcb_discard_reply(chain->conn, cookie.sequence); + } + + chain->gc = xcb_generate_id(chain->conn); + if (!chain->gc) { + result = vk_error(VK_ERROR_UNKNOWN); + goto fail; + } + + cookie = xcb_create_gc(chain->conn, + chain->gc, + chain->window, + XCB_GC_GRAPHICS_EXPOSURES, + (uint32_t []) { 0 }); + xcb_discard_reply(chain->conn, cookie.sequence); + + *pSwapChain = (VkSwapChainWSI) chain; + + return VK_SUCCESS; + + fail: + return result; +} + +VkResult anv_DestroySwapChainWSI( + VkSwapChainWSI swapChain) +{ + struct anv_swap_chain *chain = (struct anv_swap_chain *) swapChain; + struct anv_device *device = chain->device; + + anv_device_free(device, chain); + + return VK_SUCCESS; +} + +VkResult anv_GetSwapChainInfoWSI( + VkSwapChainWSI swapChain, + VkSwapChainInfoTypeWSI infoType, + size_t* pDataSize, + void* pData) +{ + struct anv_swap_chain *chain = (struct anv_swap_chain *) swapChain; + VkSwapChainImageInfoWSI *images; + size_t size; + + switch (infoType) { + case VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI: + size = sizeof(*images) * chain->count; + if (pData && *pDataSize < size) + return VK_ERROR_INVALID_VALUE; + + *pDataSize = size; + if (!pData) + return VK_SUCCESS; + + images = pData; + for (uint32_t i = 0; i < chain->count; i++) { + images[i].image = (VkImage) chain->images[i].image; + images[i].memory = (VkDeviceMemory) chain->images[i].memory; + } + + return VK_SUCCESS; + + default: + return VK_UNSUPPORTED; + } +} + +VkResult anv_QueuePresentWSI( + VkQueue queue_, + const VkPresentInfoWSI* pPresentInfo) +{ + struct anv_image *image = (struct anv_image *) pPresentInfo->image; + struct anv_swap_chain *chain = image->swap_chain; + xcb_void_cookie_t cookie; + xcb_pixmap_t pixmap; + + assert(pPresentInfo->sType == VK_STRUCTURE_TYPE_PRESENT_INFO_WSI); + + if (chain == NULL) + return vk_error(VK_ERROR_INVALID_VALUE); + + pixmap = XCB_NONE; + for (uint32_t i = 0; i < chain->count; i++) { + if ((VkImage) chain->images[i].image == pPresentInfo->image) { + pixmap = chain->images[i].pixmap; + break; + } + } + + if (pixmap == XCB_NONE) + return vk_error(VK_ERROR_INVALID_VALUE); + + cookie = xcb_copy_area(chain->conn, + pixmap, + chain->window, + chain->gc, + 0, 0, + 0, 0, + chain->extent.width, + chain->extent.height); + xcb_discard_reply(chain->conn, cookie.sequence); + + xcb_flush(chain->conn); + + return VK_SUCCESS; +} -- 2.30.2