core: Drop dmabuf texture creation api in OutputBackend

It never belonged in the OutputBackend, but we also didn't have a better
place when the relevant code had been added.

With the introduction of graphics buffer allocators, it's no longer the
case.
This commit is contained in:
Vlad Zahorodnii 2023-08-23 12:33:39 +03:00
parent 2c809305b0
commit dabf3038f0
14 changed files with 143 additions and 235 deletions

View file

@ -76,7 +76,6 @@ target_sources(kwin PRIVATE
decorations/decorationpalette.cpp
decorations/decorations_logging.cpp
decorations/settings.cpp
dmabuftexture.cpp
dpmsinputeventfilter.cpp
effectloader.cpp
effects.cpp

View file

@ -13,7 +13,6 @@
#include "backends/libinput/libinputbackend.h"
#include "core/outputconfiguration.h"
#include "core/session.h"
#include "dmabuftexture.h"
#include "drm_egl_backend.h"
#include "drm_gpu.h"
#include "drm_logging.h"
@ -22,7 +21,6 @@
#include "drm_qpainter_backend.h"
#include "drm_render_backend.h"
#include "drm_virtual_output.h"
#include "gbm_dmabuf.h"
#include "utils/udev.h"
// KF5
#include <KCoreAddons>
@ -350,53 +348,6 @@ void DrmBackend::removeVirtualOutput(Output *output)
Q_EMIT outputsQueried();
}
gbm_bo *DrmBackend::createBo(const QSize &size, quint32 format, const QVector<uint64_t> &modifiers)
{
const auto eglBackend = dynamic_cast<EglGbmBackend *>(m_renderBackend);
if (!eglBackend || !primaryGpu()->gbmDevice()) {
return nullptr;
}
return createGbmBo(primaryGpu()->gbmDevice(), size, format, modifiers);
}
std::optional<DmaBufParams> DrmBackend::testCreateDmaBuf(const QSize &size, quint32 format, const QVector<uint64_t> &modifiers)
{
gbm_bo *bo = createBo(size, format, modifiers);
if (!bo) {
return {};
}
auto ret = dmaBufParamsForBo(bo);
gbm_bo_destroy(bo);
return ret;
}
std::shared_ptr<DmaBufTexture> DrmBackend::createDmaBufTexture(const QSize &size, quint32 format, uint64_t modifier)
{
QVector<uint64_t> mods = {modifier};
gbm_bo *bo = createBo(size, format, mods);
if (!bo) {
return {};
}
// The bo will be kept around until the last fd is closed.
std::optional<DmaBufAttributes> attributes = dmaBufAttributesForBo(bo);
gbm_bo_destroy(bo);
if (!attributes.has_value()) {
return nullptr;
}
const auto eglBackend = static_cast<EglGbmBackend *>(m_renderBackend);
eglBackend->makeCurrent();
if (auto texture = eglBackend->importDmaBufAsTexture(attributes.value())) {
return std::make_shared<DmaBufTexture>(texture, std::move(attributes.value()));
} else {
return nullptr;
}
}
DrmGpu *DrmBackend::primaryGpu() const
{
return m_gpus.empty() ? nullptr : m_gpus.front().get();

View file

@ -21,8 +21,6 @@
#include <memory>
struct gbm_bo;
namespace KWin
{
@ -52,8 +50,6 @@ public:
std::unique_ptr<OpenGLBackend> createOpenGLBackend() override;
EglDisplay *sceneEglDisplayObject() const override;
std::optional<DmaBufParams> testCreateDmaBuf(const QSize &size, quint32 format, const QVector<uint64_t> &modifiers) override;
std::shared_ptr<DmaBufTexture> createDmaBufTexture(const QSize &size, quint32 format, const uint64_t modifier) override;
bool initialize() override;
Outputs outputs() const override;
@ -108,8 +104,6 @@ private:
std::vector<std::unique_ptr<DrmGpu>> m_gpus;
std::unique_ptr<DpmsInputEventFilter> m_dpmsFilter;
DrmRenderBackend *m_renderBackend = nullptr;
gbm_bo *createBo(const QSize &size, quint32 format, const QVector<uint64_t> &modifiers);
};
}

View file

@ -9,7 +9,6 @@
#include "config-kwin.h"
#include "core/graphicsbuffer.h"
#include "core/outputbackend.h"
#include <drm_fourcc.h>
#include <gbm.h>
@ -56,45 +55,4 @@ inline std::optional<DmaBufAttributes> dmaBufAttributesForBo(gbm_bo *bo)
return attributes;
}
inline DmaBufParams dmaBufParamsForBo(gbm_bo *bo)
{
DmaBufParams attributes;
attributes.planeCount = gbm_bo_get_plane_count(bo);
attributes.width = gbm_bo_get_width(bo);
attributes.height = gbm_bo_get_height(bo);
attributes.format = gbm_bo_get_format(bo);
attributes.modifier = gbm_bo_get_modifier(bo);
return attributes;
}
inline gbm_bo *createGbmBo(gbm_device *device, const QSize &size, quint32 format, const QVector<uint64_t> &modifiers)
{
gbm_bo *bo = nullptr;
if (modifiers.count() > 0 && !(modifiers.count() == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID)) {
#if HAVE_GBM_BO_CREATE_WITH_MODIFIERS2
bo = gbm_bo_create_with_modifiers2(device,
size.width(),
size.height(),
format,
modifiers.constData(), modifiers.count(),
GBM_BO_USE_RENDERING);
#else
bo = gbm_bo_create_with_modifiers(device,
size.width(),
size.height(),
format,
modifiers.constData(), modifiers.count());
#endif
}
if (!bo && (modifiers.isEmpty() || modifiers.contains(DRM_FORMAT_MOD_INVALID))) {
bo = gbm_bo_create(device,
size.width(),
size.height(),
format,
GBM_BO_USE_LINEAR);
}
return bo;
}
} // namespace KWin

View file

@ -8,7 +8,6 @@
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "wayland_backend.h"
#include "dmabuftexture.h"
#include "dpmsinputeventfilter.h"
#include "input.h"
#include "wayland_display.h"
@ -34,8 +33,6 @@
#include <unistd.h>
#include <wayland-client-core.h>
#include "../drm/gbm_dmabuf.h"
#include "wayland-linux-dmabuf-unstable-v1-client-protocol.h"
namespace KWin
@ -603,37 +600,6 @@ void WaylandBackend::removeVirtualOutput(Output *output)
}
}
std::optional<DmaBufParams> WaylandBackend::testCreateDmaBuf(const QSize &size, quint32 format, const QVector<uint64_t> &modifiers)
{
gbm_bo *bo = createGbmBo(m_gbmDevice, size, format, modifiers);
if (!bo) {
return {};
}
auto ret = dmaBufParamsForBo(bo);
gbm_bo_destroy(bo);
return ret;
}
std::shared_ptr<DmaBufTexture> WaylandBackend::createDmaBufTexture(const QSize &size, quint32 format, uint64_t modifier)
{
gbm_bo *bo = createGbmBo(m_gbmDevice, size, format, {modifier});
if (!bo) {
return {};
}
// The bo will be kept around until the last fd is closed.
std::optional<DmaBufAttributes> attributes = dmaBufAttributesForBo(bo);
gbm_bo_destroy(bo);
if (!attributes.has_value()) {
return nullptr;
}
m_eglBackend->makeCurrent();
return std::make_shared<DmaBufTexture>(m_eglBackend->importDmaBufAsTexture(attributes.value()), std::move(attributes.value()));
}
static wl_buffer *importDmaBufBuffer(WaylandDisplay *display, const DmaBufAttributes *attributes)
{
zwp_linux_buffer_params_v1 *params = zwp_linux_dmabuf_v1_create_params(display->linuxDmabuf()->handle());

View file

@ -26,7 +26,6 @@
struct wl_buffer;
struct wl_display;
struct gbm_device;
struct gbm_bo;
namespace KWayland
{
@ -243,9 +242,6 @@ public:
wl_buffer *importBuffer(GraphicsBuffer *graphicsBuffer);
std::optional<DmaBufParams> testCreateDmaBuf(const QSize &size, quint32 format, const QVector<uint64_t> &modifiers) override;
std::shared_ptr<DmaBufTexture> createDmaBufTexture(const QSize &size, quint32 format, uint64_t modifier) override;
gbm_device *gbmDevice() const
{
return m_gbmDevice;

View file

@ -9,7 +9,6 @@
#include "outputbackend.h"
#include "dmabuftexture.h"
#include "inputbackend.h"
#include "output.h"
#include "outputconfiguration.h"
@ -44,21 +43,6 @@ std::unique_ptr<QPainterBackend> OutputBackend::createQPainterBackend()
return nullptr;
}
std::optional<DmaBufParams> OutputBackend::testCreateDmaBuf(const QSize &size, quint32 format, const QVector<uint64_t> &modifiers)
{
return {};
}
std::shared_ptr<DmaBufTexture> OutputBackend::createDmaBufTexture(const QSize &size, quint32 format, uint64_t modifier)
{
return {};
}
std::shared_ptr<DmaBufTexture> OutputBackend::createDmaBufTexture(const DmaBufParams &attribs)
{
return createDmaBufTexture({attribs.width, attribs.height}, attribs.format, attribs.modifier);
}
bool OutputBackend::applyOutputChanges(const OutputConfiguration &config)
{
const auto availableOutputs = outputs();

View file

@ -22,22 +22,12 @@ namespace KWin
{
class Output;
class DmaBufTexture;
class InputBackend;
class OpenGLBackend;
class QPainterBackend;
class OutputConfiguration;
class EglDisplay;
struct DmaBufParams
{
int planeCount = 0;
int width = 0;
int height = 0;
uint32_t format = 0;
uint64_t modifier = 0;
};
class KWIN_EXPORT Outputs : public QVector<Output *>
{
public:
@ -60,9 +50,6 @@ public:
virtual std::unique_ptr<InputBackend> createInputBackend();
virtual std::unique_ptr<OpenGLBackend> createOpenGLBackend();
virtual std::unique_ptr<QPainterBackend> createQPainterBackend();
virtual std::optional<DmaBufParams> testCreateDmaBuf(const QSize &size, quint32 format, const QVector<uint64_t> &modifiers);
virtual std::shared_ptr<DmaBufTexture> createDmaBufTexture(const QSize &size, quint32 format, const uint64_t modifier);
std::shared_ptr<DmaBufTexture> createDmaBufTexture(const DmaBufParams &attributes);
virtual EglDisplay *sceneEglDisplayObject() const = 0;
/**

View file

@ -1,39 +0,0 @@
/*
SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "dmabuftexture.h"
#include "libkwineffects/kwinglutils.h"
#include <unistd.h>
namespace KWin
{
DmaBufTexture::DmaBufTexture(std::shared_ptr<GLTexture> texture, DmaBufAttributes &&attributes)
: m_texture(texture)
, m_framebuffer(std::make_unique<GLFramebuffer>(texture.get()))
, m_attributes(std::move(attributes))
{
}
DmaBufTexture::~DmaBufTexture() = default;
const DmaBufAttributes &DmaBufTexture::attributes() const
{
return m_attributes;
}
KWin::GLTexture *DmaBufTexture::texture() const
{
return m_texture.get();
}
KWin::GLFramebuffer *DmaBufTexture::framebuffer() const
{
return m_framebuffer.get();
}
} // namespace KWin

View file

@ -4,6 +4,7 @@ target_sources(screencast PRIVATE
outputscreencastsource.cpp
pipewirecore.cpp
regionscreencastsource.cpp
screencastdmabuftexture.cpp
screencastmanager.cpp
screencastsource.cpp
screencaststream.cpp

View file

@ -0,0 +1,42 @@
/*
SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "plugins/screencast/screencastdmabuftexture.h"
#include "core/graphicsbuffer.h"
#include "libkwineffects/kwinglutils.h"
namespace KWin
{
ScreenCastDmaBufTexture::ScreenCastDmaBufTexture(std::shared_ptr<GLTexture> texture, GraphicsBuffer *buffer)
: m_texture(texture)
, m_framebuffer(std::make_unique<GLFramebuffer>(texture.get()))
, m_buffer(buffer)
{
}
ScreenCastDmaBufTexture::~ScreenCastDmaBufTexture()
{
m_framebuffer.reset();
m_texture.reset();
m_buffer->drop();
}
GraphicsBuffer *ScreenCastDmaBufTexture::buffer() const
{
return m_buffer;
}
KWin::GLTexture *ScreenCastDmaBufTexture::texture() const
{
return m_texture.get();
}
KWin::GLFramebuffer *ScreenCastDmaBufTexture::framebuffer() const
{
return m_framebuffer.get();
}
} // namespace KWin

View file

@ -6,31 +6,28 @@
#pragma once
#include "kwin_export.h"
#include "core/graphicsbuffer.h"
#include <memory>
namespace KWin
{
class GLFramebuffer;
class GLTexture;
class GraphicsBuffer;
class KWIN_EXPORT DmaBufTexture
class ScreenCastDmaBufTexture
{
public:
explicit DmaBufTexture(std::shared_ptr<GLTexture> texture, DmaBufAttributes &&attributes);
virtual ~DmaBufTexture();
explicit ScreenCastDmaBufTexture(std::shared_ptr<GLTexture> texture, GraphicsBuffer *buffer);
virtual ~ScreenCastDmaBufTexture();
const DmaBufAttributes &attributes() const;
GraphicsBuffer *buffer() const;
GLTexture *texture() const;
GLFramebuffer *framebuffer() const;
protected:
std::shared_ptr<GLTexture> m_texture;
std::unique_ptr<GLFramebuffer> m_framebuffer;
DmaBufAttributes m_attributes;
GraphicsBuffer *m_buffer;
};
}

View file

@ -8,17 +8,20 @@
#include "screencaststream.h"
#include "composite.h"
#include "core/graphicsbufferallocator.h"
#include "core/outputbackend.h"
#include "core/renderbackend.h"
#include "cursor.h"
#include "dmabuftexture.h"
#include "kwinscreencast_logging.h"
#include "libkwineffects/kwingltexture.h"
#include "libkwineffects/kwinglutils.h"
#include "main.h"
#include "pipewirecore.h"
#include "platformsupport/scenes/opengl/abstract_egl_backend.h"
#include "platformsupport/scenes/opengl/eglnativefence.h"
#include "platformsupport/scenes/opengl/openglbackend.h"
#include "scene/workspacescene.h"
#include "screencastdmabuftexture.h"
#include "screencastsource.h"
#include <KLocalizedString>
@ -176,9 +179,9 @@ void ScreenCastStream::onStreamParamChanged(uint32_t id, const struct spa_pod *f
if (receivedModifiers.count() > 1) {
receivedModifiers.removeAll(DRM_FORMAT_MOD_INVALID);
}
m_dmabufParams = kwinApp()->outputBackend()->testCreateDmaBuf(m_resolution, m_drmFormat, receivedModifiers);
m_dmabufParams = testCreateDmaBuf(m_resolution, m_drmFormat, receivedModifiers);
} else {
m_dmabufParams = kwinApp()->outputBackend()->testCreateDmaBuf(m_resolution, m_drmFormat, {DRM_FORMAT_MOD_INVALID});
m_dmabufParams = testCreateDmaBuf(m_resolution, m_drmFormat, {DRM_FORMAT_MOD_INVALID});
}
// In case we fail to use any modifier from the list of offered ones, remove these
@ -213,21 +216,21 @@ void ScreenCastStream::onStreamAddBuffer(pw_buffer *buffer)
spa_data->mapoffset = 0;
spa_data->flags = SPA_DATA_FLAG_READWRITE;
std::shared_ptr<DmaBufTexture> dmabuff;
std::shared_ptr<ScreenCastDmaBufTexture> dmabuff;
if (spa_data[0].type != SPA_ID_INVALID && spa_data[0].type & (1 << SPA_DATA_DmaBuf)) {
Q_ASSERT(m_dmabufParams);
dmabuff = kwinApp()->outputBackend()->createDmaBufTexture(*m_dmabufParams);
dmabuff = createDmaBufTexture(*m_dmabufParams);
}
if (dmabuff) {
spa_data->maxsize = dmabuff->attributes().pitch[0] * m_resolution.height();
const DmaBufAttributes *dmabufAttribs = dmabuff->buffer()->dmabufAttributes();
spa_data->maxsize = dmabufAttribs->pitch[0] * m_resolution.height();
const DmaBufAttributes &dmabufAttribs = dmabuff->attributes();
Q_ASSERT(buffer->buffer->n_datas >= uint(dmabufAttribs.planeCount));
for (int i = 0; i < dmabufAttribs.planeCount; ++i) {
Q_ASSERT(buffer->buffer->n_datas >= uint(dmabufAttribs->planeCount));
for (int i = 0; i < dmabufAttribs->planeCount; ++i) {
buffer->buffer->datas[i].type = SPA_DATA_DmaBuf;
buffer->buffer->datas[i].fd = dmabufAttribs.fd[i].get();
buffer->buffer->datas[i].fd = dmabufAttribs->fd[i].get();
buffer->buffer->datas[i].data = nullptr;
}
m_dmabufDataForPwBuffer.insert(buffer, dmabuff);
@ -406,7 +409,7 @@ bool ScreenCastStream::createStream()
// Also support modifier-less DmaBufs
m_modifiers += DRM_FORMAT_MOD_INVALID;
}
m_hasDmaBuf = kwinApp()->outputBackend()->testCreateDmaBuf(m_resolution, m_drmFormat, {DRM_FORMAT_MOD_INVALID}).has_value();
m_hasDmaBuf = testCreateDmaBuf(m_resolution, m_drmFormat, {DRM_FORMAT_MOD_INVALID}).has_value();
char buffer[2048];
QVector<const spa_pod *> params = buildFormats(false, buffer);
@ -542,11 +545,11 @@ void ScreenCastStream::recordFrame(const QRegion &_damagedRegion)
auto &buf = m_dmabufDataForPwBuffer[buffer];
Q_ASSERT(buf);
const DmaBufAttributes &dmabufAttribs = buf->attributes();
Q_ASSERT(buffer->buffer->n_datas >= uint(dmabufAttribs.planeCount));
for (int i = 0; i < dmabufAttribs.planeCount; ++i) {
buffer->buffer->datas[i].chunk->stride = dmabufAttribs.pitch[i];
buffer->buffer->datas[i].chunk->offset = dmabufAttribs.offset[i];
const DmaBufAttributes *dmabufAttribs = buf->buffer()->dmabufAttributes();
Q_ASSERT(buffer->buffer->n_datas >= uint(dmabufAttribs->planeCount));
for (int i = 0; i < dmabufAttribs->planeCount; ++i) {
buffer->buffer->datas[i].chunk->stride = dmabufAttribs->pitch[i];
buffer->buffer->datas[i].chunk->offset = dmabufAttribs->offset[i];
}
spa_data->chunk->size = spa_data->maxsize;
@ -877,6 +880,65 @@ void ScreenCastStream::setCursorMode(KWaylandServer::ScreencastV1Interface::Curs
m_cursor.viewport = viewport;
}
std::optional<ScreenCastDmaBufTextureParams> ScreenCastStream::testCreateDmaBuf(const QSize &size, quint32 format, const QVector<uint64_t> &modifiers)
{
AbstractEglBackend *backend = dynamic_cast<AbstractEglBackend *>(Compositor::self()->backend());
if (!backend) {
return std::nullopt;
}
GraphicsBuffer *buffer = backend->graphicsBufferAllocator()->allocate(GraphicsBufferOptions{
.size = size,
.format = format,
.modifiers = modifiers,
});
if (!buffer) {
return std::nullopt;
}
auto drop = qScopeGuard([&buffer]() {
buffer->drop();
});
const DmaBufAttributes *attrs = buffer->dmabufAttributes();
if (!attrs) {
return std::nullopt;
}
return ScreenCastDmaBufTextureParams{
.planeCount = attrs->planeCount,
.width = attrs->width,
.height = attrs->height,
.format = attrs->format,
.modifier = attrs->modifier,
};
}
std::shared_ptr<ScreenCastDmaBufTexture> ScreenCastStream::createDmaBufTexture(const ScreenCastDmaBufTextureParams &params)
{
AbstractEglBackend *backend = dynamic_cast<AbstractEglBackend *>(Compositor::self()->backend());
if (!backend) {
return nullptr;
}
GraphicsBuffer *buffer = backend->graphicsBufferAllocator()->allocate(GraphicsBufferOptions{
.size = QSize(params.width, params.height),
.format = params.format,
.modifiers = {params.modifier},
});
if (!buffer) {
return nullptr;
}
const DmaBufAttributes *attrs = buffer->dmabufAttributes();
if (!attrs) {
buffer->drop();
return nullptr;
}
backend->makeCurrent();
return std::make_shared<ScreenCastDmaBufTexture>(backend->importDmaBufAsTexture(*attrs), buffer);
}
} // namespace KWin
#include "moc_screencaststream.cpp"

View file

@ -10,15 +10,12 @@
#include "config-kwin.h"
#include "core/outputbackend.h"
#include "dmabuftexture.h"
#include "libkwineffects/kwinglobals.h"
#include "wayland/screencast_v1_interface.h"
#include <QDateTime>
#include <QHash>
#include <QObject>
#include <QSize>
#include <QRegion>
#include <QSocketNotifier>
#include <QTimer>
#include <chrono>
@ -34,11 +31,21 @@ namespace KWin
{
class Cursor;
class ScreenCastDmaBufTexture;
class EGLNativeFence;
class GLTexture;
class PipeWireCore;
class ScreenCastSource;
struct ScreenCastDmaBufTextureParams
{
int planeCount = 0;
int width = 0;
int height = 0;
uint32_t format = 0;
uint64_t modifier = 0;
};
class KWIN_EXPORT ScreenCastStream : public QObject
{
Q_OBJECT
@ -94,6 +101,9 @@ private:
struct spa_fraction *defaultFramerate, struct spa_fraction *minFramerate, struct spa_fraction *maxFramerate,
const QVector<uint64_t> &modifiers, quint32 modifiersFlags);
std::optional<ScreenCastDmaBufTextureParams> testCreateDmaBuf(const QSize &size, quint32 format, const QVector<uint64_t> &modifiers);
std::shared_ptr<ScreenCastDmaBufTexture> createDmaBufTexture(const ScreenCastDmaBufTextureParams &params);
std::shared_ptr<PipeWireCore> m_pwCore;
std::unique_ptr<ScreenCastSource> m_source;
struct pw_stream *m_pwStream = nullptr;
@ -110,7 +120,7 @@ private:
spa_video_info_raw m_videoFormat;
QString m_error;
QVector<uint64_t> m_modifiers;
std::optional<DmaBufParams> m_dmabufParams; // when fixated
std::optional<ScreenCastDmaBufTextureParams> m_dmabufParams; // when fixated
struct
{
@ -125,7 +135,7 @@ private:
} m_cursor;
QRectF cursorGeometry(Cursor *cursor) const;
QHash<struct pw_buffer *, std::shared_ptr<DmaBufTexture>> m_dmabufDataForPwBuffer;
QHash<struct pw_buffer *, std::shared_ptr<ScreenCastDmaBufTexture>> m_dmabufDataForPwBuffer;
pw_buffer *m_pendingBuffer = nullptr;
std::unique_ptr<QSocketNotifier> m_pendingNotifier;