platforms/drm: support underscan
This commit is contained in:
parent
5fe6de699c
commit
925ff96401
4 changed files with 60 additions and 6 deletions
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue