KWin
Loading...
Searching...
No Matches
wayland_qpainter_backend.cpp
Go to the documentation of this file.
1/*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2019 Roman Gilg <subdiff@gmail.com>
6 SPDX-FileCopyrightText: 2013, 2015 Martin Gräßlin <mgraesslin@kde.org>
7
8 SPDX-License-Identifier: GPL-2.0-or-later
9*/
14#include "wayland_backend.h"
15#include "wayland_output.h"
16
17#include <KWayland/Client/surface.h>
18
19#include <cmath>
20#include <drm_fourcc.h>
21#include <wayland-client-protocol.h>
22
23namespace KWin
24{
25namespace Wayland
26{
27
29 : m_waylandOutput(output)
30 , m_backend(backend)
31{
32}
33
37
39{
40 wl_buffer *buffer = m_waylandOutput->backend()->importBuffer(m_back->buffer());
41 Q_ASSERT(buffer);
42
43 auto s = m_waylandOutput->surface();
44 s->attachBuffer(buffer);
45 s->damage(m_damageJournal.lastDamage());
46 s->setScale(std::ceil(m_waylandOutput->scale()));
47 s->commit();
48
49 m_swapchain->release(m_back);
50}
51
53{
54 return m_damageJournal.accumulate(bufferAge, infiniteRegion());
55}
56
57std::optional<OutputLayerBeginFrameInfo> WaylandQPainterPrimaryLayer::beginFrame()
58{
59 const QSize nativeSize(m_waylandOutput->modeSize());
60 if (!m_swapchain || m_swapchain->size() != nativeSize) {
61 m_swapchain = std::make_unique<QPainterSwapchain>(m_backend->graphicsBufferAllocator(), nativeSize, DRM_FORMAT_XRGB8888);
62 }
63
64 m_back = m_swapchain->acquire();
65 if (!m_back) {
66 return std::nullopt;
67 }
68
69 m_renderStart = std::chrono::steady_clock::now();
71 .renderTarget = RenderTarget(m_back->view()->image()),
72 .repaint = accumulateDamage(m_back->age()),
73 };
74}
75
76bool WaylandQPainterPrimaryLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
77{
78 m_renderTime = std::chrono::steady_clock::now() - m_renderStart;
79 m_damageJournal.add(damagedRegion);
80 return true;
81}
82
83std::chrono::nanoseconds WaylandQPainterPrimaryLayer::queryRenderTime() const
84{
85 return m_renderTime;
86}
87
89 : m_output(output)
90 , m_backend(backend)
91{
92}
93
97
98std::optional<OutputLayerBeginFrameInfo> WaylandQPainterCursorLayer::beginFrame()
99{
100 const auto tmp = size().expandedTo(QSize(64, 64));
101 const QSize bufferSize(std::ceil(tmp.width()), std::ceil(tmp.height()));
102 if (!m_swapchain || m_swapchain->size() != bufferSize) {
103 m_swapchain = std::make_unique<QPainterSwapchain>(m_backend->graphicsBufferAllocator(), bufferSize, DRM_FORMAT_ARGB8888);
104 }
105
106 m_back = m_swapchain->acquire();
107 if (!m_back) {
108 return std::nullopt;
109 }
110
111 m_renderStart = std::chrono::steady_clock::now();
113 .renderTarget = RenderTarget(m_back->view()->image()),
114 .repaint = infiniteRegion(),
115 };
116}
117
118bool WaylandQPainterCursorLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
119{
120 m_renderTime = std::chrono::steady_clock::now() - m_renderStart;
121 wl_buffer *buffer = m_output->backend()->importBuffer(m_back->buffer());
122 Q_ASSERT(buffer);
123
124 m_output->cursor()->update(buffer, scale(), hotspot().toPoint());
125 m_swapchain->release(m_back);
126 return true;
127}
128
129std::chrono::nanoseconds WaylandQPainterCursorLayer::queryRenderTime() const
130{
131 return m_renderTime;
132}
133
136 , m_backend(b)
137 , m_allocator(std::make_unique<ShmGraphicsBufferAllocator>())
138{
139
140 const auto waylandOutputs = m_backend->waylandOutputs();
141 for (auto *output : waylandOutputs) {
142 createOutput(output);
143 }
144 connect(m_backend, &WaylandBackend::outputAdded, this, &WaylandQPainterBackend::createOutput);
145 connect(m_backend, &WaylandBackend::outputRemoved, this, [this](Output *waylandOutput) {
146 m_outputs.erase(waylandOutput);
147 });
148}
149
153
154void WaylandQPainterBackend::createOutput(Output *waylandOutput)
155{
156 m_outputs[waylandOutput] = Layers{
157 .primaryLayer = std::make_unique<WaylandQPainterPrimaryLayer>(static_cast<WaylandOutput *>(waylandOutput), this),
158 .cursorLayer = std::make_unique<WaylandQPainterCursorLayer>(static_cast<WaylandOutput *>(waylandOutput), this),
159 };
160}
161
163{
164 return m_allocator.get();
165}
166
167void WaylandQPainterBackend::present(Output *output, const std::shared_ptr<OutputFrame> &frame)
168{
169 m_outputs[output].primaryLayer->present();
170 static_cast<WaylandOutput *>(output)->framePending(frame);
171}
172
174{
175 return m_outputs[output].primaryLayer.get();
176}
177
179{
180 return m_outputs[output].cursorLayer.get();
181}
182
183}
184}
185
186#include "moc_wayland_qpainter_backend.cpp"
void add(const QRegion &region)
QRegion accumulate(int bufferAge, const QRegion &fallback=QRegion()) const
QRegion lastDamage() const
void outputAdded(Output *output)
void outputRemoved(Output *output)
qreal scale() const
Definition output.cpp:455
QSize modeSize() const
Definition output.cpp:480
qreal scale() const
QSizeF size() const
QPointF hotspot() const
Class encapsulating all Wayland data structures needed by the Egl backend.
QList< WaylandOutput * > waylandOutputs() const
wl_buffer * importBuffer(GraphicsBuffer *graphicsBuffer)
void update(wl_buffer *buffer, qreal scale, const QPoint &hotspot)
WaylandCursor * cursor() const
WaylandBackend * backend() const
KWayland::Client::Surface * surface() const
OutputLayer * primaryLayer(Output *output) override
GraphicsBufferAllocator * graphicsBufferAllocator() const override
OutputLayer * cursorLayer(Output *output) override
void present(Output *output, const std::shared_ptr< OutputFrame > &frame) override
std::chrono::nanoseconds queryRenderTime() const override
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override
std::optional< OutputLayerBeginFrameInfo > beginFrame() override
WaylandQPainterCursorLayer(WaylandOutput *output, WaylandQPainterBackend *backend)
std::optional< OutputLayerBeginFrameInfo > beginFrame() override
std::chrono::nanoseconds queryRenderTime() const override
WaylandQPainterPrimaryLayer(WaylandOutput *output, WaylandQPainterBackend *backend)
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override
KWIN_EXPORT QRect infiniteRegion()
Definition globals.h:234