KWin
Loading...
Searching...
No Matches
drm_qpainter_layer.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: 2022 Xaver Hugl <xaver.hugl@gmail.com>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8*/
11#include "drm_buffer.h"
12#include "drm_gpu.h"
13#include "drm_logging.h"
14#include "drm_pipeline.h"
15#include "drm_virtual_output.h"
17
18#include <cerrno>
19#include <drm_fourcc.h>
20
21namespace KWin
22{
23
28
29std::optional<OutputLayerBeginFrameInfo> DrmQPainterLayer::beginFrame()
30{
31 if (!doesSwapchainFit()) {
32 m_swapchain = std::make_shared<QPainterSwapchain>(m_pipeline->gpu()->graphicsBufferAllocator(), m_pipeline->mode()->size(), DRM_FORMAT_XRGB8888);
33 m_damageJournal = DamageJournal();
34 }
35
36 m_currentBuffer = m_swapchain->acquire();
37 if (!m_currentBuffer) {
38 return std::nullopt;
39 }
40
41 m_renderStart = std::chrono::steady_clock::now();
42 const QRegion repaint = m_damageJournal.accumulate(m_currentBuffer->age(), infiniteRegion());
44 .renderTarget = RenderTarget(m_currentBuffer->view()->image()),
45 .repaint = repaint,
46 };
47}
48
49bool DrmQPainterLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
50{
51 m_renderTime = std::chrono::steady_clock::now() - m_renderStart;
52 m_currentFramebuffer = m_pipeline->gpu()->importBuffer(m_currentBuffer->buffer(), FileDescriptor{});
53 m_damageJournal.add(damagedRegion);
54 m_swapchain->release(m_currentBuffer);
55 if (!m_currentFramebuffer) {
56 qCWarning(KWIN_DRM, "Failed to create dumb framebuffer: %s", strerror(errno));
57 }
58 return m_currentFramebuffer != nullptr;
59}
60
62{
63 if (!doesSwapchainFit()) {
64 m_swapchain = std::make_shared<QPainterSwapchain>(m_pipeline->gpu()->graphicsBufferAllocator(), m_pipeline->mode()->size(), DRM_FORMAT_XRGB8888);
65 m_currentBuffer = m_swapchain->acquire();
66 if (m_currentBuffer) {
67 m_currentFramebuffer = m_pipeline->gpu()->importBuffer(m_currentBuffer->buffer(), FileDescriptor{});
68 m_swapchain->release(m_currentBuffer);
69 if (!m_currentFramebuffer) {
70 qCWarning(KWIN_DRM, "Failed to create dumb framebuffer: %s", strerror(errno));
71 }
72 } else {
73 m_currentFramebuffer.reset();
74 }
75 }
76 return m_currentFramebuffer != nullptr;
77}
78
79bool DrmQPainterLayer::doesSwapchainFit() const
80{
81 return m_swapchain && m_swapchain->size() == m_pipeline->mode()->size();
82}
83
84std::shared_ptr<DrmFramebuffer> DrmQPainterLayer::currentBuffer() const
85{
86 return m_currentFramebuffer;
87}
88
90{
91 return m_damageJournal.lastDamage();
92}
93
95{
96 m_swapchain.reset();
97}
98
99std::chrono::nanoseconds DrmQPainterLayer::queryRenderTime() const
100{
101 return m_renderTime;
102}
103
108
109std::optional<OutputLayerBeginFrameInfo> DrmCursorQPainterLayer::beginFrame()
110{
111 if (!m_swapchain) {
112 m_swapchain = std::make_shared<QPainterSwapchain>(m_pipeline->gpu()->graphicsBufferAllocator(), m_pipeline->gpu()->cursorSize(), DRM_FORMAT_ARGB8888);
113 }
114 m_currentBuffer = m_swapchain->acquire();
115 if (!m_currentBuffer) {
116 return std::nullopt;
117 }
118 m_renderStart = std::chrono::steady_clock::now();
120 .renderTarget = RenderTarget(m_currentBuffer->view()->image()),
121 .repaint = infiniteRegion(),
122 };
123}
124
125bool DrmCursorQPainterLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
126{
127 m_renderTime = std::chrono::steady_clock::now() - m_renderStart;
128 m_currentFramebuffer = m_pipeline->gpu()->importBuffer(m_currentBuffer->buffer(), FileDescriptor{});
129 m_swapchain->release(m_currentBuffer);
130 if (!m_currentFramebuffer) {
131 qCWarning(KWIN_DRM, "Failed to create dumb framebuffer for the cursor: %s", strerror(errno));
132 }
133 return m_currentFramebuffer != nullptr;
134}
135
137{
138 return false;
139}
140
141std::shared_ptr<DrmFramebuffer> DrmCursorQPainterLayer::currentBuffer() const
142{
143 return m_currentFramebuffer;
144}
145
147{
148 return {};
149}
150
152{
153 m_swapchain.reset();
154}
155
156std::chrono::nanoseconds DrmCursorQPainterLayer::queryRenderTime() const
157{
158 return m_renderTime;
159}
160
165
166std::optional<OutputLayerBeginFrameInfo> DrmVirtualQPainterLayer::beginFrame()
167{
168 if (m_image.isNull() || m_image.size() != m_output->modeSize()) {
169 m_image = QImage(m_output->modeSize(), QImage::Format_RGB32);
170 }
171 m_renderStart = std::chrono::steady_clock::now();
173 .renderTarget = RenderTarget(&m_image),
174 .repaint = QRegion(),
175 };
176}
177
178bool DrmVirtualQPainterLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
179{
180 m_renderTime = std::chrono::steady_clock::now() - m_renderStart;
181 m_currentDamage = damagedRegion;
182 return true;
183}
184
186{
187 return m_currentDamage;
188}
189
193
194std::chrono::nanoseconds DrmVirtualQPainterLayer::queryRenderTime() const
195{
196 return m_renderTime;
197}
198}
void add(const QRegion &region)
QRegion accumulate(int bufferAge, const QRegion &fallback=QRegion()) const
QRegion lastDamage() const
std::shared_ptr< DrmFramebuffer > currentBuffer() const override
std::chrono::nanoseconds queryRenderTime() const override
QRegion currentDamage() const override
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override
std::optional< OutputLayerBeginFrameInfo > beginFrame() override
DrmCursorQPainterLayer(DrmPipeline *pipeline)
std::shared_ptr< DrmFramebuffer > importBuffer(GraphicsBuffer *buffer, FileDescriptor &&explicitFence)
Definition drm_gpu.cpp:839
GraphicsBufferAllocator * graphicsBufferAllocator() const
Definition drm_gpu.cpp:834
QSize cursorSize() const
Definition drm_gpu.cpp:801
DrmGpu * gpu() const
std::shared_ptr< DrmConnectorMode > mode() const
DrmPipeline *const m_pipeline
Definition drm_layer.h:44
std::optional< OutputLayerBeginFrameInfo > beginFrame() override
DrmQPainterLayer(DrmPipeline *pipeline)
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override
std::chrono::nanoseconds queryRenderTime() const override
std::shared_ptr< DrmFramebuffer > currentBuffer() const override
QRegion currentDamage() const override
std::optional< OutputLayerBeginFrameInfo > beginFrame() override
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override
std::chrono::nanoseconds queryRenderTime() const override
DrmVirtualQPainterLayer(DrmVirtualOutput *output)
QRegion currentDamage() const override
QSize modeSize() const
Definition output.cpp:480
KWIN_EXPORT QRect infiniteRegion()
Definition globals.h:234