Commit cec4e57b authored by Roman Gilg's avatar Roman Gilg
Browse files

[platforms/drm] Do plane and object chore

Summary:
This cleans up some of the code, moves and deletes superfluous functions,
improves in-code docs and runtime warnings.

Test Plan: On vt.

Reviewers: #kwin

Subscribers: kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D25867
parent 33bcc43f
......@@ -37,8 +37,9 @@ DrmObject::DrmObject(uint32_t object_id, int fd)
DrmObject::~DrmObject()
{
foreach(Property* p, m_props)
for (auto *p : m_props) {
delete p;
}
}
void DrmObject::setPropertyNames(QVector<QByteArray> &&vector)
......@@ -50,11 +51,12 @@ void DrmObject::setPropertyNames(QVector<QByteArray> &&vector)
void DrmObject::initProp(int n, drmModeObjectProperties *properties, QVector<QByteArray> enumNames)
{
for (unsigned int i = 0; i < properties->count_props; ++i) {
DrmScopedPointer<drmModePropertyRes> prop(
drmModeGetProperty(fd(), properties->props[i]));
DrmScopedPointer<drmModePropertyRes> prop( drmModeGetProperty(fd(), properties->props[i]) );
if (!prop) {
qCWarning(KWIN_DRM) << "Getting property" << i << "failed";
continue;
}
if (prop->name == m_propsNames[n]) {
qCDebug(KWIN_DRM).nospace() << m_id << ": " << prop->name << "' (id " << prop->prop_id
<< "): " << properties->prop_values[i];
......@@ -63,20 +65,16 @@ void DrmObject::initProp(int n, drmModeObjectProperties *properties, QVector<QBy
}
}
bool DrmObject::atomicAddProperty(drmModeAtomicReq *req, Property *property)
bool DrmObject::atomicPopulate(drmModeAtomicReq *req) const
{
if (drmModeAtomicAddProperty(req, m_id, property->propId(), property->value()) <= 0) {
qCWarning(KWIN_DRM) << "Adding property" << property->name() << "to atomic commit failed for object" << this;
return false;
}
return true;
return doAtomicPopulate(req, 0);
}
bool DrmObject::atomicPopulate(drmModeAtomicReq *req)
bool DrmObject::doAtomicPopulate(drmModeAtomicReq *req, int firstProperty) const
{
bool ret = true;
for (int i = 0; i < m_props.size(); i++) {
for (int i = firstProperty; i < m_props.size(); i++) {
auto property = m_props.at(i);
if (!property) {
continue;
......@@ -85,7 +83,32 @@ bool DrmObject::atomicPopulate(drmModeAtomicReq *req)
}
if (!ret) {
qCWarning(KWIN_DRM) << "Failed to populate atomic plane" << m_id;
qCWarning(KWIN_DRM) << "Failed to populate atomic object" << m_id;
return false;
}
return true;
}
void DrmObject::setValue(int prop, uint64_t new_value)
{
Q_ASSERT(prop < m_props.size());
auto property = m_props.at(prop);
if (property) {
property->setValue(new_value);
}
}
bool DrmObject::propHasEnum(int prop, uint64_t value) const
{
auto property = m_props.at(prop);
return property ? property->hasEnum(value) : false;
}
bool DrmObject::atomicAddProperty(drmModeAtomicReq *req, Property *property) const
{
if (drmModeAtomicAddProperty(req, m_id, property->propId(), property->value()) <= 0) {
qCWarning(KWIN_DRM) << "Adding property" << property->name()
<< "to atomic commit failed for object" << this;
return false;
}
return true;
......@@ -101,7 +124,7 @@ DrmObject::Property::Property(drmModePropertyRes *prop, uint64_t val, QVector<QB
, m_value(val)
{
if (!enumNames.isEmpty()) {
qCDebug(KWIN_DRM) << m_propName << " has enums:" << enumNames;
qCDebug(KWIN_DRM) << m_propName << " can have enums:" << enumNames;
m_enumNames = enumNames;
initEnumMap(prop);
}
......@@ -111,35 +134,35 @@ DrmObject::Property::~Property() = default;
void DrmObject::Property::initEnumMap(drmModePropertyRes *prop)
{
if (!((prop->flags & DRM_MODE_PROP_ENUM) || (prop->flags & DRM_MODE_PROP_BITMASK)) || prop->count_enums < 1) {
if ( ( !(prop->flags & DRM_MODE_PROP_ENUM) && !(prop->flags & DRM_MODE_PROP_BITMASK) )
|| prop->count_enums < 1 ) {
qCWarning(KWIN_DRM) << "Property '" << prop->name << "' ( id ="
<< m_propId << ") should be enum valued, but it is not.";
return;
}
int nameCount = m_enumNames.size();
const int nameCount = m_enumNames.size();
m_enumMap.resize(nameCount);
qCDebug(KWIN_DRM).nospace() << "Test all " << prop->count_enums <<
" possible enums" <<":";
qCDebug(KWIN_DRM).nospace() << "Available are " << prop->count_enums <<
" enums. Query their runtime values:";
for (int i = 0; i < prop->count_enums; i++) {
struct drm_mode_property_enum *en = &prop->enums[i];
int j = 0;
while (QByteArray(en->name) != m_enumNames[j]) {
j++;
if (j == nameCount) {
qCWarning(KWIN_DRM).nospace() << m_propName << " has unrecognized enum '"
<< en->name << "'";
break;
}
}
if (j == nameCount) {
qCWarning(KWIN_DRM).nospace() << m_propName << " has unrecognized enum '" << en->name << "'";
} else {
qCDebug(KWIN_DRM).nospace() << "Enum '"
<< en->name << "': runtime-value = " << en->value;
if (j < nameCount) {
qCDebug(KWIN_DRM).nospace() << "Enum '" << en->name
<< "': runtime-value = " << en->value;
m_enumMap[j] = en->value;
}
}
......@@ -147,7 +170,12 @@ void DrmObject::Property::initEnumMap(drmModePropertyRes *prop)
if (KWIN_DRM().isDebugEnabled()) {
for (int i = 0; i < m_enumMap.size(); i++) {
if (m_value == m_enumMap[i]) {
qCDebug(KWIN_DRM) << "=>" << m_propName << "with mapped enum value" << m_enumNames[i];
// TODO: This does not work with bitmask properties, because from kernel we get the
// values for some reason as the shift distance instead of the full value.
// See: https://github.com/torvalds/linux/blob/6794862a/drivers/
// gpu/drm/drm_blend.c#L267
qCDebug(KWIN_DRM) << "=>" << m_propName
<< "with mapped enum value" << m_enumNames[i];
}
}
}
......
......@@ -17,8 +17,7 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef KWIN_DRM_OBJECT_H
#define KWIN_DRM_OBJECT_H
#pragma once
#include <QVector>
#include <QByteArray>
......@@ -36,11 +35,18 @@ class DrmOutput;
class DrmObject
{
public:
// creates drm object by its id delivered by the kernel
/**
* Create DRM object representation.
* @param object_id provided by the kernel
* @param fd of the DRM device
*/
DrmObject(uint32_t object_id, int fd);
virtual ~DrmObject();
/**
* Must be called to query necessary data directly after creation.
* @return true when initializing was successful
*/
virtual bool atomicInit() = 0;
uint32_t id() const {
......@@ -54,32 +60,37 @@ public:
m_output = output;
}
bool propHasEnum(int prop, uint64_t value) const {
auto property = m_props.at(prop);
return property ? property->hasEnum(value) : false;
}
void setValue(int prop, uint64_t new_value)
{
Q_ASSERT(prop < m_props.size());
auto property = m_props.at(prop);
if (property) {
property->setValue(new_value);
}
}
int fd() const {
return m_fd;
}
virtual bool atomicPopulate(drmModeAtomicReq *req);
/**
* Populate an atomic request with data of this object.
* @param req the atomic request
* @return true when the request was successfully populated
*/
virtual bool atomicPopulate(drmModeAtomicReq *req) const;
void setValue(int prop, uint64_t new_value);
bool propHasEnum(int prop, uint64_t value) const;
protected:
virtual bool initProps() = 0; // only derived classes know names and quantity of properties
/**
* Initialize properties of object. Only derived classes know names and quantities of
* properties.
*
* @return true when properties have been initialized successfully
*/
virtual bool initProps() = 0;
void setPropertyNames(QVector<QByteArray> &&vector);
void initProp(int n, drmModeObjectProperties *properties, QVector<QByteArray> enumNames = QVector<QByteArray>(0));
void initProp(int n, drmModeObjectProperties *properties,
QVector<QByteArray> enumNames = QVector<QByteArray>(0));
bool doAtomicPopulate(drmModeAtomicReq *req, int firstProperty) const;
class Property;
bool atomicAddProperty(drmModeAtomicReq *req, Property *property);
bool atomicAddProperty(drmModeAtomicReq *req, Property *property) const;
int m_fd;
const uint32_t m_id;
......@@ -96,7 +107,14 @@ protected:
void initEnumMap(drmModePropertyRes *prop);
uint64_t enumMap(int n) {
/**
* 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 {
......@@ -129,8 +147,5 @@ private:
QVector<QByteArray> m_propsNames;
};
}
#endif
......@@ -60,6 +60,11 @@ bool DrmPlane::atomicInit()
return true;
}
bool DrmPlane::atomicPopulate(drmModeAtomicReq *req) const
{
return doAtomicPopulate(req, 1);
}
bool DrmPlane::initProps()
{
setPropertyNames( {
......@@ -106,20 +111,22 @@ bool DrmPlane::initProps()
} else if (j == int(PropertyIndex::Rotation)) {
initProp(j, properties.data(), rotationNames);
m_supportedTransformations = Transformations();
auto testTransform = [j, this] (uint64_t value, Transformation t, const QString &name) {
auto checkSupport = [j, this] (uint64_t value, Transformation t, const QString &name) {
if (propHasEnum(j, value)) {
qCDebug(KWIN_DRM) << name;
m_supportedTransformations |= t;
}
};
qCDebug(KWIN_DRM).nospace() << "Supported Transformations on plane " << m_id << ":";
testTransform(0, Transformation::Rotate0, "rotate-0");
testTransform(1, Transformation::Rotate90, "rotate-90");
testTransform(2, Transformation::Rotate180, "rotate-180");
testTransform(3, Transformation::Rotate270, "rotate-270");
testTransform(4, Transformation::ReflectX, "reflect-x-axis");
testTransform(5, Transformation::ReflectY, "reflect-y-axis");
checkSupport(0, Transformation::Rotate0, "rotate-0");
checkSupport(1, Transformation::Rotate90, "rotate-90");
checkSupport(2, Transformation::Rotate180, "rotate-180");
checkSupport(3, Transformation::Rotate270, "rotate-270");
checkSupport(4, Transformation::ReflectX, "reflect-x");
checkSupport(5, Transformation::ReflectY, "reflect-y");
qCDebug(KWIN_DRM) << "";
} else {
initProp(j, properties.data());
}
......@@ -153,6 +160,8 @@ void DrmPlane::setNext(DrmBuffer *b)
void DrmPlane::setTransformation(Transformations t)
{
// TODO: When being pedantic, this should go through the enum mapping. Just remember
// that these are the shift distance, not the shifted value.
if (auto property = m_props.at(int(PropertyIndex::Rotation))) {
property->setValue(int(t));
}
......@@ -166,25 +175,6 @@ DrmPlane::Transformations DrmPlane::transformation()
return Transformations(Transformation::Rotate0);
}
bool DrmPlane::atomicPopulate(drmModeAtomicReq *req)
{
bool ret = true;
for (int i = 1; i < m_props.size(); i++) {
auto property = m_props.at(i);
if (!property) {
continue;
}
ret &= atomicAddProperty(req, property);
}
if (!ret) {
qCWarning(KWIN_DRM) << "Failed to populate atomic plane" << m_id;
return false;
}
return true;
}
void DrmPlane::flipBuffer()
{
m_current = m_next;
......
......@@ -17,11 +17,10 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef KWIN_DRM_OBJECT_PLANE_H
#define KWIN_DRM_OBJECT_PLANE_H
#pragma once
#include "drm_object.h"
// drm
#include <xf86drmMode.h>
namespace KWin
......@@ -60,12 +59,12 @@ public:
};
enum class Transformation {
Rotate0 = 1 << 0,
Rotate90 = 1 << 1,
Rotate180 = 1 << 2,
Rotate270 = 1 << 3,
ReflectX = 1 << 4,
ReflectY = 1 << 5
Rotate0 = 1 << 0,
Rotate90 = 1 << 1,
Rotate180 = 1 << 2,
Rotate270 = 1 << 3,
ReflectX = 1 << 4,
ReflectY = 1 << 5
};
Q_DECLARE_FLAGS(Transformations, Transformation);
......@@ -93,7 +92,6 @@ public:
void setTransformation(Transformations t);
Transformations transformation();
bool atomicPopulate(drmModeAtomicReq *req) override;
void flipBuffer();
void flipBufferWithDelete();
......@@ -101,6 +99,8 @@ public:
return m_supportedTransformations;
}
bool atomicPopulate(drmModeAtomicReq *req) const override;
private:
DrmBuffer *m_current = nullptr;
DrmBuffer *m_next = nullptr;
......@@ -118,5 +118,3 @@ private:
Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::DrmPlane::Transformations)
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment