/* KWin - the KDE window manager This file is part of the KDE project. SPDX-FileCopyrightText: 2016 Roman Gilg SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include #include // drm #include #include "drm_pointer.h" namespace KWin { class DrmBackend; class DrmGpu; class DrmOutput; class DrmObject { public: virtual ~DrmObject(); /** * Must be called to query necessary data directly after creation. * @return true when initializing was successful */ virtual bool init() = 0; uint32_t id() const { return m_id; } DrmGpu *gpu() const { return m_gpu; } /** * Populate an atomic request with data of this object. * @param req the atomic request * @return true when the request was successfully populated */ bool atomicPopulate(drmModeAtomicReq *req) const; template bool setPending(T prop, uint64_t new_value) { if (auto &property = m_props.at(static_cast(prop))) { property->setPending(new_value); return true; } return false; } template bool setPendingBlob(T prop, void *data, size_t length) { if (auto &property = m_props.at(static_cast(prop))) { return property->setPendingBlob(data, length); } 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; } class Property { public: Property(DrmGpu *gpu, drmModePropertyRes *prop, uint64_t val, const QVector &enumNames, drmModePropertyBlobRes *blob); virtual ~Property(); void initEnumMap(drmModePropertyRes *prop); /** * For properties of enum type the enum map identifies the kernel runtime values, * which must be queried beforehand. * * @param n the index to the enum * @return the runtime enum value corresponding with enum index @param n */ uint64_t enumMap(int n) const { return m_enumMap[n]; // TODO: test on index out of bounds? } bool hasEnum(uint64_t value) const { return m_enumMap.contains(value); } template bool setEnum(T index) { if (hasEnum(static_cast(index))) { setPending(m_enumMap[static_cast(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); 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; 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; QVector m_enumMap; QVector m_enumNames; const bool m_immutable; bool m_legacy = false; const DrmGpu *m_gpu; }; template Property *getProp(T propIndex) const { return m_props[static_cast(propIndex)]; } QVector properties(); void commit(); void commitPending(); void rollbackPending(); bool needsCommit() const; virtual bool needsModeset() const = 0; virtual bool updateProperties(); protected: struct PropertyDefinition { PropertyDefinition(const QByteArray &name, const QVector &&enumNames = {}) : name(name), enumNames(enumNames) { } QByteArray name; QVector enumNames; }; DrmObject(DrmGpu *gpu, uint32_t objectId, const QVector &&vector, uint32_t objectType); bool initProps(); template void deleteProp(T prop) { delete m_props[static_cast(prop)]; m_props[static_cast(prop)] = nullptr; } QVector m_props; private: DrmGpu *m_gpu; const uint32_t m_id; const uint32_t m_objectType; const QVector m_propertyDefinitions; }; } QDebug& operator<<(QDebug& stream, const KWin::DrmObject*);