aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSameer Lattannavar <sameer.lattannavar@intel.com>2020-10-07 02:08:49 +0000
committerSameer Lattannavar <sameer.lattannavar@intel.com>2020-10-07 02:08:49 +0000
commit6c83de91fa492e3aba0288de95d4dd8656a9d07b (patch)
tree160c84769913f0c864f29a28900898e5a5dda7de
parentad486e359d4b0f294d6b8aac754bdc96e9df6042 (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.h2
-rw-r--r--xbmc/windowing/gbm/DRMAtomic.cpp86
-rw-r--r--xbmc/windowing/gbm/DRMAtomic.h10
-rw-r--r--xbmc/windowing/gbm/WinSystemGbm.cpp21
-rw-r--r--xbmc/windowing/gbm/WinSystemGbm.h2
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);