summaryrefslogtreecommitdiff
path: root/kde-plasma/kwin/files/kwin-5.24.4-backends-drm-fetch-immutable-blobs.patch
blob: 16c7756d33e2c18054e6cc923dfb1eca7280a1a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
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