platforms/drm: split DrmObject::Property out in its own files

This commit is contained in:
Xaver Hugl 2021-09-22 14:01:01 +02:00
parent 307b5ce3ca
commit a70321c592
5 changed files with 322 additions and 250 deletions

View file

@ -1,6 +1,7 @@
set(DRM_SOURCES
drm_backend.cpp
drm_object.cpp
drm_property.cpp
drm_object_connector.cpp
drm_object_crtc.cpp
drm_object_plane.cpp

View file

@ -17,10 +17,6 @@
namespace KWin
{
/*
* Definitions for class DrmObject
*/
DrmObject::DrmObject(DrmGpu *gpu, uint32_t objectId, const QVector<PropertyDefinition> &&vector, uint32_t objectType)
: m_gpu(gpu)
, m_id(objectId)
@ -94,7 +90,7 @@ bool DrmObject::atomicPopulate(drmModeAtomicReq *req) const
return true;
}
QVector<DrmObject::Property*> DrmObject::properties()
QVector<DrmProperty *> DrmObject::properties()
{
return m_props;
}
@ -156,7 +152,7 @@ bool DrmObject::updateProperties()
if (m_props[propIndex]) {
m_props[propIndex]->setCurrent(properties->prop_values[drmPropIndex]);
} else {
m_props[propIndex] = new Property(this, prop.data(), properties->prop_values[drmPropIndex], def.enumNames);
m_props[propIndex] = new DrmProperty(this, prop.data(), properties->prop_values[drmPropIndex], def.enumNames);
}
found = true;
break;
@ -187,160 +183,9 @@ DrmGpu *DrmObject::gpu() const
return m_gpu;
}
/*
* Definitions for DrmObject::Property
*/
DrmObject::Property::Property(DrmObject *obj, drmModePropertyRes *prop, uint64_t val, const QVector<QByteArray> &enumNames)
: m_propId(prop->prop_id)
, m_propName(prop->name)
, m_pending(val)
, m_next(val)
, m_current(val)
, m_immutable(prop->flags & DRM_MODE_PROP_IMMUTABLE)
, m_obj(obj)
uint32_t DrmObject::type() const
{
if (!enumNames.isEmpty()) {
m_enumNames = enumNames;
initEnumMap(prop);
}
}
DrmObject::Property::~Property() = default;
void DrmObject::Property::setPending(uint64_t value)
{
m_pending = value;
}
uint64_t DrmObject::Property::pending() const
{
return m_pending;
}
bool DrmObject::Property::setPendingBlob(void *blob, size_t length)
{
if (!blob && !m_pendingBlob) {
return true;
}
if (blob && m_pendingBlob && length == m_pendingBlob->length && memcmp(blob, m_pendingBlob->data, length) == 0) {
return true;
}
uint32_t id = 0;
if (blob != nullptr) {
if (drmModeCreatePropertyBlob(m_obj->m_gpu->fd(), blob, length, &id) != 0) {
qCWarning(KWIN_DRM) << "Creating property blob failed!" << strerror(errno);
return false;
}
}
if (m_pendingBlob && m_pendingBlob != m_currentBlob && m_pendingBlob != m_nextBlob) {
drmModeDestroyPropertyBlob(m_obj->m_gpu->fd(), m_pendingBlob->id);
drmModeFreePropertyBlob(m_pendingBlob);
}
m_pending = id;
m_pendingBlob = drmModeGetPropertyBlob(m_obj->m_gpu->fd(), m_pending);
return true;
}
void DrmObject::Property::setCurrent(uint64_t value)
{
m_current = value;
}
uint64_t DrmObject::Property::current() const
{
return m_current;
}
void DrmObject::Property::setCurrentBlob(drmModePropertyBlobRes *blob)
{
if (m_currentBlob && m_currentBlob != m_pendingBlob && m_currentBlob != m_nextBlob && m_currentBlob != blob) {
drmModeDestroyPropertyBlob(m_obj->m_gpu->fd(), m_currentBlob->id);
drmModeFreePropertyBlob(m_currentBlob);
}
m_currentBlob = blob;
m_current = blob ? blob->id : 0;
}
void DrmObject::Property::commit()
{
if (m_immutable || m_current == m_pending) {
return;
}
if (m_pendingBlob || m_currentBlob) {
setCurrentBlob(m_pendingBlob);
} else {
setCurrent(m_pending);
}
}
void DrmObject::Property::commitPending()
{
if (m_immutable || m_next == m_pending) {
return;
}
if (m_pendingBlob || m_nextBlob) {
if (m_nextBlob && m_nextBlob != m_currentBlob) {
drmModeDestroyPropertyBlob(m_obj->m_gpu->fd(), m_nextBlob->id);
drmModeFreePropertyBlob(m_nextBlob);
}
m_next = m_pending;
m_nextBlob = m_pendingBlob;
} else {
m_next = m_pending;
}
}
void DrmObject::Property::rollbackPending()
{
if (m_immutable || m_next == m_pending) {
return;
}
if (m_pendingBlob || m_nextBlob) {
if (m_pendingBlob && m_pendingBlob != m_currentBlob) {
drmModeDestroyPropertyBlob(m_obj->m_gpu->fd(), m_pendingBlob->id);
drmModeFreePropertyBlob(m_pendingBlob);
}
m_pending = m_next;
m_pendingBlob = m_nextBlob;
} else {
m_pending = m_next;
}
}
bool DrmObject::Property::needsCommit() const
{
return m_pending != m_current;
}
bool DrmObject::Property::setPropertyLegacy(uint64_t value)
{
if (drmModeObjectSetProperty(m_obj->m_gpu->fd(), m_obj->id(), m_obj->m_objectType, m_propId, value) == 0) {
m_current = m_next = m_pending = value;
return true;
} else {
return false;
}
}
void DrmObject::Property::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;
} else {
qCWarning(KWIN_DRM, "%s has unrecognized enum '%s'", qPrintable(m_propName), en->name);
}
}
return m_objectType;
}
}

View file

@ -16,6 +16,7 @@
#include <xf86drmMode.h>
#include "drm_pointer.h"
#include "drm_property.h"
namespace KWin
{
@ -37,6 +38,8 @@ public:
uint32_t id() const;
DrmGpu *gpu() const;
uint32_t type() const;
QVector<DrmProperty*> properties();
void commit();
void commitPending();
@ -72,100 +75,11 @@ public:
return property ? property->hasEnum(value) : false;
}
class Property
{
public:
Property(DrmObject *obj, drmModePropertyRes *prop, uint64_t val, const QVector<QByteArray> &enumNames);
virtual ~Property();
void initEnumMap(drmModePropertyRes *prop);
QVector<QByteArray> enumNames() const {
return m_enumNames;
}
bool hasEnum(uint64_t value) const {
return m_enumMap.contains(value);
}
bool hasAllEnums() const {
return m_enumMap.count() == m_enumNames.count();
}
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;
}
return false;
}
uint32_t propId() const {
return m_propId;
}
const QByteArray &name() const {
return m_propName;
}
bool isImmutable() const {
return m_immutable;
}
bool isLegacy() const {
return m_legacy;
}
/**
* Makes this property be ignored by DrmObject::atomicPopulate
*/
void setLegacy() {
m_legacy = true;
}
void setPending(uint64_t value);
uint64_t pending() const;
bool setPendingBlob(void *blob, size_t length);
void setCurrent(uint64_t value);
uint64_t current() const;
void setCurrentBlob(drmModePropertyBlobRes *blob);
void commit();
void commitPending();
void rollbackPending();
bool needsCommit() const;
bool setPropertyLegacy(uint64_t value);
private:
uint32_t m_propId = 0;
QByteArray m_propName;
// the value that will be m_next after the property has been committed
// has not necessarily been tested to work
uint64_t m_pending = 0;
drmModePropertyBlobRes *m_pendingBlob = nullptr;
// the value that will be m_current after the next atomic commit
// and has been tested to work
uint64_t m_next = 0;
drmModePropertyBlobRes *m_nextBlob = nullptr;
// the value currently set for or by the kernel
uint64_t m_current = 0;
drmModePropertyBlobRes *m_currentBlob = nullptr;
QMap<uint32_t, uint64_t> m_enumMap;
QVector<QByteArray> m_enumNames;
const bool m_immutable;
bool m_legacy = false;
const DrmObject *m_obj;
};
template <typename T>
Property *getProp(T propIndex) const {
DrmProperty *getProp(T propIndex) const {
return m_props[static_cast<uint32_t>(propIndex)];
}
QVector<Property*> properties();
protected:
enum class Requirement {
Required,
@ -196,7 +110,7 @@ protected:
m_props[static_cast<uint32_t>(prop)] = nullptr;
}
QVector<Property *> m_props;
QVector<DrmProperty *> m_props;
private:
DrmGpu *m_gpu;

View file

@ -0,0 +1,215 @@
/*
KWin - the KDE window manager
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-License-Identifier: GPL-2.0-or-later
*/
#include "drm_property.h"
#include "drm_object.h"
#include "drm_gpu.h"
#include "logging.h"
namespace KWin
{
DrmProperty::DrmProperty(DrmObject *obj, drmModePropertyRes *prop, uint64_t val, const QVector<QByteArray> &enumNames)
: m_propId(prop->prop_id)
, m_propName(prop->name)
, m_pending(val)
, m_next(val)
, m_current(val)
, m_immutable(prop->flags & DRM_MODE_PROP_IMMUTABLE)
, m_obj(obj)
{
if (!enumNames.isEmpty()) {
m_enumNames = enumNames;
initEnumMap(prop);
}
}
DrmProperty::~DrmProperty() = default;
bool DrmProperty::setPendingBlob(void *blob, size_t length)
{
if (!blob && !m_pendingBlob) {
return true;
}
if (blob && m_pendingBlob && length == m_pendingBlob->length && memcmp(blob, m_pendingBlob->data, length) == 0) {
return true;
}
uint32_t id = 0;
if (blob != nullptr) {
if (drmModeCreatePropertyBlob(m_obj->gpu()->fd(), blob, length, &id) != 0) {
qCWarning(KWIN_DRM) << "Creating property blob failed!" << strerror(errno);
return false;
}
}
if (m_pendingBlob && m_pendingBlob != m_currentBlob && m_pendingBlob != m_nextBlob) {
drmModeDestroyPropertyBlob(m_obj->gpu()->fd(), m_pendingBlob->id);
drmModeFreePropertyBlob(m_pendingBlob);
}
m_pending = id;
m_pendingBlob = drmModeGetPropertyBlob(m_obj->gpu()->fd(), m_pending);
return true;
}
void DrmProperty::setCurrentBlob(drmModePropertyBlobRes *blob)
{
if (m_currentBlob && m_currentBlob != m_pendingBlob && m_currentBlob != m_nextBlob && m_currentBlob != blob) {
drmModeDestroyPropertyBlob(m_obj->gpu()->fd(), m_currentBlob->id);
drmModeFreePropertyBlob(m_currentBlob);
}
m_currentBlob = blob;
m_current = blob ? blob->id : 0;
}
void DrmProperty::commit()
{
if (m_immutable || m_current == m_pending) {
return;
}
if (m_pendingBlob || m_currentBlob) {
setCurrentBlob(m_pendingBlob);
} else {
setCurrent(m_pending);
}
}
void DrmProperty::commitPending()
{
if (m_immutable || m_next == m_pending) {
return;
}
if (m_pendingBlob || m_nextBlob) {
if (m_nextBlob && m_nextBlob != m_currentBlob) {
drmModeDestroyPropertyBlob(m_obj->gpu()->fd(), m_nextBlob->id);
drmModeFreePropertyBlob(m_nextBlob);
}
m_next = m_pending;
m_nextBlob = m_pendingBlob;
} else {
m_next = m_pending;
}
}
void DrmProperty::rollbackPending()
{
if (m_immutable || m_next == m_pending) {
return;
}
if (m_pendingBlob || m_nextBlob) {
if (m_pendingBlob && m_pendingBlob != m_currentBlob) {
drmModeDestroyPropertyBlob(m_obj->gpu()->fd(), m_pendingBlob->id);
drmModeFreePropertyBlob(m_pendingBlob);
}
m_pending = m_next;
m_pendingBlob = m_nextBlob;
} else {
m_pending = m_next;
}
}
bool DrmProperty::setPropertyLegacy(uint64_t value)
{
return drmModeObjectSetProperty(m_obj->gpu()->fd(), m_obj->id(), m_obj->type(), m_propId, value) == 0;
}
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;
} else {
qCWarning(KWIN_DRM, "%s has unrecognized enum '%s'", qPrintable(m_propName), en->name);
}
}
}
void DrmProperty::setPending(uint64_t value)
{
m_pending = value;
}
uint64_t DrmProperty::pending() const
{
return m_pending;
}
bool DrmProperty::needsCommit() const
{
return m_pending != m_current;
}
drmModePropertyBlobRes *DrmProperty::currentBlob() const
{
return m_currentBlob;
}
drmModePropertyBlobRes *DrmProperty::pendingBlob() const
{
return m_pendingBlob;
}
void DrmProperty::setCurrent(uint64_t value)
{
m_current = value;
}
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();
}
uint32_t DrmProperty::propId() const
{
return m_propId;
}
const QByteArray &DrmProperty::name() const
{
return m_propName;
}
bool DrmProperty::isImmutable() const
{
return m_immutable;
}
bool DrmProperty::isLegacy() const
{
return m_legacy;
}
void DrmProperty::setLegacy()
{
m_legacy = true;
}
}

View file

@ -0,0 +1,97 @@
/*
KWin - the KDE window manager
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-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <xf86drmMode.h>
#include <QVector>
#include <QMap>
#include <QByteArray>
namespace KWin
{
class DrmObject;
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 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;
}
return false;
}
uint32_t propId() const;
const QByteArray &name() const;
bool isImmutable() const;
bool isLegacy() const;
/**
* Makes this property be ignored by DrmObject::atomicPopulate
*/
void setLegacy();
void setPending(uint64_t value);
uint64_t pending() const;
bool setPendingBlob(void *blob, size_t length);
drmModePropertyBlobRes *pendingBlob() const;
void setCurrent(uint64_t value);
uint64_t current() const;
void setCurrentBlob(drmModePropertyBlobRes *blob);
drmModePropertyBlobRes *currentBlob() const;
void commit();
void commitPending();
void rollbackPending();
bool needsCommit() const;
bool setPropertyLegacy(uint64_t value);
private:
uint32_t m_propId = 0;
QByteArray m_propName;
// the value that will be m_next after the property has been committed
// has not necessarily been tested to work
uint64_t m_pending = 0;
drmModePropertyBlobRes *m_pendingBlob = nullptr;
// the value that will be m_current after the next atomic commit
// and has been tested to work
uint64_t m_next = 0;
drmModePropertyBlobRes *m_nextBlob = nullptr;
// the value currently set for or by the kernel
uint64_t m_current = 0;
drmModePropertyBlobRes *m_currentBlob = nullptr;
QMap<uint32_t, uint64_t> m_enumMap;
QVector<QByteArray> m_enumNames;
const bool m_immutable;
bool m_legacy = false;
const DrmObject *m_obj;
};
}