if(BUILD_WSI_WAYLAND)
add_library(wayland_wsi STATIC
wsi/wayland/surface_properties.cpp
+ wsi/wayland/surface.cpp
wsi/wayland/wl_helpers.cpp
wsi/wayland/swapchain.cpp)
wsi/swapchain_base.cpp
wsi/wsi_factory.cpp
wsi/headless/surface_properties.cpp
+ wsi/headless/surface.cpp
wsi/headless/swapchain.cpp)
target_compile_definitions(${PROJECT_NAME} PRIVATE ${WSI_DEFINES})
target_include_directories(${PROJECT_NAME} PRIVATE
GET_PROC_ADDR(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
GET_PROC_ADDR(vkGetPhysicalDeviceSurfaceFormatsKHR);
GET_PROC_ADDR(vkGetPhysicalDeviceSurfacePresentModesKHR);
+ GET_PROC_ADDR(vkDestroySurfaceKHR);
GET_PROC_ADDR(vkEnumerateDeviceExtensionProperties);
GET_PROC_ADDR(vkEnumerateInstanceLayerProperties);
#include "private_data.hpp"
#include "wsi/wsi_factory.hpp"
+#include "wsi/surface.hpp"
#include "util/unordered_map.hpp"
#include "util/log.hpp"
, SetInstanceLoaderData(set_loader_data)
, enabled_layer_platforms(enabled_layer_platforms)
, allocator(alloc)
+ , surfaces(alloc)
{
}
return get_instance_private_data(phys_dev);
}
-static VkIcdWsiPlatform get_platform_of_surface(VkSurfaceKHR surface)
+VkResult instance_private_data::add_surface(VkSurfaceKHR vk_surface, util::unique_ptr<wsi::surface> &wsi_surface)
{
- VkIcdSurfaceBase *surface_base = reinterpret_cast<VkIcdSurfaceBase *>(surface);
- return surface_base->platform;
+ scoped_mutex lock(surfaces_lock);
+
+ auto it = surfaces.find(vk_surface);
+ if (it != surfaces.end())
+ {
+ WSI_LOG_WARNING("Hash collision when adding new surface (%p). Old surface is replaced.",
+ reinterpret_cast<void *>(vk_surface));
+ surfaces.erase(it);
+ }
+
+ auto result = surfaces.try_insert(std::make_pair(vk_surface, nullptr));
+ if (result.has_value())
+ {
+ assert(result->second);
+ result->first->second = wsi_surface.release();
+ return VK_SUCCESS;
+ }
+
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+}
+
+wsi::surface *instance_private_data::get_surface(VkSurfaceKHR vk_surface)
+{
+ scoped_mutex lock(surfaces_lock);
+ auto it = surfaces.find(vk_surface);
+ if (it != surfaces.end())
+ {
+ return it->second;
+ }
+
+ return nullptr;
+}
+
+void instance_private_data::remove_surface(VkSurfaceKHR vk_surface, const util::allocator &alloc)
+{
+ scoped_mutex lock(surfaces_lock);
+ auto it = surfaces.find(vk_surface);
+ if (it != surfaces.end())
+ {
+ alloc.destroy<wsi::surface>(1, it->second);
+ surfaces.erase(it);
+ }
+ /* Failing to find a surface is not an error. It could have been created by a WSI extension, which is not handled
+ * by this layer.
+ */
}
bool instance_private_data::does_layer_support_surface(VkSurfaceKHR surface)
{
- return enabled_layer_platforms.contains(get_platform_of_surface(surface));
+ scoped_mutex lock(surfaces_lock);
+ auto it = surfaces.find(surface);
+ return it != surfaces.end();
}
void instance_private_data::destroy(instance_private_data *instance_data)
#include "util/platform_set.hpp"
#include "util/custom_allocator.hpp"
#include "util/unordered_set.hpp"
+#include "util/unordered_map.hpp"
#include <vulkan/vulkan.h>
#include <vulkan/vk_layer.h>
#include <vulkan/vk_icd.h>
+#include <vulkan/vulkan_wayland.h>
#include <memory>
#include <unordered_set>
using scoped_mutex = std::lock_guard<std::mutex>;
+/** Forward declare stored objects */
+namespace wsi
+{
+class surface;
+}
+
namespace layer
{
OPTIONAL(GetPhysicalDeviceSurfaceFormatsKHR) \
OPTIONAL(GetPhysicalDeviceSurfacePresentModesKHR) \
OPTIONAL(GetPhysicalDeviceSurfaceSupportKHR) \
+ OPTIONAL(CreateHeadlessSurfaceEXT) \
+ OPTIONAL(CreateWaylandSurfaceKHR) \
+ OPTIONAL(DestroySurfaceKHR) \
OPTIONAL(GetPhysicalDeviceImageFormatProperties2KHR) \
OPTIONAL(GetPhysicalDeviceFormatProperties2KHR) \
OPTIONAL(GetPhysicalDevicePresentRectanglesKHR)
static instance_private_data &get(VkPhysicalDevice phys_dev);
/**
+ * @brief Associate a VkSurface with a WSI surface object.
+ *
+ * @param vk_surface The VkSurface object created by the Vulkan implementation.
+ * @param wsi_surface The WSI layer object representing the surface.
+ *
+ * @return VK_SUCCESS or VK_ERROR_OUT_OF_HOST_MEMORY
+ *
+ * @note On success this transfers ownership of the WSI surface. The WSI surface is then explicitly destroyed by the
+ * user with @ref remove_surface
+ */
+ VkResult add_surface(VkSurfaceKHR vk_surface, util::unique_ptr<wsi::surface> &wsi_surface);
+
+ /**
+ * @brief Returns any associated WSI surface to the VkSurface.
+ *
+ * @param vk_surface The VkSurface object queried for association.
+ *
+ * @return nullptr or a raw pointer to the WSI surface.
+ *
+ * @note This returns a raw pointer that does not change any ownership. The user is responsible for ensuring that the
+ * pointer is valid as it explicitly controls the lifetime of the object.
+ */
+ wsi::surface *get_surface(VkSurfaceKHR vk_surface);
+
+ /**
+ * @brief Destroys any VkSurface associated WSI surface.
+ *
+ * @param vk_surface The VkSurface to check for associations.
+ * @param alloc The allocator to use if destroying a @ref wsi::surface object.
+ */
+ void remove_surface(VkSurfaceKHR vk_surface, const util::allocator &alloc);
+
+ /**
* @brief Get the set of enabled platforms that are also supported by the layer.
*/
const util::wsi_platform_set &get_enabled_platforms()
const PFN_vkSetInstanceLoaderData SetInstanceLoaderData;
const util::wsi_platform_set enabled_layer_platforms;
const util::allocator allocator;
+
+ /**
+ * @brief Container for all VkSurface objects tracked and supported by the Layer's WSI implementation.
+ *
+ * Uses plain pointers to store surface data as the lifetime of the object is explicitly controlled by the Vulkan
+ * application. The application may also use different but compatible host allocators on creation and destruction.
+ */
+ util::unordered_map<VkSurfaceKHR, wsi::surface *> surfaces;
+
+ /**
+ * @brief Lock for thread safe access to @ref surfaces
+ */
+ std::mutex surfaces_lock;
};
/**
auto &instance = layer::instance_private_data::get(physicalDevice);
if (instance.should_layer_handle_surface(physicalDevice, surface))
{
- wsi::surface_properties *props = wsi::get_surface_properties(surface);
+ wsi::surface_properties *props = wsi::get_surface_properties(instance, surface);
assert(props != nullptr);
return props->get_surface_capabilities(physicalDevice, surface, pSurfaceCapabilities);
}
auto &instance = layer::instance_private_data::get(physicalDevice);
if (instance.should_layer_handle_surface(physicalDevice, surface))
{
- wsi::surface_properties *props = wsi::get_surface_properties(surface);
+ wsi::surface_properties *props = wsi::get_surface_properties(instance, surface);
assert(props != nullptr);
return props->get_surface_formats(physicalDevice, surface, pSurfaceFormatCount, pSurfaceFormats);
}
auto &instance = layer::instance_private_data::get(physicalDevice);
if (instance.should_layer_handle_surface(physicalDevice, surface))
{
- wsi::surface_properties *props = wsi::get_surface_properties(surface);
+ wsi::surface_properties *props = wsi::get_surface_properties(instance, surface);
assert(props != nullptr);
return props->get_surface_present_modes(physicalDevice, surface, pPresentModeCount, pPresentModes);
}
return instance.disp.GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, pSupported);
}
+VKAPI_ATTR void wsi_layer_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface,
+ const VkAllocationCallbacks *pAllocator)
+{
+ auto &instance_data = layer::instance_private_data::get(instance);
+
+ instance_data.disp.DestroySurfaceKHR(instance, surface, pAllocator);
+
+ instance_data.remove_surface(
+ surface, util::allocator{ instance_data.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT, pAllocator });
+}
+
} /* extern "C" */
VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
uint32_t queueFamilyIndex, VkSurfaceKHR surface,
VkBool32 *pSupported);
+
+/**
+ * @brief Implements vkDestroySurfaceKHR Vulkan entrypoint.
+ */
+VKAPI_ATTR void wsi_layer_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface,
+ const VkAllocationCallbacks *pAllocator);
}
return device_data.disp.CreateSwapchainKHR(device_data.device, pSwapchainCreateInfo, pAllocator, pSwapchain);
}
- wsi::swapchain_base *sc = wsi::allocate_surface_swapchain(surface, device_data, pAllocator);
+ auto sc = wsi::allocate_surface_swapchain(surface, device_data, pAllocator);
if (sc == nullptr)
{
return VK_ERROR_OUT_OF_HOST_MEMORY;
VkResult result = sc->init(device, pSwapchainCreateInfo);
if (result != VK_SUCCESS)
{
- /* Error occured during initialization, need to free allocated memory. */
- wsi::destroy_surface_swapchain(sc, device_data, pAllocator);
return result;
}
- auto vulkan_swapchain = reinterpret_cast<VkSwapchainKHR>(sc);
- result = device_data.add_layer_swapchain(vulkan_swapchain);
+ result = device_data.add_layer_swapchain(reinterpret_cast<VkSwapchainKHR>(sc.get()));
if (result != VK_SUCCESS)
{
- wsi::destroy_surface_swapchain(sc, device_data, pAllocator);
return result;
}
- *pSwapchain = vulkan_swapchain;
+ *pSwapchain = reinterpret_cast<VkSwapchainKHR>(sc.release());
return result;
}
}
VkResult result;
- wsi::surface_properties *props = wsi::get_surface_properties(surface);
+ wsi::surface_properties *props = wsi::get_surface_properties(instance, surface);
assert(props);
if (nullptr == pRects)
* destroy method.
*/
template <typename T>
-class deleter
+class deleter : public allocator
{
public:
- deleter(allocator allocator)
- : m_allocator(std::move(allocator))
+ deleter()
+ : deleter(allocator::get_generic())
+ {}
+
+ deleter(allocator alloc)
+ : allocator(std::move(alloc))
{}
void operator()(T *object)
{
- m_allocator.destroy<T>(1, object);
+ destroy<T>(1, object);
}
-
-private:
- allocator m_allocator;
};
/**
--- /dev/null
+/*
+ * Copyright (c) 2021 Arm Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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 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.
+ */
+
+/** @file
+ * @brief Implementation of a headless WSI Surface
+ */
+
+#include "surface.hpp"
+#include "swapchain.hpp"
+#include "surface_properties.hpp"
+
+namespace wsi
+{
+namespace headless
+{
+
+wsi::surface_properties &surface::get_properties()
+{
+ return surface_properties::get_instance();
+}
+
+util::unique_ptr<swapchain_base> 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<swapchain_base>(alloc.make_unique<swapchain>(dev_data, allocator));
+}
+
+} /* namespace headless */
+} /* namespace wsi */
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2021 Arm Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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 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.
+ */
+
+/** @file
+ * @brief Definitions for a headless WSI Surface
+ */
+
+#pragma once
+
+#include "wsi/surface.hpp"
+
+namespace wsi
+{
+namespace headless
+{
+
+class surface : public wsi::surface
+{
+public:
+ surface() = default;
+ wsi::surface_properties &get_properties() override;
+ util::unique_ptr<swapchain_base> allocate_swapchain(layer::device_private_data &dev_data,
+ const VkAllocationCallbacks *allocator) override;
+};
+
+} /* namespace headless */
+} /* namespace wsi */
\ No newline at end of file
#include <array>
#include <cassert>
#include <cstdlib>
+#include <cstring>
#include <map>
#include <mutex>
#include <layer/private_data.hpp>
#include "surface_properties.hpp"
+#include "surface.hpp"
#define UNUSED(x) ((void)(x))
return res;
}
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL CreateHeadlessSurfaceEXT(VkInstance instance,
+ const VkHeadlessSurfaceCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkSurfaceKHR *pSurface)
+{
+ 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<wsi::surface>(allocator.make_unique<surface>());
+ if (wsi_surface == nullptr)
+ {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ VkResult res = instance_data.disp.CreateHeadlessSurfaceEXT(instance, pCreateInfo, pAllocator, pSurface);
+ if (res == VK_SUCCESS)
+ {
+ res = instance_data.add_surface(*pSurface, wsi_surface);
+ if (res != VK_SUCCESS)
+ {
+ instance_data.disp.DestroySurfaceKHR(instance, *pSurface, pAllocator);
+ }
+ }
+ return res;
+}
+
+PFN_vkVoidFunction surface_properties::get_proc_addr(const char *name)
+{
+ if (strcmp(name, "vkCreateHeadlessSurfaceEXT") == 0)
+ {
+ return reinterpret_cast<PFN_vkVoidFunction>(CreateHeadlessSurfaceEXT);
+ }
+ return nullptr;
+}
+
} /* namespace headless */
} /* namespace wsi */
VkResult get_surface_present_modes(VkPhysicalDevice physical_device, VkSurfaceKHR surface,
uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes) override;
+ PFN_vkVoidFunction get_proc_addr(const char *name) override;
+
static surface_properties &get_instance();
};
--- /dev/null
+/*
+ * Copyright (c) 2021 Arm Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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 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.
+ */
+
+/**
+ * @file
+ * @brief Vulkan WSI surface interfaces.
+ */
+
+#pragma once
+
+#include <vulkan/vulkan.h>
+#include "surface_properties.hpp"
+#include "swapchain_base.hpp"
+
+namespace wsi
+{
+
+/**
+ * @brief A generic WSI representation of a VkSurface.
+ *
+ * The association between these objects and VkSurfaces is kept in the VkInstance private data.
+ */
+class surface
+{
+public:
+ virtual ~surface() = default;
+
+ /**
+ * @brief Returns a @ref surface_properties implementation that can be specific to the VkSurface represented.
+ */
+ virtual surface_properties &get_properties() = 0;
+
+ /**
+ * @brief Allocates a swapchain for the VkSurface type represented.
+ *
+ * @param dev_data The VkDevice associated private date.
+ * @param allocator Allocation callbacks to use for host memory.
+ *
+ * @return nullptr on failure otherwise a constructed swapchain.
+ */
+ virtual util::unique_ptr<swapchain_base> allocate_swapchain(layer::device_private_data &dev_data,
+ const VkAllocationCallbacks *allocator) = 0;
+};
+
+} /* namespace wsi */
\ No newline at end of file
/**
* @brief Implements vkGetProcAddr for entrypoints specific to the surface type.
+ *
+ * At least the specific VkSurface creation entrypoint must be intercepted.
*/
- virtual PFN_vkVoidFunction get_proc_addr(const char *name)
- {
- return nullptr;
- }
+ virtual PFN_vkVoidFunction get_proc_addr(const char *name) = 0;
};
} /* namespace wsi */
--- /dev/null
+/*
+ * Copyright (c) 2021 Arm Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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 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.
+ */
+
+/** @file
+ * @brief Implementation of a Wayland WSI Surface
+ */
+
+#include "surface.hpp"
+#include "swapchain.hpp"
+#include "surface_properties.hpp"
+
+namespace wsi
+{
+namespace wayland
+{
+
+wsi::surface_properties &surface::get_properties()
+{
+ return surface_properties::get_instance();
+}
+
+util::unique_ptr<swapchain_base> 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<swapchain_base>(alloc.make_unique<swapchain>(dev_data, allocator));
+}
+
+} // namespace wayland
+} // namespace wsi
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2021 Arm Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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 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.
+ */
+
+/** @file
+ * @brief Definitions for a Wayland WSI Surface
+ */
+
+#pragma once
+
+#include "wsi/surface.hpp"
+
+namespace wsi
+{
+namespace wayland
+{
+
+class surface : public wsi::surface
+{
+public:
+ surface() = default;
+
+ wsi::surface_properties &get_properties() override;
+ util::unique_ptr<swapchain_base> allocate_swapchain(layer::device_private_data &dev_data,
+ const VkAllocationCallbacks *allocator) override;
+};
+
+} // namespace wayland
+} // namespace wsi
\ No newline at end of file
#include <array>
#include <cstring>
#include "surface_properties.hpp"
+#include "surface.hpp"
#include "layer/private_data.hpp"
#include "wl_helpers.hpp"
#include "wl_object_owner.hpp"
return VK_TRUE;
}
+extern "C" VkResult CreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface)
+{
+ 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<wsi::surface>(allocator.make_unique<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);
+ if (res != VK_SUCCESS)
+ {
+ instance_data.disp.DestroySurfaceKHR(instance, *pSurface, pAllocator);
+ }
+ }
+ return res;
+}
+
PFN_vkVoidFunction surface_properties::get_proc_addr(const char *name)
{
if (strcmp(name, "vkGetPhysicalDeviceWaylandPresentationSupportKHR") == 0)
{
return reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceWaylandPresentationSupportKHR);
}
+ else if (strcmp(name, "vkCreateWaylandSurfaceKHR") == 0)
+ {
+ return reinterpret_cast<PFN_vkVoidFunction>(CreateWaylandSurfaceKHR);
+ }
return nullptr;
}
+
} // namespace wayland
} // namespace wsi
*/
#include "wsi_factory.hpp"
+#include "surface.hpp"
#include "headless/surface_properties.hpp"
-#include "headless/swapchain.hpp"
#include <cassert>
#include <cstdlib>
#if BUILD_WSI_WAYLAND
#include <vulkan/vulkan_wayland.h>
#include "wayland/surface_properties.hpp"
-#include "wayland/swapchain.hpp"
#endif
namespace wsi
}
}
-surface_properties *get_surface_properties(VkSurfaceKHR surface)
+surface_properties *get_surface_properties(layer::instance_private_data &instance_data, VkSurfaceKHR surface)
{
- VkIcdSurfaceBase *surface_base = reinterpret_cast<VkIcdSurfaceBase *>(surface);
+ auto *wsi_surface = instance_data.get_surface(surface);
- return get_surface_properties(surface_base->platform);
-}
+ if (wsi_surface)
+ {
+ return &wsi_surface->get_properties();
+ }
-template <typename swapchain_type>
-static swapchain_base *allocate_swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *pAllocator)
-{
- util::allocator alloc{ dev_data.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE, pAllocator };
- return alloc.create<swapchain_type>(1, dev_data, pAllocator);
+ return nullptr;
}
-swapchain_base *allocate_surface_swapchain(VkSurfaceKHR surface, layer::device_private_data &dev_data,
- const VkAllocationCallbacks *pAllocator)
+util::unique_ptr<swapchain_base> allocate_surface_swapchain(VkSurfaceKHR surface, layer::device_private_data &dev_data,
+ const VkAllocationCallbacks *pAllocator)
{
- VkIcdSurfaceBase *surface_base = reinterpret_cast<VkIcdSurfaceBase *>(surface);
-
- switch (surface_base->platform)
+ wsi::surface *wsi_surface = dev_data.instance_data.get_surface(surface);
+ if (wsi_surface)
{
- case VK_ICD_WSI_PLATFORM_HEADLESS:
- return allocate_swapchain<wsi::headless::swapchain>(dev_data, pAllocator);
-#if BUILD_WSI_WAYLAND
- case VK_ICD_WSI_PLATFORM_WAYLAND:
- return allocate_swapchain<wsi::wayland::swapchain>(dev_data, pAllocator);
-#endif
- default:
- return nullptr;
+ return wsi_surface->allocate_swapchain(dev_data, pAllocator);
}
+ return nullptr;
}
util::wsi_platform_set find_enabled_layer_platforms(const VkInstanceCreateInfo *pCreateInfo)
{
assert(swapchain);
- util::allocator alloc{ swapchain->get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE, pAllocator };
+ util::allocator alloc{ dev_data.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT, pAllocator };
alloc.destroy(1, swapchain);
}
/**
* @brief Obtains the surface properties for the specific surface type.
*
- * @param surface The surface for which to get the properties.
+ * @param instance_data The instance specific data.
+ * @param surface The surface for which to get the properties.
*
* @return nullptr if surface type is unsupported.
*/
-surface_properties *get_surface_properties(VkSurfaceKHR surface);
+surface_properties *get_surface_properties(layer::instance_private_data &instance_data, VkSurfaceKHR surface);
/**
* @brief Allocates a surface specific swapchain.
*
* @return nullptr on failure.
*/
-swapchain_base *allocate_surface_swapchain(VkSurfaceKHR surface, layer::device_private_data &dev_data,
- const VkAllocationCallbacks *pAllocator);
+util::unique_ptr<swapchain_base> allocate_surface_swapchain(VkSurfaceKHR surface, layer::device_private_data &dev_data,
+ const VkAllocationCallbacks *pAllocator);
/**
* @brief Destroys a swapchain and frees memory. Used with @ref allocate_surface_swapchain.