{core,backends/wayland}: Refactor gbm buffer allocator

This commit is contained in:
Vlad Zahorodnii 2023-04-12 16:59:42 +03:00
parent 3ac4f8a7dc
commit 103d8d8abe
7 changed files with 252 additions and 48 deletions

View file

@ -42,7 +42,9 @@ target_sources(kwin PRIVATE
core/colorlut.cpp
core/colorpipelinestage.cpp
core/colortransformation.cpp
core/gbmgraphicsbufferallocator.cpp
core/graphicsbuffer.cpp
core/graphicsbufferallocator.cpp
core/inputbackend.cpp
core/inputdevice.cpp
core/output.cpp

View file

@ -9,7 +9,7 @@
*/
#include "wayland_egl_backend.h"
#include "../drm/gbm_dmabuf.h"
#include "core/gbmgraphicsbufferallocator.h"
#include "platformsupport/scenes/opengl/basiceglsurfacetexture_internal.h"
#include "platformsupport/scenes/opengl/basiceglsurfacetexture_wayland.h"
@ -44,34 +44,10 @@ namespace KWin
namespace Wayland
{
WaylandEglLayerBuffer::WaylandEglLayerBuffer(const QSize &size, uint32_t format, const QVector<uint64_t> &modifiers, WaylandEglBackend *backend)
: m_backend(backend)
WaylandEglLayerBuffer::WaylandEglLayerBuffer(GbmGraphicsBuffer *buffer, WaylandEglBackend *backend)
: m_graphicsBuffer(buffer)
{
gbm_device *gbmDevice = backend->backend()->gbmDevice();
if (!modifiers.isEmpty()) {
m_bo = gbm_bo_create_with_modifiers(gbmDevice,
size.width(),
size.height(),
format,
modifiers.constData(),
modifiers.size());
}
if (!m_bo) {
m_bo = gbm_bo_create(gbmDevice,
size.width(),
size.height(),
format,
GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
}
if (!m_bo) {
qCCritical(KWIN_WAYLAND_BACKEND) << "Failed to allocate a buffer for an output layer";
return;
}
DmaBufAttributes attributes = dmaBufAttributesForBo(m_bo);
const DmaBufAttributes &attributes = buffer->dmabufAttributes();
zwp_linux_buffer_params_v1 *params = zwp_linux_dmabuf_v1_create_params(backend->backend()->display()->linuxDmabuf()->handle());
for (int i = 0; i < attributes.planeCount; ++i) {
@ -84,10 +60,10 @@ WaylandEglLayerBuffer::WaylandEglLayerBuffer(const QSize &size, uint32_t format,
attributes.modifier & 0xffffffff);
}
m_buffer = zwp_linux_buffer_params_v1_create_immed(params, size.width(), size.height(), format, 0);
m_buffer = zwp_linux_buffer_params_v1_create_immed(params, attributes.width, attributes.height, attributes.format, 0);
zwp_linux_buffer_params_v1_destroy(params);
m_texture = backend->importDmaBufAsTexture(std::move(attributes));
m_texture = backend->importDmaBufAsTexture(attributes);
m_framebuffer = std::make_unique<GLFramebuffer>(m_texture.get());
}
@ -96,12 +72,13 @@ WaylandEglLayerBuffer::~WaylandEglLayerBuffer()
m_texture.reset();
m_framebuffer.reset();
if (m_buffer) {
wl_buffer_destroy(m_buffer);
}
if (m_bo) {
gbm_bo_destroy(m_bo);
}
wl_buffer_destroy(m_buffer);
m_graphicsBuffer->drop();
}
GbmGraphicsBuffer *WaylandEglLayerBuffer::graphicsBuffer() const
{
return m_graphicsBuffer;
}
wl_buffer *WaylandEglLayerBuffer::buffer() const
@ -124,17 +101,19 @@ int WaylandEglLayerBuffer::age() const
return m_age;
}
gbm_bo *WaylandEglLayerBuffer::bo() const
{
return m_bo;
}
WaylandEglLayerSwapchain::WaylandEglLayerSwapchain(const QSize &size, uint32_t format, const QVector<uint64_t> &modifiers, WaylandEglBackend *backend)
: m_backend(backend)
, m_size(size)
{
GbmGraphicsBufferAllocator allocator(backend->backend()->gbmDevice());
for (int i = 0; i < 2; ++i) {
m_buffers.append(std::make_shared<WaylandEglLayerBuffer>(size, format, modifiers, backend));
GbmGraphicsBuffer *buffer = allocator.allocate(size, format, modifiers);
if (!buffer) {
qCWarning(KWIN_WAYLAND_BACKEND) << "Failed to allocate layer swapchain buffer";
continue;
}
m_buffers.append(std::make_shared<WaylandEglLayerBuffer>(buffer, backend));
}
}
@ -290,12 +269,12 @@ bool WaylandEglCursorLayer::endFrame(const QRegion &renderedRegion, const QRegio
quint32 WaylandEglCursorLayer::format() const
{
return gbm_bo_get_format(m_buffer->bo());
return m_buffer->graphicsBuffer()->dmabufAttributes().format;
}
quint32 WaylandEglPrimaryLayer::format() const
{
return gbm_bo_get_format(m_buffer->bo());
return m_buffer->graphicsBuffer()->dmabufAttributes().format;
}
WaylandEglBackend::WaylandEglBackend(WaylandBackend *b)

View file

@ -25,6 +25,7 @@ struct gbm_bo;
namespace KWin
{
class GLFramebuffer;
class GbmGraphicsBuffer;
namespace Wayland
{
@ -35,19 +36,18 @@ class WaylandEglBackend;
class WaylandEglLayerBuffer
{
public:
WaylandEglLayerBuffer(const QSize &size, uint32_t format, const QVector<uint64_t> &modifiers, WaylandEglBackend *backend);
WaylandEglLayerBuffer(GbmGraphicsBuffer *buffer, WaylandEglBackend *backend);
~WaylandEglLayerBuffer();
GbmGraphicsBuffer *graphicsBuffer() const;
wl_buffer *buffer() const;
GLFramebuffer *framebuffer() const;
std::shared_ptr<GLTexture> texture() const;
int age() const;
gbm_bo *bo() const;
private:
WaylandEglBackend *m_backend;
GbmGraphicsBuffer *m_graphicsBuffer;
wl_buffer *m_buffer = nullptr;
gbm_bo *m_bo = nullptr;
std::unique_ptr<GLFramebuffer> m_framebuffer;
std::shared_ptr<GLTexture> m_texture;
int m_age = 0;

View file

@ -0,0 +1,123 @@
/*
SPDX-FileCopyrightText: 2023 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "core/gbmgraphicsbufferallocator.h"
#include "backends/drm/gbm_dmabuf.h" // FIXME: move dmaBufAttributesForBo() elsewhere
#include <drm_fourcc.h>
#include <gbm.h>
namespace KWin
{
GbmGraphicsBufferAllocator::GbmGraphicsBufferAllocator(gbm_device *device)
: m_gbmDevice(device)
{
}
GbmGraphicsBufferAllocator::~GbmGraphicsBufferAllocator()
{
}
GbmGraphicsBuffer *GbmGraphicsBufferAllocator::allocate(const QSize &size, uint32_t format, const QVector<uint64_t> &modifiers)
{
gbm_bo *bo = nullptr;
if (!modifiers.isEmpty() && !(modifiers.size() == 1 && modifiers.first() == DRM_FORMAT_MOD_INVALID)) {
bo = gbm_bo_create_with_modifiers(m_gbmDevice,
size.width(),
size.height(),
format,
modifiers.constData(),
modifiers.size());
}
if (!bo) {
bo = gbm_bo_create(m_gbmDevice,
size.width(),
size.height(),
format,
GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
}
if (!bo) {
return nullptr;
}
return new GbmGraphicsBuffer(bo, size, format);
}
static bool alphaChannelFromDrmFormat(uint32_t drmFormat)
{
switch (drmFormat) {
case DRM_FORMAT_ARGB4444:
case DRM_FORMAT_ABGR4444:
case DRM_FORMAT_RGBA4444:
case DRM_FORMAT_BGRA4444:
case DRM_FORMAT_ARGB1555:
case DRM_FORMAT_ABGR1555:
case DRM_FORMAT_RGBA5551:
case DRM_FORMAT_BGRA5551:
case DRM_FORMAT_ARGB8888:
case DRM_FORMAT_ABGR8888:
case DRM_FORMAT_RGBA8888:
case DRM_FORMAT_BGRA8888:
case DRM_FORMAT_ARGB2101010:
case DRM_FORMAT_ABGR2101010:
case DRM_FORMAT_RGBA1010102:
case DRM_FORMAT_BGRA1010102:
case DRM_FORMAT_XRGB8888_A8:
case DRM_FORMAT_XBGR8888_A8:
case DRM_FORMAT_RGBX8888_A8:
case DRM_FORMAT_BGRX8888_A8:
case DRM_FORMAT_RGB888_A8:
case DRM_FORMAT_BGR888_A8:
case DRM_FORMAT_RGB565_A8:
case DRM_FORMAT_BGR565_A8:
return true;
default:
return false;
}
}
GbmGraphicsBuffer::GbmGraphicsBuffer(gbm_bo *handle, const QSize &size, uint32_t format)
: m_bo(handle)
, m_dmabufAttributes(dmaBufAttributesForBo(handle))
, m_size(size)
, m_hasAlphaChannel(alphaChannelFromDrmFormat(format))
{
}
GbmGraphicsBuffer::~GbmGraphicsBuffer()
{
gbm_bo_destroy(m_bo);
}
QSize GbmGraphicsBuffer::size() const
{
return m_size;
}
bool GbmGraphicsBuffer::hasAlphaChannel() const
{
return m_hasAlphaChannel;
}
GraphicsBuffer::Origin GbmGraphicsBuffer::origin() const
{
return Origin::TopLeft;
}
const DmaBufAttributes &GbmGraphicsBuffer::dmabufAttributes() const
{
return m_dmabufAttributes;
}
} // namespace KWin

View file

@ -0,0 +1,52 @@
/*
SPDX-FileCopyrightText: 2023 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "core/dmabufattributes.h"
#include "core/graphicsbuffer.h"
#include "core/graphicsbufferallocator.h"
struct gbm_bo;
struct gbm_device;
namespace KWin
{
class KWIN_EXPORT GbmGraphicsBuffer : public GraphicsBuffer
{
Q_OBJECT
public:
GbmGraphicsBuffer(gbm_bo *handle, const QSize &size, uint32_t format);
~GbmGraphicsBuffer() override;
QSize size() const override;
bool hasAlphaChannel() const override;
Origin origin() const override;
const DmaBufAttributes &dmabufAttributes() const;
private:
gbm_bo *m_bo;
DmaBufAttributes m_dmabufAttributes;
QSize m_size;
bool m_hasAlphaChannel;
};
class KWIN_EXPORT GbmGraphicsBufferAllocator : public GraphicsBufferAllocator
{
public:
explicit GbmGraphicsBufferAllocator(gbm_device *device);
~GbmGraphicsBufferAllocator() override;
GbmGraphicsBuffer *allocate(const QSize &size, uint32_t format, const QVector<uint64_t> &modifiers = {}) override;
private:
gbm_device *m_gbmDevice;
};
} // namespace KWin

View file

@ -0,0 +1,20 @@
/*
SPDX-FileCopyrightText: 2023 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "core/graphicsbufferallocator.h"
namespace KWin
{
GraphicsBufferAllocator::GraphicsBufferAllocator()
{
}
GraphicsBufferAllocator::~GraphicsBufferAllocator()
{
}
} // namespace KWin

View file

@ -0,0 +1,28 @@
/*
SPDX-FileCopyrightText: 2023 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "kwin_export.h"
#include <QSize>
#include <QVector>
namespace KWin
{
class GraphicsBuffer;
class KWIN_EXPORT GraphicsBufferAllocator
{
public:
GraphicsBufferAllocator();
virtual ~GraphicsBufferAllocator();
virtual GraphicsBuffer *allocate(const QSize &size, uint32_t format, const QVector<uint64_t> &modifiers = {}) = 0;
};
} // namespace KWin