platforms/drm: support underscan

This commit is contained in:
Xaver Hugl 2021-06-22 23:28:08 +02:00
parent 5fe6de699c
commit 925ff96401
4 changed files with 60 additions and 6 deletions

View file

@ -122,6 +122,14 @@ protected:
bool hasEnum(uint64_t value) const {
return m_enumMap.contains(value);
}
template <typename T>
bool setEnum(T index) {
if (hasEnum(static_cast<uint64_t>(index))) {
setValue(m_enumMap[static_cast<uint32_t>(index)]);
return true;
}
return false;
}
uint32_t propId() const {
return m_propId;

View file

@ -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<uint32_t>(PropertyIndex::Underscan)];
auto vborder = m_props[static_cast<uint32_t>(PropertyIndex::Underscan_vborder)];
auto hborder = m_props[static_cast<uint32_t>(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<uint32_t>(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<uint32_t>(PropertyIndex::Overscan)];
return m_props[static_cast<uint32_t>(PropertyIndex::Overscan)] || m_props[static_cast<uint32_t>(PropertyIndex::Underscan)];
}
uint32_t DrmConnector::overscan() const
{
if (const auto &prop = m_props[static_cast<uint32_t>(PropertyIndex::Overscan)]) {
return prop->value();
} else if (const auto &prop = m_props[static_cast<uint32_t>(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<uint32_t>(PropertyIndex::Overscan)]) {
prop->setValue(overscan);
} else if (auto prop = m_props[static_cast<uint32_t>(PropertyIndex::Underscan)]) {
float aspectRatio = modeSize.width() / static_cast<float>(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

View file

@ -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<uint32_t> 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;

View file

@ -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<DrmBuffer> &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());
}
}