backends/drm: fix layer destruction
Layers need to release their resources whenever the render backend gets replaced.
This commit is contained in:
parent
a04bdf2355
commit
b530a5b66d
20 changed files with 172 additions and 91 deletions
|
@ -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;
|
||||
|
|
28
src/backends/drm/drm_layer.cpp
Normal file
28
src/backends/drm/drm_layer.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
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);
|
||||
}
|
||||
if (m_surface) {
|
||||
gbm_surface_destroy(m_surface);
|
||||
|
@ -71,7 +72,7 @@ GbmSurface::~GbmSurface()
|
|||
|
||||
bool GbmSurface::makeContextCurrent() const
|
||||
{
|
||||
if (eglMakeCurrent(m_gpu->eglDisplay(), m_eglSurface, m_eglSurface, m_gpu->eglBackend()->context()) == EGL_FALSE) {
|
||||
if (eglMakeCurrent(m_eglBackend->eglDisplay(), m_eglSurface, m_eglSurface, m_eglBackend->context()) == EGL_FALSE) {
|
||||
qCCritical(KWIN_DRM) << "eglMakeCurrent failed:" << getEglErrorString();
|
||||
return false;
|
||||
}
|
||||
|
@ -83,7 +84,7 @@ bool GbmSurface::makeContextCurrent() const
|
|||
|
||||
QSharedPointer<DrmGbmBuffer> GbmSurface::swapBuffersForDrm(const QRegion &dirty)
|
||||
{
|
||||
auto error = eglSwapBuffers(m_gpu->eglDisplay(), m_eglSurface);
|
||||
auto error = eglSwapBuffers(m_eglBackend->eglDisplay(), m_eglSurface);
|
||||
if (error != EGL_TRUE) {
|
||||
qCCritical(KWIN_DRM) << "an error occurred while swapping buffers" << getEglErrorString();
|
||||
return nullptr;
|
||||
|
@ -92,15 +93,15 @@ QSharedPointer<DrmGbmBuffer> GbmSurface::swapBuffersForDrm(const QRegion &dirty)
|
|||
if (!bo) {
|
||||
return nullptr;
|
||||
}
|
||||
auto buffer = QSharedPointer<DrmGbmBuffer>::create(m_gpu, this, bo);
|
||||
auto buffer = QSharedPointer<DrmGbmBuffer>::create(m_eglBackend->gpu(), this, bo);
|
||||
m_currentBuffer = buffer;
|
||||
m_lockedBuffers << m_currentBuffer.get();
|
||||
if (!buffer->bufferId()) {
|
||||
return nullptr;
|
||||
}
|
||||
m_currentDrmBuffer = buffer;
|
||||
if (m_gpu->eglBackend()->supportsBufferAge()) {
|
||||
eglQuerySurface(m_gpu->eglDisplay(), m_eglSurface, EGL_BUFFER_AGE_EXT, &m_bufferAge);
|
||||
if (m_eglBackend->supportsBufferAge()) {
|
||||
eglQuerySurface(m_eglBackend->eglDisplay(), m_eglSurface, EGL_BUFFER_AGE_EXT, &m_bufferAge);
|
||||
m_damageJournal.add(dirty);
|
||||
}
|
||||
return buffer;
|
||||
|
@ -108,7 +109,7 @@ QSharedPointer<DrmGbmBuffer> GbmSurface::swapBuffersForDrm(const QRegion &dirty)
|
|||
|
||||
QSharedPointer<GbmBuffer> GbmSurface::swapBuffers(const QRegion &dirty)
|
||||
{
|
||||
auto error = eglSwapBuffers(m_gpu->eglDisplay(), m_eglSurface);
|
||||
auto error = eglSwapBuffers(m_eglBackend->eglDisplay(), m_eglSurface);
|
||||
if (error != EGL_TRUE) {
|
||||
qCCritical(KWIN_DRM) << "an error occurred while swapping buffers" << getEglErrorString();
|
||||
return nullptr;
|
||||
|
@ -119,8 +120,8 @@ QSharedPointer<GbmBuffer> GbmSurface::swapBuffers(const QRegion &dirty)
|
|||
}
|
||||
m_currentBuffer = QSharedPointer<GbmBuffer>::create(this, bo);
|
||||
m_lockedBuffers << m_currentBuffer.get();
|
||||
if (m_gpu->eglBackend()->supportsBufferAge()) {
|
||||
eglQuerySurface(m_gpu->eglDisplay(), m_eglSurface, EGL_BUFFER_AGE_EXT, &m_bufferAge);
|
||||
if (m_eglBackend->supportsBufferAge()) {
|
||||
eglQuerySurface(m_eglBackend->eglDisplay(), m_eglSurface, EGL_BUFFER_AGE_EXT, &m_bufferAge);
|
||||
m_damageJournal.add(dirty);
|
||||
}
|
||||
return m_currentBuffer;
|
||||
|
@ -179,7 +180,7 @@ int GbmSurface::bufferAge() const
|
|||
|
||||
QRegion GbmSurface::repaintRegion(const QRect &geometry) const
|
||||
{
|
||||
if (m_gpu->eglBackend()->supportsBufferAge()) {
|
||||
if (m_eglBackend->supportsBufferAge()) {
|
||||
return m_damageJournal.accumulate(m_bufferAge, geometry);
|
||||
} else {
|
||||
return geometry;
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace KWin
|
|||
{
|
||||
|
||||
class GLRenderTarget;
|
||||
class EglGbmBackend;
|
||||
|
||||
class GbmSurface
|
||||
{
|
||||
|
@ -52,7 +53,7 @@ public:
|
|||
|
||||
private:
|
||||
gbm_surface *m_surface;
|
||||
DrmGpu *m_gpu;
|
||||
EglGbmBackend *const m_eglBackend;
|
||||
EGLSurface m_eglSurface = EGL_NO_SURFACE;
|
||||
QSize m_size;
|
||||
const uint32_t m_format;
|
||||
|
|
|
@ -23,12 +23,12 @@ DrmQPainterBackend::DrmQPainterBackend(DrmBackend *backend)
|
|||
: QPainterBackend()
|
||||
, m_backend(backend)
|
||||
{
|
||||
m_backend->primaryGpu()->setRenderBackend(this);
|
||||
m_backend->setRenderBackend(this);
|
||||
}
|
||||
|
||||
DrmQPainterBackend::~DrmQPainterBackend()
|
||||
{
|
||||
m_backend->primaryGpu()->setRenderBackend(nullptr);
|
||||
m_backend->setRenderBackend(nullptr);
|
||||
}
|
||||
|
||||
QImage *DrmQPainterBackend::bufferForScreen(AbstractOutput *output)
|
||||
|
@ -51,7 +51,7 @@ void DrmQPainterBackend::endFrame(AbstractOutput *output, const QRegion &rendere
|
|||
static_cast<DrmAbstractOutput*>(output)->present();
|
||||
}
|
||||
|
||||
QSharedPointer<DrmLayer> DrmQPainterBackend::createLayer(DrmDisplayDevice *displayDevice) const
|
||||
QSharedPointer<DrmLayer> DrmQPainterBackend::createLayer(DrmDisplayDevice *displayDevice)
|
||||
{
|
||||
return QSharedPointer<DrmQPainterLayer>::create(displayDevice);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,10 @@ public:
|
|||
QImage *bufferForScreen(AbstractOutput *output) override;
|
||||
QRegion beginFrame(AbstractOutput *output) override;
|
||||
void endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) override;
|
||||
QSharedPointer<DrmLayer> createLayer(DrmDisplayDevice *displayDevice) const override;
|
||||
QSharedPointer<DrmLayer> createLayer(DrmDisplayDevice *displayDevice) override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void aboutToBeDestroyed();
|
||||
|
||||
private:
|
||||
DrmBackend *m_backend;
|
||||
|
|
Loading…
Reference in a new issue