diff options
author | Tianhao Ni <tianhao.ni@samsung.com> | 2022-01-21 09:12:49 +0800 |
---|---|---|
committer | Tianhao Ni <tianhao.ni@samsung.com> | 2022-01-25 10:56:13 +0800 |
commit | b76a840231d266e500adac8ab70ac0e706639f96 (patch) | |
tree | ece7f81d249e25d33da31bb578dace020d1e526a | |
parent | 4cc42e6d28cbb094995f35392bc97f65630e382e (diff) | |
download | vulkan-wsi-layer-b76a840231d266e500adac8ab70ac0e706639f96.tar.gz vulkan-wsi-layer-b76a840231d266e500adac8ab70ac0e706639f96.tar.bz2 vulkan-wsi-layer-b76a840231d266e500adac8ab70ac0e706639f96.zip |
Upgrade WSI Layer
Change-Id: I6eb06fb17aa1d35d9eea661f9f128261ca3ae6ba
Signed-off-by: Tianhao Ni <tianhao.ni@samsung.com>
-rw-r--r-- | CMakeLists.txt | 9 | ||||
-rw-r--r-- | layer/VkLayer_window_system_integration.json | 5 | ||||
-rw-r--r-- | layer/layer.cpp | 63 | ||||
-rw-r--r-- | layer/surface_api.cpp | 36 | ||||
-rw-r--r-- | layer/surface_api.hpp | 20 | ||||
-rw-r--r-- | layer/swapchain_api.cpp | 28 | ||||
-rw-r--r-- | util/log.cpp | 104 | ||||
-rw-r--r-- | util/log.hpp | 43 | ||||
-rw-r--r-- | util/log_util.hpp | 8 | ||||
-rw-r--r-- | wsi/swapchain_base.cpp | 15 | ||||
-rw-r--r-- | wsi/swapchain_base.hpp | 14 | ||||
-rw-r--r-- | wsi/swapchain_base_tizen.cpp | 236 | ||||
-rw-r--r-- | wsi/swapchain_base_tizen.hpp | 247 | ||||
-rw-r--r-- | wsi/tizen/surface.cpp | 65 | ||||
-rw-r--r-- | wsi/tizen/surface.hpp | 69 | ||||
-rw-r--r-- | wsi/tizen/surface_properties.cpp | 75 | ||||
-rw-r--r-- | wsi/tizen/surface_properties.hpp | 18 | ||||
-rw-r--r-- | wsi/tizen/swapchain.cpp | 657 | ||||
-rw-r--r-- | wsi/tizen/swapchain.hpp | 182 | ||||
-rw-r--r-- | wsi/wsi_factory.cpp | 18 | ||||
-rw-r--r-- | wsi/wsi_factory.hpp | 4 |
21 files changed, 867 insertions, 1049 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b04161..9e403f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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}) diff --git a/layer/VkLayer_window_system_integration.json b/layer/VkLayer_window_system_integration.json index b63be97..3cf22d4 100644 --- a/layer/VkLayer_window_system_integration.json +++ b/layer/VkLayer_window_system_integration.json @@ -31,11 +31,14 @@ "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" } diff --git a/layer/layer.cpp b/layer/layer.cpp index 14923a3..986436a 100644 --- a/layer/layer.cpp +++ b/layer/layer.cpp @@ -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); diff --git a/layer/surface_api.cpp b/layer/surface_api.cpp index 7a4f858..fc681aa 100644 --- a/layer/surface_api.cpp +++ b/layer/surface_api.cpp @@ -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); } @@ -167,31 +167,15 @@ wsi_layer_vkGetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice, } 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; diff --git a/layer/surface_api.hpp b/layer/surface_api.hpp index 8bda47a..2e51904 100644 --- a/layer/surface_api.hpp +++ b/layer/surface_api.hpp @@ -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; -} diff --git a/layer/swapchain_api.cpp b/layer/swapchain_api.cpp index 906f6df..dcb0b55 100644 --- a/layer/swapchain_api.cpp +++ b/layer/swapchain_api.cpp @@ -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 = ®ions->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 index 5e29217..0000000 --- a/util/log.cpp +++ /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 */ diff --git a/util/log.hpp b/util/log.hpp index 2bd71de..f6c60d3 100644 --- a/util/log.hpp +++ b/util/log.hpp @@ -23,45 +23,20 @@ */ #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 index 4789199..0000000 --- a/util/log_util.hpp +++ /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) - diff --git a/wsi/swapchain_base.cpp b/wsi/swapchain_base.cpp index ab24f0b..6c8cd30 100644 --- a/wsi/swapchain_base.cpp +++ b/wsi/swapchain_base.cpp @@ -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; diff --git a/wsi/swapchain_base.hpp b/wsi/swapchain_base.hpp index c8d5573..485cca0 100644 --- a/wsi/swapchain_base.hpp +++ b/wsi/swapchain_base.hpp @@ -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 index c64d6e5..0000000 --- a/wsi/swapchain_base_tizen.cpp +++ /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 index c98d10e..0000000 --- a/wsi/swapchain_base_tizen.hpp +++ /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 index 0000000..8d2b4e5 --- /dev/null +++ b/wsi/tizen/surface.cpp @@ -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 ¶ms) + : 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 index 0000000..7280ad9 --- /dev/null +++ b/wsi/tizen/surface.hpp @@ -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; + +}; +} +} diff --git a/wsi/tizen/surface_properties.cpp b/wsi/tizen/surface_properties.cpp index ea89d6e..0dd0530 100644 --- a/wsi/tizen/surface_properties.cpp +++ b/wsi/tizen/surface_properties.cpp @@ -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 diff --git a/wsi/tizen/surface_properties.hpp b/wsi/tizen/surface_properties.hpp index f385030..028e940 100644 --- a/wsi/tizen/surface_properties.hpp +++ b/wsi/tizen/surface_properties.hpp @@ -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 diff --git a/wsi/tizen/swapchain.cpp b/wsi/tizen/swapchain.cpp index fcea070..55795b1 100644 --- a/wsi/tizen/swapchain.cpp +++ b/wsi/tizen/swapchain.cpp @@ -23,6 +23,7 @@ */ #include "swapchain.hpp" +#include "surface_properties.hpp" #include <cstring> #include <cassert> @@ -33,36 +34,60 @@ #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 diff --git a/wsi/tizen/swapchain.hpp b/wsi/tizen/swapchain.hpp index 63c6788..a9f2836 100644 --- a/wsi/tizen/swapchain.hpp +++ b/wsi/tizen/swapchain.hpp @@ -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 diff --git a/wsi/wsi_factory.cpp b/wsi/wsi_factory.cpp index b23998a..7957a96 100644 --- a/wsi/wsi_factory.cpp +++ b/wsi/wsi_factory.cpp @@ -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) diff --git a/wsi/wsi_factory.hpp b/wsi/wsi_factory.hpp index a643f97..e858c91 100644 --- a/wsi/wsi_factory.hpp +++ b/wsi/wsi_factory.hpp @@ -29,11 +29,7 @@ #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" |