diff options
Diffstat (limited to 'kde-plasma/kwin/files/kwin-5.24.4-backends-drm-fetch-immutable-blobs.patch')
-rw-r--r-- | kde-plasma/kwin/files/kwin-5.24.4-backends-drm-fetch-immutable-blobs.patch | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/kde-plasma/kwin/files/kwin-5.24.4-backends-drm-fetch-immutable-blobs.patch b/kde-plasma/kwin/files/kwin-5.24.4-backends-drm-fetch-immutable-blobs.patch new file mode 100644 index 000000000000..16c7756d33e2 --- /dev/null +++ b/kde-plasma/kwin/files/kwin-5.24.4-backends-drm-fetch-immutable-blobs.patch @@ -0,0 +1,214 @@ +From 82c2324b5675ea2d5e3b962f270bda1d186e7326 Mon Sep 17 00:00:00 2001 +From: Xaver Hugl <xaver.hugl@gmail.com> +Date: Mon, 4 Apr 2022 20:19:05 +0200 +Subject: [PATCH] backends/drm: fetch immutable blobs in DrmProperty + +If the blob is fetched while there is no kernel-visible reference to it, +the driver may re-use the blob ID. When DrmProperty is created or updated, +KWin holds a reference on the blob via drmModeObjectProperties, so this +should prevent any possible issues. + +CCBUG: 449285 +--- + src/backends/drm/drm_object_connector.cpp | 13 +++----- + src/backends/drm/drm_object_plane.cpp | 39 +++++++++++------------ + src/backends/drm/drm_property.cpp | 27 +++++++++++++++- + src/backends/drm/drm_property.h | 7 +++- + 4 files changed, 54 insertions(+), 32 deletions(-) + +diff --git a/src/backends/drm/drm_object_connector.cpp b/src/backends/drm/drm_object_connector.cpp +index a0045290df..0cdbd70b4f 100644 +--- a/src/backends/drm/drm_object_connector.cpp ++++ b/src/backends/drm/drm_object_connector.cpp +@@ -337,16 +337,11 @@ bool DrmConnector::updateProperties() + } + + // parse edid +- auto edidProp = getProp(PropertyIndex::Edid); +- if (edidProp) { +- DrmScopedPointer<drmModePropertyBlobRes> blob(drmModeGetPropertyBlob(gpu()->fd(), edidProp->current())); +- if (blob && blob->data) { +- m_edid = Edid(blob->data, blob->length); +- if (!m_edid.isValid()) { +- qCWarning(KWIN_DRM) << "Couldn't parse EDID for connector" << this; +- } ++ if (const auto edidProp = getProp(PropertyIndex::Edid); edidProp && edidProp->immutableBlob()) { ++ m_edid = Edid(edidProp->immutableBlob()->data, edidProp->immutableBlob()->length); ++ if (!m_edid.isValid()) { ++ qCWarning(KWIN_DRM) << "Couldn't parse EDID for connector" << this; + } +- deleteProp(PropertyIndex::Edid); + } else { + qCDebug(KWIN_DRM) << "Could not find edid for connector" << this; + } +diff --git a/src/backends/drm/drm_object_plane.cpp b/src/backends/drm/drm_object_plane.cpp +index 6967fdd50d..c4dcca96d4 100644 +--- a/src/backends/drm/drm_object_plane.cpp ++++ b/src/backends/drm/drm_object_plane.cpp +@@ -73,29 +73,26 @@ bool DrmPlane::init() + checkSupport(5, Transformation::ReflectY); + + // read formats from blob if available and if modifiers are supported, and from the plane object if not +- if (auto formatProp = getProp(PropertyIndex::In_Formats); formatProp && gpu()->addFB2ModifiersSupported()) { +- DrmScopedPointer<drmModePropertyBlobRes> propertyBlob(drmModeGetPropertyBlob(gpu()->fd(), formatProp->current())); +- if (propertyBlob && propertyBlob->data) { +- auto blob = static_cast<drm_format_modifier_blob*>(propertyBlob->data); +- auto modifiers = reinterpret_cast<drm_format_modifier*>(reinterpret_cast<uint8_t*>(blob) + blob->modifiers_offset); +- uint32_t *formatarr = reinterpret_cast<uint32_t*>(reinterpret_cast<uint8_t*>(blob) + blob->formats_offset); +- +- for (uint32_t f = 0; f < blob->count_formats; f++) { +- auto format = formatarr[f]; +- QVector<uint64_t> mods; +- for (uint32_t m = 0; m < blob->count_modifiers; m++) { +- auto modifier = &modifiers[m]; +- // The modifier advertisement blob is partitioned into groups of 64 formats +- if (m < modifier->offset || m > modifier->offset + 63) { +- continue; +- } +- if (!(modifier->formats & (1 << (f - modifier->offset)))) { +- continue; +- } +- mods << modifier->modifier; ++ if (const auto formatProp = getProp(PropertyIndex::In_Formats); formatProp && formatProp->immutableBlob() && gpu()->addFB2ModifiersSupported()) { ++ auto blob = static_cast<drm_format_modifier_blob *>(formatProp->immutableBlob()->data); ++ auto modifiers = reinterpret_cast<drm_format_modifier *>(reinterpret_cast<uint8_t *>(blob) + blob->modifiers_offset); ++ uint32_t *formatarr = reinterpret_cast<uint32_t *>(reinterpret_cast<uint8_t *>(blob) + blob->formats_offset); ++ ++ for (uint32_t f = 0; f < blob->count_formats; f++) { ++ auto format = formatarr[f]; ++ QVector<uint64_t> mods; ++ for (uint32_t m = 0; m < blob->count_modifiers; m++) { ++ auto modifier = &modifiers[m]; ++ // The modifier advertisement blob is partitioned into groups of 64 formats ++ if (m < modifier->offset || m > modifier->offset + 63) { ++ continue; + } +- m_supportedFormats.insert(format, mods); ++ if (!(modifier->formats & (1 << (f - modifier->offset)))) { ++ continue; ++ } ++ mods << modifier->modifier; + } ++ m_supportedFormats.insert(format, mods); + } + } else { + for (uint32_t i = 0; i < p->count_formats; i++) { +diff --git a/src/backends/drm/drm_property.cpp b/src/backends/drm/drm_property.cpp +index 28af8ec07f..8ab0dc0e5a 100644 +--- a/src/backends/drm/drm_property.cpp ++++ b/src/backends/drm/drm_property.cpp +@@ -24,6 +24,7 @@ DrmProperty::DrmProperty(DrmObject *obj, drmModePropertyRes *prop, uint64_t val, + , m_next(val) + , m_current(val) + , m_immutable(prop->flags & DRM_MODE_PROP_IMMUTABLE) ++ , m_isBlob(prop->flags & DRM_MODE_PROP_BLOB) + , m_obj(obj) + { + if (!enumNames.isEmpty()) { +@@ -35,6 +36,7 @@ DrmProperty::DrmProperty(DrmObject *obj, drmModePropertyRes *prop, uint64_t val, + m_minValue = prop->values[0]; + m_maxValue = prop->values[1]; + } ++ updateBlob(); + } + + DrmProperty::~DrmProperty() = default; +@@ -110,7 +112,10 @@ bool DrmProperty::needsCommit() const + + void DrmProperty::setCurrent(uint64_t value) + { +- m_current = value; ++ if (m_current != value) { ++ updateBlob(); ++ m_current = value; ++ } + } + + uint64_t DrmProperty::current() const +@@ -122,10 +127,12 @@ QVector<QByteArray> DrmProperty::enumNames() const + { + return m_enumNames; + } ++ + bool DrmProperty::hasEnum(uint64_t value) const + { + return m_enumMap.contains(value); + } ++ + bool DrmProperty::hasAllEnums() const + { + return m_enumMap.count() == m_enumNames.count(); +@@ -166,4 +173,22 @@ uint64_t DrmProperty::maxValue() const + return m_maxValue; + } + ++void DrmProperty::updateBlob() ++{ ++ if (m_immutable && m_isBlob) { ++ if (m_current != 0) { ++ m_immutableBlob.reset(drmModeGetPropertyBlob(m_obj->gpu()->fd(), m_current)); ++ if (m_immutableBlob && (!m_immutableBlob->data || !m_immutableBlob->length)) { ++ m_immutableBlob.reset(); ++ } ++ } else { ++ m_immutableBlob.reset(); ++ } ++ } ++} ++ ++drmModePropertyBlobRes *DrmProperty::immutableBlob() const ++{ ++ return m_immutableBlob.get(); ++} + } +diff --git a/src/backends/drm/drm_property.h b/src/backends/drm/drm_property.h +index 48bdeafdc2..1ae547f41e 100644 +--- a/src/backends/drm/drm_property.h ++++ b/src/backends/drm/drm_property.h +@@ -9,9 +9,9 @@ + */ + + #pragma once ++#include "drm_pointer.h" + + #include <xf86drmMode.h> +- + #include <QVector> + #include <QMap> + #include <QByteArray> +@@ -59,6 +59,7 @@ public: + + void setCurrent(uint64_t value); + uint64_t current() const; ++ drmModePropertyBlobRes *immutableBlob() const; + + uint64_t minValue() const; + uint64_t maxValue() const; +@@ -78,6 +79,8 @@ public: + } + + private: ++ void updateBlob(); ++ + uint32_t m_propId = 0; + QByteArray m_propName; + +@@ -89,6 +92,7 @@ private: + uint64_t m_next = 0; + // the value currently set for or by the kernel + uint64_t m_current = 0; ++ DrmScopedPointer<drmModePropertyBlobRes> m_immutableBlob; + + uint64_t m_minValue = -1; + uint64_t m_maxValue = -1; +@@ -96,6 +100,7 @@ private: + QMap<uint32_t, uint64_t> m_enumMap; + QVector<QByteArray> m_enumNames; + const bool m_immutable; ++ const bool m_isBlob; + bool m_legacy = false; + const DrmObject *m_obj; + }; +-- +GitLab + |