mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-20 16:00:08 +01:00
wsi/display: Expose HDR10 colorspace based on EDID
Uses libdisplay-info to parse the edid, grab the metadata and see if HDR10 is supported by the display. Reviewed-by: Emma Anholt <emma@anholt.net> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35461>
This commit is contained in:
parent
2c870bbe20
commit
13137393f6
2 changed files with 122 additions and 6 deletions
|
|
@ -55,7 +55,7 @@ if with_platform_wayland
|
||||||
vulkan_wsi_list += '-DVK_USE_PLATFORM_WAYLAND_KHR'
|
vulkan_wsi_list += '-DVK_USE_PLATFORM_WAYLAND_KHR'
|
||||||
endif
|
endif
|
||||||
if system_has_kms_drm and not with_platform_android
|
if system_has_kms_drm and not with_platform_android
|
||||||
vulkan_wsi_deps += [dep_libdrm]
|
vulkan_wsi_deps += [dep_libdrm, dep_display_info]
|
||||||
vulkan_wsi_list += '-DVK_USE_PLATFORM_DISPLAY_KHR'
|
vulkan_wsi_list += '-DVK_USE_PLATFORM_DISPLAY_KHR'
|
||||||
endif
|
endif
|
||||||
if with_xlib_lease
|
if with_xlib_lease
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,12 @@
|
||||||
#include "wsi_common_display.h"
|
#include "wsi_common_display.h"
|
||||||
#include "wsi_common_queue.h"
|
#include "wsi_common_queue.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBDISPLAY_INFO
|
||||||
|
#include "libdisplay-info/info.h"
|
||||||
|
#include "libdisplay-info/edid.h"
|
||||||
|
#include "libdisplay-info/cta.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#define wsi_display_debug(...) fprintf(stderr, __VA_ARGS__)
|
#define wsi_display_debug(...) fprintf(stderr, __VA_ARGS__)
|
||||||
#define wsi_display_debug_code(...) __VA_ARGS__
|
#define wsi_display_debug_code(...) __VA_ARGS__
|
||||||
|
|
@ -149,6 +155,11 @@ enum colorspace_enum {
|
||||||
COLORSPACE_ENUM_MAX,
|
COLORSPACE_ENUM_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct wsi_display_connector_metadata {
|
||||||
|
VkHdrMetadataEXT hdr_metadata;
|
||||||
|
bool supports_st2084;
|
||||||
|
} wsi_display_connector_metadata;
|
||||||
|
|
||||||
typedef struct wsi_display_connector {
|
typedef struct wsi_display_connector {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct wsi_display *wsi;
|
struct wsi_display *wsi;
|
||||||
|
|
@ -170,6 +181,7 @@ typedef struct wsi_display_connector {
|
||||||
#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
|
#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
|
||||||
xcb_randr_output_t output;
|
xcb_randr_output_t output;
|
||||||
#endif
|
#endif
|
||||||
|
struct wsi_display_connector_metadata metadata;
|
||||||
} wsi_display_connector;
|
} wsi_display_connector;
|
||||||
|
|
||||||
struct wsi_display {
|
struct wsi_display {
|
||||||
|
|
@ -198,6 +210,65 @@ struct wsi_display {
|
||||||
uint64_t color_outcome_serial_counter;
|
uint64_t color_outcome_serial_counter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
wsi_display_parse_edid(struct wsi_display_connector *connector, drmModePropertyBlobRes *blob)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_LIBDISPLAY_INFO
|
||||||
|
struct wsi_display_connector_metadata *metadata = &connector->metadata;
|
||||||
|
struct di_info *info = di_info_parse_edid(blob->data, blob->length);
|
||||||
|
|
||||||
|
if (!info) {
|
||||||
|
fprintf(stderr, "wsi_display_parse_edid: Failed to parse edid. Reason: %s\n", di_info_get_failure_msg(info));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct di_edid *edid = di_info_get_edid(info);
|
||||||
|
|
||||||
|
const struct di_edid_chromaticity_coords *chroma = di_edid_get_chromaticity_coords(edid);
|
||||||
|
const struct di_cta_hdr_static_metadata_block *hdr_static_metadata = NULL;
|
||||||
|
const struct di_cta_colorimetry_block *colorimetry = NULL;
|
||||||
|
|
||||||
|
const struct di_edid_cta *cta = NULL;
|
||||||
|
const struct di_edid_ext * const *exts = di_edid_get_extensions(edid);
|
||||||
|
for (; *exts != NULL; exts++) {
|
||||||
|
if ((cta = di_edid_ext_get_cta(*exts)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cta) {
|
||||||
|
const struct di_cta_data_block * const * blocks = di_edid_cta_get_data_blocks(cta);
|
||||||
|
for (; *blocks != NULL; blocks++) {
|
||||||
|
if (!hdr_static_metadata && (hdr_static_metadata = di_cta_data_block_get_hdr_static_metadata(*blocks)))
|
||||||
|
continue;
|
||||||
|
if (!colorimetry && (colorimetry = di_cta_data_block_get_colorimetry(*blocks)))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chroma) {
|
||||||
|
metadata->hdr_metadata.displayPrimaryRed = (VkXYColorEXT){ chroma->red_x, chroma->red_y };
|
||||||
|
metadata->hdr_metadata.displayPrimaryGreen = (VkXYColorEXT){ chroma->green_x, chroma->green_y };
|
||||||
|
metadata->hdr_metadata.displayPrimaryBlue = (VkXYColorEXT){ chroma->blue_x, chroma->blue_y };
|
||||||
|
metadata->hdr_metadata.whitePoint = (VkXYColorEXT){ chroma->white_x, chroma->white_y };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hdr_static_metadata) {
|
||||||
|
metadata->hdr_metadata.maxFrameAverageLightLevel = hdr_static_metadata->desired_content_max_frame_avg_luminance;
|
||||||
|
metadata->hdr_metadata.minLuminance = hdr_static_metadata->desired_content_min_luminance;
|
||||||
|
metadata->hdr_metadata.maxLuminance = hdr_static_metadata->desired_content_max_luminance;
|
||||||
|
/* To be filled in by the app based on the scene, default to desired_content_max_luminance. */
|
||||||
|
metadata->hdr_metadata.maxContentLightLevel = hdr_static_metadata->desired_content_max_luminance;
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata->supports_st2084 =
|
||||||
|
chroma &&
|
||||||
|
colorimetry && colorimetry->bt2020_rgb &&
|
||||||
|
hdr_static_metadata && hdr_static_metadata->eotfs && hdr_static_metadata->eotfs->pq;
|
||||||
|
|
||||||
|
di_info_destroy(info);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the mapping from our property enums to the KMS property ID for that
|
* Creates the mapping from our property enums to the KMS property ID for that
|
||||||
* property associated with the object.
|
* property associated with the object.
|
||||||
|
|
@ -295,6 +366,14 @@ find_properties(struct wsi_display_connector *connector, int fd, uint32_t type)
|
||||||
#undef COLORSPACE_ENUM
|
#undef COLORSPACE_ENUM
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(prop->name, "EDID")) {
|
||||||
|
drmModePropertyBlobRes *blob = drmModeGetPropertyBlob(fd, props->prop_values[p]);
|
||||||
|
if (blob) {
|
||||||
|
wsi_display_parse_edid(connector, blob);
|
||||||
|
drmModeFreePropertyBlob(blob);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
drmModeFreeProperty(prop);
|
drmModeFreeProperty(prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1243,6 +1322,20 @@ static const struct wsi_display_surface_format
|
||||||
},
|
},
|
||||||
.drm_format = DRM_FORMAT_XRGB8888
|
.drm_format = DRM_FORMAT_XRGB8888
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.surface_format = {
|
||||||
|
.format = VK_FORMAT_A2B10G10R10_UNORM_PACK32,
|
||||||
|
.colorSpace = VK_COLOR_SPACE_HDR10_ST2084_EXT,
|
||||||
|
},
|
||||||
|
.drm_format = DRM_FORMAT_XBGR2101010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.surface_format = {
|
||||||
|
.format = VK_FORMAT_A2R10G10B10_UNORM_PACK32,
|
||||||
|
.colorSpace = VK_COLOR_SPACE_HDR10_ST2084_EXT,
|
||||||
|
},
|
||||||
|
.drm_format = DRM_FORMAT_XRGB2101010
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -1263,6 +1356,21 @@ get_sorted_vk_formats(struct wsi_device *wsi_device, VkSurfaceFormatKHR *sorted_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
surface_format_supported(VkIcdSurfaceBase *icd_surface, VkSurfaceFormatKHR surface_format)
|
||||||
|
{
|
||||||
|
VkIcdSurfaceDisplay *surface = (VkIcdSurfaceDisplay *) icd_surface;
|
||||||
|
wsi_display_mode *mode = wsi_display_mode_from_handle(surface->displayMode);
|
||||||
|
|
||||||
|
if (surface_format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (surface_format.colorSpace == VK_COLOR_SPACE_HDR10_ST2084_EXT)
|
||||||
|
return mode->connector->metadata.supports_st2084;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static VkResult
|
static VkResult
|
||||||
wsi_display_surface_get_formats(VkIcdSurfaceBase *icd_surface,
|
wsi_display_surface_get_formats(VkIcdSurfaceBase *icd_surface,
|
||||||
struct wsi_device *wsi_device,
|
struct wsi_device *wsi_device,
|
||||||
|
|
@ -1276,10 +1384,12 @@ wsi_display_surface_get_formats(VkIcdSurfaceBase *icd_surface,
|
||||||
get_sorted_vk_formats(wsi_device, sorted_formats);
|
get_sorted_vk_formats(wsi_device, sorted_formats);
|
||||||
|
|
||||||
for (unsigned i = 0; i < ARRAY_SIZE(sorted_formats); i++) {
|
for (unsigned i = 0; i < ARRAY_SIZE(sorted_formats); i++) {
|
||||||
|
if (surface_format_supported(icd_surface, sorted_formats[i])) {
|
||||||
vk_outarray_append_typed(VkSurfaceFormatKHR, &out, f) {
|
vk_outarray_append_typed(VkSurfaceFormatKHR, &out, f) {
|
||||||
*f = sorted_formats[i];
|
*f = sorted_formats[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return vk_outarray_status(&out);
|
return vk_outarray_status(&out);
|
||||||
}
|
}
|
||||||
|
|
@ -1298,11 +1408,13 @@ wsi_display_surface_get_formats2(VkIcdSurfaceBase *surface,
|
||||||
get_sorted_vk_formats(wsi_device, sorted_formats);
|
get_sorted_vk_formats(wsi_device, sorted_formats);
|
||||||
|
|
||||||
for (unsigned i = 0; i < ARRAY_SIZE(sorted_formats); i++) {
|
for (unsigned i = 0; i < ARRAY_SIZE(sorted_formats); i++) {
|
||||||
|
if (surface_format_supported(surface, sorted_formats[i])) {
|
||||||
vk_outarray_append_typed(VkSurfaceFormat2KHR, &out, f) {
|
vk_outarray_append_typed(VkSurfaceFormat2KHR, &out, f) {
|
||||||
assert(f->sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR);
|
assert(f->sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR);
|
||||||
f->surfaceFormat = sorted_formats[i];
|
f->surfaceFormat = sorted_formats[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return vk_outarray_status(&out);
|
return vk_outarray_status(&out);
|
||||||
}
|
}
|
||||||
|
|
@ -2798,6 +2910,10 @@ wsi_display_surface_create_swapchain(
|
||||||
|
|
||||||
chain->surface = surface;
|
chain->surface = surface;
|
||||||
|
|
||||||
|
/* Default HDR metadata when the HDR10/ST2084 colorspace is used
|
||||||
|
* to the metadata provided by the EDID. */
|
||||||
|
chain->hdr_metadata = display_mode->connector->metadata.hdr_metadata;
|
||||||
|
|
||||||
p_atomic_inc(&display_mode->connector->refcount);
|
p_atomic_inc(&display_mode->connector->refcount);
|
||||||
|
|
||||||
for (uint32_t image = 0; image < chain->base.image_count; image++) {
|
for (uint32_t image = 0; image < chain->base.image_count; image++) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue