backends/virtual: Port to ShmGraphicsBufferAllocator

This commit is contained in:
Vlad Zahorodnii 2023-04-23 21:05:44 +03:00
parent b0bdffe08f
commit 4b2568bdcf
2 changed files with 117 additions and 6 deletions

View file

@ -7,27 +7,107 @@
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "virtual_qpainter_backend.h"
#include "core/shmgraphicsbufferallocator.h"
#include "utils/softwarevsyncmonitor.h"
#include "virtual_backend.h"
#include "virtual_logging.h"
#include "virtual_output.h"
#include <QPainter>
#include <drm_fourcc.h>
#include <sys/mman.h>
namespace KWin
{
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();
}
}
VirtualQPainterBufferSlot::VirtualQPainterBufferSlot(ShmGraphicsBuffer *graphicsBuffer)
: graphicsBuffer(graphicsBuffer)
{
const ShmAttributes *attributes = graphicsBuffer->shmAttributes();
size = attributes->size.height() * attributes->stride;
data = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, attributes->fd.get(), 0);
if (data == MAP_FAILED) {
qCWarning(KWIN_VIRTUAL) << "Failed to map a shared memory buffer";
return;
}
image = QImage(static_cast<uchar *>(data), attributes->size.width(), attributes->size.height(), drmFormatToQImageFormat(attributes->format));
}
VirtualQPainterBufferSlot::~VirtualQPainterBufferSlot()
{
if (data) {
munmap(data, size);
}
graphicsBuffer->drop();
}
VirtualQPainterSwapchain::VirtualQPainterSwapchain(const QSize &size, uint32_t format)
: m_allocator(std::make_unique<ShmGraphicsBufferAllocator>())
, m_size(size)
, m_format(format)
{
}
QSize VirtualQPainterSwapchain::size() const
{
return m_size;
}
std::shared_ptr<VirtualQPainterBufferSlot> VirtualQPainterSwapchain::acquire()
{
for (const auto &slot : m_slots) {
if (!slot->graphicsBuffer->isReferenced()) {
return slot;
}
}
ShmGraphicsBuffer *buffer = m_allocator->allocate(m_size, m_format);
if (!buffer) {
qCDebug(KWIN_VIRTUAL) << "Did not get a new Buffer from Shm Pool";
return nullptr;
}
auto slot = std::make_shared<VirtualQPainterBufferSlot>(buffer);
m_slots.push_back(slot);
return slot;
}
VirtualQPainterLayer::VirtualQPainterLayer(Output *output)
: m_output(output)
, m_image(output->pixelSize(), QImage::Format_RGB32)
{
m_image.fill(Qt::black);
}
std::optional<OutputLayerBeginFrameInfo> VirtualQPainterLayer::beginFrame()
{
const QSize nativeSize(m_output->modeSize());
if (!m_swapchain || m_swapchain->size() != nativeSize) {
m_swapchain = std::make_unique<VirtualQPainterSwapchain>(nativeSize, DRM_FORMAT_XRGB8888);
}
m_current = m_swapchain->acquire();
if (!m_current) {
return std::nullopt;
}
return OutputLayerBeginFrameInfo{
.renderTarget = RenderTarget(&m_image),
.renderTarget = RenderTarget(&m_current->image),
.repaint = m_output->rect(),
};
}
@ -39,12 +119,12 @@ bool VirtualQPainterLayer::endFrame(const QRegion &renderedRegion, const QRegion
QImage *VirtualQPainterLayer::image()
{
return &m_image;
return &m_current->image;
}
quint32 VirtualQPainterLayer::format() const
{
return DRM_FORMAT_RGBX8888;
return DRM_FORMAT_XRGB8888;
}
VirtualQPainterBackend::VirtualQPainterBackend(VirtualBackend *backend)

View file

@ -19,8 +19,38 @@
namespace KWin
{
class ShmGraphicsBuffer;
class ShmGraphicsBufferAllocator;
class VirtualBackend;
class VirtualQPainterBufferSlot
{
public:
VirtualQPainterBufferSlot(ShmGraphicsBuffer *graphicsBuffer);
~VirtualQPainterBufferSlot();
ShmGraphicsBuffer *graphicsBuffer;
QImage image;
void *data = nullptr;
int size;
};
class VirtualQPainterSwapchain
{
public:
VirtualQPainterSwapchain(const QSize &size, uint32_t format);
QSize size() const;
std::shared_ptr<VirtualQPainterBufferSlot> acquire();
private:
std::unique_ptr<ShmGraphicsBufferAllocator> m_allocator;
QSize m_size;
uint32_t m_format;
std::vector<std::shared_ptr<VirtualQPainterBufferSlot>> m_slots;
};
class VirtualQPainterLayer : public OutputLayer
{
public:
@ -33,7 +63,8 @@ public:
private:
Output *const m_output;
QImage m_image;
std::unique_ptr<VirtualQPainterSwapchain> m_swapchain;
std::shared_ptr<VirtualQPainterBufferSlot> m_current;
};
class VirtualQPainterBackend : public QPainterBackend