From 925ff9640190cb7523b176ea95aaecccf93329d6 Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Tue, 22 Jun 2021 23:28:08 +0200 Subject: [PATCH] platforms/drm: support underscan --- src/plugins/platforms/drm/drm_object.h | 8 ++++ .../platforms/drm/drm_object_connector.cpp | 39 +++++++++++++++++-- .../platforms/drm/drm_object_connector.h | 11 +++++- src/plugins/platforms/drm/drm_output.cpp | 8 +++- 4 files changed, 60 insertions(+), 6 deletions(-) diff --git a/src/plugins/platforms/drm/drm_object.h b/src/plugins/platforms/drm/drm_object.h index 59221ef9bd..cffe47e49e 100644 --- a/src/plugins/platforms/drm/drm_object.h +++ b/src/plugins/platforms/drm/drm_object.h @@ -122,6 +122,14 @@ protected: bool hasEnum(uint64_t value) const { return m_enumMap.contains(value); } + template + bool setEnum(T index) { + if (hasEnum(static_cast(index))) { + setValue(m_enumMap[static_cast(index)]); + return true; + } + return false; + } uint32_t propId() const { return m_propId; diff --git a/src/plugins/platforms/drm/drm_object_connector.cpp b/src/plugins/platforms/drm/drm_object_connector.cpp index c617d5b468..5921425436 100644 --- a/src/plugins/platforms/drm/drm_object_connector.cpp +++ b/src/plugins/platforms/drm/drm_object_connector.cpp @@ -49,6 +49,13 @@ bool DrmConnector::init() PropertyDefinition(QByteArrayLiteral("EDID")), PropertyDefinition(QByteArrayLiteral("overscan")), PropertyDefinition(QByteArrayLiteral("vrr_capable")), + PropertyDefinition(QByteArrayLiteral("underscan")), + PropertyDefinition(QByteArrayLiteral("underscan vborder")), + PropertyDefinition(QByteArrayLiteral("underscan hborder"), { + QByteArrayLiteral("off"), + QByteArrayLiteral("on"), + QByteArrayLiteral("auto") + }), }, DRM_MODE_OBJECT_CONNECTOR)) { return false; } @@ -59,6 +66,17 @@ bool DrmConnector::init() qCDebug(KWIN_DRM) << "Could not find DPMS property!"; } + auto underscan = m_props[static_cast(PropertyIndex::Underscan)]; + auto vborder = m_props[static_cast(PropertyIndex::Underscan_vborder)]; + auto hborder = m_props[static_cast(PropertyIndex::Underscan_hborder)]; + if (underscan && vborder && hborder) { + underscan->setEnum(vborder->value() > 0 ? UnderscanOptions::On : UnderscanOptions::Off); + } else { + deleteProp(PropertyIndex::Underscan); + deleteProp(PropertyIndex::Underscan_vborder); + deleteProp(PropertyIndex::Underscan_hborder); + } + // parse edid auto edidProp = m_props[static_cast(PropertyIndex::Edid)]; if (edidProp && edidProp->blob() && edidProp->blob()->data) { @@ -152,20 +170,35 @@ QSize DrmConnector::physicalSize() const bool DrmConnector::hasOverscan() const { - return m_props[static_cast(PropertyIndex::Overscan)]; + return m_props[static_cast(PropertyIndex::Overscan)] || m_props[static_cast(PropertyIndex::Underscan)]; } uint32_t DrmConnector::overscan() const { if (const auto &prop = m_props[static_cast(PropertyIndex::Overscan)]) { return prop->value(); + } else if (const auto &prop = m_props[static_cast(PropertyIndex::Underscan_vborder)]) { + return prop->value(); } return 0; } -void DrmConnector::setOverscan(uint32_t overscan) +void DrmConnector::setOverscan(uint32_t overscan, const QSize &modeSize) { - setValue(PropertyIndex::Overscan, overscan); + if (auto prop = m_props[static_cast(PropertyIndex::Overscan)]) { + prop->setValue(overscan); + } else if (auto prop = m_props[static_cast(PropertyIndex::Underscan)]) { + float aspectRatio = modeSize.width() / static_cast(modeSize.height()); + prop->setEnum(overscan > 0 ? UnderscanOptions::On : UnderscanOptions::Off); + uint32_t hborder = overscan / aspectRatio; + if (hborder > 128) { + hborder = 128; + overscan = 128 * aspectRatio; + } + // overscan only goes from 0-100 so we cut off the 101-128 value range of underscan_vborder + setValue(PropertyIndex::Underscan_vborder, overscan); + setValue(PropertyIndex::Underscan_hborder, hborder); + } } bool DrmConnector::vrrCapable() const diff --git a/src/plugins/platforms/drm/drm_object_connector.h b/src/plugins/platforms/drm/drm_object_connector.h index 547ad9a53a..34dedafd7c 100644 --- a/src/plugins/platforms/drm/drm_object_connector.h +++ b/src/plugins/platforms/drm/drm_object_connector.h @@ -32,9 +32,18 @@ public: Edid = 3, Overscan = 4, VrrCapable = 5, + Underscan = 6, + Underscan_vborder = 7, + Underscan_hborder = 8, Count }; + enum class UnderscanOptions : uint32_t { + Off = 0, + On = 1, + Auto = 2, + }; + QVector encoders() { return m_encoders; } @@ -65,7 +74,7 @@ public: bool hasOverscan() const; uint32_t overscan() const; - void setOverscan(uint32_t overscan); + void setOverscan(uint32_t overscan, const QSize &modeSize); bool vrrCapable() const; diff --git a/src/plugins/platforms/drm/drm_output.cpp b/src/plugins/platforms/drm/drm_output.cpp index 5632c792a1..4af3bde5c5 100644 --- a/src/plugins/platforms/drm/drm_output.cpp +++ b/src/plugins/platforms/drm/drm_output.cpp @@ -572,6 +572,8 @@ void DrmOutput::updateMode(int modeIndex) } m_mode = connector->modes[modeIndex]; m_modesetRequested = true; + // aspect ratio might need to be adjusted + m_conn->setOverscan(m_conn->overscan(), modeSize()); setCurrentModeInternal(); } @@ -685,6 +687,8 @@ bool DrmOutput::presentAtomically(const QSharedPointer &buffer) updateCursor(); showCursor(); } + // aspect ratio might need to be adjusted + m_conn->setOverscan(m_conn->overscan(), modeSize()); setCurrentModeInternal(); Q_EMIT screens()->changed(); } @@ -909,8 +913,8 @@ bool DrmOutput::setGammaRamp(const GammaRamp &gamma) void DrmOutput::setOverscan(uint32_t overscan) { if (m_conn->hasOverscan() && overscan <= 100) { - m_conn->setOverscan(overscan); - setOverscanInternal(overscan); + m_conn->setOverscan(overscan, modeSize()); + setOverscanInternal(m_conn->overscan()); } }