backends/virtual: Port to ShmGraphicsBufferAllocator
This commit is contained in:
parent
b0bdffe08f
commit
4b2568bdcf
2 changed files with 117 additions and 6 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue