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

backends/drm: fix layer destruction

Layers need to release their resources whenever the render backend gets
replaced.
parent a04bdf23
Pipeline #141089 passed with stage
in 21 minutes and 6 seconds
......@@ -14,6 +14,7 @@ set(DRM_SOURCES
dumb_swapchain.cpp
shadowbuffer.cpp
drm_display_device.cpp
drm_layer.cpp
drm_pipeline.cpp
drm_pipeline_legacy.cpp
drm_abstract_output.cpp
......
......@@ -28,6 +28,7 @@
#include "waylandoutputconfig.h"
#include "egl_gbm_backend.h"
#include "gbm_dmabuf.h"
#include "drm_render_backend.h"
// KF5
#include <KCoreAddons>
#include <KLocalizedString>
......@@ -550,7 +551,13 @@ OpenGLBackend *DrmBackend::createOpenGLBackend()
void DrmBackend::sceneInitialized()
{
updateOutputs();
if (m_outputs.isEmpty()) {
updateOutputs();
} else {
for (const auto &gpu : qAsConst(m_gpus)) {
gpu->recreateSurfaces();
}
}
}
QVector<CompositingType> DrmBackend::supportedCompositors() const
......@@ -593,8 +600,8 @@ void DrmBackend::removeVirtualOutput(AbstractOutput *output)
DmaBufTexture *DrmBackend::createDmaBufTexture(const QSize &size)
{
if (primaryGpu()->eglBackend() && primaryGpu()->gbmDevice()) {
primaryGpu()->eglBackend()->makeCurrent();
if (const auto eglBackend = dynamic_cast<EglGbmBackend*>(m_renderBackend); eglBackend && primaryGpu()->gbmDevice()) {
eglBackend->makeCurrent();
return GbmDmaBuf::createBuffer(size, primaryGpu()->gbmDevice());
} else {
return nullptr;
......@@ -664,4 +671,14 @@ bool DrmBackend::applyOutputChanges(const WaylandOutputConfig &config)
return true;
}
void DrmBackend::setRenderBackend(DrmRenderBackend *backend)
{
m_renderBackend = backend;
}
DrmRenderBackend *DrmBackend::renderBackend() const
{
return m_renderBackend;
}
}
......@@ -30,6 +30,7 @@ class DrmAbstractOutput;
class Cursor;
class DrmGpu;
class DrmVirtualOutput;
class DrmRenderBackend;
class KWIN_EXPORT DrmBackend : public Platform
{
......@@ -67,6 +68,9 @@ public:
bool isActive() const;
void setRenderBackend(DrmRenderBackend *backend);
DrmRenderBackend *renderBackend() const;
public Q_SLOTS:
void turnOutputsOn();
void sceneInitialized() override;
......@@ -105,6 +109,7 @@ private:
QVector<DrmGpu*> m_gpus;
QScopedPointer<DpmsInputEventFilter> m_dpmsFilter;
QScopedPointer<PlaceholderInputEventFilter> m_placeholderFilter;
DrmRenderBackend *m_renderBackend = nullptr;
};
......
......@@ -422,7 +422,7 @@ bool DrmGpu::testPipelines()
QVector<DrmPipeline*> inactivePipelines;
for (const auto &pipeline : qAsConst(m_pipelines)) {
if (!pipeline->pending.layer) {
pipeline->pending.layer = m_renderBackend->createLayer(pipeline->displayDevice());
pipeline->pending.layer = m_platform->renderBackend()->createLayer(pipeline->displayDevice());
}
if (!pipeline->pending.active) {
pipeline->pending.active = true;
......@@ -562,21 +562,6 @@ void DrmGpu::removeOutput(DrmOutput *output)
delete output;
}
EglGbmBackend *DrmGpu::eglBackend() const
{
return dynamic_cast<EglGbmBackend*>(m_renderBackend);
}
DrmRenderBackend *DrmGpu::renderBackend() const
{
return m_renderBackend;
}
void DrmGpu::setRenderBackend(DrmRenderBackend *backend)
{
m_renderBackend = backend;
}
DrmBackend *DrmGpu::platform() const {
return m_platform;
}
......@@ -782,4 +767,16 @@ QSize DrmGpu::cursorSize() const
return m_cursorSize;
}
void DrmGpu::recreateSurfaces()
{
for (const auto &pipeline : qAsConst(m_pipelines)) {
pipeline->pending.layer = m_platform->renderBackend()->createLayer(pipeline->displayDevice());
}
for (const auto &output : qAsConst(m_outputs)) {
if (const auto virtualOutput = qobject_cast<DrmVirtualOutput*>(output)) {
virtualOutput->recreateSurface();
}
}
}
}
......@@ -59,8 +59,6 @@ public:
bool isNVidia() const;
gbm_device *gbmDevice() const;
EGLDisplay eglDisplay() const;
EglGbmBackend *eglBackend() const;
DrmRenderBackend *renderBackend() const;
DrmBackend *platform() const;
/**
* Returns the clock from which presentation timestamps are sourced. The returned value
......@@ -73,7 +71,6 @@ public:
const QVector<DrmPipeline*> pipelines() const;
void setEglDisplay(EGLDisplay display);
void setRenderBackend(DrmRenderBackend *backend);
bool updateOutputs();
......@@ -89,6 +86,8 @@ public:
bool needsModeset() const;
bool maybeModeset();
void recreateSurfaces();
Q_SIGNALS:
void outputAdded(DrmAbstractOutput *output);
void outputRemoved(DrmAbstractOutput *output);
......@@ -122,7 +121,6 @@ private:
clockid_t m_presentationClock;
gbm_device* m_gbmDevice;
EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
DrmRenderBackend *m_renderBackend;
DrmBackend* const m_platform;
QVector<DrmPlane*> m_planes;
......
/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "drm_layer.h"
namespace KWin
{
DrmLayer::DrmLayer(KWin::DrmDisplayDevice* device)
: m_displayDevice(device)
{
}
DrmLayer::~DrmLayer() = default;
DrmDisplayDevice *DrmLayer::displayDevice() const
{
return m_displayDevice;
}
}
#include "drm_layer.moc"
......@@ -11,6 +11,7 @@
#include <optional>
#include <QRegion>
#include <QSharedPointer>
#include <QObject>
namespace KWin
{
......@@ -19,10 +20,12 @@ class SurfaceItem;
class DrmBuffer;
class DrmDisplayDevice;
class DrmLayer
class DrmLayer : public QObject
{
Q_OBJECT
public:
virtual ~DrmLayer() = default;
DrmLayer(DrmDisplayDevice *device);
virtual ~DrmLayer();
virtual std::optional<QRegion> startRendering() = 0;
virtual bool endRendering(const QRegion &damagedRegion) = 0;
......@@ -44,7 +47,10 @@ public:
virtual QRegion currentDamage() const = 0;
virtual bool hasDirectScanoutBuffer() const = 0;
virtual DrmDisplayDevice *displayDevice() const = 0;
DrmDisplayDevice *displayDevice() const;
protected:
DrmDisplayDevice *const m_displayDevice;
};
}
......@@ -10,6 +10,9 @@
#include "dumb_swapchain.h"
#include "drm_abstract_output.h"
#include "drm_buffer.h"
#include "scene_qpainter_drm_backend.h"
#include "drm_gpu.h"
#include "drm_backend.h"
#include <drm_fourcc.h>
......@@ -17,8 +20,11 @@ namespace KWin
{
DrmQPainterLayer::DrmQPainterLayer(DrmDisplayDevice *displayDevice)
: m_displayDevice(displayDevice)
: DrmLayer(displayDevice)
{
connect(static_cast<DrmQPainterBackend*>(displayDevice->gpu()->platform()->renderBackend()), &DrmQPainterBackend::aboutToBeDestroyed, this, [this]() {
m_swapchain.reset();
});
}
std::optional<QRegion> DrmQPainterLayer::startRendering()
......@@ -69,11 +75,6 @@ QRegion DrmQPainterLayer::currentDamage() const
return m_currentDamage;
}
DrmDisplayDevice *DrmQPainterLayer::displayDevice() const
{
return m_displayDevice;
}
bool DrmQPainterLayer::hasDirectScanoutBuffer() const
{
return false;
......
......@@ -14,7 +14,8 @@ namespace KWin
class DumbSwapchain;
class DrmQPainterLayer : public DrmLayer {
class DrmQPainterLayer : public DrmLayer
{
public:
DrmQPainterLayer(DrmDisplayDevice *displayDevice);
......@@ -25,14 +26,12 @@ public:
QSharedPointer<DrmBuffer> currentBuffer() const override;
QRegion currentDamage() const override;
bool hasDirectScanoutBuffer() const override;
DrmDisplayDevice *displayDevice() const override;
private:
bool doesSwapchainFit() const;
QSharedPointer<DumbSwapchain> m_swapchain;
QRegion m_currentDamage;
DrmDisplayDevice *const m_displayDevice;
};
}
......@@ -21,7 +21,7 @@ class DrmRenderBackend
public:
virtual ~DrmRenderBackend() = default;
virtual QSharedPointer<DrmLayer> createLayer(DrmDisplayDevice *displayDevice) const = 0;
virtual QSharedPointer<DrmLayer> createLayer(DrmDisplayDevice *displayDevice) = 0;
};
......
......@@ -44,7 +44,7 @@ DrmVirtualOutput::DrmVirtualOutput(const QString &name, DrmGpu *gpu, const QSize
QByteArray("EDID_") + name.toUtf8());
m_renderLoop->setRefreshRate(modes[m_modeIndex].refreshRate);
m_layer = gpu->renderBackend()->createLayer(this);
recreateSurface();
}
DrmVirtualOutput::~DrmVirtualOutput()
......@@ -131,4 +131,9 @@ bool DrmVirtualOutput::testScanout()
return true;
}
void DrmVirtualOutput::recreateSurface()
{
m_layer = m_gpu->platform()->renderBackend()->createLayer(this);
}
}
......@@ -43,6 +43,8 @@ public:
DrmLayer *outputLayer() const override;
bool testScanout() override;
void recreateSurface();
private:
void vblank(std::chrono::nanoseconds timestamp);
void setDpmsMode(DpmsMode mode) override;
......
......@@ -49,14 +49,15 @@ EglGbmBackend::EglGbmBackend(DrmBackend *drmBackend)
: AbstractEglBackend(drmBackend->primaryGpu()->deviceId())
, m_backend(drmBackend)
{
drmBackend->primaryGpu()->setRenderBackend(this);
drmBackend->setRenderBackend(this);
setIsDirectRendering(true);
}
EglGbmBackend::~EglGbmBackend()
{
Q_EMIT aboutToBeDestroyed();
cleanup();
m_backend->primaryGpu()->setRenderBackend(nullptr);
m_backend->setRenderBackend(nullptr);
}
bool EglGbmBackend::initializeEgl()
......@@ -331,9 +332,14 @@ EGLConfig EglGbmBackend::config(uint32_t format) const
return m_configs[format];
}
QSharedPointer<DrmLayer> EglGbmBackend::createLayer(DrmDisplayDevice *displayDevice) const
QSharedPointer<DrmLayer> EglGbmBackend::createLayer(DrmDisplayDevice *displayDevice)
{
return QSharedPointer<EglGbmLayer>::create(m_backend->primaryGpu(), displayDevice);
return QSharedPointer<EglGbmLayer>::create(this, displayDevice);
}
DrmGpu *EglGbmBackend::gpu() const
{
return m_backend->primaryGpu();
}
bool operator==(const GbmFormat &lhs, const GbmFormat &rhs)
......
......@@ -67,7 +67,7 @@ public:
void init() override;
bool scanout(AbstractOutput *output, SurfaceItem *surfaceItem) override;
bool prefer10bpc() const override;
QSharedPointer<DrmLayer> createLayer(DrmDisplayDevice *displayDevice) const override;
QSharedPointer<DrmLayer> createLayer(DrmDisplayDevice *displayDevice) override;
QSharedPointer<GLTexture> textureForOutput(AbstractOutput *requestedOutput) const override;
......@@ -75,6 +75,10 @@ public:
EGLConfig config(uint32_t format) const;
GbmFormat gbmFormatForDrmFormat(uint32_t format) const;
std::optional<uint32_t> chooseFormat(DrmDisplayDevice *displyDevice) const;
DrmGpu *gpu() const;
Q_SIGNALS:
void aboutToBeDestroyed();
protected:
void aboutToStartPainting(AbstractOutput *output, const QRegion &damage) override;
......
......@@ -19,6 +19,7 @@
#include "egl_dmabuf.h"
#include "surfaceitem_wayland.h"
#include "kwineglimagetexture.h"
#include "drm_backend.h"
#include "KWaylandServer/surface_interface.h"
#include "KWaylandServer/linuxdmabufv1clientbuffer.h"
......@@ -32,20 +33,31 @@
namespace KWin
{
EglGbmLayer::EglGbmLayer(DrmGpu *renderGpu, DrmDisplayDevice *displayDevice)
: m_displayDevice(displayDevice)
, m_renderGpu(renderGpu)
EglGbmLayer::EglGbmLayer(EglGbmBackend *eglBackend, DrmDisplayDevice *displayDevice)
: DrmLayer(displayDevice)
, m_eglBackend(eglBackend)
{
connect(eglBackend, &EglGbmBackend::aboutToBeDestroyed, this, &EglGbmLayer::destroyResources);
}
EglGbmLayer::~EglGbmLayer()
{
if (m_gbmSurface && m_shadowBuffer && m_gbmSurface->makeContextCurrent()) {
m_shadowBuffer.reset();
}
if (m_oldGbmSurface && m_oldShadowBuffer && m_oldGbmSurface->makeContextCurrent()) {
m_oldShadowBuffer.reset();
destroyResources();
}
void EglGbmLayer::destroyResources()
{
if (m_shadowBuffer || m_oldShadowBuffer) {
if (m_gbmSurface) {
m_gbmSurface->makeContextCurrent();
} else if (m_oldGbmSurface) {
m_oldGbmSurface->makeContextCurrent();
}
}
m_shadowBuffer.reset();
m_oldShadowBuffer.reset();
m_gbmSurface.reset();
m_oldGbmSurface.reset();
}
std::optional<QRegion> EglGbmLayer::startRendering()
......@@ -87,7 +99,7 @@ std::optional<QRegion> EglGbmLayer::startRendering()
m_shadowBuffer = m_oldShadowBuffer;
} else {
if (m_displayDevice->softwareTransforms() != DrmPlane::Transformations(DrmPlane::Transformation::Rotate0)) {
const auto format = m_renderGpu->eglBackend()->gbmFormatForDrmFormat(m_gbmSurface->format());
const auto format = m_eglBackend->gbmFormatForDrmFormat(m_gbmSurface->format());
m_shadowBuffer = QSharedPointer<ShadowBuffer>::create(m_displayDevice->sourceSize(), format);
if (!m_shadowBuffer->isComplete()) {
return std::optional<QRegion>();
......@@ -164,37 +176,37 @@ bool EglGbmLayer::createGbmSurface()
static bool modifiersEnvSet = false;
static const bool modifiersEnv = qEnvironmentVariableIntValue("KWIN_DRM_USE_MODIFIERS", &modifiersEnvSet) != 0;
auto format = m_renderGpu->eglBackend()->chooseFormat(m_displayDevice);
auto format = m_eglBackend->chooseFormat(m_displayDevice);
if (!format || m_importMode == MultiGpuImportMode::DumbBufferXrgb8888) {
format = DRM_FORMAT_XRGB8888;
}
const auto modifiers = m_displayDevice->supportedModifiers(format.value());
const auto size = m_displayDevice->bufferSize();
const auto config = m_renderGpu->eglBackend()->config(format.value());
const bool allowModifiers = m_renderGpu->addFB2ModifiersSupported() && m_displayDevice->gpu()->addFB2ModifiersSupported()
&& ((m_renderGpu->isNVidia() && !modifiersEnvSet) || (modifiersEnvSet && modifiersEnv));
const auto config = m_eglBackend->config(format.value());
const bool allowModifiers = m_eglBackend->gpu()->addFB2ModifiersSupported() && m_displayDevice->gpu()->addFB2ModifiersSupported()
&& ((m_eglBackend->gpu()->isNVidia() && !modifiersEnvSet) || (modifiersEnvSet && modifiersEnv));
QSharedPointer<GbmSurface> gbmSurface;
#if HAVE_GBM_BO_GET_FD_FOR_PLANE
if (!allowModifiers) {
#else
// modifiers have to be disabled with multi-gpu if gbm_bo_get_fd_for_plane is not available
if (!allowModifiers || m_displayDevice->gpu() != m_renderGpu) {
if (!allowModifiers || m_displayDevice->gpu() != m_eglBackend->gpu()) {
#endif
int flags = GBM_BO_USE_RENDERING;
if (m_displayDevice->gpu() == m_renderGpu) {
if (m_displayDevice->gpu() == m_eglBackend->gpu()) {
flags |= GBM_BO_USE_SCANOUT;
} else {
flags |= GBM_BO_USE_LINEAR;
}
gbmSurface = QSharedPointer<GbmSurface>::create(m_renderGpu, size, format.value(), flags, config);
gbmSurface = QSharedPointer<GbmSurface>::create(m_eglBackend->gpu(), size, format.value(), flags, config);
} else {
gbmSurface = QSharedPointer<GbmSurface>::create(m_renderGpu, size, format.value(), modifiers, config);
gbmSurface = QSharedPointer<GbmSurface>::create(m_eglBackend->gpu(), size, format.value(), modifiers, config);
if (!gbmSurface->isValid()) {
// the egl / gbm implementation may reject the modifier list from another gpu
// as a fallback use linear, to at least make CPU copy more efficient
const QVector<uint64_t> linear = {DRM_FORMAT_MOD_LINEAR};
gbmSurface = QSharedPointer<GbmSurface>::create(m_renderGpu, size, format.value(), linear, config);
gbmSurface = QSharedPointer<GbmSurface>::create(m_eglBackend->gpu(), size, format.value(), linear, config);
}
}
if (!gbmSurface->isValid()) {
......@@ -237,12 +249,12 @@ QSharedPointer<GLTexture> EglGbmLayer::texture() const
qCWarning(KWIN_DRM) << "Failed to record frame: No gbm buffer!";
return nullptr;
}
EGLImageKHR image = eglCreateImageKHR(m_renderGpu->eglDisplay(), nullptr, EGL_NATIVE_PIXMAP_KHR, gbmBuffer->getBo(), nullptr);
EGLImageKHR image = eglCreateImageKHR(m_eglBackend->eglDisplay(), nullptr, EGL_NATIVE_PIXMAP_KHR, gbmBuffer->getBo(), nullptr);
if (image == EGL_NO_IMAGE_KHR) {
qCWarning(KWIN_DRM) << "Failed to record frame: Error creating EGLImageKHR - " << glGetError();
return nullptr;
}
return QSharedPointer<EGLImageTexture>::create(m_renderGpu->eglDisplay(), image, GL_RGBA8, m_displayDevice->sourceSize());
return QSharedPointer<EGLImageTexture>::create(m_eglBackend->eglDisplay(), image, GL_RGBA8, m_displayDevice->sourceSize());
}
QSharedPointer<DrmBuffer> EglGbmLayer::importBuffer()
......@@ -455,7 +467,7 @@ void EglGbmLayer::sendDmabufFeedback(KWaylandServer::LinuxDmaBufV1ClientBuffer *
if (const auto &drmOutput = dynamic_cast<DrmOutput *>(m_displayDevice); drmOutput && m_scanoutCandidate.surface->dmabufFeedbackV1()) {
QVector<KWaylandServer::LinuxDmaBufV1Feedback::Tranche> scanoutTranches;
const auto &drmFormats = drmOutput->pipeline()->supportedFormats();
const auto tranches = m_renderGpu->eglBackend()->dmabuf()->tranches();
const auto tranches = m_eglBackend->dmabuf()->tranches();
for (const auto &tranche : tranches) {
KWaylandServer::LinuxDmaBufV1Feedback::Tranche scanoutTranche;
for (auto it = tranche.formatTable.constBegin(); it != tranche.formatTable.constEnd(); it++) {
......@@ -483,11 +495,6 @@ QSharedPointer<DrmBuffer> EglGbmLayer::currentBuffer() const
return m_scanoutBuffer ? m_scanoutBuffer : m_currentBuffer;
}
DrmDisplayDevice *EglGbmLayer::displayDevice() const
{
return m_displayDevice;
}
int EglGbmLayer::bufferAge() const
{
return m_gbmSurface ? m_gbmSurface->bufferAge() : 0;
......
......@@ -32,11 +32,12 @@ class DrmBuffer;
class DrmGpu;
class SurfaceItem;
class GLTexture;
class EglGbmBackend;
class EglGbmLayer : public DrmLayer
{
public:
EglGbmLayer(DrmGpu *renderGpu, DrmDisplayDevice *displayDevice);
EglGbmLayer(EglGbmBackend *eglBackend, DrmDisplayDevice *displayDevice);
~EglGbmLayer();
std::optional<QRegion> startRendering() override;
......@@ -48,7 +49,6 @@ public:
QRegion currentDamage() const override;
QSharedPointer<GLTexture> texture() const;
DrmDisplayDevice *displayDevice() const override;
int bufferAge() const;
EGLSurface eglSurface() const;
......@@ -59,6 +59,7 @@ private:
bool doesSwapchainFit(DumbSwapchain *swapchain) const;
void sendDmabufFeedback(KWaylandServer::LinuxDmaBufV1ClientBuffer *failedBuffer);
bool renderTestBuffer();
void destroyResources();
QSharedPointer<DrmBuffer> importBuffer();
QSharedPointer<DrmBuffer> importDmabuf();
......@@ -88,8 +89,7 @@ private:
QSharedPointer<DumbSwapchain> m_importSwapchain;
QSharedPointer<DumbSwapchain> m_oldImportSwapchain;
DrmDisplayDevice *const m_displayDevice;
DrmGpu *const m_renderGpu;
EglGbmBackend *const m_eglBackend;
};
}
......@@ -16,13 +16,14 @@
#include "logging.h"
#include "kwineglutils_p.h"
#include "kwinglplatform.h"
#include "drm_backend.h"
namespace KWin
{
GbmSurface::GbmSurface(DrmGpu *gpu, const QSize &size, uint32_t format, uint32_t flags, EGLConfig config)
: m_surface(gbm_surface_create(gpu->gbmDevice(), size.width(), size.height(), format, flags))
, m_gpu(gpu)
, m_eglBackend(static_cast<EglGbmBackend*>(gpu->platform()->renderBackend()))
, m_size(size)
, m_format(format)
, m_renderTarget(new GLRenderTarget(0, size))
......@@ -31,7 +32,7 @@ GbmSurface::GbmSurface(DrmGpu *gpu, const QSize &size, uint32_t format, uint32_t
qCCritical(KWIN_DRM) << "Could not create gbm surface!" << strerror(errno);
return;
}
m_eglSurface = eglCreatePlatformWindowSurfaceEXT(m_gpu->eglDisplay(), config, m_surface, nullptr);
m_eglSurface = eglCreatePlatformWindowSurfaceEXT(m_eglBackend->eglDisplay(), config, m_surface, nullptr);
if (m_eglSurface == EGL_NO_SURFACE) {
qCCritical(KWIN_DRM) << "Creating EGL surface failed!" << getEglErrorString();
}
......@@ -39,7 +40,7 @@ GbmSurface::GbmSurface(DrmGpu *gpu, const QSize &size, uint32_t format, uint32_t
GbmSurface::GbmSurface(DrmGpu *gpu, const QSize &size, uint32_t format, QVector<uint64_t> modifiers, EGLConfig config)
: m_surface(gbm_surface_create_with_modifiers(gpu->gbmDevice(), size.width(), size.height(), format, modifiers.isEmpty() ? nullptr : modifiers.constData(), modifiers.count()))
, m_gpu(gpu)
, m_eglBackend(static_cast<EglGbmBackend*>(gpu->platform()->renderBackend()))
, m_size(size)
, m_format(format)
, m_modifiers(modifiers)
......@@ -49,7 +50,7 @@ GbmSurface::GbmSurface(DrmGpu *gpu, const QSize &size, uint32_t format, QVector<
qCCritical(KWIN_DRM) << "Could not create gbm surface!" << strerror(errno);
return;
}
m_eglSurface = eglCreatePlatformWindowSurfaceEXT(m_gpu->eglDisplay(), config, m_surface, nullptr);
m_eglSurface = eglCreatePlatformWindowSurfaceEXT(m_eglBackend->eglDisplay(), config, m_surface, nullptr);
if (m_eglSurface == EGL_NO_SURFACE) {
qCCritical(KWIN_DRM) << "Creating EGL surface failed!" << getEglErrorString();
}
......@@ -62,7 +63,7 @@ GbmSurface::~GbmSurface()
buffer->releaseBuffer();
}
if (m_eglSurface != EGL_NO_SURFACE) {
eglDestroySurface(m_gpu->eglDisplay(), m_eglSurface);
eglDestroySurface(m_eglBackend->eglDisplay(), m_eglSurface);
}