Changeset View
Changeset View
Standalone View
Standalone View
plugins/platforms/drm/drm_object.cpp
Show All 31 Lines | |||||
32 | DrmObject::DrmObject(uint32_t object_id, int fd) | 32 | DrmObject::DrmObject(uint32_t object_id, int fd) | ||
33 | : m_fd(fd) | 33 | : m_fd(fd) | ||
34 | , m_id(object_id) | 34 | , m_id(object_id) | ||
35 | { | 35 | { | ||
36 | } | 36 | } | ||
37 | 37 | | |||
38 | DrmObject::~DrmObject() | 38 | DrmObject::~DrmObject() | ||
39 | { | 39 | { | ||
40 | foreach(Property* p, m_props) | 40 | for (auto *p : m_props) { | ||
41 | delete p; | 41 | delete p; | ||
42 | } | 42 | } | ||
43 | } | ||||
43 | 44 | | |||
44 | void DrmObject::setPropertyNames(QVector<QByteArray> &&vector) | 45 | void DrmObject::setPropertyNames(QVector<QByteArray> &&vector) | ||
45 | { | 46 | { | ||
46 | m_propsNames = std::move(vector); | 47 | m_propsNames = std::move(vector); | ||
47 | m_props.fill(nullptr, m_propsNames.size()); | 48 | m_props.fill(nullptr, m_propsNames.size()); | ||
48 | } | 49 | } | ||
49 | 50 | | |||
50 | void DrmObject::initProp(int n, drmModeObjectProperties *properties, QVector<QByteArray> enumNames) | 51 | void DrmObject::initProp(int n, drmModeObjectProperties *properties, QVector<QByteArray> enumNames) | ||
51 | { | 52 | { | ||
52 | for (unsigned int i = 0; i < properties->count_props; ++i) { | 53 | for (unsigned int i = 0; i < properties->count_props; ++i) { | ||
53 | DrmScopedPointer<drmModePropertyRes> prop( | 54 | DrmScopedPointer<drmModePropertyRes> prop( drmModeGetProperty(fd(), properties->props[i]) ); | ||
54 | drmModeGetProperty(fd(), properties->props[i])); | | |||
55 | if (!prop) { | 55 | if (!prop) { | ||
56 | qCWarning(KWIN_DRM) << "Getting property" << i << "failed"; | ||||
56 | continue; | 57 | continue; | ||
57 | } | 58 | } | ||
59 | | ||||
58 | if (prop->name == m_propsNames[n]) { | 60 | if (prop->name == m_propsNames[n]) { | ||
59 | qCDebug(KWIN_DRM).nospace() << m_id << ": " << prop->name << "' (id " << prop->prop_id | 61 | qCDebug(KWIN_DRM).nospace() << m_id << ": " << prop->name << "' (id " << prop->prop_id | ||
60 | << "): " << properties->prop_values[i]; | 62 | << "): " << properties->prop_values[i]; | ||
61 | m_props[n] = new Property(prop.data(), properties->prop_values[i], enumNames); | 63 | m_props[n] = new Property(prop.data(), properties->prop_values[i], enumNames); | ||
62 | } | 64 | } | ||
63 | } | 65 | } | ||
64 | } | 66 | } | ||
65 | 67 | | |||
66 | bool DrmObject::atomicAddProperty(drmModeAtomicReq *req, Property *property) | 68 | bool DrmObject::atomicPopulate(drmModeAtomicReq *req) const | ||
67 | { | 69 | { | ||
68 | if (drmModeAtomicAddProperty(req, m_id, property->propId(), property->value()) <= 0) { | 70 | return doAtomicPopulate(req, 0); | ||
69 | qCWarning(KWIN_DRM) << "Adding property" << property->name() << "to atomic commit failed for object" << this; | | |||
70 | return false; | | |||
71 | } | | |||
72 | return true; | | |||
73 | } | 71 | } | ||
74 | 72 | | |||
75 | bool DrmObject::atomicPopulate(drmModeAtomicReq *req) | 73 | bool DrmObject::doAtomicPopulate(drmModeAtomicReq *req, int firstProperty) const | ||
76 | { | 74 | { | ||
77 | bool ret = true; | 75 | bool ret = true; | ||
78 | 76 | | |||
79 | for (int i = 0; i < m_props.size(); i++) { | 77 | for (int i = firstProperty; i < m_props.size(); i++) { | ||
80 | auto property = m_props.at(i); | 78 | auto property = m_props.at(i); | ||
81 | if (!property) { | 79 | if (!property) { | ||
82 | continue; | 80 | continue; | ||
83 | } | 81 | } | ||
84 | ret &= atomicAddProperty(req, property); | 82 | ret &= atomicAddProperty(req, property); | ||
85 | } | 83 | } | ||
86 | 84 | | |||
87 | if (!ret) { | 85 | if (!ret) { | ||
88 | qCWarning(KWIN_DRM) << "Failed to populate atomic plane" << m_id; | 86 | qCWarning(KWIN_DRM) << "Failed to populate atomic object" << m_id; | ||
87 | return false; | ||||
88 | } | ||||
89 | return true; | ||||
90 | } | ||||
91 | | ||||
92 | void DrmObject::setValue(int prop, uint64_t new_value) | ||||
93 | { | ||||
94 | Q_ASSERT(prop < m_props.size()); | ||||
95 | auto property = m_props.at(prop); | ||||
96 | if (property) { | ||||
97 | property->setValue(new_value); | ||||
98 | } | ||||
99 | } | ||||
100 | | ||||
101 | bool DrmObject::propHasEnum(int prop, uint64_t value) const | ||||
102 | { | ||||
103 | auto property = m_props.at(prop); | ||||
104 | return property ? property->hasEnum(value) : false; | ||||
105 | } | ||||
106 | | ||||
107 | bool DrmObject::atomicAddProperty(drmModeAtomicReq *req, Property *property) const | ||||
108 | { | ||||
109 | if (drmModeAtomicAddProperty(req, m_id, property->propId(), property->value()) <= 0) { | ||||
110 | qCWarning(KWIN_DRM) << "Adding property" << property->name() | ||||
111 | << "to atomic commit failed for object" << this; | ||||
89 | return false; | 112 | return false; | ||
90 | } | 113 | } | ||
91 | return true; | 114 | return true; | ||
92 | } | 115 | } | ||
93 | 116 | | |||
94 | /* | 117 | /* | ||
95 | * Definitions for struct Prop | 118 | * Definitions for struct Prop | ||
96 | */ | 119 | */ | ||
97 | 120 | | |||
98 | DrmObject::Property::Property(drmModePropertyRes *prop, uint64_t val, QVector<QByteArray> enumNames) | 121 | DrmObject::Property::Property(drmModePropertyRes *prop, uint64_t val, QVector<QByteArray> enumNames) | ||
99 | : m_propId(prop->prop_id) | 122 | : m_propId(prop->prop_id) | ||
100 | , m_propName(prop->name) | 123 | , m_propName(prop->name) | ||
101 | , m_value(val) | 124 | , m_value(val) | ||
102 | { | 125 | { | ||
103 | if (!enumNames.isEmpty()) { | 126 | if (!enumNames.isEmpty()) { | ||
104 | qCDebug(KWIN_DRM) << m_propName << " has enums:" << enumNames; | 127 | qCDebug(KWIN_DRM) << m_propName << " can have enums:" << enumNames; | ||
105 | m_enumNames = enumNames; | 128 | m_enumNames = enumNames; | ||
106 | initEnumMap(prop); | 129 | initEnumMap(prop); | ||
107 | } | 130 | } | ||
108 | } | 131 | } | ||
109 | 132 | | |||
110 | DrmObject::Property::~Property() = default; | 133 | DrmObject::Property::~Property() = default; | ||
111 | 134 | | |||
112 | void DrmObject::Property::initEnumMap(drmModePropertyRes *prop) | 135 | void DrmObject::Property::initEnumMap(drmModePropertyRes *prop) | ||
113 | { | 136 | { | ||
114 | if (!((prop->flags & DRM_MODE_PROP_ENUM) || (prop->flags & DRM_MODE_PROP_BITMASK)) || prop->count_enums < 1) { | 137 | if ( ( !(prop->flags & DRM_MODE_PROP_ENUM) && !(prop->flags & DRM_MODE_PROP_BITMASK) ) | ||
138 | || prop->count_enums < 1 ) { | ||||
115 | qCWarning(KWIN_DRM) << "Property '" << prop->name << "' ( id =" | 139 | qCWarning(KWIN_DRM) << "Property '" << prop->name << "' ( id =" | ||
116 | << m_propId << ") should be enum valued, but it is not."; | 140 | << m_propId << ") should be enum valued, but it is not."; | ||
117 | return; | 141 | return; | ||
118 | } | 142 | } | ||
119 | 143 | | |||
120 | int nameCount = m_enumNames.size(); | 144 | const int nameCount = m_enumNames.size(); | ||
121 | m_enumMap.resize(nameCount); | 145 | m_enumMap.resize(nameCount); | ||
122 | 146 | | |||
123 | qCDebug(KWIN_DRM).nospace() << "Test all " << prop->count_enums << | 147 | qCDebug(KWIN_DRM).nospace() << "Available are " << prop->count_enums << | ||
124 | " possible enums" <<":"; | 148 | " enums. Query their runtime values:"; | ||
125 | 149 | | |||
126 | for (int i = 0; i < prop->count_enums; i++) { | 150 | for (int i = 0; i < prop->count_enums; i++) { | ||
127 | | ||||
128 | struct drm_mode_property_enum *en = &prop->enums[i]; | 151 | struct drm_mode_property_enum *en = &prop->enums[i]; | ||
129 | int j = 0; | 152 | int j = 0; | ||
130 | 153 | | |||
131 | while (QByteArray(en->name) != m_enumNames[j]) { | 154 | while (QByteArray(en->name) != m_enumNames[j]) { | ||
132 | j++; | 155 | j++; | ||
133 | if (j == nameCount) { | 156 | if (j == nameCount) { | ||
157 | qCWarning(KWIN_DRM).nospace() << m_propName << " has unrecognized enum '" | ||||
zzag: Simpler way
```lang=cpp
qCWarning(KWIN_DRM, "%1 has unrecogrnized enum '%2'", m_propName, en… | |||||
romangg: True, if you want you can push it. Thanks. | |||||
158 | << en->name << "'"; | ||||
134 | break; | 159 | break; | ||
135 | } | 160 | } | ||
136 | } | 161 | } | ||
137 | 162 | | |||
138 | if (j == nameCount) { | 163 | if (j < nameCount) { | ||
139 | qCWarning(KWIN_DRM).nospace() << m_propName << " has unrecognized enum '" << en->name << "'"; | 164 | qCDebug(KWIN_DRM).nospace() << "Enum '" << en->name | ||
140 | } else { | 165 | << "': runtime-value = " << en->value; | ||
141 | qCDebug(KWIN_DRM).nospace() << "Enum '" | | |||
142 | << en->name << "': runtime-value = " << en->value; | | |||
143 | m_enumMap[j] = en->value; | 166 | m_enumMap[j] = en->value; | ||
144 | } | 167 | } | ||
145 | } | 168 | } | ||
146 | 169 | | |||
147 | if (KWIN_DRM().isDebugEnabled()) { | 170 | if (KWIN_DRM().isDebugEnabled()) { | ||
148 | for (int i = 0; i < m_enumMap.size(); i++) { | 171 | for (int i = 0; i < m_enumMap.size(); i++) { | ||
149 | if (m_value == m_enumMap[i]) { | 172 | if (m_value == m_enumMap[i]) { | ||
150 | qCDebug(KWIN_DRM) << "=>" << m_propName << "with mapped enum value" << m_enumNames[i]; | 173 | // TODO: This does not work with bitmask properties, because from kernel we get the | ||
174 | // values for some reason as the shift distance instead of the full value. | ||||
175 | // See: https://github.com/torvalds/linux/blob/6794862a/drivers/ | ||||
176 | // gpu/drm/drm_blend.c#L267 | ||||
177 | qCDebug(KWIN_DRM) << "=>" << m_propName | ||||
178 | << "with mapped enum value" << m_enumNames[i]; | ||||
151 | } | 179 | } | ||
152 | } | 180 | } | ||
153 | } | 181 | } | ||
154 | } | 182 | } | ||
155 | 183 | | |||
156 | } | 184 | } |
Simpler way
I didn't test whether my code compiles though...