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"
37 #include <vulkan/vk_icd.h>
40 #include <vulkan/vulkan_wayland.h>
41 #include "tizen/surface_properties.hpp"
42 #include "tizen/swapchain.hpp"
44 #include "headless/surface_properties.hpp"
45 #include "headless/swapchain.hpp"
47 #include <vulkan/vulkan_wayland.h>
48 #include "wayland/surface_properties.hpp"
49 #include "wayland/swapchain.hpp"
56 static struct wsi_extension
58 VkExtensionProperties extension;
59 VkIcdWsiPlatform platform;
60 } const supported_wsi_extensions[] = {
62 { { VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, VK_KHR_WAYLAND_SURFACE_SPEC_VERSION }, VK_ICD_WSI_PLATFORM_WAYLAND },
64 { { VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME, VK_EXT_HEADLESS_SURFACE_SPEC_VERSION }, VK_ICD_WSI_PLATFORM_HEADLESS },
66 { { VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, VK_KHR_WAYLAND_SURFACE_SPEC_VERSION }, VK_ICD_WSI_PLATFORM_WAYLAND },
71 static surface_properties *get_surface_properties(VkIcdWsiPlatform platform)
76 case VK_ICD_WSI_PLATFORM_WAYLAND:
77 return &tizen::surface_properties::get_instance();
79 case VK_ICD_WSI_PLATFORM_HEADLESS:
80 return &headless::surface_properties::get_instance();
82 case VK_ICD_WSI_PLATFORM_WAYLAND:
83 return &wayland::surface_properties::get_instance();
91 surface_properties *get_surface_properties(VkSurfaceKHR surface)
93 VkIcdSurfaceBase *surface_base = reinterpret_cast<VkIcdSurfaceBase *>(surface);
95 return get_surface_properties(surface_base->platform);
98 template <typename swapchain_type>
99 static swapchain_base *allocate_swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *pAllocator)
103 return new swapchain_type(dev_data, pAllocator);
105 void *memory = pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(swapchain_type), alignof(swapchain_type),
106 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
107 return new (memory) swapchain_type(dev_data, pAllocator);
110 swapchain_base *allocate_surface_swapchain(VkSurfaceKHR surface, layer::device_private_data &dev_data,
111 const VkAllocationCallbacks *pAllocator)
113 VkIcdSurfaceBase *surface_base = reinterpret_cast<VkIcdSurfaceBase *>(surface);
115 switch (surface_base->platform)
118 case VK_ICD_WSI_PLATFORM_WAYLAND:
119 return allocate_swapchain<wsi::tizen::swapchain>(dev_data, pAllocator);
121 case VK_ICD_WSI_PLATFORM_HEADLESS:
122 return allocate_swapchain<wsi::headless::swapchain>(dev_data, pAllocator);
123 #if BUILD_WSI_WAYLAND
124 case VK_ICD_WSI_PLATFORM_WAYLAND:
125 return allocate_swapchain<wsi::wayland::swapchain>(dev_data, pAllocator);
133 util::wsi_platform_set find_enabled_layer_platforms(const VkInstanceCreateInfo *pCreateInfo)
135 util::wsi_platform_set ret;
136 for (const auto &ext_provided_by_layer : supported_wsi_extensions)
138 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++)
140 const char* ext_requested_by_user = pCreateInfo->ppEnabledExtensionNames[i];
141 if (strcmp(ext_requested_by_user, ext_provided_by_layer.extension.extensionName) == 0)
143 ret.add(ext_provided_by_layer.platform);
150 VkResult add_extensions_required_by_layer(VkPhysicalDevice phys_dev, const util::wsi_platform_set enabled_platforms,
151 util::extension_list &extensions_to_enable)
154 util::allocator allocator{extensions_to_enable.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND};
155 util::extension_list device_extensions{allocator};
156 VkResult res = device_extensions.add(phys_dev);
157 if (res != VK_SUCCESS)
164 for (const auto &wsi_ext : supported_wsi_extensions)
166 /* Skip iterating over platforms not enabled in the instance. */
167 if (!enabled_platforms.contains(wsi_ext.platform))
172 surface_properties *props = get_surface_properties(wsi_ext.platform);
173 const auto &extensions_required_by_layer = props->get_required_device_extensions();
175 bool supported = device_extensions.contains(extensions_required_by_layer);
178 /* Can we accept failure? The layer unconditionally advertises support for this platform and the loader uses
179 * this information to enable its own support of the vkCreate*SurfaceKHR entrypoints. The rest of the Vulkan
180 * stack may not support this extension so we cannot blindly fall back to it.
181 * For now treat this as an error.
183 return VK_ERROR_INITIALIZATION_FAILED;
187 res = extensions_to_enable.add(extensions_required_by_layer);
188 if (res != VK_SUCCESS)
196 void destroy_surface_swapchain(swapchain_base *swapchain, const VkAllocationCallbacks *pAllocator)
206 swapchain->~swapchain_base();
207 pAllocator->pfnFree(pAllocator->pUserData, reinterpret_cast<void *>(swapchain));
211 PFN_vkVoidFunction get_proc_addr(const char *name)
214 * Note that we here assume that there are no two get_proc_addr implementations
215 * that handle the same function name.
217 for (const auto &wsi_ext : supported_wsi_extensions)
219 PFN_vkVoidFunction func = get_surface_properties(wsi_ext.platform)->get_proc_addr(name);