From: Rosen Zhelev Date: Thu, 22 Jul 2021 22:49:15 +0000 (+0100) Subject: wsi: Move common objects to the wayland wsi::surface X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=24f18c6c44162b005a58c6639badb0c6e6ef68b0;p=platform%2Fcore%2Fuifw%2Fvulkan-wsi-tizen.git wsi: Move common objects to the wayland wsi::surface Moves data and Wayland objects such as the registry to the wsi::wayland::surface implementation. This also fixes a few issues with queries where the Wayland display's default queue was wrongly used and minimizes leaking of server memory from registry creation. Moves the ownership of the zwp_linux_dmabuf_interface object to the wsi::wayland::surface as it can be shared between swapchains. Fixes issues with casting VkSurfaces in the Wayland backend that can fail when using other layers that wrap the object. Change-Id: Ibacf0d4229b73bd685254507f52e58d6341aa9b6 Signed-off-by: Rosen Zhelev --- diff --git a/wsi/wayland/surface.cpp b/wsi/wayland/surface.cpp index f70d3d5..a22f6e8 100644 --- a/wsi/wayland/surface.cpp +++ b/wsi/wayland/surface.cpp @@ -29,22 +29,198 @@ #include "surface.hpp" #include "swapchain.hpp" #include "surface_properties.hpp" +#include "wl_object_owner.hpp" +#include "wl_helpers.hpp" +#include "util/log.hpp" namespace wsi { namespace wayland { +struct formats_vector +{ + util::vector *formats{nullptr}; + bool is_out_of_memory{false}; +}; + +namespace +{ +/* Handler for format event of the zwp_linux_dmabuf_v1 interface. */ +extern "C" void zwp_linux_dmabuf_v1_format_impl(void *data, struct zwp_linux_dmabuf_v1 *dma_buf, uint32_t drm_format) +{ +} + +/* Handler for modifier event of the zwp_linux_dmabuf_v1 interface. */ +extern "C" void zwp_linux_dmabuf_v1_modifier_impl(void *data, struct zwp_linux_dmabuf_v1 *dma_buf, uint32_t drm_format, + uint32_t modifier_hi, uint32_t modifier_low) +{ + auto *drm_supported_formats = reinterpret_cast(data); + + drm_format_pair format = {}; + format.fourcc = drm_format; + format.modifier = (static_cast(modifier_hi) << 32) | modifier_low; + + if (!drm_supported_formats->is_out_of_memory) + { + drm_supported_formats->is_out_of_memory = !drm_supported_formats->formats->try_push_back(format); + } +} +} // namespace + +/* + * @brief Get supported formats and modifiers using the zwp_linux_dmabuf_v1 interface. + * + * @param[in] display The wl_display that is being used. + * @param[in] queue The wl_event_queue set for the @p dmabuf_interface + * @param[in] dmabuf_interface Object of the zwp_linux_dmabuf_v1 interface. + * @param[out] supported_formats Vector which will contain the supported drm + * formats and their modifiers. + * + * @retval VK_SUCCESS Indicates success. + * @retval VK_ERROR_UNKNOWN Indicates one of the Wayland functions failed. + * @retval VK_ERROR_OUT_OF_DEVICE_MEMORY Indicates the host went out of memory. + */ +static VkResult get_supported_formats_and_modifiers(wl_display *display, wl_event_queue *queue, + zwp_linux_dmabuf_v1 *dmabuf_interface, + util::vector &supported_formats) +{ + formats_vector drm_supported_formats; + drm_supported_formats.formats = &supported_formats; + + const zwp_linux_dmabuf_v1_listener dma_buf_listener = { + .format = zwp_linux_dmabuf_v1_format_impl, + .modifier = zwp_linux_dmabuf_v1_modifier_impl, + }; + int res = zwp_linux_dmabuf_v1_add_listener(dmabuf_interface, &dma_buf_listener, &drm_supported_formats); + if (res < 0) + { + WSI_LOG_ERROR("Failed to add zwp_linux_dmabuf_v1 listener."); + return VK_ERROR_UNKNOWN; + } + + /* Get all modifier events. */ + res = wl_display_roundtrip_queue(display, queue); + if (res < 0) + { + WSI_LOG_ERROR("Roundtrip failed."); + return VK_ERROR_UNKNOWN; + } + + if (drm_supported_formats.is_out_of_memory) + { + WSI_LOG_ERROR("Host got out of memory."); + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + + return VK_SUCCESS; +} + +struct surface::init_parameters +{ + const util::allocator& allocator; + wl_display *display; + wl_surface *surf; +}; + +surface::surface(const init_parameters ¶ms) + : wsi::surface() + , wayland_display(params.display) + , wayland_surface(params.surf) + , supported_formats(params.allocator) + , properties(*this, params.allocator) + , surface_queue(nullptr) +{ +} + +bool surface::init() +{ + surface_queue = wl_display_create_queue(wayland_display); + + if (surface_queue == nullptr) + { + WSI_LOG_ERROR("Failed to create wl surface queue."); + return false; + } + + auto display_proxy = make_proxy_with_queue(wayland_display, surface_queue); + if (display_proxy == nullptr) + { + WSI_LOG_ERROR("Failed to create wl display proxy."); + return false; + }; + + auto registry = registry_owner{ wl_display_get_registry(display_proxy.get()) }; + if (registry == nullptr) + { + WSI_LOG_ERROR("Failed to get wl display registry."); + return false; + } + + const wl_registry_listener registry_listener = { registry_handler }; + int res = wl_registry_add_listener(registry.get(), ®istry_listener, &dmabuf_interface); + if (res < 0) + { + WSI_LOG_ERROR("Failed to add registry listener."); + return false; + } + + res = wl_display_roundtrip_queue(wayland_display, surface_queue); + if (res < 0) + { + WSI_LOG_ERROR("Roundtrip failed."); + return false; + } + + if (dmabuf_interface.get() == nullptr) + { + WSI_LOG_ERROR("Failed to obtain zwp_linux_dma_buf_v1 interface."); + return false; + } + + VkResult vk_res = + get_supported_formats_and_modifiers(wayland_display, surface_queue, dmabuf_interface.get(), supported_formats); + if (vk_res != VK_SUCCESS) + { + return false; + } + + return true; +} + +util::unique_ptr surface::make_surface(const util::allocator &allocator, wl_display *display, + wl_surface *surf) +{ + init_parameters params {allocator, display, surf}; + auto wsi_surface = allocator.make_unique(params); + if (wsi_surface != nullptr) + { + if (wsi_surface->init()) + { + return wsi_surface; + } + } + return nullptr; +} + +surface::~surface() +{ + if (surface_queue != nullptr) + { + wl_event_queue_destroy(surface_queue); + } +} + wsi::surface_properties &surface::get_properties() { - return surface_properties::get_instance(); + return properties; } util::unique_ptr surface::allocate_swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *allocator) { util::allocator alloc{ dev_data.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT, allocator }; - return util::unique_ptr(alloc.make_unique(dev_data, allocator)); + return util::unique_ptr(alloc.make_unique(dev_data, allocator, *this)); } } // namespace wayland diff --git a/wsi/wayland/surface.hpp b/wsi/wayland/surface.hpp index 12c1462..8bc0fdb 100644 --- a/wsi/wayland/surface.hpp +++ b/wsi/wayland/surface.hpp @@ -28,21 +28,104 @@ #pragma once +#include + #include "wsi/surface.hpp" +#include "surface_properties.hpp" +#include "wl_object_owner.hpp" namespace wsi { namespace wayland { +struct drm_format_pair +{ + uint32_t fourcc; + uint64_t modifier; +}; + class surface : public wsi::surface { public: - surface() = default; + surface() = delete; + struct init_parameters; + + /** Constructor to allow for custom allocation, but require privately defined arguments. */ + surface(const init_parameters&); + + /** + * @brief Allocates and initializes a surface + * + * @param allocator An allocator to use for host allocations needed for the surface. + * @param display The Wayland display used to create the VkSurface + * @param surf The Wayland surface used to create the VkSurface + * + * @return A constructed and initalized surface or nullptr on failure + */ + static util::unique_ptr make_surface(const util::allocator &allocator, wl_display *display, + wl_surface *surf); + + /** Destructor */ + ~surface() override; wsi::surface_properties &get_properties() override; util::unique_ptr allocate_swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *allocator) override; + + /** Returns the Wayland display */ + wl_display *get_wl_display() const + { + return wayland_display; + } + + /** Returns the Wayland surface */ + wl_surface *get_wl_surface() const + { + return wayland_surface; + } + + /** + * @brief Returns a pointer to the Wayland zwp_linux_dmabuf_v1 interface. + * + * The raw pointer is valid throughout the lifetime of this surface. + */ + zwp_linux_dmabuf_v1 *get_dmabuf_interface() + { + return dmabuf_interface.get(); + } + + /** + * @brief Returns a reference to a list of DRM formats supported by the Wayland surface. + * + * The reference is valid throughout the lifetime of this surface. + */ + const util::vector &get_formats() const + { + return supported_formats; + } + +private: + /** + * @brief Initialize the WSI surface by creating Wayland queues and linking to Wayland protocols. + * + * @return true on success, false otherwise. + */ + bool init(); + + /** The native Wayland display */ + wl_display *wayland_display; + /** The native Wayland surface */ + wl_surface *wayland_surface; + /** A list of DRM formats supported by the Wayland compositor on this surface */ + util::vector supported_formats; + /** Surface properties specific to the Wayland surface. */ + surface_properties properties; + + /** Container for the zwp_linux_dmabuf_v1 interface binding */ + zwp_linux_dmabuf_v1_owner dmabuf_interface; + /** Private queue for surface events generated by the layer */ + wl_event_queue *surface_queue; }; } // namespace wayland diff --git a/wsi/wayland/surface_properties.cpp b/wsi/wayland/surface_properties.cpp index 2da5e1d..7622c4a 100644 --- a/wsi/wayland/surface_properties.cpp +++ b/wsi/wayland/surface_properties.cpp @@ -47,15 +47,17 @@ namespace wsi namespace wayland { -struct vk_format_hasher +surface_properties::surface_properties(surface &wsi_surface, const util::allocator &allocator) + : specific_surface(&wsi_surface) + , supported_formats(allocator) { - size_t operator()(const VkFormat format) const - { - return std::hash()(static_cast(format)); - } -}; +} -using vk_format_set = std::unordered_set; +surface_properties::surface_properties() + : specific_surface(nullptr) + , supported_formats(util::allocator::get_generic()) +{ +} surface_properties &surface_properties::get_instance() { @@ -100,118 +102,64 @@ VkResult surface_properties::get_surface_capabilities(VkPhysicalDevice physical_ return VK_SUCCESS; } -static void get_vk_supported_formats(const util::vector &drm_supported_formats, - vk_format_set &vk_supported_formats) +static VkResult get_vk_supported_formats(const util::vector &drm_supported_formats, + vk_format_set &vk_supported_formats) { for (const auto &drm_format : drm_supported_formats) { const VkFormat vk_format = util::drm::drm_to_vk_format(drm_format.fourcc); if (vk_format != VK_FORMAT_UNDEFINED) { - const VkFormat srgb_vk_format = util::drm::drm_to_vk_srgb_format(drm_format.fourcc); - if (srgb_vk_format != VK_FORMAT_UNDEFINED) + auto it = vk_supported_formats.try_insert(vk_format); + if (!it.has_value()) { - vk_supported_formats.insert({srgb_vk_format, vk_format}); + return VK_ERROR_OUT_OF_HOST_MEMORY; } - else + } + const VkFormat srgb_vk_format = util::drm::drm_to_vk_srgb_format(drm_format.fourcc); + if (srgb_vk_format != VK_FORMAT_UNDEFINED) + { + auto it = vk_supported_formats.try_insert(srgb_vk_format); + if (!it.has_value()) { - vk_supported_formats.insert(vk_format); + return VK_ERROR_OUT_OF_HOST_MEMORY; } } } -} - -/* - * @brief Query a surface's supported formats from the compositor. - * - * @details A wl_registry is created in order to get a zwp_linux_dmabuf_v1 object. - * Then a listener is attached to that object in order to get the supported formats - * from the server. The supported formats are stored in @p vk_supported_formats. - * - * @param[in] surface The surface, which the supported formats - * are for. - * @param[out] vk_supported_formats unordered_set which will store the supported - * formats. - * - * @retval VK_SUCCESS Indicates success. - * @retval VK_ERROR_SURFACE_LOST_KHR Indicates one of the Wayland functions failed. - * @retval VK_ERROR_OUT_OF_DEVICE_MEMORY Indicates the host went out of memory. - */ -static VkResult query_supported_formats( - const VkSurfaceKHR surface, vk_format_set &vk_supported_formats, const util::allocator& allocator) -{ - const VkIcdSurfaceWayland *vk_surf = reinterpret_cast(surface); - wl_display *display = vk_surf->display; - - auto registry = registry_owner{wl_display_get_registry(display)}; - if (registry.get() == nullptr) - { - WSI_LOG_ERROR("Failed to get wl display registry."); - return VK_ERROR_SURFACE_LOST_KHR; - } - - auto dmabuf_interface = zwp_linux_dmabuf_v1_owner{nullptr}; - const wl_registry_listener registry_listener = { registry_handler }; - int res = wl_registry_add_listener(registry.get(), ®istry_listener, &dmabuf_interface); - if (res < 0) - { - WSI_LOG_ERROR("Failed to add registry listener."); - return VK_ERROR_SURFACE_LOST_KHR; - } - - /* Get the dma buf interface. */ - res = wl_display_roundtrip(display); - if (res < 0) - { - WSI_LOG_ERROR("Roundtrip failed."); - return VK_ERROR_SURFACE_LOST_KHR; - } - - if (dmabuf_interface.get() == nullptr) - { - return VK_ERROR_SURFACE_LOST_KHR; - } - - util::vector drm_supported_formats{allocator}; - const VkResult ret = get_supported_formats_and_modifiers(display, dmabuf_interface.get(), drm_supported_formats); - if (ret != VK_SUCCESS) - { - return ret == VK_ERROR_UNKNOWN ? VK_ERROR_SURFACE_LOST_KHR : ret; - } - - get_vk_supported_formats(drm_supported_formats, vk_supported_formats); - - return ret; + return VK_SUCCESS; } VkResult surface_properties::get_surface_formats(VkPhysicalDevice physical_device, VkSurfaceKHR surface, uint32_t *surfaceFormatCount, VkSurfaceFormatKHR *surfaceFormats) { - vk_format_set formats; - auto &instance = layer::instance_private_data::get(physical_device); - const auto query_res = query_supported_formats(surface, formats, instance.get_allocator()); - if (query_res != VK_SUCCESS) + + assert(specific_surface); + if (!supported_formats.size()) { - return query_res; + VkResult res = get_vk_supported_formats(specific_surface->get_formats(), supported_formats); + if (res != VK_SUCCESS) + { + return res; + } } assert(surfaceFormatCount != nullptr); if (nullptr == surfaceFormats) { - *surfaceFormatCount = formats.size(); + *surfaceFormatCount = supported_formats.size(); return VK_SUCCESS; } VkResult res = VK_SUCCESS; - if (formats.size() > *surfaceFormatCount) + if (supported_formats.size() > *surfaceFormatCount) { res = VK_INCOMPLETE; } uint32_t format_count = 0; - for (const auto &format : formats) + for (const auto &format : supported_formats) { if (format_count >= *surfaceFormatCount) { @@ -287,15 +235,17 @@ extern "C" VkResult CreateWaylandSurfaceKHR(VkInstance instance, const VkWayland { auto &instance_data = layer::instance_private_data::get(instance); util::allocator allocator{ instance_data.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT, pAllocator }; - auto wsi_surface = util::unique_ptr(allocator.make_unique()); + auto wsi_surface = surface::make_surface(allocator, pCreateInfo->display, pCreateInfo->surface); if (wsi_surface == nullptr) { return VK_ERROR_OUT_OF_HOST_MEMORY; } + VkResult res = instance_data.disp.CreateWaylandSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface); if (res == VK_SUCCESS) { - res = instance_data.add_surface(*pSurface, wsi_surface); + auto surface_base = util::unique_ptr(std::move(wsi_surface)); + res = instance_data.add_surface(*pSurface, surface_base); if (res != VK_SUCCESS) { instance_data.disp.DestroySurfaceKHR(instance, *pSurface, pAllocator); diff --git a/wsi/wayland/surface_properties.hpp b/wsi/wayland/surface_properties.hpp index 755c9c4..75e4491 100644 --- a/wsi/wayland/surface_properties.hpp +++ b/wsi/wayland/surface_properties.hpp @@ -25,15 +25,30 @@ #pragma once #include "wsi/surface_properties.hpp" +#include "util/unordered_set.hpp" namespace wsi { namespace wayland { +struct vk_format_hasher +{ + size_t operator()(const VkFormat format) const + { + return std::hash()(static_cast(format)); + } +}; + +using vk_format_set = util::unordered_set; + +class surface; + class surface_properties : public wsi::surface_properties { public: + surface_properties(surface &wsi_surface, const util::allocator &alloc); + static surface_properties &get_instance(); VkResult get_surface_capabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface, @@ -46,6 +61,16 @@ public: VkResult get_required_device_extensions(util::extension_list &extension_list) override; PFN_vkVoidFunction get_proc_addr(const char *name) override; + +private: + surface_properties(); + + /** If the properties are specific to a @ref wsi::wayland::surface this is a pointer to it. Can be nullptr for + * generic Wayland surface properties. + */ + surface *specific_surface; + /** Set of supported Vulkan formats by the @ref specific_surface. */ + vk_format_set supported_formats; }; } // namespace wayland diff --git a/wsi/wayland/swapchain.cpp b/wsi/wayland/swapchain.cpp index d7a00f7..5ea2e48 100644 --- a/wsi/wayland/swapchain.cpp +++ b/wsi/wayland/swapchain.cpp @@ -26,6 +26,7 @@ #include "swapchain.hpp" #include "wl_helpers.hpp" +#include "surface_properties.hpp" #include #include @@ -47,24 +48,6 @@ namespace wsi namespace wayland { -template -static std::unique_ptr> -make_proxy_with_queue(T *object, wl_event_queue *queue) -{ - auto proxy = reinterpret_cast(wl_proxy_create_wrapper(object)); - if (proxy != nullptr) - { - wl_proxy_set_queue(reinterpret_cast(proxy), queue); - } - - auto delete_proxy = [](T *proxy) - { - wl_proxy_wrapper_destroy(reinterpret_cast(proxy)); - }; - - return std::unique_ptr>(proxy, delete_proxy); -} - const VkImageAspectFlagBits plane_flag_bits[MAX_PLANES] = { VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT, VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT, @@ -84,12 +67,13 @@ struct swapchain::wayland_image_data uint32_t num_planes; }; -swapchain::swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *pAllocator) +swapchain::swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *pAllocator, + surface &wsi_surface) : swapchain_base(dev_data, pAllocator) - , m_display(nullptr) - , m_surface(nullptr) - , m_dmabuf_interface(nullptr) - , m_surface_queue(nullptr) + , m_display(wsi_surface.get_wl_display()) + , m_surface(wsi_surface.get_wl_surface()) + , m_dmabuf_interface(wsi_surface.get_dmabuf_interface()) + , m_swapchain_queue(nullptr) , m_buffer_queue(nullptr) , m_wsi_allocator(nullptr) , m_present_pending(false) @@ -102,9 +86,9 @@ swapchain::~swapchain() wsialloc_delete(m_wsi_allocator); m_wsi_allocator = nullptr; - if (m_surface_queue != nullptr) + if (m_swapchain_queue != nullptr) { - wl_event_queue_destroy(m_surface_queue); + wl_event_queue_destroy(m_swapchain_queue); } if (m_buffer_queue != nullptr) { @@ -112,65 +96,25 @@ swapchain::~swapchain() } } -struct display_queue -{ - wl_display *display; - wl_event_queue *queue; -}; - VkResult swapchain::init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *pSwapchainCreateInfo) { - VkIcdSurfaceWayland *vk_surf = reinterpret_cast(pSwapchainCreateInfo->surface); - - m_display = vk_surf->display; - m_surface = vk_surf->surface; - - m_surface_queue = wl_display_create_queue(m_display); - - if (m_surface_queue == nullptr) + if ((m_display == nullptr) || (m_surface == nullptr) || (m_dmabuf_interface == nullptr)) { - WSI_LOG_ERROR("Failed to create wl surface display_queue."); return VK_ERROR_INITIALIZATION_FAILED; } - m_buffer_queue = wl_display_create_queue(m_display); - if (m_buffer_queue == nullptr) - { - WSI_LOG_ERROR("Failed to create wl buffer display_queue."); - return VK_ERROR_INITIALIZATION_FAILED; - } - - auto display_proxy = make_proxy_with_queue(m_display, m_surface_queue); - if (display_proxy == nullptr) - { - WSI_LOG_ERROR("Failed to create wl display proxy."); - return VK_ERROR_INITIALIZATION_FAILED; - } + m_swapchain_queue = wl_display_create_queue(m_display); - auto registry = registry_owner{ wl_display_get_registry(display_proxy.get()) }; - if (registry == nullptr) + if (m_swapchain_queue == nullptr) { - WSI_LOG_ERROR("Failed to get wl display registry."); + WSI_LOG_ERROR("Failed to create swapchain wl queue."); return VK_ERROR_INITIALIZATION_FAILED; } - const wl_registry_listener registry_listener = { registry_handler }; - int res = wl_registry_add_listener(registry.get(), ®istry_listener, &m_dmabuf_interface); - if (res < 0) - { - WSI_LOG_ERROR("Failed to add registry listener."); - return VK_ERROR_INITIALIZATION_FAILED; - } - - res = wl_display_roundtrip_queue(m_display, m_surface_queue); - if (res < 0) - { - WSI_LOG_ERROR("Roundtrip failed."); - return VK_ERROR_INITIALIZATION_FAILED; - } - - if (m_dmabuf_interface.get() == nullptr) + m_buffer_queue = wl_display_create_queue(m_display); + if (m_buffer_queue == nullptr) { + WSI_LOG_ERROR("Failed to create buffer wl queue."); return VK_ERROR_INITIALIZATION_FAILED; } @@ -594,7 +538,7 @@ VkResult swapchain::create_image(VkImageCreateInfo image_create_info, swapchain_ } /* create a wl_buffer using the dma_buf protocol */ - auto dmabuf_interface_proxy = make_proxy_with_queue(m_dmabuf_interface.get(), m_surface_queue); + auto dmabuf_interface_proxy = make_proxy_with_queue(m_dmabuf_interface, m_swapchain_queue); if (dmabuf_interface_proxy == nullptr) { WSI_LOG_ERROR("Failed to allocate dma-buf interface proxy."); @@ -622,7 +566,7 @@ VkResult swapchain::create_image(VkImageCreateInfo image_create_info, swapchain_ /* TODO: don't roundtrip - we should be able to send the create request now, * and only wait for it on first present. only do this once, not for all buffers created */ - res = wl_display_roundtrip_queue(m_display, m_surface_queue); + res = wl_display_roundtrip_queue(m_display, m_swapchain_queue); if (res < 0) { destroy_image(image); @@ -679,7 +623,7 @@ void swapchain::present_image(uint32_t pendingIndex) * time if the compositor isn't responding (perhaps because the * window is hidden). */ - res = dispatch_queue(m_display, m_surface_queue, -1); + res = dispatch_queue(m_display, m_swapchain_queue, -1); } while (res > 0 && m_present_pending); if (res <= 0) @@ -697,7 +641,7 @@ void swapchain::present_image(uint32_t pendingIndex) if (m_present_mode == VK_PRESENT_MODE_FIFO_KHR) { /* request a hint when we can present the _next_ frame */ - auto surface_proxy = make_proxy_with_queue(m_surface, m_surface_queue); + auto surface_proxy = make_proxy_with_queue(m_surface, m_swapchain_queue); if (surface_proxy == nullptr) { WSI_LOG_ERROR("failed to create wl_surface proxy"); diff --git a/wsi/wayland/swapchain.hpp b/wsi/wayland/swapchain.hpp index d9941fe..2f99ad3 100644 --- a/wsi/wayland/swapchain.hpp +++ b/wsi/wayland/swapchain.hpp @@ -34,6 +34,7 @@ extern "C" { #include #include "util/wsialloc/wsialloc.h" #include "wl_object_owner.hpp" +#include "surface.hpp" namespace wsi { @@ -43,7 +44,8 @@ namespace wayland class swapchain : public wsi::swapchain_base { public: - explicit swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *allocator); + explicit swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *allocator, + surface &wsi_surface); ~swapchain(); @@ -108,10 +110,9 @@ private: struct wl_display *m_display; struct wl_surface *m_surface; - zwp_linux_dmabuf_v1_owner m_dmabuf_interface; - + struct zwp_linux_dmabuf_v1 *m_dmabuf_interface; /* The queue on which we dispatch the swapchain related events, mostly frame completion */ - struct wl_event_queue *m_surface_queue; + struct wl_event_queue *m_swapchain_queue; /* The queue on which we dispatch buffer related events, mostly buffer_release */ struct wl_event_queue *m_buffer_queue; diff --git a/wsi/wayland/wl_helpers.cpp b/wsi/wayland/wl_helpers.cpp index 1d453c2..0d400b4 100644 --- a/wsi/wayland/wl_helpers.cpp +++ b/wsi/wayland/wl_helpers.cpp @@ -34,73 +34,6 @@ #include "util/log.hpp" -struct formats_vector -{ - util::vector *formats{nullptr}; - bool is_out_of_memory{false}; -}; - -namespace -{ - /* Handler for format event of the zwp_linux_dmabuf_v1 interface. */ - extern "C" void dma_buf_format_handler(void *data, - struct zwp_linux_dmabuf_v1 *dma_buf, - uint32_t drm_format) {} - - /* Handler for modifier event of the zwp_linux_dmabuf_v1 interface. */ - extern "C" void dma_buf_modifier_handler(void *data, - struct zwp_linux_dmabuf_v1 *dma_buf, - uint32_t drm_format, uint32_t modifier_hi, - uint32_t modifier_low) - { - auto *drm_supported_formats = reinterpret_cast(data); - - drm_format_pair format = {}; - format.fourcc = drm_format; - format.modifier = (static_cast(modifier_hi) << 32) | modifier_low; - - if (!drm_supported_formats->formats->try_push_back(format)) - { - drm_supported_formats->is_out_of_memory = true; - } - } -} - -VkResult get_supported_formats_and_modifiers( - wl_display* display, zwp_linux_dmabuf_v1 *dmabuf_interface, - util::vector &supported_formats) -{ - formats_vector drm_supported_formats; - drm_supported_formats.formats = &supported_formats; - - const zwp_linux_dmabuf_v1_listener dma_buf_listener = { - .format = dma_buf_format_handler, .modifier = dma_buf_modifier_handler, - }; - int res = zwp_linux_dmabuf_v1_add_listener(dmabuf_interface, &dma_buf_listener, - &drm_supported_formats); - if (res < 0) - { - WSI_LOG_ERROR("Failed to add zwp_linux_dmabuf_v1 listener."); - return VK_ERROR_UNKNOWN; - } - - /* Get all modifier events. */ - res = wl_display_roundtrip(display); - if (res < 0) - { - WSI_LOG_ERROR("Roundtrip failed."); - return VK_ERROR_UNKNOWN; - } - - if (drm_supported_formats.is_out_of_memory) - { - WSI_LOG_ERROR("Host got out of memory."); - return VK_ERROR_OUT_OF_HOST_MEMORY; - } - - return VK_SUCCESS; -} - extern "C" { void registry_handler(void *data, struct wl_registry *wl_registry, uint32_t name, const char *interface, diff --git a/wsi/wayland/wl_helpers.hpp b/wsi/wayland/wl_helpers.hpp index f1a6369..e19093f 100644 --- a/wsi/wayland/wl_helpers.hpp +++ b/wsi/wayland/wl_helpers.hpp @@ -28,27 +28,6 @@ #include #include #include "util/custom_allocator.hpp" -struct drm_format_pair -{ - uint32_t fourcc; - uint64_t modifier; -}; - -/* - * @brief Get supported formats and modifiers using the zwp_linux_dmabuf_v1 interface. - * - * @param[in] display The wl_display that is being used. - * @param[in] dmabuf_interface Object of the zwp_linux_dmabuf_v1 interface. - * @param[out] supported_formats Vector which will contain the supported drm - * formats and their modifiers. - * - * @retval VK_SUCCESS Indicates success. - * @retval VK_ERROR_UNKNOWN Indicates one of the Wayland functions failed. - * @retval VK_ERROR_OUT_OF_DEVICE_MEMORY Indicates the host went out of memory. - */ -VkResult get_supported_formats_and_modifiers( - struct wl_display* display, struct zwp_linux_dmabuf_v1 *dmabuf_interface, - util::vector &supported_formats); extern "C" { void registry_handler(void *data, struct wl_registry *wl_registry, uint32_t name, const char *interface, diff --git a/wsi/wayland/wl_object_owner.hpp b/wsi/wayland/wl_object_owner.hpp index fc5208d..c291c2d 100644 --- a/wsi/wayland/wl_object_owner.hpp +++ b/wsi/wayland/wl_object_owner.hpp @@ -57,5 +57,20 @@ struct dmabuf_deleter using registry_owner = std::unique_ptr; using zwp_linux_dmabuf_v1_owner = std::unique_ptr; + +template +static std::unique_ptr> make_proxy_with_queue(T *object, wl_event_queue *queue) +{ + auto proxy = reinterpret_cast(wl_proxy_create_wrapper(object)); + if (proxy != nullptr) + { + wl_proxy_set_queue(reinterpret_cast(proxy), queue); + } + + auto delete_proxy = [](T *proxy) { wl_proxy_wrapper_destroy(reinterpret_cast(proxy)); }; + + return std::unique_ptr>(proxy, delete_proxy); +} + } // namespace wayland } // namespace wsi