1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qsgsoftwarerenderer_p.h"
5
6#include "qsgsoftwarerenderablenodeupdater_p.h"
7#include "qsgsoftwarerenderlistbuilder_p.h"
8#include "qsgsoftwarecontext_p.h"
9#include "qsgsoftwarerenderablenode_p.h"
10
11#include <QtGui/QPaintDevice>
12#include <QtGui/QBackingStore>
13#include <QElapsedTimer>
14
15Q_LOGGING_CATEGORY(lcRenderer, "qt.scenegraph.softwarecontext.renderer")
16
17QT_BEGIN_NAMESPACE
18
19QSGSoftwareRenderer::QSGSoftwareRenderer(QSGRenderContext *context)
20 : QSGAbstractSoftwareRenderer(context)
21 , m_paintDevice(nullptr)
22 , m_backingStore(nullptr)
23{
24}
25
26QSGSoftwareRenderer::~QSGSoftwareRenderer()
27{
28}
29
30void QSGSoftwareRenderer::setCurrentPaintDevice(QPaintDevice *device)
31{
32 m_paintDevice = device;
33 m_backingStore = nullptr;
34}
35
36QPaintDevice *QSGSoftwareRenderer::currentPaintDevice() const
37{
38 return m_paintDevice;
39}
40
41void QSGSoftwareRenderer::setBackingStore(QBackingStore *backingStore)
42{
43 m_backingStore = backingStore;
44 m_paintDevice = nullptr;
45}
46
47QRegion QSGSoftwareRenderer::flushRegion() const
48{
49 return m_flushRegion;
50}
51
52void QSGSoftwareRenderer::renderScene()
53{
54 QSGRenderer::renderScene();
55}
56
57void QSGSoftwareRenderer::render()
58{
59 if (!m_paintDevice && !m_backingStore && !m_rt.paintDevice)
60 return;
61
62 QPaintDevice *paintDevice = m_paintDevice ? m_paintDevice : m_rt.paintDevice;
63 QBackingStore *backingStore = nullptr;
64 // If no paint device and there is a backingstore, set the current paint device
65 if (!paintDevice && m_backingStore) {
66 // For HiDPI QBackingStores, the paint device is not valid
67 // until begin() has been called. See: QTBUG-55875
68 m_backingStore->beginPaint(QRegion());
69 paintDevice = m_backingStore->paintDevice();
70 m_backingStore->endPaint();
71 backingStore = m_backingStore;
72 }
73
74 QElapsedTimer renderTimer;
75
76 setBackgroundColor(clearColor());
77 setBackgroundRect(rect: QRect(0, 0,
78 paintDevice->width() / paintDevice->devicePixelRatio(),
79 paintDevice->height() / paintDevice->devicePixelRatio()),
80 devicePixelRatio: paintDevice->devicePixelRatio());
81
82 // Build Renderlist
83 // The renderlist is created by visiting each node in the tree and when a
84 // renderable node is reach, we find the coorosponding RenderableNode object
85 // and append it to the renderlist. At this point the RenderableNode object
86 // should not need any further updating so it is just a matter of appending
87 // RenderableNodes
88 renderTimer.start();
89 buildRenderList();
90 qint64 buildRenderListTime = renderTimer.restart();
91
92 // Optimize Renderlist
93 // This is a pass through the renderlist to determine what actually needs to
94 // be painted. Without this pass the renderlist will simply render each item
95 // from back to front, with a high potential for overdraw. It would also lead
96 // to the entire window being flushed every frame. The objective of the
97 // optimization pass is to only paint dirty nodes that are not occuluded. A
98 // side effect of this is that additional nodes may need to be marked dirty to
99 // force a repaint. It is also important that any item that needs to be
100 // repainted only paints what is needed, via the use of clip regions.
101 const QRegion updateRegion = optimizeRenderList();
102 qint64 optimizeRenderListTime = renderTimer.restart();
103
104 // If Rendering to a backingstore, prepare it to be updated
105 if (backingStore != nullptr) {
106 backingStore->beginPaint(updateRegion);
107 // It is possible that a QBackingStore's paintDevice() will change
108 // when begin() is called.
109 paintDevice = backingStore->paintDevice();
110 }
111
112 QPainter painter(paintDevice);
113 painter.setRenderHint(hint: QPainter::Antialiasing);
114 auto rc = static_cast<QSGSoftwareRenderContext *>(context());
115 QPainter *prevPainter = rc->m_activePainter;
116 rc->m_activePainter = &painter;
117
118 // Render the contents Renderlist
119 m_flushRegion = renderNodes(painter: &painter);
120 qint64 renderTime = renderTimer.elapsed();
121
122 painter.end();
123 if (backingStore != nullptr)
124 backingStore->endPaint();
125
126 rc->m_activePainter = prevPainter;
127 qCDebug(lcRenderer) << "render" << m_flushRegion << buildRenderListTime << optimizeRenderListTime << renderTime;
128}
129
130QT_END_NAMESPACE
131

source code of qtdeclarative/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp