diff --git a/src/backends/drm/drm_object.cpp b/src/backends/drm/drm_object.cpp index 15d5074f1e..ffb5cbf227 100644 --- a/src/backends/drm/drm_object.cpp +++ b/src/backends/drm/drm_object.cpp @@ -32,7 +32,7 @@ bool DrmObject::initProps() return false; } if (KWIN_DRM().isDebugEnabled()) { - auto debug = QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC, KWIN_DRM().categoryName()).debug().nospace(); + auto debug = QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC, KWIN_DRM().categoryName()).debug().nospace().noquote(); switch (m_objectType) { case DRM_MODE_OBJECT_CONNECTOR: debug << "Connector "; @@ -53,16 +53,7 @@ bool DrmObject::initProps() } const auto &prop = m_props[i]; if (prop) { - debug << prop->name() << "="; - if (m_propertyDefinitions[i].enumNames.isEmpty()) { - debug << prop->current(); - } else { - if (prop->hasEnum(prop->current())) { - debug << prop->enumNames().at(prop->enumForValue(prop->current())); - } else { - debug << "invalid value: " << prop->current(); - } - } + debug << prop->name() << "=" << prop->valueString(prop->current()); } else { debug << m_propertyDefinitions[i].name << " not found"; } diff --git a/src/backends/drm/drm_object.h b/src/backends/drm/drm_object.h index c6bb0b2e57..ac6b88282a 100644 --- a/src/backends/drm/drm_object.h +++ b/src/backends/drm/drm_object.h @@ -66,13 +66,6 @@ public: return false; } - template - bool propHasEnum(T prop, uint64_t value) const - { - const auto &property = m_props.at(static_cast(prop)); - return property ? property->hasEnum(value) : false; - } - template DrmProperty *getProp(T propIndex) const { diff --git a/src/backends/drm/drm_pipeline.cpp b/src/backends/drm/drm_pipeline.cpp index 76534864ab..65506ff03d 100644 --- a/src/backends/drm/drm_pipeline.cpp +++ b/src/backends/drm/drm_pipeline.cpp @@ -266,9 +266,13 @@ void DrmPipeline::prepareAtomicModeset() m_pending.crtc->setPending(DrmCrtc::PropertyIndex::ModeId, m_pending.mode->blobId()); m_pending.crtc->primaryPlane()->setPending(DrmPlane::PropertyIndex::CrtcId, m_pending.crtc->id()); - m_pending.crtc->primaryPlane()->setTransformation(m_pending.bufferOrientation); + if (const auto rotation = m_pending.crtc->primaryPlane()->getProp(DrmPlane::PropertyIndex::Rotation)) { + rotation->setEnum(m_pending.bufferOrientation); + } if (m_pending.crtc->cursorPlane()) { - m_pending.crtc->cursorPlane()->setTransformation(DrmPlane::Transformation::Rotate0); + if (const auto rotation = m_pending.crtc->cursorPlane()->getProp(DrmPlane::PropertyIndex::Rotation)) { + rotation->setEnum(DrmPlane::Transformation::Rotate0); + } } } @@ -296,7 +300,7 @@ void DrmPipeline::checkHardwareRotation() if (m_pending.crtc && m_pending.crtc->primaryPlane()) { const bool supported = (m_pending.bufferOrientation & m_pending.crtc->primaryPlane()->supportedTransformations()); if (!supported) { - m_pending.bufferOrientation = DrmPlane::Transformations(DrmPlane::Transformation::Rotate0); + m_pending.bufferOrientation = DrmPlane::Transformation::Rotate0; } } else { m_pending.bufferOrientation = DrmPlane::Transformation::Rotate0; diff --git a/src/backends/drm/drm_plane.cpp b/src/backends/drm/drm_plane.cpp index d919b2d208..e5592487fd 100644 --- a/src/backends/drm/drm_plane.cpp +++ b/src/backends/drm/drm_plane.cpp @@ -3,6 +3,7 @@ This file is part of the KDE project. SPDX-FileCopyrightText: 2016 Roman Gilg + SPDX-FileCopyrightText: 2022 Xaver Hugl SPDX-License-Identifier: GPL-2.0-or-later */ @@ -53,18 +54,22 @@ bool DrmPlane::init() bool success = initProps(); if (success) { - m_supportedTransformations = Transformations(); - auto checkSupport = [this](uint64_t value, Transformation t) { - if (propHasEnum(PropertyIndex::Rotation, value)) { - m_supportedTransformations |= t; - } - }; - checkSupport(0, Transformation::Rotate0); - checkSupport(1, Transformation::Rotate90); - checkSupport(2, Transformation::Rotate180); - checkSupport(3, Transformation::Rotate270); - checkSupport(4, Transformation::ReflectX); - checkSupport(5, Transformation::ReflectY); + if (const auto prop = getProp(PropertyIndex::Rotation)) { + m_supportedTransformations = Transformations(); + auto checkSupport = [this, prop](Transformation t) { + if (prop->hasEnum(t)) { + m_supportedTransformations |= t; + } + }; + checkSupport(Transformation::Rotate0); + checkSupport(Transformation::Rotate90); + checkSupport(Transformation::Rotate180); + checkSupport(Transformation::Rotate270); + checkSupport(Transformation::ReflectX); + checkSupport(Transformation::ReflectY); + } else { + m_supportedTransformations = Transformation::Rotate0; + } // read formats from blob if available and if modifiers are supported, and from the plane object if not if (const auto formatProp = getProp(PropertyIndex::In_Formats); formatProp && formatProp->immutableBlob() && gpu()->addFB2ModifiersSupported()) { @@ -96,15 +101,6 @@ void DrmPlane::setNext(const std::shared_ptr &b) m_next = b; } -bool DrmPlane::setTransformation(Transformations t) -{ - if (m_supportedTransformations & t) { - return setPending(PropertyIndex::Rotation, t); - } else { - return false; - } -} - DrmPlane::Transformations DrmPlane::transformation() { if (auto property = getProp(PropertyIndex::Rotation)) { diff --git a/src/backends/drm/drm_plane.h b/src/backends/drm/drm_plane.h index 5184e73e8e..3bd1fff839 100644 --- a/src/backends/drm/drm_plane.h +++ b/src/backends/drm/drm_plane.h @@ -3,6 +3,7 @@ This file is part of the KDE project. SPDX-FileCopyrightText: 2016 Roman Gilg + SPDX-FileCopyrightText: 2022 Xaver Hugl SPDX-License-Identifier: GPL-2.0-or-later */ @@ -81,7 +82,6 @@ public: void setBuffer(DrmFramebuffer *buffer); void set(const QPoint &srcPos, const QSize &srcSize, const QPoint &dstPos, const QSize &dstSize); - bool setTransformation(Transformations t); Transformations transformation(); Transformations supportedTransformations() const; diff --git a/src/backends/drm/drm_property.cpp b/src/backends/drm/drm_property.cpp index f5b88317d0..576eb1f190 100644 --- a/src/backends/drm/drm_property.cpp +++ b/src/backends/drm/drm_property.cpp @@ -3,7 +3,7 @@ This file is part of the KDE project. SPDX-FileCopyrightText: 2016 Roman Gilg - SPDX-FileCopyrightText: 2021 Xaver Hugl + SPDX-FileCopyrightText: 2021-2022 Xaver Hugl SPDX-License-Identifier: GPL-2.0-or-later */ @@ -25,6 +25,7 @@ DrmProperty::DrmProperty(DrmObject *obj, drmModePropertyRes *prop, uint64_t val, , m_current(val) , m_immutable(prop->flags & DRM_MODE_PROP_IMMUTABLE) , m_isBlob(prop->flags & DRM_MODE_PROP_BLOB) + , m_isBitmask(prop->flags & DRM_MODE_PROP_BITMASK) , m_obj(obj) { if (!enumNames.isEmpty()) { @@ -39,8 +40,6 @@ DrmProperty::DrmProperty(DrmObject *obj, drmModePropertyRes *prop, uint64_t val, updateBlob(); } -DrmProperty::~DrmProperty() = default; - void DrmProperty::commit() { if (m_immutable || m_current == m_pending) { @@ -77,18 +76,17 @@ bool DrmProperty::setPropertyLegacy(uint64_t value) void DrmProperty::initEnumMap(drmModePropertyRes *prop) { - if ((!(prop->flags & DRM_MODE_PROP_ENUM) && !(prop->flags & DRM_MODE_PROP_BITMASK)) - || prop->count_enums < 1) { - qCWarning(KWIN_DRM) << "Property '" << prop->name << "' ( id =" - << m_propId << ") should be enum valued, but it is not."; - return; - } - for (int i = 0; i < prop->count_enums; i++) { struct drm_mode_property_enum *en = &prop->enums[i]; int j = m_enumNames.indexOf(QByteArray(en->name)); if (j >= 0) { - m_enumMap[j] = en->value; + if (m_isBitmask) { + m_enumToPropertyMap[1 << j] = 1 << en->value; + m_propertyToEnumMap[1 << en->value] = 1 << j; + } else { + m_enumToPropertyMap[j] = en->value; + m_propertyToEnumMap[en->value] = j; + } } else { qCWarning(KWIN_DRM, "%s has unrecognized enum '%s'", qPrintable(m_propName), en->name); } @@ -121,19 +119,9 @@ uint64_t DrmProperty::current() const return m_current; } -QVector 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(); + return m_enumToPropertyMap.count() == m_enumNames.count(); } uint32_t DrmProperty::propId() const @@ -151,6 +139,11 @@ bool DrmProperty::isImmutable() const return m_immutable; } +bool DrmProperty::isBitmask() const +{ + return m_isBitmask; +} + bool DrmProperty::isLegacy() const { return m_legacy; @@ -189,4 +182,43 @@ drmModePropertyBlobRes *DrmProperty::immutableBlob() const { return m_immutableBlob.get(); } + +QString DrmProperty::valueString(uint64_t value) const +{ + if (m_isBitmask) { + QString ret; + bool first = true; + for (uint64_t mask = 1; mask >= value && mask != 0; mask <<= 1) { + if (value & mask) { + if (!first) { + ret += " | "; + } + first = false; + uint64_t enumValue = enumForValue(mask); + int enumIndex = 0; + while (!(enumValue & (1ull << enumIndex)) && enumIndex < 64) { + enumIndex++; + } + if (enumIndex < m_enumNames.size()) { + ret += m_enumNames[enumIndex]; + } + } + } + return ret; + } else if (!m_enumNames.isEmpty()) { + if (const uint64_t index = enumForValue(value); index < (uint)m_enumNames.size()) { + return m_enumNames[index]; + } else { + return QStringLiteral("invalid value: %d").arg(value); + } + } else if (m_propName == QStringLiteral("SRC_X") || m_propName == QStringLiteral("SRC_Y") || m_propName == QStringLiteral("SRC_W") || m_propName == QStringLiteral("SRC_H")) { + QString ret; + ret.setNum(value / (float)(1ul << 16)); + return ret; + } else { + QString ret; + ret.setNum(value); + return ret; + } +} } diff --git a/src/backends/drm/drm_property.h b/src/backends/drm/drm_property.h index a358dbba6c..d165cca5f6 100644 --- a/src/backends/drm/drm_property.h +++ b/src/backends/drm/drm_property.h @@ -3,13 +3,14 @@ This file is part of the KDE project. SPDX-FileCopyrightText: 2016 Roman Gilg - SPDX-FileCopyrightText: 2021 Xaver Hugl + SPDX-FileCopyrightText: 2021-2022 Xaver Hugl SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include "drm_pointer.h" +#include "drm_logging.h" #include #include @@ -26,31 +27,50 @@ class DrmProperty { public: DrmProperty(DrmObject *obj, drmModePropertyRes *prop, uint64_t val, const QVector &enumNames); - virtual ~DrmProperty(); - void initEnumMap(drmModePropertyRes *prop); - - QVector enumNames() const; - bool hasEnum(uint64_t value) const; bool hasAllEnums() const; + + template + bool hasEnum(Enum value) const + { + return m_enumToPropertyMap.contains(static_cast(value)); + } template T enumForValue(uint64_t value) const { - return static_cast(m_enumMap[value]); - } - template - bool setEnum(T index) - { - if (hasEnum(static_cast(index))) { - setPending(m_enumMap[static_cast(index)]); - return true; + if (m_isBitmask) { + uint64_t ret = 0; + for (uint64_t mask = 1; value >= mask && mask != 0; mask <<= 1) { + if (value & mask) { + ret |= m_propertyToEnumMap[mask]; + } + } + return static_cast(ret); + } else { + return static_cast(m_propertyToEnumMap[value]); + } + } + template + void setEnum(Enum value) + { + const uint64_t integer = static_cast(value); + if (m_isBitmask) { + uint64_t set = 0; + for (uint64_t mask = 1; integer >= mask && mask != 0; mask <<= 1) { + if (integer & mask) { + set |= m_enumToPropertyMap[mask]; + } + } + setPending(set); + } else { + setPending(m_enumToPropertyMap[integer]); } - return false; } uint32_t propId() const; const QByteArray &name() const; bool isImmutable() const; + bool isBitmask() const; bool isLegacy() const; /** * Makes this property be ignored by DrmObject::atomicPopulate @@ -77,12 +97,15 @@ public: bool setEnumLegacy(T value) { if (hasEnum(static_cast(value))) { - return setPropertyLegacy(m_enumMap[static_cast(value)]); + return setPropertyLegacy(m_enumToPropertyMap[static_cast(value)]); } return false; } + QString valueString(uint64_t value) const; + private: + void initEnumMap(drmModePropertyRes *prop); void updateBlob(); uint32_t m_propId = 0; @@ -101,10 +124,12 @@ private: uint64_t m_minValue = -1; uint64_t m_maxValue = -1; - QMap m_enumMap; + QMap m_enumToPropertyMap; + QMap m_propertyToEnumMap; QVector m_enumNames; const bool m_immutable; const bool m_isBlob; + const bool m_isBitmask; bool m_legacy = false; const DrmObject *m_obj; };