backends/drm: fixes for bitmask drm properties

This commit is contained in:
Xaver Hugl 2022-05-14 23:29:14 +02:00
parent 420358709a
commit b5873ef792
7 changed files with 123 additions and 82 deletions

View file

@ -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<uint32_t>(prop->current()));
} else {
debug << "invalid value: " << prop->current();
}
}
debug << prop->name() << "=" << prop->valueString(prop->current());
} else {
debug << m_propertyDefinitions[i].name << " not found";
}

View file

@ -66,13 +66,6 @@ public:
return false;
}
template<typename T>
bool propHasEnum(T prop, uint64_t value) const
{
const auto &property = m_props.at(static_cast<uint32_t>(prop));
return property ? property->hasEnum(value) : false;
}
template<typename T>
DrmProperty *getProp(T propIndex) const
{

View file

@ -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;

View file

@ -3,6 +3,7 @@
This file is part of the KDE project.
SPDX-FileCopyrightText: 2016 Roman Gilg <subdiff@gmail.com>
SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com>
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<DrmFramebuffer> &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)) {

View file

@ -3,6 +3,7 @@
This file is part of the KDE project.
SPDX-FileCopyrightText: 2016 Roman Gilg <subdiff@gmail.com>
SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com>
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;

View file

@ -3,7 +3,7 @@
This file is part of the KDE project.
SPDX-FileCopyrightText: 2016 Roman Gilg <subdiff@gmail.com>
SPDX-FileCopyrightText: 2021 Xaver Hugl <xaver.hugl@gmail.com>
SPDX-FileCopyrightText: 2021-2022 Xaver Hugl <xaver.hugl@gmail.com>
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<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();
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<uint64_t>(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<uint64_t>(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;
}
}
}

View file

@ -3,13 +3,14 @@
This file is part of the KDE project.
SPDX-FileCopyrightText: 2016 Roman Gilg <subdiff@gmail.com>
SPDX-FileCopyrightText: 2021 Xaver Hugl <xaver.hugl@gmail.com>
SPDX-FileCopyrightText: 2021-2022 Xaver Hugl <xaver.hugl@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "drm_pointer.h"
#include "drm_logging.h"
#include <QByteArray>
#include <QMap>
@ -26,31 +27,50 @@ class DrmProperty
{
public:
DrmProperty(DrmObject *obj, drmModePropertyRes *prop, uint64_t val, const QVector<QByteArray> &enumNames);
virtual ~DrmProperty();
void initEnumMap(drmModePropertyRes *prop);
QVector<QByteArray> enumNames() const;
bool hasEnum(uint64_t value) const;
bool hasAllEnums() const;
template<typename Enum>
bool hasEnum(Enum value) const
{
return m_enumToPropertyMap.contains(static_cast<uint64_t>(value));
}
template<typename T>
T enumForValue(uint64_t value) const
{
return static_cast<T>(m_enumMap[value]);
}
template<typename T>
bool setEnum(T index)
{
if (hasEnum(static_cast<uint64_t>(index))) {
setPending(m_enumMap[static_cast<uint32_t>(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<T>(ret);
} else {
return static_cast<T>(m_propertyToEnumMap[value]);
}
}
template<typename Enum>
void setEnum(Enum value)
{
const uint64_t integer = static_cast<uint64_t>(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<uint64_t>(value))) {
return setPropertyLegacy(m_enumMap[static_cast<uint32_t>(value)]);
return setPropertyLegacy(m_enumToPropertyMap[static_cast<uint32_t>(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<uint32_t, uint64_t> m_enumMap;
QMap<uint64_t, uint64_t> m_enumToPropertyMap;
QMap<uint64_t, uint64_t> m_propertyToEnumMap;
QVector<QByteArray> m_enumNames;
const bool m_immutable;
const bool m_isBlob;
const bool m_isBitmask;
bool m_legacy = false;
const DrmObject *m_obj;
};