File indexing completed on 2025-04-20 10:57:36
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 SPDX-FileCopyrightText: 2021-2022 Xaver Hugl <xaver.hugl@gmail.com> 0007 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 0011 #include "drm_property.h" 0012 #include "drm_gpu.h" 0013 #include "drm_logging.h" 0014 #include "drm_object.h" 0015 #include <cerrno> 0016 0017 namespace KWin 0018 { 0019 0020 DrmProperty::DrmProperty(DrmObject *obj, drmModePropertyRes *prop, uint64_t val, const QVector<QByteArray> &enumNames) 0021 : m_propId(prop->prop_id) 0022 , m_propName(prop->name) 0023 , m_pending(val) 0024 , m_next(val) 0025 , m_current(val) 0026 , m_immutable(prop->flags & DRM_MODE_PROP_IMMUTABLE) 0027 , m_isBlob(prop->flags & DRM_MODE_PROP_BLOB) 0028 , m_isBitmask(prop->flags & DRM_MODE_PROP_BITMASK) 0029 , m_obj(obj) 0030 { 0031 if (!enumNames.isEmpty()) { 0032 m_enumNames = enumNames; 0033 initEnumMap(prop); 0034 } 0035 if (prop->flags & DRM_MODE_PROP_RANGE) { 0036 Q_ASSERT(prop->count_values > 1); 0037 m_minValue = prop->values[0]; 0038 m_maxValue = prop->values[1]; 0039 } 0040 updateBlob(); 0041 } 0042 0043 void DrmProperty::commit() 0044 { 0045 if (m_immutable || m_current == m_pending) { 0046 return; 0047 } 0048 setCurrent(m_pending); 0049 } 0050 0051 void DrmProperty::commitPending() 0052 { 0053 if (m_immutable || m_next == m_pending) { 0054 return; 0055 } 0056 m_next = m_pending; 0057 } 0058 0059 void DrmProperty::rollbackPending() 0060 { 0061 if (m_immutable || m_next == m_pending) { 0062 return; 0063 } 0064 m_pending = m_next; 0065 } 0066 0067 bool DrmProperty::setPropertyLegacy(uint64_t value) 0068 { 0069 if (drmModeObjectSetProperty(m_obj->gpu()->fd(), m_obj->id(), m_obj->type(), m_propId, value) == 0) { 0070 m_current = m_next = m_pending = value; 0071 return true; 0072 } else { 0073 return false; 0074 } 0075 } 0076 0077 void DrmProperty::initEnumMap(drmModePropertyRes *prop) 0078 { 0079 for (int i = 0; i < prop->count_enums; i++) { 0080 struct drm_mode_property_enum *en = &prop->enums[i]; 0081 int j = m_enumNames.indexOf(QByteArray(en->name)); 0082 if (j >= 0) { 0083 if (m_isBitmask) { 0084 m_enumToPropertyMap[1 << j] = 1 << en->value; 0085 m_propertyToEnumMap[1 << en->value] = 1 << j; 0086 } else { 0087 m_enumToPropertyMap[j] = en->value; 0088 m_propertyToEnumMap[en->value] = j; 0089 } 0090 } else { 0091 qCWarning(KWIN_DRM, "%s has unrecognized enum '%s'", qPrintable(m_propName), en->name); 0092 } 0093 } 0094 } 0095 0096 void DrmProperty::setPending(uint64_t value) 0097 { 0098 m_pending = value; 0099 } 0100 0101 uint64_t DrmProperty::pending() const 0102 { 0103 return m_pending; 0104 } 0105 0106 bool DrmProperty::needsCommit() const 0107 { 0108 return m_pending != m_current; 0109 } 0110 0111 void DrmProperty::setCurrent(uint64_t value) 0112 { 0113 m_current = value; 0114 updateBlob(); 0115 } 0116 0117 uint64_t DrmProperty::current() const 0118 { 0119 return m_current; 0120 } 0121 0122 bool DrmProperty::hasAllEnums() const 0123 { 0124 return m_enumToPropertyMap.count() == m_enumNames.count(); 0125 } 0126 0127 uint32_t DrmProperty::propId() const 0128 { 0129 return m_propId; 0130 } 0131 0132 const QByteArray &DrmProperty::name() const 0133 { 0134 return m_propName; 0135 } 0136 0137 bool DrmProperty::isImmutable() const 0138 { 0139 return m_immutable; 0140 } 0141 0142 bool DrmProperty::isBitmask() const 0143 { 0144 return m_isBitmask; 0145 } 0146 0147 bool DrmProperty::isLegacy() const 0148 { 0149 return m_legacy; 0150 } 0151 0152 void DrmProperty::setLegacy() 0153 { 0154 m_legacy = true; 0155 } 0156 0157 uint64_t DrmProperty::minValue() const 0158 { 0159 return m_minValue; 0160 } 0161 0162 uint64_t DrmProperty::maxValue() const 0163 { 0164 return m_maxValue; 0165 } 0166 0167 void DrmProperty::updateBlob() 0168 { 0169 if (m_immutable && m_isBlob) { 0170 if (m_current != 0) { 0171 m_immutableBlob.reset(drmModeGetPropertyBlob(m_obj->gpu()->fd(), m_current)); 0172 if (m_immutableBlob && (!m_immutableBlob->data || !m_immutableBlob->length)) { 0173 m_immutableBlob.reset(); 0174 } 0175 } else { 0176 m_immutableBlob.reset(); 0177 } 0178 } 0179 } 0180 0181 drmModePropertyBlobRes *DrmProperty::immutableBlob() const 0182 { 0183 return m_immutableBlob.get(); 0184 } 0185 0186 QString DrmProperty::valueString(uint64_t value) const 0187 { 0188 if (m_isBitmask) { 0189 QString ret; 0190 bool first = true; 0191 for (uint64_t mask = 1; mask >= value && mask != 0; mask <<= 1) { 0192 if (value & mask) { 0193 if (!first) { 0194 ret += " | "; 0195 } 0196 first = false; 0197 uint64_t enumValue = enumForValue<uint64_t>(mask); 0198 int enumIndex = 0; 0199 while (!(enumValue & (1ull << enumIndex)) && enumIndex < 64) { 0200 enumIndex++; 0201 } 0202 if (enumIndex < m_enumNames.size()) { 0203 ret += m_enumNames[enumIndex]; 0204 } 0205 } 0206 } 0207 return ret; 0208 } else if (!m_enumNames.isEmpty()) { 0209 if (const uint64_t index = enumForValue<uint64_t>(value); index < (uint)m_enumNames.size()) { 0210 return m_enumNames[index]; 0211 } else { 0212 return QStringLiteral("invalid value: %d").arg(value); 0213 } 0214 } else if (m_propName == QStringLiteral("SRC_X") || m_propName == QStringLiteral("SRC_Y") || m_propName == QStringLiteral("SRC_W") || m_propName == QStringLiteral("SRC_H")) { 0215 QString ret; 0216 ret.setNum(value / (float)(1ul << 16)); 0217 return ret; 0218 } else { 0219 QString ret; 0220 ret.setNum(value); 0221 return ret; 0222 } 0223 } 0224 }