Refactor DRM presentation

Presentation doesn't have to go through DrmBackend and by moving
DrmGpu::deleteBufferAfterPageflip into DrmBuffer some code can be
simplified
This commit is contained in:
Xaver Hugl 2021-03-20 19:18:52 +01:00
parent 8c352f685e
commit a8055e4546
13 changed files with 44 additions and 80 deletions

View file

@ -516,23 +516,6 @@ DrmOutput *DrmBackend::findOutput(quint32 connector)
return nullptr;
}
bool DrmBackend::present(DrmBuffer *buffer, DrmOutput *output)
{
if (!buffer || buffer->bufferId() == 0) {
if (output->gpu()->deleteBufferAfterPageFlip()) {
delete buffer;
}
return false;
}
if (output->present(buffer)) {
return true;
} else if (output->gpu()->deleteBufferAfterPageFlip()) {
delete buffer;
}
return false;
}
void DrmBackend::initCursor()
{
@ -640,7 +623,6 @@ void DrmBackend::moveCursor()
QPainterBackend *DrmBackend::createQPainterBackend()
{
m_gpus.at(0)->setDeleteBufferAfterPageFlip(false);
return new DrmQPainterBackend(this, m_gpus.at(0));
}

View file

@ -61,8 +61,6 @@ public:
void init() override;
void prepareShutdown() override;
bool present(DrmBuffer *buffer, DrmOutput *output);
Outputs outputs() const override;
Outputs enabledOutputs() const override;
QVector<DrmOutput*> drmOutputs() const {

View file

@ -23,6 +23,9 @@ public:
virtual ~DrmBuffer() = default;
virtual bool needsModeChange(DrmBuffer *b) const {Q_UNUSED(b) return false;}
virtual bool shouldDeleteAfterPageflip() const {
return false;
}
quint32 bufferId() const {
return m_bufferId;

View file

@ -40,6 +40,9 @@ public:
return true;
}
}
bool shouldDeleteAfterPageflip() const override {
return true;
}
bool hasBo() const {
return m_bo != nullptr;

View file

@ -62,8 +62,6 @@ DrmGpu::DrmGpu(DrmBackend *backend, QByteArray devNode, int fd, int drmId) : m_b
DrmScopedPointer<drmVersion> version(drmGetVersion(fd));
m_useEglStreams = strstr(version->name, "nvidia-drm");
m_deleteBufferAfterPageFlip = !m_useEglStreams;
m_socketNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
connect(m_socketNotifier, &QSocketNotifier::activated, this, &DrmGpu::dispatchEvents);
}

View file

@ -58,10 +58,6 @@ public:
return m_useEglStreams;
}
bool deleteBufferAfterPageFlip() const {
return m_deleteBufferAfterPageFlip;
}
QByteArray devNode() const {
return m_devNode;
}
@ -86,10 +82,6 @@ public:
m_eglDisplay = display;
}
void setDeleteBufferAfterPageFlip(bool deleteBuffer) {
m_deleteBufferAfterPageFlip = deleteBuffer;
}
DrmDumbBuffer *createBuffer(const QSize &size) const {
return new DrmDumbBuffer(m_fd, size);
}
@ -132,7 +124,6 @@ private:
const int m_drmId;
bool m_atomicModeSetting;
bool m_useEglStreams;
bool m_deleteBufferAfterPageFlip;
gbm_device* m_gbmDevice;
EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
clockid_t m_presentationClock;

View file

@ -67,7 +67,7 @@ bool DrmCrtc::initProps()
void DrmCrtc::flipBuffer()
{
if (m_currentBuffer && m_gpu->deleteBufferAfterPageFlip() && m_currentBuffer != m_nextBuffer) {
if (m_currentBuffer && m_currentBuffer->shouldDeleteAfterPageflip() && m_currentBuffer != m_nextBuffer) {
delete m_currentBuffer;
}
m_currentBuffer = m_nextBuffer;
@ -94,7 +94,7 @@ bool DrmCrtc::blank(DrmOutput *output)
}
if (output->setModeLegacy(m_blackBuffer)) {
if (m_currentBuffer && m_gpu->deleteBufferAfterPageFlip()) {
if (m_currentBuffer && m_currentBuffer->shouldDeleteAfterPageflip()) {
delete m_currentBuffer;
delete m_nextBuffer;
}

View file

@ -164,16 +164,11 @@ DrmPlane::Transformations DrmPlane::transformation()
void DrmPlane::flipBuffer()
{
if (m_current != m_next && m_current && m_current->shouldDeleteAfterPageflip()) {
delete m_current;
}
m_current = m_next;
m_next = nullptr;
}
void DrmPlane::flipBufferWithDelete()
{
if (m_current != m_next) {
delete m_current;
}
flipBuffer();
}
}

View file

@ -87,7 +87,6 @@ public:
Transformations transformation();
void flipBuffer();
void flipBufferWithDelete();
Transformations supportedTransformations() const {
return m_supportedTransformations;

View file

@ -70,7 +70,7 @@ void DrmOutput::teardown()
if (m_primaryPlane) {
// TODO: when having multiple planes, also clean up these
if (m_gpu->deleteBufferAfterPageFlip()) {
if (m_primaryPlane->current() && m_primaryPlane->current()->shouldDeleteAfterPageflip()) {
delete m_primaryPlane->current();
}
m_primaryPlane->setCurrent(nullptr);
@ -670,41 +670,23 @@ void DrmOutput::pageFlipped()
if (!m_crtc) {
return;
}
// Egl based surface buffers get destroyed, QPainter based dumb buffers not
// TODO: split up DrmOutput in two for dumb and egl/gbm surface buffer compatible subclasses completely?
if (m_gpu->deleteBufferAfterPageFlip()) {
if (m_gpu->atomicModeSetting()) {
if (!m_primaryPlane->next()) {
// on manual vt switch
// TODO: when we later use overlay planes it might happen, that we have a page flip with only
// damage on one of these, and therefore the primary plane has no next buffer
// -> Then we don't want to return here!
if (m_primaryPlane->current()) {
m_primaryPlane->current()->releaseGbm();
}
return;
if (m_gpu->atomicModeSetting()) {
if (!m_primaryPlane->next()) {
if (m_primaryPlane->current()) {
m_primaryPlane->current()->releaseGbm();
}
for (DrmPlane *p : m_nextPlanesFlipList) {
p->flipBufferWithDelete();
}
m_nextPlanesFlipList.clear();
} else {
if (!m_crtc->next()) {
// on manual vt switch
if (DrmBuffer *b = m_crtc->current()) {
b->releaseGbm();
}
}
m_crtc->flipBuffer();
return;
}
for (DrmPlane *p : m_nextPlanesFlipList) {
p->flipBuffer();
}
m_nextPlanesFlipList.clear();
} else {
if (m_gpu->atomicModeSetting()){
for (DrmPlane *p : m_nextPlanesFlipList) {
p->flipBuffer();
if (!m_crtc->next()) {
// on manual vt switch
if (DrmBuffer *b = m_crtc->current()) {
b->releaseGbm();
}
m_nextPlanesFlipList.clear();
} else {
m_crtc->flipBuffer();
}
m_crtc->flipBuffer();
}
@ -716,14 +698,25 @@ void DrmOutput::pageFlipped()
bool DrmOutput::present(DrmBuffer *buffer)
{
if (!buffer || buffer->bufferId() == 0) {
if (buffer && buffer->shouldDeleteAfterPageflip()) {
delete buffer;
}
return false;
}
if (m_dpmsModePending != DpmsMode::On) {
return false;
}
bool result;
if (m_gpu->atomicModeSetting()) {
return presentAtomically(buffer);
result = presentAtomically(buffer);
} else {
return presentLegacy(buffer);
result = presentLegacy(buffer);
}
if (!result && buffer->shouldDeleteAfterPageflip()) {
delete buffer;
}
return result;
}
bool DrmOutput::dpmsAtomicOff()
@ -976,8 +969,10 @@ bool DrmOutput::atomicReqModesetPopulate(drmModeAtomicReq *req, bool enable)
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::CrtcH), targetRect.height());
m_primaryPlane->setValue(int(DrmPlane::PropertyIndex::CrtcId), m_crtc->id());
} else {
if (m_gpu->deleteBufferAfterPageFlip()) {
if (m_primaryPlane->current() && m_primaryPlane->current()->shouldDeleteAfterPageflip()) {
delete m_primaryPlane->current();
}
if (m_primaryPlane->next() && m_primaryPlane->next()->shouldDeleteAfterPageflip()) {
delete m_primaryPlane->next();
}
m_primaryPlane->setCurrent(nullptr);

View file

@ -602,7 +602,7 @@ bool EglGbmBackend::presentOnOutput(Output &output, const QRegion &damagedRegion
}
Q_EMIT output.output->outputChange(damagedRegion);
if (!m_backend->present(output.buffer, output.output)) {
if (!output.output->present(output.buffer)) {
return false;
}

View file

@ -446,7 +446,7 @@ bool EglStreamBackend::presentOnOutput(EglStreamBackend::Output &o)
return false;
}
return m_backend->present(o.buffer, o.output);
return o.output->present(o.buffer);
}
SceneOpenGLTexturePrivate *EglStreamBackend::createBackendTexture(SceneOpenGLTexture *texture)

View file

@ -114,7 +114,7 @@ void DrmQPainterBackend::endFrame(int screenId, int mask, const QRegion &damage)
const Output &rendererOutput = m_outputs[screenId];
DrmOutput *drmOutput = rendererOutput.output;
if (!m_backend->present(rendererOutput.buffer[rendererOutput.index], drmOutput)) {
if (!drmOutput->present(rendererOutput.buffer[rendererOutput.index])) {
RenderLoopPrivate *renderLoopPrivate = RenderLoopPrivate::get(drmOutput->renderLoop());
renderLoopPrivate->notifyFrameFailed();
}