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 | |
35 | QT_BEGIN_NAMESPACE_DATAVISUALIZATION |
36 | |
37 | DeclarativeRenderNode::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 | |
57 | DeclarativeRenderNode::~DeclarativeRenderNode() |
58 | { |
59 | delete m_fbo; |
60 | delete m_multisampledFBO; |
61 | delete m_texture; |
62 | |
63 | m_nodeMutex.clear(); |
64 | } |
65 | |
66 | void 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 | |
76 | void DeclarativeRenderNode::update() |
77 | { |
78 | if (m_dirtyFBO) { |
79 | updateFBO(); |
80 | m_dirtyFBO = false; |
81 | } |
82 | } |
83 | |
84 | void 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 | |
126 | void DeclarativeRenderNode::setQuickWindow(QQuickWindow *window) |
127 | { |
128 | Q_ASSERT(window); |
129 | |
130 | m_window = window; |
131 | } |
132 | |
133 | void 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 | |
143 | void DeclarativeRenderNode::setSamples(int samples) |
144 | { |
145 | if (m_samples == samples) |
146 | return; |
147 | |
148 | m_samples = samples; |
149 | m_dirtyFBO = true; |
150 | } |
151 | |
152 | void 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 |
180 | void DeclarativeRenderNode::handleControllerDestroyed() |
181 | { |
182 | m_controller = 0; |
183 | } |
184 | |
185 | QT_END_NAMESPACE_DATAVISUALIZATION |
186 | |