diff options
-rw-r--r-- | cmake/modules/FindLibDisplayInfo.cmake | 36 | ||||
-rw-r--r-- | cmake/platform/linux/gbm.cmake | 2 | ||||
-rw-r--r-- | tools/depends/target/Makefile | 5 | ||||
-rw-r--r-- | tools/depends/target/hwdata/Makefile | 28 | ||||
-rw-r--r-- | tools/depends/target/libdisplay-info/Makefile | 54 | ||||
-rw-r--r-- | xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.cpp | 8 | ||||
-rw-r--r-- | xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.h | 3 | ||||
-rw-r--r-- | xbmc/utils/CMakeLists.txt | 5 | ||||
-rw-r--r-- | xbmc/utils/DisplayInfo.cpp | 165 | ||||
-rw-r--r-- | xbmc/utils/DisplayInfo.h | 64 | ||||
-rw-r--r-- | xbmc/windowing/gbm/WinSystemGbm.cpp | 41 | ||||
-rw-r--r-- | xbmc/windowing/gbm/WinSystemGbm.h | 11 | ||||
-rw-r--r-- | xbmc/windowing/gbm/drm/DRMConnector.cpp | 28 | ||||
-rw-r--r-- | xbmc/windowing/gbm/drm/DRMConnector.h | 2 |
14 files changed, 439 insertions, 13 deletions
diff --git a/cmake/modules/FindLibDisplayInfo.cmake b/cmake/modules/FindLibDisplayInfo.cmake new file mode 100644 index 0000000000..add628d8c7 --- /dev/null +++ b/cmake/modules/FindLibDisplayInfo.cmake @@ -0,0 +1,36 @@ +#.rst: +# FindLibDisplayInfo +# ------- +# Finds the libdisplay-info library +# +# This will define the following variables:: +# +# LIBDISPLAYINFO_FOUND - system has LIBDISPLAY-INFO +# LIBDISPLAYINFO_INCLUDE_DIRS - the LIBDISPLAY-INFO include directory +# LIBDISPLAYINFO_LIBRARIES - the LIBDISPLAY-INFO libraries +# LIBDISPLAYINFO_DEFINITIONS - the LIBDISPLAY-INFO definitions +# + +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_LIBDISPLAYINFO libdisplay-info QUIET) +endif() + +find_path(LIBDISPLAYINFO_INCLUDE_DIR libdisplay-info/edid.h + PATHS ${PC_LIBDISPLAYINFO_INCLUDEDIR}) + +find_library(LIBDISPLAYINFO_LIBRARY NAMES display-info + PATHS ${PC_LIBDISPLAYINFO_LIBDIR}) + +set(LIBDISPLAYINFO_VERSION ${PC_LIBDISPLAYINFO_VERSION}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(LibDisplayInfo + REQUIRED_VARS LIBDISPLAYINFO_LIBRARY LIBDISPLAYINFO_INCLUDE_DIR + VERSION_VAR LIBDISPLAYINFO_VERSION) + +if(LIBDISPLAYINFO_FOUND) + set(LIBDISPLAYINFO_LIBRARIES ${LIBDISPLAYINFO_LIBRARY}) + set(LIBDISPLAYINFO_INCLUDE_DIRS ${LIBDISPLAYINFO_INCLUDE_DIR}) +endif() + +mark_as_advanced(LIBDISPLAYINFO_INCLUDE_DIR LIBDISPLAYINFO_LIBRARY) diff --git a/cmake/platform/linux/gbm.cmake b/cmake/platform/linux/gbm.cmake index 5e0475a67c..d250326589 100644 --- a/cmake/platform/linux/gbm.cmake +++ b/cmake/platform/linux/gbm.cmake @@ -1,4 +1,4 @@ -list(APPEND PLATFORM_REQUIRED_DEPS GBM LibDRM LibInput Xkbcommon UDEV) +list(APPEND PLATFORM_REQUIRED_DEPS GBM LibDRM LibInput Xkbcommon UDEV LibDisplayInfo) list(APPEND PLATFORM_OPTIONAL_DEPS VAAPI) if(APP_RENDER_SYSTEM STREQUAL "gl") diff --git a/tools/depends/target/Makefile b/tools/depends/target/Makefile index 656f2c7a75..07619fcc77 100644 --- a/tools/depends/target/Makefile +++ b/tools/depends/target/Makefile @@ -136,6 +136,10 @@ ifeq ($(OS),linux) DEPENDS += wayland waylandpp wayland-protocols webos-wayland-extensions webos-userland EXCLUDED_DEPENDS += dbus libcec linux-system-x11-libs pipewire mesa endif + + ifneq (,$(findstring gbm,$(TARGET_PLATFORM))) + DEPENDS += hwdata libdisplay-info + endif endif DEPENDS := $(filter-out $(EXCLUDED_DEPENDS),$(DEPENDS)) @@ -160,6 +164,7 @@ libbluray: fontconfig freetype2 $(ICONV) udfread libxml2 libcdio-gplv3: $(ICONV) libcdio: $(ICONV) libcec: p8-platform +libdisplay-info: meson-cross-file hwdata libdrm: meson-cross-file libevdev: libudev libgcrypt: libgpg-error diff --git a/tools/depends/target/hwdata/Makefile b/tools/depends/target/hwdata/Makefile new file mode 100644 index 0000000000..8e1155e59d --- /dev/null +++ b/tools/depends/target/hwdata/Makefile @@ -0,0 +1,28 @@ +include ../../Makefile.include +DEPS =../../Makefile.include Makefile ../../download-files.include + +LIBNAME=hwdata +VERSION=0.368 +ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz +SHA512=a38adffa503f6f37ddefbad9a0fe9694605ffe54781fc88dd91937a09a54a7de70e027138f34a64bc3a701ab91656c1ae2dc938ed7cb0f73652d34a2ae917690 +include ../../download-files.include + +all: .installed-$(PLATFORM) + +download: $(TARBALLS_LOCATION)/$(ARCHIVE) + +$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + +.installed-$(PLATFORM): $(PLATFORM) + cd $(PLATFORM); ./configure --prefix=$(PREFIX) --datarootdir=$(PREFIX)/share --disable-blacklist + cd $(PLATFORM); make install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/depends/target/libdisplay-info/Makefile b/tools/depends/target/libdisplay-info/Makefile new file mode 100644 index 0000000000..561a5aeb49 --- /dev/null +++ b/tools/depends/target/libdisplay-info/Makefile @@ -0,0 +1,54 @@ +include ../../Makefile.include +DEPS =../../Makefile.include Makefile ../../download-files.include + +LIBNAME=libdisplay-info +VERSION=0.1.1 +ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz +SHA512=8b11c35315f3f16f6853b2ba5daa39c622f2326cfa01d54574beb577efd38d25b8260f7d74c63924473a0487bffdbff727ddc05b12d36e2106b78aadc7d4ff42 +include ../../download-files.include + +MESON_BUILD_TYPE=release + +ifeq ($(DEBUG_BUILD), yes) + MESON_BUILD_TYPE=debug +endif + +# configuration settings +CONFIGURE = $(NATIVEPREFIX)/bin/python3 $(NATIVEPREFIX)/bin/meson \ + --prefix=$(PREFIX) \ + --libdir=lib \ + --buildtype=$(MESON_BUILD_TYPE) + + +ifeq ($(CROSS_COMPILING), yes) +CONFIGURE += --cross-file $(PREFIX)/share/cross-file.meson +export CC=$(CC_FOR_BUILD) +export CXX=$(CXX_FOR_BUILD) +export CFLAGS=$(CFLAGS_FOR_BUILD) +export CXXFLAGS=$(CXXFLAGS_FOR_BUILD) +else +export CC CXX CFLAGS CXXFLAGS +endif +export PKG_CONFIG_LIBDIR=$(PREFIX)/share/pkgconfig + +all: .installed-$(PLATFORM) + +download: $(TARBALLS_LOCATION)/$(ARCHIVE) + +$(PLATFORM): $(DEPS) | $(TARBALLS_LOCATION)/$(ARCHIVE).$(HASH_TYPE) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + +.installed-$(PLATFORM): $(PLATFORM) + cd $(PLATFORM); rm -rf build; mkdir -p build + cd $(PLATFORM); $(CONFIGURE) . build + cd $(PLATFORM)/build; $(NATIVEPREFIX)/bin/ninja -v + cd $(PLATFORM)/build; $(NATIVEPREFIX)/bin/ninja -v install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.cpp b/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.cpp index b1c23ffc3d..4f7bd602e5 100644 --- a/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.cpp +++ b/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.cpp @@ -50,17 +50,17 @@ std::string GetColorRange(const VideoPicture& picture) return "YCbCr limited range"; } -uint8_t GetEOTF(const VideoPicture& picture) +KODI::UTILS::Eotf GetEOTF(const VideoPicture& picture) { switch (picture.color_transfer) { case AVCOL_TRC_SMPTE2084: - return HDMI_EOTF_SMPTE_ST2084; + return KODI::UTILS::Eotf::PQ; case AVCOL_TRC_ARIB_STD_B67: case AVCOL_TRC_BT2020_10: - return HDMI_EOTF_BT_2100_HLG; + return KODI::UTILS::Eotf::HLG; default: - return HDMI_EOTF_TRADITIONAL_GAMMA_SDR; + return KODI::UTILS::Eotf::TRADITIONAL_SDR; } } diff --git a/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.h b/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.h index e77f75b58b..28496466cd 100644 --- a/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.h +++ b/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.h @@ -10,6 +10,7 @@ #include "cores/VideoPlayer/Buffers/VideoBuffer.h" #include "cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h" +#include "utils/DisplayInfo.h" extern "C" { @@ -36,7 +37,7 @@ enum hdmi_eotf std::string GetColorEncoding(const VideoPicture& picture); std::string GetColorRange(const VideoPicture& picture); -uint8_t GetEOTF(const VideoPicture& picture); +KODI::UTILS::Eotf GetEOTF(const VideoPicture& picture); const AVMasteringDisplayMetadata* GetMasteringDisplayMetadata(const VideoPicture& picture); const AVContentLightMetadata* GetContentLightMetadata(const VideoPicture& picture); diff --git a/xbmc/utils/CMakeLists.txt b/xbmc/utils/CMakeLists.txt index 8e1328999f..4f6c12dd29 100644 --- a/xbmc/utils/CMakeLists.txt +++ b/xbmc/utils/CMakeLists.txt @@ -237,6 +237,11 @@ if("gbm" IN_LIST CORE_PLATFORM_NAME_LC OR "wayland" IN_LIST CORE_PLATFORM_NAME_L list(APPEND SOURCES DRMHelpers.cpp) list(APPEND HEADERS DRMHelpers.h) endif() + + if(LIBDISPLAYINFO_FOUND) + list(APPEND SOURCES DisplayInfo.cpp) + list(APPEND HEADERS DisplayInfo.h) + endif() endif() core_add_library(utils) diff --git a/xbmc/utils/DisplayInfo.cpp b/xbmc/utils/DisplayInfo.cpp new file mode 100644 index 0000000000..655a55d375 --- /dev/null +++ b/xbmc/utils/DisplayInfo.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "DisplayInfo.h" + +#include "utils/log.h" + +extern "C" +{ +#include <libdisplay-info/cta.h> +#include <libdisplay-info/edid.h> +#include <libdisplay-info/info.h> +} + +using namespace KODI; +using namespace UTILS; + +void CDisplayInfo::DiInfoDeleter::operator()(di_info* p) +{ + di_info_destroy(p); +} + +std::unique_ptr<CDisplayInfo> CDisplayInfo::Create(const std::vector<uint8_t>& edid) +{ + auto info = std::unique_ptr<CDisplayInfo>(new CDisplayInfo(edid)); + if (!info->IsValid()) + return {}; + + info->Parse(); + + info->LogInfo(); + + return info; +} + +CDisplayInfo::CDisplayInfo(const std::vector<uint8_t>& edid) +{ + m_info.reset(di_info_parse_edid(edid.data(), edid.size())); +} + +CDisplayInfo::~CDisplayInfo() = default; + +bool CDisplayInfo::IsValid() const +{ + if (!m_info) + return false; + + const char* error = di_info_get_failure_msg(m_info.get()); + if (error) + { + CLog::Log(LOGERROR, "[display-info] error: {}", error); + return false; + } + + return true; +} + +void CDisplayInfo::Parse() +{ + char* str = nullptr; + + str = di_info_get_make(m_info.get()); + m_make = str ? str : "unknown"; + free(str); + + str = di_info_get_model(m_info.get()); + m_model = str ? str : "unknown"; + free(str); + + const di_edid* edid = di_info_get_edid(m_info.get()); + + const di_edid_ext* const* extensions = di_edid_get_extensions(edid); + for (const di_edid_ext* extension = *extensions; extension != nullptr; + extension = *(++extensions)) + { + di_edid_ext_tag tag = di_edid_ext_get_tag(extension); + + switch (tag) + { + case DI_EDID_EXT_CEA: + { + const di_edid_cta* cta = di_edid_ext_get_cta(extension); + + const di_cta_data_block* const* blocks = di_edid_cta_get_data_blocks(cta); + for (const di_cta_data_block* block = *blocks; block != nullptr; block = *(++blocks)) + { + di_cta_data_block_tag cta_tag = di_cta_data_block_get_tag(block); + + switch (cta_tag) + { + case DI_CTA_DATA_BLOCK_HDR_STATIC_METADATA: + { + m_hdr_static_metadata = di_cta_data_block_get_hdr_static_metadata(block); + + break; + } + default: + break; + } + } + + break; + } + default: + break; + } + } +} + +void CDisplayInfo::LogInfo() const +{ + CLog::Log(LOGINFO, "[display-info] make: '{}' model: '{}'", m_make, m_model); + + if (m_hdr_static_metadata) + { + CLog::Log(LOGINFO, "[display-info] supports hdr static metadata type1: {}", + m_hdr_static_metadata->descriptors->type1); + + CLog::Log(LOGINFO, "[display-info] supported eotf:"); + CLog::Log(LOGINFO, "[display-info] traditional sdr: {}", + m_hdr_static_metadata->eotfs->traditional_sdr); + CLog::Log(LOGINFO, "[display-info] traditional hdr: {}", + m_hdr_static_metadata->eotfs->traditional_hdr); + CLog::Log(LOGINFO, "[display-info] traditional pq: {}", m_hdr_static_metadata->eotfs->pq); + CLog::Log(LOGINFO, "[display-info] traditional hlg: {}", m_hdr_static_metadata->eotfs->hlg); + + CLog::Log(LOGINFO, "[display-info] luma min: '{}' avg: '{}' max: '{}'", + m_hdr_static_metadata->desired_content_min_luminance, + m_hdr_static_metadata->desired_content_max_frame_avg_luminance, + m_hdr_static_metadata->desired_content_max_luminance); + } +} + +bool CDisplayInfo::SupportsHDRStaticMetadataType1() const +{ + if (!m_hdr_static_metadata) + return false; + + return m_hdr_static_metadata->descriptors->type1; +} + +bool CDisplayInfo::SupportsEOTF(Eotf eotf) const +{ + if (!m_hdr_static_metadata) + return false; + + switch (eotf) + { + case Eotf::TRADITIONAL_SDR: + return m_hdr_static_metadata->eotfs->traditional_sdr; + case Eotf::TRADITIONAL_HDR: + return m_hdr_static_metadata->eotfs->traditional_hdr; + case Eotf::PQ: + return m_hdr_static_metadata->eotfs->pq; + case Eotf::HLG: + return m_hdr_static_metadata->eotfs->hlg; + default: + return false; + } +} diff --git a/xbmc/utils/DisplayInfo.h b/xbmc/utils/DisplayInfo.h new file mode 100644 index 0000000000..8f01113dd2 --- /dev/null +++ b/xbmc/utils/DisplayInfo.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include <memory> +#include <stdint.h> +#include <string> +#include <vector> + +struct di_info; +struct di_cta_hdr_static_metadata_block; + +namespace KODI +{ +namespace UTILS +{ + +enum class Eotf +{ + TRADITIONAL_SDR, + TRADITIONAL_HDR, + PQ, + HLG, +}; + +class CDisplayInfo +{ +public: + static std::unique_ptr<CDisplayInfo> Create(const std::vector<uint8_t>& edid); + + ~CDisplayInfo(); + + bool SupportsHDRStaticMetadataType1() const; + + bool SupportsEOTF(Eotf eotf) const; + +private: + explicit CDisplayInfo(const std::vector<uint8_t>& edid); + + bool IsValid() const; + void Parse(); + void LogInfo() const; + + struct DiInfoDeleter + { + void operator()(di_info* p); + }; + + std::unique_ptr<di_info, DiInfoDeleter> m_info; + + std::string m_make; + std::string m_model; + + const di_cta_hdr_static_metadata_block* m_hdr_static_metadata = nullptr; +}; + +} // namespace UTILS +} // namespace KODI diff --git a/xbmc/windowing/gbm/WinSystemGbm.cpp b/xbmc/windowing/gbm/WinSystemGbm.cpp index 9e6d0971ad..f33b6dde41 100644 --- a/xbmc/windowing/gbm/WinSystemGbm.cpp +++ b/xbmc/windowing/gbm/WinSystemGbm.cpp @@ -21,6 +21,7 @@ #include "settings/Settings.h" #include "settings/SettingsComponent.h" #include "settings/lib/Setting.h" +#include "utils/DisplayInfo.h" #include "utils/StringUtils.h" #include "utils/log.h" #include "windowing/GraphicContext.h" @@ -70,6 +71,8 @@ CWinSystemGbm::CWinSystemGbm() : m_libinput->Start(); } +CWinSystemGbm::~CWinSystemGbm() = default; + bool CWinSystemGbm::InitWindowSystem() { const char* x11 = getenv("DISPLAY"); @@ -106,6 +109,16 @@ bool CWinSystemGbm::InitWindowSystem() } } + CDRMConnector* connector = m_DRM->GetConnector(); + if (connector) + { + std::vector<uint8_t> edid = connector->GetEDID(); + if (!edid.empty()) + { + m_info = UTILS::CDisplayInfo::Create(edid); + } + } + if (!m_GBM->CreateDevice(m_DRM->GetFileDescriptor())) { m_GBM.reset(); @@ -345,13 +358,16 @@ bool CWinSystemGbm::SetHDR(const VideoPicture* videoPicture) return true; } + KODI::UTILS::Eotf eotf = DRMPRIME::GetEOTF(*videoPicture); + auto connector = drm->GetConnector(); - if (connector->SupportsProperty("HDR_OUTPUT_METADATA")) + if (connector->SupportsProperty("HDR_OUTPUT_METADATA") && m_info && + m_info->SupportsHDRStaticMetadataType1() && m_info->SupportsEOTF(eotf)) { hdr_output_metadata hdr_metadata = {}; hdr_metadata.metadata_type = DRMPRIME::HDMI_STATIC_METADATA_TYPE1; - hdr_metadata.hdmi_metadata_type1.eotf = DRMPRIME::GetEOTF(*videoPicture); + hdr_metadata.hdmi_metadata_type1.eotf = static_cast<uint8_t>(eotf); hdr_metadata.hdmi_metadata_type1.metadata_type = DRMPRIME::HDMI_STATIC_METADATA_TYPE1; if (m_hdr_blob_id) @@ -437,7 +453,22 @@ bool CWinSystemGbm::IsHDRDisplay() if (!connector) return false; - //! @todo: improve detection (edid?) - // we have no way to know if the display is actually HDR capable and we blindly set the HDR metadata - return connector->SupportsProperty("HDR_OUTPUT_METADATA"); + return connector->SupportsProperty("HDR_OUTPUT_METADATA") && m_info && + m_info->SupportsHDRStaticMetadataType1(); +} + +CHDRCapabilities CWinSystemGbm::GetDisplayHDRCapabilities() const +{ + if (!m_info) + return {}; + + CHDRCapabilities caps; + + if (m_info->SupportsEOTF(UTILS::Eotf::PQ)) + caps.SetHDR10(); + + if (m_info->SupportsEOTF(UTILS::Eotf::HLG)) + caps.SetHLG(); + + return caps; } diff --git a/xbmc/windowing/gbm/WinSystemGbm.h b/xbmc/windowing/gbm/WinSystemGbm.h index b313d331d5..f57739ee3b 100644 --- a/xbmc/windowing/gbm/WinSystemGbm.h +++ b/xbmc/windowing/gbm/WinSystemGbm.h @@ -24,6 +24,10 @@ class IDispResource; namespace KODI { +namespace UTILS +{ +class CDisplayInfo; +} namespace WINDOWING { namespace GBM @@ -33,7 +37,7 @@ class CWinSystemGbm : public CWinSystemBase { public: CWinSystemGbm(); - ~CWinSystemGbm() override = default; + ~CWinSystemGbm() override; const std::string GetName() override { return "gbm"; } @@ -59,6 +63,7 @@ public: bool SetHDR(const VideoPicture* videoPicture) override; bool IsHDRDisplay() override; + CHDRCapabilities GetDisplayHDRCapabilities() const override; std::shared_ptr<CVideoLayerBridge> GetVideoLayerBridge() const { return m_videoLayerBridge; } void RegisterVideoLayerBridge(std::shared_ptr<CVideoLayerBridge> bridge) @@ -89,8 +94,10 @@ protected: private: uint32_t m_hdr_blob_id = 0; + + std::unique_ptr<UTILS::CDisplayInfo> m_info; }; } } -} +} // namespace KODI diff --git a/xbmc/windowing/gbm/drm/DRMConnector.cpp b/xbmc/windowing/gbm/drm/DRMConnector.cpp index fc76b90575..94f8e909ff 100644 --- a/xbmc/windowing/gbm/drm/DRMConnector.cpp +++ b/xbmc/windowing/gbm/drm/DRMConnector.cpp @@ -97,3 +97,31 @@ std::string CDRMConnector::GetName() { return GetType() + "-" + std::to_string(m_connector->connector_type_id); } + +std::vector<uint8_t> CDRMConnector::GetEDID() const +{ + auto property = std::find_if(m_propsInfo.begin(), m_propsInfo.end(), + [](auto& prop) { return prop->name == std::string_view("EDID"); }); + + if (property == m_propsInfo.end()) + { + CLog::LogF(LOGDEBUG, "failed to find EDID property for connector: {}", + m_connector->connector_id); + return {}; + } + + uint64_t blob_id = m_props->prop_values[std::distance(m_propsInfo.begin(), property)]; + if (blob_id == 0) + return {}; + + drmModePropertyBlobPtr blob = drmModeGetPropertyBlob(m_fd, blob_id); + if (!blob) + return {}; + + auto data = static_cast<uint8_t*>(blob->data); + auto edid = std::vector<uint8_t>(data, data + blob->length); + + drmModeFreePropertyBlob(blob); + + return edid; +} diff --git a/xbmc/windowing/gbm/drm/DRMConnector.h b/xbmc/windowing/gbm/drm/DRMConnector.h index 5a29222f12..cde242d49f 100644 --- a/xbmc/windowing/gbm/drm/DRMConnector.h +++ b/xbmc/windowing/gbm/drm/DRMConnector.h @@ -39,6 +39,8 @@ public: bool IsConnected() { return m_connector->connection == DRM_MODE_CONNECTED; } bool CheckConnector(); + std::vector<uint8_t> GetEDID() const; + private: struct DrmModeConnectorDeleter { |