platforms/drm: Add support for setting overscan

BUG: 428201
This commit is contained in:
Xaver Hugl 2021-04-11 16:26:21 +02:00
parent ff3cb59967
commit 0292c4a74c
8 changed files with 96 additions and 1 deletions

View file

@ -37,7 +37,10 @@ AbstractWaylandOutput::Capabilities AbstractWaylandOutput::capabilities() const
void AbstractWaylandOutput::setCapabilityInternal(Capability capability, bool on) void AbstractWaylandOutput::setCapabilityInternal(Capability capability, bool on)
{ {
if (static_cast<bool>(m_capabilities & capability) != on) {
m_capabilities.setFlag(capability, on); m_capabilities.setFlag(capability, on);
emit capabilitiesChanged();
}
} }
QString AbstractWaylandOutput::name() const QString AbstractWaylandOutput::name() const
@ -172,6 +175,10 @@ void AbstractWaylandOutput::applyChanges(const KWaylandServer::OutputChangeSet *
setScale(changeSet->scaleF()); setScale(changeSet->scaleF());
emitModeChanged = true; emitModeChanged = true;
} }
if (changeSet->overscanChanged()) {
qCDebug(KWIN_CORE) << "Setting overscan:" << changeSet->overscan();
setOverscan(changeSet->overscan());
}
overallSizeCheckNeeded |= emitModeChanged; overallSizeCheckNeeded |= emitModeChanged;
if (overallSizeCheckNeeded) { if (overallSizeCheckNeeded) {
@ -343,4 +350,22 @@ bool AbstractWaylandOutput::isBeingRecorded()
return m_recorders; return m_recorders;
} }
void AbstractWaylandOutput::setOverscanInternal(uint32_t overscan)
{
if (m_overscan != overscan) {
m_overscan = overscan;
emit overscanChanged();
}
}
uint32_t AbstractWaylandOutput::overscan() const
{
return m_overscan;
}
void AbstractWaylandOutput::setOverscan(uint32_t overscan)
{
Q_UNUSED(overscan);
}
} }

View file

@ -65,6 +65,7 @@ public:
enum class Capability : uint { enum class Capability : uint {
Dpms = 0x1, Dpms = 0x1,
Overscan = 0x2,
}; };
Q_DECLARE_FLAGS(Capabilities, Capability) Q_DECLARE_FLAGS(Capabilities, Capability)
@ -128,6 +129,9 @@ public:
DpmsMode dpmsMode() const; DpmsMode dpmsMode() const;
virtual void setDpmsMode(DpmsMode mode); virtual void setDpmsMode(DpmsMode mode);
uint32_t overscan() const;
virtual void setOverscan(uint32_t overscan);
/** /**
* Returns a matrix that can translate into the display's coordinates system * Returns a matrix that can translate into the display's coordinates system
*/ */
@ -144,6 +148,8 @@ Q_SIGNALS:
void scaleChanged(); void scaleChanged();
void transformChanged(); void transformChanged();
void dpmsModeChanged(); void dpmsModeChanged();
void capabilitiesChanged();
void overscanChanged();
protected: protected:
void initialize(const QString &model, const QString &manufacturer, void initialize(const QString &model, const QString &manufacturer,
@ -178,6 +184,7 @@ protected:
void setDpmsModeInternal(DpmsMode dpmsMode); void setDpmsModeInternal(DpmsMode dpmsMode);
void setCapabilityInternal(Capability capability, bool on = true); void setCapabilityInternal(Capability capability, bool on = true);
void setSubPixelInternal(SubPixel subPixel); void setSubPixelInternal(SubPixel subPixel);
void setOverscanInternal(uint32_t overscan);
QSize orientateSize(const QSize &size) const; QSize orientateSize(const QSize &size) const;
@ -202,6 +209,7 @@ private:
int m_recorders = 0; int m_recorders = 0;
bool m_isEnabled = true; bool m_isEnabled = true;
bool m_internal = false; bool m_internal = false;
uint32_t m_overscan = 0;
}; };
} }

View file

@ -62,6 +62,7 @@ bool DrmConnector::init()
PropertyDefinition(QByteArrayLiteral("non-desktop")), PropertyDefinition(QByteArrayLiteral("non-desktop")),
PropertyDefinition(QByteArrayLiteral("DPMS")), PropertyDefinition(QByteArrayLiteral("DPMS")),
PropertyDefinition(QByteArrayLiteral("EDID")), PropertyDefinition(QByteArrayLiteral("EDID")),
PropertyDefinition(QByteArrayLiteral("overscan")),
}, DRM_MODE_OBJECT_CONNECTOR)) { }, DRM_MODE_OBJECT_CONNECTOR)) {
return false; return false;
} }
@ -206,6 +207,22 @@ AbstractWaylandOutput::SubPixel DrmConnector::subpixel() const
} }
} }
bool DrmConnector::hasOverscan() const
{
return m_props[static_cast<uint32_t>(PropertyIndex::Overscan)];
}
uint32_t DrmConnector::overscan() const
{
if (const auto &prop = m_props[static_cast<uint32_t>(PropertyIndex::Overscan)]) {
return prop->value();
}
return 0;
}
void DrmConnector::setOverscan(uint32_t overscan)
{
setValue(PropertyIndex::Overscan, overscan);
}
} }

View file

@ -35,6 +35,7 @@ public:
NonDesktop = 1, NonDesktop = 1,
Dpms = 2, Dpms = 2,
Edid = 3, Edid = 3,
Overscan = 4,
Count Count
}; };
@ -82,6 +83,10 @@ public:
AbstractWaylandOutput::SubPixel subpixel() const; AbstractWaylandOutput::SubPixel subpixel() const;
bool hasOverscan() const;
uint32_t overscan() const;
void setOverscan(uint32_t overscan);
private: private:
DrmScopedPointer<drmModeConnector> m_conn; DrmScopedPointer<drmModeConnector> m_conn;
QVector<uint32_t> m_encoders; QVector<uint32_t> m_encoders;

View file

@ -158,6 +158,10 @@ bool DrmOutput::init()
setSubPixelInternal(m_conn->subpixel()); setSubPixelInternal(m_conn->subpixel());
setInternal(m_conn->isInternal()); setInternal(m_conn->isInternal());
setCapabilityInternal(Capability::Dpms); setCapabilityInternal(Capability::Dpms);
if (m_conn->hasOverscan()) {
setCapabilityInternal(Capability::Overscan);
setOverscanInternal(m_conn->overscan());
}
initOutputDevice(); initOutputDevice();
m_pipeline = new DrmPipeline(this, m_gpu, m_conn, m_crtc, m_primaryPlane, m_cursorPlane); m_pipeline = new DrmPipeline(this, m_gpu, m_conn, m_crtc, m_primaryPlane, m_cursorPlane);
@ -417,4 +421,12 @@ bool DrmOutput::setGammaRamp(const GammaRamp &gamma)
return m_pipeline->setGammaRamp(gamma); return m_pipeline->setGammaRamp(gamma);
} }
void DrmOutput::setOverscan(uint32_t overscan)
{
if (m_conn->hasOverscan() && overscan <= 100) {
m_conn->setOverscan(overscan);
setOverscanInternal(overscan);
}
}
} }

View file

@ -102,6 +102,7 @@ private:
int gammaRampSize() const override; int gammaRampSize() const override;
bool setGammaRamp(const GammaRamp &gamma) override; bool setGammaRamp(const GammaRamp &gamma) override;
void setOverscan(uint32_t overscan) override;
DrmBackend *m_backend; DrmBackend *m_backend;
DrmGpu *m_gpu; DrmGpu *m_gpu;

View file

@ -20,6 +20,15 @@ static KWaylandServer::OutputDeviceInterface::SubPixel kwinSubPixelToOutputDevic
return static_cast<KWaylandServer::OutputDeviceInterface::SubPixel>(subPixel); return static_cast<KWaylandServer::OutputDeviceInterface::SubPixel>(subPixel);
} }
static KWaylandServer::OutputDeviceInterface::Capabilities kwinCapabilitiesToOutputDeviceCapabilities(AbstractWaylandOutput::Capabilities caps)
{
KWaylandServer::OutputDeviceInterface::Capabilities ret;
if (caps & AbstractWaylandOutput::Capability::Overscan) {
ret |= KWaylandServer::OutputDeviceInterface::Capability::Overscan;
}
return ret;
}
WaylandOutputDevice::WaylandOutputDevice(AbstractWaylandOutput *output, QObject *parent) WaylandOutputDevice::WaylandOutputDevice(AbstractWaylandOutput *output, QObject *parent)
: QObject(parent) : QObject(parent)
, m_platformOutput(output) , m_platformOutput(output)
@ -36,6 +45,8 @@ WaylandOutputDevice::WaylandOutputDevice(AbstractWaylandOutput *output, QObject
m_outputDevice->setEisaId(output->eisaId()); m_outputDevice->setEisaId(output->eisaId());
m_outputDevice->setSerialNumber(output->serialNumber()); m_outputDevice->setSerialNumber(output->serialNumber());
m_outputDevice->setSubPixel(kwinSubPixelToOutputDeviceSubPixel(output->subPixel())); m_outputDevice->setSubPixel(kwinSubPixelToOutputDeviceSubPixel(output->subPixel()));
m_outputDevice->setOverscan(output->overscan());
m_outputDevice->setCapabilities(kwinCapabilitiesToOutputDeviceCapabilities(output->capabilities()));
const auto modes = output->modes(); const auto modes = output->modes();
for (const AbstractWaylandOutput::Mode &mode : modes) { for (const AbstractWaylandOutput::Mode &mode : modes) {
@ -64,6 +75,10 @@ WaylandOutputDevice::WaylandOutputDevice(AbstractWaylandOutput *output, QObject
this, &WaylandOutputDevice::handleTransformChanged); this, &WaylandOutputDevice::handleTransformChanged);
connect(output, &AbstractWaylandOutput::modeChanged, connect(output, &AbstractWaylandOutput::modeChanged,
this, &WaylandOutputDevice::handleModeChanged); this, &WaylandOutputDevice::handleModeChanged);
connect(output, &AbstractWaylandOutput::capabilitiesChanged,
this, &WaylandOutputDevice::handleCapabilitiesChanged);
connect(output, &AbstractWaylandOutput::overscanChanged,
this, &WaylandOutputDevice::handleOverscanChanged);
} }
void WaylandOutputDevice::handleGeometryChanged() void WaylandOutputDevice::handleGeometryChanged()
@ -95,4 +110,14 @@ void WaylandOutputDevice::handleModeChanged()
m_outputDevice->setCurrentMode(m_platformOutput->modeSize(), m_platformOutput->refreshRate()); m_outputDevice->setCurrentMode(m_platformOutput->modeSize(), m_platformOutput->refreshRate());
} }
void WaylandOutputDevice::handleCapabilitiesChanged()
{
m_outputDevice->setCapabilities(kwinCapabilitiesToOutputDeviceCapabilities(m_platformOutput->capabilities()));
}
void WaylandOutputDevice::handleOverscanChanged()
{
m_outputDevice->setOverscan(m_platformOutput->overscan());
}
} // namespace KWin } // namespace KWin

View file

@ -26,6 +26,8 @@ private Q_SLOTS:
void handleEnabledChanged(); void handleEnabledChanged();
void handleTransformChanged(); void handleTransformChanged();
void handleModeChanged(); void handleModeChanged();
void handleCapabilitiesChanged();
void handleOverscanChanged();
private: private:
AbstractWaylandOutput *m_platformOutput; AbstractWaylandOutput *m_platformOutput;