aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorboogie <boogiepop@gmx.com>2024-01-13 19:39:52 +0100
committerboogie <boogiepop@gmx.com>2024-10-04 23:51:07 +0200
commitcfb130d42a8fce7fc6a12015e34a9df8388e47de (patch)
tree32cc8e410f70b2527c7629c29ee274ae00bfe45b
parentf02afef0f39f8a3770d0e9fd5483e8a53a1814d7 (diff)
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.
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIME.cpp2
-rw-r--r--xbmc/windowing/gbm/drm/DRMObject.cpp30
-rw-r--r--xbmc/windowing/gbm/drm/DRMObject.h3
-rw-r--r--xbmc/windowing/gbm/drm/DRMUtils.cpp169
-rw-r--r--xbmc/windowing/gbm/drm/DRMUtils.h5
5 files changed, 149 insertions, 60 deletions
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIME.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIME.cpp
index 66df0e49c7..2ef7f4d521 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIME.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererDRMPRIME.cpp
@@ -77,7 +77,7 @@ CBaseRenderer* CRendererDRMPRIME::Create(CVideoBuffer* buffer)
if (!plane)
return nullptr;
- if (!plane->SupportsFormatAndModifier(format, modifier))
+ if (!drm->FindVideoPlane(format, modifier))
return nullptr;
return new CRendererDRMPRIME();
diff --git a/xbmc/windowing/gbm/drm/DRMObject.cpp b/xbmc/windowing/gbm/drm/DRMObject.cpp
index 5ffce40fa3..99dda24490 100644
--- a/xbmc/windowing/gbm/drm/DRMObject.cpp
+++ b/xbmc/windowing/gbm/drm/DRMObject.cpp
@@ -105,6 +105,25 @@ std::optional<uint64_t> CDRMObject::GetPropertyValue(std::string_view name,
return {};
}
+std::optional<std::span<uint64_t, 2>> 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<bool>(drm_property_type_is(prop, DRM_MODE_PROP_RANGE)))
+ return {};
+
+ if (prop->count_values != 2)
+ return {};
+
+ return std::make_optional<std::span<uint64_t, 2>>(prop->values, 2);
+}
+
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<bool> CDRMObject::IsPropertyImmutable(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 {};
+
+ return static_cast<bool>(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..39ba28a004 100644
--- a/xbmc/windowing/gbm/drm/DRMObject.h
+++ b/xbmc/windowing/gbm/drm/DRMObject.h
@@ -12,6 +12,7 @@
#include <cstdint>
#include <memory>
#include <optional>
+#include <span>
#include <string_view>
#include <vector>
@@ -40,6 +41,8 @@ public:
bool SetProperty(const std::string& name, uint64_t value);
bool SupportsProperty(const std::string& name);
+ std::optional<bool> IsPropertyImmutable(std::string_view name);
+ std::optional<std::span<uint64_t, 2>> 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..22db758ab6 100644
--- a/xbmc/windowing/gbm/drm/DRMUtils.cpp
+++ b/xbmc/windowing/gbm/drm/DRMUtils.cpp
@@ -181,77 +181,130 @@ bool CDRMUtils::FindPreferredMode()
return true;
}
-bool CDRMUtils::FindPlanes()
+bool CDRMUtils::FindGuiPlane()
{
- for (size_t i = 0; i < m_crtcs.size(); i++)
- {
- if (!(m_encoder->GetPossibleCrtcs() & (1 << i)))
+ /* find the gui plane which support ARGB and 8bit or 10 bit XRGB
+ * prefer the one which does not support NV12, because it can be re-used in future for video
+ * prefer the highest id number because they are listed on top where zpos is not available
+ * and use the gui plane crtc as the crtc
+ * */
+ CDRMPlane* gui_plane_nv12{nullptr};
+ CDRMPlane* gui_plane{nullptr};
+ CDRMCrtc* gui_crtc_nv12{nullptr};
+ CDRMCrtc* gui_crtc{nullptr};
+
+ for (size_t crtc_offset = 0; crtc_offset < m_crtcs.size(); crtc_offset++)
+ {
+ if (!(m_encoder->GetPossibleCrtcs() & (1 << crtc_offset)))
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;
- });
-
- uint32_t videoPlaneId{0};
-
- if (videoPlane != m_planes.end())
- videoPlaneId = videoPlane->get()->GetPlaneId();
-
- auto guiPlane =
- std::find_if(m_planes.begin(), m_planes.end(), [&i, &videoPlaneId](auto& plane) {
- if (plane->GetPossibleCrtcs() & (1 << i))
- {
- return (plane->GetPlaneId() != videoPlaneId &&
- (videoPlaneId == 0 || plane->SupportsFormat(DRM_FORMAT_ARGB8888)) &&
- (plane->SupportsFormat(DRM_FORMAT_XRGB2101010) ||
- plane->SupportsFormat(DRM_FORMAT_XRGB8888)));
- }
- return false;
- });
-
- if (videoPlane != m_planes.end() && guiPlane != m_planes.end())
+ for (auto& plane : m_planes)
{
- m_crtc = m_crtcs[i].get();
- m_video_plane = videoPlane->get();
- m_gui_plane = guiPlane->get();
- break;
- }
+ if (!(plane.get()->GetPossibleCrtcs() & (1 << crtc_offset)))
+ continue;
- if (guiPlane != m_planes.end())
- {
- if (!m_crtc && m_encoder->GetCrtcId() == m_crtcs[i]->GetCrtcId())
+ if (plane.get()->SupportsFormat(DRM_FORMAT_ARGB8888) &&
+ (plane.get()->SupportsFormat(DRM_FORMAT_XRGB2101010) ||
+ plane.get()->SupportsFormat(DRM_FORMAT_XRGB8888)))
{
- m_crtc = m_crtcs[i].get();
- m_gui_plane = guiPlane->get();
- m_video_plane = nullptr;
+ if (plane.get()->SupportsFormat(DRM_FORMAT_NV12) &&
+ (gui_plane_nv12 == nullptr || gui_plane_nv12->GetId() < plane.get()->GetId()))
+ {
+ gui_plane_nv12 = plane.get();
+ gui_crtc_nv12 = m_crtcs[crtc_offset].get();
+ }
+ else if (!plane.get()->SupportsFormat(DRM_FORMAT_NV12) &&
+ (gui_plane == nullptr || gui_plane->GetId() < plane.get()->GetId()))
+ {
+ gui_plane = plane.get();
+ gui_crtc = m_crtcs[crtc_offset].get();
+ }
}
}
}
- CLog::Log(LOGINFO, "CDRMUtils::{} - using crtc: {}", __FUNCTION__, m_crtc->GetCrtcId());
-
- // video plane may not be available
- if (m_video_plane)
- CLog::Log(LOGDEBUG, "CDRMUtils::{} - using video plane {}", __FUNCTION__,
- m_video_plane->GetPlaneId());
-
- if (m_gui_plane->SupportsFormat(DRM_FORMAT_XRGB2101010))
+ // fallback to NV12 supporting plane
+ if (gui_plane == nullptr)
{
- m_gui_plane->SetFormat(DRM_FORMAT_XRGB2101010);
- CLog::Log(LOGDEBUG, "CDRMUtils::{} - using 10bit gui plane {}", __FUNCTION__,
- m_gui_plane->GetPlaneId());
+ gui_crtc = gui_crtc_nv12;
+ gui_plane = gui_plane_nv12;
}
- else
+
+ if (gui_plane != nullptr)
{
- m_gui_plane->SetFormat(DRM_FORMAT_XRGB8888);
- CLog::Log(LOGDEBUG, "CDRMUtils::{} - using gui plane {}", __FUNCTION__,
- m_gui_plane->GetPlaneId());
+ m_crtc = gui_crtc;
+ m_gui_plane = gui_plane;
+
+ CLog::Log(LOGINFO, "CDRMUtils::{} - using crtc: {}", __FUNCTION__, m_crtc->GetCrtcId());
+ if (m_gui_plane->SupportsFormat(DRM_FORMAT_XRGB2101010))
+ {
+ m_gui_plane->SetFormat(DRM_FORMAT_XRGB2101010);
+ CLog::Log(LOGDEBUG, "CDRMUtils::{} - using 10bit gui plane {}", __FUNCTION__,
+ m_gui_plane->GetPlaneId());
+ }
+ else
+ {
+ m_gui_plane->SetFormat(DRM_FORMAT_XRGB8888);
+ CLog::Log(LOGDEBUG, "CDRMUtils::{} - using gui plane {}", __FUNCTION__,
+ m_gui_plane->GetPlaneId());
+ }
+ return true;
}
+ CLog::Log(LOGERROR, "CDRMUtils::{} - Can not find a GUI plane", __FUNCTION__);
+ return false;
+}
+
+bool CDRMUtils::FindVideoPlane(uint32_t format, uint64_t modifier)
+{
+ 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(); }));
+
+ auto guiplane_id = m_gui_plane->GetId();
+ auto videoPlane = std::find_if(m_planes.begin(), m_planes.end(),
+ [&crtc_offset, &format, &modifier, &guiplane_id](auto& plane)
+ {
+ if (plane->GetPossibleCrtcs() & (1 << crtc_offset))
+ {
+ return (guiplane_id != plane->GetPlaneId() &&
+ plane->SupportsFormatAndModifier(format, modifier));
+ }
+ return false;
+ });
+
+ if (videoPlane == m_planes.end())
+ {
+ CLog::Log(LOGERROR,
+ "CDRMUtils::{} - Can not find a Video Plane plane for format {}, modifier {}",
+ __FUNCTION__, format, modifier);
+ return false;
+ }
+
+ m_video_plane = videoPlane->get();
+ CLog::Log(LOGDEBUG, "CDRMUtils::{} - using video plane {}", __FUNCTION__,
+ m_video_plane->GetPlaneId());
+
+ if (!supports_zpos || zpos_immutable)
+ return true;
+
+ // re-sort the video and gui planes
+ auto limits = m_gui_plane->GetRangePropertyLimits("zpos");
+
+ if (!limits)
+ return true;
+
+ 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()[1]);
+ CLog::Log(LOGDEBUG, "CDRMUtils::{} - video plane id,zpos: {}, {}", __FUNCTION__,
+ m_video_plane->GetId(), limits.value()[0]);
+
return true;
}
@@ -467,9 +520,11 @@ bool CDRMUtils::InitDrm()
if (!FindCrtc())
return false;
- if (!FindPlanes())
+ if (!FindGuiPlane())
return false;
+ FindVideoPlane(DRM_FORMAT_NV12, DRM_FORMAT_MOD_LINEAR);
+
if (!FindPreferredMode())
return false;
diff --git a/xbmc/windowing/gbm/drm/DRMUtils.h b/xbmc/windowing/gbm/drm/DRMUtils.h
index f92f716fc4..b99a6dc4fe 100644
--- a/xbmc/windowing/gbm/drm/DRMUtils.h
+++ b/xbmc/windowing/gbm/drm/DRMUtils.h
@@ -64,6 +64,8 @@ public:
static uint32_t FourCCWithoutAlpha(uint32_t fourcc);
void SetInFenceFd(int fd) { m_inFenceFd = fd; }
+ bool FindVideoPlane(uint32_t format, uint64_t modifier);
+ bool FindGuiPlane();
int TakeOutFenceFd()
{
int fd{-1};
@@ -89,13 +91,13 @@ protected:
int m_inFenceFd{-1};
int m_outFenceFd{-1};
+ std::vector<std::unique_ptr<CDRMCrtc>> m_crtcs;
std::vector<std::unique_ptr<CDRMPlane>> m_planes;
private:
bool FindConnector();
bool FindEncoder();
bool FindCrtc();
- bool FindPlanes();
bool FindPreferredMode();
bool RestoreOriginalMode();
RESOLUTION_INFO GetResolutionInfo(drmModeModeInfoPtr mode);
@@ -106,7 +108,6 @@ private:
std::vector<std::unique_ptr<CDRMConnector>> m_connectors;
std::vector<std::unique_ptr<CDRMEncoder>> m_encoders;
- std::vector<std::unique_ptr<CDRMCrtc>> m_crtcs;
};
}