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 QSize paintSize;
64 qreal paintDevicePixelRatio = 1.0;
65
66 if (paintDevice) {
67 paintSize = QSize(paintDevice->width(), paintDevice->height());
68 paintDevicePixelRatio = paintDevice->devicePixelRatio();
69 } else {
70 // For HiDPI QBackingStores, the paint device is valid between calls to
71 // beginPaint() and endPaint(). See: QTBUG-55875
72
73 m_backingStore->beginPaint(QRegion());
74
75 const QPaintDevice *backingStorePaintDevice = m_backingStore->paintDevice();
76 paintSize = QSize(backingStorePaintDevice->width(), backingStorePaintDevice->height());
77 paintDevicePixelRatio = backingStorePaintDevice->devicePixelRatio();
78
79 m_backingStore->endPaint();
80 }
81
82 QElapsedTimer renderTimer;
83
84 setBackgroundColor(clearColor());
85 setBackgroundRect(rect: QRect(0, 0,
86 paintSize.width() / paintDevicePixelRatio,
87 paintSize.height() / paintDevicePixelRatio),
88 devicePixelRatio: paintDevicePixelRatio);
89
90 // Build Renderlist
91 // The renderlist is created by visiting each node in the tree and when a
92 // renderable node is reach, we find the coorosponding RenderableNode object
93 // and append it to the renderlist. At this point the RenderableNode object
94 // should not need any further updating so it is just a matter of appending
95 // RenderableNodes
96 renderTimer.start();
97 buildRenderList();
98 qint64 buildRenderListTime = renderTimer.restart();
99
100 // Optimize Renderlist
101 // This is a pass through the renderlist to determine what actually needs to
102 // be painted. Without this pass the renderlist will simply render each item
103 // from back to front, with a high potential for overdraw. It would also lead
104 // to the entire window being flushed every frame. The objective of the
105 // optimization pass is to only paint dirty nodes that are not occuluded. A
106 // side effect of this is that additional nodes may need to be marked dirty to
107 // force a repaint. It is also important that any item that needs to be
108 // repainted only paints what is needed, via the use of clip regions.
109 const QRegion updateRegion = optimizeRenderList();
110 qint64 optimizeRenderListTime = renderTimer.restart();
111
112 // If Rendering to a backingstore, prepare it to be updated
113 bool usingBackingStore = false;
114 if (!paintDevice) {
115 m_backingStore->beginPaint(updateRegion);
116 paintDevice = m_backingStore->paintDevice();
117 usingBackingStore = true;
118 }
119
120 QPainter painter(paintDevice);
121 painter.setRenderHint(hint: QPainter::Antialiasing);
122 auto rc = static_cast<QSGSoftwareRenderContext *>(context());
123 QPainter *prevPainter = rc->m_activePainter;
124 rc->m_activePainter = &painter;
125
126 // Render the contents Renderlist
127 m_flushRegion = renderNodes(painter: &painter);
128 qint64 renderTime = renderTimer.elapsed();
129
130 painter.end();
131 if (usingBackingStore)
132 m_backingStore->endPaint();
133
134 rc->m_activePainter = prevPainter;
135 qCDebug(lcRenderer) << "render" << m_flushRegion << buildRenderListTime << optimizeRenderListTime << renderTime;
136}
137
138QT_END_NAMESPACE
139

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

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