From e3a833b50fba83f8a55e617d8a1b09b9a5c030dc Mon Sep 17 00:00:00 2001 From: boogie Date: Sat, 13 Jan 2024 19:39:52 +0100 Subject: [PATCH 1/2] windowing/gbm: Dynamic plane selection This commit allows kodi to select gui and video planes according to format and modifier combination and sorts to gui plane on top of video plane if zpos is supported and not immutable by the planes. --- .../HwDecRender/RendererDRMPRIME.cpp | 4 +- xbmc/windowing/gbm/drm/DRMAtomic.cpp | 43 +++++++++++++++++++ xbmc/windowing/gbm/drm/DRMAtomic.h | 1 + xbmc/windowing/gbm/drm/DRMObject.cpp | 30 +++++++++++++ xbmc/windowing/gbm/drm/DRMObject.h | 2 + xbmc/windowing/gbm/drm/DRMUtils.cpp | 21 +++++---- xbmc/windowing/gbm/drm/DRMUtils.h | 4 +- 7 files changed, 93 insertions(+), 12 deletions(-) diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIME.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIME.cpp index a07b4f7440..04d42c0982 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIME.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIME.cpp @@ -77,9 +77,11 @@ CBaseRenderer* CRendererDRMPRIME::Create(CVideoBuffer* buffer) if (!plane) return nullptr; - if (!plane->SupportsFormatAndModifier(format, modifier)) + if (!drm->FindPlanes(format, modifier)) return nullptr; + drm->SortPlanes(); + return new CRendererDRMPRIME(); } diff --git a/xbmc/windowing/gbm/drm/DRMAtomic.cpp b/xbmc/windowing/gbm/drm/DRMAtomic.cpp index ff7f137d60..de03b8476e 100644 --- a/xbmc/windowing/gbm/drm/DRMAtomic.cpp +++ b/xbmc/windowing/gbm/drm/DRMAtomic.cpp @@ -61,6 +61,49 @@ bool CDRMAtomic::SetScalingFilter(CDRMObject* object, const char* name, const ch return true; } +void CDRMAtomic::SortPlanes() +{ + bool supports_zpos = m_gui_plane->SupportsProperty("zpos"); + bool zpos_immutable = supports_zpos && m_gui_plane->IsPropertyImmutable("zpos").value(); + + auto crtc_offset = std::distance( + m_crtcs.begin(), + std::find_if(m_crtcs.begin(), m_crtcs.end(), + [this](auto& crtc) { return crtc->GetCrtcId() == m_crtc->GetCrtcId(); })); + + // Disable unused planes after planes are re-selected in the active crtc + for (auto& plane : m_planes) + { + if (!(plane.get()->GetPossibleCrtcs() & (1 << crtc_offset))) + continue; + + if ((m_video_plane == nullptr || m_video_plane->GetId() != plane.get()->GetId()) && + (m_gui_plane == nullptr || m_gui_plane->GetId() != plane.get()->GetId())) + { + CLog::Log(LOGDEBUG, "CDRMUtils::{} - disabled plane {}", __FUNCTION__, + plane.get()->GetPlaneId()); + AddProperty(plane.get(), "FB_ID", 0); + AddProperty(plane.get(), "CRTC_ID", 0); + } + } + + if (!supports_zpos || zpos_immutable) + return; + + // re-sort the video and gui planes + std::optional limits = m_gui_plane->GetRangePropertyLimits("zpos"); + + if(!limits) + return; + + m_gui_plane->SetProperty("zpos", limits.value()[1]); + m_video_plane->SetProperty("zpos", limits.value()[0]); + CLog::Log(LOGDEBUG, "CDRMUtils::{} - gui plane id,zpos: {}, {}", __FUNCTION__, + m_gui_plane->GetId(), limits.value()[0] + 1); + CLog::Log(LOGDEBUG, "CDRMUtils::{} - video plane id,zpos: {}, {}", __FUNCTION__, + m_video_plane->GetId(), limits.value()[0]); +} + void CDRMAtomic::DrmAtomicCommit(int fb_id, int flags, bool rendered, bool videoLayer) { uint32_t blob_id; diff --git a/xbmc/windowing/gbm/drm/DRMAtomic.h b/xbmc/windowing/gbm/drm/DRMAtomic.h index 6b19657587..ee6314ffaf 100644 --- a/xbmc/windowing/gbm/drm/DRMAtomic.h +++ b/xbmc/windowing/gbm/drm/DRMAtomic.h @@ -33,6 +33,7 @@ public: bool InitDrm() override; void DestroyDrm() override; bool AddProperty(CDRMObject* object, const char* name, uint64_t value); + void SortPlanes(); bool DisplayHardwareScalingEnabled(); diff --git a/xbmc/windowing/gbm/drm/DRMObject.cpp b/xbmc/windowing/gbm/drm/DRMObject.cpp index 5ffce40fa3..2fafdc7b95 100644 --- a/xbmc/windowing/gbm/drm/DRMObject.cpp +++ b/xbmc/windowing/gbm/drm/DRMObject.cpp @@ -105,6 +105,25 @@ std::optional CDRMObject::GetPropertyValue(std::string_view name, return {}; } +std::optional CDRMObject::GetRangePropertyLimits(std::string_view name) +{ + auto property = std::find_if(m_propsInfo.begin(), m_propsInfo.end(), + [&name](const auto& prop) { return prop->name == name; }); + + if (property == m_propsInfo.end()) + return {}; + + auto prop = property->get(); + + if (!static_cast(drm_property_type_is(prop, DRM_MODE_PROP_RANGE))) + return {}; + + if (prop->count_values != 2) + return {}; + + return prop->values; +} + bool CDRMObject::SetProperty(const std::string& name, uint64_t value) { auto property = std::find_if(m_propsInfo.begin(), m_propsInfo.end(), @@ -130,3 +149,14 @@ bool CDRMObject::SupportsProperty(const std::string& name) return false; } + +std::optional CDRMObject::IsPropertyImmutable(const std::string& name) +{ + auto property = std::find_if(m_propsInfo.begin(), m_propsInfo.end(), + [&name](const auto& prop) { return prop->name == name; }); + + if (property == m_propsInfo.end()) + return {}; + + return static_cast(drm_property_type_is(property->get(), DRM_MODE_PROP_IMMUTABLE)); +} diff --git a/xbmc/windowing/gbm/drm/DRMObject.h b/xbmc/windowing/gbm/drm/DRMObject.h index c4200b1a86..bee880de20 100644 --- a/xbmc/windowing/gbm/drm/DRMObject.h +++ b/xbmc/windowing/gbm/drm/DRMObject.h @@ -40,6 +40,8 @@ public: bool SetProperty(const std::string& name, uint64_t value); bool SupportsProperty(const std::string& name); + std::optional IsPropertyImmutable(const std::string& name); + std::optional GetRangePropertyLimits(std::string_view name); protected: explicit CDRMObject(int fd); diff --git a/xbmc/windowing/gbm/drm/DRMUtils.cpp b/xbmc/windowing/gbm/drm/DRMUtils.cpp index 3dd4ee9783..e3aab14d3a 100644 --- a/xbmc/windowing/gbm/drm/DRMUtils.cpp +++ b/xbmc/windowing/gbm/drm/DRMUtils.cpp @@ -181,20 +181,23 @@ bool CDRMUtils::FindPreferredMode() return true; } -bool CDRMUtils::FindPlanes() +bool CDRMUtils::FindPlanes(uint32_t format, uint64_t modifier) { for (size_t i = 0; i < m_crtcs.size(); i++) { if (!(m_encoder->GetPossibleCrtcs() & (1 << i))) continue; - auto videoPlane = std::find_if(m_planes.begin(), m_planes.end(), [&i](auto& plane) { - if (plane->GetPossibleCrtcs() & (1 << i)) - { - return plane->SupportsFormat(DRM_FORMAT_NV12); - } - return false; - }); + auto videoPlane = + std::find_if(m_planes.begin(), m_planes.end(), + [&i, &format, &modifier](auto& plane) + { + if (plane->GetPossibleCrtcs() & (1 << i)) + { + return plane->SupportsFormatAndModifier(format, modifier); + } + return false; + }); uint32_t videoPlaneId{0}; @@ -467,7 +470,7 @@ bool CDRMUtils::InitDrm() if (!FindCrtc()) return false; - if (!FindPlanes()) + if (!FindPlanes(DRM_FORMAT_NV12, DRM_FORMAT_MOD_LINEAR)) return false; if (!FindPreferredMode()) diff --git a/xbmc/windowing/gbm/drm/DRMUtils.h b/xbmc/windowing/gbm/drm/DRMUtils.h index f92f716fc4..fcf9d772e3 100644 --- a/xbmc/windowing/gbm/drm/DRMUtils.h +++ b/xbmc/windowing/gbm/drm/DRMUtils.h @@ -64,6 +64,7 @@ public: static uint32_t FourCCWithoutAlpha(uint32_t fourcc); void SetInFenceFd(int fd) { m_inFenceFd = fd; } + bool FindPlanes(uint32_t format, uint64_t modifier); int TakeOutFenceFd() { int fd{-1}; @@ -89,13 +90,13 @@ protected: int m_inFenceFd{-1}; int m_outFenceFd{-1}; + std::vector> m_crtcs; std::vector> m_planes; private: bool FindConnector(); bool FindEncoder(); bool FindCrtc(); - bool FindPlanes(); bool FindPreferredMode(); bool RestoreOriginalMode(); RESOLUTION_INFO GetResolutionInfo(drmModeModeInfoPtr mode); @@ -106,7 +107,6 @@ private: std::vector> m_connectors; std::vector> m_encoders; - std::vector> m_crtcs; }; } -- 2.43.0