From fabe4a85e310827fedb8092129d1f53f2882c883 Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Thu, 17 Nov 2022 17:07:50 +0000 Subject: [PATCH] [wsi] Add parseColorimetryInfo helper --- src/wsi/meson.build | 12 +++++--- src/wsi/wsi_edid.cpp | 72 +++++++++++++++++++++++++++++++++++++++++++ src/wsi/wsi_edid.h | 38 +++++++++++++++++++++++ src/wsi/wsi_monitor.h | 4 +-- 4 files changed, 120 insertions(+), 6 deletions(-) create mode 100644 src/wsi/wsi_edid.cpp create mode 100644 src/wsi/wsi_edid.h diff --git a/src/wsi/meson.build b/src/wsi/meson.build index a7442dfb4..17efa26b2 100644 --- a/src/wsi/meson.build +++ b/src/wsi/meson.build @@ -1,3 +1,7 @@ +wsi_common_src = [ + 'wsi_edid.cpp', +] + wsi_win32_src = [ 'win32/wsi_monitor_win32.cpp', 'win32/wsi_window_win32.cpp', @@ -9,11 +13,11 @@ wsi_sdl2_src = [ ] if dxvk_wsi == 'win32' - wsi_src = wsi_win32_src - wsi_deps = [] + wsi_src = wsi_common_src + wsi_win32_src + wsi_deps = [ dep_displayinfo ] elif dxvk_wsi == 'sdl2' - wsi_src = wsi_sdl2_src - wsi_deps = [ lib_sdl2 ] + wsi_src = wsi_common_src + wsi_sdl2_src + wsi_deps = [ dep_displayinfo, lib_sdl2 ] else error('Unknown wsi') endif diff --git a/src/wsi/wsi_edid.cpp b/src/wsi/wsi_edid.cpp new file mode 100644 index 000000000..01741b91c --- /dev/null +++ b/src/wsi/wsi_edid.cpp @@ -0,0 +1,72 @@ +extern "C" { +#include "libdisplay-info/info.h" +#include "libdisplay-info/edid.h" +#include "libdisplay-info/cta.h" +} + +#include "wsi_edid.h" + +#include "../util/util_string.h" +#include "../util/log/log.h" + +namespace dxvk::wsi { + + std::optional parseColorimetryInfo( + const WsiEdidData& edidData) { + WsiDisplayMetadata metadata = {}; + + di_info* info = di_info_parse_edid(edidData.data(), edidData.size()); + if (!info) { + Logger::err(str::format("wsi: parseColorimetryInfo: Failed to get parse edid. Reason: ", di_info_get_failure_msg(info))); + return std::nullopt; + } + + const di_edid* edid = di_info_get_edid(info); + + const di_edid_chromaticity_coords* chroma = di_edid_get_chromaticity_coords(edid); + const di_cta_hdr_static_metadata_block* hdr_static_metadata = nullptr; + const di_cta_colorimetry_block* colorimetry = nullptr; + + const di_edid_cta* cta = nullptr; + const di_edid_ext* const* exts = di_edid_get_extensions(edid); + for (; *exts != nullptr; exts++) { + if ((cta = di_edid_ext_get_cta(*exts))) + break; + } + + if (cta) { + const di_cta_data_block* const* blocks = di_edid_cta_get_data_blocks(cta); + for (; *blocks != nullptr; blocks++) { + if ((hdr_static_metadata = di_cta_data_block_get_hdr_static_metadata(*blocks))) + continue; + if ((colorimetry = di_cta_data_block_get_colorimetry(*blocks))) + continue; + } + } + + if (chroma) { + metadata.redPrimary[0] = chroma->red_x; + metadata.redPrimary[1] = chroma->red_y; + metadata.greenPrimary[0] = chroma->green_x; + metadata.greenPrimary[1] = chroma->green_y; + metadata.bluePrimary[0] = chroma->blue_x; + metadata.bluePrimary[1] = chroma->blue_y; + metadata.whitePoint[0] = chroma->white_x; + metadata.whitePoint[1] = chroma->white_y; + } + + if (hdr_static_metadata) { + metadata.maxFullFrameLuminance = hdr_static_metadata->desired_content_max_frame_avg_luminance; + metadata.minLuminance = hdr_static_metadata->desired_content_min_luminance; + metadata.maxLuminance = hdr_static_metadata->desired_content_max_luminance; + } + + metadata.supportsST2084 = + chroma && + colorimetry && colorimetry->bt2020_rgb && + hdr_static_metadata && hdr_static_metadata->eotfs && hdr_static_metadata->eotfs->pq; + + return metadata; + } + +} \ No newline at end of file diff --git a/src/wsi/wsi_edid.h b/src/wsi/wsi_edid.h new file mode 100644 index 000000000..04bf239d0 --- /dev/null +++ b/src/wsi/wsi_edid.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include + +namespace dxvk::wsi { + + /** + * \brief Edid blob + */ + using WsiEdidData = std::vector; + + /** + * \brief Display colorimetry info + */ + struct WsiDisplayMetadata { + bool supportsST2084; + + float redPrimary[2]; + float greenPrimary[2]; + float bluePrimary[2]; + float whitePoint[2]; + float minLuminance; + float maxLuminance; + float maxFullFrameLuminance; + }; + + /** + * \brief Parse colorimetry info from the EDID + * + * \param [in] edidData The edid blob + * \returns The display metadata + colorimetry info + */ + std::optional parseColorimetryInfo( + const WsiEdidData& edidData); + +} diff --git a/src/wsi/wsi_monitor.h b/src/wsi/wsi_monitor.h index 84c00b087..ef542fed4 100644 --- a/src/wsi/wsi_monitor.h +++ b/src/wsi/wsi_monitor.h @@ -6,6 +6,8 @@ #include #include +#include "wsi_edid.h" + namespace dxvk::wsi { /** @@ -125,8 +127,6 @@ namespace dxvk::wsi { *pHeight = rect.bottom - rect.top; } - using WsiEdidData = std::vector; - /** * \brief Get the EDID of a monitor *