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

This commit is contained in:
Vlad Zahorodnii 2023-04-13 12:37:42 +03:00
parent 2288f39469
commit ce2b4c0bee
11 changed files with 364 additions and 186 deletions

View file

@ -58,6 +58,7 @@ target_sources(kwin PRIVATE
core/session_consolekit.cpp
core/session_logind.cpp
core/session_noop.cpp
core/shmgraphicsbufferallocator.cpp
cursor.cpp
cursordelegate_opengl.cpp
cursordelegate_qpainter.cpp

View file

@ -13,7 +13,6 @@
#include <KWayland/Client/registry.h>
#include <KWayland/Client/relativepointer.h>
#include <KWayland/Client/seat.h>
#include <KWayland/Client/shm_pool.h>
#include <KWayland/Client/subcompositor.h>
#include <KWayland/Client/xdgdecoration.h>
#include <KWayland/Client/xdgshell.h>
@ -202,10 +201,12 @@ WaylandDisplay::~WaylandDisplay()
m_relativePointerManager.reset();
m_seat.reset();
m_xdgDecorationManager.reset();
m_shmPool.reset();
m_xdgShell.reset();
m_linuxDmabuf.reset();
if (m_shm) {
wl_shm_destroy(m_shm);
}
if (m_registry) {
wl_registry_destroy(m_registry);
}
@ -267,9 +268,9 @@ KWayland::Client::RelativePointerManager *WaylandDisplay::relativePointerManager
return m_relativePointerManager.get();
}
KWayland::Client::ShmPool *WaylandDisplay::shmPool() const
wl_shm *WaylandDisplay::shm() const
{
return m_shmPool.get();
return m_shm;
}
KWayland::Client::Seat *WaylandDisplay::seat() const
@ -303,8 +304,7 @@ void WaylandDisplay::registry_global(void *data, wl_registry *registry, uint32_t
display->m_compositor = std::make_unique<KWayland::Client::Compositor>();
display->m_compositor->setup(static_cast<wl_compositor *>(wl_registry_bind(registry, name, &wl_compositor_interface, std::min(version, 4u))));
} else if (strcmp(interface, wl_shm_interface.name) == 0) {
display->m_shmPool = std::make_unique<KWayland::Client::ShmPool>();
display->m_shmPool->setup(static_cast<wl_shm *>(wl_registry_bind(registry, name, &wl_shm_interface, std::min(version, 1u))));
display->m_shm = static_cast<wl_shm *>(wl_registry_bind(registry, name, &wl_shm_interface, std::min(version, 1u)));
} else if (strcmp(interface, wl_seat_interface.name) == 0) {
display->m_seat = std::make_unique<KWayland::Client::Seat>();
display->m_seat->setup(static_cast<wl_seat *>(wl_registry_bind(registry, name, &wl_seat_interface, std::min(version, 2u))));

View file

@ -13,6 +13,7 @@
struct wl_display;
struct wl_registry;
struct wl_shm;
struct zwp_linux_dmabuf_v1;
namespace KWayland
@ -24,7 +25,6 @@ class PointerConstraints;
class PointerGestures;
class RelativePointerManager;
class Seat;
class ShmPool;
class XdgDecorationManager;
class XdgShell;
}
@ -71,7 +71,7 @@ public:
KWayland::Client::RelativePointerManager *relativePointerManager() const;
KWayland::Client::Seat *seat() const;
KWayland::Client::XdgDecorationManager *xdgDecorationManager() const;
KWayland::Client::ShmPool *shmPool() const;
wl_shm *shm() const;
KWayland::Client::XdgShell *xdgShell() const;
WaylandLinuxDmabufV1 *linuxDmabuf() const;
@ -84,6 +84,7 @@ private:
wl_display *m_display = nullptr;
wl_registry *m_registry = nullptr;
wl_shm *m_shm = nullptr;
std::unique_ptr<WaylandEventThread> m_eventThread;
std::unique_ptr<WaylandLinuxDmabufV1> m_linuxDmabuf;
std::unique_ptr<KWayland::Client::Compositor> m_compositor;
@ -92,7 +93,6 @@ private:
std::unique_ptr<KWayland::Client::RelativePointerManager> m_relativePointerManager;
std::unique_ptr<KWayland::Client::Seat> m_seat;
std::unique_ptr<KWayland::Client::XdgDecorationManager> m_xdgDecorationManager;
std::unique_ptr<KWayland::Client::ShmPool> m_shmPool;
std::unique_ptr<KWayland::Client::XdgShell> m_xdgShell;
};

View file

@ -8,106 +8,149 @@
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "wayland_qpainter_backend.h"
#include "core/shmgraphicsbufferallocator.h"
#include "wayland_backend.h"
#include "wayland_display.h"
#include "wayland_logging.h"
#include "wayland_output.h"
#include <KWayland/Client/buffer.h>
#include <KWayland/Client/shm_pool.h>
#include <KWayland/Client/surface.h>
#include <cmath>
#include <drm_fourcc.h>
#include <sys/mman.h>
#include <wayland-client-protocol.h>
namespace KWin
{
namespace Wayland
{
WaylandQPainterBufferSlot::WaylandQPainterBufferSlot(QSharedPointer<KWayland::Client::Buffer> buffer)
: buffer(buffer)
, image(buffer->address(), buffer->size().width(), buffer->size().height(), QImage::Format_RGB32)
static uint32_t drmFormatToShmFormat(uint32_t drmFormat)
{
buffer->setUsed(true);
switch (drmFormat) {
case DRM_FORMAT_ARGB8888:
return WL_SHM_FORMAT_ARGB8888;
case DRM_FORMAT_XRGB8888:
return WL_SHM_FORMAT_XRGB8888;
default:
return static_cast<wl_shm_format>(drmFormat);
}
}
static QImage::Format drmFormatToQImageFormat(uint32_t drmFormat)
{
switch (drmFormat) {
case DRM_FORMAT_ARGB8888:
return QImage::Format_ARGB32;
case DRM_FORMAT_XRGB8888:
return QImage::Format_RGB32;
default:
Q_UNREACHABLE();
}
}
WaylandQPainterBufferSlot::WaylandQPainterBufferSlot(WaylandDisplay *display, ShmGraphicsBuffer *graphicsBuffer)
: graphicsBuffer(graphicsBuffer)
{
const ShmAttributes *attributes = graphicsBuffer->shmAttributes();
size = attributes->size.height() * attributes->stride;
wl_shm_pool *pool = wl_shm_create_pool(display->shm(), attributes->fd.get(), size);
buffer = wl_shm_pool_create_buffer(pool,
attributes->offset,
attributes->size.width(),
attributes->size.height(),
attributes->stride,
drmFormatToShmFormat(attributes->format));
wl_shm_pool_destroy(pool);
static const wl_buffer_listener listener = {
.release = [](void *userData, wl_buffer *buffer) {
WaylandQPainterBufferSlot *slot = static_cast<WaylandQPainterBufferSlot *>(userData);
slot->used = false;
},
};
wl_buffer_add_listener(buffer, &listener, this);
data = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, attributes->fd.get(), attributes->offset);
if (data == MAP_FAILED) {
qCWarning(KWIN_WAYLAND_BACKEND) << "Failed to map a shared memory buffer";
return;
}
image = QImage(static_cast<uchar *>(data), attributes->size.width(), attributes->size.height(), drmFormatToQImageFormat(attributes->format));
}
WaylandQPainterBufferSlot::~WaylandQPainterBufferSlot()
{
buffer->setUsed(false);
}
WaylandQPainterPrimaryLayer::WaylandQPainterPrimaryLayer(WaylandOutput *output)
: m_waylandOutput(output)
, m_pool(output->backend()->display()->shmPool())
{
connect(m_pool, &KWayland::Client::ShmPool::poolResized, this, &WaylandQPainterPrimaryLayer::remapBuffer);
}
WaylandQPainterPrimaryLayer::~WaylandQPainterPrimaryLayer()
{
m_slots.clear();
}
void WaylandQPainterPrimaryLayer::remapBuffer()
{
qCDebug(KWIN_WAYLAND_BACKEND) << "Remapped back buffer of surface" << m_waylandOutput->surface();
const QSize nativeSize(m_waylandOutput->geometry().size() * m_waylandOutput->scale());
for (const auto &slot : m_slots) {
slot->image = QImage(slot->buffer->address(), nativeSize.width(), nativeSize.height(), QImage::Format_RGB32);
if (data) {
munmap(data, size);
}
wl_buffer_destroy(buffer);
graphicsBuffer->drop();
}
void WaylandQPainterPrimaryLayer::present()
WaylandQPainterSwapchain::WaylandQPainterSwapchain(WaylandOutput *output, const QSize &size, uint32_t format)
: m_allocator(std::make_unique<ShmGraphicsBufferAllocator>())
, m_output(output)
, m_size(size)
, m_format(format)
{
}
QSize WaylandQPainterSwapchain::size() const
{
return m_size;
}
std::shared_ptr<WaylandQPainterBufferSlot> WaylandQPainterSwapchain::acquire()
{
for (const auto &slot : m_slots) {
if (slot.get() == m_back) {
slot->age = 1;
} else if (slot->age > 0) {
slot->age++;
if (!slot->used) {
slot->used = true;
return slot;
}
}
auto s = m_waylandOutput->surface();
s->attachBuffer(m_back->buffer);
s->damage(m_damageJournal.lastDamage());
s->setScale(std::ceil(m_waylandOutput->scale()));
s->commit();
}
WaylandQPainterBufferSlot *WaylandQPainterPrimaryLayer::back() const
{
return m_back;
}
WaylandQPainterBufferSlot *WaylandQPainterPrimaryLayer::acquire()
{
const QSize nativeSize(m_waylandOutput->pixelSize());
if (m_swapchainSize != nativeSize) {
m_swapchainSize = nativeSize;
m_slots.clear();
}
for (const auto &slot : m_slots) {
if (slot->buffer->isReleased()) {
m_back = slot.get();
slot->buffer->setReleased(false);
return m_back;
}
}
auto buffer = m_pool->getBuffer(nativeSize, nativeSize.width() * 4, KWayland::Client::Buffer::Format::RGB32).toStrongRef();
ShmGraphicsBuffer *buffer = m_allocator->allocate(m_size, m_format);
if (!buffer) {
qCDebug(KWIN_WAYLAND_BACKEND) << "Did not get a new Buffer from Shm Pool";
return nullptr;
}
m_slots.push_back(std::make_unique<WaylandQPainterBufferSlot>(buffer));
m_back = m_slots.back().get();
auto slot = std::make_shared<WaylandQPainterBufferSlot>(m_output->backend()->display(), buffer);
m_slots.push_back(slot);
// qCDebug(KWIN_WAYLAND_BACKEND) << "Created a new back buffer for output surface" << m_waylandOutput->surface();
return m_back;
return slot;
}
void WaylandQPainterSwapchain::release(std::shared_ptr<WaylandQPainterBufferSlot> buffer)
{
for (const auto &slot : m_slots) {
if (slot == buffer) {
slot->age = 1;
} else if (slot->age > 0) {
slot->age++;
}
}
}
WaylandQPainterPrimaryLayer::WaylandQPainterPrimaryLayer(WaylandOutput *output)
: m_waylandOutput(output)
{
}
void WaylandQPainterPrimaryLayer::present()
{
auto s = m_waylandOutput->surface();
s->attachBuffer(m_back->buffer);
s->damage(m_damageJournal.lastDamage());
s->setScale(std::ceil(m_waylandOutput->scale()));
s->commit();
m_swapchain->release(m_back);
}
QRegion WaylandQPainterPrimaryLayer::accumulateDamage(int bufferAge) const
@ -117,10 +160,19 @@ QRegion WaylandQPainterPrimaryLayer::accumulateDamage(int bufferAge) const
std::optional<OutputLayerBeginFrameInfo> WaylandQPainterPrimaryLayer::beginFrame()
{
WaylandQPainterBufferSlot *slot = acquire();
const QSize nativeSize(m_waylandOutput->pixelSize());
if (!m_swapchain || m_swapchain->size() != nativeSize) {
m_swapchain = std::make_unique<WaylandQPainterSwapchain>(m_waylandOutput, nativeSize, DRM_FORMAT_XRGB8888);
}
m_back = m_swapchain->acquire();
if (!m_back) {
return std::nullopt;
}
return OutputLayerBeginFrameInfo{
.renderTarget = RenderTarget(&slot->image),
.repaint = accumulateDamage(slot->age),
.renderTarget = RenderTarget(&m_back->image),
.repaint = accumulateDamage(m_back->age),
};
}
@ -140,28 +192,29 @@ WaylandQPainterCursorLayer::WaylandQPainterCursorLayer(WaylandOutput *output)
{
}
WaylandQPainterCursorLayer::~WaylandQPainterCursorLayer()
{
}
std::optional<OutputLayerBeginFrameInfo> WaylandQPainterCursorLayer::beginFrame()
{
const auto tmp = size().expandedTo(QSize(64, 64));
const QSize bufferSize(std::ceil(tmp.width()), std::ceil(tmp.height()));
if (m_backingStore.size() != bufferSize) {
m_backingStore = QImage(bufferSize, QImage::Format_ARGB32_Premultiplied);
if (!m_swapchain || m_swapchain->size() != bufferSize) {
m_swapchain = std::make_unique<WaylandQPainterSwapchain>(m_output, bufferSize, DRM_FORMAT_ARGB8888);
}
m_back = m_swapchain->acquire();
if (!m_back) {
return std::nullopt;
}
return OutputLayerBeginFrameInfo{
.renderTarget = RenderTarget(&m_backingStore),
.renderTarget = RenderTarget(&m_back->image),
.repaint = infiniteRegion(),
};
}
bool WaylandQPainterCursorLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
{
KWayland::Client::Buffer::Ptr buffer = m_output->backend()->display()->shmPool()->createBuffer(m_backingStore);
m_output->cursor()->update(*buffer.lock(), scale(), hotspot().toPoint());
m_output->cursor()->update(m_back->buffer, scale(), hotspot().toPoint());
m_swapchain->release(m_back);
return true;
}

View file

@ -13,67 +13,76 @@
#include "platformsupport/scenes/qpainter/qpainterbackend.h"
#include "utils/damagejournal.h"
#include <KWayland/Client/buffer.h>
#include <QImage>
#include <QObject>
namespace KWayland
{
namespace Client
{
class ShmPool;
class Buffer;
}
}
struct wl_buffer;
namespace KWin
{
class Output;
class ShmGraphicsBuffer;
class ShmGraphicsBufferAllocator;
namespace Wayland
{
class WaylandBackend;
class WaylandDisplay;
class WaylandOutput;
class WaylandQPainterBackend;
class WaylandQPainterBufferSlot
{
public:
WaylandQPainterBufferSlot(QSharedPointer<KWayland::Client::Buffer> buffer);
WaylandQPainterBufferSlot(WaylandDisplay *display, ShmGraphicsBuffer *graphicsBuffer);
~WaylandQPainterBufferSlot();
QSharedPointer<KWayland::Client::Buffer> buffer;
ShmGraphicsBuffer *graphicsBuffer;
wl_buffer *buffer;
QImage image;
void *data = nullptr;
int size;
int age = 0;
bool used = false;
};
class WaylandQPainterSwapchain
{
public:
WaylandQPainterSwapchain(WaylandOutput *output, const QSize &size, uint32_t format);
QSize size() const;
std::shared_ptr<WaylandQPainterBufferSlot> acquire();
void release(std::shared_ptr<WaylandQPainterBufferSlot> buffer);
private:
std::unique_ptr<ShmGraphicsBufferAllocator> m_allocator;
WaylandOutput *m_output;
QSize m_size;
uint32_t m_format;
std::vector<std::shared_ptr<WaylandQPainterBufferSlot>> m_slots;
};
class WaylandQPainterPrimaryLayer : public OutputLayer
{
public:
WaylandQPainterPrimaryLayer(WaylandOutput *output);
~WaylandQPainterPrimaryLayer() override;
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
quint32 format() const override;
void remapBuffer();
WaylandQPainterBufferSlot *back() const;
WaylandQPainterBufferSlot *acquire();
void present();
QRegion accumulateDamage(int bufferAge) const;
private:
WaylandOutput *m_waylandOutput;
KWayland::Client::ShmPool *m_pool;
DamageJournal m_damageJournal;
std::vector<std::unique_ptr<WaylandQPainterBufferSlot>> m_slots;
WaylandQPainterBufferSlot *m_back = nullptr;
QSize m_swapchainSize;
std::unique_ptr<WaylandQPainterSwapchain> m_swapchain;
std::shared_ptr<WaylandQPainterBufferSlot> m_back;
friend class WaylandQPainterBackend;
};
@ -84,7 +93,6 @@ class WaylandQPainterCursorLayer : public OutputLayer
public:
explicit WaylandQPainterCursorLayer(WaylandOutput *output);
~WaylandQPainterCursorLayer() override;
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
@ -92,7 +100,8 @@ public:
private:
WaylandOutput *m_output;
QImage m_backingStore;
std::unique_ptr<WaylandQPainterSwapchain> m_swapchain;
std::shared_ptr<WaylandQPainterBufferSlot> m_back;
};
class WaylandQPainterBackend : public QPainterBackend

View file

@ -56,43 +56,6 @@ GbmGraphicsBuffer *GbmGraphicsBufferAllocator::allocate(const QSize &size, uint3
return new GbmGraphicsBuffer(std::move(attributes.value()), bo);
}
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(DmaBufAttributes attributes, gbm_bo *handle)
: m_bo(handle)
, m_dmabufAttributes(std::move(attributes))

View file

@ -6,6 +6,8 @@
#include "core/graphicsbuffer.h"
#include <drm_fourcc.h>
namespace KWin
{
@ -57,4 +59,46 @@ const DmaBufAttributes *GraphicsBuffer::dmabufAttributes() const
return nullptr;
}
const ShmAttributes *GraphicsBuffer::shmAttributes() const
{
return nullptr;
}
bool GraphicsBuffer::alphaChannelFromDrmFormat(uint32_t format)
{
switch (format) {
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;
}
}
} // namespace KWin

View file

@ -10,6 +10,7 @@
#include "utils/filedescriptor.h"
#include <QObject>
#include <QSize>
namespace KWin
{
@ -27,6 +28,15 @@ struct DmaBufAttributes
int pitch[4] = {0, 0, 0, 0};
};
struct ShmAttributes
{
FileDescriptor fd;
int stride;
off_t offset;
QSize size;
uint32_t format;
};
/**
* The GraphicsBuffer class represents a chunk of memory containing graphics data.
*
@ -52,6 +62,9 @@ public:
virtual bool hasAlphaChannel() const = 0;
virtual const DmaBufAttributes *dmabufAttributes() const;
virtual const ShmAttributes *shmAttributes() const;
static bool alphaChannelFromDrmFormat(uint32_t format);
Q_SIGNALS:
void released();

View file

@ -0,0 +1,94 @@
/*
SPDX-FileCopyrightText: 2023 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "core/shmgraphicsbufferallocator.h"
#include "config-kwin.h"
#include <drm_fourcc.h>
#include <fcntl.h>
#include <sys/mman.h>
namespace KWin
{
ShmGraphicsBuffer::ShmGraphicsBuffer(ShmAttributes &&attributes)
: m_attributes(std::move(attributes))
, m_hasAlphaChannel(alphaChannelFromDrmFormat(attributes.format))
{
}
QSize ShmGraphicsBuffer::size() const
{
return m_attributes.size;
}
bool ShmGraphicsBuffer::hasAlphaChannel() const
{
return m_hasAlphaChannel;
}
const ShmAttributes *ShmGraphicsBuffer::shmAttributes() const
{
return &m_attributes;
}
ShmGraphicsBuffer *ShmGraphicsBufferAllocator::allocate(const QSize &size, uint32_t format, const QVector<uint64_t> &modifiers)
{
if (!modifiers.isEmpty()) {
return nullptr;
}
switch (format) {
case DRM_FORMAT_ARGB8888:
case DRM_FORMAT_XRGB8888:
break;
default:
return nullptr;
}
const int stride = size.width() * 4;
const int bufferSize = size.height() * stride;
#if HAVE_MEMFD
FileDescriptor fd = FileDescriptor(memfd_create("shm", MFD_CLOEXEC | MFD_ALLOW_SEALING));
if (!fd.isValid()) {
return nullptr;
}
if (ftruncate(fd.get(), bufferSize) < 0) {
return nullptr;
}
fcntl(fd.get(), F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_SEAL);
#else
char templateName[] = "/tmp/kwin-shm-XXXXXX";
FileDescriptor fd{mkstemp(templateName)};
if (!fd.isValid()) {
return nullptr;
}
unlink(templateName);
int flags = fcntl(fd.get(), F_GETFD);
if (flags == -1 || fcntl(fd.get(), F_SETFD, flags | FD_CLOEXEC) == -1) {
return nullptr;
}
if (ftruncate(fd.get(), bufferSize) < 0) {
return nullptr;
}
#endif
return new ShmGraphicsBuffer(ShmAttributes{
.fd = std::move(fd),
.stride = stride,
.offset = 0,
.size = size,
.format = format,
});
}
} // namespace KWin

View file

@ -0,0 +1,38 @@
/*
SPDX-FileCopyrightText: 2023 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "core/graphicsbuffer.h"
#include "core/graphicsbufferallocator.h"
#include "utils/filedescriptor.h"
namespace KWin
{
class KWIN_EXPORT ShmGraphicsBuffer : public GraphicsBuffer
{
Q_OBJECT
public:
explicit ShmGraphicsBuffer(ShmAttributes &&attributes);
QSize size() const override;
bool hasAlphaChannel() const override;
const ShmAttributes *shmAttributes() const override;
private:
ShmAttributes m_attributes;
bool m_hasAlphaChannel;
};
class KWIN_EXPORT ShmGraphicsBufferAllocator : public GraphicsBufferAllocator
{
public:
ShmGraphicsBuffer *allocate(const QSize &size, uint32_t format, const QVector<uint64_t> &modifiers = {}) override;
};
} // namespace KWin

View file

@ -327,43 +327,6 @@ void LinuxDmaBufV1ClientBufferIntegration::setSupportedFormatsWithModifiers(cons
}
}
static bool testAlphaChannel(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;
}
}
void LinuxDmaBufV1ClientBuffer::buffer_destroy_resource(wl_resource *resource)
{
if (LinuxDmaBufV1ClientBuffer *buffer = LinuxDmaBufV1ClientBuffer::get(resource)) {
@ -384,7 +347,7 @@ const struct wl_buffer_interface LinuxDmaBufV1ClientBuffer::implementation = {
LinuxDmaBufV1ClientBuffer::LinuxDmaBufV1ClientBuffer(KWin::DmaBufAttributes &&attrs)
{
m_attrs = std::move(attrs);
m_hasAlphaChannel = testAlphaChannel(m_attrs.format);
m_hasAlphaChannel = alphaChannelFromDrmFormat(m_attrs.format);
}
void LinuxDmaBufV1ClientBuffer::initialize(wl_resource *resource)