2024-03-06 09:39:05 +01:00
|
|
|
/*
|
2025-01-15 16:05:05 +00:00
|
|
|
* Copyright (c) 2024-2025 Arm Limited.
|
2024-03-06 09:39:05 +01:00
|
|
|
*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
|
2024-11-28 06:36:17 +00:00
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
|
|
#include <util/macros.hpp>
|
2025-11-20 13:55:45 +00:00
|
|
|
#include <wsi/extensions/external_memory_extension.hpp>
|
2024-11-28 06:36:17 +00:00
|
|
|
#include <wsi/extensions/image_compression_control.hpp>
|
|
|
|
|
#include <wsi/extensions/present_id.hpp>
|
2024-03-06 09:39:05 +01:00
|
|
|
#include <wsi/swapchain_base.hpp>
|
2024-11-28 06:36:17 +00:00
|
|
|
|
2024-03-06 09:39:05 +01:00
|
|
|
#include "swapchain.hpp"
|
2025-05-09 16:04:39 +00:00
|
|
|
#include "present_wait_display.hpp"
|
2024-03-06 09:39:05 +01:00
|
|
|
|
|
|
|
|
namespace wsi
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
namespace display
|
|
|
|
|
{
|
|
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
class display_image_data : public swapchain_image_data
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
display_image_data(int drm_fd, uint32_t fb_id)
|
|
|
|
|
: m_drm_fd(drm_fd)
|
|
|
|
|
, m_fb_id(fb_id)
|
|
|
|
|
{
|
|
|
|
|
assert(drm_fd != -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~display_image_data()
|
|
|
|
|
{
|
|
|
|
|
int result = drmModeRmFB(m_drm_fd, m_fb_id);
|
|
|
|
|
assert(result == 0);
|
|
|
|
|
UNUSED(result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t get_fb_id()
|
|
|
|
|
{
|
|
|
|
|
return m_fb_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
2025-12-17 09:55:55 +00:00
|
|
|
int m_drm_fd;
|
2025-11-20 13:55:45 +00:00
|
|
|
uint32_t m_fb_id;
|
|
|
|
|
};
|
|
|
|
|
|
2024-03-06 09:39:05 +01:00
|
|
|
swapchain::swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *pAllocator,
|
|
|
|
|
surface &wsi_surface)
|
|
|
|
|
: wsi::swapchain_base(dev_data, pAllocator)
|
|
|
|
|
, m_display_mode(wsi_surface.get_display_mode())
|
2025-11-20 13:55:45 +00:00
|
|
|
, m_image_factory(m_allocator, m_device_data)
|
2024-03-06 09:39:05 +01:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
swapchain::~swapchain()
|
|
|
|
|
{
|
|
|
|
|
/* Call the base class teardown */
|
|
|
|
|
teardown();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-28 06:36:17 +00:00
|
|
|
VkResult swapchain::add_required_extensions(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info)
|
|
|
|
|
{
|
2025-11-20 13:55:45 +00:00
|
|
|
UNUSED(device);
|
2024-11-28 06:36:17 +00:00
|
|
|
|
2025-08-20 11:45:46 +00:00
|
|
|
if (m_device_data.is_present_id_enabled() ||
|
|
|
|
|
(swapchain_create_info->flags & VK_SWAPCHAIN_CREATE_PRESENT_ID_2_BIT_KHR))
|
2024-11-28 06:36:17 +00:00
|
|
|
{
|
|
|
|
|
if (!add_swapchain_extension(m_allocator.make_unique<wsi_ext_present_id>()))
|
|
|
|
|
{
|
|
|
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (m_device_data.should_layer_handle_frame_boundary_events())
|
|
|
|
|
{
|
|
|
|
|
if (!add_swapchain_extension(m_allocator.make_unique<wsi_ext_frame_boundary>(m_device_data)))
|
|
|
|
|
{
|
|
|
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-28 14:46:50 +00:00
|
|
|
bool present_wait2;
|
|
|
|
|
constexpr VkSwapchainCreateFlagsKHR present_wait2_mask =
|
|
|
|
|
(VK_SWAPCHAIN_CREATE_PRESENT_ID_2_BIT_KHR | VK_SWAPCHAIN_CREATE_PRESENT_WAIT_2_BIT_KHR);
|
|
|
|
|
present_wait2 = (swapchain_create_info->flags & present_wait2_mask) == present_wait2_mask;
|
|
|
|
|
|
|
|
|
|
if (m_device_data.is_present_wait_enabled() || present_wait2)
|
2025-05-09 16:04:39 +00:00
|
|
|
{
|
2025-08-28 14:46:50 +00:00
|
|
|
if (!add_swapchain_extension(m_allocator.make_unique<wsi_ext_present_wait_display>(
|
|
|
|
|
*get_swapchain_extension<wsi_ext_present_id>(true), present_wait2)))
|
2025-05-09 16:04:39 +00:00
|
|
|
{
|
|
|
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-28 06:36:17 +00:00
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-06 09:39:05 +01:00
|
|
|
VkResult swapchain::init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info,
|
|
|
|
|
bool &use_presentation_thread)
|
|
|
|
|
{
|
2025-01-15 16:05:05 +00:00
|
|
|
UNUSED(device);
|
|
|
|
|
UNUSED(swapchain_create_info);
|
|
|
|
|
UNUSED(use_presentation_thread);
|
2025-03-26 17:15:21 +00:00
|
|
|
|
2025-03-27 18:06:44 +00:00
|
|
|
auto wsi_allocator = swapchain_wsialloc_allocator::create();
|
|
|
|
|
if (!wsi_allocator.has_value())
|
2024-03-06 09:39:05 +01:00
|
|
|
{
|
|
|
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-27 18:06:44 +00:00
|
|
|
m_wsi_allocator = m_allocator.make_unique<swapchain_wsialloc_allocator>(std::move(*wsi_allocator));
|
|
|
|
|
if (m_wsi_allocator == nullptr)
|
|
|
|
|
{
|
|
|
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
|
|
|
}
|
2024-03-06 09:39:05 +01:00
|
|
|
|
2025-09-11 08:28:03 +00:00
|
|
|
if (is_mutable_format_enabled())
|
|
|
|
|
{
|
|
|
|
|
WSI_LOG_ERROR("Mutable format swapchain is not supported for display backend");
|
|
|
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
return init_image_factory(*swapchain_create_info);
|
2024-03-06 09:39:05 +01:00
|
|
|
}
|
|
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
VkResult swapchain::init_image_factory(const VkSwapchainCreateInfoKHR &swapchain_create_info)
|
2024-03-06 09:39:05 +01:00
|
|
|
{
|
2024-04-11 10:05:24 +02:00
|
|
|
auto &display = drm_display::get_display();
|
|
|
|
|
if (!display.has_value())
|
|
|
|
|
{
|
|
|
|
|
WSI_LOG_ERROR("DRM display not available.");
|
2025-11-20 13:55:45 +00:00
|
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
2024-04-11 10:05:24 +02:00
|
|
|
}
|
|
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
std::variant<VkResult, util::unique_ptr<vulkan_image_handle_creator>> image_handle_creator_result =
|
|
|
|
|
create_image_creator(swapchain_create_info);
|
|
|
|
|
if (auto error = std::get_if<VkResult>(&image_handle_creator_result))
|
2024-03-06 09:39:05 +01:00
|
|
|
{
|
2025-11-20 13:55:45 +00:00
|
|
|
return *error;
|
2024-03-06 09:39:05 +01:00
|
|
|
}
|
|
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
auto image_handle_creator =
|
|
|
|
|
std::get<util::unique_ptr<vulkan_image_handle_creator>>(std::move(image_handle_creator_result));
|
2024-03-06 09:39:05 +01:00
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
auto compression_control = image_create_compression_control::create(m_device, &swapchain_create_info);
|
|
|
|
|
auto sc_img_create_ext_mem_result = swapchain_image_create_external_memory::create(
|
|
|
|
|
image_handle_creator->get_image_create_info(), compression_control, *m_wsi_allocator,
|
|
|
|
|
*display->get_supported_formats(), m_device_data.physical_device, m_allocator);
|
|
|
|
|
if (auto error = std::get_if<VkResult>(&sc_img_create_ext_mem_result))
|
2024-03-06 09:39:05 +01:00
|
|
|
{
|
2025-11-20 13:55:45 +00:00
|
|
|
return *error;
|
2024-03-06 09:39:05 +01:00
|
|
|
}
|
|
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
auto sc_img_create_ext_mem =
|
|
|
|
|
std::get<util::unique_ptr<swapchain_image_create_external_memory>>(std::move(sc_img_create_ext_mem_result));
|
2025-03-26 17:15:21 +00:00
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
auto external_image_create_info = sc_img_create_ext_mem->get_external_image_create_info();
|
|
|
|
|
TRY_LOG_CALL(image_handle_creator->add_extension(std::move(sc_img_create_ext_mem)));
|
2024-10-16 08:57:32 +00:00
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
wsialloc_create_info_args wsialloc_args = { external_image_create_info.selected_format,
|
|
|
|
|
external_image_create_info.flags, external_image_create_info.extent,
|
|
|
|
|
external_image_create_info.explicit_compression };
|
2024-10-16 08:57:32 +00:00
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
auto backing_memory_creator =
|
|
|
|
|
m_allocator.make_unique<external_image_backing_memory_creator>(m_device_data, *m_wsi_allocator, wsialloc_args);
|
2025-11-28 15:06:11 +00:00
|
|
|
if (backing_memory_creator == nullptr)
|
|
|
|
|
{
|
|
|
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
|
|
|
}
|
2024-10-16 08:57:32 +00:00
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
m_image_factory.init(std::move(image_handle_creator), std::move(backing_memory_creator), true, true);
|
2024-03-06 09:39:05 +01:00
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
VkResult swapchain::create_framebuffer(image_backing_memory_external &image_external_memory, uint32_t &out_fb_id)
|
2024-03-06 09:39:05 +01:00
|
|
|
{
|
|
|
|
|
VkResult ret_code = VK_SUCCESS;
|
|
|
|
|
std::array<uint32_t, util::MAX_PLANES> strides{ 0, 0, 0, 0 };
|
2024-04-11 10:05:24 +02:00
|
|
|
std::array<uint64_t, util::MAX_PLANES> modifiers{ 0, 0, 0, 0 };
|
2025-11-20 13:55:45 +00:00
|
|
|
|
|
|
|
|
wsialloc_create_info_args img_create_info = image_external_memory.get_image_create_info();
|
|
|
|
|
external_memory &ext_memory = image_external_memory.get_external_memory();
|
|
|
|
|
|
|
|
|
|
const util::drm::drm_format_pair allocated_format{ img_create_info.selected_format.fourcc,
|
|
|
|
|
img_create_info.selected_format.modifier };
|
2024-03-06 09:39:05 +01:00
|
|
|
|
|
|
|
|
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() };
|
|
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
const auto &buffer_fds = ext_memory.get_buffer_fds();
|
2024-03-06 09:39:05 +01:00
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
for (uint32_t plane = 0; plane < ext_memory.get_num_planes(); plane++)
|
2024-03-06 09:39:05 +01:00
|
|
|
{
|
2025-11-20 13:55:45 +00:00
|
|
|
assert(ext_memory.get_strides()[plane] > 0);
|
2025-12-17 09:55:55 +00:00
|
|
|
strides[plane] = static_cast<uint32_t>(ext_memory.get_strides()[plane]);
|
2024-04-11 10:05:24 +02:00
|
|
|
modifiers[plane] = allocated_format.modifier;
|
2024-03-06 09:39:05 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-11 10:05:24 +02:00
|
|
|
if (!display->is_format_supported(allocated_format))
|
|
|
|
|
{
|
|
|
|
|
WSI_LOG_ERROR("Format not supported.");
|
|
|
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int error = 0;
|
|
|
|
|
if (display->supports_fb_modifiers())
|
|
|
|
|
{
|
2025-11-20 13:55:45 +00:00
|
|
|
error = drmModeAddFB2WithModifiers(display->get_drm_fd(), img_create_info.extent.width,
|
|
|
|
|
img_create_info.extent.height, allocated_format.fourcc, buffer_handles.data(),
|
|
|
|
|
strides.data(), ext_memory.get_offsets().data(), modifiers.data(), &out_fb_id,
|
|
|
|
|
DRM_MODE_FB_MODIFIERS);
|
2024-04-11 10:05:24 +02:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2025-11-20 13:55:45 +00:00
|
|
|
error = drmModeAddFB2(display->get_drm_fd(), img_create_info.extent.width, img_create_info.extent.height,
|
2024-04-11 10:05:24 +02:00
|
|
|
allocated_format.fourcc, buffer_handles.data(), strides.data(),
|
2025-11-20 13:55:45 +00:00
|
|
|
ext_memory.get_offsets().data(), &out_fb_id, 0);
|
2024-04-11 10:05:24 +02:00
|
|
|
}
|
2024-03-06 09:39:05 +01:00
|
|
|
|
|
|
|
|
if (error != 0)
|
|
|
|
|
{
|
|
|
|
|
WSI_LOG_ERROR("Failed to create framebuffer: %s", strerror(errno));
|
|
|
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret_code;
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
VkResult swapchain::allocate_and_bind_swapchain_image(swapchain_image &image)
|
2024-03-06 09:39:05 +01:00
|
|
|
{
|
2025-09-05 15:06:38 +00:00
|
|
|
util::unique_lock<util::recursive_mutex> image_status_lock(m_image_status_mutex);
|
|
|
|
|
if (!image_status_lock)
|
|
|
|
|
{
|
|
|
|
|
WSI_LOG_ERROR("Failed to acquire image status lock in allocate_and_bind_swapchain_image.");
|
|
|
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
|
|
|
}
|
2024-03-06 09:39:05 +01:00
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
auto &display = drm_display::get_display();
|
|
|
|
|
if (!display.has_value())
|
2024-10-16 08:57:32 +00:00
|
|
|
{
|
2025-11-20 13:55:45 +00:00
|
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
2024-10-16 08:57:32 +00:00
|
|
|
}
|
|
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
auto &backing_memory = swapchain_image_factory::get_backing_memory_from_image<image_backing_memory_external>(image);
|
|
|
|
|
TRY_LOG_CALL(backing_memory.allocate());
|
2024-10-16 08:57:32 +00:00
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
uint32_t fb_id = 0;
|
|
|
|
|
TRY_LOG(create_framebuffer(backing_memory, fb_id), "Failed to create framebuffer");
|
2024-10-16 08:57:32 +00:00
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
TRY_LOG_CALL(backing_memory.import_and_bind(image.get_image()));
|
2025-01-15 16:05:05 +00:00
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
auto image_data = m_allocator.make_unique<display_image_data>(display->get_drm_fd(), fb_id);
|
|
|
|
|
if (image_data == nullptr)
|
|
|
|
|
{
|
|
|
|
|
int result = drmModeRmFB(display->get_drm_fd(), fb_id);
|
|
|
|
|
assert(result == 0);
|
|
|
|
|
UNUSED(result);
|
2024-10-16 08:57:32 +00:00
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
2024-10-16 08:57:32 +00:00
|
|
|
}
|
2025-11-20 13:55:45 +00:00
|
|
|
image.set_data(std::move(image_data));
|
2024-10-16 08:57:32 +00:00
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
return VK_SUCCESS;
|
2024-10-16 08:57:32 +00:00
|
|
|
}
|
|
|
|
|
|
2024-08-22 16:45:28 +01:00
|
|
|
void swapchain::present_image(const pending_present_request &pending_present)
|
2024-03-06 09:39:05 +01:00
|
|
|
{
|
2025-11-20 13:55:45 +00:00
|
|
|
|
|
|
|
|
auto &image = m_swapchain_images[pending_present.image_index];
|
|
|
|
|
auto image_data = image.get_data<display_image_data>();
|
|
|
|
|
|
2024-03-06 09:39:05 +01:00
|
|
|
const auto &display = drm_display::get_display();
|
|
|
|
|
if (!display.has_value())
|
|
|
|
|
{
|
|
|
|
|
set_error_state(VK_ERROR_SURFACE_LOST_KHR);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
int drm_res = 0;
|
2024-03-06 09:39:05 +01:00
|
|
|
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();
|
2025-12-17 09:55:55 +00:00
|
|
|
drm_res = drmModeSetCrtc(display->get_drm_fd(), static_cast<uint32_t>(display->get_crtc_id()),
|
|
|
|
|
image_data->get_fb_id(), 0, 0, &connector_id, 1, &modeInfo);
|
2024-03-06 09:39:05 +01:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
2025-12-17 09:55:55 +00:00
|
|
|
drm_res = drmModePageFlip(display->get_drm_fd(), static_cast<uint32_t>(display->get_crtc_id()),
|
|
|
|
|
image_data->get_fb_id(), DRM_MODE_PAGE_FLIP_EVENT, (void *)&page_flip_complete);
|
2024-03-06 09:39:05 +01:00
|
|
|
|
|
|
|
|
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
|
|
|
|
|
{
|
2024-11-05 18:47:31 +00:00
|
|
|
int result = FD_ISSET(display->get_drm_fd(), &fds);
|
|
|
|
|
assert(result > 0);
|
|
|
|
|
UNUSED(result);
|
2024-03-06 09:39:05 +01:00
|
|
|
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 */
|
2025-12-17 09:55:55 +00:00
|
|
|
auto presented_index = static_cast<uint32_t>(m_swapchain_images.size());
|
2024-03-06 09:39:05 +01:00
|
|
|
if (!m_first_present)
|
|
|
|
|
{
|
|
|
|
|
for (uint32_t i = 0; i < m_swapchain_images.size(); ++i)
|
|
|
|
|
{
|
2025-11-20 13:55:45 +00:00
|
|
|
if (m_swapchain_images[i].get_status() == swapchain_image::PRESENTED)
|
2024-03-06 09:39:05 +01:00
|
|
|
{
|
|
|
|
|
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. */
|
2025-11-20 13:55:45 +00:00
|
|
|
m_swapchain_images[pending_present.image_index].set_status(swapchain_image::PRESENTED);
|
2024-11-28 06:36:17 +00:00
|
|
|
|
2025-08-13 08:41:21 +00:00
|
|
|
auto *ext = get_swapchain_extension<wsi_ext_present_id>();
|
|
|
|
|
if (ext != nullptr)
|
2024-11-28 06:36:17 +00:00
|
|
|
{
|
2025-04-01 09:27:18 +00:00
|
|
|
ext->mark_delivered(pending_present.present_id);
|
2024-11-28 06:36:17 +00:00
|
|
|
}
|
2024-08-22 16:45:28 +01:00
|
|
|
|
2024-03-06 09:39:05 +01:00
|
|
|
/* And release the old one. */
|
|
|
|
|
if (presented_index < m_swapchain_images.size())
|
|
|
|
|
{
|
|
|
|
|
unpresent_image(presented_index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
std::variant<VkResult, util::unique_ptr<vulkan_image_handle_creator>> swapchain::create_image_creator(
|
|
|
|
|
const VkSwapchainCreateInfoKHR &swapchain_create_info)
|
2024-03-06 09:39:05 +01:00
|
|
|
{
|
2025-11-20 13:55:45 +00:00
|
|
|
UNUSED(swapchain_create_info);
|
2024-03-06 09:39:05 +01:00
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
auto image_handle_creator = m_allocator.make_unique<vulkan_image_handle_creator>(m_allocator, swapchain_create_info);
|
|
|
|
|
if (image_handle_creator == nullptr)
|
2024-03-06 09:39:05 +01:00
|
|
|
{
|
2025-11-20 13:55:45 +00:00
|
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
2024-03-06 09:39:05 +01:00
|
|
|
}
|
|
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
return image_handle_creator;
|
2024-03-06 09:39:05 +01:00
|
|
|
}
|
|
|
|
|
|
2025-11-20 13:55:45 +00:00
|
|
|
swapchain_image_factory &swapchain::get_image_factory()
|
2025-03-26 13:18:02 +00:00
|
|
|
{
|
2025-11-20 13:55:45 +00:00
|
|
|
return m_image_factory;
|
2025-03-26 13:18:02 +00:00
|
|
|
}
|
|
|
|
|
|
2024-03-06 09:39:05 +01:00
|
|
|
} /* namespace display */
|
|
|
|
|
|
|
|
|
|
} /* namespace wsi*/
|