platforms/drm: Add buffer age support in qpainter backend
Currently, the entire screen will be repainted when using the qpainter render backend. With this change, kwin will repaint only the dirty parts on the screen.
This commit is contained in:
parent
603db353a3
commit
e087b2ce2f
4 changed files with 54 additions and 16 deletions
|
@ -26,26 +26,42 @@ DumbSwapchain::DumbSwapchain(DrmGpu *gpu, const QSize &size)
|
|||
break;
|
||||
}
|
||||
buffer->image()->fill(Qt::black);
|
||||
m_buffers << buffer;
|
||||
m_slots.append(Slot{.buffer = buffer, .age = 0,});
|
||||
}
|
||||
if (m_buffers.count() < 2) {
|
||||
if (m_slots.count() < 2) {
|
||||
qCWarning(KWIN_DRM) << "Failed to create dumb buffers for swapchain!";
|
||||
m_buffers.clear();
|
||||
m_slots.clear();
|
||||
}
|
||||
}
|
||||
|
||||
QSharedPointer<DrmDumbBuffer> DumbSwapchain::acquireBuffer()
|
||||
QSharedPointer<DrmDumbBuffer> DumbSwapchain::acquireBuffer(int *age)
|
||||
{
|
||||
if (m_buffers.isEmpty()) {
|
||||
if (m_slots.isEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
index = (index + 1) % m_buffers.count();
|
||||
return m_buffers[index];
|
||||
index = (index + 1) % m_slots.count();
|
||||
if (age) {
|
||||
*age = m_slots[index].age;
|
||||
}
|
||||
return m_slots[index].buffer;
|
||||
}
|
||||
|
||||
QSharedPointer<DrmDumbBuffer> DumbSwapchain::currentBuffer() const
|
||||
{
|
||||
return m_buffers[index];
|
||||
return m_slots[index].buffer;
|
||||
}
|
||||
|
||||
void DumbSwapchain::releaseBuffer(QSharedPointer<DrmDumbBuffer> buffer)
|
||||
{
|
||||
Q_ASSERT(m_slots[index].buffer == buffer);
|
||||
|
||||
for (qsizetype i = 0; i < m_slots.count(); ++i) {
|
||||
if (m_slots[i].buffer == buffer) {
|
||||
m_slots[i].age = 1;
|
||||
} else if (m_slots[i].age > 0) {
|
||||
m_slots[i].age++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,22 +24,32 @@ class DumbSwapchain
|
|||
public:
|
||||
DumbSwapchain(DrmGpu *gpu, const QSize &size);
|
||||
|
||||
QSharedPointer<DrmDumbBuffer> acquireBuffer();
|
||||
QSharedPointer<DrmDumbBuffer> acquireBuffer(int *age = nullptr);
|
||||
QSharedPointer<DrmDumbBuffer> currentBuffer() const;
|
||||
void releaseBuffer(QSharedPointer<DrmDumbBuffer> buffer);
|
||||
|
||||
qsizetype slotCount() const {
|
||||
return m_slots.count();
|
||||
}
|
||||
|
||||
QSize size() const {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
bool isEmpty() const {
|
||||
return m_buffers.isEmpty();
|
||||
return m_slots.isEmpty();
|
||||
}
|
||||
|
||||
private:
|
||||
QSize m_size;
|
||||
struct Slot
|
||||
{
|
||||
QSharedPointer<DrmDumbBuffer> buffer;
|
||||
int age = 0;
|
||||
};
|
||||
|
||||
QSize m_size;
|
||||
int index = 0;
|
||||
QVector<QSharedPointer<DrmDumbBuffer>> m_buffers;
|
||||
QVector<Slot> m_slots;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ void DrmQPainterBackend::initOutput(DrmOutput *output)
|
|||
return;
|
||||
}
|
||||
it->swapchain = QSharedPointer<DumbSwapchain>::create(m_gpu, output->pixelSize());
|
||||
it->damageJournal.setCapacity(it->swapchain->slotCount());
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -68,21 +69,30 @@ QImage *DrmQPainterBackend::bufferForScreen(int screenId)
|
|||
|
||||
QRegion DrmQPainterBackend::beginFrame(int screenId)
|
||||
{
|
||||
m_outputs[screenId].swapchain->acquireBuffer();
|
||||
return m_outputs[screenId].output->geometry();
|
||||
Output *rendererOutput = &m_outputs[screenId];
|
||||
|
||||
int bufferAge;
|
||||
rendererOutput->swapchain->acquireBuffer(&bufferAge);
|
||||
|
||||
return rendererOutput->damageJournal.accumulate(bufferAge, rendererOutput->output->geometry());
|
||||
}
|
||||
|
||||
void DrmQPainterBackend::endFrame(int screenId, const QRegion &damage)
|
||||
{
|
||||
Q_UNUSED(damage)
|
||||
|
||||
const Output &rendererOutput = m_outputs[screenId];
|
||||
Output &rendererOutput = m_outputs[screenId];
|
||||
DrmOutput *drmOutput = rendererOutput.output;
|
||||
|
||||
if (!drmOutput->present(rendererOutput.swapchain->currentBuffer(), drmOutput->geometry())) {
|
||||
QSharedPointer<DrmDumbBuffer> back = rendererOutput.swapchain->currentBuffer();
|
||||
rendererOutput.swapchain->releaseBuffer(back);
|
||||
|
||||
if (!drmOutput->present(back, drmOutput->geometry())) {
|
||||
RenderLoopPrivate *renderLoopPrivate = RenderLoopPrivate::get(drmOutput->renderLoop());
|
||||
renderLoopPrivate->notifyFrameFailed();
|
||||
}
|
||||
|
||||
rendererOutput.damageJournal.add(damage);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#ifndef KWIN_SCENE_QPAINTER_DRM_BACKEND_H
|
||||
#define KWIN_SCENE_QPAINTER_DRM_BACKEND_H
|
||||
#include "qpainterbackend.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
|
@ -39,6 +40,7 @@ private:
|
|||
struct Output {
|
||||
DrmOutput *output;
|
||||
QSharedPointer<DumbSwapchain> swapchain;
|
||||
DamageJournal damageJournal;
|
||||
};
|
||||
QVector<Output> m_outputs;
|
||||
DrmBackend *m_backend;
|
||||
|
|
Loading…
Reference in a new issue