platforms/drm: re-use buffers for testing

b38bb416 introduced flicker when restarting compositing because the
DrmGpu::findWorkingCombination method usually creates new buffers for
the commit, without rendering into them. Instead of that, re-use
existing buffers where possible
This commit is contained in:
Xaver Hugl 2021-09-17 11:01:18 +02:00
parent d308262d4a
commit a7a515a0af
9 changed files with 59 additions and 17 deletions

View file

@ -62,6 +62,8 @@ public:
virtual QSharedPointer<DrmBuffer> renderTestFrame(DrmAbstractOutput *output) = 0;
virtual uint32_t drmFormat() const = 0;
static AbstractEglDrmBackend *renderingBackend() {
return static_cast<AbstractEglDrmBackend*>(primaryBackend());
}

View file

@ -18,18 +18,21 @@
// drm
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <drm_fourcc.h>
namespace KWin
{
DrmBuffer:: DrmBuffer(DrmGpu *gpu)
DrmBuffer:: DrmBuffer(DrmGpu *gpu, uint32_t format, uint64_t modifier)
: m_gpu(gpu)
, m_format(format)
, m_modifier(modifier)
{
}
// DrmDumbBuffer
DrmDumbBuffer::DrmDumbBuffer(DrmGpu *gpu, const QSize &size)
: DrmBuffer(gpu)
: DrmBuffer(gpu, DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_LINEAR)
{
m_size = size;
drm_mode_create_dumb createArgs;

View file

@ -20,7 +20,7 @@ class DrmGpu;
class DrmBuffer
{
public:
DrmBuffer(DrmGpu *gpu);
DrmBuffer(DrmGpu *gpu, uint32_t format, uint64_t modifier);
virtual ~DrmBuffer() = default;
virtual bool needsModeChange(DrmBuffer *b) const {Q_UNUSED(b) return false;}
@ -36,11 +36,19 @@ public:
DrmGpu *gpu() const {
return m_gpu;
}
uint32_t format() const {
return m_format;
}
uint64_t modifier() const {
return m_modifier;
}
protected:
quint32 m_bufferId = 0;
QSize m_size;
DrmGpu *m_gpu;
uint32_t m_format;
uint64_t m_modifier;
};
class DrmDumbBuffer : public DrmBuffer

View file

@ -85,13 +85,13 @@ bool GbmBuffer::map(uint32_t flags)
DrmGbmBuffer::DrmGbmBuffer(DrmGpu *gpu, GbmSurface *surface, gbm_bo *bo)
: DrmBuffer(gpu), GbmBuffer(surface, bo)
: DrmBuffer(gpu, gbm_bo_get_format(bo), gbm_bo_get_modifier(bo)), GbmBuffer(surface, bo)
{
initialize();
}
DrmGbmBuffer::DrmGbmBuffer(DrmGpu *gpu, gbm_bo *buffer, KWaylandServer::ClientBuffer *clientBuffer)
: DrmBuffer(gpu), GbmBuffer(buffer, clientBuffer)
: DrmBuffer(gpu, gbm_bo_get_format(buffer), gbm_bo_get_modifier(buffer)), GbmBuffer(buffer, clientBuffer)
{
initialize();
}
@ -108,7 +108,6 @@ DrmGbmBuffer::~DrmGbmBuffer()
void DrmGbmBuffer::initialize()
{
m_size = QSize(gbm_bo_get_width(m_bo), gbm_bo_get_height(m_bo));
uint32_t format = gbm_bo_get_format(m_bo);
uint32_t handles[4] = { };
uint32_t strides[4] = { };
uint32_t offsets[4] = { };
@ -119,7 +118,7 @@ void DrmGbmBuffer::initialize()
handles[i] = gbm_bo_get_handle_for_plane(m_bo, i).u32;
strides[i] = gbm_bo_get_stride_for_plane(m_bo, i);
offsets[i] = gbm_bo_get_offset(m_bo, i);
modifiers[i] = gbm_bo_get_modifier(m_bo);
modifiers[i] = m_modifier;
}
} else {
handles[0] = gbm_bo_get_handle(m_bo).u32;
@ -128,17 +127,17 @@ void DrmGbmBuffer::initialize()
}
if (modifiers[0] != DRM_FORMAT_MOD_INVALID && m_gpu->addFB2ModifiersSupported()) {
if (drmModeAddFB2WithModifiers(m_gpu->fd(), m_size.width(), m_size.height(), format, handles, strides, offsets, modifiers, &m_bufferId, DRM_MODE_FB_MODIFIERS)) {
if (drmModeAddFB2WithModifiers(m_gpu->fd(), m_size.width(), m_size.height(), m_format, handles, strides, offsets, modifiers, &m_bufferId, DRM_MODE_FB_MODIFIERS)) {
gbm_format_name_desc name;
gbm_format_get_name(format, &name);
gbm_format_get_name(m_format, &name);
qCCritical(KWIN_DRM) << "drmModeAddFB2WithModifiers on GPU" << m_gpu->devNode() << "failed for a buffer with format" << name.name << "and modifier" << modifiers[0] << strerror(errno);
}
} else {
if (drmModeAddFB2(m_gpu->fd(), m_size.width(), m_size.height(), format, handles, strides, offsets, &m_bufferId, 0)) {
if (drmModeAddFB2(m_gpu->fd(), m_size.width(), m_size.height(), m_format, handles, strides, offsets, &m_bufferId, 0)) {
// fallback
if (drmModeAddFB(m_gpu->fd(), m_size.width(), m_size.height(), 24, 32, strides[0], handles[0], &m_bufferId) != 0) {
gbm_format_name_desc name;
gbm_format_get_name(format, &name);
gbm_format_get_name(m_format, &name);
qCCritical(KWIN_DRM) << "drmModeAddFB2 and drmModeAddFB both failed on GPU" << m_gpu->devNode() << "for a buffer with format" << name.name << "and modifier" << modifiers[0] << strerror(errno);
}
}

View file

@ -275,10 +275,29 @@ bool DrmPipeline::checkTestBuffer()
if (!isActive()) {
return true;
}
QSharedPointer<DrmBuffer> buffer;
#if HAVE_GBM
auto backend = m_gpu->eglBackend();
if (backend && m_output) {
QSharedPointer<DrmBuffer> buffer;
// try to re-use buffers if possible.
const auto &checkBuffer = [this, backend, &buffer](const QSharedPointer<DrmBuffer> &buf){
if (buf->format() == backend->drmFormat()
&& (!m_gpu->atomicModeSetting() || supportedModifiers(buf->format()).contains(buf->modifier()))
&& buf->size() == sourceSize()) {
buffer = buf;
}
};
if (m_primaryPlane && m_primaryPlane->next()) {
checkBuffer(m_primaryPlane->next());
} else if (m_primaryPlane && m_primaryPlane->current()) {
checkBuffer(m_primaryPlane->current());
} else if (m_crtc->next()) {
checkBuffer(m_crtc->next());
} else if (m_crtc->current()) {
checkBuffer(m_crtc->current());
}
// if we don't have a fitting buffer already, get or create one
if (buffer) {
#if HAVE_GBM
} else if (backend && m_output) {
buffer = backend->renderTestFrame(m_output);
} else if (backend && m_gpu->gbmDevice()) {
gbm_bo *bo = gbm_bo_create(m_gpu->gbmDevice(), sourceSize().width(), sourceSize().height(), GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
@ -286,12 +305,10 @@ bool DrmPipeline::checkTestBuffer()
return false;
}
buffer = QSharedPointer<DrmGbmBuffer>::create(m_gpu, bo, nullptr);
#endif
} else {
buffer = QSharedPointer<DrmDumbBuffer>::create(m_gpu, sourceSize());
}
#else
buffer = QSharedPointer<DrmDumbBuffer>::create(m_gpu, sourceSize());
#endif
if (buffer && buffer->bufferId()) {
m_oldTestBuffer = m_primaryBuffer;
m_primaryBuffer = buffer;

View file

@ -734,4 +734,9 @@ bool EglGbmBackend::hasOutput(AbstractOutput *output) const
return m_outputs.contains(output);
}
uint32_t EglGbmBackend::drmFormat() const
{
return m_gbmFormat;
}
}

View file

@ -65,6 +65,7 @@ public:
bool directScanoutAllowed(AbstractOutput *output) const override;
QSharedPointer<DrmBuffer> renderTestFrame(DrmAbstractOutput *output) override;
uint32_t drmFormat() const override;
protected:
void cleanupSurfaces() override;

View file

@ -32,6 +32,7 @@
#include <KWaylandServer/clientbuffer.h>
#include <KWaylandServer/display.h>
#include <KWaylandServer/eglstream_controller_interface.h>
#include <drm_fourcc.h>
namespace KWin
{
@ -576,6 +577,11 @@ bool EglStreamBackend::hasOutput(AbstractOutput *output) const
return m_outputs.contains(output);
}
uint32_t EglStreamBackend::drmFormat() const
{
return DRM_FORMAT_XRGB8888;
}
/************************************************
* EglTexture
************************************************/

View file

@ -44,6 +44,7 @@ public:
void removeOutput(DrmAbstractOutput *output) override;
QSharedPointer<DrmBuffer> renderTestFrame(DrmAbstractOutput *output) override;
uint32_t drmFormat() const override;
protected:
void cleanupSurfaces() override;