2021-01-31 20:09:53 +00:00
|
|
|
/*
|
2024-04-09 16:04:28 +01:00
|
|
|
* Copyright (c) 2017-2024 Arm Limited.
|
2021-01-31 20:09:53 +00: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.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#define VK_USE_PLATFORM_WAYLAND_KHR 1
|
|
|
|
|
|
|
|
|
|
#include "swapchain.hpp"
|
2021-03-03 15:06:41 +00:00
|
|
|
#include "wl_helpers.hpp"
|
2021-07-22 23:49:15 +01:00
|
|
|
#include "surface_properties.hpp"
|
2021-01-31 20:09:53 +00:00
|
|
|
|
2022-01-24 15:02:03 +00:00
|
|
|
#include <cstdint>
|
2021-01-31 20:09:53 +00:00
|
|
|
#include <cstring>
|
|
|
|
|
#include <cassert>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <cstdlib>
|
|
|
|
|
#include <cerrno>
|
|
|
|
|
#include <cstdio>
|
|
|
|
|
#include <climits>
|
2021-03-12 14:19:59 +00:00
|
|
|
#include <functional>
|
2021-01-31 20:09:53 +00:00
|
|
|
|
|
|
|
|
#include "util/drm/drm_utils.hpp"
|
2021-03-23 10:24:43 +00:00
|
|
|
#include "util/log.hpp"
|
2021-09-23 15:35:51 +01:00
|
|
|
#include "util/helpers.hpp"
|
2021-11-03 11:25:48 +00:00
|
|
|
#include "util/macros.hpp"
|
2022-03-18 12:05:46 +00:00
|
|
|
#include "util/format_modifiers.hpp"
|
2021-03-12 14:19:59 +00:00
|
|
|
|
2021-01-31 20:09:53 +00:00
|
|
|
namespace wsi
|
|
|
|
|
{
|
|
|
|
|
namespace wayland
|
|
|
|
|
{
|
|
|
|
|
|
2021-07-22 23:49:15 +01:00
|
|
|
swapchain::swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *pAllocator,
|
|
|
|
|
surface &wsi_surface)
|
2021-01-31 20:09:53 +00:00
|
|
|
: swapchain_base(dev_data, pAllocator)
|
2021-07-22 23:49:15 +01:00
|
|
|
, m_display(wsi_surface.get_wl_display())
|
|
|
|
|
, m_surface(wsi_surface.get_wl_surface())
|
2021-07-23 19:42:11 +01:00
|
|
|
, m_wsi_surface(&wsi_surface)
|
2021-01-31 20:09:53 +00:00
|
|
|
, m_buffer_queue(nullptr)
|
2021-05-05 15:44:32 +01:00
|
|
|
, m_wsi_allocator(nullptr)
|
2022-07-04 10:15:14 +01:00
|
|
|
, m_image_creation_parameters({}, m_allocator, {}, {})
|
2021-01-31 20:09:53 +00:00
|
|
|
{
|
2022-07-04 10:15:14 +01:00
|
|
|
m_image_create_info.format = VK_FORMAT_UNDEFINED;
|
2021-01-31 20:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
swapchain::~swapchain()
|
|
|
|
|
{
|
|
|
|
|
teardown();
|
2021-03-03 15:06:41 +00:00
|
|
|
|
2021-10-04 12:30:14 +01:00
|
|
|
if (m_wsi_allocator != nullptr)
|
|
|
|
|
{
|
|
|
|
|
wsialloc_delete(m_wsi_allocator);
|
|
|
|
|
}
|
2021-05-05 15:44:32 +01:00
|
|
|
m_wsi_allocator = nullptr;
|
2021-01-31 20:09:53 +00:00
|
|
|
if (m_buffer_queue != nullptr)
|
|
|
|
|
{
|
|
|
|
|
wl_event_queue_destroy(m_buffer_queue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 15:45:34 +00:00
|
|
|
VkResult swapchain::init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info,
|
|
|
|
|
bool &use_presentation_thread)
|
2021-01-31 20:09:53 +00:00
|
|
|
{
|
2021-07-23 19:42:11 +01:00
|
|
|
if ((m_display == nullptr) || (m_surface == nullptr) || (m_wsi_surface->get_dmabuf_interface() == nullptr))
|
2021-01-31 20:09:53 +00:00
|
|
|
{
|
|
|
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-22 23:49:15 +01:00
|
|
|
m_buffer_queue = wl_display_create_queue(m_display);
|
|
|
|
|
if (m_buffer_queue == nullptr)
|
2021-03-03 15:06:41 +00:00
|
|
|
{
|
2021-07-22 23:49:15 +01:00
|
|
|
WSI_LOG_ERROR("Failed to create buffer wl queue.");
|
2021-03-03 15:06:41 +00:00
|
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
|
|
|
}
|
2021-01-31 20:09:53 +00:00
|
|
|
|
2021-11-15 13:59:10 +00:00
|
|
|
WSIALLOC_ASSERT_VERSION();
|
2021-07-28 15:39:11 +00:00
|
|
|
if (wsialloc_new(&m_wsi_allocator) != WSIALLOC_ERROR_NONE)
|
2021-01-31 20:09:53 +00:00
|
|
|
{
|
2021-03-23 10:24:43 +00:00
|
|
|
WSI_LOG_ERROR("Failed to create wsi allocator.");
|
2021-01-31 20:09:53 +00:00
|
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 15:45:34 +00:00
|
|
|
/*
|
|
|
|
|
* When VK_PRESENT_MODE_MAILBOX_KHR has been chosen by the application we don't
|
|
|
|
|
* initialize the page flip thread so the present_image function can be called
|
|
|
|
|
* during vkQueuePresent.
|
|
|
|
|
*/
|
2021-10-15 13:34:37 +01:00
|
|
|
use_presentation_thread = (m_present_mode != VK_PRESENT_MODE_MAILBOX_KHR);
|
2021-10-14 15:45:34 +00:00
|
|
|
|
2021-01-31 20:09:53 +00:00
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-03 11:25:48 +00:00
|
|
|
VWL_CAPI_CALL(void) buffer_release(void *data, struct wl_buffer *wayl_buffer) VWL_API_POST
|
2021-01-31 20:09:53 +00:00
|
|
|
{
|
2021-03-12 14:19:59 +00:00
|
|
|
auto sc = reinterpret_cast<swapchain *>(data);
|
2021-01-31 20:09:53 +00:00
|
|
|
sc->release_buffer(wayl_buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void swapchain::release_buffer(struct wl_buffer *wayl_buffer)
|
|
|
|
|
{
|
|
|
|
|
uint32_t i;
|
|
|
|
|
for (i = 0; i < m_swapchain_images.size(); i++)
|
|
|
|
|
{
|
2021-03-12 14:19:59 +00:00
|
|
|
auto data = reinterpret_cast<wayland_image_data *>(m_swapchain_images[i].data);
|
2021-12-09 13:18:52 +00:00
|
|
|
if (data && data->buffer == wayl_buffer)
|
2021-01-31 20:09:53 +00:00
|
|
|
{
|
|
|
|
|
unpresent_image(i);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* check we found a buffer to unpresent */
|
|
|
|
|
assert(i < m_swapchain_images.size());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct wl_buffer_listener buffer_listener = { buffer_release };
|
|
|
|
|
|
2021-07-23 19:42:11 +01:00
|
|
|
VkResult swapchain::get_surface_compatible_formats(const VkImageCreateInfo &info,
|
|
|
|
|
util::vector<wsialloc_format> &importable_formats,
|
|
|
|
|
util::vector<uint64_t> &exportable_modifers)
|
2021-01-31 20:09:53 +00:00
|
|
|
{
|
2021-07-23 19:42:11 +01:00
|
|
|
/* Query supported modifers. */
|
|
|
|
|
util::vector<VkDrmFormatModifierPropertiesEXT> drm_format_props(
|
|
|
|
|
util::allocator(m_allocator, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
|
2022-11-24 11:24:34 +00:00
|
|
|
|
|
|
|
|
TRY_LOG(util::get_drm_format_properties(m_device_data.physical_device, info.format, drm_format_props),
|
|
|
|
|
"Failed to get format properties");
|
|
|
|
|
|
2021-07-23 19:42:11 +01:00
|
|
|
for (const auto &prop : drm_format_props)
|
|
|
|
|
{
|
|
|
|
|
bool is_supported = false;
|
|
|
|
|
drm_format_pair drm_format{ util::drm::vk_to_drm_format(info.format), prop.drmFormatModifier };
|
2022-03-18 12:05:46 +00:00
|
|
|
|
2021-07-23 19:42:11 +01:00
|
|
|
for (const auto &format : m_wsi_surface->get_formats())
|
|
|
|
|
{
|
|
|
|
|
if (format.fourcc == drm_format.fourcc && format.modifier == drm_format.modifier)
|
|
|
|
|
{
|
|
|
|
|
is_supported = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!is_supported)
|
|
|
|
|
{
|
|
|
|
|
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;
|
2022-11-24 11:24:34 +00:00
|
|
|
|
|
|
|
|
VkResult result = VK_SUCCESS;
|
2021-07-23 19:42:11 +01:00
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
|
2022-03-18 12:05:46 +00:00
|
|
|
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
|
|
|
|
VkImageCompressionControlEXT compression_control = {};
|
|
|
|
|
compression_control.sType = VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT;
|
2022-07-04 10:15:14 +01:00
|
|
|
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();
|
2022-03-18 12:05:46 +00:00
|
|
|
|
|
|
|
|
if (m_device_data.is_swapchain_compression_control_enabled())
|
|
|
|
|
{
|
|
|
|
|
compression_control.pNext = image_info.pNext;
|
|
|
|
|
image_info.pNext = &compression_control;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2021-07-23 19:42:11 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-01-31 20:09:53 +00:00
|
|
|
|
2021-07-23 19:42:11 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-21 15:28:09 +00:00
|
|
|
VkResult swapchain::allocate_wsialloc(VkImageCreateInfo &image_create_info, wayland_image_data *image_data,
|
2021-11-08 17:53:12 +00:00
|
|
|
util::vector<wsialloc_format> &importable_formats,
|
2021-09-23 15:35:51 +01:00
|
|
|
wsialloc_format *allocated_format)
|
|
|
|
|
{
|
|
|
|
|
bool is_protected_memory = (image_create_info.flags & VK_IMAGE_CREATE_PROTECTED_BIT) != 0;
|
2022-03-18 12:05:46 +00:00
|
|
|
uint64_t allocation_flags = is_protected_memory ? WSIALLOC_ALLOCATE_PROTECTED : 0;
|
|
|
|
|
|
|
|
|
|
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
2022-07-04 10:15:14 +01:00
|
|
|
if (m_image_compression_control_params.flags & VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT)
|
2022-03-18 12:05:46 +00:00
|
|
|
{
|
|
|
|
|
allocation_flags |= WSIALLOC_ALLOCATE_HIGHEST_FIXED_RATE_COMPRESSION;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2021-09-23 15:35:51 +01:00
|
|
|
wsialloc_allocate_info alloc_info = { importable_formats.data(), static_cast<unsigned>(importable_formats.size()),
|
2022-03-18 12:05:46 +00:00
|
|
|
image_create_info.extent.width, image_create_info.extent.height,
|
|
|
|
|
allocation_flags };
|
|
|
|
|
|
2024-05-23 14:53:26 +01:00
|
|
|
wsialloc_allocate_result alloc_result = { 0 };
|
|
|
|
|
/* Clear fds for error purposes */
|
|
|
|
|
for (int i = 0; i < WSIALLOC_MAX_PLANES; ++i)
|
|
|
|
|
{
|
|
|
|
|
alloc_result.buffer_fds[i] = -1;
|
|
|
|
|
}
|
|
|
|
|
const auto res = wsialloc_alloc(m_wsi_allocator, &alloc_info, &alloc_result);
|
2021-09-23 15:35:51 +01:00
|
|
|
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;
|
|
|
|
|
}
|
2024-05-23 14:53:26 +01:00
|
|
|
*allocated_format = alloc_result.format;
|
2022-10-21 15:28:09 +00:00
|
|
|
auto &external_memory = image_data->external_mem;
|
2024-05-23 14:53:26 +01:00
|
|
|
external_memory.set_strides(alloc_result.average_row_strides);
|
|
|
|
|
external_memory.set_buffer_fds(alloc_result.buffer_fds);
|
|
|
|
|
external_memory.set_offsets(alloc_result.offsets);
|
2023-02-16 09:44:58 +00:00
|
|
|
external_memory.set_memory_handle_type(VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
|
2021-09-23 15:35:51 +01:00
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-21 15:28:09 +00:00
|
|
|
static VkResult fill_image_create_info(VkImageCreateInfo &image_create_info,
|
|
|
|
|
util::vector<VkSubresourceLayout> &image_plane_layouts,
|
|
|
|
|
VkImageDrmFormatModifierExplicitCreateInfoEXT &drm_mod_info,
|
|
|
|
|
VkExternalMemoryImageCreateInfoKHR &external_info,
|
|
|
|
|
wayland_image_data &image_data, uint64_t modifier)
|
2021-07-23 19:42:11 +01:00
|
|
|
{
|
2022-11-24 11:24:34 +00:00
|
|
|
TRY_LOG_CALL(image_data.external_mem.fill_image_plane_layouts(image_plane_layouts));
|
2022-10-21 15:28:09 +00:00
|
|
|
|
|
|
|
|
if (image_data.external_mem.is_disjoint())
|
2021-03-12 14:19:59 +00:00
|
|
|
{
|
2022-10-21 15:28:09 +00:00
|
|
|
image_create_info.flags |= VK_IMAGE_CREATE_DISJOINT_BIT;
|
2021-03-12 14:19:59 +00:00
|
|
|
}
|
|
|
|
|
|
2022-10-21 15:28:09 +00:00
|
|
|
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, wayland_image_data *image_data, VkImage *image)
|
|
|
|
|
{
|
2021-07-23 19:42:11 +01:00
|
|
|
util::vector<wsialloc_format> importable_formats(util::allocator(m_allocator, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
|
2021-09-23 15:35:51 +01:00
|
|
|
auto &m_allocated_format = m_image_creation_parameters.m_allocated_format;
|
|
|
|
|
if (m_image_create_info.format != VK_FORMAT_UNDEFINED)
|
2021-03-12 14:19:59 +00:00
|
|
|
{
|
2021-09-23 15:35:51 +01:00
|
|
|
if (!importable_formats.try_push_back(m_allocated_format))
|
|
|
|
|
{
|
|
|
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
|
|
|
}
|
2022-11-24 11:24:34 +00:00
|
|
|
TRY_LOG_CALL(allocate_wsialloc(m_image_create_info, image_data, importable_formats, &m_allocated_format));
|
2021-01-31 20:09:53 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-09-23 15:35:51 +01:00
|
|
|
util::vector<uint64_t> exportable_modifiers(util::allocator(m_allocator, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
|
2022-11-24 11:24:34 +00:00
|
|
|
TRY_LOG_CALL(get_surface_compatible_formats(image_create_info, importable_formats, exportable_modifiers));
|
2021-09-23 15:35:51 +01:00
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
}
|
2021-07-23 19:42:11 +01:00
|
|
|
|
|
|
|
|
wsialloc_format allocated_format = { 0 };
|
2022-11-24 11:24:34 +00:00
|
|
|
TRY_LOG_CALL(allocate_wsialloc(image_create_info, image_data, importable_formats, &allocated_format));
|
2021-03-12 14:19:59 +00:00
|
|
|
|
2022-11-24 11:24:34 +00:00
|
|
|
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));
|
2021-01-31 20:09:53 +00:00
|
|
|
|
2021-09-23 15:35:51 +01:00
|
|
|
m_image_create_info = image_create_info;
|
|
|
|
|
m_allocated_format = allocated_format;
|
|
|
|
|
}
|
2022-10-21 15:28:09 +00:00
|
|
|
|
2022-11-24 11:24:34 +00:00
|
|
|
TRY_LOG(m_device_data.disp.CreateImage(m_device, &m_image_create_info, get_allocation_callbacks(), image),
|
|
|
|
|
"Image creation failed");
|
|
|
|
|
return VK_SUCCESS;
|
2021-01-31 20:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
2022-10-21 15:28:09 +00:00
|
|
|
VkResult swapchain::create_wl_buffer(const VkImageCreateInfo &image_create_info, swapchain_image &image,
|
|
|
|
|
wayland_image_data *image_data)
|
2021-01-31 20:09:53 +00:00
|
|
|
{
|
|
|
|
|
/* create a wl_buffer using the dma_buf protocol */
|
2021-11-12 13:31:02 +00:00
|
|
|
zwp_linux_buffer_params_v1 *params = zwp_linux_dmabuf_v1_create_params(m_wsi_surface->get_dmabuf_interface());
|
2021-12-07 17:25:30 +00:00
|
|
|
uint32_t modifier_hi = m_image_creation_parameters.m_allocated_format.modifier >> 32;
|
|
|
|
|
uint32_t modifier_low = m_image_creation_parameters.m_allocated_format.modifier & 0xFFFFFFFF;
|
2022-10-21 15:28:09 +00:00
|
|
|
for (uint32_t plane = 0; plane < image_data->external_mem.get_num_planes(); plane++)
|
2021-03-12 14:19:59 +00:00
|
|
|
{
|
2022-10-21 15:28:09 +00:00
|
|
|
zwp_linux_buffer_params_v1_add(params, image_data->external_mem.get_buffer_fds()[plane], plane,
|
|
|
|
|
image_data->external_mem.get_offsets()[plane],
|
|
|
|
|
image_data->external_mem.get_strides()[plane], modifier_hi, modifier_low);
|
2021-03-12 14:19:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto fourcc = util::drm::vk_to_drm_format(image_create_info.format);
|
2022-11-11 14:27:03 +00:00
|
|
|
assert(image_create_info.extent.width <= INT32_MAX);
|
|
|
|
|
assert(image_create_info.extent.height <= INT32_MAX);
|
2021-11-12 13:31:02 +00:00
|
|
|
image_data->buffer = zwp_linux_buffer_params_v1_create_immed(params, image_create_info.extent.width,
|
|
|
|
|
image_create_info.extent.height, fourcc, 0);
|
|
|
|
|
zwp_linux_buffer_params_v1_destroy(params);
|
2021-10-04 12:30:14 +01:00
|
|
|
|
2021-03-15 15:46:32 +00:00
|
|
|
wl_proxy_set_queue(reinterpret_cast<wl_proxy *>(image_data->buffer), m_buffer_queue);
|
2021-11-12 13:31:02 +00:00
|
|
|
auto res = wl_buffer_add_listener(image_data->buffer, &buffer_listener, this);
|
2021-01-31 20:09:53 +00:00
|
|
|
if (res < 0)
|
|
|
|
|
{
|
2021-03-15 15:46:32 +00:00
|
|
|
destroy_image(image);
|
|
|
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
2021-01-31 20:09:53 +00:00
|
|
|
}
|
2022-10-21 15:28:09 +00:00
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
2021-01-31 20:09:53 +00:00
|
|
|
|
2022-10-21 15:28:09 +00:00
|
|
|
VkResult swapchain::create_and_bind_swapchain_image(VkImageCreateInfo image_create_info, swapchain_image &image)
|
|
|
|
|
{
|
|
|
|
|
/* Create image_data */
|
|
|
|
|
auto image_data = m_allocator.create<wayland_image_data>(1, m_device, m_allocator);
|
|
|
|
|
if (image_data == nullptr)
|
2022-01-24 15:02:03 +00:00
|
|
|
{
|
2022-10-21 15:28:09 +00:00
|
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
2022-01-24 15:02:03 +00:00
|
|
|
}
|
2022-10-21 15:28:09 +00:00
|
|
|
|
|
|
|
|
std::unique_lock<std::recursive_mutex> image_status_lock(m_image_status_mutex);
|
|
|
|
|
image.data = image_data;
|
|
|
|
|
image.status = swapchain_image::FREE;
|
2022-11-24 11:24:34 +00:00
|
|
|
|
|
|
|
|
TRY_LOG(allocate_image(image_create_info, image_data, &image.image), "Failed to allocate image");
|
2022-10-21 15:28:09 +00:00
|
|
|
image_status_lock.unlock();
|
|
|
|
|
|
2022-11-24 11:24:34 +00:00
|
|
|
TRY_LOG(create_wl_buffer(image_create_info, image, image_data), "Failed to create wl_buffer");
|
2022-01-24 15:02:03 +00:00
|
|
|
|
2022-11-24 11:24:34 +00:00
|
|
|
TRY_LOG(image_data->external_mem.import_memory_and_bind_swapchain_image(image.image),
|
|
|
|
|
"Failed to import memory and bind swapchain image");
|
2022-01-24 15:02:03 +00:00
|
|
|
|
2021-01-31 20:09:53 +00:00
|
|
|
/* Initialize presentation fence. */
|
2021-09-01 22:30:31 +01:00
|
|
|
auto present_fence = sync_fd_fence_sync::create(m_device_data);
|
|
|
|
|
if (!present_fence.has_value())
|
2021-01-31 20:09:53 +00:00
|
|
|
{
|
2021-09-01 22:30:31 +01:00
|
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
2021-01-31 20:09:53 +00:00
|
|
|
}
|
2021-09-01 22:30:31 +01:00
|
|
|
image_data->present_fence = std::move(present_fence.value());
|
2021-03-15 15:46:32 +00:00
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
2021-01-31 20:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void swapchain::present_image(uint32_t pendingIndex)
|
|
|
|
|
{
|
|
|
|
|
int res;
|
|
|
|
|
wayland_image_data *image_data = reinterpret_cast<wayland_image_data *>(m_swapchain_images[pendingIndex].data);
|
2021-10-27 12:21:59 +01:00
|
|
|
|
2021-01-31 20:09:53 +00:00
|
|
|
/* if a frame is already pending, wait for a hint to present again */
|
2021-10-27 12:21:59 +01:00
|
|
|
if (!m_wsi_surface->wait_next_frame_event())
|
2021-01-31 20:09:53 +00:00
|
|
|
{
|
2021-09-22 11:15:26 +01:00
|
|
|
set_error_state(VK_ERROR_SURFACE_LOST_KHR);
|
2021-01-31 20:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wl_surface_attach(m_surface, image_data->buffer, 0, 0);
|
2021-09-01 22:30:31 +01:00
|
|
|
|
|
|
|
|
auto present_sync_fd = image_data->present_fence.export_sync_fd();
|
|
|
|
|
if (!present_sync_fd.has_value())
|
|
|
|
|
{
|
|
|
|
|
WSI_LOG_ERROR("Failed to export present fence.");
|
2021-09-22 11:15:26 +01:00
|
|
|
set_error_state(VK_ERROR_SURFACE_LOST_KHR);
|
2021-09-01 22:30:31 +01:00
|
|
|
}
|
|
|
|
|
else if (present_sync_fd->is_valid())
|
|
|
|
|
{
|
|
|
|
|
zwp_linux_surface_synchronization_v1_set_acquire_fence(m_wsi_surface->get_surface_sync_interface(),
|
|
|
|
|
present_sync_fd->get());
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-31 20:09:53 +00:00
|
|
|
/* TODO: work out damage */
|
|
|
|
|
wl_surface_damage(m_surface, 0, 0, INT32_MAX, INT32_MAX);
|
|
|
|
|
|
|
|
|
|
if (m_present_mode == VK_PRESENT_MODE_FIFO_KHR)
|
|
|
|
|
{
|
2021-10-27 12:21:59 +01:00
|
|
|
if (!m_wsi_surface->set_frame_callback())
|
2021-03-15 15:46:32 +00:00
|
|
|
{
|
2021-09-22 11:15:26 +01:00
|
|
|
set_error_state(VK_ERROR_SURFACE_LOST_KHR);
|
2021-01-31 20:09:53 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wl_surface_commit(m_surface);
|
|
|
|
|
res = wl_display_flush(m_display);
|
|
|
|
|
if (res < 0)
|
|
|
|
|
{
|
2021-03-23 10:24:43 +00:00
|
|
|
WSI_LOG_ERROR("error flushing the display");
|
2021-01-31 20:09:53 +00:00
|
|
|
/* Setting the swapchain as invalid */
|
2021-09-22 11:15:26 +01:00
|
|
|
set_error_state(VK_ERROR_SURFACE_LOST_KHR);
|
2021-01-31 20:09:53 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void swapchain::destroy_image(swapchain_image &image)
|
|
|
|
|
{
|
2021-05-27 14:57:53 +01:00
|
|
|
std::unique_lock<std::recursive_mutex> image_status_lock(m_image_status_mutex);
|
|
|
|
|
|
2021-01-31 20:09:53 +00:00
|
|
|
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;
|
|
|
|
|
}
|
2021-05-27 14:57:53 +01:00
|
|
|
|
|
|
|
|
image.status = swapchain_image::INVALID;
|
2021-01-31 20:09:53 +00:00
|
|
|
}
|
2021-05-27 14:57:53 +01:00
|
|
|
|
|
|
|
|
image_status_lock.unlock();
|
|
|
|
|
|
2021-01-31 20:09:53 +00:00
|
|
|
if (image.data != nullptr)
|
|
|
|
|
{
|
|
|
|
|
auto image_data = reinterpret_cast<wayland_image_data *>(image.data);
|
|
|
|
|
if (image_data->buffer != nullptr)
|
|
|
|
|
{
|
|
|
|
|
wl_buffer_destroy(image_data->buffer);
|
|
|
|
|
}
|
2021-03-12 14:19:59 +00:00
|
|
|
m_allocator.destroy(1, image_data);
|
2021-01-31 20:09:53 +00:00
|
|
|
image.data = nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool swapchain::free_image_found()
|
|
|
|
|
{
|
|
|
|
|
for (auto &img : m_swapchain_images)
|
|
|
|
|
{
|
|
|
|
|
if (img.status == swapchain_image::FREE)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkResult swapchain::get_free_buffer(uint64_t *timeout)
|
|
|
|
|
{
|
|
|
|
|
int ms_timeout, res;
|
|
|
|
|
|
|
|
|
|
if (*timeout >= INT_MAX * 1000llu * 1000llu)
|
|
|
|
|
{
|
|
|
|
|
ms_timeout = INT_MAX;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ms_timeout = *timeout / 1000llu / 1000llu;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The current dispatch_queue implementation will return if any
|
|
|
|
|
* events are returned, even if no events are dispatched to the buffer
|
|
|
|
|
* queue. Therefore dispatch repeatedly until a buffer has been freed.
|
|
|
|
|
*/
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
res = dispatch_queue(m_display, m_buffer_queue, ms_timeout);
|
|
|
|
|
} while (!free_image_found() && res > 0);
|
|
|
|
|
|
|
|
|
|
if (res > 0)
|
|
|
|
|
{
|
|
|
|
|
*timeout = 0;
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
else if (res == 0)
|
|
|
|
|
{
|
|
|
|
|
if (*timeout == 0)
|
|
|
|
|
{
|
|
|
|
|
return VK_NOT_READY;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return VK_TIMEOUT;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2023-04-18 10:58:09 +01:00
|
|
|
return VK_ERROR_SURFACE_LOST_KHR;
|
2021-01-31 20:09:53 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-09 16:04:28 +01:00
|
|
|
VkResult swapchain::image_set_present_payload(swapchain_image &image, VkQueue queue,
|
|
|
|
|
const queue_submit_semaphores &semaphores)
|
2021-09-01 22:30:31 +01:00
|
|
|
{
|
|
|
|
|
auto image_data = reinterpret_cast<wayland_image_data *>(image.data);
|
2024-04-09 16:04:28 +01:00
|
|
|
return image_data->present_fence.set_payload(queue, semaphores);
|
2021-09-01 22:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-23 15:35:51 +01:00
|
|
|
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<wayland_image_data *>(swapchain_image.data);
|
2022-10-21 15:28:09 +00:00
|
|
|
return image_data->external_mem.bind_swapchain_image_memory(bind_image_mem_info->image);
|
2021-09-23 15:35:51 +01:00
|
|
|
}
|
|
|
|
|
|
2021-01-31 20:09:53 +00:00
|
|
|
} // namespace wayland
|
|
|
|
|
} // namespace wsi
|