1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Data Visualization module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 or (at your option) any later version
20** approved by the KDE Free Qt Foundation. The licenses are as published by
21** the Free Software Foundation and appearing in the file LICENSE.GPL3
22** included in the packaging of this file. Please review the following
23** information to ensure the GNU General Public License requirements will
24** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25**
26** $QT_END_LICENSE$
27**
28****************************************************************************/
29
30#include "declarativerendernode_p.h"
31#include "abstractdeclarative_p.h"
32#include <QtGui/QOpenGLFramebufferObject>
33#include <QtCore/QMutexLocker>
34
35QT_BEGIN_NAMESPACE_DATAVISUALIZATION
36
37DeclarativeRenderNode::DeclarativeRenderNode(AbstractDeclarative *declarative,
38 const QSharedPointer<QMutex> &nodeMutex)
39 : QSGGeometryNode(),
40 m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4),
41 m_texture(0),
42 m_declarative(declarative),
43 m_controller(0),
44 m_fbo(0),
45 m_multisampledFBO(0),
46 m_window(0),
47 m_samples(0),
48 m_dirtyFBO(false)
49{
50 m_nodeMutex = nodeMutex;
51 setMaterial(&m_material);
52 setOpaqueMaterial(&m_materialO);
53 setGeometry(&m_geometry);
54 setFlag(UsePreprocess);
55}
56
57DeclarativeRenderNode::~DeclarativeRenderNode()
58{
59 delete m_fbo;
60 delete m_multisampledFBO;
61 delete m_texture;
62
63 m_nodeMutex.clear();
64}
65
66void DeclarativeRenderNode::setSize(const QSize &size)
67{
68 if (size == m_size)
69 return;
70
71 m_size = size;
72 m_dirtyFBO = true;
73 markDirty(bits: DirtyGeometry);
74}
75
76void DeclarativeRenderNode::update()
77{
78 if (m_dirtyFBO) {
79 updateFBO();
80 m_dirtyFBO = false;
81 }
82}
83
84void DeclarativeRenderNode::updateFBO()
85{
86 m_declarative->activateOpenGLContext(window: m_window);
87
88 if (m_fbo)
89 delete m_fbo;
90
91 m_fbo = new QOpenGLFramebufferObject(m_size);
92 m_fbo->setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
93
94 // Multisampled
95 if (m_multisampledFBO) {
96 delete m_multisampledFBO;
97 m_multisampledFBO = 0;
98 }
99 if (m_samples > 0) {
100 QOpenGLFramebufferObjectFormat multisampledFrambufferFormat;
101 multisampledFrambufferFormat.setSamples(m_samples);
102 multisampledFrambufferFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
103
104 m_multisampledFBO = new QOpenGLFramebufferObject(m_size, multisampledFrambufferFormat);
105 }
106
107 QSGGeometry::updateTexturedRectGeometry(g: &m_geometry,
108 rect: QRectF(0, 0,
109 m_size.width()
110 / m_controller->scene()->devicePixelRatio(),
111 m_size.height()
112 / m_controller->scene()->devicePixelRatio()),
113 sourceRect: QRectF(0, 1, 1, -1));
114
115 delete m_texture;
116 const uint id = m_fbo->texture();
117 m_texture =
118 m_window->createTextureFromNativeObject(type: QQuickWindow::NativeObjectTexture,
119 nativeObjectPtr: &id, nativeLayout: 0 /* nativeLayout */, size: m_size);
120 m_material.setTexture(m_texture);
121 m_materialO.setTexture(m_texture);
122
123 m_declarative->doneOpenGLContext(window: m_window);
124}
125
126void DeclarativeRenderNode::setQuickWindow(QQuickWindow *window)
127{
128 Q_ASSERT(window);
129
130 m_window = window;
131}
132
133void DeclarativeRenderNode::setController(Abstract3DController *controller)
134{
135 QMutexLocker locker(m_nodeMutex.data());
136 m_controller = controller;
137 if (m_controller) {
138 connect(sender: m_controller, signal: &QObject::destroyed,
139 receiver: this, slot: &DeclarativeRenderNode::handleControllerDestroyed, type: Qt::DirectConnection);
140 }
141}
142
143void DeclarativeRenderNode::setSamples(int samples)
144{
145 if (m_samples == samples)
146 return;
147
148 m_samples = samples;
149 m_dirtyFBO = true;
150}
151
152void DeclarativeRenderNode::preprocess()
153{
154 QMutexLocker locker(m_nodeMutex.data());
155
156 if (!m_controller)
157 return;
158
159 QOpenGLFramebufferObject *targetFBO;
160 if (m_samples > 0)
161 targetFBO = m_multisampledFBO;
162 else
163 targetFBO = m_fbo;
164
165 m_declarative->activateOpenGLContext(window: m_window);
166
167 targetFBO->bind();
168 // Render scene here
169 m_controller->render(defaultFboHandle: targetFBO->handle());
170
171 targetFBO->release();
172
173 if (m_samples > 0)
174 QOpenGLFramebufferObject::blitFramebuffer(target: m_fbo, source: m_multisampledFBO);
175
176 m_declarative->doneOpenGLContext(window: m_window);
177}
178
179// This function is called within m_nodeMutex lock
180void DeclarativeRenderNode::handleControllerDestroyed()
181{
182 m_controller = 0;
183}
184
185QT_END_NAMESPACE_DATAVISUALIZATION
186

source code of qtdatavis3d/src/datavisualizationqml2/declarativerendernode.cpp