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:
parent
d308262d4a
commit
a7a515a0af
9 changed files with 59 additions and 17 deletions
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -734,4 +734,9 @@ bool EglGbmBackend::hasOutput(AbstractOutput *output) const
|
|||
return m_outputs.contains(output);
|
||||
}
|
||||
|
||||
uint32_t EglGbmBackend::drmFormat() const
|
||||
{
|
||||
return m_gbmFormat;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
************************************************/
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue