1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "declarativerendernode_p.h"
5#include "abstractdeclarative_p.h"
6#include <QtOpenGL/QOpenGLFramebufferObject>
7#include <QtCore/QMutexLocker>
8
9QT_BEGIN_NAMESPACE
10
11DeclarativeRenderNode::DeclarativeRenderNode(AbstractDeclarative *declarative,
12 const QSharedPointer<QMutex> &nodeMutex)
13 : QSGGeometryNode(),
14 m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4),
15 m_texture(0),
16 m_declarative(declarative),
17 m_controller(0),
18 m_fbo(0),
19 m_multisampledFBO(0),
20 m_window(0),
21 m_samples(0),
22 m_dirtyFBO(false)
23{
24 m_nodeMutex = nodeMutex;
25 setMaterial(&m_material);
26 setOpaqueMaterial(&m_materialO);
27 setGeometry(&m_geometry);
28 setFlag(UsePreprocess);
29}
30
31DeclarativeRenderNode::~DeclarativeRenderNode()
32{
33 delete m_fbo;
34 delete m_multisampledFBO;
35 delete m_texture;
36
37 m_nodeMutex.clear();
38}
39
40void DeclarativeRenderNode::setSize(const QSize &size)
41{
42 if (size == m_size)
43 return;
44
45 m_size = size;
46 m_dirtyFBO = true;
47 markDirty(bits: DirtyGeometry);
48}
49
50void DeclarativeRenderNode::update()
51{
52 if (m_dirtyFBO) {
53 updateFBO();
54 m_dirtyFBO = false;
55 }
56}
57
58void DeclarativeRenderNode::updateFBO()
59{
60 m_declarative->activateOpenGLContext(window: m_window);
61
62 if (m_fbo)
63 delete m_fbo;
64
65 m_fbo = new QOpenGLFramebufferObject(m_size);
66 m_fbo->setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
67
68 // Multisampled
69 if (m_multisampledFBO) {
70 delete m_multisampledFBO;
71 m_multisampledFBO = 0;
72 }
73 if (m_samples > 0) {
74 QOpenGLFramebufferObjectFormat multisampledFrambufferFormat;
75 multisampledFrambufferFormat.setSamples(m_samples);
76 multisampledFrambufferFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
77
78 m_multisampledFBO = new QOpenGLFramebufferObject(m_size, multisampledFrambufferFormat);
79 }
80
81 QSGGeometry::updateTexturedRectGeometry(g: &m_geometry,
82 rect: QRectF(0, 0,
83 m_size.width()
84 / m_controller->scene()->devicePixelRatio(),
85 m_size.height()
86 / m_controller->scene()->devicePixelRatio()),
87 sourceRect: QRectF(0, 1, 1, -1));
88
89 delete m_texture;
90 const uint id = m_fbo->texture();
91 m_texture = QNativeInterface::QSGOpenGLTexture::fromNative(textureId: id, window: m_window, size: m_size);
92 m_material.setTexture(m_texture);
93 m_materialO.setTexture(m_texture);
94
95 m_declarative->doneOpenGLContext(window: m_window);
96}
97
98void DeclarativeRenderNode::setQuickWindow(QQuickWindow *window)
99{
100 Q_ASSERT(window);
101
102 m_window = window;
103}
104
105void DeclarativeRenderNode::setController(Abstract3DController *controller)
106{
107 QMutexLocker locker(m_nodeMutex.data());
108 m_controller = controller;
109 if (m_controller) {
110 connect(sender: m_controller, signal: &QObject::destroyed,
111 context: this, slot: &DeclarativeRenderNode::handleControllerDestroyed, type: Qt::DirectConnection);
112 }
113}
114
115void DeclarativeRenderNode::setSamples(int samples)
116{
117 if (m_samples == samples)
118 return;
119
120 m_samples = samples;
121 m_dirtyFBO = true;
122}
123
124void DeclarativeRenderNode::preprocess()
125{
126 QMutexLocker locker(m_nodeMutex.data());
127
128 if (!m_controller)
129 return;
130
131 QOpenGLFramebufferObject *targetFBO;
132 if (m_samples > 0)
133 targetFBO = m_multisampledFBO;
134 else
135 targetFBO = m_fbo;
136
137 m_declarative->activateOpenGLContext(window: m_window);
138
139 targetFBO->bind();
140 // Render scene here
141 m_controller->render(defaultFboHandle: targetFBO->handle());
142
143 targetFBO->release();
144
145 if (m_samples > 0)
146 QOpenGLFramebufferObject::blitFramebuffer(target: m_fbo, source: m_multisampledFBO);
147
148 m_declarative->doneOpenGLContext(window: m_window);
149}
150
151// This function is called within m_nodeMutex lock
152void DeclarativeRenderNode::handleControllerDestroyed()
153{
154 m_controller = 0;
155}
156
157QT_END_NAMESPACE
158

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