Only use drmModeAddFB2WithModifiers if supported

This commit is contained in:
Xaver Hugl 2021-03-22 11:43:24 +01:00
parent c1635c1179
commit eb7703cd64
11 changed files with 47 additions and 33 deletions

View file

@ -9,6 +9,7 @@
#include "drm_buffer.h"
#include "logging.h"
#include "drm_gpu.h"
// system
#include <sys/mman.h>
@ -21,14 +22,14 @@
namespace KWin
{
DrmBuffer:: DrmBuffer(int fd)
: m_fd(fd)
DrmBuffer:: DrmBuffer(DrmGpu *gpu)
: m_gpu(gpu)
{
}
// DrmDumbBuffer
DrmDumbBuffer::DrmDumbBuffer(int fd, const QSize &size)
: DrmBuffer(fd)
DrmDumbBuffer::DrmDumbBuffer(DrmGpu *gpu, const QSize &size)
: DrmBuffer(gpu)
{
m_size = size;
drm_mode_create_dumb createArgs;
@ -36,14 +37,14 @@ DrmDumbBuffer::DrmDumbBuffer(int fd, const QSize &size)
createArgs.bpp = 32;
createArgs.width = size.width();
createArgs.height = size.height();
if (drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &createArgs) != 0) {
if (drmIoctl(m_gpu->fd(), DRM_IOCTL_MODE_CREATE_DUMB, &createArgs) != 0) {
qCWarning(KWIN_DRM) << "DRM_IOCTL_MODE_CREATE_DUMB failed";
return;
}
m_handle = createArgs.handle;
m_bufferSize = createArgs.size;
m_stride = createArgs.pitch;
if (drmModeAddFB(fd, size.width(), size.height(), 24, 32,
if (drmModeAddFB(m_gpu->fd(), size.width(), size.height(), 24, 32,
m_stride, createArgs.handle, &m_bufferId) != 0) {
qCWarning(KWIN_DRM) << "drmModeAddFB failed with errno" << errno;
}
@ -52,7 +53,7 @@ DrmDumbBuffer::DrmDumbBuffer(int fd, const QSize &size)
DrmDumbBuffer::~DrmDumbBuffer()
{
if (m_bufferId) {
drmModeRmFB(fd(), m_bufferId);
drmModeRmFB(m_gpu->fd(), m_bufferId);
}
delete m_image;
@ -62,7 +63,7 @@ DrmDumbBuffer::~DrmDumbBuffer()
if (m_handle) {
drm_mode_destroy_dumb destroyArgs;
destroyArgs.handle = m_handle;
drmIoctl(fd(), DRM_IOCTL_MODE_DESTROY_DUMB, &destroyArgs);
drmIoctl(m_gpu->fd(), DRM_IOCTL_MODE_DESTROY_DUMB, &destroyArgs);
}
}
@ -82,10 +83,10 @@ bool DrmDumbBuffer::map(QImage::Format format)
drm_mode_map_dumb mapArgs;
memset(&mapArgs, 0, sizeof mapArgs);
mapArgs.handle = m_handle;
if (drmIoctl(fd(), DRM_IOCTL_MODE_MAP_DUMB, &mapArgs) != 0) {
if (drmIoctl(m_gpu->fd(), DRM_IOCTL_MODE_MAP_DUMB, &mapArgs) != 0) {
return false;
}
void *address = mmap(nullptr, m_bufferSize, PROT_WRITE, MAP_SHARED, fd(), mapArgs.offset);
void *address = mmap(nullptr, m_bufferSize, PROT_WRITE, MAP_SHARED, m_gpu->fd(), mapArgs.offset);
if (address == MAP_FAILED) {
return false;
}

View file

@ -15,11 +15,13 @@
namespace KWin
{
class DrmGpu;
class DrmBuffer : public QObject
{
Q_OBJECT
public:
DrmBuffer(int fd);
DrmBuffer(DrmGpu *gpu);
virtual ~DrmBuffer() = default;
virtual bool needsModeChange(DrmBuffer *b) const {Q_UNUSED(b) return false;}
@ -34,20 +36,20 @@ public:
virtual void releaseGbm() {}
int fd() const {
return m_fd;
DrmGpu *gpu() const {
return m_gpu;
}
protected:
quint32 m_bufferId = 0;
QSize m_size;
int m_fd;
DrmGpu *m_gpu;
};
class DrmDumbBuffer : public DrmBuffer
{
public:
DrmDumbBuffer(int fd, const QSize &size);
DrmDumbBuffer(DrmGpu *gpu, const QSize &size);
~DrmDumbBuffer() override;
bool needsModeChange(DrmBuffer *b) const override;

View file

@ -11,6 +11,7 @@
#include "gbm_surface.h"
#include "logging.h"
#include "drm_gpu.h"
// system
#include <sys/mman.h>
@ -28,8 +29,8 @@ namespace KWin
{
// DrmSurfaceBuffer
DrmSurfaceBuffer::DrmSurfaceBuffer(int fd, const QSharedPointer<GbmSurface> &surface)
: DrmBuffer(fd)
DrmSurfaceBuffer::DrmSurfaceBuffer(DrmGpu *gpu, const QSharedPointer<GbmSurface> &surface)
: DrmBuffer(gpu)
, m_surface(surface)
{
m_bo = m_surface->lockFrontBuffer();
@ -40,8 +41,8 @@ DrmSurfaceBuffer::DrmSurfaceBuffer(int fd, const QSharedPointer<GbmSurface> &sur
initialize();
}
DrmSurfaceBuffer::DrmSurfaceBuffer(int fd, gbm_bo *buffer, KWaylandServer::BufferInterface *bufferInterface)
: DrmBuffer(fd)
DrmSurfaceBuffer::DrmSurfaceBuffer(DrmGpu *gpu, gbm_bo *buffer, KWaylandServer::BufferInterface *bufferInterface)
: DrmBuffer(gpu)
, m_bo(buffer)
, m_bufferInterface(bufferInterface)
{
@ -55,7 +56,7 @@ DrmSurfaceBuffer::DrmSurfaceBuffer(int fd, gbm_bo *buffer, KWaylandServer::Buffe
DrmSurfaceBuffer::~DrmSurfaceBuffer()
{
if (m_bufferId) {
drmModeRmFB(fd(), m_bufferId);
drmModeRmFB(m_gpu->fd(), m_bufferId);
}
releaseGbm();
if (m_bufferInterface) {
@ -99,14 +100,14 @@ void DrmSurfaceBuffer::initialize()
modifiers[0] = DRM_FORMAT_MOD_INVALID;
}
if (modifiers[0] != DRM_FORMAT_MOD_INVALID) {
if (drmModeAddFB2WithModifiers(m_fd, m_size.width(), m_size.height(), gbm_bo_get_format(m_bo), handles, strides, offsets, modifiers, &m_bufferId, DRM_MODE_FB_MODIFIERS)) {
if (modifiers[0] != DRM_FORMAT_MOD_INVALID && m_gpu->addFB2ModifiersSupported()) {
if (drmModeAddFB2WithModifiers(m_gpu->fd(), m_size.width(), m_size.height(), gbm_bo_get_format(m_bo), handles, strides, offsets, modifiers, &m_bufferId, DRM_MODE_FB_MODIFIERS)) {
qCWarning(KWIN_DRM) << "drmModeAddFB2WithModifiers failed!" << strerror(errno);
}
} else {
if (drmModeAddFB2(m_fd, m_size.width(), m_size.height(), gbm_bo_get_format(m_bo), handles, strides, offsets, &m_bufferId, 0)) {
if (drmModeAddFB2(m_gpu->fd(), m_size.width(), m_size.height(), gbm_bo_get_format(m_bo), handles, strides, offsets, &m_bufferId, 0)) {
// fallback
if (drmModeAddFB(m_fd, m_size.width(), m_size.height(), 24, 32, strides[0], handles[0], &m_bufferId) != 0) {
if (drmModeAddFB(m_gpu->fd(), m_size.width(), m_size.height(), 24, 32, strides[0], handles[0], &m_bufferId) != 0) {
qCWarning(KWIN_DRM) << "drmModeAddFB2 and drmModeAddFB both failed!" << strerror(errno);
}
}

View file

@ -29,8 +29,8 @@ class GbmSurface;
class DrmSurfaceBuffer : public DrmBuffer
{
public:
DrmSurfaceBuffer(int fd, const QSharedPointer<GbmSurface> &surface);
DrmSurfaceBuffer(int fd, gbm_bo *buffer, KWaylandServer::BufferInterface *bufferInterface);
DrmSurfaceBuffer(DrmGpu *gpu, const QSharedPointer<GbmSurface> &surface);
DrmSurfaceBuffer(DrmGpu *gpu, gbm_bo *buffer, KWaylandServer::BufferInterface *bufferInterface);
~DrmSurfaceBuffer() override;
bool needsModeChange(DrmBuffer *b) const override {

View file

@ -58,6 +58,11 @@ DrmGpu::DrmGpu(DrmBackend *backend, QByteArray devNode, int fd, int drmId) : m_b
m_presentationClock = CLOCK_REALTIME;
}
if (!qEnvironmentVariableIsSet("KWIN_DRM_NO_MODIFIERS")) {
m_addFB2ModifiersSupported = drmGetCap(fd, DRM_CAP_ADDFB2_MODIFIERS, &capability) && capability == 1;
qCDebug(KWIN_DRM) << "drmModeAddFB2WithModifiers is" << (m_addFB2ModifiersSupported ? "supported" : "not supported");
}
// find out if this GPU is using the NVidia proprietary driver
DrmScopedPointer<drmVersion> version(drmGetVersion(fd));
m_useEglStreams = strstr(version->name, "nvidia-drm");

View file

@ -92,6 +92,10 @@ public:
*/
clockid_t presentationClock() const;
bool addFB2ModifiersSupported() const {
return m_addFB2ModifiersSupported;
}
void waitIdle();
Q_SIGNALS:
@ -124,6 +128,7 @@ private:
EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
clockid_t m_presentationClock;
QSocketNotifier *m_socketNotifier = nullptr;
bool m_addFB2ModifiersSupported = false;
// all planes: primarys, cursors and overlays
QVector<DrmPlane*> m_planes;

View file

@ -81,7 +81,7 @@ bool DrmCrtc::blank(DrmOutput *output)
}
if (!m_blackBuffer) {
DrmDumbBuffer *blackBuffer = new DrmDumbBuffer(m_gpu->fd(), output->pixelSize());
DrmDumbBuffer *blackBuffer = new DrmDumbBuffer(m_gpu, output->pixelSize());
if (!blackBuffer->map()) {
delete blackBuffer;
return false;

View file

@ -359,7 +359,7 @@ void DrmOutput::initEdid(drmModeConnector *connector)
bool DrmOutput::initCursor(const QSize &cursorSize)
{
auto createCursor = [this, cursorSize] (int index) {
m_cursor[index].reset(new DrmDumbBuffer(m_gpu->fd(), cursorSize));
m_cursor[index].reset(new DrmDumbBuffer(m_gpu, cursorSize));
if (!m_cursor[index]->map(QImage::Format_ARGB32_Premultiplied)) {
return false;
}

View file

@ -580,7 +580,7 @@ void EglGbmBackend::aboutToStartPainting(int screenId, const QRegion &damagedReg
bool EglGbmBackend::presentOnOutput(Output &output, const QRegion &damagedRegion)
{
if (output.directScanoutBuffer) {
output.buffer = QSharedPointer<DrmSurfaceBuffer>::create(m_gpu->fd(), output.directScanoutBuffer, output.bufferInterface);
output.buffer = QSharedPointer<DrmSurfaceBuffer>::create(m_gpu, output.directScanoutBuffer, output.bufferInterface);
} else if (isPrimary()) {
if (supportsSwapBuffersWithDamage()) {
QVector<EGLint> rects = regionToRects(output.damageHistory.constFirst(), output.output);
@ -595,7 +595,7 @@ bool EglGbmBackend::presentOnOutput(Output &output, const QRegion &damagedRegion
return false;
}
}
output.buffer = QSharedPointer<DrmSurfaceBuffer>::create(m_gpu->fd(), output.gbmSurface);
output.buffer = QSharedPointer<DrmSurfaceBuffer>::create(m_gpu, output.gbmSurface);
} else {
qCDebug(KWIN_DRM) << "imported gbm_bo does not exist!";
return false;

View file

@ -281,7 +281,7 @@ bool EglStreamBackend::resetOutput(Output &o, DrmOutput *drmOutput)
{
o.output = drmOutput;
// dumb buffer used for modesetting
o.buffer = QSharedPointer<DrmDumbBuffer>::create(m_gpu->fd(), drmOutput->pixelSize());
o.buffer = QSharedPointer<DrmDumbBuffer>::create(m_gpu, drmOutput->pixelSize());
EGLAttrib streamAttribs[] = {
EGL_STREAM_FIFO_LENGTH_KHR, 0, // mailbox mode

View file

@ -45,7 +45,7 @@ void DrmQPainterBackend::initOutput(DrmOutput *output)
{
Output o;
auto initBuffer = [&o, output, this] (int index) {
o.buffer[index] = QSharedPointer<DrmDumbBuffer>::create(m_gpu->fd(), output->pixelSize());
o.buffer[index] = QSharedPointer<DrmDumbBuffer>::create(m_gpu, output->pixelSize());
if (o.buffer[index]->map()) {
o.buffer[index]->image()->fill(Qt::black);
}
@ -61,7 +61,7 @@ void DrmQPainterBackend::initOutput(DrmOutput *output)
return;
}
auto initBuffer = [it, output, this] (int index) {
it->buffer[index] = QSharedPointer<DrmDumbBuffer>::create(m_gpu->fd(), output->pixelSize());
it->buffer[index] = QSharedPointer<DrmDumbBuffer>::create(m_gpu, output->pixelSize());
if (it->buffer[index]->map()) {
it->buffer[index]->image()->fill(Qt::black);
}