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 QtQuick module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
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 Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #include "qsgengine_p.h" |
41 | |
42 | #include <QtQuick/qsgtexture.h> |
43 | #include <private/qsgcontext_p.h> |
44 | #include <private/qsgrenderer_p.h> |
45 | #include <private/qsgplaintexture_p.h> |
46 | |
47 | #if QT_CONFIG(opengl) |
48 | # include <QtGui/QOpenGLContext> |
49 | # include <private/qsgdefaultrendercontext_p.h> |
50 | #endif |
51 | |
52 | QT_BEGIN_NAMESPACE |
53 | |
54 | #if QT_DEPRECATED_SINCE(5, 15) |
55 | |
56 | /*! |
57 | \class QSGEngine |
58 | \brief The QSGEngine class allows low level rendering of a scene graph. |
59 | \inmodule QtQuick |
60 | \since 5.4 |
61 | |
62 | \deprecated |
63 | |
64 | A QSGEngine can be used to render a tree of QSGNode directly on a QWindow |
65 | or QOpenGLFramebufferObject without any integration with QML, QQuickWindow |
66 | or QQuickItem and the convenience that they provide. |
67 | |
68 | This means that you must handle event propagation, animation timing, |
69 | and node lifetime yourself. |
70 | |
71 | \note This class is for very low level access to an independent scene graph. |
72 | Most of the time you will instead want to subclass QQuickItem and insert |
73 | your QSGNode in a normal QtQuick scene by overriding QQuickItem::updatePaintNode(). |
74 | |
75 | \warning This class is only suitable when working directly with OpenGL. It |
76 | is not compatible with the \l{Scene Graph Adaptations}{RHI-based rendering |
77 | path}. |
78 | |
79 | \sa QSGAbstractRenderer |
80 | */ |
81 | |
82 | /*! |
83 | \enum QSGEngine::CreateTextureOption |
84 | |
85 | The CreateTextureOption enums are used to customize how a texture is wrapped. |
86 | |
87 | \value TextureHasAlphaChannel The texture has an alpha channel and should |
88 | be drawn using blending. |
89 | |
90 | \value TextureOwnsGLTexture The texture object owns the texture id and |
91 | will delete the GL texture when the texture object is deleted. |
92 | |
93 | \value TextureCanUseAtlas The image can be uploaded into a texture atlas. |
94 | |
95 | \value TextureIsOpaque The texture object is opaque. |
96 | */ |
97 | |
98 | QSGEnginePrivate::QSGEnginePrivate() |
99 | : sgContext(QSGContext::createDefaultContext()) |
100 | , sgRenderContext(sgContext.data()->createRenderContext()) |
101 | { |
102 | } |
103 | |
104 | /*! |
105 | Constructs a new QSGEngine with its \a parent |
106 | */ |
107 | QSGEngine::QSGEngine(QObject *parent) |
108 | : QObject(*(new QSGEnginePrivate), parent) |
109 | { |
110 | } |
111 | |
112 | /*! |
113 | Destroys the engine |
114 | */ |
115 | QSGEngine::~QSGEngine() |
116 | { |
117 | } |
118 | |
119 | /*! |
120 | Initialize the engine with \a context. |
121 | |
122 | \warning You have to make sure that you call |
123 | QOpenGLContext::makeCurrent() on \a context before calling this. |
124 | */ |
125 | void QSGEngine::initialize(QOpenGLContext *context) |
126 | { |
127 | Q_D(QSGEngine); |
128 | #if QT_CONFIG(opengl) |
129 | if (context && QOpenGLContext::currentContext() != context) { |
130 | qWarning(msg: "WARNING: The context must be current before calling QSGEngine::initialize." ); |
131 | return; |
132 | } |
133 | #endif |
134 | if (d->sgRenderContext && !d->sgRenderContext->isValid()) { |
135 | d->sgRenderContext->setAttachToGraphicsContext(false); |
136 | #if QT_CONFIG(opengl) |
137 | QSGDefaultRenderContext *rc = qobject_cast<QSGDefaultRenderContext *>(object: d->sgRenderContext.data()); |
138 | if (rc) { |
139 | QSGDefaultRenderContext::InitParams params; |
140 | params.sampleCount = qMax(a: 1, b: context->format().samples()); |
141 | params.openGLContext = context; |
142 | // leave the size hint and surface unset, we do not know, that's fine |
143 | rc->initialize(params: ¶ms); |
144 | } else { |
145 | d->sgRenderContext->initialize(params: nullptr); |
146 | } |
147 | #else |
148 | d->sgRenderContext->initialize(nullptr); |
149 | #endif |
150 | #if QT_CONFIG(opengl) |
151 | if (context) |
152 | connect(sender: context, signal: &QOpenGLContext::aboutToBeDestroyed, receiver: this, slot: &QSGEngine::invalidate); |
153 | #endif |
154 | } |
155 | |
156 | #if !QT_CONFIG(opengl) |
157 | Q_UNUSED(context); |
158 | #endif |
159 | } |
160 | |
161 | /*! |
162 | Invalidate the engine releasing its resources |
163 | |
164 | You will have to call initialize() and createRenderer() if you |
165 | want to use it again. |
166 | */ |
167 | void QSGEngine::invalidate() |
168 | { |
169 | Q_D(QSGEngine); |
170 | d->sgRenderContext->invalidate(); |
171 | } |
172 | |
173 | /*! |
174 | Returns a renderer that can be used to render a QSGNode tree |
175 | |
176 | You call initialize() first with the QOpenGLContext that you |
177 | want to use with this renderer. This will return a null |
178 | renderer otherwise. |
179 | */ |
180 | QSGAbstractRenderer *QSGEngine::createRenderer() const |
181 | { |
182 | Q_D(const QSGEngine); |
183 | if (!d->sgRenderContext->isValid()) |
184 | return nullptr; |
185 | |
186 | QSGRenderer *renderer = d->sgRenderContext->createRenderer(); |
187 | renderer->setCustomRenderMode(qgetenv(varName: "QSG_VISUALIZE" )); |
188 | return renderer; |
189 | } |
190 | |
191 | /*! |
192 | Creates a texture using the data of \a image |
193 | |
194 | Valid \a options are TextureCanUseAtlas and TextureIsOpaque. |
195 | |
196 | The caller takes ownership of the texture and the |
197 | texture should only be used with this engine. |
198 | |
199 | \sa createTextureFromId(), QSGSimpleTextureNode::setOwnsTexture(), QQuickWindow::createTextureFromImage() |
200 | */ |
201 | QSGTexture *QSGEngine::createTextureFromImage(const QImage &image, CreateTextureOptions options) const |
202 | { |
203 | Q_D(const QSGEngine); |
204 | if (!d->sgRenderContext->isValid()) |
205 | return nullptr; |
206 | uint flags = 0; |
207 | if (options & TextureCanUseAtlas) flags |= QSGRenderContext::CreateTexture_Atlas; |
208 | if (!(options & TextureIsOpaque)) flags |= QSGRenderContext::CreateTexture_Alpha; |
209 | return d->sgRenderContext->createTexture(image, flags); |
210 | } |
211 | |
212 | /*! |
213 | Creates a texture object that wraps the GL texture \a id uploaded with \a size |
214 | |
215 | Valid \a options are TextureHasAlphaChannel and TextureOwnsGLTexture |
216 | |
217 | The caller takes ownership of the texture object and the |
218 | texture should only be used with this engine. |
219 | |
220 | \sa createTextureFromImage(), QSGSimpleTextureNode::setOwnsTexture(), QQuickWindow::createTextureFromId() |
221 | */ |
222 | QSGTexture *QSGEngine::createTextureFromId(uint id, const QSize &size, CreateTextureOptions options) const |
223 | { |
224 | Q_D(const QSGEngine); |
225 | if (d->sgRenderContext->isValid()) { |
226 | QSGPlainTexture *texture = new QSGPlainTexture(); |
227 | texture->setTextureId(id); |
228 | texture->setHasAlphaChannel(options & TextureHasAlphaChannel); |
229 | texture->setOwnsTexture(options & TextureOwnsGLTexture); |
230 | texture->setTextureSize(size); |
231 | return texture; |
232 | } |
233 | return nullptr; |
234 | } |
235 | |
236 | /*! |
237 | Returns the current renderer interface if there is one. Otherwise null is returned. |
238 | |
239 | \sa QSGRenderNode, QSGRendererInterface |
240 | \since 5.8 |
241 | */ |
242 | QSGRendererInterface *QSGEngine::rendererInterface() const |
243 | { |
244 | Q_D(const QSGEngine); |
245 | return d->sgRenderContext->isValid() |
246 | ? d->sgRenderContext->sceneGraphContext()->rendererInterface(renderContext: d->sgRenderContext.data()) |
247 | : nullptr; |
248 | } |
249 | |
250 | /*! |
251 | Creates a simple rectangle node. When the scenegraph is not initialized, the return value is null. |
252 | |
253 | This is cross-backend alternative to constructing a QSGSimpleRectNode directly. |
254 | |
255 | \since 5.8 |
256 | \sa QSGRectangleNode |
257 | */ |
258 | QSGRectangleNode *QSGEngine::createRectangleNode() const |
259 | { |
260 | Q_D(const QSGEngine); |
261 | return d->sgRenderContext->isValid() ? d->sgRenderContext->sceneGraphContext()->createRectangleNode() : nullptr; |
262 | } |
263 | |
264 | /*! |
265 | Creates a simple image node. When the scenegraph is not initialized, the return value is null. |
266 | |
267 | This is cross-backend alternative to constructing a QSGSimpleTextureNode directly. |
268 | |
269 | \since 5.8 |
270 | \sa QSGImageNode |
271 | */ |
272 | |
273 | QSGImageNode *QSGEngine::createImageNode() const |
274 | { |
275 | Q_D(const QSGEngine); |
276 | return d->sgRenderContext->isValid() ? d->sgRenderContext->sceneGraphContext()->createImageNode() : nullptr; |
277 | } |
278 | |
279 | /*! |
280 | Creates a nine patch node. When the scenegraph is not initialized, the return value is null. |
281 | |
282 | \since 5.8 |
283 | */ |
284 | |
285 | QSGNinePatchNode *QSGEngine::createNinePatchNode() const |
286 | { |
287 | Q_D(const QSGEngine); |
288 | return d->sgRenderContext->isValid() ? d->sgRenderContext->sceneGraphContext()->createNinePatchNode() : nullptr; |
289 | } |
290 | |
291 | #endif |
292 | |
293 | QT_END_NAMESPACE |
294 | |
295 | #include "moc_qsgengine.cpp" |
296 | |