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
This commit is contained in:
parent
d6af43763c
commit
34616520c2
4 changed files with 53 additions and 31 deletions
|
@ -312,16 +312,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;
|
||||
}
|
||||
|
|
|
@ -67,29 +67,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);
|
||||
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;
|
||||
}
|
||||
if (!(modifier->formats & (1 << (f - modifier->offset)))) {
|
||||
continue;
|
||||
}
|
||||
mods << modifier->modifier;
|
||||
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++) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
#include "drm_pointer.h"
|
||||
|
||||
#include <xf86drmMode.h>
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QMap>
|
||||
#include <QVector>
|
||||
|
@ -61,6 +61,7 @@ public:
|
|||
|
||||
void setCurrent(uint64_t value);
|
||||
uint64_t current() const;
|
||||
drmModePropertyBlobRes *immutableBlob() const;
|
||||
|
||||
uint64_t minValue() const;
|
||||
uint64_t maxValue() const;
|
||||
|
@ -81,6 +82,8 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
void updateBlob();
|
||||
|
||||
uint32_t m_propId = 0;
|
||||
QByteArray m_propName;
|
||||
|
||||
|
@ -92,6 +95,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;
|
||||
|
@ -99,6 +103,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;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue