From b02486ff87a9b60b95d9ee263a159b75db25ab12 Mon Sep 17 00:00:00 2001 From: Iason Paraskevopoulos Date: Thu, 23 May 2024 14:53:26 +0100 Subject: [PATCH] Extend wsialloc_alloc with disjoint information Extends wsialloc_alloc to return whether or not the allocation will be disjoint. Groups wsialloc_alloc's return values to a struct. Change-Id: I7542e37d8af16ce7989ab235c02305d562f3c667 Signed-off-by: Iason Paraskevopoulos --- util/wsialloc/wsialloc.h | 82 ++++++++++++++++++++++-------------- util/wsialloc/wsialloc_ion.c | 34 ++++++++------- wsi/external_memory.hpp | 17 +++++++- wsi/wayland/swapchain.cpp | 21 +++++---- 4 files changed, 97 insertions(+), 57 deletions(-) diff --git a/util/wsialloc/wsialloc.h b/util/wsialloc/wsialloc.h index 2358130..7f71fc1 100644 --- a/util/wsialloc/wsialloc.h +++ b/util/wsialloc/wsialloc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, 2021-2022 Arm Limited. + * Copyright (c) 2017-2024 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -31,7 +31,12 @@ #define _WSIALLOC_H_ #include +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" #include +#pragma GCC diagnostic pop #ifdef __cplusplus extern "C" { @@ -57,9 +62,10 @@ extern "C" { * Version History: * 1 - Initial wsialloc interface * 2 - Added WSIALLOC_ALLOCATE_HIGHEST_FIXED_RATE_COMPRESSION + * 3 - Grouped the return values of wsialloc_alloc to wsialloc_allocate_result and added another value for returning + * whether or not the allocation will be disjoint. */ - -#define WSIALLOC_INTERFACE_VERSION 2 +#define WSIALLOC_INTERFACE_VERSION 3 #define WSIALLOC_CONCAT(x, y) x##y #define WSIALLOC_SYMBOL_VERSION(symbol, version) WSIALLOC_CONCAT(symbol, version) @@ -152,70 +158,82 @@ enum wsialloc_allocate_flag typedef struct wsialloc_format { - uint32_t fourcc; /**< The DRM_FORMAT_<...> code */ + uint32_t fourcc; /**< The DRM_FORMAT_<...> code */ uint64_t modifier; /**< DRM modifier applied to all planes. */ - uint64_t flags; /**< Set of @r wsialloc_format_flag format flags. */ + uint64_t flags; /**< Set of @r wsialloc_format_flag format flags. */ } wsialloc_format; typedef struct wsialloc_allocate_info { - wsialloc_format *formats; /** List of formats to select from for the allocation */ - unsigned format_count; /** Number of elements in formats array */ - uint32_t width; /** The number of pixel columns required in the buffer. */ - uint32_t height; /** The number of pixel rows required in the buffer. */ - uint64_t flags; /** Set of @r wsialloc_allocate_flag allocation flags. */ + wsialloc_format *formats; /** List of formats to select from for the allocation. */ + unsigned format_count; /** Number of elements in formats array. */ + uint32_t width; /** The number of pixel columns required in the buffer. */ + uint32_t height; /** The number of pixel rows required in the buffer. */ + uint64_t flags; /** Set of @r wsialloc_allocate_flag allocation flags. */ } wsialloc_allocate_info; +typedef struct wsialloc_allocate_result +{ + wsialloc_format format; /** The selected format for allocation. */ + /** Per plane distance between rows of blocks divided by the block height measured in bytes. */ + int average_row_strides[WSIALLOC_MAX_PLANES]; + /** Per plane offset into the file descriptor for the start of the plane. */ + uint32_t offsets[WSIALLOC_MAX_PLANES]; + int buffer_fds[WSIALLOC_MAX_PLANES]; /** Per plane file descriptor for the buffer. */ + bool is_disjoint; /** Whether different fds will be used for each plane. */ +} wsialloc_allocate_result; + /** * @brief Allocate a buffer from the WSI Allocator * * Allocate a buffer of size @p info::width x @p info::height in a way that is suitable for the underlying * window system and GPU. * - * The allocation is made using a format from the list specified in @p info::formats . On success, @p format is set with + * The allocation is made using a format from the list specified in @p info::formats . On success, @p result::format is set with * the selected format that was used for the allocation. * * Each plane is returned as a file descriptor. All other information returned about the buffer is also per-plane. It is - * assumed the caller already knows how many planes are implied by the @p format that was selected. + * assumed the caller already knows how many planes are implied by the @p result::format that was selected. * * Each row in the buffer may be larger than @p info::width to account for buffer alignment requirements in the - * underlying window system. @p strides must be examined to determine the number of bytes between subsequent rows - * in each of the buffer's planes. Only positive strides are allowed. + * underlying window system. @p result::average_row_strides must be examined to determine the number of bytes between + * subsequent rows in each of the buffer's planes. Only positive average_row_strides are allowed. * - * The client may free the buffer's planes by invoking close() on some or all of the elements of @p buffer_fds + * The client may free the buffer's planes by invoking close() on some or all of the elements of @p result::buffer_fds * - * The same file descriptor ('fd') may be written to different elements of @p buffer_fds more than once, for some or all + * The same file descriptor ('fd') may be written to different elements of @p result::buffer_fds more than once, for some or all * of the planes. In this case: - * - @p offsets @b must be used to determine where each plane starts in the file descriptor - * - When the client frees the buffer, each unique fd in @p buffer_fds must only be closed once. + * - @p result::offsets @b must be used to determine where each plane starts in the file descriptor + * - When the client frees the buffer, each unique fd in @p result::buffer_fds must only be closed once. * - * Even if @p buffer_fds are all different or @p format is for a single plane, then the client must inspect @p offsets - * in case it contains non-zero values. + * Even if @p result::buffer_fds are all different or @p result::format is for a single plane, then the client must inspect + * @p result::offsets in case it contains non-zero values. * - * @note The implementation might not export the file descriptors in @p buffer_fds in such a way that allows the client + * If @p result::buffer_fds are different then @p result::disjoint should be set to true. + * + * @note The implementation might not export the file descriptors in @p result::buffer_fds in such a way that allows the client * to directly map them on the CPU as writable (PROT_WRITE). * - * The selected @p format modifier allows for a fourcc_mod_code() (as defined in drm_fourcc.h) to define + * The selected @p result::format modifier allows for a fourcc_mod_code() (as defined in drm_fourcc.h) to define * a reordering or other modification of the data in the buffer's planes (e.g. compression, * change in number of planes, etc). * - * @p strides is the per plane row byte stride of the @p format. For linear formats this is the number of bytes from the - * start of a row to the start of the next row. For block based formats it is the number of bytes from the start of one - * row of blocks to the start of the next. It may also have format specific meaning for formats not in those categories. + * @p result::average_row_strides are per plane row average byte strides of the @p result::format. This is the number of bytes from the + * start of a row of blocks divided by the block height. It may also have format specific meaning for formats not in those + * categories. * - * @p strides and @p offsets may have modifier-specific meaning when a @p format with modifier is selected. + * @p result::average_row_strides and @p result::offsets may have modifier-specific + * meaning when a @p result::format with modifier is selected. * - * @pre @p strides, @p buffer_fds, @p offsets are pointers to storage large enough to hold per-plane information + * @pre @p result::average_row_strides, @p result::buffer_fds, @p result::offsets + * are pointers to storage large enough to hold per-plane information. * @pre @p info::width >=1 && @p info::height >= 1 * @pre @p allocator is a currently valid WSI Allocator from wsialloc_new() * @post The allocated buffer will be zeroed. * * @param allocator The WSI Allocator to allocate from. * @param[in] info The requested allocation information. - * @param[out] format The selected format for allocation. - * @param[out] strides Per-plane row byte stride of the buffer. - * @param[out] buffer_fds Per-plane file descriptors for the buffer. - * @param[out] offsets Per-plane offset into the file descriptor for the start of the plane. + * @param[out] result The allocation's result. * @retval WSIALLOC_ERROR_NONE on successful buffer allocation. * @retval WSIALLOC_ERROR_INVALID is returned for invalid parameters. @@ -226,7 +244,7 @@ typedef struct wsialloc_allocate_info */ wsialloc_error wsialloc_alloc(wsialloc_allocator *allocator, const wsialloc_allocate_info *info, - wsialloc_format *format, int *strides, int *buffer_fds, uint32_t *offsets); + wsialloc_allocate_result *result); #ifdef __cplusplus } diff --git a/util/wsialloc/wsialloc_ion.c b/util/wsialloc/wsialloc_ion.c index 7a450ab..5fe79c1 100644 --- a/util/wsialloc/wsialloc_ion.c +++ b/util/wsialloc/wsialloc_ion.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, 2021-2022 Arm Limited. + * Copyright (c) 2017-2024 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -44,7 +44,7 @@ * * This should only be increased when this implementation is updated to match newer versions of wsialloc.h. */ -#define WSIALLOC_IMPLEMENTATION_VERSION 2 +#define WSIALLOC_IMPLEMENTATION_VERSION 3 /* Ensure we are implementing the wsialloc version matching the wsialloc.h header we are using. */ #if WSIALLOC_IMPLEMENTATION_VERSION != WSIALLOC_INTERFACE_VERSION @@ -81,7 +81,8 @@ static int find_alloc_heap_id(int fd) struct ion_heap_data heaps[ION_NUM_HEAP_IDS]; struct ion_heap_query query = { - .cnt = ION_NUM_HEAP_IDS, .heaps = (uint64_t)(uintptr_t)heaps, + .cnt = ION_NUM_HEAP_IDS, + .heaps = (uint64_t)(uintptr_t)heaps, }; int ret = ioctl(fd, ION_IOC_HEAP_QUERY, &query); @@ -109,7 +110,9 @@ static int allocate(int fd, size_t size, uint32_t heap_id) assert(fd != -1); struct ion_allocation_data alloc = { - .len = size, .heap_id_mask = 1u << heap_id, .flags = 0, + .len = size, + .heap_id_mask = 1u << heap_id, + .flags = 0, }; int ret = ioctl(fd, ION_IOC_ALLOC, &alloc); if (ret < 0) @@ -281,13 +284,13 @@ static const fmt_spec *find_format(uint32_t fourcc) } static bool validate_parameters(const wsialloc_allocator *allocator, const wsialloc_allocate_info *info, - const wsialloc_format *format, const int *strides, const uint32_t *offsets) + wsialloc_allocate_result *result) { if (allocator == NULL) { return false; } - else if (!strides || !offsets) + else if (!result) { return false; } @@ -304,15 +307,13 @@ static bool validate_parameters(const wsialloc_allocator *allocator, const wsial } wsialloc_error wsialloc_alloc(wsialloc_allocator *allocator, const wsialloc_allocate_info *info, - wsialloc_format *format, int *strides, int *buffer_fds, uint32_t *offsets) + wsialloc_allocate_result *result) { assert(allocator != NULL); assert(info != NULL); - assert(format != NULL); - assert(strides != NULL); - assert(offsets != NULL); + assert(result != NULL); - if (!validate_parameters(allocator, info, format, strides, offsets)) + if (!validate_parameters(allocator, info, result)) { return WSIALLOC_ERROR_INVALID; } @@ -355,13 +356,16 @@ wsialloc_error wsialloc_alloc(wsialloc_allocator *allocator, const wsialloc_allo if (err == WSIALLOC_ERROR_NONE) { - *format = selected_format_desc.format; - *strides = local_strides[0]; - *offsets = local_offsets[0]; + result->format = selected_format_desc.format; + result->average_row_strides[0] = local_strides[0]; + result->offsets[0] = local_offsets[0]; if (!(info->flags & WSIALLOC_ALLOCATE_NO_MEMORY)) { - *buffer_fds = local_fds[0]; + result->buffer_fds[0] = local_fds[0]; } + + result->is_disjoint = false; } + return err; } diff --git a/wsi/external_memory.hpp b/wsi/external_memory.hpp index 1bfa5b5..44efdc1 100644 --- a/wsi/external_memory.hpp +++ b/wsi/external_memory.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Arm Limited. + * Copyright (c) 2022-2024 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -82,6 +82,11 @@ public: m_buffer_fds = buffer_fds; } + void set_buffer_fds(const int *buffer_fds) + { + std::copy(buffer_fds, buffer_fds + MAX_PLANES, m_buffer_fds.begin()); + } + /** * @brief Set the per plane stride values. */ @@ -90,6 +95,11 @@ public: m_strides = strides; } + void set_strides(const int *strides) + { + std::copy(strides, strides + MAX_PLANES, m_strides.begin()); + } + /** * @brief Set the per plane offset values. */ @@ -98,6 +108,11 @@ public: m_offsets = offsets; } + void set_offsets(const uint32_t *offsets) + { + std::copy(offsets, offsets + MAX_PLANES, m_offsets.begin()); + } + /** * @brief Get the number of planes the external format uses. */ diff --git a/wsi/wayland/swapchain.cpp b/wsi/wayland/swapchain.cpp index 950f318..112dbce 100644 --- a/wsi/wayland/swapchain.cpp +++ b/wsi/wayland/swapchain.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, 2021-2023 Arm Limited. + * Copyright (c) 2017-2019, 2021-2024 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -273,11 +273,13 @@ VkResult swapchain::allocate_wsialloc(VkImageCreateInfo &image_create_info, wayl image_create_info.extent.width, image_create_info.extent.height, allocation_flags }; - std::array strides{}; - std::array buffer_fds{ -1, -1, -1, -1 }; - std::array offsets{}; - const auto res = - wsialloc_alloc(m_wsi_allocator, &alloc_info, allocated_format, strides.data(), buffer_fds.data(), offsets.data()); + 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); if (res != WSIALLOC_ERROR_NONE) { WSI_LOG_ERROR("Failed allocation of DMA Buffer. WSI error: %d", static_cast(res)); @@ -287,10 +289,11 @@ VkResult swapchain::allocate_wsialloc(VkImageCreateInfo &image_create_info, wayl } return VK_ERROR_OUT_OF_HOST_MEMORY; } + *allocated_format = alloc_result.format; 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_strides(alloc_result.average_row_strides); + external_memory.set_buffer_fds(alloc_result.buffer_fds); + external_memory.set_offsets(alloc_result.offsets); external_memory.set_memory_handle_type(VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); return VK_SUCCESS; }