Commit d5dad1b4 authored by Xaver Hugl's avatar Xaver Hugl
Browse files

backends/drm: properly release all buffers on render backend destruction

Releasing the buffers is necessary for example in the case of a GPU reset,
to make sure that the gbm surface is still properly destroyed and all buffers
with invalid content freed.
parent c65c8223
Pipeline #172574 passed with stage
in 30 minutes and 59 seconds
......@@ -695,4 +695,10 @@ DrmRenderBackend *DrmBackend::renderBackend() const
return m_renderBackend;
}
void DrmBackend::releaseBuffers()
{
for (const auto &gpu : qAsConst(m_gpus)) {
gpu->releaseBuffers();
}
}
}
......@@ -71,6 +71,8 @@ public:
void setRenderBackend(DrmRenderBackend *backend);
DrmRenderBackend *renderBackend() const;
void releaseBuffers();
public Q_SLOTS:
void turnOutputsOn();
void sceneInitialized() override;
......
......@@ -99,14 +99,15 @@ void DrmGpuBuffer::createFds()
}
DrmFramebuffer::DrmFramebuffer(const std::shared_ptr<DrmGpuBuffer> &buffer, uint32_t fbId)
: m_buffer(buffer)
, m_framebufferId(fbId)
: m_framebufferId(fbId)
, m_gpu(buffer->gpu())
, m_buffer(buffer)
{
}
DrmFramebuffer::~DrmFramebuffer()
{
drmModeRmFB(m_buffer->gpu()->fd(), m_framebufferId);
drmModeRmFB(m_gpu->fd(), m_framebufferId);
}
uint32_t DrmFramebuffer::framebufferId() const
......@@ -119,6 +120,11 @@ DrmGpuBuffer *DrmFramebuffer::buffer() const
return m_buffer.get();
}
void DrmFramebuffer::releaseBuffer()
{
m_buffer.reset();
}
std::shared_ptr<DrmFramebuffer> DrmFramebuffer::createFramebuffer(const std::shared_ptr<DrmGpuBuffer> &buffer)
{
const auto size = buffer->size();
......
......@@ -58,13 +58,19 @@ public:
~DrmFramebuffer();
uint32_t framebufferId() const;
/**
* may be nullptr
*/
DrmGpuBuffer *buffer() const;
void releaseBuffer();
static std::shared_ptr<DrmFramebuffer> createFramebuffer(const std::shared_ptr<DrmGpuBuffer> &buffer);
protected:
const std::shared_ptr<DrmGpuBuffer> m_buffer;
const uint32_t m_framebufferId;
DrmGpu *const m_gpu;
std::shared_ptr<DrmGpuBuffer> m_buffer;
};
}
......@@ -12,6 +12,7 @@
#include "abstract_egl_backend.h"
#include "drm_backend.h"
#include "drm_layer.h"
#include "drm_lease_output.h"
#include "drm_object_connector.h"
#include "drm_object_crtc.h"
......@@ -780,6 +781,24 @@ QSize DrmGpu::cursorSize() const
return m_cursorSize;
}
void DrmGpu::releaseBuffers()
{
for (const auto &plane : qAsConst(m_planes)) {
plane->releaseBuffers();
}
for (const auto &crtc : qAsConst(m_crtcs)) {
crtc->releaseBuffers();
}
for (const auto &pipeline : qAsConst(m_pipelines)) {
pipeline->layer()->releaseBuffers();
}
for (const auto &output : qAsConst(m_outputs)) {
if (const auto virtualOutput = qobject_cast<DrmVirtualOutput *>(output)) {
virtualOutput->outputLayer()->releaseBuffers();
}
}
}
void DrmGpu::recreateSurfaces()
{
for (const auto &pipeline : qAsConst(m_pipelines)) {
......
......@@ -82,6 +82,7 @@ public:
bool needsModeset() const;
bool maybeModeset();
void releaseBuffers();
void recreateSurfaces();
Q_SIGNALS:
......
......@@ -29,6 +29,7 @@ public:
virtual QSharedPointer<GLTexture> texture() const;
virtual QRegion currentDamage() const;
virtual void releaseBuffers() = 0;
};
class DrmPipelineLayer : public DrmOutputLayer
......
......@@ -20,12 +20,9 @@
namespace KWin
{
DrmLeaseEglGbmLayer::DrmLeaseEglGbmLayer(EglGbmBackend *backend, DrmPipeline *pipeline)
DrmLeaseEglGbmLayer::DrmLeaseEglGbmLayer(DrmPipeline *pipeline)
: DrmPipelineLayer(pipeline)
{
connect(backend, &EglGbmBackend::aboutToBeDestroyed, this, [this]() {
m_framebuffer.reset();
});
}
bool DrmLeaseEglGbmLayer::checkTestBuffer()
......@@ -68,4 +65,9 @@ void DrmLeaseEglGbmLayer::endFrame(const QRegion &damagedRegion, const QRegion &
Q_UNUSED(damagedRegion)
Q_UNUSED(renderedRegion)
}
void DrmLeaseEglGbmLayer::releaseBuffers()
{
m_framebuffer.reset();
}
}
......@@ -19,13 +19,14 @@ class EglGbmBackend;
class DrmLeaseEglGbmLayer : public DrmPipelineLayer
{
public:
DrmLeaseEglGbmLayer(EglGbmBackend *backend, DrmPipeline *pipeline);
DrmLeaseEglGbmLayer(DrmPipeline *pipeline);
OutputLayerBeginFrameInfo beginFrame() override;
void endFrame(const QRegion &damagedRegion, const QRegion &renderedRegion) override;
bool checkTestBuffer() override;
std::shared_ptr<DrmFramebuffer> currentBuffer() const override;
void releaseBuffers() override;
private:
std::shared_ptr<DrmFramebuffer> m_framebuffer;
......
......@@ -108,4 +108,13 @@ void DrmCrtc::disable()
setPending(PropertyIndex::ModeId, 0);
}
void DrmCrtc::releaseBuffers()
{
if (m_nextBuffer) {
m_nextBuffer->releaseBuffer();
}
if (m_currentBuffer) {
m_currentBuffer->releaseBuffer();
}
}
}
......@@ -53,6 +53,7 @@ public:
void setCurrent(const std::shared_ptr<DrmFramebuffer> &buffer);
void setNext(const std::shared_ptr<DrmFramebuffer> &buffer);
void flipBuffer();
void releaseBuffers();
private:
DrmScopedPointer<drmModeCrtc> m_crtc;
......
......@@ -201,4 +201,13 @@ void DrmPlane::disable()
setPending(PropertyIndex::FbId, 0);
}
void DrmPlane::releaseBuffers()
{
if (m_next) {
m_next->releaseBuffer();
}
if (m_current) {
m_current->releaseBuffer();
}
}
}
......@@ -86,6 +86,8 @@ public:
Transformations transformation();
Transformations supportedTransformations() const;
void releaseBuffers();
private:
std::shared_ptr<DrmFramebuffer> m_current;
std::shared_ptr<DrmFramebuffer> m_next;
......
......@@ -371,7 +371,7 @@ QSize DrmPipeline::bufferSize() const
bool DrmPipeline::isCursorVisible() const
{
const QRect mode = QRect(QPoint(), m_pending.mode->size());
return m_pending.cursorFb && QRect(m_pending.cursorPos, m_pending.cursorFb->buffer()->size()).intersects(mode);
return m_pending.cursorFb && (!m_pending.cursorFb->buffer() || QRect(m_pending.cursorPos, m_pending.cursorFb->buffer()->size()).intersects(mode));
}
DrmConnector *DrmPipeline::connector() const
......
......@@ -23,12 +23,9 @@
namespace KWin
{
DrmQPainterLayer::DrmQPainterLayer(DrmQPainterBackend *backend, DrmPipeline *pipeline)
DrmQPainterLayer::DrmQPainterLayer(DrmPipeline *pipeline)
: DrmPipelineLayer(pipeline)
{
connect(backend, &DrmQPainterBackend::aboutToBeDestroyed, this, [this]() {
m_swapchain.reset();
});
}
OutputLayerBeginFrameInfo DrmQPainterLayer::beginFrame()
......@@ -76,6 +73,11 @@ QRegion DrmQPainterLayer::currentDamage() const
return m_currentDamage;
}
void DrmQPainterLayer::releaseBuffers()
{
m_swapchain.reset();
}
DrmVirtualQPainterLayer::DrmVirtualQPainterLayer(DrmVirtualOutput *output)
: m_output(output)
{
......@@ -103,12 +105,13 @@ QRegion DrmVirtualQPainterLayer::currentDamage() const
return m_currentDamage;
}
DrmLeaseQPainterLayer::DrmLeaseQPainterLayer(DrmQPainterBackend *backend, DrmPipeline *pipeline)
void DrmVirtualQPainterLayer::releaseBuffers()
{
}
DrmLeaseQPainterLayer::DrmLeaseQPainterLayer(DrmPipeline *pipeline)
: DrmPipelineLayer(pipeline)
{
connect(backend, &DrmQPainterBackend::aboutToBeDestroyed, this, [this]() {
m_buffer.reset();
});
}
bool DrmLeaseQPainterLayer::checkTestBuffer()
......@@ -140,4 +143,9 @@ void DrmLeaseQPainterLayer::endFrame(const QRegion &damagedRegion, const QRegion
Q_UNUSED(damagedRegion)
Q_UNUSED(renderedRegion)
}
void DrmLeaseQPainterLayer::releaseBuffers()
{
m_buffer.reset();
}
}
......@@ -24,13 +24,14 @@ class DrmFramebuffer;
class DrmQPainterLayer : public DrmPipelineLayer
{
public:
DrmQPainterLayer(DrmQPainterBackend *backend, DrmPipeline *pipeline);
DrmQPainterLayer(DrmPipeline *pipeline);
OutputLayerBeginFrameInfo beginFrame() override;
void endFrame(const QRegion &damagedRegion, const QRegion &renderedRegion) override;
bool checkTestBuffer() override;
std::shared_ptr<DrmFramebuffer> currentBuffer() const override;
QRegion currentDamage() const override;
void releaseBuffers() override;
private:
bool doesSwapchainFit() const;
......@@ -49,6 +50,7 @@ public:
void endFrame(const QRegion &damagedRegion, const QRegion &renderedRegion) override;
QRegion currentDamage() const override;
void releaseBuffers() override;
private:
QImage m_image;
......@@ -59,13 +61,14 @@ private:
class DrmLeaseQPainterLayer : public DrmPipelineLayer
{
public:
DrmLeaseQPainterLayer(DrmQPainterBackend *backend, DrmPipeline *pipeline);
DrmLeaseQPainterLayer(DrmPipeline *pipeline);
OutputLayerBeginFrameInfo beginFrame() override;
void endFrame(const QRegion &damagedRegion, const QRegion &renderedRegion) override;
bool checkTestBuffer() override;
std::shared_ptr<DrmFramebuffer> currentBuffer() const override;
void releaseBuffers() override;
private:
std::shared_ptr<DrmFramebuffer> m_framebuffer;
......
......@@ -56,7 +56,7 @@ EglGbmBackend::EglGbmBackend(DrmBackend *drmBackend)
EglGbmBackend::~EglGbmBackend()
{
Q_EMIT aboutToBeDestroyed();
m_backend->releaseBuffers();
cleanup();
m_backend->setRenderBackend(nullptr);
}
......@@ -242,7 +242,7 @@ QSharedPointer<DrmPipelineLayer> EglGbmBackend::createDrmPipelineLayer(DrmPipeli
if (pipeline->output()) {
return QSharedPointer<EglGbmLayer>::create(this, pipeline);
} else {
return QSharedPointer<DrmLeaseEglGbmLayer>::create(this, pipeline);
return QSharedPointer<DrmLeaseEglGbmLayer>::create(pipeline);
}
}
......
......@@ -78,9 +78,6 @@ public:
std::optional<GbmFormat> gbmFormatForDrmFormat(uint32_t format) const;
DrmGpu *gpu() const;
Q_SIGNALS:
void aboutToBeDestroyed();
private:
bool initializeEgl();
bool initBufferConfigs();
......
......@@ -137,4 +137,10 @@ bool EglGbmLayer::hasDirectScanoutBuffer() const
return m_scanoutBuffer != nullptr;
}
void EglGbmLayer::releaseBuffers()
{
m_currentBuffer.reset();
m_scanoutBuffer.reset();
m_surface.destroyResources();
}
}
......@@ -39,6 +39,7 @@ public:
bool hasDirectScanoutBuffer() const override;
QRegion currentDamage() const override;
QSharedPointer<GLTexture> texture() const override;
void releaseBuffers() override;
private:
std::shared_ptr<DrmFramebuffer> m_scanoutBuffer;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment