File indexing completed on 2025-04-20 10:57:35
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2016 Roman Gilg <subdiff@gmail.com> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 #include "drm_object.h" 0010 0011 #include <errno.h> 0012 0013 #include "drm_gpu.h" 0014 #include "drm_logging.h" 0015 #include "drm_pointer.h" 0016 0017 namespace KWin 0018 { 0019 0020 DrmObject::DrmObject(DrmGpu *gpu, uint32_t objectId, const QVector<PropertyDefinition> &&vector, uint32_t objectType) 0021 : m_gpu(gpu) 0022 , m_id(objectId) 0023 , m_objectType(objectType) 0024 , m_propertyDefinitions(vector) 0025 { 0026 m_props.resize(m_propertyDefinitions.count()); 0027 } 0028 0029 bool DrmObject::initProps() 0030 { 0031 if (!updateProperties()) { 0032 return false; 0033 } 0034 if (KWIN_DRM().isDebugEnabled()) { 0035 auto debug = QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC, KWIN_DRM().categoryName()).debug().nospace().noquote(); 0036 switch (m_objectType) { 0037 case DRM_MODE_OBJECT_CONNECTOR: 0038 debug << "Connector "; 0039 break; 0040 case DRM_MODE_OBJECT_CRTC: 0041 debug << "Crtc "; 0042 break; 0043 case DRM_MODE_OBJECT_PLANE: 0044 debug << "Plane "; 0045 break; 0046 default: 0047 Q_UNREACHABLE(); 0048 } 0049 debug << m_id << " has properties "; 0050 for (size_t i = 0; i < m_props.size(); i++) { 0051 if (i > 0) { 0052 debug << ", "; 0053 } 0054 const auto &prop = m_props[i]; 0055 if (prop) { 0056 debug << prop->name() << "=" << prop->valueString(prop->current()); 0057 } else { 0058 debug << m_propertyDefinitions[i].name << " not found"; 0059 } 0060 } 0061 } 0062 return true; 0063 } 0064 0065 bool DrmObject::atomicPopulate(drmModeAtomicReq *req) const 0066 { 0067 for (const auto &property : std::as_const(m_props)) { 0068 if (property && !property->isImmutable() && !property->isLegacy() && property->needsCommit()) { 0069 if (drmModeAtomicAddProperty(req, m_id, property->propId(), property->pending()) <= 0) { 0070 qCWarning(KWIN_DRM) << "Adding property" << property->name() << "->" << property->pending() 0071 << "to atomic commit failed for object" << this << "with error" << strerror(errno); 0072 return false; 0073 } 0074 } 0075 } 0076 return true; 0077 } 0078 0079 void DrmObject::commit() 0080 { 0081 for (const auto &prop : std::as_const(m_props)) { 0082 if (prop) { 0083 prop->commit(); 0084 } 0085 } 0086 } 0087 0088 void DrmObject::commitPending() 0089 { 0090 for (const auto &prop : std::as_const(m_props)) { 0091 if (prop) { 0092 prop->commitPending(); 0093 } 0094 } 0095 } 0096 0097 void DrmObject::rollbackPending() 0098 { 0099 for (const auto &prop : std::as_const(m_props)) { 0100 if (prop) { 0101 prop->rollbackPending(); 0102 } 0103 } 0104 } 0105 0106 bool DrmObject::needsCommit() const 0107 { 0108 for (const auto &prop : std::as_const(m_props)) { 0109 if (prop && prop->needsCommit()) { 0110 return true; 0111 } 0112 } 0113 return false; 0114 } 0115 0116 bool DrmObject::updateProperties() 0117 { 0118 DrmUniquePtr<drmModeObjectProperties> properties(drmModeObjectGetProperties(m_gpu->fd(), m_id, m_objectType)); 0119 if (!properties) { 0120 qCWarning(KWIN_DRM) << "Failed to get properties for object" << m_id; 0121 return false; 0122 } 0123 for (int propIndex = 0; propIndex < m_propertyDefinitions.count(); propIndex++) { 0124 const PropertyDefinition &def = m_propertyDefinitions[propIndex]; 0125 bool found = false; 0126 for (uint32_t drmPropIndex = 0; drmPropIndex < properties->count_props; drmPropIndex++) { 0127 DrmUniquePtr<drmModePropertyRes> prop(drmModeGetProperty(m_gpu->fd(), properties->props[drmPropIndex])); 0128 if (!prop) { 0129 qCWarning(KWIN_DRM, "Getting property %d of object %d failed!", drmPropIndex, m_id); 0130 continue; 0131 } 0132 if (def.name == prop->name) { 0133 if (m_props[propIndex]) { 0134 m_props[propIndex]->setCurrent(properties->prop_values[drmPropIndex]); 0135 } else { 0136 m_props[propIndex] = std::make_unique<DrmProperty>(this, prop.get(), properties->prop_values[drmPropIndex], def.enumNames); 0137 } 0138 found = true; 0139 break; 0140 } 0141 } 0142 if (!found) { 0143 m_props[propIndex].reset(); 0144 } 0145 } 0146 for (int i = 0; i < m_propertyDefinitions.count(); i++) { 0147 bool required = m_gpu->atomicModeSetting() ? m_propertyDefinitions[i].requirement == Requirement::Required 0148 : m_propertyDefinitions[i].requirement == Requirement::RequiredForLegacy; 0149 if (!m_props[i] && required) { 0150 qCWarning(KWIN_DRM, "Required property %s for object %d not found!", qPrintable(m_propertyDefinitions[i].name), m_id); 0151 return false; 0152 } 0153 } 0154 return true; 0155 } 0156 0157 uint32_t DrmObject::id() const 0158 { 0159 return m_id; 0160 } 0161 0162 DrmGpu *DrmObject::gpu() const 0163 { 0164 return m_gpu; 0165 } 0166 0167 uint32_t DrmObject::type() const 0168 { 0169 return m_objectType; 0170 } 0171 0172 QString DrmObject::typeName() const 0173 { 0174 switch (m_objectType) { 0175 case DRM_MODE_OBJECT_CONNECTOR: 0176 return QStringLiteral("connector"); 0177 case DRM_MODE_OBJECT_CRTC: 0178 return QStringLiteral("crtc"); 0179 case DRM_MODE_OBJECT_PLANE: 0180 return QStringLiteral("plane"); 0181 default: 0182 return QStringLiteral("unknown?"); 0183 } 0184 } 0185 0186 void DrmObject::printProps(PrintMode mode) 0187 { 0188 bool any = mode == PrintMode::All || std::any_of(m_props.begin(), m_props.end(), [](const auto &prop) { 0189 return prop && !prop->isImmutable() && prop->needsCommit(); 0190 }); 0191 if (!any) { 0192 return; 0193 } 0194 qCDebug(KWIN_DRM) << typeName() << id(); 0195 for (const auto &prop : m_props) { 0196 if (prop) { 0197 uint64_t current = prop->name().startsWith("SRC_") ? prop->current() >> 16 : prop->current(); 0198 if (prop->isImmutable() || !prop->needsCommit()) { 0199 if (mode == PrintMode::All) { 0200 qCDebug(KWIN_DRM).nospace() << "\t" << prop->name() << ": " << current; 0201 } 0202 } else { 0203 uint64_t pending = prop->name().startsWith("SRC_") ? prop->pending() >> 16 : prop->pending(); 0204 qCDebug(KWIN_DRM).nospace() << "\t" << prop->name() << ": " << current << "->" << pending; 0205 } 0206 } 0207 } 0208 } 0209 } 0210 0211 QDebug operator<<(QDebug s, const KWin::DrmObject *obj) 0212 { 0213 QDebugStateSaver saver(s); 0214 if (obj) { 0215 s.nospace() << "DrmObject(id=" << obj->id() << ", gpu=" << obj->gpu() << ')'; 0216 } else { 0217 s << "DrmObject(0x0)"; 0218 } 0219 return s; 0220 }