2 * Copyright (c) 2019-2021 Arm Limited.
4 * SPDX-License-Identifier: MIT
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * @brief Implements factory methods for obtaining the specific surface and swapchain implementations.
30 #include "wsi_factory.hpp"
31 #include "headless/surface_properties.hpp"
32 #include "headless/swapchain.hpp"
39 #include <vulkan/vk_icd.h>
42 #include <vulkan/vulkan_wayland.h>
43 #include "wayland/surface_properties.hpp"
44 #include "wayland/swapchain.hpp"
46 #include <vulkan/vulkan_wayland.h>
47 #include "tizen/surface_properties.hpp"
48 #include "tizen/swapchain.hpp"
54 static struct wsi_extension
56 VkExtensionProperties extension;
57 VkIcdWsiPlatform platform;
58 } const supported_wsi_extensions[] = {
59 { { VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME, VK_EXT_HEADLESS_SURFACE_SPEC_VERSION }, VK_ICD_WSI_PLATFORM_HEADLESS },
60 #if BUILD_WSI_WAYLAND || BUILD_WSI_TIZEN
61 { { VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, VK_KHR_WAYLAND_SURFACE_SPEC_VERSION }, VK_ICD_WSI_PLATFORM_WAYLAND },
65 static surface_properties *get_surface_properties(VkIcdWsiPlatform platform)
69 case VK_ICD_WSI_PLATFORM_HEADLESS:
70 return &headless::surface_properties::get_instance();
72 case VK_ICD_WSI_PLATFORM_WAYLAND:
73 return &wayland::surface_properties::get_instance();
75 case VK_ICD_WSI_PLATFORM_WAYLAND:
76 return &tizen::surface_properties::get_instance();
83 surface_properties *get_surface_properties(VkSurfaceKHR surface)
85 VkIcdSurfaceBase *surface_base = reinterpret_cast<VkIcdSurfaceBase *>(surface);
87 return get_surface_properties(surface_base->platform);
90 template <typename swapchain_type>
91 static swapchain_base *allocate_swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *pAllocator)
95 return new swapchain_type(dev_data, pAllocator);
97 void *memory = pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(swapchain_type), alignof(swapchain_type),
98 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
99 return new (memory) swapchain_type(dev_data, pAllocator);
102 swapchain_base *allocate_surface_swapchain(VkSurfaceKHR surface, layer::device_private_data &dev_data,
103 const VkAllocationCallbacks *pAllocator)
105 VkIcdSurfaceBase *surface_base = reinterpret_cast<VkIcdSurfaceBase *>(surface);
107 switch (surface_base->platform)
109 case VK_ICD_WSI_PLATFORM_HEADLESS:
110 return allocate_swapchain<wsi::headless::swapchain>(dev_data, pAllocator);
111 #if BUILD_WSI_WAYLAND
112 case VK_ICD_WSI_PLATFORM_WAYLAND:
113 return allocate_swapchain<wsi::wayland::swapchain>(dev_data, pAllocator);
114 #elif BUILD_WSI_TIZEN
115 case VK_ICD_WSI_PLATFORM_WAYLAND:
116 return allocate_swapchain<wsi::tizen::swapchain>(dev_data, pAllocator);
123 util::wsi_platform_set find_enabled_layer_platforms(const VkInstanceCreateInfo *pCreateInfo)
125 util::wsi_platform_set ret;
126 for (const auto &ext_provided_by_layer : supported_wsi_extensions)
128 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++)
130 const char* ext_requested_by_user = pCreateInfo->ppEnabledExtensionNames[i];
131 if (strcmp(ext_requested_by_user, ext_provided_by_layer.extension.extensionName) == 0)
133 ret.add(ext_provided_by_layer.platform);
140 VkResult add_extensions_required_by_layer(VkPhysicalDevice phys_dev, const util::wsi_platform_set enabled_platforms,
141 util::extension_list &extensions_to_enable)
144 util::allocator allocator{extensions_to_enable.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND};
145 util::extension_list device_extensions{allocator};
146 VkResult res = device_extensions.add(phys_dev);
147 if (res != VK_SUCCESS)
154 for (const auto &wsi_ext : supported_wsi_extensions)
156 /* Skip iterating over platforms not enabled in the instance. */
157 if (!enabled_platforms.contains(wsi_ext.platform))
162 surface_properties *props = get_surface_properties(wsi_ext.platform);
163 const auto &extensions_required_by_layer = props->get_required_device_extensions();
165 bool supported = device_extensions.contains(extensions_required_by_layer);
168 /* Can we accept failure? The layer unconditionally advertises support for this platform and the loader uses
169 * this information to enable its own support of the vkCreate*SurfaceKHR entrypoints. The rest of the Vulkan
170 * stack may not support this extension so we cannot blindly fall back to it.
171 * For now treat this as an error.
173 return VK_ERROR_INITIALIZATION_FAILED;
177 res = extensions_to_enable.add(extensions_required_by_layer);
178 if (res != VK_SUCCESS)
186 void destroy_surface_swapchain(swapchain_base *swapchain, const VkAllocationCallbacks *pAllocator)
196 swapchain->~swapchain_base();
197 pAllocator->pfnFree(pAllocator->pUserData, reinterpret_cast<void *>(swapchain));
201 PFN_vkVoidFunction get_proc_addr(const char *name)
204 * Note that we here assume that there are no two get_proc_addr implementations
205 * that handle the same function name.
207 for (const auto &wsi_ext : supported_wsi_extensions)
209 PFN_vkVoidFunction func = get_surface_properties(wsi_ext.platform)->get_proc_addr(name);