mirror of
https://gitlab.freedesktop.org/mesa/vulkan-wsi-layer.git
synced 2026-05-09 06:08:03 +02:00
VK_KHR_display swapchain implementation
Implementation of VK_KHR_display swapchain class. VK_KHR_display is another WSI backend that provides surfaces to render directly to a display. The swapchain class is responsible for creating and managing a swapchain based on the specific type of surface provided by VK_KHR_display. Change-Id: I9b103c20c3444b1ca75f3df7edf6b66fc87a0992 Signed-off-by: Dennis Wildmark <dennis.wildmark@arm.com>
This commit is contained in:
parent
46c770bea6
commit
23cd21c99c
9 changed files with 915 additions and 14 deletions
|
|
@ -61,17 +61,13 @@ option(BUILD_WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN "Build with support for VK_
|
|||
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")
|
||||
|
||||
if(BUILD_WSI_WAYLAND)
|
||||
if(BUILD_WSI_WAYLAND OR BUILD_WSI_DISPLAY)
|
||||
set(BUILD_DRM_UTILS true)
|
||||
if(SELECT_EXTERNAL_ALLOCATOR STREQUAL "none")
|
||||
message(FATAL_ERROR "Wayland only supported with an external allocator.")
|
||||
message(FATAL_ERROR "WSI only supported with an external allocator.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(BUILD_WSI_DISPLAY)
|
||||
set(BUILD_DRM_UTILS true)
|
||||
endif()
|
||||
|
||||
if(BUILD_DRM_UTILS)
|
||||
add_library(drm_utils STATIC util/drm/drm_utils.cpp)
|
||||
|
||||
|
|
@ -191,7 +187,9 @@ endif()
|
|||
if (BUILD_WSI_DISPLAY)
|
||||
add_library(wsi_display STATIC
|
||||
wsi/display/drm_display.cpp
|
||||
wsi/display/surface_properties.cpp)
|
||||
wsi/display/surface_properties.cpp
|
||||
wsi/display/swapchain.cpp
|
||||
wsi/display/surface.cpp)
|
||||
|
||||
pkg_check_modules(LIBDRM REQUIRED libdrm)
|
||||
message(STATUS "Using libdrm include directories: ${LIBDRM_INCLUDE_DIRS}")
|
||||
|
|
@ -208,6 +206,11 @@ if (BUILD_WSI_DISPLAY)
|
|||
target_compile_options(wsi_display INTERFACE "-DBUILD_WSI_DISPLAY=1")
|
||||
target_link_libraries(wsi_display ${LIBDRM_LDFLAGS} drm)
|
||||
target_link_libraries(wsi_display drm_utils)
|
||||
if(NOT EXTERNAL_WSIALLOC_LIBRARY STREQUAL "")
|
||||
target_link_libraries(wsi_display ${EXTERNAL_WSIALLOC_LIBRARY})
|
||||
else()
|
||||
target_link_libraries(wsi_display wsialloc)
|
||||
endif()
|
||||
list(APPEND LINK_WSI_LIBS wsi_display)
|
||||
else()
|
||||
list(APPEND JSON_COMMANDS COMMAND sed -i '/VK_KHR_display/d' ${CMAKE_CURRENT_BINARY_DIR}/VkLayer_window_system_integration.json)
|
||||
|
|
|
|||
|
|
@ -222,6 +222,8 @@ static constexpr uint32_t API_VERSION_MAX = UINT32_MAX;
|
|||
EP(CreateHeadlessSurfaceEXT, VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME, API_VERSION_MAX, false) \
|
||||
/* VK_KHR_wayland_surface */ \
|
||||
EP(CreateWaylandSurfaceKHR, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, API_VERSION_MAX, false) \
|
||||
/* VK_KHR_display */ \
|
||||
EP(CreateDisplayPlaneSurfaceKHR, VK_KHR_DISPLAY_EXTENSION_NAME, API_VERSION_MAX, false) \
|
||||
/* VK_KHR_get_surface_capabilities2 */ \
|
||||
EP(GetPhysicalDeviceSurfaceCapabilities2KHR, VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, API_VERSION_MAX, \
|
||||
false) \
|
||||
|
|
|
|||
|
|
@ -61,6 +61,44 @@ using drm_plane_resources_owner = drm_owner<_drmModePlaneRes, drmModeFreePlaneRe
|
|||
using drm_object_properties_owner = drm_owner<_drmModeObjectProperties, drmModeFreeObjectProperties>;
|
||||
using drm_property_owner = drm_owner<_drmModeProperty, drmModeFreeProperty>;
|
||||
|
||||
/**
|
||||
* @brief Owner class for an array of DRM GEM buffer handles.
|
||||
*/
|
||||
template <size_t array_size>
|
||||
class drm_gem_handle_array : private util::noncopyable
|
||||
{
|
||||
public:
|
||||
drm_gem_handle_array(int fd)
|
||||
: m_fd(fd)
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t &operator[](size_t size)
|
||||
{
|
||||
return m_handle[size];
|
||||
}
|
||||
|
||||
uint32_t *data()
|
||||
{
|
||||
return m_handle.data();
|
||||
}
|
||||
|
||||
~drm_gem_handle_array()
|
||||
{
|
||||
for (auto handle : m_handle)
|
||||
{
|
||||
if (handle != UINT32_MAX && m_fd != -1)
|
||||
{
|
||||
drmCloseBufferHandle(m_fd, handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
int m_fd{ -1 };
|
||||
std::array<uint32_t, array_size> m_handle{ UINT32_MAX };
|
||||
};
|
||||
|
||||
/* Forward declaration */
|
||||
class drm_display;
|
||||
|
||||
|
|
|
|||
72
wsi/display/surface.cpp
Normal file
72
wsi/display/surface.cpp
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* @brief Implementation of a headless WSI Surface
|
||||
*/
|
||||
|
||||
#include "surface.hpp"
|
||||
#include "swapchain.hpp"
|
||||
#include "surface_properties.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
namespace display
|
||||
{
|
||||
|
||||
surface::surface(drm_display_mode *display_mode)
|
||||
: m_display_mode(display_mode)
|
||||
, m_surface_properties(*this)
|
||||
{
|
||||
}
|
||||
|
||||
wsi::surface_properties &surface::get_properties()
|
||||
{
|
||||
return m_surface_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));
|
||||
}
|
||||
|
||||
VkExtent2D surface::get_current_extent() const
|
||||
{
|
||||
return m_current_extent;
|
||||
}
|
||||
|
||||
void surface::set_current_extent(VkExtent2D extent)
|
||||
{
|
||||
m_current_extent = extent;
|
||||
}
|
||||
|
||||
drm_display_mode *surface::get_display_mode()
|
||||
{
|
||||
return m_display_mode;
|
||||
}
|
||||
|
||||
} /* namespace display */
|
||||
} /* namespace wsi */
|
||||
59
wsi/display/surface.hpp
Normal file
59
wsi/display/surface.hpp
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* @brief Definitions for a headless WSI Surface
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "wsi/surface.hpp"
|
||||
#include "surface_properties.hpp"
|
||||
#include "drm_display.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
namespace display
|
||||
{
|
||||
|
||||
class surface : public wsi::surface
|
||||
{
|
||||
public:
|
||||
surface(drm_display_mode *mode);
|
||||
wsi::surface_properties &get_properties() override;
|
||||
util::unique_ptr<swapchain_base> allocate_swapchain(layer::device_private_data &dev_data,
|
||||
const VkAllocationCallbacks *allocator) override;
|
||||
|
||||
VkExtent2D get_current_extent() const;
|
||||
void set_current_extent(VkExtent2D extent);
|
||||
drm_display_mode *get_display_mode();
|
||||
|
||||
private:
|
||||
drm_display_mode *m_display_mode;
|
||||
VkExtent2D m_current_extent;
|
||||
surface_properties m_surface_properties;
|
||||
};
|
||||
|
||||
} /* namespace display */
|
||||
} /* namespace wsi */
|
||||
|
|
@ -26,6 +26,7 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include "surface_properties.hpp"
|
||||
#include "surface.hpp"
|
||||
#include "util/macros.hpp"
|
||||
|
||||
namespace wsi
|
||||
|
|
@ -36,11 +37,28 @@ namespace display
|
|||
|
||||
constexpr int max_core_1_0_formats = VK_FORMAT_ASTC_12x12_SRGB_BLOCK + 1;
|
||||
|
||||
surface_properties::surface_properties()
|
||||
: m_specific_surface(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
surface_properties::surface_properties(surface &wsi_surface)
|
||||
: m_specific_surface(&wsi_surface)
|
||||
{
|
||||
}
|
||||
|
||||
VkResult surface_properties::get_surface_capabilities(VkPhysicalDevice physical_device,
|
||||
VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
|
||||
{
|
||||
get_surface_capabilities_common(physical_device, pSurfaceCapabilities);
|
||||
|
||||
if (m_specific_surface != nullptr)
|
||||
{
|
||||
pSurfaceCapabilities->currentExtent = m_specific_surface->get_current_extent();
|
||||
pSurfaceCapabilities->minImageExtent = m_specific_surface->get_current_extent();
|
||||
pSurfaceCapabilities->maxImageExtent = m_specific_surface->get_current_extent();
|
||||
}
|
||||
|
||||
/* Image count limits */
|
||||
pSurfaceCapabilities->minImageCount = 2;
|
||||
pSurfaceCapabilities->maxImageCount = 3;
|
||||
|
|
@ -240,13 +258,30 @@ VWL_VKAPI_CALL(VkResult)
|
|||
CreateDisplayPlaneSurfaceKHR(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface)
|
||||
{
|
||||
UNUSED(instance);
|
||||
UNUSED(pCreateInfo);
|
||||
UNUSED(pAllocator);
|
||||
UNUSED(pSurface);
|
||||
// TODO: Create the surface object here, which in turn creates the surface_properties object
|
||||
auto &instance_data = layer::instance_private_data::get(instance);
|
||||
util::allocator allocator{ instance_data.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT, pAllocator };
|
||||
|
||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||
drm_display_mode *display_mode = reinterpret_cast<drm_display_mode *>(pCreateInfo->displayMode);
|
||||
|
||||
auto wsi_surface = allocator.make_unique<surface>(display_mode);
|
||||
if (wsi_surface == nullptr)
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
VkResult res = instance_data.disp.CreateDisplayPlaneSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
|
||||
if (res == VK_SUCCESS)
|
||||
{
|
||||
|
||||
wsi_surface->set_current_extent(pCreateInfo->imageExtent);
|
||||
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;
|
||||
}
|
||||
|
||||
VWL_VKAPI_CALL(VkResult)
|
||||
|
|
@ -504,6 +539,16 @@ VkResult surface_properties::get_required_instance_extensions(util::extension_li
|
|||
return extension_list.add(required_instance_extensions.data(), required_instance_extensions.size());
|
||||
}
|
||||
|
||||
VkResult surface_properties::get_required_device_extensions(util::extension_list &extension_list)
|
||||
{
|
||||
const std::array required_device_extensions{
|
||||
VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
|
||||
VK_KHR_BIND_MEMORY_2_EXTENSION_NAME,
|
||||
};
|
||||
|
||||
return extension_list.add(required_device_extensions.data(), required_device_extensions.size());
|
||||
}
|
||||
|
||||
bool surface_properties::is_surface_extension_enabled(const layer::instance_private_data &instance_data)
|
||||
{
|
||||
return instance_data.is_instance_extension_enabled(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||
|
|
|
|||
|
|
@ -35,9 +35,15 @@ namespace wsi
|
|||
namespace display
|
||||
{
|
||||
|
||||
class surface;
|
||||
|
||||
class surface_properties : public wsi::surface_properties
|
||||
{
|
||||
public:
|
||||
surface_properties();
|
||||
|
||||
surface_properties(surface &wsi_surface);
|
||||
|
||||
VkResult get_surface_capabilities(VkPhysicalDevice physical_device,
|
||||
VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) override;
|
||||
|
||||
|
|
@ -52,12 +58,14 @@ public:
|
|||
|
||||
VkResult get_required_instance_extensions(util::extension_list &extension_list) override;
|
||||
|
||||
VkResult get_required_device_extensions(util::extension_list &extension_list) override;
|
||||
|
||||
bool is_surface_extension_enabled(const layer::instance_private_data &instance_data) override;
|
||||
|
||||
static surface_properties &get_instance();
|
||||
|
||||
private:
|
||||
std::shared_ptr<drm_display> display;
|
||||
surface *const m_specific_surface;
|
||||
};
|
||||
|
||||
} /* namespace display */
|
||||
|
|
|
|||
545
wsi/display/swapchain.cpp
Normal file
545
wsi/display/swapchain.cpp
Normal file
|
|
@ -0,0 +1,545 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file swapchain.cpp
|
||||
*
|
||||
* @brief Contains the class implementation for a display swapchain.
|
||||
*/
|
||||
|
||||
#include <vulkan/vk_icd.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <wsi/swapchain_base.hpp>
|
||||
#include "swapchain.hpp"
|
||||
#include "surface.hpp"
|
||||
#include "util/macros.hpp"
|
||||
|
||||
#include <errno.h>
|
||||
namespace wsi
|
||||
{
|
||||
|
||||
namespace display
|
||||
{
|
||||
|
||||
swapchain::swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *pAllocator,
|
||||
surface &wsi_surface)
|
||||
: wsi::swapchain_base(dev_data, pAllocator)
|
||||
, m_wsi_allocator(nullptr)
|
||||
, m_display_mode(wsi_surface.get_display_mode())
|
||||
, m_image_creation_parameters({}, m_allocator, {}, {})
|
||||
{
|
||||
m_image_create_info.format = VK_FORMAT_UNDEFINED;
|
||||
}
|
||||
|
||||
swapchain::~swapchain()
|
||||
{
|
||||
/* Call the base class teardown */
|
||||
teardown();
|
||||
|
||||
/* Free WSI allocator. */
|
||||
if (m_wsi_allocator != nullptr)
|
||||
{
|
||||
wsialloc_delete(m_wsi_allocator);
|
||||
}
|
||||
m_wsi_allocator = nullptr;
|
||||
}
|
||||
|
||||
static void page_flip_event(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data)
|
||||
{
|
||||
UNUSED(fd);
|
||||
UNUSED(sequence);
|
||||
UNUSED(tv_sec);
|
||||
UNUSED(tv_usec);
|
||||
bool *done = (bool *)user_data;
|
||||
*done = true;
|
||||
}
|
||||
|
||||
VkResult swapchain::init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info,
|
||||
bool &use_presentation_thread)
|
||||
{
|
||||
|
||||
WSIALLOC_ASSERT_VERSION();
|
||||
if (wsialloc_new(&m_wsi_allocator) != WSIALLOC_ERROR_NONE)
|
||||
{
|
||||
WSI_LOG_ERROR("Failed to create wsi allocator.");
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
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<display_image_data *>(swapchain_image.data);
|
||||
return image_data->external_mem.bind_swapchain_image_memory(bind_image_mem_info->image);
|
||||
}
|
||||
|
||||
VkResult swapchain::get_surface_compatible_formats(const VkImageCreateInfo &info,
|
||||
util::vector<wsialloc_format> &importable_formats,
|
||||
util::vector<uint64_t> &exportable_modifers)
|
||||
{
|
||||
/* Query supported modifers. */
|
||||
util::vector<VkDrmFormatModifierPropertiesEXT> drm_format_props(
|
||||
util::allocator(m_allocator, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
|
||||
|
||||
TRY_LOG(util::get_drm_format_properties(m_device_data.physical_device, info.format, drm_format_props),
|
||||
"Failed to get format properties");
|
||||
|
||||
for (const auto &prop : drm_format_props)
|
||||
{
|
||||
drm_format_pair drm_format{ util::drm::vk_to_drm_format(info.format), prop.drmFormatModifier };
|
||||
|
||||
// TODO query surface class for support of format+modifier combination. For now support no modifiers.
|
||||
if ((drm_format.modifier != 0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
VkExternalImageFormatPropertiesKHR external_props = {};
|
||||
external_props.sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR;
|
||||
|
||||
VkImageFormatProperties2KHR format_props = {};
|
||||
format_props.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR;
|
||||
format_props.pNext = &external_props;
|
||||
|
||||
VkResult result = VK_SUCCESS;
|
||||
{
|
||||
VkPhysicalDeviceExternalImageFormatInfoKHR external_info = {};
|
||||
external_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR;
|
||||
external_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
|
||||
|
||||
VkPhysicalDeviceImageDrmFormatModifierInfoEXT drm_mod_info = {};
|
||||
drm_mod_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT;
|
||||
drm_mod_info.pNext = &external_info;
|
||||
drm_mod_info.drmFormatModifier = prop.drmFormatModifier;
|
||||
drm_mod_info.sharingMode = info.sharingMode;
|
||||
drm_mod_info.queueFamilyIndexCount = info.queueFamilyIndexCount;
|
||||
drm_mod_info.pQueueFamilyIndices = info.pQueueFamilyIndices;
|
||||
|
||||
VkPhysicalDeviceImageFormatInfo2KHR image_info = {};
|
||||
image_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR;
|
||||
image_info.pNext = &drm_mod_info;
|
||||
image_info.format = info.format;
|
||||
image_info.type = info.imageType;
|
||||
image_info.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
|
||||
image_info.usage = info.usage;
|
||||
image_info.flags = info.flags;
|
||||
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
VkImageCompressionControlEXT compression_control = {};
|
||||
compression_control.sType = VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT;
|
||||
compression_control.flags = m_image_compression_control_params.flags;
|
||||
compression_control.compressionControlPlaneCount =
|
||||
m_image_compression_control_params.compression_control_plane_count;
|
||||
compression_control.pFixedRateFlags = m_image_compression_control_params.fixed_rate_flags.data();
|
||||
|
||||
if (m_device_data.is_swapchain_compression_control_enabled())
|
||||
{
|
||||
compression_control.pNext = image_info.pNext;
|
||||
image_info.pNext = &compression_control;
|
||||
}
|
||||
#endif
|
||||
result = m_device_data.instance_data.disp.GetPhysicalDeviceImageFormatProperties2KHR(
|
||||
m_device_data.physical_device, &image_info, &format_props);
|
||||
}
|
||||
if (result != VK_SUCCESS)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (format_props.imageFormatProperties.maxExtent.width < info.extent.width ||
|
||||
format_props.imageFormatProperties.maxExtent.height < info.extent.height ||
|
||||
format_props.imageFormatProperties.maxExtent.depth < info.extent.depth)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (format_props.imageFormatProperties.maxMipLevels < info.mipLevels ||
|
||||
format_props.imageFormatProperties.maxArrayLayers < info.arrayLayers)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if ((format_props.imageFormatProperties.sampleCounts & info.samples) != info.samples)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (external_props.externalMemoryProperties.externalMemoryFeatures &
|
||||
VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR)
|
||||
{
|
||||
if (!exportable_modifers.try_push_back(drm_format.modifier))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if (external_props.externalMemoryProperties.externalMemoryFeatures &
|
||||
VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR)
|
||||
{
|
||||
uint64_t flags =
|
||||
(prop.drmFormatModifierTilingFeatures & VK_FORMAT_FEATURE_DISJOINT_BIT) ? 0 : WSIALLOC_FORMAT_NON_DISJOINT;
|
||||
wsialloc_format import_format{ drm_format.fourcc, drm_format.modifier, flags };
|
||||
if (!importable_formats.try_push_back(import_format))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult swapchain::allocate_wsialloc(VkImageCreateInfo &image_create_info, display_image_data *image_data,
|
||||
util::vector<wsialloc_format> &importable_formats,
|
||||
wsialloc_format *allocated_format)
|
||||
{
|
||||
bool is_protected_memory = (image_create_info.flags & VK_IMAGE_CREATE_PROTECTED_BIT) != 0;
|
||||
uint64_t allocation_flags = is_protected_memory ? WSIALLOC_ALLOCATE_PROTECTED : 0;
|
||||
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
if (m_image_compression_control_params.flags & VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT)
|
||||
{
|
||||
allocation_flags |= WSIALLOC_ALLOCATE_HIGHEST_FIXED_RATE_COMPRESSION;
|
||||
}
|
||||
#endif
|
||||
|
||||
wsialloc_allocate_info alloc_info = { importable_formats.data(), static_cast<unsigned>(importable_formats.size()),
|
||||
image_create_info.extent.width, image_create_info.extent.height,
|
||||
allocation_flags };
|
||||
|
||||
std::array<int, MAX_PLANES> strides{};
|
||||
std::array<int, MAX_PLANES> buffer_fds{ -1, -1, -1, -1 };
|
||||
std::array<uint32_t, MAX_PLANES> offsets{};
|
||||
const auto res =
|
||||
wsialloc_alloc(m_wsi_allocator, &alloc_info, allocated_format, strides.data(), buffer_fds.data(), offsets.data());
|
||||
if (res != WSIALLOC_ERROR_NONE)
|
||||
{
|
||||
WSI_LOG_ERROR("Failed allocation of DMA Buffer. WSI error: %d", static_cast<int>(res));
|
||||
if (res == WSIALLOC_ERROR_NOT_SUPPORTED)
|
||||
{
|
||||
return VK_ERROR_FORMAT_NOT_SUPPORTED;
|
||||
}
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
auto &external_memory = image_data->external_mem;
|
||||
external_memory.set_strides(strides);
|
||||
external_memory.set_buffer_fds(buffer_fds);
|
||||
external_memory.set_offsets(offsets);
|
||||
external_memory.set_memory_handle_type(VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static VkResult fill_image_create_info(VkImageCreateInfo &image_create_info,
|
||||
util::vector<VkSubresourceLayout> &image_plane_layouts,
|
||||
VkImageDrmFormatModifierExplicitCreateInfoEXT &drm_mod_info,
|
||||
VkExternalMemoryImageCreateInfoKHR &external_info,
|
||||
display_image_data &image_data, uint64_t modifier)
|
||||
{
|
||||
TRY_LOG_CALL(image_data.external_mem.fill_image_plane_layouts(image_plane_layouts));
|
||||
|
||||
if (image_data.external_mem.is_disjoint())
|
||||
{
|
||||
image_create_info.flags |= VK_IMAGE_CREATE_DISJOINT_BIT;
|
||||
}
|
||||
|
||||
image_data.external_mem.fill_drm_mod_info(image_create_info.pNext, drm_mod_info, image_plane_layouts, modifier);
|
||||
image_data.external_mem.fill_external_info(external_info, &drm_mod_info);
|
||||
image_create_info.pNext = &external_info;
|
||||
image_create_info.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult swapchain::allocate_image(VkImageCreateInfo &image_create_info, display_image_data *image_data, VkImage *image)
|
||||
{
|
||||
util::vector<wsialloc_format> importable_formats(util::allocator(m_allocator, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
|
||||
auto &m_allocated_format = m_image_creation_parameters.m_allocated_format;
|
||||
if (m_image_create_info.format != VK_FORMAT_UNDEFINED)
|
||||
{
|
||||
if (!importable_formats.try_push_back(m_allocated_format))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
TRY_LOG_CALL(allocate_wsialloc(m_image_create_info, image_data, importable_formats, &m_allocated_format));
|
||||
}
|
||||
else
|
||||
{
|
||||
util::vector<uint64_t> exportable_modifiers(util::allocator(m_allocator, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
|
||||
TRY_LOG_CALL(get_surface_compatible_formats(image_create_info, importable_formats, exportable_modifiers));
|
||||
|
||||
/* TODO: Handle exportable images which use ICD allocated memory in preference to an external allocator. */
|
||||
if (importable_formats.empty())
|
||||
{
|
||||
WSI_LOG_ERROR("Export/Import not supported.");
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
||||
wsialloc_format allocated_format = { 0 };
|
||||
TRY_LOG_CALL(allocate_wsialloc(image_create_info, image_data, importable_formats, &allocated_format));
|
||||
|
||||
TRY_LOG_CALL(fill_image_create_info(
|
||||
image_create_info, m_image_creation_parameters.m_image_layout, m_image_creation_parameters.m_drm_mod_info,
|
||||
m_image_creation_parameters.m_external_info, *image_data, allocated_format.modifier));
|
||||
|
||||
m_image_create_info = image_create_info;
|
||||
m_allocated_format = allocated_format;
|
||||
}
|
||||
|
||||
TRY_LOG(m_device_data.disp.CreateImage(m_device, &m_image_create_info, get_allocation_callbacks(), image),
|
||||
"Image creation failed");
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult swapchain::create_framebuffer(const VkImageCreateInfo &image_create_info, swapchain_image &image,
|
||||
display_image_data *image_data)
|
||||
{
|
||||
VkResult ret_code = VK_SUCCESS;
|
||||
std::array<uint32_t, util::MAX_PLANES> strides{ 0, 0, 0, 0 };
|
||||
|
||||
auto &display = drm_display::get_display();
|
||||
if (!display.has_value())
|
||||
{
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
||||
drm_gem_handle_array<util::MAX_PLANES> buffer_handles{ display->get_drm_fd() };
|
||||
|
||||
const auto &buffer_fds = image_data->external_mem.get_buffer_fds();
|
||||
|
||||
for (uint32_t plane = 0; plane < image_data->external_mem.get_num_planes(); plane++)
|
||||
{
|
||||
assert(image_data->external_mem.get_strides()[plane] > 0);
|
||||
strides[plane] = image_data->external_mem.get_strides()[plane];
|
||||
if (drmPrimeFDToHandle(display->get_drm_fd(), buffer_fds[plane], &buffer_handles[plane]) != 0)
|
||||
{
|
||||
WSI_LOG_ERROR("Failed to convert buffer FD to GEM handle: %s", std::strerror(errno));
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
int error = drmModeAddFB2(display->get_drm_fd(), image_create_info.extent.width, image_create_info.extent.height,
|
||||
m_image_creation_parameters.m_allocated_format.fourcc, buffer_handles.data(),
|
||||
strides.data(), image_data->external_mem.get_offsets().data(), &image_data->fb_id, 0);
|
||||
|
||||
if (error != 0)
|
||||
{
|
||||
WSI_LOG_ERROR("Failed to create framebuffer: %s", strerror(errno));
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
VkResult swapchain::create_and_bind_swapchain_image(VkImageCreateInfo image_create_info, swapchain_image &image)
|
||||
{
|
||||
/* Create image_data */
|
||||
auto image_data = m_allocator.create<display_image_data>(1, m_device, m_allocator);
|
||||
if (image_data == nullptr)
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
std::unique_lock<std::recursive_mutex> image_status_lock(m_image_status_mutex);
|
||||
image.data = image_data;
|
||||
image.status = swapchain_image::FREE;
|
||||
|
||||
TRY_LOG(allocate_image(image_create_info, image_data, &image.image), "Failed to allocate image");
|
||||
image_status_lock.unlock();
|
||||
|
||||
TRY_LOG(create_framebuffer(image_create_info, image, image_data), "Failed to create framebuffer");
|
||||
|
||||
TRY_LOG(image_data->external_mem.import_memory_and_bind_swapchain_image(image.image),
|
||||
"Failed to import memory and bind swapchain image");
|
||||
|
||||
/* Initialize presentation fence. */
|
||||
auto present_fence = sync_fd_fence_sync::create(m_device_data);
|
||||
if (!present_fence.has_value())
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
image_data->present_fence = std::move(present_fence.value());
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void swapchain::present_image(uint32_t pending_index)
|
||||
{
|
||||
int drm_res = 0;
|
||||
display_image_data *image_data = reinterpret_cast<display_image_data *>(m_swapchain_images[pending_index].data);
|
||||
const auto &display = drm_display::get_display();
|
||||
if (!display.has_value())
|
||||
{
|
||||
set_error_state(VK_ERROR_SURFACE_LOST_KHR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_first_present)
|
||||
{
|
||||
/* Now we can set the mode of the new swapchain. */
|
||||
drmModeModeInfo modeInfo = m_display_mode->get_drm_mode();
|
||||
|
||||
uint32_t connector_id = display->get_connector_id();
|
||||
drm_res = drmModeSetCrtc(display->get_drm_fd(), display->get_crtc_id(), image_data->fb_id, 0, 0, &connector_id, 1,
|
||||
&modeInfo);
|
||||
|
||||
if (drm_res != 0)
|
||||
{
|
||||
WSI_LOG_ERROR("drmModeSetCrtc failed: %s\n", std::strerror(errno));
|
||||
set_error_state(VK_ERROR_SURFACE_LOST_KHR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* The swapchain has already started presenting. */
|
||||
else
|
||||
{
|
||||
|
||||
bool page_flip_complete = false;
|
||||
|
||||
drm_res = drmModePageFlip(display->get_drm_fd(), display->get_crtc_id(), image_data->fb_id,
|
||||
DRM_MODE_PAGE_FLIP_EVENT, (void *)&page_flip_complete);
|
||||
|
||||
if (drm_res != 0)
|
||||
{
|
||||
WSI_LOG_ERROR("drmModePageFlip failed: %s\n", std::strerror(errno));
|
||||
set_error_state(VK_ERROR_SURFACE_LOST_KHR);
|
||||
return;
|
||||
}
|
||||
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(display->get_drm_fd(), &fds);
|
||||
|
||||
do
|
||||
{
|
||||
struct timeval t;
|
||||
t.tv_sec = 1;
|
||||
t.tv_usec = 0;
|
||||
drm_res = select(display->get_drm_fd() + 1, &fds, NULL, NULL, &t);
|
||||
|
||||
if (drm_res < 0)
|
||||
{
|
||||
if (errno != EINTR && errno != EAGAIN)
|
||||
{
|
||||
WSI_LOG_ERROR("select() failed with errno: %d\n", errno);
|
||||
set_error_state(VK_ERROR_SURFACE_LOST_KHR);
|
||||
break;
|
||||
}
|
||||
WSI_LOG_ERROR("select() failed with %d, carrying on with page flip\n", errno);
|
||||
}
|
||||
else if (drm_res == 0)
|
||||
{
|
||||
WSI_LOG_ERROR("select() timed out, carrying on with page flip\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(FD_ISSET(display->get_drm_fd(), &fds));
|
||||
|
||||
drmEventContext ev = {};
|
||||
ev.version = DRM_EVENT_CONTEXT_VERSION;
|
||||
ev.page_flip_handler = page_flip_event;
|
||||
|
||||
drmHandleEvent(display->get_drm_fd(), &ev);
|
||||
}
|
||||
} while ((drm_res == -1 && (errno == EINTR || errno == EAGAIN)) || drm_res == 0 || !page_flip_complete);
|
||||
}
|
||||
|
||||
/* Find currently presented image */
|
||||
uint32_t presented_index = m_swapchain_images.size();
|
||||
if (!m_first_present)
|
||||
{
|
||||
for (uint32_t i = 0; i < m_swapchain_images.size(); ++i)
|
||||
{
|
||||
if (m_swapchain_images[i].status == swapchain_image::PRESENTED)
|
||||
{
|
||||
presented_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* There should always be a presented image, unless there was an error */
|
||||
assert(presented_index < m_swapchain_images.size());
|
||||
}
|
||||
/* The image is on screen, change the image status to PRESENTED. */
|
||||
m_swapchain_images[pending_index].status = swapchain_image::PRESENTED;
|
||||
/* And release the old one. */
|
||||
if (presented_index < m_swapchain_images.size())
|
||||
{
|
||||
unpresent_image(presented_index);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
VkResult swapchain::image_set_present_payload(swapchain_image &image, VkQueue queue, const VkSemaphore *sem_payload,
|
||||
uint32_t sem_count)
|
||||
{
|
||||
|
||||
auto image_data = reinterpret_cast<display_image_data *>(image.data);
|
||||
return image_data->present_fence.set_payload(queue, sem_payload, sem_count);
|
||||
}
|
||||
|
||||
VkResult swapchain::image_wait_present(swapchain_image &image, uint64_t timeout)
|
||||
{
|
||||
auto data = reinterpret_cast<display_image_data *>(image.data);
|
||||
return data->present_fence.wait_payload(timeout);
|
||||
}
|
||||
|
||||
void swapchain::destroy_image(swapchain_image &image)
|
||||
{
|
||||
std::unique_lock<std::recursive_mutex> image_status_lock(m_image_status_mutex);
|
||||
|
||||
if (image.status != swapchain_image::INVALID)
|
||||
{
|
||||
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<display_image_data *>(image.data);
|
||||
auto &display = drm_display::get_display();
|
||||
if (!display.has_value())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (image_data->fb_id != std::numeric_limits<uint32_t>::max())
|
||||
{
|
||||
|
||||
int result = drmModeRmFB(display->get_drm_fd(), image_data->fb_id);
|
||||
assert(result == 0);
|
||||
}
|
||||
|
||||
m_allocator.destroy(1, image_data);
|
||||
image.data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace display */
|
||||
|
||||
} /* namespace wsi*/
|
||||
129
wsi/display/swapchain.hpp
Normal file
129
wsi/display/swapchain.hpp
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file swapchain.hpp
|
||||
*
|
||||
* @brief Contains the class definition for a display swapchain.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vulkan/vk_icd.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <wsi/swapchain_base.hpp>
|
||||
#include "util/wsialloc/wsialloc.h"
|
||||
#include "drm_display.hpp"
|
||||
#include "wsi/external_memory.hpp"
|
||||
#include "surface.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
|
||||
namespace display
|
||||
{
|
||||
|
||||
struct display_image_data
|
||||
{
|
||||
display_image_data(const VkDevice &device, const util::allocator &allocator)
|
||||
: external_mem(device, allocator)
|
||||
, fb_id(std::numeric_limits<uint32_t>::max())
|
||||
{
|
||||
}
|
||||
|
||||
external_memory external_mem;
|
||||
uint32_t fb_id;
|
||||
sync_fd_fence_sync present_fence;
|
||||
};
|
||||
|
||||
struct image_creation_parameters
|
||||
{
|
||||
wsialloc_format m_allocated_format;
|
||||
util::vector<VkSubresourceLayout> m_image_layout;
|
||||
VkExternalMemoryImageCreateInfoKHR m_external_info;
|
||||
VkImageDrmFormatModifierExplicitCreateInfoEXT m_drm_mod_info;
|
||||
|
||||
image_creation_parameters(wsialloc_format allocated_format, util::allocator allocator,
|
||||
VkExternalMemoryImageCreateInfoKHR external_info,
|
||||
VkImageDrmFormatModifierExplicitCreateInfoEXT drm_mod_info)
|
||||
: m_allocated_format(allocated_format)
|
||||
, m_image_layout(allocator)
|
||||
, m_external_info(external_info)
|
||||
, m_drm_mod_info(drm_mod_info)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct drm_format_pair
|
||||
{
|
||||
uint32_t fourcc;
|
||||
uint64_t modifier;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Display swapchain class.
|
||||
*/
|
||||
class swapchain : public wsi::swapchain_base
|
||||
{
|
||||
public:
|
||||
swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *pAllocator, surface &wsi_surface);
|
||||
virtual ~swapchain();
|
||||
virtual VkResult init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info,
|
||||
bool &use_presentation_thread) override;
|
||||
|
||||
virtual VkResult bind_swapchain_image(VkDevice &device, const VkBindImageMemoryInfo *bind_image_mem_info,
|
||||
const VkBindImageMemorySwapchainInfoKHR *bind_sc_info) override;
|
||||
|
||||
virtual VkResult create_and_bind_swapchain_image(VkImageCreateInfo image_create_info,
|
||||
swapchain_image &image) override;
|
||||
|
||||
virtual void present_image(uint32_t pending_index) override;
|
||||
|
||||
virtual VkResult image_set_present_payload(swapchain_image &image, VkQueue queue, const VkSemaphore *sem_payload,
|
||||
uint32_t sem_count) override;
|
||||
virtual VkResult image_wait_present(swapchain_image &image, uint64_t timeout) override;
|
||||
|
||||
void destroy_image(swapchain_image &image) override;
|
||||
|
||||
private:
|
||||
VkResult allocate_image(VkImageCreateInfo &image_create_info, display_image_data *image_data, VkImage *image);
|
||||
|
||||
VkResult allocate_wsialloc(VkImageCreateInfo &image_create_info, display_image_data *image_data,
|
||||
util::vector<wsialloc_format> &importable_formats, wsialloc_format *allocated_format);
|
||||
|
||||
VkResult get_surface_compatible_formats(const VkImageCreateInfo &info,
|
||||
util::vector<wsialloc_format> &importable_formats,
|
||||
util::vector<uint64_t> &exportable_modifers);
|
||||
|
||||
VkResult create_framebuffer(const VkImageCreateInfo &image_create_info, swapchain_image &image,
|
||||
display_image_data *image_data);
|
||||
|
||||
wsialloc_allocator *m_wsi_allocator;
|
||||
drm_display_mode *m_display_mode;
|
||||
image_creation_parameters m_image_creation_parameters;
|
||||
};
|
||||
|
||||
} /* namespace display */
|
||||
|
||||
} /* namespace wsi*/
|
||||
Loading…
Add table
Reference in a new issue