diff options
author | Markus Härer <markus.haerer@gmx.net> | 2024-10-09 23:57:33 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-09 23:57:33 +0200 |
commit | bf45dda56f7db137303db478073c25e5e0a99cbb (patch) | |
tree | 6a94f3adc45b2baf0ca6dc8d4193f96fd1880701 | |
parent | b4e65aaef8ce82de38caaa3185fa4dad16bc93c2 (diff) | |
parent | ca63e568cf6b5d44652c1b187088c3a8f9675d0d (diff) |
Merge pull request #24431 from hbiyik/gbm_drm_dynamic_afbc_video_planes
Dynamic Selection of DRM planes with GBM
10 files changed, 163 insertions, 65 deletions
diff --git a/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.h b/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.h index b83ee8ca68..dca6e82177 100644 --- a/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.h +++ b/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.h @@ -54,6 +54,8 @@ public: virtual const VideoPicture& GetPicture() const { return m_picture; } virtual uint32_t GetWidth() const { return GetPicture().iWidth; } virtual uint32_t GetHeight() const { return GetPicture().iHeight; } + virtual uint32_t GetXOffset() const { return GetPicture().m_xOffset; } + virtual uint32_t GetYOffset() const { return GetPicture().m_yOffset; } virtual AVDRMFrameDescriptor* GetDescriptor() const = 0; virtual bool IsValid() const { return true; } diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.cpp index 495d6a25f5..a5468d12a0 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.cpp +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.cpp @@ -58,6 +58,8 @@ void VideoPicture::Reset() iWidth = 0; iHeight = 0; + m_xOffset = 0; + m_yOffset = 0; iDisplayWidth = 0; iDisplayHeight = 0; } diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h index ca83b1a04f..f3373612e8 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h @@ -75,6 +75,8 @@ public: unsigned int iWidth; unsigned int iHeight; + unsigned int m_xOffset{0}; + unsigned int m_yOffset{0}; unsigned int iDisplayWidth; //< width of the picture without black bars unsigned int iDisplayHeight; //< height of the picture without black bars diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp index eb2943bb8c..0d407043dd 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp @@ -505,6 +505,8 @@ void CDVDVideoCodecDRMPRIME::SetPictureParams(VideoPicture* pVideoPicture) { pVideoPicture->iWidth = m_pFrame->width; pVideoPicture->iHeight = m_pFrame->height; + pVideoPicture->m_xOffset = m_pFrame->crop_left; + pVideoPicture->m_yOffset = m_pFrame->crop_top; double aspect_ratio = 0; AVRational pixel_aspect = m_pFrame->sample_aspect_ratio; 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/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp index 34d1ab6235..33db29b140 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp @@ -118,9 +118,10 @@ bool CVideoLayerBridgeDRMPRIME::Map(CVideoBufferDRMPRIME* buffer) flags = DRM_MODE_FB_MODIFIERS; // add the video frame FB - ret = drmModeAddFB2WithModifiers(m_DRM->GetFileDescriptor(), buffer->GetWidth(), - buffer->GetHeight(), layer->format, handles, pitches, offsets, - modifier, &buffer->m_fb_id, flags); + ret = drmModeAddFB2WithModifiers(m_DRM->GetFileDescriptor(), + buffer->GetWidth() + buffer->GetXOffset(), + buffer->GetHeight() + buffer->GetYOffset(), layer->format, + handles, pitches, offsets, modifier, &buffer->m_fb_id, flags); if (ret < 0) { CLog::Log(LOGERROR, "CVideoLayerBridgeDRMPRIME::{} - failed to add fb {}, ret = {}", @@ -188,8 +189,8 @@ void CVideoLayerBridgeDRMPRIME::SetVideoPlane(CVideoBufferDRMPRIME* buffer, cons auto plane = m_DRM->GetVideoPlane(); m_DRM->AddProperty(plane, "FB_ID", buffer->m_fb_id); m_DRM->AddProperty(plane, "CRTC_ID", m_DRM->GetCrtc()->GetCrtcId()); - m_DRM->AddProperty(plane, "SRC_X", 0); - m_DRM->AddProperty(plane, "SRC_Y", 0); + m_DRM->AddProperty(plane, "SRC_X", buffer->GetXOffset() << 16); + m_DRM->AddProperty(plane, "SRC_Y", buffer->GetYOffset() << 16); m_DRM->AddProperty(plane, "SRC_W", buffer->GetWidth() << 16); m_DRM->AddProperty(plane, "SRC_H", buffer->GetHeight() << 16); m_DRM->AddProperty(plane, "CRTC_X", static_cast<int32_t>(destRect.x1) & ~1); 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; }; } |