From ce2b4c0bee79a8ad239b6a99d3f3cb619ed8c519 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Thu, 13 Apr 2023 12:37:42 +0300 Subject: [PATCH] {core,backends/wayland}: Refactor shm buffer allocator --- src/CMakeLists.txt | 1 + src/backends/wayland/wayland_display.cpp | 12 +- src/backends/wayland/wayland_display.h | 6 +- .../wayland/wayland_qpainter_backend.cpp | 209 +++++++++++------- .../wayland/wayland_qpainter_backend.h | 57 +++-- src/core/gbmgraphicsbufferallocator.cpp | 37 ---- src/core/graphicsbuffer.cpp | 44 ++++ src/core/graphicsbuffer.h | 13 ++ src/core/shmgraphicsbufferallocator.cpp | 94 ++++++++ src/core/shmgraphicsbufferallocator.h | 38 ++++ src/wayland/linuxdmabufv1clientbuffer.cpp | 39 +--- 11 files changed, 364 insertions(+), 186 deletions(-) create mode 100644 src/core/shmgraphicsbufferallocator.cpp create mode 100644 src/core/shmgraphicsbufferallocator.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c36efa872a..2be53dc6ac 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 diff --git a/src/backends/wayland/wayland_display.cpp b/src/backends/wayland/wayland_display.cpp index 4c935f172f..5e622f82a5 100644 --- a/src/backends/wayland/wayland_display.cpp +++ b/src/backends/wayland/wayland_display.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -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(); display->m_compositor->setup(static_cast(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(); - display->m_shmPool->setup(static_cast(wl_registry_bind(registry, name, &wl_shm_interface, std::min(version, 1u)))); + display->m_shm = static_cast(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(); display->m_seat->setup(static_cast(wl_registry_bind(registry, name, &wl_seat_interface, std::min(version, 2u)))); diff --git a/src/backends/wayland/wayland_display.h b/src/backends/wayland/wayland_display.h index 650b53fbbc..2206aef34d 100644 --- a/src/backends/wayland/wayland_display.h +++ b/src/backends/wayland/wayland_display.h @@ -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 m_eventThread; std::unique_ptr m_linuxDmabuf; std::unique_ptr m_compositor; @@ -92,7 +93,6 @@ private: std::unique_ptr m_relativePointerManager; std::unique_ptr m_seat; std::unique_ptr m_xdgDecorationManager; - std::unique_ptr m_shmPool; std::unique_ptr m_xdgShell; }; diff --git a/src/backends/wayland/wayland_qpainter_backend.cpp b/src/backends/wayland/wayland_qpainter_backend.cpp index a3b3756577..92d3920d55 100644 --- a/src/backends/wayland/wayland_qpainter_backend.cpp +++ b/src/backends/wayland/wayland_qpainter_backend.cpp @@ -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 -#include #include #include #include +#include +#include namespace KWin { namespace Wayland { -WaylandQPainterBufferSlot::WaylandQPainterBufferSlot(QSharedPointer 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(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(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(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()) + , m_output(output) + , m_size(size) + , m_format(format) +{ +} + +QSize WaylandQPainterSwapchain::size() const +{ + return m_size; +} + +std::shared_ptr 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(buffer)); - m_back = m_slots.back().get(); + auto slot = std::make_shared(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 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 WaylandQPainterPrimaryLayer::beginFrame() { - WaylandQPainterBufferSlot *slot = acquire(); + const QSize nativeSize(m_waylandOutput->pixelSize()); + if (!m_swapchain || m_swapchain->size() != nativeSize) { + m_swapchain = std::make_unique(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 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(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; } diff --git a/src/backends/wayland/wayland_qpainter_backend.h b/src/backends/wayland/wayland_qpainter_backend.h index 8094b9e5c5..196983f36c 100644 --- a/src/backends/wayland/wayland_qpainter_backend.h +++ b/src/backends/wayland/wayland_qpainter_backend.h @@ -13,67 +13,76 @@ #include "platformsupport/scenes/qpainter/qpainterbackend.h" #include "utils/damagejournal.h" -#include - #include #include -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 buffer); + WaylandQPainterBufferSlot(WaylandDisplay *display, ShmGraphicsBuffer *graphicsBuffer); ~WaylandQPainterBufferSlot(); - QSharedPointer 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 acquire(); + void release(std::shared_ptr buffer); + +private: + std::unique_ptr m_allocator; + WaylandOutput *m_output; + QSize m_size; + uint32_t m_format; + std::vector> m_slots; }; class WaylandQPainterPrimaryLayer : public OutputLayer { public: WaylandQPainterPrimaryLayer(WaylandOutput *output); - ~WaylandQPainterPrimaryLayer() override; std::optional 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> m_slots; - WaylandQPainterBufferSlot *m_back = nullptr; - QSize m_swapchainSize; + std::unique_ptr m_swapchain; + std::shared_ptr m_back; friend class WaylandQPainterBackend; }; @@ -84,7 +93,6 @@ class WaylandQPainterCursorLayer : public OutputLayer public: explicit WaylandQPainterCursorLayer(WaylandOutput *output); - ~WaylandQPainterCursorLayer() override; std::optional 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 m_swapchain; + std::shared_ptr m_back; }; class WaylandQPainterBackend : public QPainterBackend diff --git a/src/core/gbmgraphicsbufferallocator.cpp b/src/core/gbmgraphicsbufferallocator.cpp index 5ee1f0bf47..8d88b9a452 100644 --- a/src/core/gbmgraphicsbufferallocator.cpp +++ b/src/core/gbmgraphicsbufferallocator.cpp @@ -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)) diff --git a/src/core/graphicsbuffer.cpp b/src/core/graphicsbuffer.cpp index d4ec5d85b1..7fc4c1d0fb 100644 --- a/src/core/graphicsbuffer.cpp +++ b/src/core/graphicsbuffer.cpp @@ -6,6 +6,8 @@ #include "core/graphicsbuffer.h" +#include + 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 diff --git a/src/core/graphicsbuffer.h b/src/core/graphicsbuffer.h index e9af382de2..d786c532c1 100644 --- a/src/core/graphicsbuffer.h +++ b/src/core/graphicsbuffer.h @@ -10,6 +10,7 @@ #include "utils/filedescriptor.h" #include +#include 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(); diff --git a/src/core/shmgraphicsbufferallocator.cpp b/src/core/shmgraphicsbufferallocator.cpp new file mode 100644 index 0000000000..46e640f609 --- /dev/null +++ b/src/core/shmgraphicsbufferallocator.cpp @@ -0,0 +1,94 @@ +/* + SPDX-FileCopyrightText: 2023 Vlad Zahorodnii + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#include "core/shmgraphicsbufferallocator.h" + +#include "config-kwin.h" + +#include +#include +#include + +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 &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 diff --git a/src/core/shmgraphicsbufferallocator.h b/src/core/shmgraphicsbufferallocator.h new file mode 100644 index 0000000000..678163e142 --- /dev/null +++ b/src/core/shmgraphicsbufferallocator.h @@ -0,0 +1,38 @@ +/* + SPDX-FileCopyrightText: 2023 Vlad Zahorodnii + + 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 &modifiers = {}) override; +}; + +} // namespace KWin diff --git a/src/wayland/linuxdmabufv1clientbuffer.cpp b/src/wayland/linuxdmabufv1clientbuffer.cpp index 6e80e2a294..2e9dc6871d 100644 --- a/src/wayland/linuxdmabufv1clientbuffer.cpp +++ b/src/wayland/linuxdmabufv1clientbuffer.cpp @@ -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)