diff options
author | Sameer Lattannavar <sameer.lattannavar@intel.com> | 2020-10-07 02:08:49 +0000 |
---|---|---|
committer | Sameer Lattannavar <sameer.lattannavar@intel.com> | 2020-10-07 02:08:49 +0000 |
commit | 6c83de91fa492e3aba0288de95d4dd8656a9d07b (patch) | |
tree | 160c84769913f0c864f29a28900898e5a5dda7de | |
parent | ad486e359d4b0f294d6b8aac754bdc96e9df6042 (diff) |
[DRMAtomic] add scaling_filter property support at plane level
As part of
https://software.intel.com/en-us/articles/integer-scaling-support-on-intel-graphics
this work, enabling integer scaling for better Pixel Art games at plane level.
This commit has 4 parts in it:
1) adding SCALING_FILTER property support at plane level only when
user toggles Setting "Display hardware scaling filter" at Settings->System->Display
2) calculating scaling factor based on source & destination
resolutions with maintaing the aspect ratio.
3) reading DRM property for right Scaling Filter eg: "Nearest Neighbor"
4) retaining default behavior when user does not toggle the setting
Ref:Kernel changes are floated at https://patchwork.freedesktop.org/series/73883/#rev7
Date: Wed Sep 02 2020
Addressing review comments on:
1) Code readability
2) Variable Assignment & usage
3) Checking for 'nullptr' for Settings when read
Date: Tue Sep 08 2020
Addressed further review comments on formatting.
Date: Sun Oct 04 2020
Exposing 'CWinSystemGbm::SetDisplayHardwareScaling' to Kodi core. Usage of this
function is to pass windowSystem resolution to DRM.
Signed-off-by: Sameer Lattannavar <sameer.lattannavar@intel.com>
Signed-off-by: Garrett Brown <themagnificentmrb@gmail.com>
-rw-r--r-- | xbmc/windowing/WinSystem.h | 2 | ||||
-rw-r--r-- | xbmc/windowing/gbm/DRMAtomic.cpp | 86 | ||||
-rw-r--r-- | xbmc/windowing/gbm/DRMAtomic.h | 10 | ||||
-rw-r--r-- | xbmc/windowing/gbm/WinSystemGbm.cpp | 21 | ||||
-rw-r--r-- | xbmc/windowing/gbm/WinSystemGbm.h | 2 |
5 files changed, 117 insertions, 4 deletions
diff --git a/xbmc/windowing/WinSystem.h b/xbmc/windowing/WinSystem.h index 751bbde0f8..076d915b04 100644 --- a/xbmc/windowing/WinSystem.h +++ b/xbmc/windowing/WinSystem.h @@ -57,6 +57,8 @@ public: virtual bool DestroyWindow(){ return false; } virtual bool ResizeWindow(int newWidth, int newHeight, int newLeft, int newTop) = 0; virtual bool SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays) = 0; + virtual bool DisplayHardwareScalingEnabled() { return false; } + virtual void UpdateDisplayHardwareScaling(const RESOLUTION_INFO& resInfo) { } virtual bool MoveWindow(int topLeft, int topRight){return false;} virtual void FinishModeChange(RESOLUTION res){} virtual void FinishWindowResize(int newWidth, int newHeight) {ResizeWindow(newWidth, newHeight, -1, -1);} diff --git a/xbmc/windowing/gbm/DRMAtomic.cpp b/xbmc/windowing/gbm/DRMAtomic.cpp index 092ad3fc18..076a35b701 100644 --- a/xbmc/windowing/gbm/DRMAtomic.cpp +++ b/xbmc/windowing/gbm/DRMAtomic.cpp @@ -12,6 +12,8 @@ #include "guilib/GUIComponent.h" #include "guilib/GUIWindowManager.h" #include "settings/Settings.h" +#include "settings/SettingsComponent.h" +#include "settings/lib/Setting.h" #include "utils/log.h" #include <errno.h> @@ -23,6 +25,57 @@ using namespace KODI::WINDOWING::GBM; +const std::string CDRMAtomic::SETTING_VIDEOSCREEN_HW_SCALING_FILTER = "videoscreen.hwscalingfilter"; + +enum drm_scaling_filter +{ + DRM_SCALING_FILTER_DEFAULT, + DRM_SCALING_FILTER_NEAREST_NEIGHBOR, +}; + +uint32_t CDRMAtomic::GetScalingFilterType(const char* type) +{ + if (!strcmp(type, "Nearest Neighbor")) + return DRM_SCALING_FILTER_NEAREST_NEIGHBOR; + else + return DRM_SCALING_FILTER_DEFAULT; +} + +uint32_t CDRMAtomic::GetScalingFactor(uint32_t srcWidth, + uint32_t srcHeight, + uint32_t destWidth, + uint32_t destHeight) +{ + uint32_t factor_W = destWidth / srcWidth; + uint32_t factor_H = destHeight / srcHeight; + if (factor_W != factor_H) + return (factor_W < factor_H) ? factor_W : factor_H; + return factor_W; +} + +bool CDRMAtomic::SetScalingFilter(struct drm_object* object, const char* name, const char* type) +{ + uint32_t filter_type = GetScalingFilterType(type); + if (SupportsPropertyAndValue(object, name, filter_type)) + { + if (AddProperty(object, name, filter_type)) + { + CLog::Log(LOGDEBUG, "CDRMAtomic::{}, Original Window size: {}x{}", __FUNCTION__, m_width, + m_height); + uint32_t mar_scale_factor = + GetScalingFactor(m_width, m_height, m_mode->hdisplay, m_mode->vdisplay); + uint32_t diff_w = m_mode->hdisplay - (mar_scale_factor * m_width); + uint32_t diff_h = m_mode->vdisplay - (mar_scale_factor * m_height); + AddProperty(object, "CRTC_X", (diff_w / 2)); + AddProperty(object, "CRTC_Y", (diff_h / 2)); + AddProperty(object, "CRTC_W", (mar_scale_factor * m_width)); + AddProperty(object, "CRTC_H", (mar_scale_factor * m_height)); + return true; + } + } + return false; +} + void CDRMAtomic::DrmAtomicCommit(int fb_id, int flags, bool rendered, bool videoLayer) { uint32_t blob_id; @@ -71,10 +124,18 @@ void CDRMAtomic::DrmAtomicCommit(int fb_id, int flags, bool rendered, bool video AddProperty(m_gui_plane, "SRC_Y", 0); AddProperty(m_gui_plane, "SRC_W", m_width << 16); AddProperty(m_gui_plane, "SRC_H", m_height << 16); - AddProperty(m_gui_plane, "CRTC_X", 0); - AddProperty(m_gui_plane, "CRTC_Y", 0); - AddProperty(m_gui_plane, "CRTC_W", m_mode->hdisplay); - AddProperty(m_gui_plane, "CRTC_H", m_mode->vdisplay); + if (DislayHardwareScalingEnabled()) + { + SetScalingFilter(m_gui_plane, "SCALING_FILTER", "Nearest Neighbor"); + } + else + { + AddProperty(m_gui_plane, "CRTC_X", 0); + AddProperty(m_gui_plane, "CRTC_Y", 0); + AddProperty(m_gui_plane, "CRTC_W", m_mode->hdisplay); + AddProperty(m_gui_plane, "CRTC_H", m_mode->vdisplay); + } + } else if (videoLayer && !CServiceBroker::GetGUI()->GetWindowManager().HasVisibleControls()) { @@ -165,6 +226,13 @@ bool CDRMAtomic::InitDrm() } CLog::Log(LOGDEBUG, "CDRMAtomic::%s - initialized atomic DRM", __FUNCTION__); + if (SupportsProperty(m_gui_plane, "SCALING_FILTER")) + { + const std::shared_ptr<CSettings> settings = + CServiceBroker::GetSettingsComponent()->GetSettings(); + settings->GetSetting(SETTING_VIDEOSCREEN_HW_SCALING_FILTER)->SetVisible(true); + } + return true; } @@ -241,3 +309,13 @@ bool CDRMAtomic::ResetPlanes() return true; } + +bool CDRMAtomic::DislayHardwareScalingEnabled() +{ + auto settings = CServiceBroker::GetSettingsComponent()->GetSettings(); + + if (settings && settings->GetBool(SETTING_VIDEOSCREEN_HW_SCALING_FILTER)) + return true; + + return false; +} diff --git a/xbmc/windowing/gbm/DRMAtomic.h b/xbmc/windowing/gbm/DRMAtomic.h index d08d72e3fc..528d1db8e2 100644 --- a/xbmc/windowing/gbm/DRMAtomic.h +++ b/xbmc/windowing/gbm/DRMAtomic.h @@ -28,11 +28,21 @@ public: bool InitDrm() override; void DestroyDrm() override; bool AddProperty(struct drm_object* object, const char* name, uint64_t value) override; + static bool DislayHardwareScalingEnabled(); private: void DrmAtomicCommit(int fb_id, int flags, bool rendered, bool videoLayer); bool ResetPlanes(); + uint32_t GetScalingFilterType(const char* type); + uint32_t GetScalingFactor(uint32_t srcWidth, + uint32_t srcHeight, + uint32_t destWidth, + uint32_t destHeight); + bool SetScalingFilter(struct drm_object *object, const char *name, const char *type); + + static const std::string SETTING_VIDEOSCREEN_HW_SCALING_FILTER; + bool m_need_modeset; bool m_active = true; drmModeAtomicReq *m_req = nullptr; diff --git a/xbmc/windowing/gbm/WinSystemGbm.cpp b/xbmc/windowing/gbm/WinSystemGbm.cpp index 87ba41d0de..7f27392f6e 100644 --- a/xbmc/windowing/gbm/WinSystemGbm.cpp +++ b/xbmc/windowing/gbm/WinSystemGbm.cpp @@ -201,6 +201,27 @@ bool CWinSystemGbm::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl return result; } +bool CWinSystemGbm::DisplayHardwareScalingEnabled() +{ + auto drmAtomic = std::dynamic_pointer_cast<CDRMAtomic>(m_DRM); + if (drmAtomic && drmAtomic->DislayHardwareScalingEnabled()) + return true; + + return false; +} + +void CWinSystemGbm::UpdateDisplayHardwareScaling(const RESOLUTION_INFO& resInfo) +{ + if (!DisplayHardwareScalingEnabled()) + return; + + //! @todo The PR that made the res struct constant was abandoned due to drama. + // It should be const-corrected and changed here. + RESOLUTION_INFO& resMutable = const_cast<RESOLUTION_INFO&>(resInfo); + + SetFullScreen(true, resMutable, false); +} + void CWinSystemGbm::FlipPage(bool rendered, bool videoLayer) { if (m_videoLayerBridge && !videoLayer) diff --git a/xbmc/windowing/gbm/WinSystemGbm.h b/xbmc/windowing/gbm/WinSystemGbm.h index f13ba27dd3..944be57175 100644 --- a/xbmc/windowing/gbm/WinSystemGbm.h +++ b/xbmc/windowing/gbm/WinSystemGbm.h @@ -40,6 +40,8 @@ public: bool ResizeWindow(int newWidth, int newHeight, int newLeft, int newTop) override; bool SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays) override; + bool DisplayHardwareScalingEnabled() override; + void UpdateDisplayHardwareScaling(const RESOLUTION_INFO& resInfo) override; void FlipPage(bool rendered, bool videoLayer); |