diff options
author | Dave Airlie <[email protected]> | 2016-10-14 07:49:34 +0100 |
---|---|---|
committer | Dave Airlie <[email protected]> | 2016-10-19 10:15:43 +1000 |
commit | 6c3bd1cdb3c60a0140b57a2064e02f5869b0f9bc (patch) | |
tree | 3e59e634ae3fdfce6944737431db5584db2c84b0 /src | |
parent | 3f7ef2488938d31b5ead043891fadc3cee4c6f05 (diff) |
radv: port to common wsi codebase
This drops all the radv WSI code in favour of using
the new shared code that was ported from anv
This regresses Talos for now, Jason has pointed out
the bug is in Talos and we should wait for them to fix it.
Reviewed-by: Jason Ekstrand <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/amd/vulkan/Makefile.am | 2 | ||||
-rw-r--r-- | src/amd/vulkan/Makefile.sources | 1 | ||||
-rw-r--r-- | src/amd/vulkan/radv_private.h | 5 | ||||
-rw-r--r-- | src/amd/vulkan/radv_wsi.c | 176 | ||||
-rw-r--r-- | src/amd/vulkan/radv_wsi.h | 81 | ||||
-rw-r--r-- | src/amd/vulkan/radv_wsi_wayland.c | 860 | ||||
-rw-r--r-- | src/amd/vulkan/radv_wsi_x11.c | 951 |
7 files changed, 216 insertions, 1860 deletions
diff --git a/src/amd/vulkan/Makefile.am b/src/amd/vulkan/Makefile.am index e2f5c029a07..44d2a6660bc 100644 --- a/src/amd/vulkan/Makefile.am +++ b/src/amd/vulkan/Makefile.am @@ -38,6 +38,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/include \ -I$(top_builddir)/src \ -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/vulkan/wsi \ -I$(top_srcdir)/src/amd \ -I$(top_srcdir)/src/amd/common \ -I$(top_builddir)/src/compiler \ @@ -93,6 +94,7 @@ libvulkan_common_la_SOURCES = $(VULKAN_SOURCES) VULKAN_LIB_DEPS += \ libvulkan_common.la \ + $(top_builddir)/src/vulkan/wsi/libvulkan_wsi.la \ $(top_builddir)/src/amd/common/libamd_common.la \ $(top_builddir)/src/amd/addrlib/libamdgpu_addrlib.la \ $(top_builddir)/src/compiler/nir/libnir.la \ diff --git a/src/amd/vulkan/Makefile.sources b/src/amd/vulkan/Makefile.sources index a8857e90f34..d163b980749 100644 --- a/src/amd/vulkan/Makefile.sources +++ b/src/amd/vulkan/Makefile.sources @@ -59,7 +59,6 @@ VULKAN_FILES := \ radv_util.c \ radv_util.h \ radv_wsi.c \ - radv_wsi.h \ si_cmd_buffer.c \ vk_format_table.c \ vk_format.h \ diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index dd89efae17f..caf27f2c2de 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -70,6 +70,7 @@ typedef uint32_t xcb_window_t; #include "radv_entrypoints.h" +#include "wsi_common.h" #define MAX_VBS 32 #define MAX_VERTEX_ATTRIBS 32 @@ -242,8 +243,6 @@ void *radv_lookup_entrypoint(const char *name); extern struct radv_dispatch_table dtable; -#define VK_ICD_WSI_PLATFORM_MAX 5 - struct radv_physical_device { VK_LOADER_DATA _loader_data; @@ -259,7 +258,7 @@ struct radv_physical_device { uint32_t pci_vendor_id; uint32_t pci_device_id; - struct radv_wsi_interface * wsi[VK_ICD_WSI_PLATFORM_MAX]; + struct wsi_device wsi_device; }; struct radv_instance { diff --git a/src/amd/vulkan/radv_wsi.c b/src/amd/vulkan/radv_wsi.c index 1a0171d8c9f..ba5c37ba268 100644 --- a/src/amd/vulkan/radv_wsi.c +++ b/src/amd/vulkan/radv_wsi.c @@ -23,27 +23,33 @@ * IN THE SOFTWARE. */ -#include "radv_wsi.h" +#include "radv_private.h" +#include "wsi_common.h" +static const struct wsi_callbacks wsi_cbs = { + .get_phys_device_format_properties = radv_GetPhysicalDeviceFormatProperties, +}; VkResult radv_init_wsi(struct radv_physical_device *physical_device) { VkResult result; - memset(physical_device->wsi, 0, sizeof(physical_device->wsi)); + memset(physical_device->wsi_device.wsi, 0, sizeof(physical_device->wsi_device.wsi)); #ifdef VK_USE_PLATFORM_XCB_KHR - result = radv_x11_init_wsi(physical_device); + result = wsi_x11_init_wsi(&physical_device->wsi_device, &physical_device->instance->alloc); if (result != VK_SUCCESS) return result; #endif #ifdef VK_USE_PLATFORM_WAYLAND_KHR - result = radv_wl_init_wsi(physical_device); + result = wsi_wl_init_wsi(&physical_device->wsi_device, &physical_device->instance->alloc, + radv_physical_device_to_handle(physical_device), + &wsi_cbs); if (result != VK_SUCCESS) { #ifdef VK_USE_PLATFORM_XCB_KHR - radv_x11_finish_wsi(physical_device); + wsi_x11_finish_wsi(&physical_device->wsi_device, &physical_device->instance->alloc); #endif return result; } @@ -56,10 +62,10 @@ void radv_finish_wsi(struct radv_physical_device *physical_device) { #ifdef VK_USE_PLATFORM_WAYLAND_KHR - radv_wl_finish_wsi(physical_device); + wsi_wl_finish_wsi(&physical_device->wsi_device, &physical_device->instance->alloc); #endif #ifdef VK_USE_PLATFORM_XCB_KHR - radv_x11_finish_wsi(physical_device); + wsi_x11_finish_wsi(&physical_device->wsi_device, &physical_device->instance->alloc); #endif } @@ -82,9 +88,11 @@ VkResult radv_GetPhysicalDeviceSurfaceSupportKHR( { RADV_FROM_HANDLE(radv_physical_device, device, physicalDevice); RADV_FROM_HANDLE(_VkIcdSurfaceBase, surface, _surface); - struct radv_wsi_interface *iface = device->wsi[surface->platform]; + struct wsi_interface *iface = device->wsi_device.wsi[surface->platform]; - return iface->get_support(surface, device, queueFamilyIndex, pSupported); + return iface->get_support(surface, &device->wsi_device, + &device->instance->alloc, + queueFamilyIndex, pSupported); } VkResult radv_GetPhysicalDeviceSurfaceCapabilitiesKHR( @@ -94,9 +102,9 @@ VkResult radv_GetPhysicalDeviceSurfaceCapabilitiesKHR( { RADV_FROM_HANDLE(radv_physical_device, device, physicalDevice); RADV_FROM_HANDLE(_VkIcdSurfaceBase, surface, _surface); - struct radv_wsi_interface *iface = device->wsi[surface->platform]; + struct wsi_interface *iface = device->wsi_device.wsi[surface->platform]; - return iface->get_capabilities(surface, device, pSurfaceCapabilities); + return iface->get_capabilities(surface, pSurfaceCapabilities); } VkResult radv_GetPhysicalDeviceSurfaceFormatsKHR( @@ -107,9 +115,9 @@ VkResult radv_GetPhysicalDeviceSurfaceFormatsKHR( { RADV_FROM_HANDLE(radv_physical_device, device, physicalDevice); RADV_FROM_HANDLE(_VkIcdSurfaceBase, surface, _surface); - struct radv_wsi_interface *iface = device->wsi[surface->platform]; + struct wsi_interface *iface = device->wsi_device.wsi[surface->platform]; - return iface->get_formats(surface, device, pSurfaceFormatCount, + return iface->get_formats(surface, &device->wsi_device, pSurfaceFormatCount, pSurfaceFormats); } @@ -121,12 +129,119 @@ VkResult radv_GetPhysicalDeviceSurfacePresentModesKHR( { RADV_FROM_HANDLE(radv_physical_device, device, physicalDevice); RADV_FROM_HANDLE(_VkIcdSurfaceBase, surface, _surface); - struct radv_wsi_interface *iface = device->wsi[surface->platform]; + struct wsi_interface *iface = device->wsi_device.wsi[surface->platform]; - return iface->get_present_modes(surface, device, pPresentModeCount, + return iface->get_present_modes(surface, pPresentModeCount, pPresentModes); } +static VkResult +radv_wsi_image_create(VkDevice device_h, + const VkSwapchainCreateInfoKHR *pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkImage *image_p, + VkDeviceMemory *memory_p, + uint32_t *size, + uint32_t *offset, + uint32_t *row_pitch, int *fd_p) +{ + struct radv_device *device = radv_device_from_handle(device_h); + VkResult result = VK_SUCCESS; + struct radeon_surf *surface; + VkImage image_h; + struct radv_image *image; + bool bret; + int fd; + + result = radv_image_create(device_h, + &(struct radv_image_create_info) { + .vk_info = + &(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, + .arrayLayers = 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, + }, + .scanout = true}, + NULL, + &image_h); + if (result != VK_SUCCESS) + return result; + + image = radv_image_from_handle(image_h); + + VkDeviceMemory memory_h; + struct radv_device_memory *memory; + result = radv_AllocateMemory(device_h, + &(VkMemoryAllocateInfo) { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .allocationSize = image->size, + .memoryTypeIndex = 0, + }, + NULL /* XXX: pAllocator */, + &memory_h); + if (result != VK_SUCCESS) + goto fail_create_image; + + memory = radv_device_memory_from_handle(memory_h); + + radv_BindImageMemory(VK_NULL_HANDLE, image_h, memory_h, 0); + + bret = device->ws->buffer_get_fd(device->ws, + memory->bo, &fd); + if (bret == false) + goto fail_alloc_memory; + + { + struct radeon_bo_metadata metadata; + radv_init_metadata(device, image, &metadata); + device->ws->buffer_set_metadata(memory->bo, &metadata); + } + surface = &image->surface; + + *image_p = image_h; + *memory_p = memory_h; + *fd_p = fd; + *size = image->size; + *offset = image->offset; + *row_pitch = surface->level[0].pitch_bytes; + return VK_SUCCESS; + fail_alloc_memory: + radv_FreeMemory(device_h, memory_h, pAllocator); + +fail_create_image: + radv_DestroyImage(device_h, image_h, pAllocator); + + return result; +} + +static void +radv_wsi_image_free(VkDevice device, + const VkAllocationCallbacks* pAllocator, + VkImage image_h, + VkDeviceMemory memory_h) +{ + radv_DestroyImage(device, image_h, pAllocator); + + radv_FreeMemory(device, memory_h, pAllocator); +} + +static const struct wsi_image_fns radv_wsi_image_fns = { + .create_wsi_image = radv_wsi_image_create, + .free_wsi_image = radv_wsi_image_free, +}; + VkResult radv_CreateSwapchainKHR( VkDevice _device, const VkSwapchainCreateInfoKHR* pCreateInfo, @@ -135,12 +250,19 @@ VkResult radv_CreateSwapchainKHR( { RADV_FROM_HANDLE(radv_device, device, _device); RADV_FROM_HANDLE(_VkIcdSurfaceBase, surface, pCreateInfo->surface); - struct radv_wsi_interface *iface = - device->instance->physicalDevice.wsi[surface->platform]; - struct radv_swapchain *swapchain; - - VkResult result = iface->create_swapchain(surface, device, pCreateInfo, - pAllocator, &swapchain); + struct wsi_interface *iface = + device->instance->physicalDevice.wsi_device.wsi[surface->platform]; + struct wsi_swapchain *swapchain; + const VkAllocationCallbacks *alloc; + if (pAllocator) + alloc = pAllocator; + else + alloc = &device->alloc; + VkResult result = iface->create_swapchain(surface, _device, + &device->instance->physicalDevice.wsi_device, + pCreateInfo, + alloc, &radv_wsi_image_fns, + &swapchain); if (result != VK_SUCCESS) return result; @@ -152,7 +274,7 @@ VkResult radv_CreateSwapchainKHR( for (unsigned i = 0; i < ARRAY_SIZE(swapchain->fences); i++) swapchain->fences[i] = VK_NULL_HANDLE; - *pSwapchain = radv_swapchain_to_handle(swapchain); + *pSwapchain = wsi_swapchain_to_handle(swapchain); return VK_SUCCESS; } @@ -162,7 +284,7 @@ void radv_DestroySwapchainKHR( VkSwapchainKHR _swapchain, const VkAllocationCallbacks* pAllocator) { - RADV_FROM_HANDLE(radv_swapchain, swapchain, _swapchain); + RADV_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain); for (unsigned i = 0; i < ARRAY_SIZE(swapchain->fences); i++) { if (swapchain->fences[i] != VK_NULL_HANDLE) @@ -178,7 +300,7 @@ VkResult radv_GetSwapchainImagesKHR( uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages) { - RADV_FROM_HANDLE(radv_swapchain, swapchain, _swapchain); + RADV_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain); return swapchain->get_images(swapchain, pSwapchainImageCount, pSwapchainImages); @@ -192,7 +314,7 @@ VkResult radv_AcquireNextImageKHR( VkFence fence, uint32_t* pImageIndex) { - RADV_FROM_HANDLE(radv_swapchain, swapchain, _swapchain); + RADV_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain); return swapchain->acquire_next_image(swapchain, timeout, semaphore, pImageIndex); @@ -206,9 +328,9 @@ VkResult radv_QueuePresentKHR( VkResult result = VK_SUCCESS; for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) { - RADV_FROM_HANDLE(radv_swapchain, swapchain, pPresentInfo->pSwapchains[i]); + RADV_FROM_HANDLE(wsi_swapchain, swapchain, pPresentInfo->pSwapchains[i]); - assert(swapchain->device == queue->device); + assert(radv_device_from_handle(swapchain->device) == queue->device); if (swapchain->fences[0] == VK_NULL_HANDLE) { result = radv_CreateFence(radv_device_to_handle(queue->device), &(VkFenceCreateInfo) { diff --git a/src/amd/vulkan/radv_wsi.h b/src/amd/vulkan/radv_wsi.h deleted file mode 100644 index 04fd0f67ed1..00000000000 --- a/src/amd/vulkan/radv_wsi.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright © 2016 Red Hat - * based on intel anv code: - * 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. - */ - -#ifndef RADV_WSI_H -#define RADV_WSI_H - -#include "radv_private.h" - -struct radv_swapchain; -struct radv_wsi_interface { - VkResult (*get_support)(VkIcdSurfaceBase *surface, - struct radv_physical_device *device, - uint32_t queueFamilyIndex, - VkBool32* pSupported); - VkResult (*get_capabilities)(VkIcdSurfaceBase *surface, - struct radv_physical_device *device, - VkSurfaceCapabilitiesKHR* pSurfaceCapabilities); - VkResult (*get_formats)(VkIcdSurfaceBase *surface, - struct radv_physical_device *device, - uint32_t* pSurfaceFormatCount, - VkSurfaceFormatKHR* pSurfaceFormats); - VkResult (*get_present_modes)(VkIcdSurfaceBase *surface, - struct radv_physical_device *device, - uint32_t* pPresentModeCount, - VkPresentModeKHR* pPresentModes); - VkResult (*create_swapchain)(VkIcdSurfaceBase *surface, - struct radv_device *device, - const VkSwapchainCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - struct radv_swapchain **swapchain); -}; - -struct radv_swapchain { - struct radv_device *device; - - VkAllocationCallbacks alloc; - - VkFence fences[3]; - - VkResult (*destroy)(struct radv_swapchain *swapchain, - const VkAllocationCallbacks *pAllocator); - VkResult (*get_images)(struct radv_swapchain *swapchain, - uint32_t *pCount, VkImage *pSwapchainImages); - VkResult (*acquire_next_image)(struct radv_swapchain *swap_chain, - uint64_t timeout, VkSemaphore semaphore, - uint32_t *image_index); - VkResult (*queue_present)(struct radv_swapchain *swap_chain, - uint32_t image_index); -}; - -RADV_DEFINE_NONDISP_HANDLE_CASTS(_VkIcdSurfaceBase, VkSurfaceKHR) -RADV_DEFINE_NONDISP_HANDLE_CASTS(radv_swapchain, VkSwapchainKHR) - -VkResult radv_x11_init_wsi(struct radv_physical_device *physical_device); -void radv_x11_finish_wsi(struct radv_physical_device *physical_device); -VkResult radv_wl_init_wsi(struct radv_physical_device *physical_device); -void radv_wl_finish_wsi(struct radv_physical_device *physical_device); - -#endif /* RADV_WSI_H */ diff --git a/src/amd/vulkan/radv_wsi_wayland.c b/src/amd/vulkan/radv_wsi_wayland.c index 06af89469c3..c6a9667d906 100644 --- a/src/amd/vulkan/radv_wsi_wayland.c +++ b/src/amd/vulkan/radv_wsi_wayland.c @@ -26,855 +26,33 @@ #include <wayland-client.h> #include <wayland-drm-client-protocol.h> -#include "radv_wsi.h" - -#include "vk_format.h" -#include <util/hash_table.h> -#include <util/u_vector.h> -#define MIN_NUM_IMAGES 2 - -struct wsi_wl_display { - struct radv_physical_device *physical_device; - struct wl_display * display; - struct wl_drm * drm; - - /* Vector of VkFormats supported */ - struct u_vector formats; - - uint32_t capabilities; -}; - -struct wsi_wayland { - struct radv_wsi_interface base; - - struct radv_physical_device * physical_device; - - pthread_mutex_t mutex; - /* Hash table of wl_display -> wsi_wl_display mappings */ - struct hash_table * displays; -}; - -static void -wsi_wl_display_add_vk_format(struct wsi_wl_display *display, VkFormat format) -{ - /* Don't add a format that's already in the list */ - VkFormat *f; - u_vector_foreach(f, &display->formats) - if (*f == format) - return; - - /* Don't add formats that aren't renderable. */ - VkFormatProperties props; - radv_GetPhysicalDeviceFormatProperties( - radv_physical_device_to_handle(display->physical_device), format, &props); - if (!(props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) - return; - - f = u_vector_add(&display->formats); - if (f) - *f = format; -} - -static void -drm_handle_device(void *data, struct wl_drm *drm, const char *name) -{ - fprintf(stderr, "wl_drm.device(%s)\n", name); -} - -static uint32_t -wl_drm_format_for_vk_format(VkFormat vk_format, bool alpha) -{ - switch (vk_format) { - /* TODO: Figure out what all the formats mean and make this table - * correct. - */ -#if 0 - case VK_FORMAT_R4G4B4A4_UNORM: - return alpha ? WL_DRM_FORMAT_ABGR4444 : WL_DRM_FORMAT_XBGR4444; - case VK_FORMAT_R5G6B5_UNORM: - return WL_DRM_FORMAT_BGR565; - case VK_FORMAT_R5G5B5A1_UNORM: - return alpha ? WL_DRM_FORMAT_ABGR1555 : WL_DRM_FORMAT_XBGR1555; - case VK_FORMAT_R8G8B8_UNORM: - return WL_DRM_FORMAT_XBGR8888; - case VK_FORMAT_R8G8B8A8_UNORM: - return alpha ? WL_DRM_FORMAT_ABGR8888 : WL_DRM_FORMAT_XBGR8888; - case VK_FORMAT_R10G10B10A2_UNORM: - return alpha ? WL_DRM_FORMAT_ABGR2101010 : WL_DRM_FORMAT_XBGR2101010; - case VK_FORMAT_B4G4R4A4_UNORM: - return alpha ? WL_DRM_FORMAT_ARGB4444 : WL_DRM_FORMAT_XRGB4444; - case VK_FORMAT_B5G6R5_UNORM: - return WL_DRM_FORMAT_RGB565; - case VK_FORMAT_B5G5R5A1_UNORM: - return alpha ? WL_DRM_FORMAT_XRGB1555 : WL_DRM_FORMAT_XRGB1555; -#endif - case VK_FORMAT_B8G8R8_SRGB: - return WL_DRM_FORMAT_BGRX8888; - case VK_FORMAT_B8G8R8A8_SRGB: - return alpha ? WL_DRM_FORMAT_ARGB8888 : WL_DRM_FORMAT_XRGB8888; -#if 0 - case VK_FORMAT_B10G10R10A2_UNORM: - return alpha ? WL_DRM_FORMAT_ARGB2101010 : WL_DRM_FORMAT_XRGB2101010; -#endif - - default: - assert(!"Unsupported Vulkan format"); - return 0; - } -} - -static void -drm_handle_format(void *data, struct wl_drm *drm, uint32_t wl_format) -{ - struct wsi_wl_display *display = data; - - switch (wl_format) { -#if 0 - case WL_DRM_FORMAT_ABGR4444: - case WL_DRM_FORMAT_XBGR4444: - wsi_wl_display_add_vk_format(display, VK_FORMAT_R4G4B4A4_UNORM); - break; - case WL_DRM_FORMAT_BGR565: - wsi_wl_display_add_vk_format(display, VK_FORMAT_R5G6B5_UNORM); - break; - case WL_DRM_FORMAT_ABGR1555: - case WL_DRM_FORMAT_XBGR1555: - wsi_wl_display_add_vk_format(display, VK_FORMAT_R5G5B5A1_UNORM); - break; - case WL_DRM_FORMAT_XBGR8888: - wsi_wl_display_add_vk_format(display, VK_FORMAT_R8G8B8_UNORM); - /* fallthrough */ - case WL_DRM_FORMAT_ABGR8888: - wsi_wl_display_add_vk_format(display, VK_FORMAT_R8G8B8A8_UNORM); - break; - case WL_DRM_FORMAT_ABGR2101010: - case WL_DRM_FORMAT_XBGR2101010: - wsi_wl_display_add_vk_format(display, VK_FORMAT_R10G10B10A2_UNORM); - break; - case WL_DRM_FORMAT_ARGB4444: - case WL_DRM_FORMAT_XRGB4444: - wsi_wl_display_add_vk_format(display, VK_FORMAT_B4G4R4A4_UNORM); - break; - case WL_DRM_FORMAT_RGB565: - wsi_wl_display_add_vk_format(display, VK_FORMAT_B5G6R5_UNORM); - break; - case WL_DRM_FORMAT_ARGB1555: - case WL_DRM_FORMAT_XRGB1555: - wsi_wl_display_add_vk_format(display, VK_FORMAT_B5G5R5A1_UNORM); - break; -#endif - case WL_DRM_FORMAT_XRGB8888: - wsi_wl_display_add_vk_format(display, VK_FORMAT_B8G8R8_SRGB); - /* fallthrough */ - case WL_DRM_FORMAT_ARGB8888: - wsi_wl_display_add_vk_format(display, VK_FORMAT_B8G8R8A8_SRGB); - break; -#if 0 - case WL_DRM_FORMAT_ARGB2101010: - case WL_DRM_FORMAT_XRGB2101010: - wsi_wl_display_add_vk_format(display, VK_FORMAT_B10G10R10A2_UNORM); - break; -#endif - } -} - -static void -drm_handle_authenticated(void *data, struct wl_drm *drm) -{ -} - -static void -drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t capabilities) -{ - struct wsi_wl_display *display = data; - - display->capabilities = capabilities; -} - -static const struct wl_drm_listener drm_listener = { - drm_handle_device, - drm_handle_format, - drm_handle_authenticated, - drm_handle_capabilities, -}; - -static void -registry_handle_global(void *data, struct wl_registry *registry, - uint32_t name, const char *interface, uint32_t version) -{ - struct wsi_wl_display *display = data; - - if (strcmp(interface, "wl_drm") == 0) { - assert(display->drm == NULL); - - assert(version >= 2); - display->drm = wl_registry_bind(registry, name, &wl_drm_interface, 2); - - if (display->drm) - wl_drm_add_listener(display->drm, &drm_listener, display); - } -} - -static void -registry_handle_global_remove(void *data, struct wl_registry *registry, - uint32_t name) -{ /* No-op */ } - -static const struct wl_registry_listener registry_listener = { - registry_handle_global, - registry_handle_global_remove -}; - -static void -wsi_wl_display_destroy(struct wsi_wayland *wsi, struct wsi_wl_display *display) -{ - u_vector_finish(&display->formats); - if (display->drm) - wl_drm_destroy(display->drm); - vk_free(&wsi->physical_device->instance->alloc, display); -} - -static struct wsi_wl_display * -wsi_wl_display_create(struct wsi_wayland *wsi, struct wl_display *wl_display) -{ - struct wsi_wl_display *display = - vk_alloc(&wsi->physical_device->instance->alloc, sizeof(*display), 8, - VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); - if (!display) - return NULL; - - memset(display, 0, sizeof(*display)); - - display->display = wl_display; - display->physical_device = wsi->physical_device; - - if (!u_vector_init(&display->formats, sizeof(VkFormat), 8)) - goto fail; - - struct wl_registry *registry = wl_display_get_registry(wl_display); - if (!registry) - return NULL; - - wl_registry_add_listener(registry, ®istry_listener, display); - - /* Round-rip to get the wl_drm global */ - wl_display_roundtrip(wl_display); - - if (!display->drm) - goto fail; - - /* Round-rip to get wl_drm formats and capabilities */ - wl_display_roundtrip(wl_display); - - /* We need prime support */ - if (!(display->capabilities & WL_DRM_CAPABILITY_PRIME)) - goto fail; - - /* We don't need this anymore */ - wl_registry_destroy(registry); - - return display; - -fail: - if (registry) - wl_registry_destroy(registry); - - wsi_wl_display_destroy(wsi, display); - return NULL; -} - -static struct wsi_wl_display * -wsi_wl_get_display(struct radv_physical_device *device, - struct wl_display *wl_display) -{ - struct wsi_wayland *wsi = - (struct wsi_wayland *)device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND]; - - pthread_mutex_lock(&wsi->mutex); - - struct hash_entry *entry = _mesa_hash_table_search(wsi->displays, - wl_display); - if (!entry) { - /* We're about to make a bunch of blocking calls. Let's drop the - * mutex for now so we don't block up too badly. - */ - pthread_mutex_unlock(&wsi->mutex); - - struct wsi_wl_display *display = wsi_wl_display_create(wsi, wl_display); - - pthread_mutex_lock(&wsi->mutex); - - entry = _mesa_hash_table_search(wsi->displays, wl_display); - if (entry) { - /* Oops, someone raced us to it */ - wsi_wl_display_destroy(wsi, display); - } else { - entry = _mesa_hash_table_insert(wsi->displays, wl_display, display); - } - } - - pthread_mutex_unlock(&wsi->mutex); - - return entry->data; -} +#include "wsi_common_wayland.h" +#include "radv_private.h" VkBool32 radv_GetPhysicalDeviceWaylandPresentationSupportKHR( - VkPhysicalDevice physicalDevice, - uint32_t queueFamilyIndex, - struct wl_display* display) -{ - RADV_FROM_HANDLE(radv_physical_device, physical_device, physicalDevice); - - return wsi_wl_get_display(physical_device, display) != NULL; -} - -static VkResult -wsi_wl_surface_get_support(VkIcdSurfaceBase *surface, - struct radv_physical_device *device, - uint32_t queueFamilyIndex, - VkBool32* pSupported) -{ - *pSupported = true; - - return VK_SUCCESS; -} - -static const VkPresentModeKHR present_modes[] = { - VK_PRESENT_MODE_MAILBOX_KHR, - VK_PRESENT_MODE_FIFO_KHR, -}; - -static VkResult -wsi_wl_surface_get_capabilities(VkIcdSurfaceBase *surface, - struct radv_physical_device *device, - VkSurfaceCapabilitiesKHR* caps) + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + struct wl_display* display) { - caps->minImageCount = MIN_NUM_IMAGES; - caps->maxImageCount = 4; - caps->currentExtent = (VkExtent2D) { -1, -1 }; - caps->minImageExtent = (VkExtent2D) { 1, 1 }; - caps->maxImageExtent = (VkExtent2D) { INT16_MAX, INT16_MAX }; - caps->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; - caps->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; - caps->maxImageArrayLayers = 1; - - caps->supportedCompositeAlpha = - VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR | - VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR; + RADV_FROM_HANDLE(radv_physical_device, physical_device, physicalDevice); - caps->supportedUsageFlags = - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - - return VK_SUCCESS; + return wsi_wl_get_presentation_support(&physical_device->wsi_device, display); } -static VkResult -wsi_wl_surface_get_formats(VkIcdSurfaceBase *icd_surface, - struct radv_physical_device *device, - uint32_t* pSurfaceFormatCount, - VkSurfaceFormatKHR* pSurfaceFormats) -{ - VkIcdSurfaceWayland *surface = (VkIcdSurfaceWayland *)icd_surface; - struct wsi_wl_display *display = - wsi_wl_get_display(device, surface->display); - - uint32_t count = u_vector_length(&display->formats); - - if (pSurfaceFormats == NULL) { - *pSurfaceFormatCount = count; - return VK_SUCCESS; - } - - assert(*pSurfaceFormatCount >= count); - *pSurfaceFormatCount = count; - - VkFormat *f; - u_vector_foreach(f, &display->formats) { - *(pSurfaceFormats++) = (VkSurfaceFormatKHR) { - .format = *f, - /* TODO: We should get this from the compositor somehow */ - .colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR, - }; - } - - return VK_SUCCESS; -} - -static VkResult -wsi_wl_surface_get_present_modes(VkIcdSurfaceBase *surface, - struct radv_physical_device *device, - uint32_t* pPresentModeCount, - VkPresentModeKHR* pPresentModes) -{ - if (pPresentModes == NULL) { - *pPresentModeCount = ARRAY_SIZE(present_modes); - return VK_SUCCESS; - } - - assert(*pPresentModeCount >= ARRAY_SIZE(present_modes)); - typed_memcpy(pPresentModes, present_modes, *pPresentModeCount); - *pPresentModeCount = ARRAY_SIZE(present_modes); - - return VK_SUCCESS; -} - -static VkResult -wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *surface, - struct radv_device *device, - const VkSwapchainCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - struct radv_swapchain **swapchain); - VkResult radv_CreateWaylandSurfaceKHR( - VkInstance _instance, - const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSurfaceKHR* pSurface) -{ - RADV_FROM_HANDLE(radv_instance, instance, _instance); - - assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR); - - VkIcdSurfaceWayland *surface; - - surface = vk_alloc2(&instance->alloc, pAllocator, sizeof *surface, 8, - VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); - if (surface == NULL) - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); - - surface->base.platform = VK_ICD_WSI_PLATFORM_WAYLAND; - surface->display = pCreateInfo->display; - surface->surface = pCreateInfo->surface; - - *pSurface = _VkIcdSurfaceBase_to_handle(&surface->base); - - return VK_SUCCESS; -} - -struct wsi_wl_image { - struct radv_image * image; - struct radv_device_memory * memory; - struct wl_buffer * buffer; - bool busy; -}; - -struct wsi_wl_swapchain { - struct radv_swapchain base; - - struct wsi_wl_display * display; - struct wl_event_queue * queue; - struct wl_surface * surface; - - VkExtent2D extent; - VkFormat vk_format; - uint32_t drm_format; - - VkPresentModeKHR present_mode; - bool fifo_ready; - - uint32_t image_count; - struct wsi_wl_image images[0]; -}; - -static VkResult -wsi_wl_swapchain_get_images(struct radv_swapchain *radv_chain, - uint32_t *pCount, VkImage *pSwapchainImages) -{ - struct wsi_wl_swapchain *chain = (struct wsi_wl_swapchain *)radv_chain; - - if (pSwapchainImages == NULL) { - *pCount = chain->image_count; - return VK_SUCCESS; - } - - assert(chain->image_count <= *pCount); - for (uint32_t i = 0; i < chain->image_count; i++) - pSwapchainImages[i] = radv_image_to_handle(chain->images[i].image); - - *pCount = chain->image_count; - - return VK_SUCCESS; -} - -static VkResult -wsi_wl_swapchain_acquire_next_image(struct radv_swapchain *radv_chain, - uint64_t timeout, - VkSemaphore semaphore, - uint32_t *image_index) -{ - struct wsi_wl_swapchain *chain = (struct wsi_wl_swapchain *)radv_chain; - - int ret = wl_display_dispatch_queue_pending(chain->display->display, - chain->queue); - /* XXX: I'm not sure if out-of-date is the right error here. If - * wl_display_dispatch_queue_pending fails it most likely means we got - * kicked by the server so this seems more-or-less correct. - */ - if (ret < 0) - return vk_error(VK_ERROR_OUT_OF_DATE_KHR); - - while (1) { - for (uint32_t i = 0; i < chain->image_count; i++) { - if (!chain->images[i].busy) { - /* We found a non-busy image */ - *image_index = i; - chain->images[i].busy = true; - return VK_SUCCESS; - } - } - - /* This time we do a blocking dispatch because we can't go - * anywhere until we get an event. - */ - int ret = wl_display_roundtrip_queue(chain->display->display, - chain->queue); - if (ret < 0) - return vk_error(VK_ERROR_OUT_OF_DATE_KHR); - } -} - -static void -frame_handle_done(void *data, struct wl_callback *callback, uint32_t serial) -{ - struct wsi_wl_swapchain *chain = data; - - chain->fifo_ready = true; - - wl_callback_destroy(callback); -} - -static const struct wl_callback_listener frame_listener = { - frame_handle_done, -}; - -static VkResult -wsi_wl_swapchain_queue_present(struct radv_swapchain *radv_chain, - uint32_t image_index) + VkInstance _instance, + const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface) { - struct wsi_wl_swapchain *chain = (struct wsi_wl_swapchain *)radv_chain; - - if (chain->present_mode == VK_PRESENT_MODE_FIFO_KHR) { - while (!chain->fifo_ready) { - int ret = wl_display_dispatch_queue(chain->display->display, - chain->queue); - if (ret < 0) - return vk_error(VK_ERROR_OUT_OF_DATE_KHR); - } - } - - assert(image_index < chain->image_count); - wl_surface_attach(chain->surface, chain->images[image_index].buffer, 0, 0); - wl_surface_damage(chain->surface, 0, 0, INT32_MAX, INT32_MAX); - - if (chain->present_mode == VK_PRESENT_MODE_FIFO_KHR) { - struct wl_callback *frame = wl_surface_frame(chain->surface); - wl_proxy_set_queue((struct wl_proxy *)frame, chain->queue); - wl_callback_add_listener(frame, &frame_listener, chain); - chain->fifo_ready = false; - } - - chain->images[image_index].busy = true; - wl_surface_commit(chain->surface); - wl_display_flush(chain->display->display); - - return VK_SUCCESS; -} - -static void -wsi_wl_image_finish(struct wsi_wl_swapchain *chain, struct wsi_wl_image *image, - const VkAllocationCallbacks* pAllocator) -{ - VkDevice vk_device = radv_device_to_handle(chain->base.device); - radv_FreeMemory(vk_device, radv_device_memory_to_handle(image->memory), - pAllocator); - radv_DestroyImage(vk_device, radv_image_to_handle(image->image), - pAllocator); -} - -static void -buffer_handle_release(void *data, struct wl_buffer *buffer) -{ - struct wsi_wl_image *image = data; - - assert(image->buffer == buffer); - - image->busy = false; -} - -static const struct wl_buffer_listener buffer_listener = { - buffer_handle_release, -}; - -static VkResult -wsi_wl_image_init(struct wsi_wl_swapchain *chain, - struct wsi_wl_image *image, - const VkSwapchainCreateInfoKHR *pCreateInfo, - const VkAllocationCallbacks* pAllocator) -{ - VkDevice vk_device = radv_device_to_handle(chain->base.device); - VkResult result; - bool bret; - VkImage vk_image; - struct radeon_surf *surface; - int fd; - result = radv_image_create(vk_device, - &(struct radv_image_create_info) { - .vk_info = - &(VkImageCreateInfo) { - .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - .imageType = VK_IMAGE_TYPE_2D, - .format = chain->vk_format, - .extent = { - .width = chain->extent.width, - .height = chain->extent.height, - .depth = 1 - }, - .mipLevels = 1, - .arrayLayers = 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 | - pCreateInfo->imageUsage), - .flags = 0, - }, - .scanout = true}, - pAllocator, - &vk_image); - - if (result != VK_SUCCESS) - return result; - - image->image = radv_image_from_handle(vk_image); - assert(vk_format_is_color(image->image->vk_format)); - - VkDeviceMemory vk_memory; - result = radv_AllocateMemory(vk_device, - &(VkMemoryAllocateInfo) { - .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - .allocationSize = image->image->size, - .memoryTypeIndex = 0, - }, - pAllocator, - &vk_memory); - - if (result != VK_SUCCESS) - goto fail_image; - - image->memory = radv_device_memory_from_handle(vk_memory); - - result = radv_BindImageMemory(vk_device, vk_image, vk_memory, 0); - - if (result != VK_SUCCESS) - goto fail_mem; - - bret = chain->base.device->ws->buffer_get_fd(chain->base.device->ws, - image->memory->bo, &fd); - if (bret == false) - goto fail_mem; - - { - struct radeon_bo_metadata metadata; - radv_init_metadata(chain->base.device, image->image, &metadata); - chain->base.device->ws->buffer_set_metadata(image->memory->bo, &metadata); - } - surface = &image->image->surface; - - image->buffer = wl_drm_create_prime_buffer(chain->display->drm, - fd, /* name */ - chain->extent.width, - chain->extent.height, - chain->drm_format, - surface->level[0].offset, - surface->level[0].pitch_bytes, - 0, 0, 0, 0 /* unused */); - wl_display_roundtrip(chain->display->display); - close(fd); - - wl_proxy_set_queue((struct wl_proxy *)image->buffer, chain->queue); - wl_buffer_add_listener(image->buffer, &buffer_listener, image); - - return VK_SUCCESS; - -fail_mem: - radv_FreeMemory(vk_device, vk_memory, pAllocator); -fail_image: - radv_DestroyImage(vk_device, vk_image, pAllocator); - - return result; -} - -static VkResult -wsi_wl_swapchain_destroy(struct radv_swapchain *radv_chain, - const VkAllocationCallbacks *pAllocator) -{ - struct wsi_wl_swapchain *chain = (struct wsi_wl_swapchain *)radv_chain; - - for (uint32_t i = 0; i < chain->image_count; i++) { - if (chain->images[i].buffer) - wsi_wl_image_finish(chain, &chain->images[i], pAllocator); - } - - vk_free2(&chain->base.device->alloc, pAllocator, chain); - - return VK_SUCCESS; -} - -static VkResult -wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface, - struct radv_device *device, - const VkSwapchainCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - struct radv_swapchain **swapchain_out) -{ - VkIcdSurfaceWayland *surface = (VkIcdSurfaceWayland *)icd_surface; - struct wsi_wl_swapchain *chain; - VkResult result; - - assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR); - - int num_images = pCreateInfo->minImageCount; - - assert(num_images >= MIN_NUM_IMAGES); - - /* For true mailbox mode, we need at least 4 images: - * 1) One to scan out from - * 2) One to have queued for scan-out - * 3) One to be currently held by the Wayland compositor - * 4) One to render to - */ - if (pCreateInfo->presentMode == VK_PRESENT_MODE_MAILBOX_KHR) - num_images = MAX2(num_images, 4); - - size_t size = sizeof(*chain) + num_images * sizeof(chain->images[0]); - chain = vk_alloc2(&device->alloc, pAllocator, size, 8, - VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); - if (chain == NULL) - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); - - chain->base.device = device; - chain->base.destroy = wsi_wl_swapchain_destroy; - chain->base.get_images = wsi_wl_swapchain_get_images; - chain->base.acquire_next_image = wsi_wl_swapchain_acquire_next_image; - chain->base.queue_present = wsi_wl_swapchain_queue_present; - - chain->surface = surface->surface; - chain->extent = pCreateInfo->imageExtent; - chain->vk_format = pCreateInfo->imageFormat; - chain->drm_format = wl_drm_format_for_vk_format(chain->vk_format, false); - - chain->present_mode = pCreateInfo->presentMode; - chain->fifo_ready = true; - - chain->image_count = num_images; - - /* Mark a bunch of stuff as NULL. This way we can just call - * destroy_swapchain for cleanup. - */ - for (uint32_t i = 0; i < chain->image_count; i++) - chain->images[i].buffer = NULL; - chain->queue = NULL; - - chain->display = wsi_wl_get_display(&device->instance->physicalDevice, - surface->display); - if (!chain->display) { - result = vk_error(VK_ERROR_INITIALIZATION_FAILED); - goto fail; - } - - chain->queue = wl_display_create_queue(chain->display->display); - if (!chain->queue) { - result = vk_error(VK_ERROR_INITIALIZATION_FAILED); - goto fail; - } - - for (uint32_t i = 0; i < chain->image_count; i++) { - result = wsi_wl_image_init(chain, &chain->images[i], - pCreateInfo, pAllocator); - if (result != VK_SUCCESS) - goto fail; - chain->images[i].busy = false; - } - - *swapchain_out = &chain->base; - - return VK_SUCCESS; - -fail: - wsi_wl_swapchain_destroy(&chain->base, pAllocator); - - return result; -} - -VkResult -radv_wl_init_wsi(struct radv_physical_device *device) -{ - struct wsi_wayland *wsi; - VkResult result; - - wsi = vk_alloc(&device->instance->alloc, sizeof(*wsi), 8, - VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); - if (!wsi) { - result = vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); - goto fail; - } - - wsi->physical_device = device; - - int ret = pthread_mutex_init(&wsi->mutex, NULL); - if (ret != 0) { - if (ret == ENOMEM) { - result = vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); - } else { - /* FINISHME: Choose a better error. */ - result = vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); - } - - goto fail_alloc; - } - - wsi->displays = _mesa_hash_table_create(NULL, _mesa_hash_pointer, - _mesa_key_pointer_equal); - if (!wsi->displays) { - result = vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); - goto fail_mutex; - } - - wsi->base.get_support = wsi_wl_surface_get_support; - wsi->base.get_capabilities = wsi_wl_surface_get_capabilities; - wsi->base.get_formats = wsi_wl_surface_get_formats; - wsi->base.get_present_modes = wsi_wl_surface_get_present_modes; - wsi->base.create_swapchain = wsi_wl_surface_create_swapchain; - - device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND] = &wsi->base; - - return VK_SUCCESS; - -fail_mutex: - pthread_mutex_destroy(&wsi->mutex); - -fail_alloc: - vk_free(&device->instance->alloc, wsi); -fail: - device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND] = NULL; - - return result; -} - -void -radv_wl_finish_wsi(struct radv_physical_device *device) -{ - struct wsi_wayland *wsi = - (struct wsi_wayland *)device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND]; - - if (wsi) { - _mesa_hash_table_destroy(wsi->displays, NULL); + RADV_FROM_HANDLE(radv_instance, instance, _instance); + const VkAllocationCallbacks *alloc; + assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR); - pthread_mutex_destroy(&wsi->mutex); + if (pAllocator) + alloc = pAllocator; + else + alloc = &instance->alloc; - vk_free(&device->instance->alloc, wsi); - } + return wsi_create_wl_surface(alloc, pCreateInfo, pSurface); } diff --git a/src/amd/vulkan/radv_wsi_x11.c b/src/amd/vulkan/radv_wsi_x11.c index 2da8195235e..946b99095ac 100644 --- a/src/amd/vulkan/radv_wsi_x11.c +++ b/src/amd/vulkan/radv_wsi_x11.c @@ -30,934 +30,71 @@ #include <xcb/xcb.h> #include <xcb/dri3.h> #include <xcb/present.h> -#include <errno.h> -#include <unistd.h> -#include "radv_wsi.h" -#include "vk_format.h" -#include "util/hash_table.h" - -struct wsi_x11_connection { - bool has_dri3; - bool has_present; -}; - -struct wsi_x11 { - struct radv_wsi_interface base; - - pthread_mutex_t mutex; - /* Hash table of xcb_connection -> wsi_x11_connection mappings */ - struct hash_table *connections; -}; - -static struct wsi_x11_connection * -wsi_x11_connection_create(struct radv_physical_device *device, - xcb_connection_t *conn) -{ - xcb_query_extension_cookie_t dri3_cookie, pres_cookie; - xcb_query_extension_reply_t *dri3_reply, *pres_reply; - - struct wsi_x11_connection *wsi_conn = - vk_alloc(&device->instance->alloc, sizeof(*wsi_conn), 8, - VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); - if (!wsi_conn) - return NULL; - - dri3_cookie = xcb_query_extension(conn, 4, "DRI3"); - pres_cookie = xcb_query_extension(conn, 7, "PRESENT"); - - dri3_reply = xcb_query_extension_reply(conn, dri3_cookie, NULL); - pres_reply = xcb_query_extension_reply(conn, pres_cookie, NULL); - if (dri3_reply == NULL || pres_reply == NULL) { - free(dri3_reply); - free(pres_reply); - vk_free(&device->instance->alloc, wsi_conn); - return NULL; - } - - wsi_conn->has_dri3 = dri3_reply->present != 0; - wsi_conn->has_present = pres_reply->present != 0; - - free(dri3_reply); - free(pres_reply); - - return wsi_conn; -} - -static void -wsi_x11_connection_destroy(struct radv_physical_device *device, - struct wsi_x11_connection *conn) -{ - vk_free(&device->instance->alloc, conn); -} - -static struct wsi_x11_connection * -wsi_x11_get_connection(struct radv_physical_device *device, - xcb_connection_t *conn) -{ - struct wsi_x11 *wsi = - (struct wsi_x11 *)device->wsi[VK_ICD_WSI_PLATFORM_XCB]; - - pthread_mutex_lock(&wsi->mutex); - - struct hash_entry *entry = _mesa_hash_table_search(wsi->connections, conn); - if (!entry) { - /* We're about to make a bunch of blocking calls. Let's drop the - * mutex for now so we don't block up too badly. - */ - pthread_mutex_unlock(&wsi->mutex); - - struct wsi_x11_connection *wsi_conn = - wsi_x11_connection_create(device, conn); - - pthread_mutex_lock(&wsi->mutex); - - entry = _mesa_hash_table_search(wsi->connections, conn); - if (entry) { - /* Oops, someone raced us to it */ - wsi_x11_connection_destroy(device, wsi_conn); - } else { - entry = _mesa_hash_table_insert(wsi->connections, conn, wsi_conn); - } - } - - pthread_mutex_unlock(&wsi->mutex); - - return entry->data; -} - -static const VkSurfaceFormatKHR formats[] = { - { .format = VK_FORMAT_B8G8R8A8_UNORM, }, - { .format = VK_FORMAT_B8G8R8A8_SRGB, }, -}; - -static const VkPresentModeKHR present_modes[] = { - VK_PRESENT_MODE_MAILBOX_KHR, -}; - -static xcb_screen_t * -get_screen_for_root(xcb_connection_t *conn, xcb_window_t root) -{ - xcb_screen_iterator_t screen_iter = - xcb_setup_roots_iterator(xcb_get_setup(conn)); - - for (; screen_iter.rem; xcb_screen_next (&screen_iter)) { - if (screen_iter.data->root == root) - return screen_iter.data; - } - - return NULL; -} - -static xcb_visualtype_t * -screen_get_visualtype(xcb_screen_t *screen, xcb_visualid_t visual_id, - unsigned *depth) -{ - xcb_depth_iterator_t depth_iter = - xcb_screen_allowed_depths_iterator(screen); - - for (; depth_iter.rem; xcb_depth_next (&depth_iter)) { - xcb_visualtype_iterator_t visual_iter = - xcb_depth_visuals_iterator (depth_iter.data); - - for (; visual_iter.rem; xcb_visualtype_next (&visual_iter)) { - if (visual_iter.data->visual_id == visual_id) { - if (depth) - *depth = depth_iter.data->depth; - return visual_iter.data; - } - } - } - - return NULL; -} - -static xcb_visualtype_t * -connection_get_visualtype(xcb_connection_t *conn, xcb_visualid_t visual_id, - unsigned *depth) -{ - xcb_screen_iterator_t screen_iter = - xcb_setup_roots_iterator(xcb_get_setup(conn)); - - /* For this we have to iterate over all of the screens which is rather - * annoying. Fortunately, there is probably only 1. - */ - for (; screen_iter.rem; xcb_screen_next (&screen_iter)) { - xcb_visualtype_t *visual = screen_get_visualtype(screen_iter.data, - visual_id, depth); - if (visual) - return visual; - } - - return NULL; -} - -static xcb_visualtype_t * -get_visualtype_for_window(xcb_connection_t *conn, xcb_window_t window, - unsigned *depth) -{ - xcb_query_tree_cookie_t tree_cookie; - xcb_get_window_attributes_cookie_t attrib_cookie; - xcb_query_tree_reply_t *tree; - xcb_get_window_attributes_reply_t *attrib; - - tree_cookie = xcb_query_tree(conn, window); - attrib_cookie = xcb_get_window_attributes(conn, window); - - tree = xcb_query_tree_reply(conn, tree_cookie, NULL); - attrib = xcb_get_window_attributes_reply(conn, attrib_cookie, NULL); - if (attrib == NULL || tree == NULL) { - free(attrib); - free(tree); - return NULL; - } - - xcb_window_t root = tree->root; - xcb_visualid_t visual_id = attrib->visual; - free(attrib); - free(tree); - - xcb_screen_t *screen = get_screen_for_root(conn, root); - if (screen == NULL) - return NULL; - - return screen_get_visualtype(screen, visual_id, depth); -} - -static bool -visual_has_alpha(xcb_visualtype_t *visual, unsigned depth) -{ - uint32_t rgb_mask = visual->red_mask | - visual->green_mask | - visual->blue_mask; - - uint32_t all_mask = 0xffffffff >> (32 - depth); - - /* Do we have bits left over after RGB? */ - return (all_mask & ~rgb_mask) != 0; -} +#include "wsi_common_x11.h" +#include "radv_private.h" VkBool32 radv_GetPhysicalDeviceXcbPresentationSupportKHR( - VkPhysicalDevice physicalDevice, - uint32_t queueFamilyIndex, - xcb_connection_t* connection, - xcb_visualid_t visual_id) + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + xcb_connection_t* connection, + xcb_visualid_t visual_id) { - RADV_FROM_HANDLE(radv_physical_device, device, physicalDevice); - - struct wsi_x11_connection *wsi_conn = - wsi_x11_get_connection(device, connection); - - if (!wsi_conn->has_dri3) { - fprintf(stderr, "vulkan: No DRI3 support\n"); - return false; - } - - unsigned visual_depth; - if (!connection_get_visualtype(connection, visual_id, &visual_depth)) - return false; - - if (visual_depth != 24 && visual_depth != 32) - return false; + RADV_FROM_HANDLE(radv_physical_device, device, physicalDevice); - return true; + return wsi_get_physical_device_xcb_presentation_support( + &device->wsi_device, + &device->instance->alloc, + queueFamilyIndex, connection, visual_id); } VkBool32 radv_GetPhysicalDeviceXlibPresentationSupportKHR( - VkPhysicalDevice physicalDevice, - uint32_t queueFamilyIndex, - Display* dpy, - VisualID visualID) + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + Display* dpy, + VisualID visualID) { - return radv_GetPhysicalDeviceXcbPresentationSupportKHR(physicalDevice, - queueFamilyIndex, - XGetXCBConnection(dpy), - visualID); -} + RADV_FROM_HANDLE(radv_physical_device, device, physicalDevice); -static xcb_connection_t* -x11_surface_get_connection(VkIcdSurfaceBase *icd_surface) -{ - if (icd_surface->platform == VK_ICD_WSI_PLATFORM_XLIB) - return XGetXCBConnection(((VkIcdSurfaceXlib *)icd_surface)->dpy); - else - return ((VkIcdSurfaceXcb *)icd_surface)->connection; + return wsi_get_physical_device_xcb_presentation_support( + &device->wsi_device, + &device->instance->alloc, + queueFamilyIndex, XGetXCBConnection(dpy), visualID); } -static xcb_window_t -x11_surface_get_window(VkIcdSurfaceBase *icd_surface) -{ - if (icd_surface->platform == VK_ICD_WSI_PLATFORM_XLIB) - return ((VkIcdSurfaceXlib *)icd_surface)->window; - else - return ((VkIcdSurfaceXcb *)icd_surface)->window; -} - -static VkResult -x11_surface_get_support(VkIcdSurfaceBase *icd_surface, - struct radv_physical_device *device, - uint32_t queueFamilyIndex, - VkBool32* pSupported) -{ - xcb_connection_t *conn = x11_surface_get_connection(icd_surface); - xcb_window_t window = x11_surface_get_window(icd_surface); - - struct wsi_x11_connection *wsi_conn = - wsi_x11_get_connection(device, conn); - if (!wsi_conn) - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); - - if (!wsi_conn->has_dri3) { - fprintf(stderr, "vulkan: No DRI3 support\n"); - *pSupported = false; - return VK_SUCCESS; - } - - unsigned visual_depth; - if (!get_visualtype_for_window(conn, window, &visual_depth)) { - *pSupported = false; - return VK_SUCCESS; - } - - if (visual_depth != 24 && visual_depth != 32) { - *pSupported = false; - return VK_SUCCESS; - } - - *pSupported = true; - return VK_SUCCESS; -} - -static VkResult -x11_surface_get_capabilities(VkIcdSurfaceBase *icd_surface, - struct radv_physical_device *device, - VkSurfaceCapabilitiesKHR *caps) -{ - xcb_connection_t *conn = x11_surface_get_connection(icd_surface); - xcb_window_t window = x11_surface_get_window(icd_surface); - xcb_get_geometry_cookie_t geom_cookie; - xcb_generic_error_t *err; - xcb_get_geometry_reply_t *geom; - unsigned visual_depth; - - geom_cookie = xcb_get_geometry(conn, window); - - /* This does a round-trip. This is why we do get_geometry first and - * wait to read the reply until after we have a visual. - */ - xcb_visualtype_t *visual = - get_visualtype_for_window(conn, window, &visual_depth); - - geom = xcb_get_geometry_reply(conn, geom_cookie, &err); - if (geom) { - VkExtent2D extent = { geom->width, geom->height }; - caps->currentExtent = extent; - caps->minImageExtent = extent; - caps->maxImageExtent = extent; - } else { - /* This can happen if the client didn't wait for the configure event - * to come back from the compositor. In that case, we don't know the - * size of the window so we just return valid "I don't know" stuff. - */ - caps->currentExtent = (VkExtent2D) { -1, -1 }; - caps->minImageExtent = (VkExtent2D) { 1, 1 }; - caps->maxImageExtent = (VkExtent2D) { INT16_MAX, INT16_MAX }; - } - free(err); - free(geom); - - if (visual_has_alpha(visual, visual_depth)) { - caps->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR | - VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR; - } else { - caps->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR | - VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - } - - caps->minImageCount = 2; - caps->maxImageCount = 4; - caps->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; - caps->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; - caps->maxImageArrayLayers = 1; - caps->supportedUsageFlags = - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - - return VK_SUCCESS; -} - -static VkResult -x11_surface_get_formats(VkIcdSurfaceBase *surface, - struct radv_physical_device *device, - uint32_t *pSurfaceFormatCount, - VkSurfaceFormatKHR *pSurfaceFormats) -{ - if (pSurfaceFormats == NULL) { - *pSurfaceFormatCount = ARRAY_SIZE(formats); - return VK_SUCCESS; - } - - assert(*pSurfaceFormatCount >= ARRAY_SIZE(formats)); - typed_memcpy(pSurfaceFormats, formats, *pSurfaceFormatCount); - *pSurfaceFormatCount = ARRAY_SIZE(formats); - - return VK_SUCCESS; -} - -static VkResult -x11_surface_get_present_modes(VkIcdSurfaceBase *surface, - struct radv_physical_device *device, - uint32_t *pPresentModeCount, - VkPresentModeKHR *pPresentModes) -{ - if (pPresentModes == NULL) { - *pPresentModeCount = ARRAY_SIZE(present_modes); - return VK_SUCCESS; - } - - assert(*pPresentModeCount >= ARRAY_SIZE(present_modes)); - typed_memcpy(pPresentModes, present_modes, *pPresentModeCount); - *pPresentModeCount = ARRAY_SIZE(present_modes); - - return VK_SUCCESS; -} - -static VkResult -x11_surface_create_swapchain(VkIcdSurfaceBase *surface, - struct radv_device *device, - const VkSwapchainCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - struct radv_swapchain **swapchain); - VkResult radv_CreateXcbSurfaceKHR( - VkInstance _instance, - const VkXcbSurfaceCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSurfaceKHR* pSurface) + VkInstance _instance, + const VkXcbSurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface) { - RADV_FROM_HANDLE(radv_instance, instance, _instance); + RADV_FROM_HANDLE(radv_instance, instance, _instance); + const VkAllocationCallbacks *alloc; + assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR); - assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR); + if (pAllocator) + alloc = pAllocator; + else + alloc = &instance->alloc; - VkIcdSurfaceXcb *surface; - - surface = vk_alloc2(&instance->alloc, pAllocator, sizeof *surface, 8, - VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); - if (surface == NULL) - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); - - surface->base.platform = VK_ICD_WSI_PLATFORM_XCB; - surface->connection = pCreateInfo->connection; - surface->window = pCreateInfo->window; - - *pSurface = _VkIcdSurfaceBase_to_handle(&surface->base); - - return VK_SUCCESS; + return wsi_create_xcb_surface(alloc, pCreateInfo, pSurface); } VkResult radv_CreateXlibSurfaceKHR( - VkInstance _instance, - const VkXlibSurfaceCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSurfaceKHR* pSurface) -{ - RADV_FROM_HANDLE(radv_instance, instance, _instance); - - assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR); - - VkIcdSurfaceXlib *surface; - - surface = vk_alloc2(&instance->alloc, pAllocator, sizeof *surface, 8, - VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); - if (surface == NULL) - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); - - surface->base.platform = VK_ICD_WSI_PLATFORM_XLIB; - surface->dpy = pCreateInfo->dpy; - surface->window = pCreateInfo->window; - - *pSurface = _VkIcdSurfaceBase_to_handle(&surface->base); - - return VK_SUCCESS; -} - -struct x11_image { - struct radv_image * image; - struct radv_device_memory * memory; - xcb_pixmap_t pixmap; - bool busy; - struct xshmfence * shm_fence; - uint32_t sync_fence; -}; - -struct x11_swapchain { - struct radv_swapchain base; - - xcb_connection_t * conn; - xcb_window_t window; - xcb_gc_t gc; - VkExtent2D extent; - uint32_t image_count; - - xcb_present_event_t event_id; - xcb_special_event_t * special_event; - uint64_t send_sbc; - uint32_t stamp; - - struct x11_image images[0]; -}; - -static VkResult -x11_get_images(struct radv_swapchain *radv_chain, - uint32_t* pCount, VkImage *pSwapchainImages) -{ - struct x11_swapchain *chain = (struct x11_swapchain *)radv_chain; - - if (pSwapchainImages == NULL) { - *pCount = chain->image_count; - return VK_SUCCESS; - } - - assert(chain->image_count <= *pCount); - for (uint32_t i = 0; i < chain->image_count; i++) - pSwapchainImages[i] = radv_image_to_handle(chain->images[i].image); - - *pCount = chain->image_count; - - return VK_SUCCESS; -} - -static VkResult -x11_handle_dri3_present_event(struct x11_swapchain *chain, - xcb_present_generic_event_t *event) -{ - switch (event->evtype) { - case XCB_PRESENT_CONFIGURE_NOTIFY: { - xcb_present_configure_notify_event_t *config = (void *) event; - - if (config->width != chain->extent.width || - config->height != chain->extent.height) - return vk_error(VK_ERROR_OUT_OF_DATE_KHR); - - break; - } - - case XCB_PRESENT_EVENT_IDLE_NOTIFY: { - xcb_present_idle_notify_event_t *idle = (void *) event; - - for (unsigned i = 0; i < chain->image_count; i++) { - if (chain->images[i].pixmap == idle->pixmap) { - chain->images[i].busy = false; - break; - } - } - - break; - } - - case XCB_PRESENT_COMPLETE_NOTIFY: - default: - break; - } - - return VK_SUCCESS; -} - -static VkResult -x11_acquire_next_image(struct radv_swapchain *radv_chain, - uint64_t timeout, - VkSemaphore semaphore, - uint32_t *image_index) -{ - struct x11_swapchain *chain = (struct x11_swapchain *)radv_chain; - - while (1) { - for (uint32_t i = 0; i < chain->image_count; i++) { - if (!chain->images[i].busy) { - /* We found a non-busy image */ - xshmfence_await(chain->images[i].shm_fence); - *image_index = i; - chain->images[i].busy = true; - return VK_SUCCESS; - } - } - - xcb_flush(chain->conn); - xcb_generic_event_t *event = - xcb_wait_for_special_event(chain->conn, chain->special_event); - if (!event) - return vk_error(VK_ERROR_OUT_OF_DATE_KHR); - - VkResult result = x11_handle_dri3_present_event(chain, (void *)event); - free(event); - if (result != VK_SUCCESS) - return result; - } -} - -static VkResult -x11_queue_present(struct radv_swapchain *radv_chain, - uint32_t image_index) -{ - struct x11_swapchain *chain = (struct x11_swapchain *)radv_chain; - struct x11_image *image = &chain->images[image_index]; - - assert(image_index < chain->image_count); - - uint32_t options = XCB_PRESENT_OPTION_NONE; - - int64_t target_msc = 0; - int64_t divisor = 0; - int64_t remainder = 0; - - options |= XCB_PRESENT_OPTION_ASYNC; - - xshmfence_reset(image->shm_fence); - - ++chain->send_sbc; - xcb_void_cookie_t cookie = - xcb_present_pixmap(chain->conn, - chain->window, - image->pixmap, - (uint32_t) chain->send_sbc, - 0, /* valid */ - 0, /* update */ - 0, /* x_off */ - 0, /* y_off */ - XCB_NONE, /* target_crtc */ - XCB_NONE, - image->sync_fence, - options, - target_msc, - divisor, - remainder, 0, NULL); - xcb_discard_reply(chain->conn, cookie.sequence); - image->busy = true; - - xcb_flush(chain->conn); - - return VK_SUCCESS; -} - -static VkResult -x11_image_init(struct radv_device *device, struct x11_swapchain *chain, - const VkSwapchainCreateInfoKHR *pCreateInfo, - const VkAllocationCallbacks* pAllocator, - struct x11_image *image) -{ - xcb_void_cookie_t cookie; - VkResult result = VK_SUCCESS; - int fd; - VkImage image_h; - bool bret; - struct radeon_surf *surface; - result = radv_image_create(radv_device_to_handle(device), - &(struct radv_image_create_info) { - .vk_info = - &(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, - .arrayLayers = 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, - }, - .scanout = true}, - NULL, - &image_h); - if (result != VK_SUCCESS) - return result; - - image->image = radv_image_from_handle(image_h); - - VkDeviceMemory memory_h; - result = radv_AllocateMemory(radv_device_to_handle(device), - &(VkMemoryAllocateInfo) { - .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - .allocationSize = image->image->size, - .memoryTypeIndex = 0, - }, - NULL /* XXX: pAllocator */, - &memory_h); - if (result != VK_SUCCESS) - goto fail_create_image; - - image->memory = radv_device_memory_from_handle(memory_h); - // image->memory->bo.is_winsys_bo = true; - - radv_BindImageMemory(VK_NULL_HANDLE, image_h, memory_h, 0); - - bret = device->ws->buffer_get_fd(device->ws, - image->memory->bo, &fd); - if (bret == false) - goto fail_alloc_memory; - - { - struct radeon_bo_metadata metadata; - radv_init_metadata(device, image->image, &metadata); - device->ws->buffer_set_metadata(image->memory->bo, &metadata); - } - surface = &image->image->surface; - uint32_t bpp = 32; - uint32_t depth = 24; - image->pixmap = xcb_generate_id(chain->conn); - - cookie = - xcb_dri3_pixmap_from_buffer_checked(chain->conn, - image->pixmap, - chain->window, - image->image->size, - pCreateInfo->imageExtent.width, - pCreateInfo->imageExtent.height, - surface->level[0].pitch_bytes, - depth, bpp, fd); - xcb_discard_reply(chain->conn, cookie.sequence); - - int fence_fd = xshmfence_alloc_shm(); - if (fence_fd < 0) - goto fail_pixmap; - - image->shm_fence = xshmfence_map_shm(fence_fd); - if (image->shm_fence == NULL) - goto fail_shmfence_alloc; - - image->sync_fence = xcb_generate_id(chain->conn); - xcb_dri3_fence_from_fd(chain->conn, - image->pixmap, - image->sync_fence, - false, - fence_fd); - - image->busy = false; - xshmfence_trigger(image->shm_fence); - - return VK_SUCCESS; - -fail_shmfence_alloc: - close(fence_fd); - -fail_pixmap: - cookie = xcb_free_pixmap(chain->conn, image->pixmap); - xcb_discard_reply(chain->conn, cookie.sequence); - -fail_alloc_memory: - radv_FreeMemory(radv_device_to_handle(chain->base.device), - radv_device_memory_to_handle(image->memory), pAllocator); - -fail_create_image: - radv_DestroyImage(radv_device_to_handle(chain->base.device), - radv_image_to_handle(image->image), pAllocator); - - return result; -} - -static void -x11_image_finish(struct x11_swapchain *chain, - const VkAllocationCallbacks* pAllocator, - struct x11_image *image) -{ - xcb_void_cookie_t cookie; - - cookie = xcb_sync_destroy_fence(chain->conn, image->sync_fence); - xcb_discard_reply(chain->conn, cookie.sequence); - xshmfence_unmap_shm(image->shm_fence); - - cookie = xcb_free_pixmap(chain->conn, image->pixmap); - xcb_discard_reply(chain->conn, cookie.sequence); - - radv_DestroyImage(radv_device_to_handle(chain->base.device), - radv_image_to_handle(image->image), pAllocator); - - radv_FreeMemory(radv_device_to_handle(chain->base.device), - radv_device_memory_to_handle(image->memory), pAllocator); - -} - -static VkResult -x11_swapchain_destroy(struct radv_swapchain *radv_chain, - const VkAllocationCallbacks *pAllocator) -{ - struct x11_swapchain *chain = (struct x11_swapchain *)radv_chain; - - for (uint32_t i = 0; i < chain->image_count; i++) - x11_image_finish(chain, pAllocator, &chain->images[i]); - - xcb_unregister_for_special_event(chain->conn, chain->special_event); - - vk_free2(&chain->base.device->alloc, pAllocator, chain); - - return VK_SUCCESS; -} - -static VkResult -x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface, - struct radv_device *device, - const VkSwapchainCreateInfoKHR *pCreateInfo, - const VkAllocationCallbacks* pAllocator, - struct radv_swapchain **swapchain_out) -{ - struct x11_swapchain *chain; - xcb_void_cookie_t cookie; - VkResult result; - - assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR); - - int num_images = pCreateInfo->minImageCount; - - /* For true mailbox mode, we need at least 4 images: - * 1) One to scan out from - * 2) One to have queued for scan-out - * 3) One to be currently held by the Wayland compositor - * 4) One to render to - */ - if (pCreateInfo->presentMode == VK_PRESENT_MODE_MAILBOX_KHR) - num_images = MAX2(num_images, 4); - - size_t size = sizeof(*chain) + num_images * sizeof(chain->images[0]); - chain = vk_alloc2(&device->alloc, pAllocator, size, 8, - VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); - if (chain == NULL) - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); - - chain->base.device = device; - chain->base.destroy = x11_swapchain_destroy; - chain->base.get_images = x11_get_images; - chain->base.acquire_next_image = x11_acquire_next_image; - chain->base.queue_present = x11_queue_present; - - chain->conn = x11_surface_get_connection(icd_surface); - chain->window = x11_surface_get_window(icd_surface); - chain->extent = pCreateInfo->imageExtent; - chain->image_count = num_images; - - chain->send_sbc = 0; - chain->event_id = xcb_generate_id(chain->conn); - xcb_present_select_input(chain->conn, chain->event_id, chain->window, - XCB_PRESENT_EVENT_MASK_CONFIGURE_NOTIFY | - XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY | - XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY); - - /* Create an XCB event queue to hold present events outside of the usual - * application event queue - */ - chain->special_event = - xcb_register_for_special_xge(chain->conn, &xcb_present_id, - chain->event_id, NULL); - - chain->gc = xcb_generate_id(chain->conn); - if (!chain->gc) { - /* FINISHME: Choose a better error. */ - result = vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); - goto fail_register; - } - - cookie = xcb_create_gc(chain->conn, - chain->gc, - chain->window, - XCB_GC_GRAPHICS_EXPOSURES, - (uint32_t []) { 0 }); - xcb_discard_reply(chain->conn, cookie.sequence); - - uint32_t image = 0; - for (; image < chain->image_count; image++) { - result = x11_image_init(device, chain, pCreateInfo, pAllocator, - &chain->images[image]); - if (result != VK_SUCCESS) - goto fail_init_images; - } - - *swapchain_out = &chain->base; - - return VK_SUCCESS; - -fail_init_images: - for (uint32_t j = 0; j < image; j++) - x11_image_finish(chain, pAllocator, &chain->images[j]); - -fail_register: - xcb_unregister_for_special_event(chain->conn, chain->special_event); - - vk_free2(&device->alloc, pAllocator, chain); - - return result; -} - -VkResult -radv_x11_init_wsi(struct radv_physical_device *device) -{ - struct wsi_x11 *wsi; - VkResult result; - - wsi = vk_alloc(&device->instance->alloc, sizeof(*wsi), 8, - VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); - if (!wsi) { - result = vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); - goto fail; - } - - int ret = pthread_mutex_init(&wsi->mutex, NULL); - if (ret != 0) { - if (ret == ENOMEM) { - result = vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); - } else { - /* FINISHME: Choose a better error. */ - result = vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); - } - - goto fail_alloc; - } - - wsi->connections = _mesa_hash_table_create(NULL, _mesa_hash_pointer, - _mesa_key_pointer_equal); - if (!wsi->connections) { - result = vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); - goto fail_mutex; - } - - wsi->base.get_support = x11_surface_get_support; - wsi->base.get_capabilities = x11_surface_get_capabilities; - wsi->base.get_formats = x11_surface_get_formats; - wsi->base.get_present_modes = x11_surface_get_present_modes; - wsi->base.create_swapchain = x11_surface_create_swapchain; - - device->wsi[VK_ICD_WSI_PLATFORM_XCB] = &wsi->base; - device->wsi[VK_ICD_WSI_PLATFORM_XLIB] = &wsi->base; - - return VK_SUCCESS; - -fail_mutex: - pthread_mutex_destroy(&wsi->mutex); -fail_alloc: - vk_free(&device->instance->alloc, wsi); -fail: - device->wsi[VK_ICD_WSI_PLATFORM_XCB] = NULL; - device->wsi[VK_ICD_WSI_PLATFORM_XLIB] = NULL; - - return result; -} - -void -radv_x11_finish_wsi(struct radv_physical_device *device) + VkInstance _instance, + const VkXlibSurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface) { - struct wsi_x11 *wsi = - (struct wsi_x11 *)device->wsi[VK_ICD_WSI_PLATFORM_XCB]; + RADV_FROM_HANDLE(radv_instance, instance, _instance); + const VkAllocationCallbacks *alloc; - if (wsi) { - _mesa_hash_table_destroy(wsi->connections, NULL); + assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR); - pthread_mutex_destroy(&wsi->mutex); + if (pAllocator) + alloc = pAllocator; + else + alloc = &instance->alloc; - vk_free(&device->instance->alloc, wsi); - } + return wsi_create_xlib_surface(alloc, pCreateInfo, pSurface); } |