aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Rusak <lorusak@gmail.com>2021-09-28 23:34:03 -0700
committerLukas Rusak <lorusak@gmail.com>2022-07-28 20:32:32 -0700
commit67454c590387333f51da84547d4766be6b96ff9b (patch)
tree32bdd8538fafac82e759f8d110f5037cba7d2316
parented4003583e54aa3699430e2830a5dd97ffb634d6 (diff)
CWinSystemGbm: add ability to set HDR output
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp81
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.h31
-rw-r--r--xbmc/windowing/gbm/WinSystemGbm.cpp141
-rw-r--r--xbmc/windowing/gbm/WinSystemGbm.h6
4 files changed, 160 insertions, 99 deletions
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp
index a82da2225b..b91a1705ac 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp
@@ -8,8 +8,10 @@
#include "VideoLayerBridgeDRMPRIME.h"
+#include "ServiceBroker.h"
#include "cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.h"
#include "utils/log.h"
+#include "windowing/WinSystem.h"
#include "windowing/gbm/drm/DRMAtomic.h"
#include <utility>
@@ -35,17 +37,12 @@ void CVideoLayerBridgeDRMPRIME::Disable()
m_DRM->AddProperty(plane, "FB_ID", 0);
m_DRM->AddProperty(plane, "CRTC_ID", 0);
- // disable HDR metadata
- auto connector = m_DRM->GetConnector();
- if (connector->SupportsProperty("HDR_OUTPUT_METADATA"))
- {
- m_DRM->AddProperty(connector, "HDR_OUTPUT_METADATA", 0);
- m_DRM->SetActive(true);
+ auto winSystem = CServiceBroker::GetWinSystem();
+ if (!winSystem)
+ return;
- if (m_hdr_blob_id)
- drmModeDestroyPropertyBlob(m_DRM->GetFileDescriptor(), m_hdr_blob_id);
- m_hdr_blob_id = 0;
- }
+ // disable HDR metadata
+ winSystem->SetHDR(nullptr);
}
void CVideoLayerBridgeDRMPRIME::Acquire(CVideoBufferDRMPRIME* buffer)
@@ -159,8 +156,14 @@ void CVideoLayerBridgeDRMPRIME::Unmap(CVideoBufferDRMPRIME* buffer)
void CVideoLayerBridgeDRMPRIME::Configure(CVideoBufferDRMPRIME* buffer)
{
+ auto winSystem = CServiceBroker::GetWinSystem();
+ if (!winSystem)
+ return;
+
const VideoPicture& picture = buffer->GetPicture();
+ winSystem->SetHDR(&picture);
+
auto plane = m_DRM->GetVideoPlane();
bool result;
@@ -172,64 +175,6 @@ void CVideoLayerBridgeDRMPRIME::Configure(CVideoBufferDRMPRIME* buffer)
std::tie(result, value) = plane->GetPropertyValue("COLOR_RANGE", GetColorRange(picture));
if (result)
m_DRM->AddProperty(plane, "COLOR_RANGE", value);
-
- auto connector = m_DRM->GetConnector();
- if (connector->SupportsProperty("HDR_OUTPUT_METADATA"))
- {
- m_hdr_metadata.metadata_type = HDMI_STATIC_METADATA_TYPE1;
- m_hdr_metadata.hdmi_metadata_type1.eotf = GetEOTF(picture);
- m_hdr_metadata.hdmi_metadata_type1.metadata_type = HDMI_STATIC_METADATA_TYPE1;
-
- if (m_hdr_blob_id)
- drmModeDestroyPropertyBlob(m_DRM->GetFileDescriptor(), m_hdr_blob_id);
- m_hdr_blob_id = 0;
-
- if (m_hdr_metadata.hdmi_metadata_type1.eotf)
- {
- const AVMasteringDisplayMetadata* mdmd = GetMasteringDisplayMetadata(picture);
- if (mdmd && mdmd->has_primaries)
- {
- // Convert to unsigned 16-bit values in units of 0.00002,
- // where 0x0000 represents zero and 0xC350 represents 1.0000
- for (int i = 0; i < 3; i++)
- {
- m_hdr_metadata.hdmi_metadata_type1.display_primaries[i].x =
- std::round(av_q2d(mdmd->display_primaries[i][0]) * 50000.0);
- m_hdr_metadata.hdmi_metadata_type1.display_primaries[i].y =
- std::round(av_q2d(mdmd->display_primaries[i][1]) * 50000.0);
- }
- m_hdr_metadata.hdmi_metadata_type1.white_point.x =
- std::round(av_q2d(mdmd->white_point[0]) * 50000.0);
- m_hdr_metadata.hdmi_metadata_type1.white_point.y =
- std::round(av_q2d(mdmd->white_point[1]) * 50000.0);
- }
- if (mdmd && mdmd->has_luminance)
- {
- // Convert to unsigned 16-bit value in units of 1 cd/m2,
- // where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2
- m_hdr_metadata.hdmi_metadata_type1.max_display_mastering_luminance =
- std::round(av_q2d(mdmd->max_luminance));
-
- // Convert to unsigned 16-bit value in units of 0.0001 cd/m2,
- // where 0x0001 represents 0.0001 cd/m2 and 0xFFFF represents 6.5535 cd/m2
- m_hdr_metadata.hdmi_metadata_type1.min_display_mastering_luminance =
- std::round(av_q2d(mdmd->min_luminance) * 10000.0);
- }
-
- const AVContentLightMetadata* clmd = GetContentLightMetadata(picture);
- if (clmd)
- {
- m_hdr_metadata.hdmi_metadata_type1.max_cll = clmd->MaxCLL;
- m_hdr_metadata.hdmi_metadata_type1.max_fall = clmd->MaxFALL;
- }
-
- drmModeCreatePropertyBlob(m_DRM->GetFileDescriptor(), &m_hdr_metadata, sizeof(m_hdr_metadata),
- &m_hdr_blob_id);
- }
-
- m_DRM->AddProperty(connector, "HDR_OUTPUT_METADATA", m_hdr_blob_id);
- m_DRM->SetActive(true);
- }
}
void CVideoLayerBridgeDRMPRIME::SetVideoPlane(CVideoBufferDRMPRIME* buffer, const CRect& destRect)
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.h b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.h
index 3a46a91a13..8d9758f8d6 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.h
@@ -15,34 +15,6 @@
#include <drm_mode.h>
-#ifndef HAVE_HDR_OUTPUT_METADATA
-// HDR structs is copied from linux include/linux/hdmi.h
-struct hdr_metadata_infoframe
-{
- uint8_t eotf;
- uint8_t metadata_type;
- struct
- {
- uint16_t x, y;
- } display_primaries[3];
- struct
- {
- uint16_t x, y;
- } white_point;
- uint16_t max_display_mastering_luminance;
- uint16_t min_display_mastering_luminance;
- uint16_t max_cll;
- uint16_t max_fall;
-};
-struct hdr_output_metadata
-{
- uint32_t metadata_type;
- union {
- struct hdr_metadata_infoframe hdmi_metadata_type1;
- };
-};
-#endif
-
namespace KODI
{
namespace WINDOWING
@@ -78,7 +50,4 @@ private:
CVideoBufferDRMPRIME* m_buffer = nullptr;
CVideoBufferDRMPRIME* m_prev_buffer = nullptr;
-
- uint32_t m_hdr_blob_id = 0;
- struct hdr_output_metadata m_hdr_metadata = {};
};
diff --git a/xbmc/windowing/gbm/WinSystemGbm.cpp b/xbmc/windowing/gbm/WinSystemGbm.cpp
index a109e08c80..863f1ec1f7 100644
--- a/xbmc/windowing/gbm/WinSystemGbm.cpp
+++ b/xbmc/windowing/gbm/WinSystemGbm.cpp
@@ -12,6 +12,7 @@
#include "OptionalsReg.h"
#include "ServiceBroker.h"
#include "VideoSyncGbm.h"
+#include "cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.h"
#include "drm/DRMAtomic.h"
#include "drm/DRMLegacy.h"
#include "drm/OffScreenModeSetting.h"
@@ -27,6 +28,35 @@
#include <mutex>
#include <string.h>
+#ifndef HAVE_HDR_OUTPUT_METADATA
+// HDR structs is copied from linux include/linux/hdmi.h
+struct hdr_metadata_infoframe
+{
+ uint8_t eotf;
+ uint8_t metadata_type;
+ struct
+ {
+ uint16_t x, y;
+ } display_primaries[3];
+ struct
+ {
+ uint16_t x, y;
+ } white_point;
+ uint16_t max_display_mastering_luminance;
+ uint16_t min_display_mastering_luminance;
+ uint16_t max_cll;
+ uint16_t max_fall;
+};
+struct hdr_output_metadata
+{
+ uint32_t metadata_type;
+ union
+ {
+ struct hdr_metadata_infoframe hdmi_metadata_type1;
+ };
+};
+#endif
+
using namespace KODI::WINDOWING::GBM;
using namespace std::chrono_literals;
@@ -282,3 +312,114 @@ std::vector<std::string> CWinSystemGbm::GetConnectedOutputs()
{
return m_DRM->GetConnectedConnectorNames();
}
+
+bool CWinSystemGbm::SetHDR(const VideoPicture* videoPicture)
+{
+ auto settingsComponent = CServiceBroker::GetSettingsComponent();
+ if (!settingsComponent)
+ return false;
+
+ auto settings = settingsComponent->GetSettings();
+ if (!settings)
+ return false;
+
+ if (!settings->GetBool(SETTING_WINSYSTEM_IS_HDR_DISPLAY))
+ return false;
+
+ auto drm = std::dynamic_pointer_cast<CDRMAtomic>(m_DRM);
+ if (!drm)
+ return false;
+
+ if (!videoPicture)
+ {
+ auto connector = drm->GetConnector();
+ if (connector->SupportsProperty("HDR_OUTPUT_METADATA"))
+ {
+ drm->AddProperty(connector, "HDR_OUTPUT_METADATA", 0);
+ drm->SetActive(true);
+
+ if (m_hdr_blob_id)
+ drmModeDestroyPropertyBlob(drm->GetFileDescriptor(), m_hdr_blob_id);
+ m_hdr_blob_id = 0;
+ }
+
+ return true;
+ }
+
+ auto connector = drm->GetConnector();
+ if (connector->SupportsProperty("HDR_OUTPUT_METADATA"))
+ {
+ 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.metadata_type = DRMPRIME::HDMI_STATIC_METADATA_TYPE1;
+
+ if (m_hdr_blob_id)
+ drmModeDestroyPropertyBlob(drm->GetFileDescriptor(), m_hdr_blob_id);
+ m_hdr_blob_id = 0;
+
+ if (hdr_metadata.hdmi_metadata_type1.eotf)
+ {
+ const AVMasteringDisplayMetadata* mdmd = DRMPRIME::GetMasteringDisplayMetadata(*videoPicture);
+ if (mdmd && mdmd->has_primaries)
+ {
+ // Convert to unsigned 16-bit values in units of 0.00002,
+ // where 0x0000 represents zero and 0xC350 represents 1.0000
+ for (int i = 0; i < 3; i++)
+ {
+ hdr_metadata.hdmi_metadata_type1.display_primaries[i].x =
+ std::round(av_q2d(mdmd->display_primaries[i][0]) * 50000.0);
+ hdr_metadata.hdmi_metadata_type1.display_primaries[i].y =
+ std::round(av_q2d(mdmd->display_primaries[i][1]) * 50000.0);
+ }
+ hdr_metadata.hdmi_metadata_type1.white_point.x =
+ std::round(av_q2d(mdmd->white_point[0]) * 50000.0);
+ hdr_metadata.hdmi_metadata_type1.white_point.y =
+ std::round(av_q2d(mdmd->white_point[1]) * 50000.0);
+ }
+ if (mdmd && mdmd->has_luminance)
+ {
+ // Convert to unsigned 16-bit value in units of 1 cd/m2,
+ // where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2
+ hdr_metadata.hdmi_metadata_type1.max_display_mastering_luminance =
+ std::round(av_q2d(mdmd->max_luminance));
+
+ // Convert to unsigned 16-bit value in units of 0.0001 cd/m2,
+ // where 0x0001 represents 0.0001 cd/m2 and 0xFFFF represents 6.5535 cd/m2
+ hdr_metadata.hdmi_metadata_type1.min_display_mastering_luminance =
+ std::round(av_q2d(mdmd->min_luminance) * 10000.0);
+ }
+
+ const AVContentLightMetadata* clmd = DRMPRIME::GetContentLightMetadata(*videoPicture);
+ if (clmd)
+ {
+ hdr_metadata.hdmi_metadata_type1.max_cll = clmd->MaxCLL;
+ hdr_metadata.hdmi_metadata_type1.max_fall = clmd->MaxFALL;
+ }
+
+ drmModeCreatePropertyBlob(drm->GetFileDescriptor(), &hdr_metadata, sizeof(hdr_metadata),
+ &m_hdr_blob_id);
+ }
+
+ drm->AddProperty(connector, "HDR_OUTPUT_METADATA", m_hdr_blob_id);
+ drm->SetActive(true);
+ }
+
+ return true;
+}
+
+bool CWinSystemGbm::IsHDRDisplay()
+{
+ auto drm = std::dynamic_pointer_cast<CDRMAtomic>(m_DRM);
+ if (!drm)
+ return false;
+
+ auto connector = drm->GetConnector();
+ 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");
+}
diff --git a/xbmc/windowing/gbm/WinSystemGbm.h b/xbmc/windowing/gbm/WinSystemGbm.h
index ab156be786..b313d331d5 100644
--- a/xbmc/windowing/gbm/WinSystemGbm.h
+++ b/xbmc/windowing/gbm/WinSystemGbm.h
@@ -57,6 +57,9 @@ public:
void Register(IDispResource* resource) override;
void Unregister(IDispResource* resource) override;
+ bool SetHDR(const VideoPicture* videoPicture) override;
+ bool IsHDRDisplay() override;
+
std::shared_ptr<CVideoLayerBridge> GetVideoLayerBridge() const { return m_videoLayerBridge; }
void RegisterVideoLayerBridge(std::shared_ptr<CVideoLayerBridge> bridge)
{
@@ -83,6 +86,9 @@ protected:
bool m_dispReset = false;
XbmcThreads::EndTime<> m_dispResetTimer;
std::unique_ptr<CLibInputHandler> m_libinput;
+
+private:
+ uint32_t m_hdr_blob_id = 0;
};
}