kwin/src/plugins/platforms/drm/drm_object_plane.cpp
Xaver Hugl ca869e2bc5 platforms/drm: disable explicit modifiers by default
There are some unresolved issues where driving outputs can fail because
of bandwidth constraints. These don't appear to happen with implicit
modifiers, or at least they don't happen as often.
2021-09-17 13:52:07 +00:00

172 lines
6.3 KiB
C++

/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2016 Roman Gilg <subdiff@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "drm_object_plane.h"
#include "drm_buffer.h"
#include "drm_gpu.h"
#include "drm_pointer.h"
#include "logging.h"
#include "config-kwin.h"
#include <drm_fourcc.h>
namespace KWin
{
DrmPlane::DrmPlane(DrmGpu *gpu, uint32_t planeId)
: DrmObject(gpu, planeId, {
PropertyDefinition(QByteArrayLiteral("type"), Requirement::Required, {
QByteArrayLiteral("Overlay"),
QByteArrayLiteral("Primary"),
QByteArrayLiteral("Cursor")}),
PropertyDefinition(QByteArrayLiteral("SRC_X"), Requirement::Required),
PropertyDefinition(QByteArrayLiteral("SRC_Y"), Requirement::Required),
PropertyDefinition(QByteArrayLiteral("SRC_W"), Requirement::Required),
PropertyDefinition(QByteArrayLiteral("SRC_H"), Requirement::Required),
PropertyDefinition(QByteArrayLiteral("CRTC_X"), Requirement::Required),
PropertyDefinition(QByteArrayLiteral("CRTC_Y"), Requirement::Required),
PropertyDefinition(QByteArrayLiteral("CRTC_W"), Requirement::Required),
PropertyDefinition(QByteArrayLiteral("CRTC_H"), Requirement::Required),
PropertyDefinition(QByteArrayLiteral("FB_ID"), Requirement::Required),
PropertyDefinition(QByteArrayLiteral("CRTC_ID"), Requirement::Required),
PropertyDefinition(QByteArrayLiteral("rotation"), Requirement::Optional, {
QByteArrayLiteral("rotate-0"),
QByteArrayLiteral("rotate-90"),
QByteArrayLiteral("rotate-180"),
QByteArrayLiteral("rotate-270"),
QByteArrayLiteral("reflect-x"),
QByteArrayLiteral("reflect-y")}),
PropertyDefinition(QByteArrayLiteral("IN_FORMATS"), Requirement::Optional),
}, DRM_MODE_OBJECT_PLANE)
{
}
bool DrmPlane::init()
{
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;
bool success = initProps();
if (success) {
m_supportedTransformations = Transformations();
auto checkSupport = [this] (uint64_t value, Transformation t) {
if (propHasEnum(PropertyIndex::Rotation, value)) {
m_supportedTransformations |= t;
}
};
checkSupport(0, Transformation::Rotate0);
checkSupport(1, Transformation::Rotate90);
checkSupport(2, Transformation::Rotate180);
checkSupport(3, Transformation::Rotate270);
checkSupport(4, Transformation::ReflectX);
checkSupport(5, Transformation::ReflectY);
// read formats from blob if available and if modifiers are supported, and from the plane object if not
if (auto formatProp = getProp(PropertyIndex::In_Formats); formatProp && gpu()->addFB2ModifiersSupported() && qEnvironmentVariableIntValue("KWIN_DRM_USE_MODIFIERS") == 1) {
auto blob = static_cast<drm_format_modifier_blob*>(formatProp->currentBlob()->data);
auto modifiers = reinterpret_cast<drm_format_modifier*>(reinterpret_cast<uint8_t*>(blob) + blob->modifiers_offset);
uint32_t *formatarr = reinterpret_cast<uint32_t*>(reinterpret_cast<uint8_t*>(blob) + blob->formats_offset);
for (uint32_t f = 0; f < blob->count_formats; f++) {
auto format = formatarr[f];
QVector<uint64_t> mods;
for (uint32_t m = 0; m < blob->count_modifiers; m++) {
auto modifier = &modifiers[m];
// The modifier advertisement blob is partitioned into groups of 64 formats
if (m < modifier->offset || m > modifier->offset + 63) {
continue;
}
if (!(modifier->formats & (1 << (f - modifier->offset)))) {
continue;
}
mods << modifier->modifier;
}
m_supportedFormats.insert(format, mods);
}
} else {
for (uint32_t i = 0; i < p->count_formats; i++) {
m_supportedFormats.insert(p->formats[i], {});
}
}
if (m_supportedFormats.isEmpty()) {
qCWarning(KWIN_DRM) << "Driver doesn't advertise any formats for this plane. Falling back to XRGB8888 and ARGB8888 without modifiers";
m_supportedFormats.insert(DRM_FORMAT_XRGB8888, {});
m_supportedFormats.insert(DRM_FORMAT_ARGB8888, {});
}
}
return success;
}
DrmPlane::TypeIndex DrmPlane::type()
{
const auto &prop = getProp(PropertyIndex::Type);
return prop->enumForValue<DrmPlane::TypeIndex>(prop->current());
}
void DrmPlane::setNext(const QSharedPointer<DrmBuffer> &b)
{
m_next = b;
}
bool DrmPlane::setTransformation(Transformations t)
{
if (m_supportedTransformations & t) {
return setPending(PropertyIndex::Rotation, t);
} else {
return false;
}
}
DrmPlane::Transformations DrmPlane::transformation()
{
if (auto property = getProp(PropertyIndex::Rotation)) {
return Transformations(static_cast<uint32_t>(property->pending()));
}
return Transformations(Transformation::Rotate0);
}
void DrmPlane::flipBuffer()
{
m_current = m_next;
m_next = nullptr;
}
void DrmPlane::set(const QPoint &srcPos, const QSize &srcSize, const QPoint &dstPos, const QSize &dstSize)
{
// Src* are in 16.16 fixed point format
setPending(PropertyIndex::SrcX, srcPos.x() << 16);
setPending(PropertyIndex::SrcY, srcPos.y() << 16);
setPending(PropertyIndex::SrcW, srcSize.width() << 16);
setPending(PropertyIndex::SrcH, srcSize.height() << 16);
setPending(PropertyIndex::CrtcX, dstPos.x());
setPending(PropertyIndex::CrtcY, dstPos.y());
setPending(PropertyIndex::CrtcW, dstSize.width());
setPending(PropertyIndex::CrtcH, dstSize.height());
}
void DrmPlane::setBuffer(DrmBuffer *buffer)
{
setPending(PropertyIndex::FbId, buffer ? buffer->bufferId() : 0);
}
bool DrmPlane::needsModeset() const
{
auto rotation = getProp(PropertyIndex::Rotation);
if (rotation && rotation->needsCommit()) {
return true;
}
return getProp(PropertyIndex::CrtcId)->needsCommit();
}
}