Move WSI type specific calls
authorRosen <rosen.zhelev@arm.com>
Thu, 21 Nov 2019 15:23:59 +0000 (15:23 +0000)
committerMatteo Franchin <matteo.franchin@arm.com>
Thu, 21 Nov 2019 15:23:59 +0000 (15:23 +0000)
Move all WSI type specific calls to WSI factory methods. This
removes headless references in layer/ and allows for simpler
support of multiple windowing systems.

Change-Id: I757a7a3bb4267783420b52cceb3bde8ce233297e
Signed-off-by: Rosen Zhelev <rosen.zhelev@arm.com>
CMakeLists.txt
layer/layer.cpp
layer/private_data.hpp
layer/surface_api.cpp
layer/swapchain_api.cpp
wsi/headless/surface_properties.cpp
wsi/headless/surface_properties.hpp
wsi/surface_properties.hpp
wsi/wsi_factory.cpp [new file with mode: 0644]
wsi/wsi_factory.hpp [new file with mode: 0644]

index ac18c51..5fcb072 100644 (file)
@@ -47,6 +47,7 @@ add_library(${PROJECT_NAME} SHARED
    layer/swapchain_api.cpp
    util/timed_semaphore.cpp
    wsi/swapchain_base.cpp
+   wsi/wsi_factory.cpp
    wsi/headless/surface_properties.cpp
    wsi/headless/swapchain.cpp)
 set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD 11)
index 5b66173..003bf66 100644 (file)
@@ -27,8 +27,6 @@
 #include <cstring>
 #include <vulkan/vk_layer.h>
 
-#include <wsi/surface_properties.hpp>
-
 #include "private_data.hpp"
 #include "surface_api.hpp"
 #include "swapchain_api.hpp"
index 3596ad7..44ad5b6 100644 (file)
 
 #define DISPATCH_TABLE_ENTRY(x) PFN_vk##x x;
 
-#define INSTANCE_ENTRYPOINTS_LIST(V)         \
-   V(GetInstanceProcAddr)                    \
-   V(GetPhysicalDeviceProperties)            \
-   V(GetPhysicalDeviceImageFormatProperties) \
-   V(EnumerateDeviceExtensionProperties)
+#define INSTANCE_ENTRYPOINTS_LIST(V)          \
+   V(GetInstanceProcAddr)                     \
+   V(GetPhysicalDeviceProperties)             \
+   V(GetPhysicalDeviceImageFormatProperties)  \
+   V(EnumerateDeviceExtensionProperties)      \
+   V(GetPhysicalDeviceSurfaceCapabilitiesKHR) \
+   V(GetPhysicalDeviceSurfaceFormatsKHR)      \
+   V(GetPhysicalDeviceSurfacePresentModesKHR) \
+   V(GetPhysicalDeviceSurfaceSupportKHR)
 
 namespace layer
 {
index 9b798a2..52c98cd 100644 (file)
@@ -24,7 +24,9 @@
 
 #include <cassert>
 
-#include <wsi/headless/surface_properties.hpp>
+#include <wsi/wsi_factory.hpp>
+
+#include "private_data.hpp"
 #include "surface_api.hpp"
 
 extern "C"
@@ -36,11 +38,14 @@ extern "C"
    VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
       VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
    {
-      assert(physicalDevice);
-      assert(surface);
-      assert(pSurfaceCapabilities);
+      wsi::surface_properties *props = wsi::get_surface_properties(surface);
+      if (props)
+      {
+         return props->get_surface_capabilities(physicalDevice, surface, pSurfaceCapabilities);
+      }
 
-      return wsi::headless::surface_properties::get_surface_capabilities(physicalDevice, surface, pSurfaceCapabilities);
+      return layer::instance_private_data::get(layer::get_key(physicalDevice))
+         .disp.GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, pSurfaceCapabilities);
    }
 
    /**
@@ -51,10 +56,14 @@ extern "C"
                                                                       uint32_t *pSurfaceFormatCount,
                                                                       VkSurfaceFormatKHR *pSurfaceFormats)
    {
-      assert(physicalDevice);
-      assert(surface);
+      wsi::surface_properties *props = wsi::get_surface_properties(surface);
+      if (props)
+      {
+         return props->get_surface_formats(physicalDevice, surface, pSurfaceFormatCount, pSurfaceFormats);
+      }
 
-      return wsi::headless::surface_properties::get_surface_formats(physicalDevice, surface, pSurfaceFormatCount, pSurfaceFormats);
+      return layer::instance_private_data::get(layer::get_key(physicalDevice))
+         .disp.GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount, pSurfaceFormats);
    }
 
    /**
@@ -65,11 +74,14 @@ extern "C"
                                                                            uint32_t *pPresentModeCount,
                                                                            VkPresentModeKHR *pPresentModes)
    {
-      assert(physicalDevice);
-      assert(surface);
-      assert(pPresentModeCount);
+      wsi::surface_properties *props = wsi::get_surface_properties(surface);
+      if (props)
+      {
+         return props->get_surface_present_modes(physicalDevice, surface, pPresentModeCount, pPresentModes);
+      }
 
-      return wsi::headless::surface_properties::get_surface_present_modes(physicalDevice, surface, pPresentModeCount, pPresentModes);
+      return layer::instance_private_data::get(layer::get_key(physicalDevice))
+         .disp.GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, pPresentModeCount, pPresentModes);
    }
 
    /**
@@ -79,13 +91,16 @@ extern "C"
                                                                       uint32_t queueFamilyIndex, VkSurfaceKHR surface,
                                                                       VkBool32 *pSupported)
    {
-      assert(physicalDevice);
-      assert(surface);
-      assert(pSupported);
-
+      wsi::surface_properties *props = wsi::get_surface_properties(surface);
       /* We assume that presentation to surface is supported by default */
-      *pSupported = VK_TRUE;
-      return VK_SUCCESS;
+      if (props)
+      {
+         *pSupported = VK_TRUE;
+         return VK_SUCCESS;
+      }
+
+      return layer::instance_private_data::get(layer::get_key(physicalDevice))
+         .disp.GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, pSupported);
    }
 
 } /* extern "C" */
index fdf55e9..092c22c 100644 (file)
@@ -31,9 +31,8 @@
 #include <cassert>
 #include <cstdlib>
 #include <new>
-#include <vulkan/vk_icd.h>
 
-#include <wsi/headless/swapchain.hpp>
+#include <wsi/wsi_factory.hpp>
 
 #include "private_data.hpp"
 #include "swapchain_api.hpp"
@@ -48,27 +47,8 @@ extern "C"
    {
       assert(pSwapchain != nullptr);
 
-      wsi::swapchain_base *sc = nullptr;
-
-      VkIcdSurfaceBase *surface_base = reinterpret_cast<VkIcdSurfaceBase *>(pSwapchainCreateInfo->surface);
-      assert(VK_ICD_WSI_PLATFORM_HEADLESS == (int)surface_base->platform);
-
-      void *memory = nullptr;
-      if (pAllocator)
-      {
-         memory = static_cast<wsi::headless::swapchain *>(
-            pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(wsi::headless::swapchain),
-                                      alignof(wsi::headless::swapchain), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE));
-      }
-      else
-      {
-         memory = static_cast<wsi::headless::swapchain *>(malloc(sizeof(wsi::headless::swapchain)));
-      }
-
-      if (memory)
-      {
-         sc = new (memory) wsi::headless::swapchain(layer::device_private_data::get(layer::get_key(device)), pAllocator);
-      }
+      wsi::swapchain_base *sc = wsi::allocate_surface_swapchain(
+         pSwapchainCreateInfo->surface, layer::device_private_data::get(layer::get_key(device)), pAllocator);
 
       if (sc == nullptr)
       {
@@ -79,17 +59,7 @@ extern "C"
       if (result != VK_SUCCESS)
       {
          /* Error occured during initialization, need to free allocated memory. */
-         sc->~swapchain_base();
-
-         if (pAllocator != nullptr)
-         {
-            pAllocator->pfnFree(pAllocator->pUserData, reinterpret_cast<void *>(sc));
-         }
-         else
-         {
-            free(reinterpret_cast<void *>(sc));
-         }
-
+         wsi::destroy_surface_swapchain(sc, pAllocator);
          return result;
       }
 
@@ -105,16 +75,7 @@ extern "C"
 
       wsi::swapchain_base *sc = reinterpret_cast<wsi::swapchain_base *>(swapc);
 
-      sc->~swapchain_base();
-
-      if (pAllocator != nullptr)
-      {
-         pAllocator->pfnFree(pAllocator->pUserData, reinterpret_cast<void *>(swapc));
-      }
-      else
-      {
-         free(reinterpret_cast<void *>(swapc));
-      }
+      wsi::destroy_surface_swapchain(sc, pAllocator);
    }
 
    VKAPI_ATTR VkResult wsi_layer_vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapc,
index a3f69b9..b7136d7 100644 (file)
@@ -43,6 +43,12 @@ namespace wsi
 namespace headless
 {
 
+surface_properties& surface_properties::get_instance()
+{
+   static surface_properties instance;
+   return instance;
+}
+
 VkResult surface_properties::get_surface_capabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface,
                                                       VkSurfaceCapabilitiesKHR *surface_capabilities)
 {
index 2f97f26..737f2ca 100644 (file)
@@ -33,16 +33,19 @@ namespace wsi
 namespace headless
 {
 
-struct surface_properties
+class surface_properties : public wsi::surface_properties
 {
-   static VkResult get_surface_capabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface,
-                                            VkSurfaceCapabilitiesKHR *pSurfaceCapabilities);
+public:
+   VkResult get_surface_capabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface,
+                                     VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) override;
 
-   static VkResult get_surface_formats(VkPhysicalDevice physical_device, VkSurfaceKHR surface, uint32_t *surfaceFormatCount,
-                                       VkSurfaceFormatKHR *surfaceFormats);
+   VkResult get_surface_formats(VkPhysicalDevice physical_device, VkSurfaceKHR surface, uint32_t *surfaceFormatCount,
+                                VkSurfaceFormatKHR *surfaceFormats) override;
 
-   static VkResult get_surface_present_modes(VkPhysicalDevice physical_device, VkSurfaceKHR surface,
-                                             uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes);
+   VkResult get_surface_present_modes(VkPhysicalDevice physical_device, VkSurfaceKHR surface,
+                                      uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes) override;
+
+   static surface_properties &get_instance();
 };
 
 } /* namespace headless */
index b4b585b..3b2bdf5 100644 (file)
@@ -38,26 +38,26 @@ namespace wsi
 /**
  * @brief The base surface property query interface.
  */
-template <typename T>
-struct surface_properties
+class surface_properties
 {
-   static VkResult get_surface_capabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface,
-                                            VkSurfaceCapabilitiesKHR *surface_capabilities)
-   {
-      return T::get_surface_capabilities(physical_device, surface, surface_capabilities);
-   }
-
-   static VkResult get_surface_formats(VkPhysicalDevice physical_device, VkSurfaceKHR surface,
-                                       uint32_t *surface_format_count, VkSurfaceFormatKHR *surface_formats)
-   {
-      return T::get_surface_formats(physical_device, surface, surface_format_count, surface_formats);
-   }
-
-   static VkResult get_surface_present_modes(VkPhysicalDevice physical_device, VkSurfaceKHR surface,
-                                             uint32_t *present_mode_count, VkPresentModeKHR *present_modes)
-   {
-      return T::get_surface_present_modes(physical_device, surface, present_mode_count, present_modes);
-   }
+public:
+   /**
+    * Implementation of vkGetPhysicalDeviceSurfaceCapabilitiesKHR for the specific VkSurface type.
+    */
+   virtual VkResult get_surface_capabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface,
+                                             VkSurfaceCapabilitiesKHR *surface_capabilities) = 0;
+
+   /**
+    * Implementation of vkGetPhysicalDeviceSurfaceFormatsKHR for the specific VkSurface type.
+    */
+   virtual VkResult get_surface_formats(VkPhysicalDevice physical_device, VkSurfaceKHR surface,
+                                        uint32_t *surface_format_count, VkSurfaceFormatKHR *surface_formats) = 0;
+
+   /**
+    * Implementation of vkGetPhysicalDeviceSurfacePresentModesKHR for the specific VkSurface type.
+    */
+   virtual VkResult get_surface_present_modes(VkPhysicalDevice physical_device, VkSurfaceKHR surface,
+                                              uint32_t *present_mode_count, VkPresentModeKHR *present_modes) = 0;
 };
 
 } /* namespace wsi */
diff --git a/wsi/wsi_factory.cpp b/wsi/wsi_factory.cpp
new file mode 100644 (file)
index 0000000..44fc91b
--- /dev/null
@@ -0,0 +1,98 @@
+
+/*
+ * Copyright (c) 2019 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 Implements factory methods for obtaining the specific surface and swapchain implementations.
+ */
+
+#include "wsi_factory.hpp"
+#include <cassert>
+#include <cstdlib>
+#include <cstdio>
+#include <new>
+#include <vulkan/vk_icd.h>
+
+#include "headless/surface_properties.hpp"
+#include "headless/swapchain.hpp"
+
+namespace wsi
+{
+
+surface_properties *get_surface_properties(VkSurfaceKHR surface)
+{
+   VkIcdSurfaceBase *surface_base = reinterpret_cast<VkIcdSurfaceBase *>(surface);
+
+   switch (surface_base->platform)
+   {
+   case VK_ICD_WSI_PLATFORM_HEADLESS:
+      return &headless::surface_properties::get_instance();
+   default:
+      return nullptr;
+   }
+}
+
+template <typename swapchain_type>
+static swapchain_base *allocate_swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *pAllocator)
+{
+   if (!pAllocator)
+   {
+      return new swapchain_type(dev_data, pAllocator);
+   }
+   void *memory = pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(swapchain_type), alignof(swapchain_type),
+                                            VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+   return new (memory) swapchain_type(dev_data, pAllocator);
+}
+
+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)
+   {
+   case VK_ICD_WSI_PLATFORM_HEADLESS:
+      return allocate_swapchain<wsi::headless::swapchain>(dev_data, pAllocator);
+   default:
+      return nullptr;
+   }
+}
+
+void destroy_surface_swapchain(swapchain_base *swapchain, const VkAllocationCallbacks *pAllocator)
+{
+   assert(swapchain);
+
+   if (!pAllocator)
+   {
+      delete swapchain;
+   }
+   else
+   {
+      swapchain->~swapchain_base();
+      pAllocator->pfnFree(pAllocator->pUserData, reinterpret_cast<void *>(swapchain));
+   }
+}
+
+} // namespace wsi
\ No newline at end of file
diff --git a/wsi/wsi_factory.hpp b/wsi/wsi_factory.hpp
new file mode 100644 (file)
index 0000000..8f85b94
--- /dev/null
@@ -0,0 +1,68 @@
+
+/*
+ * Copyright (c) 2019 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 Contains the factory methods for obtaining the specific surface and swapchain implementations.
+ */
+#pragma once
+
+#include "swapchain_base.hpp"
+#include "surface_properties.hpp"
+#include <layer/private_data.hpp>
+
+namespace wsi
+{
+
+/**
+ * Obtains the surface properties for the specific surface type.
+ *
+ * @param surface The surface for which to get the properties.
+ *
+ * @return nullptr if surface type is unsupported.
+ */
+surface_properties *get_surface_properties(VkSurfaceKHR surface);
+
+/**
+ * Allocates a surface specific swapchain.
+ *
+ * @param surface    The surface for which a swapchain is allocated.
+ * @param dev_data   The device specific data.
+ * @param pAllocator The allocator from which to allocate any memory.
+ *
+ * @return nullptr on failure.
+ */
+swapchain_base *allocate_surface_swapchain(VkSurfaceKHR surface, layer::device_private_data &dev_data,
+                                           const VkAllocationCallbacks *pAllocator);
+
+/**
+ * Destroys a swapchain and frees memory. Used with @ref allocate_surface_swapchain.
+ *
+ * @param swapchain  Pointer to the swapchain to destroy.
+ * @param pAllocator The allocator to use for freeing memory.
+ */
+void destroy_surface_swapchain(swapchain_base *swapchain, const VkAllocationCallbacks *pAllocator);
+
+} // namespace wsi
\ No newline at end of file