platforms/drm: update properties on VT switch and failing commits
This commit is contained in:
parent
586efe94d4
commit
5ad0d18476
8 changed files with 137 additions and 97 deletions
|
@ -142,6 +142,7 @@ void DrmBackend::reactivate()
|
|||
m_active = true;
|
||||
|
||||
for (const auto &output : qAsConst(m_outputs)) {
|
||||
output->pipeline()->updateProperties();
|
||||
if (output->isEnabled()) {
|
||||
output->renderLoop()->uninhibit();
|
||||
output->showCursor();
|
||||
|
|
|
@ -19,10 +19,13 @@ namespace KWin
|
|||
* Definitions for class DrmObject
|
||||
*/
|
||||
|
||||
DrmObject::DrmObject(DrmGpu *gpu, uint32_t objectId)
|
||||
DrmObject::DrmObject(DrmGpu *gpu, uint32_t objectId, const QVector<PropertyDefinition> &&vector, uint32_t objectType)
|
||||
: m_gpu(gpu)
|
||||
, m_id(objectId)
|
||||
, m_objectType(objectType)
|
||||
, m_propertyDefinitions(vector)
|
||||
{
|
||||
m_props.resize(m_propertyDefinitions.count());
|
||||
}
|
||||
|
||||
DrmObject::~DrmObject()
|
||||
|
@ -30,37 +33,15 @@ DrmObject::~DrmObject()
|
|||
qDeleteAll(m_props);
|
||||
}
|
||||
|
||||
bool DrmObject::initProps(const QVector<PropertyDefinition> &&vector, uint32_t objectType)
|
||||
bool DrmObject::initProps()
|
||||
{
|
||||
DrmScopedPointer<drmModeObjectProperties> properties(drmModeObjectGetProperties(m_gpu->fd(), m_id, objectType));
|
||||
if (!properties) {
|
||||
qCWarning(KWIN_DRM) << "Failed to get properties for object" << m_id;
|
||||
if (!updateProperties()) {
|
||||
return false;
|
||||
}
|
||||
m_props.resize(vector.count());
|
||||
for (uint32_t i = 0; i < properties->count_props; i++) {
|
||||
DrmScopedPointer<drmModePropertyRes> prop(drmModeGetProperty(m_gpu->fd(), properties->props[i]));
|
||||
if (!prop) {
|
||||
qCWarning(KWIN_DRM, "Getting property %d of object %d failed!", i, m_id);
|
||||
continue;
|
||||
}
|
||||
for (int j = 0; j < vector.count(); j++) {
|
||||
const PropertyDefinition &def = vector[j];
|
||||
if (def.name == prop->name) {
|
||||
drmModePropertyBlobRes *blob = nullptr;
|
||||
if (prop->flags & DRM_MODE_PROP_BLOB) {
|
||||
blob = drmModeGetPropertyBlob(m_gpu->fd(), properties->prop_values[i]);
|
||||
}
|
||||
qCDebug(KWIN_DRM, "Found property %s with value %lu", def.name.data(), properties->prop_values[i]);
|
||||
m_props[j] = new Property(m_gpu, prop.data(), properties->prop_values[i], def.enumNames, blob);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (KWIN_DRM().isDebugEnabled()) {
|
||||
for (int i = 0; i < vector.count(); i++) {
|
||||
if (KWIN_DRM().isDebugEnabled() && m_gpu->atomicModeSetting()) {
|
||||
for (int i = 0; i < m_propertyDefinitions.count(); i++) {
|
||||
if (!m_props[i]) {
|
||||
qCDebug(KWIN_DRM) << "Could not find property" << vector[i].name;
|
||||
qCDebug(KWIN_DRM) << "Could not find property" << m_propertyDefinitions[i].name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -123,8 +104,50 @@ bool DrmObject::needsCommit() const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool DrmObject::updateProperties()
|
||||
{
|
||||
DrmScopedPointer<drmModeObjectProperties> properties(drmModeObjectGetProperties(m_gpu->fd(), m_id, m_objectType));
|
||||
if (!properties) {
|
||||
qCWarning(KWIN_DRM) << "Failed to get properties for object" << m_id;
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < m_propertyDefinitions.count(); i++) {
|
||||
const PropertyDefinition &def = m_propertyDefinitions[i];
|
||||
bool found = false;
|
||||
for (uint32_t j = 0; j < properties->count_props; j++) {
|
||||
DrmScopedPointer<drmModePropertyRes> prop(drmModeGetProperty(m_gpu->fd(), properties->props[j]));
|
||||
if (!prop) {
|
||||
qCWarning(KWIN_DRM, "Getting property %d of object %d failed!", j, m_id);
|
||||
continue;
|
||||
}
|
||||
if (def.name == prop->name) {
|
||||
drmModePropertyBlobRes *blob = nullptr;
|
||||
if (prop->flags & DRM_MODE_PROP_BLOB) {
|
||||
blob = drmModeGetPropertyBlob(m_gpu->fd(), properties->prop_values[j]);
|
||||
}
|
||||
if (m_props[i]) {
|
||||
if (prop->flags & DRM_MODE_PROP_BLOB) {
|
||||
m_props[i]->setCurrentBlob(blob);
|
||||
} else {
|
||||
m_props[i]->setCurrent(properties->prop_values[i]);
|
||||
}
|
||||
} else {
|
||||
qCDebug(KWIN_DRM, "Found property %s with value %lu", def.name.data(), properties->prop_values[j]);
|
||||
m_props[i] = new Property(m_gpu, prop.data(), properties->prop_values[j], def.enumNames, blob);
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
deleteProp(i);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Definitions for struct Prop
|
||||
* Definitions for DrmObject::Property
|
||||
*/
|
||||
|
||||
DrmObject::Property::Property(DrmGpu *gpu, drmModePropertyRes *prop, uint64_t val, const QVector<QByteArray> &enumNames, drmModePropertyBlobRes *blob)
|
||||
|
|
|
@ -26,12 +26,6 @@ class DrmOutput;
|
|||
class DrmObject
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create DRM object representation.
|
||||
* @param object_id provided by the kernel
|
||||
* @param fd of the DRM device
|
||||
*/
|
||||
DrmObject(DrmGpu *gpu, uint32_t objectId);
|
||||
virtual ~DrmObject();
|
||||
|
||||
/**
|
||||
|
@ -182,6 +176,8 @@ public:
|
|||
bool needsCommit() const;
|
||||
virtual bool needsModeset() const = 0;
|
||||
|
||||
virtual bool updateProperties();
|
||||
|
||||
protected:
|
||||
struct PropertyDefinition
|
||||
{
|
||||
|
@ -192,13 +188,10 @@ protected:
|
|||
QByteArray name;
|
||||
QVector<QByteArray> enumNames;
|
||||
};
|
||||
/**
|
||||
* Initialize properties of object. Only derived classes know names and quantities of
|
||||
* properties.
|
||||
*
|
||||
* @return true when properties have been initialized successfully
|
||||
*/
|
||||
bool initProps(const QVector<PropertyDefinition> &&vector, uint32_t objectType);
|
||||
|
||||
DrmObject(DrmGpu *gpu, uint32_t objectId, const QVector<PropertyDefinition> &&vector, uint32_t objectType);
|
||||
|
||||
bool initProps();
|
||||
|
||||
template <typename T>
|
||||
void deleteProp(T prop)
|
||||
|
@ -207,12 +200,13 @@ protected:
|
|||
m_props[static_cast<uint32_t>(prop)] = nullptr;
|
||||
}
|
||||
|
||||
// for comparison with received name of DRM object
|
||||
QVector<Property *> m_props;
|
||||
|
||||
private:
|
||||
DrmGpu *m_gpu;
|
||||
const uint32_t m_id;
|
||||
const uint32_t m_objectType;
|
||||
const QVector<PropertyDefinition> m_propertyDefinitions;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -22,7 +22,21 @@ namespace KWin
|
|||
{
|
||||
|
||||
DrmConnector::DrmConnector(DrmGpu *gpu, uint32_t connectorId)
|
||||
: DrmObject(gpu, connectorId)
|
||||
: DrmObject(gpu, connectorId, {
|
||||
PropertyDefinition(QByteArrayLiteral("CRTC_ID")),
|
||||
PropertyDefinition(QByteArrayLiteral("non-desktop")),
|
||||
PropertyDefinition(QByteArrayLiteral("DPMS")),
|
||||
PropertyDefinition(QByteArrayLiteral("EDID")),
|
||||
PropertyDefinition(QByteArrayLiteral("overscan")),
|
||||
PropertyDefinition(QByteArrayLiteral("vrr_capable")),
|
||||
PropertyDefinition(QByteArrayLiteral("underscan"), {
|
||||
QByteArrayLiteral("off"),
|
||||
QByteArrayLiteral("on"),
|
||||
QByteArrayLiteral("auto")
|
||||
}),
|
||||
PropertyDefinition(QByteArrayLiteral("underscan vborder")),
|
||||
PropertyDefinition(QByteArrayLiteral("underscan hborder")),
|
||||
}, DRM_MODE_OBJECT_CONNECTOR)
|
||||
, m_conn(drmModeGetConnector(gpu->fd(), connectorId))
|
||||
{
|
||||
if (m_conn) {
|
||||
|
@ -62,21 +76,7 @@ bool DrmConnector::init()
|
|||
}
|
||||
qCDebug(KWIN_DRM) << "Creating connector" << id();
|
||||
|
||||
if (!initProps({
|
||||
PropertyDefinition(QByteArrayLiteral("CRTC_ID")),
|
||||
PropertyDefinition(QByteArrayLiteral("non-desktop")),
|
||||
PropertyDefinition(QByteArrayLiteral("DPMS")),
|
||||
PropertyDefinition(QByteArrayLiteral("EDID")),
|
||||
PropertyDefinition(QByteArrayLiteral("overscan")),
|
||||
PropertyDefinition(QByteArrayLiteral("vrr_capable")),
|
||||
PropertyDefinition(QByteArrayLiteral("underscan"), {
|
||||
QByteArrayLiteral("off"),
|
||||
QByteArrayLiteral("on"),
|
||||
QByteArrayLiteral("auto")
|
||||
}),
|
||||
PropertyDefinition(QByteArrayLiteral("underscan vborder")),
|
||||
PropertyDefinition(QByteArrayLiteral("underscan hborder")),
|
||||
}, DRM_MODE_OBJECT_CONNECTOR)) {
|
||||
if (!initProps()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,13 @@ namespace KWin
|
|||
{
|
||||
|
||||
DrmCrtc::DrmCrtc(DrmGpu *gpu, uint32_t crtcId, int pipeIndex)
|
||||
: DrmObject(gpu, crtcId)
|
||||
: DrmObject(gpu, crtcId, {
|
||||
PropertyDefinition(QByteArrayLiteral("MODE_ID")),
|
||||
PropertyDefinition(QByteArrayLiteral("ACTIVE")),
|
||||
PropertyDefinition(QByteArrayLiteral("VRR_ENABLED")),
|
||||
PropertyDefinition(QByteArrayLiteral("GAMMA_LUT")),
|
||||
PropertyDefinition(QByteArrayLiteral("GAMMA_LUT_SIZE")),
|
||||
}, DRM_MODE_OBJECT_CRTC)
|
||||
, m_crtc(drmModeGetCrtc(gpu->fd(), crtcId))
|
||||
, m_pipeIndex(pipeIndex)
|
||||
{
|
||||
|
@ -30,13 +36,7 @@ bool DrmCrtc::init()
|
|||
return false;
|
||||
}
|
||||
qCDebug(KWIN_DRM) << "Init for CRTC:" << pipeIndex() << "id:" << id();
|
||||
return initProps({
|
||||
PropertyDefinition(QByteArrayLiteral("MODE_ID")),
|
||||
PropertyDefinition(QByteArrayLiteral("ACTIVE")),
|
||||
PropertyDefinition(QByteArrayLiteral("VRR_ENABLED")),
|
||||
PropertyDefinition(QByteArrayLiteral("GAMMA_LUT")),
|
||||
PropertyDefinition(QByteArrayLiteral("GAMMA_LUT_SIZE")),
|
||||
}, DRM_MODE_OBJECT_CRTC);
|
||||
return initProps();
|
||||
}
|
||||
|
||||
void DrmCrtc::flipBuffer()
|
||||
|
|
|
@ -16,29 +16,7 @@ namespace KWin
|
|||
{
|
||||
|
||||
DrmPlane::DrmPlane(DrmGpu *gpu, uint32_t planeId)
|
||||
: DrmObject(gpu, planeId)
|
||||
{
|
||||
}
|
||||
|
||||
bool DrmPlane::init()
|
||||
{
|
||||
qCDebug(KWIN_DRM) << "Atomic init for plane:" << id();
|
||||
DrmScopedPointer<drmModePlane> p(drmModeGetPlane(gpu()->fd(), id()));
|
||||
|
||||
if (!p) {
|
||||
qCWarning(KWIN_DRM) << "Failed to get kernel plane" << id();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_possibleCrtcs = p->possible_crtcs;
|
||||
|
||||
int count_formats = p->count_formats;
|
||||
m_formats.resize(count_formats);
|
||||
for (int i = 0; i < count_formats; i++) {
|
||||
m_formats[i] = p->formats[i];
|
||||
}
|
||||
|
||||
bool success = initProps({
|
||||
: DrmObject(gpu, planeId, {
|
||||
PropertyDefinition(QByteArrayLiteral("type"), {
|
||||
QByteArrayLiteral("Overlay"),
|
||||
QByteArrayLiteral("Primary"),
|
||||
|
@ -60,8 +38,29 @@ bool DrmPlane::init()
|
|||
QByteArrayLiteral("rotate-270"),
|
||||
QByteArrayLiteral("reflect-x"),
|
||||
QByteArrayLiteral("reflect-y")}),
|
||||
}, DRM_MODE_OBJECT_PLANE
|
||||
);
|
||||
}, DRM_MODE_OBJECT_PLANE)
|
||||
{
|
||||
}
|
||||
|
||||
bool DrmPlane::init()
|
||||
{
|
||||
qCDebug(KWIN_DRM) << "Atomic init for plane:" << id();
|
||||
DrmScopedPointer<drmModePlane> p(drmModeGetPlane(gpu()->fd(), id()));
|
||||
|
||||
if (!p) {
|
||||
qCWarning(KWIN_DRM) << "Failed to get kernel plane" << id();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_possibleCrtcs = p->possible_crtcs;
|
||||
|
||||
int count_formats = p->count_formats;
|
||||
m_formats.resize(count_formats);
|
||||
for (int i = 0; i < count_formats; i++) {
|
||||
m_formats[i] = p->formats[i];
|
||||
}
|
||||
|
||||
bool success = initProps();
|
||||
if (success) {
|
||||
m_supportedTransformations = Transformations();
|
||||
auto checkSupport = [this] (uint64_t value, Transformation t) {
|
||||
|
|
|
@ -83,12 +83,23 @@ bool DrmPipeline::present(const QSharedPointer<DrmBuffer> &buffer)
|
|||
return true;
|
||||
}
|
||||
}
|
||||
bool result = m_gpu->atomicModeSetting() ? atomicCommit() : presentLegacy();
|
||||
if (!result) {
|
||||
qCWarning(KWIN_DRM) << "Present failed!" << strerror(errno);
|
||||
printDebugInfo();
|
||||
if (m_gpu->atomicModeSetting()) {
|
||||
if (!atomicCommit()) {
|
||||
// update properties and try again
|
||||
updateProperties();
|
||||
if (!atomicCommit()) {
|
||||
qCWarning(KWIN_DRM) << "Atomic present failed!" << strerror(errno);
|
||||
printDebugInfo();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!presentLegacy()) {
|
||||
qCWarning(KWIN_DRM) << "Present failed!" << strerror(errno);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DrmPipeline::atomicCommit()
|
||||
|
@ -333,6 +344,10 @@ bool DrmPipeline::setActive(bool active)
|
|||
m_primaryPlane->setPending(DrmPlane::PropertyIndex::CrtcId, active ? m_crtc->id() : 0);
|
||||
if (active) {
|
||||
success = test();
|
||||
if (!success) {
|
||||
updateProperties();
|
||||
success = test();
|
||||
}
|
||||
} else {
|
||||
// immediately commit if disabling as there will be no present
|
||||
success = atomicCommit();
|
||||
|
@ -497,6 +512,13 @@ void DrmPipeline::setUserData(DrmOutput *data)
|
|||
m_pageflipUserData = data;
|
||||
}
|
||||
|
||||
void DrmPipeline::updateProperties()
|
||||
{
|
||||
for (const auto &obj : qAsConst(m_allObjects)) {
|
||||
obj->updateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
static void printProps(DrmObject *object)
|
||||
{
|
||||
auto list = object->properties();
|
||||
|
|
|
@ -71,6 +71,7 @@ public:
|
|||
void printDebugInfo() const;
|
||||
void setUserData(DrmOutput *data);
|
||||
QSize sourceSize() const;
|
||||
void updateProperties();
|
||||
|
||||
private:
|
||||
bool atomicCommit();
|
||||
|
|
Loading…
Reference in a new issue