summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTianhao Ni <tianhao.ni@samsung.com>2022-01-21 09:12:49 +0800
committerTianhao Ni <tianhao.ni@samsung.com>2022-01-25 10:56:13 +0800
commitb76a840231d266e500adac8ab70ac0e706639f96 (patch)
treeece7f81d249e25d33da31bb578dace020d1e526a
parent4cc42e6d28cbb094995f35392bc97f65630e382e (diff)
downloadvulkan-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.txt9
-rw-r--r--layer/VkLayer_window_system_integration.json5
-rw-r--r--layer/layer.cpp63
-rw-r--r--layer/surface_api.cpp36
-rw-r--r--layer/surface_api.hpp20
-rw-r--r--layer/swapchain_api.cpp28
-rw-r--r--util/log.cpp104
-rw-r--r--util/log.hpp43
-rw-r--r--util/log_util.hpp8
-rw-r--r--wsi/swapchain_base.cpp15
-rw-r--r--wsi/swapchain_base.hpp14
-rw-r--r--wsi/swapchain_base_tizen.cpp236
-rw-r--r--wsi/swapchain_base_tizen.hpp247
-rw-r--r--wsi/tizen/surface.cpp65
-rw-r--r--wsi/tizen/surface.hpp69
-rw-r--r--wsi/tizen/surface_properties.cpp75
-rw-r--r--wsi/tizen/surface_properties.hpp18
-rw-r--r--wsi/tizen/swapchain.cpp657
-rw-r--r--wsi/tizen/swapchain.hpp182
-rw-r--r--wsi/wsi_factory.cpp18
-rw-r--r--wsi/wsi_factory.hpp4
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 = &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
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 &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
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"