Upgrade WSI Layer 69/269969/3 baixl_dev
authorTianhao Ni <tianhao.ni@samsung.com>
Fri, 21 Jan 2022 01:12:49 +0000 (09:12 +0800)
committerTianhao Ni <tianhao.ni@samsung.com>
Tue, 25 Jan 2022 02:56:13 +0000 (10:56 +0800)
Change-Id: I6eb06fb17aa1d35d9eea661f9f128261ca3ae6ba
Signed-off-by: Tianhao Ni <tianhao.ni@samsung.com>
21 files changed:
CMakeLists.txt
layer/VkLayer_window_system_integration.json
layer/layer.cpp
layer/surface_api.cpp
layer/surface_api.hpp
layer/swapchain_api.cpp
util/log.cpp [deleted file]
util/log.hpp
util/log_util.hpp [deleted file]
wsi/swapchain_base.cpp
wsi/swapchain_base.hpp
wsi/swapchain_base_tizen.cpp [deleted file]
wsi/swapchain_base_tizen.hpp [deleted file]
wsi/tizen/surface.cpp [new file with mode: 0644]
wsi/tizen/surface.hpp [new file with mode: 0644]
wsi/tizen/surface_properties.cpp
wsi/tizen/surface_properties.hpp
wsi/tizen/swapchain.cpp
wsi/tizen/swapchain.hpp
wsi/wsi_factory.cpp
wsi/wsi_factory.hpp

index 6b04161d7b17df877ad375c22839ca465699a3df..9e403f2a67a564d46727e455b69de768c9071237 100644 (file)
@@ -53,7 +53,7 @@ else()
 endif()
 
 # Build Configuration options
-option(BUILD_WSI_HEADLESS "Build with support for VK_EXT_headless_surface" ON)
+option(BUILD_WSI_HEADLESS "Build with support for VK_EXT_headless_surface" OFF)
 option(BUILD_WSI_WAYLAND "Build with support for VK_KHR_wayland_surface" OFF)
 set(SELECT_EXTERNAL_ALLOCATOR "none" CACHE STRING "Select an external system allocator (none, ion)")
 set(EXTERNAL_WSIALLOC_LIBRARY "" CACHE STRING "External implementation of the wsialloc interface to use")
@@ -169,6 +169,7 @@ elseif(BUILD_WSI_TIZEN)
    endif()
    add_library(tizen_wsi STATIC
       wsi/tizen/surface_properties.cpp
+      wsi/tizen/surface.cpp
       wsi/tizen/swapchain.cpp)
 
    pkg_check_modules(LIBDRM REQUIRED libdrm)
@@ -178,7 +179,7 @@ elseif(BUILD_WSI_TIZEN)
       ${PROJECT_SOURCE_DIR}
       ${VULKAN_CXX_INCLUDE}
       ${CMAKE_CURRENT_BINARY_DIR}
-         ${LIBDRM_INCLUDE_DIRS})
+      ${LIBDRM_INCLUDE_DIRS})
 
    target_compile_options(tizen_wsi INTERFACE "-DBUILD_WSI_TIZEN=1")
    target_link_libraries(tizen_wsi dlog tbm tpl-egl)
@@ -207,7 +208,7 @@ endif()
 
 # Layer
 if(BUILD_WSI_TIZEN)
-   set(WSI_PLATFORM_SPECIFIED wsi/swapchain_base_tizen.cpp)
+   set(WSI_PLATFORM_SPECIFIED wsi/swapchain_base.cpp)
 else()
    set(WSI_PLATFORM_SPECIFIED wsi/swapchain_base.cpp wsi/headless/surface_properties.cpp wsi/headless/swapchain.cpp)
 endif()
@@ -219,8 +220,6 @@ add_library(${PROJECT_NAME} SHARED
    util/timed_semaphore.cpp
    util/custom_allocator.cpp
    util/extension_list.cpp
-   util/log.cpp
-   wsi/swapchain_base.cpp
    wsi/synchronization.cpp
    wsi/wsi_factory.cpp
    ${WSI_PLATFORM_SPECIFIED})
index b63be97c0b1048885e5d980d123696ea1594e1af..3cf22d4f399f8cce80f588957689e35d29bd832d 100644 (file)
                     "vkGetPhysicalDevicePresentRectanglesKHR"
                 ]
             },
-               {"name" : "VK_KHR_incremental_present", "spec_version" : "1"}
+            {"name" : "VK_KHR_incremental_present", "spec_version" : "1"},
             {"name" : "VK_KHR_get_surface_capabilities2", "spec_version" : "1"},
             {"name" : "VK_KHR_surface_protected_capabilities", "spec_version" : "1"},
             {"name" : "VK_EXT_display_surface_counter", "spec_version" : "1"}
         ],
+        "enable_environment": {
+            "ENABLE_WSI_LAYER": "1"
+        },
         "disable_environment": {
             "DISABLE_WSI_LAYER": "1"
         }
index 14923a3cdab03bb20f60cbdada27b8eb559093d6..986436aa49543e6251ad38e38286b00efe8f11c1 100644 (file)
@@ -123,70 +123,21 @@ VKAPI_ATTR VkResult create_instance(const VkInstanceCreateInfo *pCreateInfo, con
       modified_app_info.apiVersion = minimum_required_vulkan_version;
    }
 
-   /* Check If validation layer is enabled, if app enable validation layer,
-    * The validation layer feature VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT must be disabled
-    */
-   bool validationLayerEnabled = false;
-   const char *const *enabledLayerNames = pCreateInfo->ppEnabledLayerNames;
-   for (uint32_t i = 0; i < pCreateInfo->enabledLayerCount; i++) {
-      if (strcmp(enabledLayerNames[i], "VK_LAYER_KHRONOS_validation") == 0) {
-         validationLayerEnabled = true;
-         break;
-      }
-   }
-   if (validationLayerEnabled) {
-      VkValidationFeaturesEXT *pValidationFeatures = (VkValidationFeaturesEXT *)pCreateInfo->pNext;
-      while (pValidationFeatures && pValidationFeatures->sType != VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT) {
-         pValidationFeatures = (VkValidationFeaturesEXT *)pValidationFeatures->pNext;
-      }
-      assert(pValidationFeatures);
-      assert(pValidationFeatures->disabledValidationFeatureCount);
-
-      bool uniqueHandlesfeatureDisabled = false;
-      for (uint32_t i = 0; i < pValidationFeatures->disabledValidationFeatureCount; i++) {
-         if (pValidationFeatures->pDisabledValidationFeatures[i] == VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT ||
-             pValidationFeatures->pDisabledValidationFeatures[i] == VK_VALIDATION_FEATURE_DISABLE_ALL_EXT) {
-            uniqueHandlesfeatureDisabled = true;
-            break;
-         }
-      }
-      assert(uniqueHandlesfeatureDisabled);
-   }
-
-   /* Exclude VK_KHR_wayland_surface extension from ppEnabledExtensionNames.
-    * This extension is supported by this layer, so ICDs does not need to support it.
-    */
-   util::allocator allocator{pAllocator, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND};
-   util::extension_list enabled_extensions{allocator};
-   VkResult result;
-   result = enabled_extensions.add(pCreateInfo->ppEnabledExtensionNames, pCreateInfo->enabledExtensionCount);
-   if (result != VK_SUCCESS)
-   {
-      return result;
-   }
-
-   util::vector<const char *> modified_enabled_extensions{allocator};
-   wsi::remove_extensions_supported_by_layer(enabled_extensions);
-   if (!enabled_extensions.get_extension_strings(modified_enabled_extensions))
-   {
-      return VK_ERROR_OUT_OF_HOST_MEMORY;
-   }
-
    VkInstanceCreateInfo modified_info = *pCreateInfo;
    modified_info.pApplicationInfo = &modified_app_info;
-   modified_info.ppEnabledExtensionNames = modified_enabled_extensions.data();
-   modified_info.enabledExtensionCount = modified_enabled_extensions.size();
 
    /* Now call create instance on the chain further down the list.
     * Note that we do not remove the extensions that the layer supports from modified_info.ppEnabledExtensionNames.
     * Layers have to abide the rule that vkCreateInstance must not generate an error for unrecognized extension names.
     * Also, the loader filters the extension list to ensure that ICDs do not see extensions that they do not support.
     */
+   VkResult result;
    result = fpCreateInstance(&modified_info, pAllocator, pInstance);
    if (result != VK_SUCCESS)
    {
       return result;
    }
+   WSI_LOG_INFO("Create instance[%p]", (void *)*pInstance);
 
    instance_dispatch_table table{};
    result = table.populate(*pInstance, fpGetInstanceProcAddr);
@@ -233,6 +184,8 @@ VKAPI_ATTR VkResult create_instance(const VkInstanceCreateInfo *pCreateInfo, con
       return result;
    }
 
+   WSI_LOG_INFO("Create instance[%p] success", (void *)*pInstance);
+
    return VK_SUCCESS;
 }
 
@@ -297,6 +250,7 @@ VKAPI_ATTR VkResult create_device(VkPhysicalDevice physicalDevice, const VkDevic
    {
       return result;
    }
+   WSI_LOG_INFO("Create device[%p]", (void *)*pDevice);
 
    device_dispatch_table table{};
    result = table.populate(*pDevice, fpGetDeviceProcAddr);
@@ -339,6 +293,8 @@ VKAPI_ATTR VkResult create_device(VkPhysicalDevice physicalDevice, const VkDevic
       return result;
    }
 
+   WSI_LOG_INFO("Create device[%p] success", (void *)*pDevice);
+
    return VK_SUCCESS;
 }
 
@@ -354,6 +310,7 @@ wsi_layer_vkGetInstanceProcAddr(VkInstance instance, const char *funcName) VWL_A
 VWL_VKAPI_CALL(void)
 wsi_layer_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) VWL_API_POST
 {
+   WSI_LOG_INFO("Call Api - [%s] instance[%p]", __func__, (void *)instance);
    if (instance == VK_NULL_HANDLE)
    {
       return;
@@ -373,6 +330,7 @@ wsi_layer_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pA
 VWL_VKAPI_CALL(void)
 wsi_layer_vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) VWL_API_POST
 {
+   WSI_LOG_INFO("Call Api - [%s] device[%p]", __func__, (void *)device);
    if (device == VK_NULL_HANDLE)
    {
       return;
@@ -393,6 +351,7 @@ VWL_VKAPI_CALL(VkResult)
 wsi_layer_vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
                            VkInstance *pInstance) VWL_API_POST
 {
+   WSI_LOG_INFO("Call Api - [%s]", __func__);
    return layer::create_instance(pCreateInfo, pAllocator, pInstance);
 }
 
@@ -400,12 +359,14 @@ VWL_VKAPI_CALL(VkResult)
 wsi_layer_vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
                          const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) VWL_API_POST
 {
+   WSI_LOG_INFO("Call Api - [%s], VkDevice IN[%p]", __func__, (void *)*pDevice);
    return layer::create_device(physicalDevice, pCreateInfo, pAllocator, pDevice);
 }
 
 VWL_VKAPI_CALL(VkResult)
 VK_LAYER_EXPORT wsi_layer_vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) VWL_API_POST
 {
+   WSI_LOG_INFO("Call Api - [%s]", __func__);
    assert(pVersionStruct);
    assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
 
index 7a4f8582f0bdbb1419c2b087b4a233276bd31b56..fc681aa1c900d40471b2256ffea128f848809545 100644 (file)
@@ -120,13 +120,13 @@ wsi_layer_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface,
 
 VWL_VKAPI_CALL(VkResult)
 wsi_layer_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice,
-                                                                        const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
-                                                                        VkSurfaceCapabilities2KHR *pSurfaceCapabilities)
+                                                     const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+                                                     VkSurfaceCapabilities2KHR *pSurfaceCapabilities) VWL_API_POST
 {
    auto &instance = layer::instance_private_data::get(physicalDevice);
    if (instance.should_layer_handle_surface(physicalDevice, pSurfaceInfo->surface))
    {
-      wsi::surface_properties *props = wsi::get_surface_properties(pSurfaceInfo->surface);
+      wsi::surface_properties *props = wsi::get_surface_properties(instance, pSurfaceInfo->surface);
       assert(props != nullptr);
          const void *pNext = pSurfaceCapabilities->pNext;
          while (pNext) {
@@ -150,14 +150,14 @@ wsi_layer_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDe
 
 VWL_VKAPI_CALL(VkResult)
 wsi_layer_vkGetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice,
-                                                                   const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
-                                                                   uint32_t *pSurfaceFormatCount,
-                                                                   VkSurfaceFormat2KHR *pSurfaceFormats)
+                                                const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+                                                uint32_t *pSurfaceFormatCount,
+                                                VkSurfaceFormat2KHR *pSurfaceFormats) VWL_API_POST
 {
    auto &instance = layer::instance_private_data::get(physicalDevice);
    if (instance.should_layer_handle_surface(physicalDevice, pSurfaceInfo->surface))
    {
-      wsi::surface_properties *props = wsi::get_surface_properties(pSurfaceInfo->surface);
+      wsi::surface_properties *props = wsi::get_surface_properties(instance, pSurfaceInfo->surface);
       assert(props != nullptr);
       return props->get_surface_formats_2(physicalDevice, pSurfaceInfo->surface, pSurfaceFormatCount, pSurfaceFormats);
    }
@@ -166,32 +166,16 @@ wsi_layer_vkGetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice,
                                                            pSurfaceFormats);
 }
 
-VWL_VKAPI_CALL(VkResult)
-wsi_layer_vkGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice,
-                                                                        VkSurfaceKHR surface, uint32_t* pRectCount,
-                                                                        VkRect2D* pRects)
-{
-   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);
-      assert(props != nullptr);
-      return props->get_surface_present_rects(physicalDevice, surface, pRectCount, pRects);
-   }
-
-   return instance.disp.GetPhysicalDevicePresentRectanglesKHR(physicalDevice, surface, pRectCount, pRects);
-}
-
 VWL_VKAPI_CALL(VkResult)
 wsi_layer_vkGetPhysicalDeviceSurfaceCapabilities2EXT(VkPhysicalDevice physicalDevice,
-                                                                            VkSurfaceKHR surface,
-                                                                            VkSurfaceCapabilities2EXT* pSurfaceCapabilities)
+                                                     VkSurfaceKHR surface,
+                                                     VkSurfaceCapabilities2EXT* pSurfaceCapabilities) VWL_API_POST
 {
    auto &instance = layer::instance_private_data::get(physicalDevice);
    if (instance.should_layer_handle_surface(physicalDevice, surface))
    {
       VkResult res = VK_SUCCESS;
-      wsi::surface_properties *props = wsi::get_surface_properties(surface);
+      wsi::surface_properties *props = wsi::get_surface_properties(instance, surface);
       assert(props != nullptr);
 
          VkSurfaceCapabilitiesKHR surfaceCaps;
index 8bda47aee1316e750ae709541068fcbc3d86ff34..2e519040dabdbf42e0958a8072ab7deb3cd43a33 100644 (file)
@@ -71,23 +71,17 @@ wsi_layer_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface,
 
 VWL_VKAPI_CALL(VkResult)
 wsi_layer_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice,
-                                                                        const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
-                                                                        VkSurfaceCapabilities2KHR *pSurfaceCapabilities);
+                                                     const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+                                                     VkSurfaceCapabilities2KHR *pSurfaceCapabilities) VWL_API_POST;
 
 VWL_VKAPI_CALL(VkResult)
 wsi_layer_vkGetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice,
-                                                                   const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
-                                                                   uint32_t *pSurfaceFormatCount,
-                                                                   VkSurfaceFormat2KHR *pSurfaceFormats);
-
-VWL_VKAPI_CALL(VkResult)
-wsi_layer_vkGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice,
-                                                                        VkSurfaceKHR surface, uint32_t* pRectCount,
-                                                                        VkRect2D* pRects);
+                                                const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+                                                uint32_t *pSurfaceFormatCount,
+                                                VkSurfaceFormat2KHR *pSurfaceFormats) VWL_API_POST;
 
 VWL_VKAPI_CALL(VkResult)
 wsi_layer_vkGetPhysicalDeviceSurfaceCapabilities2EXT(VkPhysicalDevice physicalDevice,
-                                                                            VkSurfaceKHR surface,
-                                                                            VkSurfaceCapabilities2EXT* pSurfaceCapabilities);
+                                                     VkSurfaceKHR surface,
+                                                     VkSurfaceCapabilities2EXT* pSurfaceCapabilities) VWL_API_POST;
 
-}
index 906f6df3344d8660896cddd1de285836417add67..dcb0b55f4a8c58ad2debac30f61523bfb8d8b98f 100644 (file)
@@ -37,6 +37,7 @@
 #include "private_data.hpp"
 #include "swapchain_api.hpp"
 #include <util/helpers.hpp>
+#include <util/log.hpp>
 
 static bool swapchain_on_prensent = false;
 VWL_VKAPI_CALL(VkResult)
@@ -44,7 +45,7 @@ wsi_layer_vkCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *
                                const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) VWL_API_POST
 {
    if (swapchain_on_prensent) {
-      wsi_error("Already created other swapchain");
+      WSI_LOG_ERROR("Already created other swapchain");
       return VK_ERROR_INITIALIZATION_FAILED;
    }
 
@@ -64,15 +65,15 @@ wsi_layer_vkCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *
    auto sc = wsi::allocate_surface_swapchain(surface, device_data, pAllocator);
    if (sc == nullptr)
    {
-      wsi_error("Alloc swapchain failed.");
+      WSI_LOG_ERROR("Alloc swapchain failed.");
       return VK_ERROR_OUT_OF_HOST_MEMORY;
    }
-   wsi_info("Created new swapchain [%p], VkSurface [%p].", sc, surface);
+   WSI_LOG_INFO("Created new swapchain [%p], VkSurface [%p].", &(*sc), reinterpret_cast<void *>(surface));
 
    VkResult result = sc->init(device, pSwapchainCreateInfo);
    if (result != VK_SUCCESS)
    {
-      wsi_error("Init swapchain failed, ret [%d].", result);
+      WSI_LOG_ERROR("Init swapchain failed, ret [%d].", result);
       return result;
    }
 
@@ -100,7 +101,7 @@ wsi_layer_vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapc,
       return device_data.disp.DestroySwapchainKHR(device_data.device, swapc, pAllocator);
    }
 
-   wsi_info("Destroy swapchain [%p], VkSurface [%p].", swapc);
+   WSI_LOG_INFO("Destroy swapchain [%p]", reinterpret_cast<void *>(swapc));
 
    assert(swapc != VK_NULL_HANDLE);
    auto *sc = reinterpret_cast<wsi::swapchain_base *>(swapc);
@@ -220,28 +221,14 @@ wsi_layer_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo)
    }
 
    VkResult ret = VK_SUCCESS;
-   const VkPresentRegionsKHR *regions = NULL;
-   VkBaseOutStructure *s;
-   for (s = (struct VkBaseOutStructure *)((void *)(pPresentInfo->pNext));s; s = s->pNext)
-   {
-       if (s->sType == VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR)
-       {
-           regions = (const VkPresentRegionsKHR *)s;
-           break;
-       }
-   }
    for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i)
    {
       VkSwapchainKHR swapc = pPresentInfo->pSwapchains[i];
-      const VkPresentRegionKHR *region = NULL;
 
       auto *sc = reinterpret_cast<wsi::swapchain_base *>(swapc);
       assert(sc != nullptr);
 
-      if (regions && regions->pRegions)
-         region = &regions->pRegions[i];
-
-      res = sc->queue_present(queue, pPresentInfo, pPresentInfo->pImageIndices[i], region);
+      res = sc->queue_present(queue, present_info, pPresentInfo->pImageIndices[i]);
 
       if (pPresentInfo->pResults != nullptr)
       {
@@ -257,6 +244,7 @@ wsi_layer_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo)
    return ret;
 }
 
+
 VWL_VKAPI_CALL(VkResult)
 wsi_layer_vkGetDeviceGroupPresentCapabilitiesKHR(
    VkDevice device, VkDeviceGroupPresentCapabilitiesKHR *pDeviceGroupPresentCapabilities) VWL_API_POST
diff --git a/util/log.cpp b/util/log.cpp
deleted file mode 100644 (file)
index 5e29217..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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.
- */
-
-#include "log.hpp"
-#include <iostream>
-#include <cstdarg>
-#include <cstdio>
-#include <cstdlib>
-#include <string>
-#include <cstring>
-
-namespace util
-{
-
-#ifndef NDEBUG
-
-/**
- * @brief check if a log level is enabled, and print it
-*/
-static int check_and_print_log_level(int level)
-{
-   struct log_state
-   {
-      int level = WSI_DEFAULT_LOG_LEVEL;
-      log_state()
-      {
-         char *env = std::getenv("VULKAN_WSI_DEBUG_LEVEL");
-         if (env != nullptr)
-         {
-            try
-            {
-               level = std::stoi(env);
-            }
-            catch (const std::exception &e)
-            {
-               std::fprintf(stderr, "Error: %s\n", e.what());
-            }
-         }
-      }
-   };
-   static log_state state;
-
-   int result = level <= state.level;
-   if (result)
-   {
-      switch (level)
-      {
-      case 0:
-         /* Reserved for no logging */
-         break;
-      case 1:
-         std::fprintf(stderr, "ERROR");
-         break;
-      case 2:
-         std::fprintf(stderr, "WARNING");
-         break;
-      case 3:
-         std::fprintf(stderr, "INFO");
-         break;
-      default:
-         std::fprintf(stderr, "LEVEL_%d", level);
-         break;
-      }
-   }
-   return result;
-}
-
-void wsi_log_message(int level, const char *file, int line, const char *format, ...)
-{
-   if (check_and_print_log_level(level))
-   {
-      std::fprintf(stderr, "(%s:%d): ", file, line);
-      std::va_list args;
-      va_start(args, format);
-      std::vfprintf(stderr, format, args);
-      va_end(args);
-      std::putc('\n', stderr);
-   }
-}
-
-#endif
-
-} /* namespace util */
index 2bd71de7c1d9bb61380d2d6831fc8607a01b1ba2..f6c60d3ac8c39064715a984f623cdf9f660239d5 100644 (file)
  */
 
 #pragma once
-namespace util
-{
-#define WSI_DEFAULT_LOG_LEVEL 1
 
-/**
- * @brief Log a message to a certain log level
- *
- * @details For the log level, we use a bigger integer to represent an increased
- * level of verbosity. If this is not specified, the log level is default to 1.
- * We use a "staircase" approach with respect to printing logs. We  print all log
- * messages equal or below the log level set, e.g. if VULKAN_WSI_DEBUG_LEVEL
- * is set to 2, messages with log level 1 and 2 are printed. Please note that
- * the newline character '\n' is automatically appended.
- *
- * @param[in] level     The log level of this message, you can set an arbitary
- *                      integer however please refer to the included macros for
- *                      the sensible defaults.
- * @param[in] file      The source file name (``__FILE__``)
- * @param[in] line      The source file line number (``__LINE__``)
- * @param[in] format    A C-style formatting string.
- */
 
-void wsi_log_message(int level, const char *file, int line, const char *format, ...)
-#ifdef __GNUC__
-   __attribute__((format(printf, 4, 5)))
+#ifdef LOG_TAG
+#undef LOG_TAG
 #endif
-   ;
+#define LOG_TAG "WSI"
+#include <dlog/dlog.h>
 
-#ifdef NDEBUG
-static constexpr bool wsi_log_enable = false;
-#else
-static constexpr bool wsi_log_enable = true;
-#endif
 
-#define WSI_LOG(level, ...) \
-   do { if (::util::wsi_log_enable) ::util::wsi_log_message(level, __FILE__, __LINE__, __VA_ARGS__); } while (0)
+namespace util
+{
 
-#define WSI_LOG_ERROR(...) WSI_LOG(1, __VA_ARGS__)
-#define WSI_LOG_WARNING(...) WSI_LOG(2, __VA_ARGS__)
-#define WSI_LOG_INFO(...) WSI_LOG(3, __VA_ARGS__)
+#define WSI_LOG_ERROR(fmt, x...) LOGE(fmt, ##x)
+#define WSI_LOG_WARNING(fmt, x...) LOGW(fmt, ##x)
+#define WSI_LOG_INFO(fmt, x...) LOGI(fmt, ##x)
 
 } /* namespace util */
diff --git a/util/log_util.hpp b/util/log_util.hpp
deleted file mode 100644 (file)
index 4789199..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#pragma once
-
-#define LOG_TAG "WSI"
-#include <dlog/dlog.h>
-
-#define wsi_info(f, x...)    LOGI(f, ##x)
-#define wsi_error(f, x...)   LOGE(f, ##x)
-
index ab24f0bd84bb875b59de629dae4bd804dfd3bee6..6c8cd30f1f88a94964702c1cf954feab6dd68b29 100644 (file)
@@ -40,6 +40,7 @@
 #include <unistd.h>
 #include <vulkan/vulkan.h>
 
+#include <util/helpers.hpp>
 #include "util/log.hpp"
 
 #include "swapchain_base.hpp"
@@ -240,8 +241,11 @@ VkResult swapchain_base::init(VkDevice device, const VkSwapchainCreateInfoKHR *s
    image_create_info.queueFamilyIndexCount = swapchain_create_info->queueFamilyIndexCount;
    image_create_info.pQueueFamilyIndices = swapchain_create_info->pQueueFamilyIndices;
    image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
-
+#if BUILD_WSI_TIZEN
+   result = m_free_image_semaphore.init(0);
+#else
    result = m_free_image_semaphore.init(m_swapchain_images.size());
+#endif
    if (result != VK_SUCCESS)
    {
       assert(result == VK_ERROR_OUT_OF_HOST_MEMORY);
@@ -505,6 +509,13 @@ VkResult swapchain_base::queue_present(VkQueue queue, const VkPresentInfoKHR *pr
    {
       wait_semaphores = present_info->pWaitSemaphores;
       sem_count = present_info->waitSemaphoreCount;
+      const VkPresentRegionsKHR *present_regions_info = util::find_extension<VkPresentRegionsKHR>(
+              VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR, present_info->pNext);
+
+      if (present_regions_info != nullptr)
+      {
+         set_present_regions(present_regions_info->pRegions);
+      }
    }
 
    VkResult result = image_set_present_payload(m_swapchain_images[image_index], queue, wait_semaphores, sem_count);
@@ -587,12 +598,14 @@ VkResult swapchain_base::wait_for_free_buffer(uint64_t timeout)
        * waiting */
 
       retval = get_free_buffer(&timeout);
+#ifndef BUILD_WSI_TIZEN
       if (retval == VK_SUCCESS)
       {
          /* the sub-implementation has done it's thing, so re-check the
           * semaphore */
          retval = m_free_image_semaphore.wait(timeout);
       }
+#endif
    }
 
    return retval;
index c8d5573d5e129891cdea5a99c62fb4a0ff4cfe05..485cca0b8db870955af7311da87b75feace44b1f 100644 (file)
@@ -450,6 +450,18 @@ protected:
       m_error_state = state;
    }
 
+   const VkPresentRegionKHR *get_present_regions()
+   {
+      const VkPresentRegionKHR *ret = m_present_region;
+      m_present_region = nullptr;
+      return ret;
+   }
+
+   void set_present_regions(const VkPresentRegionKHR *present_region)
+   {
+      m_present_region = present_region;
+   }
+
 private:
    std::mutex m_image_acquire_lock;
    /**
@@ -541,6 +553,8 @@ private:
     * @brief A flag to track if swapchain has started presenting.
     */
    bool m_started_presenting;
+
+   const VkPresentRegionKHR *m_present_region;
 };
 
 } /* namespace wsi */
diff --git a/wsi/swapchain_base_tizen.cpp b/wsi/swapchain_base_tizen.cpp
deleted file mode 100644 (file)
index c64d6e5..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-#include <array>
-#include <cassert>
-#include <cerrno>
-#include <cstdio>
-#include <cstdlib>
-
-#include <unistd.h>
-#include <vulkan/vulkan.h>
-
-#include "swapchain_base_tizen.hpp"
-
-#if VULKAN_WSI_DEBUG > 0
-#define WSI_PRINT_ERROR(...) fprintf(stderr, ##__VA_ARGS__)
-#else
-#define WSI_PRINT_ERROR(...) (void)0
-#endif
-
-namespace wsi
-{
-
-swapchain_base::swapchain_base(layer::device_private_data &dev_data, const VkAllocationCallbacks *callbacks)
-   : m_device_data(dev_data)
-   , m_allocator(callbacks, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)
-   , m_swapchain_images(m_allocator)
-   , m_surface(VK_NULL_HANDLE)
-   , m_present_mode(VK_PRESENT_MODE_IMMEDIATE_KHR)
-   , m_descendant(VK_NULL_HANDLE)
-   , m_ancestor(VK_NULL_HANDLE)
-   , m_device(VK_NULL_HANDLE)
-   , m_queue(VK_NULL_HANDLE)
-{
-}
-
-VkResult swapchain_base::init(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info)
-{
-   assert(device != VK_NULL_HANDLE);
-   assert(swapchain_create_info != nullptr);
-   assert(swapchain_create_info->surface != VK_NULL_HANDLE);
-
-   VkResult result;
-
-   m_device = device;
-   m_surface = swapchain_create_info->surface;
-
-   /* We have allocated images, we can call the platform init function if something needs to be done. */
-   result = init_platform(device, swapchain_create_info);
-   if (result != VK_SUCCESS)
-   {
-      wsi_error("Init platform for VkSurface[%p] failed", m_surface);
-      return result;
-   }
-
-   VkImageCreateInfo image_create_info = {};
-   image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
-   image_create_info.pNext = nullptr;
-   image_create_info.imageType = VK_IMAGE_TYPE_2D;
-   image_create_info.format = swapchain_create_info->imageFormat;
-   image_create_info.extent = { swapchain_create_info->imageExtent.width, swapchain_create_info->imageExtent.height, 1 };
-   image_create_info.mipLevels = 1;
-   image_create_info.arrayLayers = swapchain_create_info->imageArrayLayers;
-   image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
-   image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
-   image_create_info.usage = swapchain_create_info->imageUsage;
-   image_create_info.flags = 0;
-   image_create_info.sharingMode = swapchain_create_info->imageSharingMode;
-   image_create_info.queueFamilyIndexCount = swapchain_create_info->queueFamilyIndexCount;
-   image_create_info.pQueueFamilyIndices = swapchain_create_info->pQueueFamilyIndices;
-   image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
-
-   result = create_image(image_create_info);
-   if (result != VK_SUCCESS)
-   {
-      wsi_error("Create image for VkSurface[%p] failed", m_surface);
-      return result;
-   }
-
-   m_device_data.disp.GetDeviceQueue(m_device, 0, 0, &m_queue);
-
-   if (swapchain_create_info->oldSwapchain != VK_NULL_HANDLE)
-   {
-      /* TO BE DONE - How to reuse the old swapchain */
-      /*
-      m_ancestor = swapchain_create_info->oldSwapchain;
-
-      auto *ancestor = reinterpret_cast<swapchain_base *>(m_ancestor);
-      ancestor->deprecate(reinterpret_cast<VkSwapchainKHR>(this));
-      */
-   }
-
-   return VK_SUCCESS;
-}
-
-void swapchain_base::teardown()
-{
-   if (m_queue != VK_NULL_HANDLE)
-   {
-      /* Make sure the vkFences are done signaling. */
-      m_device_data.disp.QueueWaitIdle(m_queue);
-   }
-}
-
-VkResult swapchain_base::acquire_next_image(uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *image_index)
-{
-   VkResult retval;
-
-   retval = acquire_image(image_index);
-   if (retval != VK_SUCCESS)
-      return retval;
-
-   if (VK_NULL_HANDLE != semaphore || VK_NULL_HANDLE != fence)
-   {
-      VkSubmitInfo submit = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
-
-      if (VK_NULL_HANDLE != semaphore)
-      {
-         submit.signalSemaphoreCount = 1;
-         submit.pSignalSemaphores = &semaphore;
-      }
-
-      submit.commandBufferCount = 0;
-      submit.pCommandBuffers = nullptr;
-      retval = m_device_data.disp.QueueSubmit(m_queue, 1, &submit, fence);
-      assert(retval == VK_SUCCESS);
-   }
-
-   return VK_SUCCESS;
-}
-
-VkResult swapchain_base::get_swapchain_images(uint32_t *swapchain_image_count, VkImage *swapchain_images)
-{
-   if (swapchain_images == nullptr)
-   {
-      /* Return the number of swapchain images. */
-      *swapchain_image_count = m_swapchain_images.size();
-
-      return VK_SUCCESS;
-   }
-   else
-   {
-      assert(m_swapchain_images.size() > 0);
-      assert(*swapchain_image_count > 0);
-
-      /* Populate array, write actual number of images returned. */
-      uint32_t current_image = 0;
-
-      do
-      {
-         swapchain_images[current_image] = m_swapchain_images[current_image].image;
-
-         current_image++;
-
-         if (current_image == m_swapchain_images.size())
-         {
-            *swapchain_image_count = current_image;
-
-            return VK_SUCCESS;
-         }
-
-      } while (current_image < *swapchain_image_count);
-
-      /* If swapchain_image_count is smaller than the number of presentable images
-       * in the swapchain, VK_INCOMPLETE must be returned instead of VK_SUCCESS. */
-      *swapchain_image_count = current_image;
-
-      return VK_INCOMPLETE;
-   }
-}
-
-VkResult swapchain_base::queue_present(VkQueue queue, const VkPresentInfoKHR *present_info, const uint32_t image_index, const VkPresentRegionKHR *region)
-{
-   VkResult result;
-
-   /* When the semaphore that comes in is signalled, we know that all work is done. So, we do not
-    * want to block any future Vulkan queue work on it. So, we pass in BOTTOM_OF_PIPE bit as the
-    * wait flag.
-    */
-   VkPipelineStageFlags pipeline_stage_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
-
-   VkSubmitInfo submit_info = { VK_STRUCTURE_TYPE_SUBMIT_INFO,
-                               NULL,
-                               present_info->waitSemaphoreCount,
-                               present_info->pWaitSemaphores,
-                               &pipeline_stage_flags,
-                               0,
-                               NULL,
-                               0,
-                               NULL };
-
-   result = m_device_data.disp.ResetFences(m_device, 1, &m_swapchain_images[image_index].present_fence);
-   if (result != VK_SUCCESS)
-   {
-      return result;
-   }
-
-   result = m_device_data.disp.QueueSubmit(queue, 1, &submit_info, m_swapchain_images[image_index].present_fence);
-   if (result != VK_SUCCESS)
-   {
-      return result;
-   }
-
-   present_image(image_index, region);
-
-   return VK_SUCCESS;
-}
-
-VkResult swapchain_base::create_swapchain_images(VkImageCreateInfo* pCreateInfo,
-                                                       const VkAllocationCallbacks* pAllocator,
-                                                       VkImage* pImage)
-{
-   return create_external_image(pCreateInfo, pAllocator, pImage);
-}
-
-VkResult swapchain_base::bind_swapchain_images(const uint32_t image_index, VkImage image)
-{
-   return bind_external_image(image_index, image);
-}
-
-void swapchain_base::deprecate(VkSwapchainKHR descendant)
-{
-   // TO BE DONE - release old swapchain resources
-}
-
-void swapchain_base::clear_ancestor()
-{
-   m_ancestor = VK_NULL_HANDLE;
-}
-
-void swapchain_base::clear_descendant()
-{
-   m_descendant = VK_NULL_HANDLE;
-}
-
-#undef WSI_PRINT_ERROR
-
-} /* namespace wsi */
-
diff --git a/wsi/swapchain_base_tizen.hpp b/wsi/swapchain_base_tizen.hpp
deleted file mode 100644 (file)
index c98d10e..0000000
+++ /dev/null
@@ -1,247 +0,0 @@
-#pragma once
-
-#include <vulkan/vulkan.h>
-
-#include <layer/private_data.hpp>
-#include <util/timed_semaphore.hpp>
-#include <util/custom_allocator.hpp>
-#include <util/log_util.hpp>
-
-namespace wsi
-{
-struct swapchain_image
-{
-   /* Implementation specific data */
-   void *data{nullptr};
-
-   VkImage image{VK_NULL_HANDLE};
-   VkFence present_fence{VK_NULL_HANDLE};
-
-   bool is_external{false};
-};
-
-/**
- * @brief Base swapchain class
- *
- * - the swapchain implementations inherit from this class.
- * - the VkSwapchain will hold a pointer to this class.
- * - much of the swapchain implementation is done by this class, as the only things needed
- *   in the implementation are how to create a presentable image and how to present an image.
- */
-class swapchain_base
-{
-public:
-   swapchain_base(layer::device_private_data &dev_data, const VkAllocationCallbacks *allocator);
-
-   virtual ~swapchain_base()
-   {
-      /* nop */
-   }
-
-   /**
-    * @brief Create swapchain.
-    *
-    * Perform all swapchain initialization, create presentable images etc.
-    */
-   VkResult init(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info);
-
-   /**
-    * @brief Acquires a free image.
-    *
-    * Current implementation blocks until a free image is available.
-    *
-    * @param timeout Unused since we block until a free image is available.
-    *
-    * @param semaphore A semaphore signaled once an image is acquired.
-    *
-    * @param fence A fence signaled once an image is acquired.
-    *
-    * @param pImageIndex The index of the acquired image.
-    *
-    * @return VK_SUCCESS on completion.
-    */
-   VkResult acquire_next_image(uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *image_index);
-
-   /**
-    * @brief Gets the number of swapchain images or a number of at most
-    * m_num_swapchain_images images.
-    *
-    * @param pSwapchainImageCount Used to return number of images in
-    * the swapchain if second parameter is nullptr or represents the
-    * number of images to be returned in second parameter.
-    *
-    * @param pSwapchainImage Array of VkImage handles.
-    *
-    * @return If number of requested images is less than the number of available
-    * images in the swapchain returns VK_INCOMPLETE otherwise VK_SUCCESS.
-    */
-   VkResult get_swapchain_images(uint32_t *swapchain_image_count, VkImage *swapchain_image);
-
-   /**
-    * @brief Submits a present request for the supplied image.
-    *
-    * @param queue The queue to which the submission will be made to.
-    *
-    * @param pPresentInfo Information about the swapchain and image to be presented.
-    *
-    * @param imageIndex The index of the image to be presented.
-    *
-    * @return If queue submission fails returns error of vkQueueSubmit, if the
-    * swapchain has a descendant who started presenting returns VK_ERROR_OUT_OF_DATE_KHR,
-    * otherwise returns VK_SUCCESS.
-    */
-   VkResult queue_present(VkQueue queue, const VkPresentInfoKHR *present_info, const uint32_t image_index, const VkPresentRegionKHR *region);
-
-   VkResult create_swapchain_images(VkImageCreateInfo* pCreateInfo,
-                                          const VkAllocationCallbacks* pAllocator,
-                                          VkImage* pImage);
-
-   VkResult bind_swapchain_images(const uint32_t image_index, VkImage image);
-
-protected:
-
-   layer::device_private_data &m_device_data;
-
-   /**
-    * @brief User provided memory allocation callbacks.
-    */
-   const util::allocator m_allocator;
-
-   /**
-    * @brief Vector of images in the swapchain.
-    */
-   util::vector<swapchain_image> m_swapchain_images;
-
-   /**
-    * @brief Handle to the surface object this swapchain will present images to.
-    */
-   VkSurfaceKHR m_surface;
-
-   /**
-    * @brief present mode to use for this swapchain
-    */
-   VkPresentModeKHR m_present_mode;
-
-   /**
-    * @brief Descendant of this swapchain.
-    * Used to check whether or not a descendant of this swapchain has started
-    * presenting images to the surface already. If it has, any calls to queuePresent
-    * for this swapchain will return VK_ERROR_OUT_OF_DATE_KHR.
-    */
-   VkSwapchainKHR m_descendant;
-
-   /**
-    * @brief Ancestor of this swapchain.
-    * Used to check whether the ancestor swapchain has completed all of its
-    * pending page flips (this is required before this swapchain presents for the
-    * first time.
-    */
-   VkSwapchainKHR m_ancestor;
-
-   /**
-    *  @brief Handle to the logical device the swapchain is created for.
-    */
-   VkDevice m_device;
-
-   /**
-    *  @brief Handle to the queue used for signalling submissions
-    */
-   VkQueue m_queue;
-
-   /**
-    * @brief Return the VkAllocationCallbacks passed in this object constructor.
-    */
-   const VkAllocationCallbacks *get_allocation_callbacks()
-   {
-      return m_allocator.get_original_callbacks();
-   }
-
-   /**
-    * @brief Method to wait on all pending buffers to be displayed.
-    */
-   void wait_for_pending_buffers();
-
-   /**
-    * @brief Remove cached ancestor.
-    */
-   void clear_ancestor();
-
-   /**
-    * @brief Remove cached descendant.
-    */
-   void clear_descendant();
-
-   /**
-    * @brief Deprecate this swapchain.
-    *
-    * If an application replaces an old swapchain with a new one, the older swapchain
-    * needs to be deprecated. This method releases all the FREE images and sets the
-    * descendant of the swapchain. We do not need to care about images in other states
-    * at this point since they will be released by the page flip thread.
-    *
-    * @param descendant Handle to the descendant swapchain.
-    */
-   void deprecate(VkSwapchainKHR descendant);
-
-   /**
-    * @brief Platform specific initialization
-    */
-   virtual VkResult init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info) = 0;
-
-   /**
-    * @brief Base swapchain teardown.
-    *
-    * Even though the inheritance gives us a nice way to defer display specific allocation
-    * and presentation outside of the base class, it however robs the children classes - which
-    * also happen to do some of their state setting - the oppurtunity to do the last clean up
-    * call, as the base class' destructor is called at the end. This method provides a way to do it.
-    * The destructor is a virtual function and much of the swapchain teardown happens in this method
-    * which gets called from the child's destructor.
-    */
-   void teardown();
-
-   /**
-    * @brief Creates a new swapchain image.
-    *
-    * @param image_create_info Data to be used to create the image.
-    *
-    * @param image Handle to the image.
-    *
-    * @return If image creation is successful returns VK_SUCCESS, otherwise
-    * will return VK_ERROR_OUT_OF_DEVICE_MEMORY or VK_ERROR_INITIALIZATION_FAILED
-    * depending on the error that occured.
-    */
-   virtual VkResult create_image(const VkImageCreateInfo &image_create_info) = 0;
-
-   virtual VkResult acquire_image(uint32_t *image_index) = 0;
-
-   /**
-    * @brief Method to present and image
-    *
-    * @param pending_index Index of the pending image to be presented.
-    *
-    */
-   virtual void present_image(uint32_t pending_index, const VkPresentRegionKHR *region) = 0;
-
-   /**
-    * @brief Transition a presented image to free.
-    *
-    * Called by swapchain implementation when a new image has been presented.
-    *
-    * @param presented_index Index of the image to be marked as free.
-    */
-   void unpresent_image(uint32_t presented_index);
-
-   /**
-    * @brief Method to release a swapchain image
-    *
-    * @param image Handle to the image about to be released.
-    */
-   virtual void destroy_image(void){};
-   virtual VkResult create_external_image(VkImageCreateInfo* pCreateInfo,
-                                           const VkAllocationCallbacks* pAllocator, VkImage* pImage) = 0;
-   virtual VkResult bind_external_image(const uint32_t image_index, VkImage image) = 0;
-};
-
-} /* namespace wsi */
-
diff --git a/wsi/tizen/surface.cpp b/wsi/tizen/surface.cpp
new file mode 100644 (file)
index 0000000..8d2b4e5
--- /dev/null
@@ -0,0 +1,65 @@
+#include "surface.hpp"
+#include "swapchain.hpp"
+#include "surface_properties.hpp"
+#include "util/log.hpp"
+
+namespace wsi
+{
+namespace tizen
+{
+
+struct surface::init_parameters
+{
+   const util::allocator& allocator;
+   wl_display *display;
+   wl_surface *surf;
+};
+
+
+surface::surface(const init_parameters &params)
+   : wsi::surface()
+   , wayland_display(params.display)
+   , wayland_surface(params.surf)
+   , properties(*this, params.allocator)
+{
+}
+
+bool surface::init()
+{
+   /* Do some surface init for tizen*/
+   return true;
+}
+
+util::unique_ptr<surface> 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<surface>(params);
+   if (wsi_surface != nullptr)
+   {
+      if (wsi_surface->init())
+      {
+         return wsi_surface;
+      }
+   }
+   return nullptr;
+}
+
+surface::~surface()
+{
+}
+
+wsi::surface_properties &surface::get_properties()
+{
+   return properties;
+}
+
+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, *this));
+}
+
+}
+}
diff --git a/wsi/tizen/surface.hpp b/wsi/tizen/surface.hpp
new file mode 100644 (file)
index 0000000..7280ad9
--- /dev/null
@@ -0,0 +1,69 @@
+
+#pragma once
+
+#include "wsi/surface.hpp"
+#include "surface_properties.hpp"
+
+namespace wsi
+{
+namespace tizen
+{
+
+class surface : public wsi::surface
+{
+public:
+   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<surface> make_surface(const util::allocator &allocator, wl_display *display,
+                                                 wl_surface *surf);
+
+   /** Destructor */
+   ~surface() override;
+
+   wsi::surface_properties &get_properties() override;
+   util::unique_ptr<swapchain_base> 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;
+   }
+
+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;
+   /** Surface properties specific to the Wayland surface. */
+   surface_properties properties;
+
+};
+}
+}
index ea89d6e341383bad38890509575d1170d64b1049..0dd05303eb0864a7c26d93d5500198ead9ce281c 100644 (file)
@@ -33,7 +33,10 @@ extern "C" {
 #include <array>
 #include <string.h>
 #include "surface_properties.hpp"
+#include "surface.hpp"
 #include "layer/private_data.hpp"
+#include "util/log.hpp"
+#include "util/macros.hpp"
 
 #define NELEMS(x) (sizeof(x) / sizeof(x[0]))
 
@@ -42,6 +45,16 @@ namespace wsi
 namespace tizen
 {
 
+surface_properties::surface_properties(surface &wsi_surface, const util::allocator &allocator)
+   : specific_surface(&wsi_surface)
+{
+}
+
+surface_properties::surface_properties()
+   : specific_surface(nullptr)
+{
+}
+
 surface_properties &surface_properties::get_instance()
 {
    static surface_properties instance;
@@ -267,38 +280,46 @@ static const char *required_device_extensions[] = {
    VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME,
    VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
    VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
+   VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME,
+   VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME,
 };
 
-static std::unique_ptr<util::extension_list> populate_device_extensions()
+VkResult surface_properties::get_required_device_extensions(util::extension_list &extension_list)
 {
-   std::unique_ptr<util::extension_list> ret(new util::extension_list(util::allocator::get_generic()));
-   ret->add(required_device_extensions, NELEMS(required_device_extensions));
-
-   return ret;
+   return extension_list.add(required_device_extensions, NELEMS(required_device_extensions));
 }
 
-const util::extension_list &surface_properties::get_required_device_extensions()
+/* TODO: Check for zwp_linux_dmabuf_v1 protocol in display */
+VWL_VKAPI_CALL(VkBool32)
+GetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physical_device, uint32_t queue_index,
+                                                        struct wl_display *display)
 {
-   static std::unique_ptr<util::extension_list> device_extensions = populate_device_extensions();
-   return *device_extensions;
+   return VK_TRUE;
 }
 
-bool surface_properties::physical_device_supported(VkPhysicalDevice dev)
+VWL_VKAPI_CALL(VkBool32)
+CreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
+                        const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) VWL_API_POST
 {
-   static util::extension_list device_extensions{util::allocator::get_generic()};
-   device_extensions.add(dev);
-
-   static util::extension_list required_extensions{util::allocator::get_generic()};
-   required_extensions.add(required_device_extensions, NELEMS(required_device_extensions));
-
-   return device_extensions.contains(required_extensions);
-}
+   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 = surface::make_surface(allocator, pCreateInfo->display, pCreateInfo->surface);
+   if (wsi_surface == nullptr)
+   {
+      return VK_ERROR_OUT_OF_HOST_MEMORY;
+   }
 
-/* TODO: Check for zwp_linux_dmabuf_v1 protocol in display */
-VkBool32 GetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physical_device, uint32_t queue_index,
-                                                        struct wl_display *display)
-{
-   return VK_TRUE;
+   VkResult res = instance_data.disp.CreateWaylandSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
+   if (res == VK_SUCCESS)
+   {
+      auto surface_base = util::unique_ptr<wsi::surface>(std::move(wsi_surface));
+      res = instance_data.add_surface(*pSurface, surface_base);
+      if (res != VK_SUCCESS)
+      {
+         instance_data.disp.DestroySurfaceKHR(instance, *pSurface, pAllocator);
+      }
+   }
+   return res;
 }
 
 PFN_vkVoidFunction surface_properties::get_proc_addr(const char *name)
@@ -307,7 +328,17 @@ PFN_vkVoidFunction surface_properties::get_proc_addr(const char *name)
    {
       return reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceWaylandPresentationSupportKHR);
    }
+   else if (strcmp(name, "vkCreateWaylandSurfaceKHR") == 0)
+   {
+      return reinterpret_cast<PFN_vkVoidFunction>(CreateWaylandSurfaceKHR);
+   }
    return nullptr;
 }
+
+bool surface_properties::is_surface_extension_enabled(const layer::instance_private_data &instance_data)
+{
+   return instance_data.is_instance_extension_enabled(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
+}
+
 } // namespace tizen
 } // namespace wsi
index f385030e75625683099c69dd69fdaa3378db4a57..028e94047f6c80255c3b998780e4b190b569f616 100644 (file)
@@ -31,9 +31,13 @@ namespace wsi
 namespace tizen
 {
 
+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,
@@ -47,11 +51,19 @@ public:
    VkResult get_surface_present_rects(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
                                       uint32_t* pRectCount, VkRect2D* pRects) override;
 
-   const util::extension_list &get_required_device_extensions() override;
-
-   bool physical_device_supported(VkPhysicalDevice dev);
+   VkResult get_required_device_extensions(util::extension_list &extension_list) override;
 
    PFN_vkVoidFunction get_proc_addr(const char *name) override;
+
+   bool is_surface_extension_enabled(const layer::instance_private_data &instance_data) 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;
 };
 
 } // namespace tizen
index fcea070e6393e91fa7469d3a3fc7b85d0157831e..55795b1a7d111702d36632c0ab614986b17fe244 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include "swapchain.hpp"
+#include "surface_properties.hpp"
 
 #include <cstring>
 #include <cassert>
 #include <climits>
 #include <drm_fourcc.h>
 
+#include "util/log.hpp"
+#include "util/macros.hpp"
+
+#define MAX_PLANES 4
+
 namespace wsi
 {
 namespace tizen
 {
+
+const VkImageAspectFlagBits plane_flag_bits[MAX_PLANES] = {
+   VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT,
+   VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT,
+   VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT,
+   VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT,
+};
+
 struct swapchain::tizen_image_data
 {
-   int buffer_fd;
-   tbm_surface_h tbm_buffer;
-#ifndef USE_ICD_MALI_NIKEM
-   VkDeviceSize stride; // rowPitch
-   VkDeviceSize offset;
-#endif
-   VkDeviceMemory memory;
+   int buffer_fd[MAX_PLANES];
+   uint32_t stride[MAX_PLANES];
+   uint32_t offset[MAX_PLANES];
+
+   tbm_surface_h buffer;
+   VkDeviceMemory memory[MAX_PLANES];
+
+   uint32_t num_planes;
+
+   sync_fd_fence_sync present_fence;
+   bool is_disjoint;
 };
 
-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_wl_display(wsi_surface.get_wl_display())
+   , m_wl_surface(wsi_surface.get_wl_surface())
+   , m_wsi_surface(&wsi_surface)
    , m_tpl_display(nullptr)
    , m_tpl_surface(nullptr)
+   , m_image_creation_parameters({}, m_allocator, {}, {})
 {
+   m_image_creation_parameters.m_image_create_info.format = VK_FORMAT_UNDEFINED;
 }
 
 swapchain::~swapchain()
 {
-   wsi_info("Release swapchain[%p]", this);
+   WSI_LOG_INFO("Release swapchain[%p]", this);
    teardown();
-   destroy_image();
    if (m_tpl_surface) {
       tpl_surface_destroy_swapchain(m_tpl_surface);
       tpl_object_unreference((tpl_object_t *)m_tpl_surface);
+
+      int refn = tpl_object_get_reference((tpl_object_t *)m_tpl_surface);
    }
    if (m_tpl_display) {
       tpl_object_unreference((tpl_object_t *)m_tpl_display);
@@ -128,39 +153,39 @@ wsi_tizen_get_tbm_format(VkFormat format, VkCompositeAlphaFlagBitsKHR comp)
    return 0;
 }
 
-VkResult swapchain::init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *pSwapchainCreateInfo)
+VkResult swapchain::init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info,
+                                  bool &use_presentation_thread)
 {
-   VkIcdSurfaceWayland *vk_surf = reinterpret_cast<VkIcdSurfaceWayland *>(pSwapchainCreateInfo->surface);
    tbm_format format;
    int tpl_present_mode;
    tpl_result_t res;
 
-   m_tpl_display = tpl_display_get_with_backend_type(TPL_BACKEND_WAYLAND_VULKAN_WSI_THREAD, reinterpret_cast<tpl_handle_t>(vk_surf->display));
+   m_tpl_display = tpl_display_get_with_backend_type(TPL_BACKEND_WAYLAND_VULKAN_WSI_THREAD, reinterpret_cast<tpl_handle_t>(m_wl_display));
    if (m_tpl_display) {
       tpl_object_reference(reinterpret_cast<tpl_object_t *>(m_tpl_display));
    } else {
-      m_tpl_display = tpl_display_create(TPL_BACKEND_WAYLAND_VULKAN_WSI_THREAD, reinterpret_cast<tpl_handle_t>(vk_surf->display));
+      m_tpl_display = tpl_display_create(TPL_BACKEND_WAYLAND_VULKAN_WSI_THREAD, reinterpret_cast<tpl_handle_t>(m_wl_display));
    }
 
    if (!m_tpl_display)
       return VK_ERROR_SURFACE_LOST_KHR;
 
-   m_tpl_surface = tpl_surface_get(m_tpl_display, vk_surf->surface);
-   wsi_info("Get tpl_surface[%p] from tpl_display[%p] for wl_surface[%p]", m_tpl_surface, m_tpl_display, vk_surf->surface);
+   m_tpl_surface = tpl_surface_get(m_tpl_display, m_wl_surface);
+   WSI_LOG_INFO("Get tpl_surface[%p] from tpl_display[%p] for wl_surface[%p]", m_tpl_surface, m_tpl_display, m_wl_surface);
    if (m_tpl_surface == NULL) {
-      format = wsi_tizen_get_tbm_format(pSwapchainCreateInfo->imageFormat, pSwapchainCreateInfo->compositeAlpha);
-      m_tpl_surface = tpl_surface_create(m_tpl_display, vk_surf->surface, TPL_SURFACE_TYPE_WINDOW, format);
+      format = wsi_tizen_get_tbm_format(swapchain_create_info->imageFormat, swapchain_create_info->compositeAlpha);
+      m_tpl_surface = tpl_surface_create(m_tpl_display, m_wl_surface, TPL_SURFACE_TYPE_WINDOW, format);
    } else {
-      wsi_error("tpl_surface[%p] already in use", m_tpl_surface);
+      WSI_LOG_ERROR("tpl_surface[%p] already in use", m_tpl_surface);
       return VK_ERROR_INITIALIZATION_FAILED;
    }
 
    if (m_tpl_surface == NULL) {
-      wsi_error("create tpl surface failed\n");
+      WSI_LOG_ERROR("create tpl surface failed\n");
       return VK_ERROR_INITIALIZATION_FAILED;
    }
 
-   switch(pSwapchainCreateInfo->presentMode) {
+   switch(swapchain_create_info->presentMode) {
       case VK_PRESENT_MODE_IMMEDIATE_KHR:
          tpl_present_mode = TPL_DISPLAY_PRESENT_MODE_IMMEDIATE;
          break;
@@ -174,337 +199,487 @@ VkResult swapchain::init_platform(VkDevice device, const VkSwapchainCreateInfoKH
          tpl_present_mode = TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED;
          break;
       default:
-         wsi_error("unsupported present mode, presentMode[%d].", pSwapchainCreateInfo->presentMode);
+         WSI_LOG_ERROR("unsupported present mode, presentMode[%d].", swapchain_create_info->presentMode);
          return VK_ERROR_INITIALIZATION_FAILED;
    }
 
    res = tpl_surface_create_swapchain(m_tpl_surface, format,
-                                      pSwapchainCreateInfo->imageExtent.width, pSwapchainCreateInfo->imageExtent.height,
-                                      pSwapchainCreateInfo->minImageCount, tpl_present_mode);
-   wsi_info("create swapchain with extent: width[%d], height[%d], image count[%d]",
-            pSwapchainCreateInfo->imageExtent.width, pSwapchainCreateInfo->imageExtent.height,
-            pSwapchainCreateInfo->minImageCount);
-
+                                      swapchain_create_info->imageExtent.width, swapchain_create_info->imageExtent.height,
+                                      swapchain_create_info->minImageCount, tpl_present_mode);
    if (res != TPL_ERROR_NONE) {
-      wsi_error("create swapchain failed, ret[%d].\n", res);
+      WSI_LOG_ERROR("create swapchain failed, ret[%d].\n", res);
       if (res == TPL_ERROR_OUT_OF_MEMORY) {
          return VK_ERROR_OUT_OF_HOST_MEMORY;
       }
       return VK_ERROR_INITIALIZATION_FAILED;
    }
+   WSI_LOG_INFO("create swapchain with extent: width[%d], height[%d], image count[%d]",
+                swapchain_create_info->imageExtent.width, swapchain_create_info->imageExtent.height,
+                swapchain_create_info->minImageCount);
 
-   return VK_SUCCESS;
-}
+   tbm_surface_h *buffers;
+   int tbm_buf_cnt = 0;
 
-VkResult swapchain::allocate_image(const VkImageCreateInfo &image_create_info, tizen_image_data *image_data,
-                                   VkImage *image)
-{
-   VkResult result = VK_SUCCESS;
-
-#ifndef USE_ICD_MALI_NIKEM
-   assert(image_data->stride >= 0);
-   VkSubresourceLayout image_layout = {};
-   image_layout.offset = image_data->offset;
-   image_layout.rowPitch = image_data->stride;
-   VkImageDrmFormatModifierExplicitCreateInfoEXT drm_mod_info = {};
-   drm_mod_info.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT;
-   drm_mod_info.pNext = image_create_info.pNext;
-   drm_mod_info.drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
-   drm_mod_info.drmFormatModifierPlaneCount = 1;
-   drm_mod_info.pPlaneLayouts = &image_layout;
-#endif
-
-   VkExternalMemoryImageCreateInfoKHR external_info = {};
-   external_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR;
-#ifndef USE_ICD_MALI_NIKEM
-   external_info.pNext = &drm_mod_info;
-#else
-   external_info.pNext = image_create_info.pNext;
-#endif
-   external_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
-
-   VkImageCreateInfo image_info = image_create_info;
-   image_info.pNext = &external_info;
-   image_info.tiling = VK_IMAGE_TILING_LINEAR;
-   result = m_device_data.disp.CreateImage(m_device, &image_info, get_allocation_callbacks(), image);
-   if (result != VK_SUCCESS)
-   {
-      wsi_error("Image creation failed.\n");
-      return result;
+   res = tpl_surface_get_swapchain_buffers(m_tpl_surface, NULL, &tbm_buf_cnt);
+   if (res == TPL_ERROR_OUT_OF_MEMORY || tbm_buf_cnt < 2)
+      return VK_ERROR_OUT_OF_HOST_MEMORY;
+   else if (res != TPL_ERROR_NONE)
+      return VK_ERROR_INITIALIZATION_FAILED;
+   WSI_LOG_INFO("Get swapchain buffer numbers [%d], swapchain [%p], tpl_surface [%p]", tbm_buf_cnt, this, m_tpl_surface);
+
+   res = tpl_surface_get_swapchain_buffers(m_tpl_surface, &buffers, &tbm_buf_cnt);
+   if (res != TPL_ERROR_NONE) {
+      WSI_LOG_ERROR("Get TPL swapchain buffers failed, ret[%d], swapchain [%p], tpl_surface [%p]", res, this, m_tpl_surface);
+      if (res == TPL_ERROR_OUT_OF_MEMORY)
+         return VK_ERROR_OUT_OF_HOST_MEMORY;
+      return VK_ERROR_INITIALIZATION_FAILED;
    }
 
-   VkMemoryFdPropertiesKHR mem_props = {};
-   mem_props.sType = VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR;
+   for (int i = 0; i < tbm_buf_cnt; i++) {
+      m_tbm_buffers.insert(std::make_pair(buffers[i], false));
+   }
+
+   // Tizen platform don't need page flip thread to manage buffer
+   use_presentation_thread = false;
 
-   result = m_device_data.disp.GetMemoryFdPropertiesKHR(m_device, VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
-                                                     image_data->buffer_fd, &mem_props);
+   return VK_SUCCESS;
+}
+
+VkResult swapchain::allocate_plane_memory(int fd, VkDeviceMemory *memory)
+{
+   uint32_t mem_index = -1;
+   VkResult result = get_fd_mem_type_index(fd, mem_index);
    if (result != VK_SUCCESS)
    {
-      wsi_error("Error querying Fd properties.\n");
       return result;
    }
 
-   uint32_t mem_idx;
-   for (mem_idx = 0; mem_idx < VK_MAX_MEMORY_TYPES; mem_idx++)
-   {
-      if (mem_props.memoryTypeBits & (1 << mem_idx))
-      {
-         break;
-      }
-   }
-   off_t dma_buf_size = lseek(image_data->buffer_fd, 0, SEEK_END);
+   const off_t dma_buf_size = lseek(fd, 0, SEEK_END);
    if (dma_buf_size < 0)
    {
-      wsi_error("Failed to get DMA Buf size.\n");
+      WSI_LOG_ERROR("Failed to get DMA Buf size.");
       return VK_ERROR_OUT_OF_HOST_MEMORY;
    }
 
    VkImportMemoryFdInfoKHR import_mem_info = {};
    import_mem_info.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR;
    import_mem_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
-   import_mem_info.fd = image_data->buffer_fd;
+   import_mem_info.fd = fd;
 
    VkMemoryAllocateInfo alloc_info = {};
    alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
    alloc_info.pNext = &import_mem_info;
    alloc_info.allocationSize = static_cast<uint64_t>(dma_buf_size);
-   alloc_info.memoryTypeIndex = mem_idx;
+   alloc_info.memoryTypeIndex = mem_index;
 
-   result = m_device_data.disp.AllocateMemory(m_device, &alloc_info, get_allocation_callbacks(), &image_data->memory);
+   result = m_device_data.disp.AllocateMemory(
+      m_device, &alloc_info, get_allocation_callbacks(), memory);
 
    if (result != VK_SUCCESS)
    {
-      wsi_error("Failed to import memory.\n");
+      WSI_LOG_ERROR("Failed to import memory.");
       return result;
    }
-   result = m_device_data.disp.BindImageMemory(m_device, *image, image_data->memory, 0);
 
-   return result;
+   return VK_SUCCESS;
 }
 
-VkResult swapchain::create_image(const VkImageCreateInfo &image_create_info)
+VkResult swapchain::get_fd_mem_type_index(int fd, uint32_t &mem_idx)
 {
-   VkResult result = VK_SUCCESS;
-   tpl_result_t res;
-   tbm_surface_h *buffers;
-   int tbm_buf_cnt = 0, i = 0;
+   VkMemoryFdPropertiesKHR mem_props = {};
+   mem_props.sType = VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR;
 
-   res = tpl_surface_get_swapchain_buffers(m_tpl_surface, NULL, &tbm_buf_cnt);
-   if (res == TPL_ERROR_OUT_OF_MEMORY)
-      return VK_ERROR_OUT_OF_HOST_MEMORY;
-   else if (res != TPL_ERROR_NONE)
-      return VK_ERROR_INITIALIZATION_FAILED;
+   VkResult result = m_device_data.disp.GetMemoryFdPropertiesKHR(
+      m_device, VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, fd, &mem_props);
+   if (result != VK_SUCCESS)
+   {
+      WSI_LOG_ERROR("Error querying Fd properties.");
+      return result;
+   }
+
+   for (mem_idx = 0; mem_idx < VK_MAX_MEMORY_TYPES; mem_idx++)
+   {
+      if (mem_props.memoryTypeBits & (1 << mem_idx))
+      {
+         break;
+      }
+   }
 
-   wsi_info("Get swapchain buffer numbers [%d], swapchain [%p], tpl_surface [%p]", tbm_buf_cnt, this, m_tpl_surface);
+   assert(mem_idx < VK_MAX_MEMORY_TYPES);
 
-   if (tbm_buf_cnt < 2)
+   return VK_SUCCESS;
+}
+
+VkResult swapchain::get_drm_format_properties(
+   VkFormat format, util::vector<VkDrmFormatModifierPropertiesEXT> &format_props_list)
+{
+   VkDrmFormatModifierPropertiesListEXT format_modifier_props = {};
+   format_modifier_props.sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT;
+
+   VkFormatProperties2KHR format_props = {};
+   format_props.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR;
+   format_props.pNext = &format_modifier_props;
+
+   m_device_data.instance_data.disp.GetPhysicalDeviceFormatProperties2KHR(
+      m_device_data.physical_device, format, &format_props);
+
+   if (!format_props_list.try_resize(format_modifier_props.drmFormatModifierCount))
+   {
       return VK_ERROR_OUT_OF_HOST_MEMORY;
+   }
 
-   res = tpl_surface_get_swapchain_buffers(m_tpl_surface, &buffers, &tbm_buf_cnt);
-   if (res != TPL_ERROR_NONE) {
-      wsi_error("Get TPL swapchain buffers failed, ret[%d], swapchain [%p], tpl_surface [%p]", res, this, m_tpl_surface);
-      if (res == TPL_ERROR_OUT_OF_MEMORY)
-         return VK_ERROR_OUT_OF_HOST_MEMORY;
+   format_modifier_props.pDrmFormatModifierProperties = format_props_list.data();
+   m_device_data.instance_data.disp.GetPhysicalDeviceFormatProperties2KHR(
+      m_device_data.physical_device, format, &format_props);
 
-      return VK_ERROR_INITIALIZATION_FAILED;
+   return VK_SUCCESS;
+}
+
+static uint32_t get_same_fd_index(int fd, int const *fds)
+{
+   uint32_t index = 0;
+   while (fd != fds[index])
+   {
+      index++;
    }
 
-   if (!m_swapchain_images.try_resize(tbm_buf_cnt)) {
-      wsi_error("Resize m_swapchain_images failed");
-      return VK_ERROR_OUT_OF_HOST_MEMORY;
+   return index;
+}
+
+VkResult swapchain::create_aliased_image_handle(const VkImageCreateInfo *image_create_info, VkImage *image)
+{
+   return m_device_data.disp.CreateImage(m_device, &m_image_creation_parameters.m_image_create_info,
+                                         get_allocation_callbacks(), image);
+}
+
+static bool get_free_tbm_surface(tbm_surface_h &buffer, std::unordered_map<tbm_surface_h, bool> &buffer_map)
+{
+   buffer = nullptr;
+   for (auto it = buffer_map.begin(); it != buffer_map.end(); it++) {
+      if (!it->second) {
+         buffer = it->first;
+         it->second = true;
+                break;
+      }
    }
 
-   wsi_info("Create swapchain images [%p], swapchain [%p], tpl_surface [%p]", &m_swapchain_images, this, m_tpl_surface);
-   i = 0;
-   for (auto &image: m_swapchain_images) {
-      tizen_image_data *image_data = nullptr;
-      if (get_allocation_callbacks() != nullptr)
-      {
-         image_data = static_cast<tizen_image_data *>(
-            get_allocation_callbacks()->pfnAllocation(get_allocation_callbacks()->pUserData, sizeof(tizen_image_data),
-                                                      alignof(tizen_image_data), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
-      } else {
-         image_data = static_cast<tizen_image_data *>(malloc(sizeof(tizen_image_data)));
+   return buffer == nullptr ? false : true;
+}
+
+VkResult swapchain::allocate_image(VkImageCreateInfo &image_create_info, tizen_image_data *image_data, VkImage *image)
+{
+   image_data->buffer = nullptr;
+   image_data->num_planes = 0;
+   for (uint32_t plane = 0; plane < MAX_PLANES; plane++)
+   {
+      image_data->buffer_fd[plane] = -1;
+      image_data->memory[plane] = VK_NULL_HANDLE;
+   }
+
+   bool is_disjoint = false;
+   auto &m_image_create_info = m_image_creation_parameters.m_image_create_info;
+   if (m_image_create_info.format != VK_FORMAT_UNDEFINED)
+   {
+      is_disjoint = (m_image_create_info.flags & VK_IMAGE_CREATE_DISJOINT_BIT) == VK_IMAGE_CREATE_DISJOINT_BIT;
+      if (!get_free_tbm_surface(image_data->buffer, m_tbm_buffers)) {
+         return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+      }
+
+      tbm_surface_info_s info;
+      tbm_surface_get_info(image_data->buffer, &info);
+      image_data->num_planes = info.num_planes;
+
+      for (uint32_t plane = 0; plane < info.num_planes; plane++) {
+         tbm_bo bo = tbm_surface_internal_get_bo(image_data->buffer, plane);
+         image_data->buffer_fd[plane] = tbm_bo_export_fd(bo);
+         image_data->stride[plane] = info.planes[plane].stride;
+         image_data->offset[plane] = info.planes[plane].offset;
       }
-      if (!image_data) {
-         wsi_error("Allocate image data failed");
-         result = VK_ERROR_OUT_OF_HOST_MEMORY;
-         goto out;
+   } else {
+      if (!get_free_tbm_surface(image_data->buffer, m_tbm_buffers)) {
+         return VK_ERROR_OUT_OF_DEVICE_MEMORY;
       }
 
-      tbm_bo bo = tbm_surface_internal_get_bo(buffers[i], 0);
-      //tbm_bo_handle bo_handle = tbm_bo_get_handle(bo, TBM_DEVICE_3D);
-      image_data->tbm_buffer = buffers[i];
-      image_data->buffer_fd = tbm_bo_export_fd(bo);//bo_handle.u32;
-      image_data->memory = VK_NULL_HANDLE;
-#ifndef USE_ICD_MALI_NIKEM
       tbm_surface_info_s info;
-      tbm_surface_get_info(buffers[i], &info);
-      image_data->stride = static_cast<VkDeviceSize>(info.planes[0].stride);
-      image_data->offset = static_cast<VkDeviceSize>(info.planes[0].offset);
-#endif
+      tbm_surface_get_info(image_data->buffer, &info);
+      image_data->num_planes = info.num_planes;
+
+      for (uint32_t plane = 0; plane < info.num_planes; plane++) {
+         tbm_bo bo = tbm_surface_internal_get_bo(image_data->buffer, plane);
+         image_data->buffer_fd[plane] = tbm_bo_export_fd(bo);
+         image_data->stride[plane] = info.planes[plane].stride;
+         image_data->offset[plane] = info.planes[plane].offset;
+         if (image_data->buffer_fd[plane] != image_data->buffer_fd[0]) {
+            is_disjoint = true;
+         }
+      }
 
-      wsi_info("New image[%d] - tbm_buffer [%p], buffer fd [%d]", i, image_data->tbm_buffer, image_data->buffer_fd);
+         auto &image_layout = m_image_creation_parameters.m_image_layout;
+      if (!image_layout.try_resize(image_data->num_planes))
+      {
+         return VK_ERROR_OUT_OF_HOST_MEMORY;
+      }
 
-      image.data = static_cast<void *>(image_data);
-      image.is_external = false;
+      for (uint32_t plane = 0; plane < image_data->num_planes; plane++)
+      {
+         assert(image_data->stride[plane] >= 0);
+         image_layout[plane].offset = image_data->offset[plane];
+         image_layout[plane].rowPitch = static_cast<uint32_t>(image_data->stride[plane]);
+      }
 
-      result = allocate_image(image_create_info, image_data, &image.image);
-      if (result != VK_SUCCESS)
+      if (is_disjoint)
       {
-         wsi_error("Failed to allocate image, ret [%d].", result);
-         goto out;
+         image_create_info.flags |= VK_IMAGE_CREATE_DISJOINT_BIT;
       }
 
-      /* Initialize presentation fence. */
-      VkFenceCreateInfo fenceInfo = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, nullptr, 0 };
-      result = m_device_data.disp.CreateFence(m_device, &fenceInfo, get_allocation_callbacks(), &image.present_fence);
-      i++;
-   }
+         auto &drm_mod_info = m_image_creation_parameters.m_drm_mod_info;
+      drm_mod_info.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT;
+      drm_mod_info.pNext = image_create_info.pNext;
+      drm_mod_info.drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
+      drm_mod_info.drmFormatModifierPlaneCount = image_data->num_planes;
+      drm_mod_info.pPlaneLayouts = image_layout.data();
 
-   return VK_SUCCESS;
+      auto &external_info = m_image_creation_parameters.m_external_info;
+      external_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR;
+      external_info.pNext = &drm_mod_info;
+      external_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
 
-out:
+      m_image_create_info = image_create_info;
+      m_image_create_info.pNext = &external_info;
+      m_image_create_info.tiling = VK_IMAGE_TILING_LINEAR;
 
-   destroy_image();
+   }
+   image_data->is_disjoint = is_disjoint;
+   VkResult result = m_device_data.disp.CreateImage(m_device, &m_image_create_info, get_allocation_callbacks(), image);
+   if (result != VK_SUCCESS)
+   {
+      WSI_LOG_ERROR("Image creation failed.");
+      return result;
+   }
+   WSI_LOG_INFO("Create image[%p]", (void *)*image);
+
+   if (is_disjoint)
+   {
+      for (uint32_t plane = 0; plane < image_data->num_planes; plane++)
+      {
+         const auto fd_index = get_same_fd_index(image_data->buffer_fd[plane], image_data->buffer_fd);
+         if (fd_index == plane)
+         {
+            VkResult result = allocate_plane_memory(image_data->buffer_fd[plane], &image_data->memory[fd_index]);
+            if (result != VK_SUCCESS)
+            {
+               return result;
+            }
+         }
+      }
+   }
+   else
+   {
+      VkResult result = allocate_plane_memory(image_data->buffer_fd[0], &image_data->memory[0]);
+      if (result != VK_SUCCESS)
+      {
+         return result;
+      }
+   }
 
-   return result;
+   return internal_bind_swapchain_image(m_device, image_data, *image);
 }
 
-VkResult swapchain::acquire_image(uint32_t *image_index)
+VkResult swapchain::create_and_bind_swapchain_image(VkImageCreateInfo image_create_info, swapchain_image &image)
 {
-   tbm_surface_h tbm_buf = tpl_surface_dequeue_buffer_with_sync(m_tpl_surface, UINT64_MAX, NULL);
+   /* Create image_data */
+   auto image_data = m_allocator.create<tizen_image_data>(1);
+   if (image_data == nullptr)
+   {
+      return VK_ERROR_OUT_OF_HOST_MEMORY;
+   }
 
-   if (tbm_buf == NULL) {
-      wsi_error("Dequeue buffer failed, swapchain [%p], tpl_surface [%p]", this, m_tpl_surface);
-      return VK_ERROR_SURFACE_LOST_KHR;
+   std::unique_lock<std::recursive_mutex> image_status_lock(m_image_status_mutex);
+
+   image.data = image_data;
+   image.status = swapchain_image::INVALID;
+   VkResult result = allocate_image(image_create_info, image_data, &image.image);
+
+   image_status_lock.unlock();
+
+   if (result != VK_SUCCESS)
+   {
+      WSI_LOG_ERROR("Failed to allocate image.");
+      destroy_image(image);
+      return result;
    }
 
+   /* Initialize presentation fence. */
+   auto present_fence = sync_fd_fence_sync::create(m_device_data);
+   if (!present_fence.has_value())
+   {
+      destroy_image(image);
+      return VK_ERROR_OUT_OF_HOST_MEMORY;
+   }
+   image_data->present_fence = std::move(present_fence.value());
 
-   for (unsigned int i = 0; i < m_swapchain_images.size(); i++) {
-      tizen_image_data *image_data = reinterpret_cast<tizen_image_data *>(m_swapchain_images[i].data);
-      if (image_data->tbm_buffer == tbm_buf) {
-         *image_index = i;
-         //wsi_error("Acquire image [%d], tbm_buffer [%p], swapchain [%p], tpl_surface [%p]", i, tbm_buf, this, m_tpl_surface);
-         return VK_SUCCESS;
+   for (uint32_t i = 0; i < m_swapchain_images.size(); i++) {
+      if (m_swapchain_images[i].data == image_data) {
+         m_tbm_buffer_idx.insert(std::make_pair(image_data->buffer, i));
+         WSI_LOG_INFO("tbm surface[%p] - idx[%d]", image_data->buffer, i);
       }
    }
 
-   wsi_error("Invalid swapchain buffer [%p], swapchain [%p], tpl_surface [%p]", tbm_buf, this, m_tpl_surface);
-   return VK_ERROR_SURFACE_LOST_KHR;
+   return VK_SUCCESS;
 }
 
-void swapchain::present_image(uint32_t pendingIndex, const VkPresentRegionKHR *region)
+void swapchain::present_image(uint32_t pendingIndex)
 {
    tizen_image_data *image_data = reinterpret_cast<tizen_image_data *>(m_swapchain_images[pendingIndex].data);
+   const VkPresentRegionKHR *region = get_present_regions();
+
    int *rects = NULL;
    int rect_count = 0;
-
    if (region)
    {
-       rect_count = region->rectangleCount;
-       rects = new int[rect_count*4];
-       for (int i = 0; i < rect_count*4; i+=4)
-       {
-           rects[i] = region->pRectangles->offset.x;
-           rects[i+1] = region->pRectangles->offset.y;
-           rects[i+2] = region->pRectangles->extent.width;
-           rects[i+3] = region->pRectangles->extent.height;
-       }
-   }
-
-   tpl_surface_enqueue_buffer_with_damage_and_sync(m_tpl_surface, image_data->tbm_buffer, rect_count, rects, -1);
+      rect_count = region->rectangleCount;
+      rects = new int[rect_count*4];
+      for (int i = 0; i < rect_count*4; i+=4)
+      {
+         rects[i] = region->pRectangles->offset.x;
+         rects[i+1] = region->pRectangles->offset.y;
+         rects[i+2] = region->pRectangles->extent.width;
+         rects[i+3] = region->pRectangles->extent.height;
+      }
+   }
+
+   tpl_surface_enqueue_buffer_with_damage_and_sync(m_tpl_surface, image_data->buffer, rect_count, rects, -1);
+
    if (rects)
        delete rects;
 }
 
-void swapchain::destroy_image(void)
+void swapchain::destroy_image(swapchain_image &image)
 {
-   for (auto &image: m_swapchain_images) {
-      if (image.present_fence != VK_NULL_HANDLE)
-      {
-         m_device_data.disp.DestroyFence(m_device, image.present_fence, get_allocation_callbacks());
-         image.present_fence = VK_NULL_HANDLE;
-      }
-#if 1
-      if (image.image != VK_NULL_HANDLE && !image.is_external)
-#else
-      if (image.image != VK_NULL_HANDLE)
-#endif
-      {
-         m_device_data.disp.DestroyImage(m_device, image.image, get_allocation_callbacks());
-         image.image = VK_NULL_HANDLE;
-      }
-      if (image.data != nullptr)
-      {
-         tizen_image_data *image_data = reinterpret_cast<tizen_image_data *>(image.data);
-         if (image_data->memory != VK_NULL_HANDLE)
-         {
-            m_device_data.disp.FreeMemory(m_device, image_data->memory, get_allocation_callbacks());
-         }
-         if (image_data->buffer_fd >= 0)
-         {
-            close(image_data->buffer_fd);
-         }
-         if (get_allocation_callbacks() != nullptr)
-         {
-            get_allocation_callbacks()->pfnFree(get_allocation_callbacks()->pUserData, image_data);
-         }
-         else
+   std::unique_lock<std::recursive_mutex> image_status_lock(m_image_status_mutex);
+
+   if (image.image != VK_NULL_HANDLE)
+   {
+      m_device_data.disp.DestroyImage(m_device, image.image, get_allocation_callbacks());
+      image.image = VK_NULL_HANDLE;
+   }
+
+   image.status = swapchain_image::INVALID;
+   image_status_lock.unlock();
+
+   if (image.data != nullptr) {
+      auto image_data = reinterpret_cast<tizen_image_data *>(image.data);
+         if (image_data->buffer != nullptr) {
+         for (uint32_t plane = 0; plane < image_data->num_planes; plane++)
          {
-            free(image_data);
+            if (image_data->memory[plane] != VK_NULL_HANDLE)
+            {
+               m_device_data.disp.FreeMemory(m_device, image_data->memory[plane], get_allocation_callbacks());
+            }
+            else if (image_data->buffer_fd[plane] >= 0)
+            {
+               const auto same_fd_index = get_same_fd_index(image_data->buffer_fd[plane], image_data->buffer_fd);
+               if (same_fd_index == plane)
+               {
+                  close(image_data->buffer_fd[plane]);
+               }
+            }
          }
-         image.data = nullptr;
-      }
+         }
+
+         m_tbm_buffers.erase(image_data->buffer);
+         m_tbm_buffer_idx.erase(image_data->buffer);
+
+      m_allocator.destroy(1, image_data);
+      image.data = nullptr;
    }
 }
 
-VkResult swapchain::create_external_image(VkImageCreateInfo* pCreateInfo,
-                                           const VkAllocationCallbacks* pAllocator, VkImage* pImage)
+VkResult swapchain::get_free_buffer(uint64_t *timeout)
 {
-   VkResult result = VK_SUCCESS;
+   tbm_surface_h tbm_buf = tpl_surface_dequeue_buffer_with_sync(m_tpl_surface, *timeout, NULL);
 
-   VkExternalMemoryImageCreateInfoKHR external_info = {};
-   external_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR;
-   external_info.pNext = pCreateInfo->pNext;
-   external_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
-
-   pCreateInfo->pNext = &external_info;
-   pCreateInfo->tiling = VK_IMAGE_TILING_LINEAR;
+   if (tbm_buf == NULL) {
+      WSI_LOG_ERROR("Dequeue buffer failed, swapchain [%p], tpl_surface [%p]", this, m_tpl_surface);
+      return VK_ERROR_SURFACE_LOST_KHR;
+   }
 
-   for (VkBaseOutStructure *s = (VkBaseOutStructure *)(pCreateInfo); s != nullptr; s = s->pNext) {
-      if (((VkBaseOutStructure *)(s->pNext))->sType == VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR) {
-         s->pNext = ((VkBaseOutStructure *)(s->pNext))->pNext;
+   auto it = m_tbm_buffers.find(tbm_buf);
+   if (it != m_tbm_buffers.end() && it->second == true) {
+      auto it_idx = m_tbm_buffer_idx.find(tbm_buf);
+      if (it_idx == m_tbm_buffer_idx.end()) {
+         WSI_LOG_ERROR("Invalid tbm surface[%p], swapchain [%p], tpl_surface [%p]", tbm_buf, this, m_tpl_surface);
+         return VK_ERROR_SURFACE_LOST_KHR;
       }
+      m_swapchain_images[it_idx->second].status = swapchain_image::FREE;
+      return VK_SUCCESS;
    }
 
-   result = m_device_data.disp.CreateImage(m_device, pCreateInfo, get_allocation_callbacks(), pImage);
-   if (result != VK_SUCCESS) {
-      wsi_error("Image creation failed.\n");
-   }
+   WSI_LOG_ERROR("Invalid swapchain buffer [%p], swapchain [%p], tpl_surface [%p]", tbm_buf, this, m_tpl_surface);
+   return VK_ERROR_SURFACE_LOST_KHR;
+}
+
+VkResult swapchain::image_set_present_payload(swapchain_image &image, VkQueue queue, const VkSemaphore *sem_payload,
+                                              uint32_t sem_count)
+{
+/*
+   auto image_data = reinterpret_cast<tizen_image_data *>(image.data);
+   return image_data->present_fence.set_payload(queue, sem_payload, sem_count);
+*/
+   return VK_SUCCESS;
+}
 
-   return result;
+VkResult swapchain::image_wait_present(swapchain_image &, uint64_t)
+{
+   /* With explicit sync in use there is no need to wait for the present sync before submiting the image to the
+    * compositor. */
+   return VK_SUCCESS;
 }
 
-VkResult swapchain::bind_external_image(const uint32_t image_index, VkImage image)
+VkResult swapchain::internal_bind_swapchain_image(VkDevice &device, tizen_image_data *image_data,
+                                                  const VkImage &image)
 {
-   VkResult result = VK_SUCCESS;
-   tizen_image_data *image_data = reinterpret_cast<tizen_image_data *>(m_swapchain_images[image_index].data);
+   auto &device_data = layer::device_private_data::get(device);
+   if (image_data->is_disjoint)
+   {
+      util::vector<VkBindImageMemoryInfo> bind_img_mem_infos(m_allocator);
+      if (!bind_img_mem_infos.try_resize(image_data->num_planes))
+      {
+         return VK_ERROR_OUT_OF_HOST_MEMORY;
+      }
+
+      util::vector<VkBindImagePlaneMemoryInfo> bind_plane_mem_infos(m_allocator);
+      if (!bind_plane_mem_infos.try_resize(image_data->num_planes))
+      {
+         return VK_ERROR_OUT_OF_HOST_MEMORY;
+      }
 
-   assert(image_data != nullptr);
-   assert(image_data->memory != VK_NULL_HANDLE);
+      for (uint32_t plane = 0; plane < image_data->num_planes; plane++)
+      {
 
-   if (m_swapchain_images[image_index].image != VK_NULL_HANDLE)
-      m_device_data.disp.DestroyImage(m_device, m_swapchain_images[image_index].image, get_allocation_callbacks());
+         bind_plane_mem_infos[plane].planeAspect = plane_flag_bits[plane];
+         bind_plane_mem_infos[plane].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO;
+         bind_plane_mem_infos[plane].pNext = NULL;
 
-   m_swapchain_images[image_index].image = image;
+         bind_img_mem_infos[plane].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
+         bind_img_mem_infos[plane].pNext = &bind_plane_mem_infos[plane];
+         bind_img_mem_infos[plane].image = image;
+         bind_img_mem_infos[plane].memory = image_data->memory[plane];
+         bind_img_mem_infos[plane].memoryOffset = image_data->offset[plane];
+      }
 
-   result = m_device_data.disp.BindImageMemory(m_device, image, image_data->memory, 0);
-   if (result == VK_SUCCESS) {
-      m_swapchain_images[image_index].is_external = true;
+      return device_data.disp.BindImageMemory2KHR(device, bind_img_mem_infos.size(), bind_img_mem_infos.data());
    }
 
-   return result;
+   return device_data.disp.BindImageMemory(device, image, image_data->memory[0], image_data->offset[0]);
+}
+
+VkResult swapchain::bind_swapchain_image(VkDevice &device, const VkBindImageMemoryInfo *bind_image_mem_info,
+                                         const VkBindImageMemorySwapchainInfoKHR *bind_sc_info)
+{
+   const wsi::swapchain_image &swapchain_image = m_swapchain_images[bind_sc_info->imageIndex];
+   auto image_data = reinterpret_cast<tizen_image_data *>(swapchain_image.data);
+   return internal_bind_swapchain_image(device, image_data, bind_image_mem_info->image);
 }
 
 } // namespace wayland
index 63c6788b28c52689eea9e62d8d56fd1b6ddb9fb8..a9f28368cd8f5a6b6624f6ea181c6f95ce8bf7d1 100644 (file)
@@ -24,7 +24,7 @@
 
 #pragma once
 
-#include "wsi/swapchain_base_tizen.hpp"
+#include "wsi/swapchain_base.hpp"
 
 extern "C" {
 #include <vulkan/vk_icd.h>
@@ -34,62 +34,210 @@ extern "C" {
 #include <tbm_surface_internal.h>
 }
 
+#include "util/custom_allocator.hpp"
+#include "surface.hpp"
+
+#include <unordered_map>
+
 namespace wsi
 {
 namespace tizen
 {
 
+struct image_creation_parameters
+{
+   VkImageCreateInfo m_image_create_info;
+   util::vector<VkSubresourceLayout> m_image_layout;
+   VkExternalMemoryImageCreateInfoKHR m_external_info;
+   VkImageDrmFormatModifierExplicitCreateInfoEXT m_drm_mod_info;
+
+   image_creation_parameters(VkImageCreateInfo image_create_info, util::allocator allocator,
+                                   VkExternalMemoryImageCreateInfoKHR external_info,
+                                   VkImageDrmFormatModifierExplicitCreateInfoEXT drm_mod_info)
+      : m_image_create_info(image_create_info)
+      , m_image_layout(allocator)
+      , m_external_info(external_info)
+      , m_drm_mod_info(drm_mod_info)
+   {
+   }
+};
+
 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();
 
+   /**
+    * @brief Creates a VkImage handle.
+    *
+    * @param      image_create_info Data to be used to create the image.
+    * @param[out] image             Handle to the image.
+    *
+    * @return If image creation is successful returns VK_SUCCESS, otherwise
+    * will return VK_ERROR_OUT_OF_DEVICE_MEMORY or VK_ERROR_OUT_OF_HOST_MEMORY
+    * depending on the error that occured.
+    */
+   VkResult create_aliased_image_handle(const VkImageCreateInfo *image_create_info, VkImage *image) override;
+
+   /**
+    * @brief Bind image to a swapchain
+    *
+    * @param device              is the logical device that owns the images and memory.
+    * @param bind_image_mem_info details the image we want to bind.
+    * @param bind_sc_info        describes the swapchain memory to bind to.
+    *
+    * @return VK_SUCCESS on success, otherwise on failure VK_ERROR_OUT_OF_HOST_MEMORY or VK_ERROR_OUT_OF_DEVICE_MEMORY
+    * can be returned.
+    */
+   VkResult bind_swapchain_image(VkDevice &device, const VkBindImageMemoryInfo *bind_image_mem_info,
+                                         const VkBindImageMemorySwapchainInfoKHR *bind_sc_info) override;
 protected:
    /**
-    * @brief Initialize platform specifics.
+    * @brief Platform specific initialization
+    *
+    * @param      device                  VkDevice object.
+    * @param      swapchain_create_info   Pointer to the swapchain create info struct.
+    * @param[out] use_presentation_thread Flag indicating if image presentation
+    *                                     must happen in a separate thread.
+    *
+    * @return VK_SUCCESS on success or an error code otherwise.
     */
-   VkResult init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *pSwapchainCreateInfo) override;
+   VkResult init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info,
+                                  bool &use_presentation_thread) override;
 
    /**
-    * @brief Creates swapchain images.
+    * @brief Creates and binds a new swapchain image.
     *
     * @param image_create_info Data to be used to create the image.
+    * @param image             Handle to the image.
     *
     * @return If image creation is successful returns VK_SUCCESS, otherwise
     * will return VK_ERROR_OUT_OF_DEVICE_MEMORY or VK_ERROR_INITIALIZATION_FAILED
-    * depending on the error that occurred.
+    * depending on the error that occured.
     */
-   VkResult create_image(const VkImageCreateInfo &image_create_info) override;
-
-   VkResult acquire_image(uint32_t *image_index) override;
+   virtual VkResult create_and_bind_swapchain_image(VkImageCreateInfo image_create_info, swapchain_image &image) override;
 
    /**
-    * @brief Method to present an image
+    * @brief Method to present and image
+    *
+    * @param pending_index Index of the pending image to be presented.
     *
-    * @param pendingIndex Index of the pending image to be presented.
     */
-   void present_image(uint32_t pendingIndex, const VkPresentRegionKHR *region) override;
+   void present_image(uint32_t pending_index) override;
 
    /**
     * @brief Method to release a swapchain image
     *
     * @param image Handle to the image about to be released.
     */
-   void destroy_image(void) override;
+   void destroy_image(swapchain_image &image) override;
+
+   /**
+    * @brief Hook for any actions to free up a buffer for acquire
+    *
+    * @param[in,out] timeout time to wait, in nanoseconds. 0 doesn't block,
+    *                        UINT64_MAX waits indefinately. The timeout should
+    *                        be updated if a sleep is required - this can
+    *                        be set to 0 if the semaphore is now not expected
+    *                        block.
+    */
+   VkResult get_free_buffer(uint64_t *timeout) override;
+
+   /**
+    * @brief Sets the present payload for a swapchain image.
+    *
+    * @param[in] image       The swapchain image for which to set a present payload.
+    * @param     queue       A Vulkan queue that can be used for any Vulkan commands needed.
+    * @param[in] sem_payload Array of Vulkan semaphores that constitute the payload.
+    * @param     sem_count   Number of elements in @p sem_payload
+    *
+    * @return VK_SUCCESS on success or an error code otherwise.
+    */
+   VkResult image_set_present_payload(swapchain_image &image, VkQueue queue, const VkSemaphore *sem_payload,
+                                              uint32_t sem_count) override;
 
-   virtual VkResult create_external_image(VkImageCreateInfo* pCreateInfo,
-                                           const VkAllocationCallbacks* pAllocator, VkImage* pImage) override;
-   virtual VkResult bind_external_image(const uint32_t image_index, VkImage image) override;
+   /**
+    * @brief Waits for the present payload of an image if necessary.
+    *
+    * If the page flip thread needs to wait for the image present synchronization payload the WSI implemention can block
+    * and wait in this call. Otherwise the function should return successfully without blocking.
+    *
+    * @param[in] image   The swapchain image for which the function may need to wait until the presentat payload has
+    *                    finished.
+    * @param     timeout Timeout for any wait in nanoseconds.
+    *
+    * @return VK_SUCCESS if waiting was successful or unnecessary. An error code otherwise.
+    */
+   VkResult image_wait_present(swapchain_image &image, uint64_t timeout) override;
 
 private:
    struct tizen_image_data;
-   VkResult allocate_image(const VkImageCreateInfo &image_create_info, tizen_image_data *image_data, VkImage *image);
+   VkResult allocate_image(VkImageCreateInfo &image_create_info, tizen_image_data *image_data, VkImage *image);
+   VkResult internal_bind_swapchain_image(VkDevice &device, tizen_image_data *swapchain_image,
+                                          const VkImage &image);
+
+   struct wl_display *m_wl_display;
+   struct wl_surface *m_wl_surface;
+   /** Raw pointer to the WSI Surface that this swapchain was created from. The Vulkan specification ensures that the
+    * surface is valid until swapchain is destroyed. */
+   surface *m_wsi_surface;
 
    tpl_display_t *m_tpl_display;
    tpl_surface_t *m_tpl_surface;
 
+   std::unordered_map<tbm_surface_h, bool> m_tbm_buffers;
+   std::unordered_map<tbm_surface_h, int> m_tbm_buffer_idx;
+
+   //std::vector<tbm_surface_h> m_tbm_buffers;
+
+   /**
+    * @brief Image creation parameters used for all swapchain images.
+    */
+   struct image_creation_parameters m_image_creation_parameters;
+
+   /*
+    * @brief Allocate memory for an image plane.
+    *
+    * Allocates a VkDeviceMemory object from a given fd for an image plane. First
+    * it makes a call to get_fd_mem_type_index() to acquire the memory type for
+    * the given fd and then it allocates device memory by calling vkAllocateMemory().
+    *
+    * @param      fd     The plane's fd.
+    * @param[out] memory The allocated VkDeviceMemory object.
+    *
+    * @return VK_SUCCESS on success. If one of the functions that are being called
+    * fails its return value is returned. VK_ERROR_OUT_OF_HOST_MEMORY is returned
+    * when the host gets out of memory.
+    */
+   VkResult allocate_plane_memory(int fd, VkDeviceMemory *memory);
+
+   /*
+    * @brief Get the memory type which the specified file descriptor can be
+    * imported as.
+    *
+    * @param      fd      The given fd.
+    * @param[out] mem_idx The index of the supported memory type.
+    *
+    * @return VK_SUCCESS on success. On failure the error value of
+    * vkGetMemoryFdPropertiesKHR is returned.
+    */
+   VkResult get_fd_mem_type_index(int fd, uint32_t &mem_idx);
+
+   /*
+    * @brief Get the properties a format has when combined with a DRM modifier.
+    *
+    * @param      format            The target format.
+    * @param[out] format_props_list A vector which will store the supported properties
+    *                               for every modifier.
+    *
+    * @return VK_SUCCESS on success. VK_ERROR_OUT_OF_HOST_MEMORY is returned when
+    * the host gets out of memory.
+    */
+   VkResult get_drm_format_properties(
+      VkFormat format, util::vector<VkDrmFormatModifierPropertiesEXT> &format_props_list);
 };
 } // namespace wayland
 } // namespace wsi
index b23998a22197e6c6c979042b740faecaa68d65a7..7957a96bdf4af235d02b2fc280bf54b7ab5837a9 100644 (file)
@@ -136,7 +136,6 @@ util::wsi_platform_set find_enabled_layer_platforms(const VkInstanceCreateInfo *
 VkResult add_extensions_required_by_layer(VkPhysicalDevice phys_dev, const util::wsi_platform_set enabled_platforms,
                                           util::extension_list &extensions_to_enable)
 {
-#if 0
    util::allocator allocator{extensions_to_enable.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND};
    util::extension_list device_extensions{allocator};
 
@@ -165,9 +164,7 @@ VkResult add_extensions_required_by_layer(VkPhysicalDevice phys_dev, const util:
    {
       return res;
    }
-#else
-   VkResult res;
-#endif
+
    for (const auto &wsi_ext : supported_wsi_extensions)
    {
       /* Skip iterating over platforms not enabled in the instance. */
@@ -188,18 +185,6 @@ VkResult add_extensions_required_by_layer(VkPhysicalDevice phys_dev, const util:
       {
          return res;
       }
-#if 0
-      bool supported = device_extensions.contains(extensions_required_by_layer);
-      if (!supported)
-      {
-         /* Can we accept failure? The layer unconditionally advertises support for this platform and the loader uses
-          * this information to enable its own support of the vkCreate*SurfaceKHR entrypoints. The rest of the Vulkan
-          * stack may not support this extension so we cannot blindly fall back to it.
-          * For now treat this as an error.
-          */
-         return VK_ERROR_INITIALIZATION_FAILED;
-      }
-#endif
 
       res = extensions_to_enable.add(extensions_required_by_layer);
       if (res != VK_SUCCESS)
@@ -210,6 +195,7 @@ VkResult add_extensions_required_by_layer(VkPhysicalDevice phys_dev, const util:
    return VK_SUCCESS;
 }
 
+
 void remove_extensions_supported_by_layer(util::extension_list &extensions_to_enable)
 {
    for (const auto &wsi_ext : supported_wsi_extensions)
index a643f978b80c75a95023954b2a5994e0d5e89414..e858c9196c57b1e19634ee1fa91c5cbd1d77ee04 100644 (file)
 
 #pragma once
 
-#if BUILD_WSI_TIZEN
-#include "swapchain_base_tizen.hpp"
-#else
 #include "swapchain_base.hpp"
-#endif
 #include "surface_properties.hpp"
 #include "util/platform_set.hpp"