diff --git a/src/plugins/platforms/drm/drm_backend.cpp b/src/plugins/platforms/drm/drm_backend.cpp index 474722e90e..bf77a5cfa2 100644 --- a/src/plugins/platforms/drm/drm_backend.cpp +++ b/src/plugins/platforms/drm/drm_backend.cpp @@ -142,6 +142,7 @@ void DrmBackend::reactivate() m_active = true; for (const auto &output : qAsConst(m_outputs)) { + output->pipeline()->updateProperties(); if (output->isEnabled()) { output->renderLoop()->uninhibit(); output->showCursor(); diff --git a/src/plugins/platforms/drm/drm_object.cpp b/src/plugins/platforms/drm/drm_object.cpp index 10aab5707e..bdbf7329b4 100644 --- a/src/plugins/platforms/drm/drm_object.cpp +++ b/src/plugins/platforms/drm/drm_object.cpp @@ -19,10 +19,13 @@ namespace KWin * Definitions for class DrmObject */ -DrmObject::DrmObject(DrmGpu *gpu, uint32_t objectId) +DrmObject::DrmObject(DrmGpu *gpu, uint32_t objectId, const QVector &&vector, uint32_t objectType) : m_gpu(gpu) , m_id(objectId) + , m_objectType(objectType) + , m_propertyDefinitions(vector) { + m_props.resize(m_propertyDefinitions.count()); } DrmObject::~DrmObject() @@ -30,37 +33,15 @@ DrmObject::~DrmObject() qDeleteAll(m_props); } -bool DrmObject::initProps(const QVector &&vector, uint32_t objectType) +bool DrmObject::initProps() { - DrmScopedPointer properties(drmModeObjectGetProperties(m_gpu->fd(), m_id, objectType)); - if (!properties) { - qCWarning(KWIN_DRM) << "Failed to get properties for object" << m_id; + if (!updateProperties()) { return false; } - m_props.resize(vector.count()); - for (uint32_t i = 0; i < properties->count_props; i++) { - DrmScopedPointer prop(drmModeGetProperty(m_gpu->fd(), properties->props[i])); - if (!prop) { - qCWarning(KWIN_DRM, "Getting property %d of object %d failed!", i, m_id); - continue; - } - for (int j = 0; j < vector.count(); j++) { - const PropertyDefinition &def = vector[j]; - if (def.name == prop->name) { - drmModePropertyBlobRes *blob = nullptr; - if (prop->flags & DRM_MODE_PROP_BLOB) { - blob = drmModeGetPropertyBlob(m_gpu->fd(), properties->prop_values[i]); - } - qCDebug(KWIN_DRM, "Found property %s with value %lu", def.name.data(), properties->prop_values[i]); - m_props[j] = new Property(m_gpu, prop.data(), properties->prop_values[i], def.enumNames, blob); - break; - } - } - } - if (KWIN_DRM().isDebugEnabled()) { - for (int i = 0; i < vector.count(); i++) { + if (KWIN_DRM().isDebugEnabled() && m_gpu->atomicModeSetting()) { + for (int i = 0; i < m_propertyDefinitions.count(); i++) { if (!m_props[i]) { - qCDebug(KWIN_DRM) << "Could not find property" << vector[i].name; + qCDebug(KWIN_DRM) << "Could not find property" << m_propertyDefinitions[i].name; } } } @@ -123,8 +104,50 @@ bool DrmObject::needsCommit() const return false; } +bool DrmObject::updateProperties() +{ + DrmScopedPointer properties(drmModeObjectGetProperties(m_gpu->fd(), m_id, m_objectType)); + if (!properties) { + qCWarning(KWIN_DRM) << "Failed to get properties for object" << m_id; + return false; + } + for (int i = 0; i < m_propertyDefinitions.count(); i++) { + const PropertyDefinition &def = m_propertyDefinitions[i]; + bool found = false; + for (uint32_t j = 0; j < properties->count_props; j++) { + DrmScopedPointer prop(drmModeGetProperty(m_gpu->fd(), properties->props[j])); + if (!prop) { + qCWarning(KWIN_DRM, "Getting property %d of object %d failed!", j, m_id); + continue; + } + if (def.name == prop->name) { + drmModePropertyBlobRes *blob = nullptr; + if (prop->flags & DRM_MODE_PROP_BLOB) { + blob = drmModeGetPropertyBlob(m_gpu->fd(), properties->prop_values[j]); + } + if (m_props[i]) { + if (prop->flags & DRM_MODE_PROP_BLOB) { + m_props[i]->setCurrentBlob(blob); + } else { + m_props[i]->setCurrent(properties->prop_values[i]); + } + } else { + qCDebug(KWIN_DRM, "Found property %s with value %lu", def.name.data(), properties->prop_values[j]); + m_props[i] = new Property(m_gpu, prop.data(), properties->prop_values[j], def.enumNames, blob); + } + found = true; + break; + } + } + if (!found) { + deleteProp(i); + } + } + return true; +} + /* - * Definitions for struct Prop + * Definitions for DrmObject::Property */ DrmObject::Property::Property(DrmGpu *gpu, drmModePropertyRes *prop, uint64_t val, const QVector &enumNames, drmModePropertyBlobRes *blob) diff --git a/src/plugins/platforms/drm/drm_object.h b/src/plugins/platforms/drm/drm_object.h index fdfdb29cec..6a520d858c 100644 --- a/src/plugins/platforms/drm/drm_object.h +++ b/src/plugins/platforms/drm/drm_object.h @@ -26,12 +26,6 @@ class DrmOutput; class DrmObject { public: - /** - * Create DRM object representation. - * @param object_id provided by the kernel - * @param fd of the DRM device - */ - DrmObject(DrmGpu *gpu, uint32_t objectId); virtual ~DrmObject(); /** @@ -182,6 +176,8 @@ public: bool needsCommit() const; virtual bool needsModeset() const = 0; + virtual bool updateProperties(); + protected: struct PropertyDefinition { @@ -192,13 +188,10 @@ protected: QByteArray name; QVector enumNames; }; - /** - * Initialize properties of object. Only derived classes know names and quantities of - * properties. - * - * @return true when properties have been initialized successfully - */ - bool initProps(const QVector &&vector, uint32_t objectType); + + DrmObject(DrmGpu *gpu, uint32_t objectId, const QVector &&vector, uint32_t objectType); + + bool initProps(); template void deleteProp(T prop) @@ -207,12 +200,13 @@ protected: m_props[static_cast(prop)] = nullptr; } - // for comparison with received name of DRM object QVector m_props; private: DrmGpu *m_gpu; const uint32_t m_id; + const uint32_t m_objectType; + const QVector m_propertyDefinitions; }; } diff --git a/src/plugins/platforms/drm/drm_object_connector.cpp b/src/plugins/platforms/drm/drm_object_connector.cpp index 4e5c02da49..acbfb45a14 100644 --- a/src/plugins/platforms/drm/drm_object_connector.cpp +++ b/src/plugins/platforms/drm/drm_object_connector.cpp @@ -22,7 +22,21 @@ namespace KWin { DrmConnector::DrmConnector(DrmGpu *gpu, uint32_t connectorId) - : DrmObject(gpu, connectorId) + : DrmObject(gpu, connectorId, { + PropertyDefinition(QByteArrayLiteral("CRTC_ID")), + PropertyDefinition(QByteArrayLiteral("non-desktop")), + PropertyDefinition(QByteArrayLiteral("DPMS")), + PropertyDefinition(QByteArrayLiteral("EDID")), + PropertyDefinition(QByteArrayLiteral("overscan")), + PropertyDefinition(QByteArrayLiteral("vrr_capable")), + PropertyDefinition(QByteArrayLiteral("underscan"), { + QByteArrayLiteral("off"), + QByteArrayLiteral("on"), + QByteArrayLiteral("auto") + }), + PropertyDefinition(QByteArrayLiteral("underscan vborder")), + PropertyDefinition(QByteArrayLiteral("underscan hborder")), + }, DRM_MODE_OBJECT_CONNECTOR) , m_conn(drmModeGetConnector(gpu->fd(), connectorId)) { if (m_conn) { @@ -62,21 +76,7 @@ bool DrmConnector::init() } qCDebug(KWIN_DRM) << "Creating connector" << id(); - if (!initProps({ - PropertyDefinition(QByteArrayLiteral("CRTC_ID")), - PropertyDefinition(QByteArrayLiteral("non-desktop")), - PropertyDefinition(QByteArrayLiteral("DPMS")), - PropertyDefinition(QByteArrayLiteral("EDID")), - PropertyDefinition(QByteArrayLiteral("overscan")), - PropertyDefinition(QByteArrayLiteral("vrr_capable")), - PropertyDefinition(QByteArrayLiteral("underscan"), { - QByteArrayLiteral("off"), - QByteArrayLiteral("on"), - QByteArrayLiteral("auto") - }), - PropertyDefinition(QByteArrayLiteral("underscan vborder")), - PropertyDefinition(QByteArrayLiteral("underscan hborder")), - }, DRM_MODE_OBJECT_CONNECTOR)) { + if (!initProps()) { return false; } diff --git a/src/plugins/platforms/drm/drm_object_crtc.cpp b/src/plugins/platforms/drm/drm_object_crtc.cpp index 78735e7433..186a2fcbb3 100644 --- a/src/plugins/platforms/drm/drm_object_crtc.cpp +++ b/src/plugins/platforms/drm/drm_object_crtc.cpp @@ -18,7 +18,13 @@ namespace KWin { DrmCrtc::DrmCrtc(DrmGpu *gpu, uint32_t crtcId, int pipeIndex) - : DrmObject(gpu, crtcId) + : DrmObject(gpu, crtcId, { + PropertyDefinition(QByteArrayLiteral("MODE_ID")), + PropertyDefinition(QByteArrayLiteral("ACTIVE")), + PropertyDefinition(QByteArrayLiteral("VRR_ENABLED")), + PropertyDefinition(QByteArrayLiteral("GAMMA_LUT")), + PropertyDefinition(QByteArrayLiteral("GAMMA_LUT_SIZE")), + }, DRM_MODE_OBJECT_CRTC) , m_crtc(drmModeGetCrtc(gpu->fd(), crtcId)) , m_pipeIndex(pipeIndex) { @@ -30,13 +36,7 @@ bool DrmCrtc::init() return false; } qCDebug(KWIN_DRM) << "Init for CRTC:" << pipeIndex() << "id:" << id(); - return initProps({ - PropertyDefinition(QByteArrayLiteral("MODE_ID")), - PropertyDefinition(QByteArrayLiteral("ACTIVE")), - PropertyDefinition(QByteArrayLiteral("VRR_ENABLED")), - PropertyDefinition(QByteArrayLiteral("GAMMA_LUT")), - PropertyDefinition(QByteArrayLiteral("GAMMA_LUT_SIZE")), - }, DRM_MODE_OBJECT_CRTC); + return initProps(); } void DrmCrtc::flipBuffer() diff --git a/src/plugins/platforms/drm/drm_object_plane.cpp b/src/plugins/platforms/drm/drm_object_plane.cpp index 7ee0c39e29..d6e2baf3c3 100644 --- a/src/plugins/platforms/drm/drm_object_plane.cpp +++ b/src/plugins/platforms/drm/drm_object_plane.cpp @@ -16,29 +16,7 @@ namespace KWin { DrmPlane::DrmPlane(DrmGpu *gpu, uint32_t planeId) - : DrmObject(gpu, planeId) -{ -} - -bool DrmPlane::init() -{ - qCDebug(KWIN_DRM) << "Atomic init for plane:" << id(); - DrmScopedPointer p(drmModeGetPlane(gpu()->fd(), id())); - - if (!p) { - qCWarning(KWIN_DRM) << "Failed to get kernel plane" << id(); - return false; - } - - m_possibleCrtcs = p->possible_crtcs; - - int count_formats = p->count_formats; - m_formats.resize(count_formats); - for (int i = 0; i < count_formats; i++) { - m_formats[i] = p->formats[i]; - } - - bool success = initProps({ + : DrmObject(gpu, planeId, { PropertyDefinition(QByteArrayLiteral("type"), { QByteArrayLiteral("Overlay"), QByteArrayLiteral("Primary"), @@ -60,8 +38,29 @@ bool DrmPlane::init() QByteArrayLiteral("rotate-270"), QByteArrayLiteral("reflect-x"), QByteArrayLiteral("reflect-y")}), - }, DRM_MODE_OBJECT_PLANE - ); + }, DRM_MODE_OBJECT_PLANE) +{ +} + +bool DrmPlane::init() +{ + qCDebug(KWIN_DRM) << "Atomic init for plane:" << id(); + DrmScopedPointer p(drmModeGetPlane(gpu()->fd(), id())); + + if (!p) { + qCWarning(KWIN_DRM) << "Failed to get kernel plane" << id(); + return false; + } + + m_possibleCrtcs = p->possible_crtcs; + + int count_formats = p->count_formats; + m_formats.resize(count_formats); + for (int i = 0; i < count_formats; i++) { + m_formats[i] = p->formats[i]; + } + + bool success = initProps(); if (success) { m_supportedTransformations = Transformations(); auto checkSupport = [this] (uint64_t value, Transformation t) { diff --git a/src/plugins/platforms/drm/drm_pipeline.cpp b/src/plugins/platforms/drm/drm_pipeline.cpp index 18b4df240e..8eeaf03227 100644 --- a/src/plugins/platforms/drm/drm_pipeline.cpp +++ b/src/plugins/platforms/drm/drm_pipeline.cpp @@ -83,12 +83,23 @@ bool DrmPipeline::present(const QSharedPointer &buffer) return true; } } - bool result = m_gpu->atomicModeSetting() ? atomicCommit() : presentLegacy(); - if (!result) { - qCWarning(KWIN_DRM) << "Present failed!" << strerror(errno); - printDebugInfo(); + if (m_gpu->atomicModeSetting()) { + if (!atomicCommit()) { + // update properties and try again + updateProperties(); + if (!atomicCommit()) { + qCWarning(KWIN_DRM) << "Atomic present failed!" << strerror(errno); + printDebugInfo(); + return false; + } + } + } else { + if (!presentLegacy()) { + qCWarning(KWIN_DRM) << "Present failed!" << strerror(errno); + return false; + } } - return result; + return true; } bool DrmPipeline::atomicCommit() @@ -333,6 +344,10 @@ bool DrmPipeline::setActive(bool active) m_primaryPlane->setPending(DrmPlane::PropertyIndex::CrtcId, active ? m_crtc->id() : 0); if (active) { success = test(); + if (!success) { + updateProperties(); + success = test(); + } } else { // immediately commit if disabling as there will be no present success = atomicCommit(); @@ -497,6 +512,13 @@ void DrmPipeline::setUserData(DrmOutput *data) m_pageflipUserData = data; } +void DrmPipeline::updateProperties() +{ + for (const auto &obj : qAsConst(m_allObjects)) { + obj->updateProperties(); + } +} + static void printProps(DrmObject *object) { auto list = object->properties(); diff --git a/src/plugins/platforms/drm/drm_pipeline.h b/src/plugins/platforms/drm/drm_pipeline.h index e82fd16805..5baa75d2aa 100644 --- a/src/plugins/platforms/drm/drm_pipeline.h +++ b/src/plugins/platforms/drm/drm_pipeline.h @@ -71,6 +71,7 @@ public: void printDebugInfo() const; void setUserData(DrmOutput *data); QSize sourceSize() const; + void updateProperties(); private: bool atomicCommit();