File indexing completed on 2024-11-10 04:56:33

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 #include "virtual_qpainter_backend.h"
0010 #include "core/graphicsbufferview.h"
0011 #include "core/shmgraphicsbufferallocator.h"
0012 #include "platformsupport/scenes/qpainter/qpainterswapchain.h"
0013 #include "utils/softwarevsyncmonitor.h"
0014 #include "virtual_backend.h"
0015 #include "virtual_output.h"
0016 
0017 #include <drm_fourcc.h>
0018 
0019 namespace KWin
0020 {
0021 
0022 VirtualQPainterLayer::VirtualQPainterLayer(Output *output, VirtualQPainterBackend *backend)
0023     : m_output(output)
0024     , m_backend(backend)
0025 {
0026 }
0027 
0028 VirtualQPainterLayer::~VirtualQPainterLayer()
0029 {
0030 }
0031 
0032 std::optional<OutputLayerBeginFrameInfo> VirtualQPainterLayer::beginFrame()
0033 {
0034     const QSize nativeSize(m_output->modeSize());
0035     if (!m_swapchain || m_swapchain->size() != nativeSize) {
0036         m_swapchain = std::make_unique<QPainterSwapchain>(m_backend->graphicsBufferAllocator(), nativeSize, DRM_FORMAT_XRGB8888);
0037     }
0038 
0039     m_current = m_swapchain->acquire();
0040     if (!m_current) {
0041         return std::nullopt;
0042     }
0043 
0044     m_renderStart = std::chrono::steady_clock::now();
0045     return OutputLayerBeginFrameInfo{
0046         .renderTarget = RenderTarget(m_current->view()->image()),
0047         .repaint = m_output->rect(),
0048     };
0049 }
0050 
0051 bool VirtualQPainterLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
0052 {
0053     m_renderTime = std::chrono::steady_clock::now() - m_renderStart;
0054     return true;
0055 }
0056 
0057 QImage *VirtualQPainterLayer::image()
0058 {
0059     return m_current->view()->image();
0060 }
0061 
0062 std::chrono::nanoseconds VirtualQPainterLayer::queryRenderTime() const
0063 {
0064     return m_renderTime;
0065 }
0066 
0067 VirtualQPainterBackend::VirtualQPainterBackend(VirtualBackend *backend)
0068     : m_allocator(std::make_unique<ShmGraphicsBufferAllocator>())
0069 {
0070     connect(backend, &VirtualBackend::outputAdded, this, &VirtualQPainterBackend::addOutput);
0071     connect(backend, &VirtualBackend::outputRemoved, this, &VirtualQPainterBackend::removeOutput);
0072 
0073     const auto outputs = backend->outputs();
0074     for (Output *output : outputs) {
0075         addOutput(output);
0076     }
0077 }
0078 
0079 VirtualQPainterBackend::~VirtualQPainterBackend() = default;
0080 
0081 void VirtualQPainterBackend::addOutput(Output *output)
0082 {
0083     m_outputs[output] = std::make_unique<VirtualQPainterLayer>(output, this);
0084 }
0085 
0086 void VirtualQPainterBackend::removeOutput(Output *output)
0087 {
0088     m_outputs.erase(output);
0089 }
0090 
0091 GraphicsBufferAllocator *VirtualQPainterBackend::graphicsBufferAllocator() const
0092 {
0093     return m_allocator.get();
0094 }
0095 
0096 void VirtualQPainterBackend::present(Output *output, const std::shared_ptr<OutputFrame> &frame)
0097 {
0098     static_cast<VirtualOutput *>(output)->present(frame);
0099 }
0100 
0101 VirtualQPainterLayer *VirtualQPainterBackend::primaryLayer(Output *output)
0102 {
0103     return m_outputs[output].get();
0104 }
0105 }
0106 
0107 #include "moc_virtual_qpainter_backend.cpp"