mirror of
https://gitlab.freedesktop.org/mesa/vulkan-wsi-layer.git
synced 2025-12-20 02:10:13 +01:00
Refactor framebuffer format support
Add support for format modifiers in framebuffers using drmModeAddFB2WithModifiers. Add compilation flag to force VK_KHR_display to not support format modifiers for framebuffers. Change-Id: Ie8eb2e96e543a15ab3534a7e73425f277a4b7d58 Signed-off-by: Dennis Wildmark <dennis.wildmark@arm.com>
This commit is contained in:
parent
23cd21c99c
commit
6c3f4e9326
10 changed files with 313 additions and 109 deletions
|
|
@ -58,6 +58,7 @@ option(BUILD_WSI_HEADLESS "Build with support for VK_EXT_headless_surface" ON)
|
|||
option(BUILD_WSI_WAYLAND "Build with support for VK_KHR_wayland_surface" OFF)
|
||||
option(BUILD_WSI_DISPLAY "Build with support for VK_KHR_display" OFF)
|
||||
option(BUILD_WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN "Build with support for VK_EXT_image_compression_control_swapchain" OFF)
|
||||
option(BUILD_WSI_DISPLAY_SUPPORT_FORMAT_MODIFIERS "Build with support for format modifiers in VK_KHR_display" ON)
|
||||
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")
|
||||
|
||||
|
|
@ -244,6 +245,12 @@ else()
|
|||
list(APPEND JSON_COMMANDS COMMAND sed -i '/VK_EXT_image_compression_control_swapchain/d' ${CMAKE_CURRENT_BINARY_DIR}/VkLayer_window_system_integration.json)
|
||||
endif()
|
||||
|
||||
if (BUILD_WSI_DISPLAY_SUPPORT_FORMAT_MODIFIERS)
|
||||
add_definitions("-DWSI_DISPLAY_SUPPORT_FORMAT_MODIFIERS=1")
|
||||
else()
|
||||
add_definitions("-DWSI_DISPLAY_SUPPORT_FORMAT_MODIFIERS=0")
|
||||
endif()
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} ${LINK_WSI_LIBS})
|
||||
|
||||
add_custom_target(manifest_json ALL COMMAND
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "drm_display.hpp"
|
||||
#include "util/custom_allocator.hpp"
|
||||
#include "wsi/surface.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
|
@ -33,6 +34,7 @@
|
|||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <mutex>
|
||||
#include <drm_fourcc.h>
|
||||
namespace wsi
|
||||
{
|
||||
|
||||
|
|
@ -42,15 +44,18 @@ namespace display
|
|||
const std::string default_dri_device_name{ "/dev/dri/card0" };
|
||||
|
||||
drm_display::drm_display(util::fd_owner drm_fd, int crtc_id, drm_connector_owner drm_connector,
|
||||
util::unique_ptr<util::vector<drm_format_pair>> supported_formats,
|
||||
util::unique_ptr<drm_display_mode> display_modes, size_t num_display_modes, uint32_t max_width,
|
||||
uint32_t max_height)
|
||||
uint32_t max_height, bool supports_fb_modifiers)
|
||||
: m_drm_fd(std::move(drm_fd))
|
||||
, m_crtc_id(crtc_id)
|
||||
, m_drm_connector(std::move(drm_connector))
|
||||
, m_supported_formats(std::move(supported_formats))
|
||||
, m_display_modes(std::move(display_modes))
|
||||
, m_num_display_modes(num_display_modes)
|
||||
, m_max_width(max_width)
|
||||
, m_max_height(max_height)
|
||||
, m_supports_fb_modifiers(supports_fb_modifiers)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -103,6 +108,100 @@ static int find_compatible_crtc(int fd, drm_resources_owner &resources, drm_conn
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
static bool find_primary_plane(const util::fd_owner &drm_fd, const drm_plane_resources_owner &plane_res,
|
||||
drm_plane_owner &primary_plane, uint32_t &primary_plane_index)
|
||||
{
|
||||
for (uint32_t i = 0; i < plane_res->count_planes; i++)
|
||||
{
|
||||
drm_plane_owner temp_plane{ drmModeGetPlane(drm_fd.get(), plane_res->planes[i]) };
|
||||
if (temp_plane != nullptr)
|
||||
{
|
||||
drm_object_properties_owner props{ drmModeObjectGetProperties(drm_fd.get(), plane_res->planes[i],
|
||||
DRM_MODE_OBJECT_PLANE) };
|
||||
if (props == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (uint32_t j = 0; j < props->count_props; j++)
|
||||
{
|
||||
drm_property_owner prop{ drmModeGetProperty(drm_fd.get(), props->props[j]) };
|
||||
if (prop == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(prop->name, "type"))
|
||||
{
|
||||
if (props->prop_values[j] == DRM_PLANE_TYPE_PRIMARY)
|
||||
{
|
||||
primary_plane = std::move(temp_plane);
|
||||
primary_plane_index = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool fill_supported_formats(const drm_plane_owner &primary_plane,
|
||||
util::vector<drm_format_pair> &supported_formats)
|
||||
{
|
||||
for (uint32_t i = 0; i < primary_plane->count_formats; i++)
|
||||
{
|
||||
if (!supported_formats.try_push_back(drm_format_pair{ primary_plane->formats[i], DRM_FORMAT_MOD_LINEAR }))
|
||||
{
|
||||
WSI_LOG_ERROR("Out of host memory.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool fill_supported_formats_with_modifiers(uint32_t primary_plane_index, const util::fd_owner &drm_fd,
|
||||
const drm_plane_resources_owner &plane_res,
|
||||
util::vector<drm_format_pair> &supported_formats)
|
||||
{
|
||||
drm_object_properties_owner object_properties{ drmModeObjectGetProperties(
|
||||
drm_fd.get(), plane_res->planes[primary_plane_index], DRM_MODE_OBJECT_PLANE) };
|
||||
if (object_properties == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < object_properties->count_props; i++)
|
||||
{
|
||||
drm_property_owner property{ drmModeGetProperty(drm_fd.get(), object_properties->props[i]) };
|
||||
if (property == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(property->name, "IN_FORMATS"))
|
||||
{
|
||||
drmModeFormatModifierIterator iter{};
|
||||
drm_property_blob_owner blob{ drmModeGetPropertyBlob(drm_fd.get(), object_properties->prop_values[i]) };
|
||||
if (blob == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
while (drmModeFormatModifierBlobIterNext(blob.get(), &iter))
|
||||
{
|
||||
if (!supported_formats.try_push_back(drm_format_pair{ iter.fmt, iter.mod }))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<drm_display> drm_display::make_display(const util::allocator &allocator, const char *drm_device)
|
||||
{
|
||||
util::fd_owner drm_fd{ open(drm_device, O_RDWR | O_CLOEXEC, 0) };
|
||||
|
|
@ -184,11 +283,66 @@ std::optional<drm_display> drm_display::make_display(const util::allocator &allo
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
/* Allow userspace to query native primary plane information */
|
||||
if (drmSetClientCap(drm_fd.get(), DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) != 0)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
drm_plane_resources_owner plane_res{ drmModeGetPlaneResources(drm_fd.get()) };
|
||||
if (plane_res == nullptr || plane_res->count_planes == 0)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
uint32_t primary_plane_index = std::numeric_limits<uint32_t>::max();
|
||||
drm_plane_owner primary_plane{ nullptr };
|
||||
|
||||
if (!find_primary_plane(drm_fd, plane_res, primary_plane, primary_plane_index))
|
||||
{
|
||||
WSI_LOG_ERROR("Failed to find primary plane for display.");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
assert(primary_plane != nullptr);
|
||||
assert(primary_plane_index != std::numeric_limits<uint32_t>::max());
|
||||
|
||||
bool supports_fb_modifiers = false;
|
||||
|
||||
#if WSI_DISPLAY_SUPPORT_FORMAT_MODIFIERS
|
||||
uint64_t addfb2_modifier_support = 0;
|
||||
if (drmGetCap(drm_fd.get(), DRM_CAP_ADDFB2_MODIFIERS, &addfb2_modifier_support) == 0)
|
||||
{
|
||||
supports_fb_modifiers = addfb2_modifier_support;
|
||||
}
|
||||
#endif
|
||||
|
||||
auto supported_formats = allocator.make_unique<util::vector<drm_format_pair>>(allocator);
|
||||
|
||||
if (supports_fb_modifiers)
|
||||
{
|
||||
if (!fill_supported_formats_with_modifiers(primary_plane_index, drm_fd, plane_res, *supported_formats))
|
||||
{
|
||||
/* Fall back to the linear formats */
|
||||
if (!fill_supported_formats(primary_plane, *supported_formats))
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!fill_supported_formats(primary_plane, *supported_formats))
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
std::copy(display_modes.begin(), display_modes.end(), display_modes_mem.get());
|
||||
|
||||
drm_display display{
|
||||
std::move(drm_fd), crtc_id, std::move(connector), std::move(display_modes_mem), display_modes.size(),
|
||||
max_width, max_height
|
||||
std::move(drm_fd), crtc_id, std::move(connector), std::move(supported_formats), std::move(display_modes_mem),
|
||||
display_modes.size(), max_width, max_height, supports_fb_modifiers
|
||||
};
|
||||
|
||||
return std::make_optional(std::move(display));
|
||||
|
|
@ -211,6 +365,26 @@ std::optional<drm_display> &drm_display::get_display()
|
|||
return display;
|
||||
}
|
||||
|
||||
const util::vector<drm_format_pair> *drm_display::get_supported_formats() const
|
||||
{
|
||||
return m_supported_formats.get();
|
||||
}
|
||||
|
||||
bool drm_display::is_format_supported(const drm_format_pair &format) const
|
||||
{
|
||||
auto supported_format =
|
||||
std::find_if(m_supported_formats->begin(), m_supported_formats->end(), [format](const auto &supported_format) {
|
||||
return format.fourcc == supported_format.fourcc && format.modifier == supported_format.modifier;
|
||||
});
|
||||
|
||||
return supported_format != m_supported_formats->end();
|
||||
}
|
||||
|
||||
bool drm_display::supports_fb_modifiers() const
|
||||
{
|
||||
return m_supports_fb_modifiers;
|
||||
}
|
||||
|
||||
drm_display_mode::drm_display_mode()
|
||||
: m_drm_mode_info{}
|
||||
, m_preferred(false)
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include "util/custom_allocator.hpp"
|
||||
#include "util/file_descriptor.hpp"
|
||||
#include "wsi/surface.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
|
|
@ -60,6 +61,7 @@ using drm_plane_owner = drm_owner<_drmModePlane, drmModeFreePlane>;
|
|||
using drm_plane_resources_owner = drm_owner<_drmModePlaneRes, drmModeFreePlaneResources>;
|
||||
using drm_object_properties_owner = drm_owner<_drmModeObjectProperties, drmModeFreeObjectProperties>;
|
||||
using drm_property_owner = drm_owner<_drmModeProperty, drmModeFreeProperty>;
|
||||
using drm_property_blob_owner = drm_owner<_drmModePropertyBlob, drmModeFreePropertyBlob>;
|
||||
|
||||
/**
|
||||
* @brief Owner class for an array of DRM GEM buffer handles.
|
||||
|
|
@ -249,6 +251,28 @@ public:
|
|||
*/
|
||||
drmModeResPtr get_drm_resources() const;
|
||||
|
||||
/**
|
||||
* @brief Get the supported formats for the display.
|
||||
*
|
||||
* @return Pointer to vector of supported formats.
|
||||
*/
|
||||
const util::vector<drm_format_pair> *get_supported_formats() const;
|
||||
|
||||
/**
|
||||
* @brief Query the display for support for adding framebuffers with format modifiers.
|
||||
*
|
||||
* @return true if supported, otherwise false.
|
||||
*/
|
||||
bool supports_fb_modifiers() const;
|
||||
|
||||
/**
|
||||
* @brief Query the display for support of a specific format and modifier combination.
|
||||
*
|
||||
* @param format The format to query support for.
|
||||
* @return true if the format is supported by the display, otherwise false.
|
||||
*/
|
||||
bool is_format_supported(const drm_format_pair &format) const;
|
||||
|
||||
/**
|
||||
* @brief Returns a CRTC compatible with this display's connector.
|
||||
*
|
||||
|
|
@ -273,8 +297,9 @@ private:
|
|||
* @param allocator The allocator that the display will use.
|
||||
*/
|
||||
drm_display(util::fd_owner drm_fd, int crtc_id, drm_connector_owner drm_connector,
|
||||
util::unique_ptr<util::vector<drm_format_pair>> supported_formats,
|
||||
util::unique_ptr<drm_display_mode> display_modes, size_t num_display_modes, uint32_t max_width,
|
||||
uint32_t max_height);
|
||||
uint32_t max_height, bool supports_fb_modifiers);
|
||||
|
||||
/**
|
||||
* @brief File descriptor for the display device.
|
||||
|
|
@ -291,6 +316,11 @@ private:
|
|||
*/
|
||||
drm_connector_owner m_drm_connector;
|
||||
|
||||
/**
|
||||
* @brief Vector of supported formats for use with the display.
|
||||
*/
|
||||
util::unique_ptr<util::vector<drm_format_pair>> m_supported_formats;
|
||||
|
||||
/**
|
||||
* @brief Pointer to available display modes for the connected display.
|
||||
*/
|
||||
|
|
@ -310,6 +340,11 @@ private:
|
|||
* @brief Maximum display resolution height.
|
||||
*/
|
||||
uint32_t m_max_height;
|
||||
|
||||
/**
|
||||
* @brief Flag to indicate if the display supports framebuffers with format modifiers.
|
||||
*/
|
||||
bool m_supports_fb_modifiers;
|
||||
};
|
||||
|
||||
} /* namespace display */
|
||||
|
|
|
|||
|
|
@ -35,8 +35,9 @@ namespace wsi
|
|||
namespace display
|
||||
{
|
||||
|
||||
surface::surface(drm_display_mode *display_mode)
|
||||
surface::surface(drm_display_mode *display_mode, VkExtent2D extent)
|
||||
: m_display_mode(display_mode)
|
||||
, m_extent(extent)
|
||||
, m_surface_properties(*this)
|
||||
{
|
||||
}
|
||||
|
|
@ -53,14 +54,9 @@ util::unique_ptr<swapchain_base> surface::allocate_swapchain(layer::device_priva
|
|||
return util::unique_ptr<swapchain_base>(alloc.make_unique<swapchain>(dev_data, allocator, *this));
|
||||
}
|
||||
|
||||
VkExtent2D surface::get_current_extent() const
|
||||
VkExtent2D surface::get_extent() const
|
||||
{
|
||||
return m_current_extent;
|
||||
}
|
||||
|
||||
void surface::set_current_extent(VkExtent2D extent)
|
||||
{
|
||||
m_current_extent = extent;
|
||||
return m_extent;
|
||||
}
|
||||
|
||||
drm_display_mode *surface::get_display_mode()
|
||||
|
|
|
|||
|
|
@ -40,18 +40,42 @@ namespace display
|
|||
class surface : public wsi::surface
|
||||
{
|
||||
public:
|
||||
surface(drm_display_mode *mode);
|
||||
/**
|
||||
* @brief Construct a new surface.
|
||||
*
|
||||
* @param mode The display mode to be used with the surface.
|
||||
* @param extent The extent of the surface.
|
||||
*/
|
||||
surface(drm_display_mode *mode, VkExtent2D extent);
|
||||
|
||||
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);
|
||||
/**
|
||||
* @brief Get the extent of the surface.
|
||||
*/
|
||||
VkExtent2D get_extent() const;
|
||||
|
||||
/**
|
||||
* @brief Get the display mode associated with this surface.
|
||||
*/
|
||||
drm_display_mode *get_display_mode();
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Pointer to the DRM display mode used with this surface.
|
||||
*/
|
||||
drm_display_mode *m_display_mode;
|
||||
VkExtent2D m_current_extent;
|
||||
|
||||
/**
|
||||
* @brief The extent of this surface.
|
||||
*/
|
||||
VkExtent2D m_extent;
|
||||
|
||||
/**
|
||||
* @brief Surface properties instance specific to this surface.
|
||||
*/
|
||||
surface_properties m_surface_properties;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -54,9 +54,9 @@ VkResult surface_properties::get_surface_capabilities(VkPhysicalDevice physical_
|
|||
|
||||
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();
|
||||
pSurfaceCapabilities->currentExtent = m_specific_surface->get_extent();
|
||||
pSurfaceCapabilities->minImageExtent = m_specific_surface->get_extent();
|
||||
pSurfaceCapabilities->maxImageExtent = m_specific_surface->get_extent();
|
||||
}
|
||||
|
||||
/* Image count limits */
|
||||
|
|
@ -80,73 +80,18 @@ VkResult surface_properties::get_surface_formats(VkPhysicalDevice physical_devic
|
|||
return VK_ERROR_SURFACE_LOST_KHR;
|
||||
}
|
||||
|
||||
int drm_fd = display->get_drm_fd();
|
||||
if (drm_fd == -1)
|
||||
{
|
||||
return VK_ERROR_SURFACE_LOST_KHR;
|
||||
}
|
||||
/* Allow userspace to query native primary plane information */
|
||||
if (drmSetClientCap(drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) != 0)
|
||||
{
|
||||
return VK_ERROR_SURFACE_LOST_KHR;
|
||||
}
|
||||
|
||||
drm_plane_resources_owner plane_res{ drmModeGetPlaneResources(drm_fd) };
|
||||
if (plane_res == nullptr || plane_res->count_planes == 0)
|
||||
{
|
||||
return VK_ERROR_SURFACE_LOST_KHR;
|
||||
}
|
||||
|
||||
/* Look for the primary plane */
|
||||
drm_plane_owner plane{ nullptr };
|
||||
for (uint32_t i = 0; i < plane_res->count_planes; i++)
|
||||
{
|
||||
drm_plane_owner temp_plane{ drmModeGetPlane(drm_fd, plane_res->planes[i]) };
|
||||
if (temp_plane != nullptr)
|
||||
{
|
||||
drm_object_properties_owner props{ drmModeObjectGetProperties(drm_fd, plane_res->planes[i],
|
||||
DRM_MODE_OBJECT_PLANE) };
|
||||
if (props != nullptr)
|
||||
{
|
||||
auto props_end = props->props + props->count_props;
|
||||
auto prop = std::find_if(props->props, props_end, [drm_fd](auto &property_id) {
|
||||
drm_property_owner prop{ drmModeGetProperty(drm_fd, property_id) };
|
||||
if (prop != nullptr && !strcmp(prop->name, "type"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if (prop != props_end)
|
||||
{
|
||||
auto index = std::distance(props->props, prop);
|
||||
if (props->prop_values[index] == DRM_PLANE_TYPE_PRIMARY)
|
||||
{
|
||||
plane = std::move(temp_plane);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (plane == nullptr)
|
||||
{
|
||||
WSI_LOG_ERROR("Failed to find primary plane.");
|
||||
return VK_ERROR_SURFACE_LOST_KHR;
|
||||
}
|
||||
auto display_formats = display->get_supported_formats();
|
||||
|
||||
uint32_t format_count = 0;
|
||||
|
||||
/* If this happens, it is just wrong */
|
||||
assert(plane->count_formats > 0);
|
||||
assert(plane->count_formats <= max_core_1_0_formats);
|
||||
assert(display_formats->size() > 0);
|
||||
assert(display_formats->size() <= max_core_1_0_formats);
|
||||
|
||||
std::array<surface_format_properties, max_core_1_0_formats> formats{};
|
||||
|
||||
for (uint32_t i = 0; i < plane->count_formats; ++i)
|
||||
for (const auto &drm_format : *display_formats)
|
||||
{
|
||||
auto vk_format = util::drm::drm_to_vk_format(plane->formats[i]);
|
||||
auto vk_format = util::drm::drm_to_vk_format(drm_format.fourcc);
|
||||
if (VK_FORMAT_UNDEFINED != vk_format)
|
||||
{
|
||||
formats[format_count] = surface_format_properties{ vk_format };
|
||||
|
|
@ -174,7 +119,7 @@ VkResult surface_properties::get_surface_formats(VkPhysicalDevice physical_devic
|
|||
* The colorSpace value is how the presentation engine interprets the format.
|
||||
* The linearity of VkFormat and the display format may be different.
|
||||
*/
|
||||
auto vk_srgb_format = util::drm::drm_to_vk_srgb_format(plane->formats[i]);
|
||||
auto vk_srgb_format = util::drm::drm_to_vk_srgb_format(drm_format.fourcc);
|
||||
if (VK_FORMAT_UNDEFINED != vk_srgb_format)
|
||||
{
|
||||
formats[format_count] = surface_format_properties{ vk_srgb_format };
|
||||
|
|
@ -263,17 +208,16 @@ CreateDisplayPlaneSurfaceKHR(VkInstance instance, const VkDisplaySurfaceCreateIn
|
|||
|
||||
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 wsi_surface = allocator.make_unique<surface>(display_mode, pCreateInfo->imageExtent);
|
||||
if (wsi_surface == nullptr)
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
auto surface_base = util::unique_ptr<wsi::surface>(std::move(wsi_surface));
|
||||
res = instance_data.add_surface(*pSurface, surface_base);
|
||||
if (res != VK_SUCCESS)
|
||||
|
|
|
|||
|
|
@ -108,12 +108,18 @@ VkResult swapchain::get_surface_compatible_formats(const VkImageCreateInfo &info
|
|||
TRY_LOG(util::get_drm_format_properties(m_device_data.physical_device, info.format, drm_format_props),
|
||||
"Failed to get format properties");
|
||||
|
||||
auto &display = drm_display::get_display();
|
||||
if (!display.has_value())
|
||||
{
|
||||
WSI_LOG_ERROR("DRM display not available.");
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
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))
|
||||
if (!display->is_format_supported(drm_format))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -315,6 +321,9 @@ VkResult swapchain::create_framebuffer(const VkImageCreateInfo &image_create_inf
|
|||
{
|
||||
VkResult ret_code = VK_SUCCESS;
|
||||
std::array<uint32_t, util::MAX_PLANES> strides{ 0, 0, 0, 0 };
|
||||
std::array<uint64_t, util::MAX_PLANES> modifiers{ 0, 0, 0, 0 };
|
||||
const drm_format_pair allocated_format{ m_image_creation_parameters.m_allocated_format.fourcc,
|
||||
m_image_creation_parameters.m_allocated_format.modifier };
|
||||
|
||||
auto &display = drm_display::get_display();
|
||||
if (!display.has_value())
|
||||
|
|
@ -330,6 +339,7 @@ VkResult swapchain::create_framebuffer(const VkImageCreateInfo &image_create_inf
|
|||
{
|
||||
assert(image_data->external_mem.get_strides()[plane] > 0);
|
||||
strides[plane] = image_data->external_mem.get_strides()[plane];
|
||||
modifiers[plane] = allocated_format.modifier;
|
||||
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));
|
||||
|
|
@ -337,9 +347,26 @@ VkResult swapchain::create_framebuffer(const VkImageCreateInfo &image_create_inf
|
|||
}
|
||||
}
|
||||
|
||||
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 (!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())
|
||||
{
|
||||
error = drmModeAddFB2WithModifiers(
|
||||
display->get_drm_fd(), image_create_info.extent.width, image_create_info.extent.height,
|
||||
allocated_format.fourcc, buffer_handles.data(), strides.data(), image_data->external_mem.get_offsets().data(),
|
||||
modifiers.data(), &image_data->fb_id, DRM_MODE_FB_MODIFIERS);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = drmModeAddFB2(display->get_drm_fd(), image_create_info.extent.width, image_create_info.extent.height,
|
||||
allocated_format.fourcc, buffer_handles.data(), strides.data(),
|
||||
image_data->external_mem.get_offsets().data(), &image_data->fb_id, 0);
|
||||
}
|
||||
|
||||
if (error != 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -75,12 +75,6 @@ struct image_creation_parameters
|
|||
}
|
||||
};
|
||||
|
||||
struct drm_format_pair
|
||||
{
|
||||
uint32_t fourcc;
|
||||
uint64_t modifier;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Display swapchain class.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Arm Limited.
|
||||
* Copyright (c) 2021, 2024 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
|
|
@ -36,6 +36,15 @@
|
|||
namespace wsi
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Struct describing a DRM format with modifier.
|
||||
*/
|
||||
struct drm_format_pair
|
||||
{
|
||||
uint32_t fourcc;
|
||||
uint64_t modifier;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A generic WSI representation of a VkSurface.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Arm Limited.
|
||||
* Copyright (c) 2021, 2024 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
|
|
@ -40,12 +40,6 @@ namespace wsi
|
|||
namespace wayland
|
||||
{
|
||||
|
||||
struct drm_format_pair
|
||||
{
|
||||
uint32_t fourcc;
|
||||
uint64_t modifier;
|
||||
};
|
||||
|
||||
/**
|
||||
* Wayland callback for global wl_registry events to handle global objects required by @ref wsi::wayland::surface
|
||||
*/
|
||||
|
|
@ -60,7 +54,7 @@ public:
|
|||
struct init_parameters;
|
||||
|
||||
/** Constructor to allow for custom allocation, but require privately defined arguments. */
|
||||
surface(const init_parameters&);
|
||||
surface(const init_parameters &);
|
||||
|
||||
/**
|
||||
* @brief Allocates and initializes a surface
|
||||
|
|
@ -109,7 +103,7 @@ public:
|
|||
*
|
||||
* The raw pointer is valid for the lifetime of the surface.
|
||||
*/
|
||||
zwp_linux_surface_synchronization_v1* get_surface_sync_interface()
|
||||
zwp_linux_surface_synchronization_v1 *get_surface_sync_interface()
|
||||
{
|
||||
return surface_sync_interface.get();
|
||||
}
|
||||
|
|
@ -166,7 +160,7 @@ private:
|
|||
|
||||
/** Container for the zwp_linux_explicit_synchronization_v1 interface binding */
|
||||
wayland_owner<zwp_linux_explicit_synchronization_v1> explicit_sync_interface;
|
||||
/** Container for the surface specific zwp_linux_surface_synchronization_v1 interface. */
|
||||
/** Container for the surface specific zwp_linux_surface_synchronization_v1 interface. */;
|
||||
wayland_owner<zwp_linux_surface_synchronization_v1> surface_sync_interface;
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue