1 /* 2 KWin - the KDE window manager 3 This file is part of the KDE project. 4 5 SPDX-FileCopyrightText: 2016 Roman Gilg <subdiff@gmail.com> 6 7 SPDX-License-Identifier: GPL-2.0-or-later 8 */ 9 #pragma once 10 11 #include <QVector> 12 #include <QByteArray> 13 #include <QMap> 14 15 // drm 16 #include <xf86drmMode.h> 17 18 #include "drm_pointer.h" 19 20 namespace KWin 21 { 22 23 class DrmBackend; 24 class DrmGpu; 25 class DrmOutput; 26 27 class DrmObject 28 { 29 public: 30 virtual ~DrmObject(); 31 32 /** 33 * Must be called to query necessary data directly after creation. 34 * @return true when initializing was successful 35 */ 36 virtual bool init() = 0; 37 id()38 uint32_t id() const { 39 return m_id; 40 } 41 gpu()42 DrmGpu *gpu() const { 43 return m_gpu; 44 } 45 46 /** 47 * Populate an atomic request with data of this object. 48 * @param req the atomic request 49 * @return true when the request was successfully populated 50 */ 51 bool atomicPopulate(drmModeAtomicReq *req) const; 52 53 template <typename T> setPending(T prop,uint64_t new_value)54 bool setPending(T prop, uint64_t new_value) 55 { 56 if (auto &property = m_props.at(static_cast<uint32_t>(prop))) { 57 property->setPending(new_value); 58 return true; 59 } 60 return false; 61 } 62 63 template <typename T> setPendingBlob(T prop,void * data,size_t length)64 bool setPendingBlob(T prop, void *data, size_t length) 65 { 66 if (auto &property = m_props.at(static_cast<uint32_t>(prop))) { 67 return property->setPendingBlob(data, length); 68 } 69 return false; 70 } 71 72 template <typename T> propHasEnum(T prop,uint64_t value)73 bool propHasEnum(T prop, uint64_t value) const 74 { 75 const auto &property = m_props.at(static_cast<uint32_t>(prop)); 76 return property ? property->hasEnum(value) : false; 77 } 78 79 class Property 80 { 81 public: 82 Property(DrmGpu *gpu, drmModePropertyRes *prop, uint64_t val, const QVector<QByteArray> &enumNames); 83 virtual ~Property(); 84 85 void initEnumMap(drmModePropertyRes *prop); 86 enumNames()87 QVector<QByteArray> enumNames() const { 88 return m_enumNames; 89 } hasEnum(uint64_t value)90 bool hasEnum(uint64_t value) const { 91 return m_enumMap.contains(value); 92 } hasAllEnums()93 bool hasAllEnums() const { 94 return m_enumMap.count() == m_enumNames.count(); 95 } 96 template <typename T> enumForValue(uint64_t value)97 T enumForValue(uint64_t value) const { 98 return static_cast<T>(m_enumMap[value]); 99 } 100 template <typename T> setEnum(T index)101 bool setEnum(T index) { 102 if (hasEnum(static_cast<uint64_t>(index))) { 103 setPending(m_enumMap[static_cast<uint32_t>(index)]); 104 return true; 105 } 106 return false; 107 } 108 propId()109 uint32_t propId() const { 110 return m_propId; 111 } name()112 const QByteArray &name() const { 113 return m_propName; 114 } isImmutable()115 bool isImmutable() const { 116 return m_immutable; 117 } isLegacy()118 bool isLegacy() const { 119 return m_legacy; 120 } 121 /** 122 * Makes this property be ignored by DrmObject::atomicPopulate 123 */ setLegacy()124 void setLegacy() { 125 m_legacy = true; 126 } 127 128 void setPending(uint64_t value); 129 uint64_t pending() const; 130 bool setPendingBlob(void *blob, size_t length); 131 132 void setCurrent(uint64_t value); 133 uint64_t current() const; 134 void setCurrentBlob(drmModePropertyBlobRes *blob); 135 136 void commit(); 137 void commitPending(); 138 void rollbackPending(); 139 bool needsCommit() const; 140 141 private: 142 uint32_t m_propId = 0; 143 QByteArray m_propName; 144 145 // the value that will be m_next after the property has been committed 146 // has not necessarily been tested to work 147 uint64_t m_pending = 0; 148 drmModePropertyBlobRes *m_pendingBlob = nullptr; 149 // the value that will be m_current after the next atomic commit 150 // and has been tested to work 151 uint64_t m_next = 0; 152 drmModePropertyBlobRes *m_nextBlob = nullptr; 153 // the value currently set for or by the kernel 154 uint64_t m_current = 0; 155 drmModePropertyBlobRes *m_currentBlob = nullptr; 156 157 QMap<uint32_t, uint64_t> m_enumMap; 158 QVector<QByteArray> m_enumNames; 159 const bool m_immutable; 160 bool m_legacy = false; 161 const DrmGpu *m_gpu; 162 }; 163 164 template <typename T> getProp(T propIndex)165 Property *getProp(T propIndex) const { 166 return m_props[static_cast<uint32_t>(propIndex)]; 167 } 168 169 QVector<Property*> properties(); 170 void commit(); 171 void commitPending(); 172 void rollbackPending(); 173 174 bool needsCommit() const; 175 virtual bool needsModeset() const = 0; 176 177 virtual bool updateProperties(); 178 179 protected: 180 enum class Requirement { 181 Required, 182 Optional 183 }; 184 struct PropertyDefinition 185 { 186 PropertyDefinition(const QByteArray &name, Requirement requirement, const QVector<QByteArray> &&enumNames = {}) namePropertyDefinition187 : name(name) 188 , requirement(requirement) 189 , enumNames(enumNames) 190 { 191 } 192 QByteArray name; 193 Requirement requirement; 194 QVector<QByteArray> enumNames; 195 }; 196 197 DrmObject(DrmGpu *gpu, uint32_t objectId, const QVector<PropertyDefinition> &&vector, uint32_t objectType); 198 199 bool initProps(); 200 201 template <typename T> deleteProp(T prop)202 void deleteProp(T prop) 203 { 204 delete m_props[static_cast<uint32_t>(prop)]; 205 m_props[static_cast<uint32_t>(prop)] = nullptr; 206 } 207 208 QVector<Property *> m_props; 209 210 private: 211 DrmGpu *m_gpu; 212 const uint32_t m_id; 213 const uint32_t m_objectType; 214 const QVector<PropertyDefinition> m_propertyDefinitions; 215 }; 216 217 } 218 219 QDebug operator<<(QDebug stream, const KWin::DrmObject*); 220