Don't give move ids to moved inserts.
[profile/ivi/qtdeclarative.git] / src / declarative / scenegraph / qsgcontext.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <private/qsgcontext_p.h>
43 #include <private/qsgrenderer_p.h>
44 #include "qsgnode.h"
45
46 #include <private/qsgdefaultrenderer_p.h>
47
48 #include <private/qsgdefaultrectanglenode_p.h>
49 #include <private/qsgdefaultimagenode_p.h>
50 #include <private/qsgdefaultglyphnode_p.h>
51 #include <private/qsgdistancefieldglyphnode_p.h>
52 #include <private/qsgdistancefieldglyphcache_p.h>
53
54 #include <private/qsgtexture_p.h>
55 #include <qsgengine.h>
56
57 #include <QGuiApplication>
58 #include <QOpenGLContext>
59
60 #include <private/qobject_p.h>
61 #include <qmutex.h>
62
63 DEFINE_BOOL_CONFIG_OPTION(qmlFlashMode, QML_FLASH_MODE)
64 DEFINE_BOOL_CONFIG_OPTION(qmlTranslucentMode, QML_TRANSLUCENT_MODE)
65 DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
66
67 /*
68     Comments about this class from Gunnar:
69
70     The QSGContext class is right now two things.. The first is the
71     adaptation layer and central storage ground for all the things
72     in the scene graph, like textures and materials. This part really
73     belongs inside the scene graph coreapi.
74
75     The other part is the QML adaptation classes, like how to implement
76     rectangle nodes. This is not part of the scene graph core API, but
77     more part of the QML adaptation of scene graph.
78
79     If we ever move the scene graph core API into its own thing, this class
80     needs to be split in two. Right now its one because we're lazy when it comes
81     to defining plugin interfaces..
82 */
83
84
85 QT_BEGIN_NAMESPACE
86
87 class QSGContextPrivate : public QObjectPrivate
88 {
89 public:
90     QSGContextPrivate()
91         : rootNode(0)
92         , renderer(0)
93         , gl(0)
94         , distanceFieldCacheManager(0)
95         , flashMode(qmlFlashMode())
96         , distanceFieldDisabled(qmlDisableDistanceField())
97     {
98         renderAlpha = qmlTranslucentMode() ? 0.5 : 1;
99     }
100
101     ~QSGContextPrivate()
102     {
103     }
104
105     QSGRootNode *rootNode;
106     QSGRenderer *renderer;
107
108     QOpenGLContext *gl;
109
110     QSGEngine engine;
111
112     QHash<QSGMaterialType *, QSGMaterialShader *> materials;
113
114     QSGDistanceFieldGlyphCacheManager *distanceFieldCacheManager;
115
116     QMutex textureMutex;
117     QList<QSGTexture *> texturesToClean;
118
119     bool flashMode;
120     float renderAlpha;
121     bool distanceFieldDisabled;
122 };
123
124
125 /*!
126     \class QSGContext
127
128     \brief The QSGContext holds the scene graph entry points for one QML engine.
129
130     The context is not ready for use until it has a QOpenGLContext. Once that happens,
131     the scene graph population can start.
132
133     \internal
134  */
135
136 QSGContext::QSGContext(QObject *parent) :
137     QObject(*(new QSGContextPrivate), parent)
138 {
139     Q_D(QSGContext);
140     d->engine.setContext(this);
141 }
142
143
144 QSGContext::~QSGContext()
145 {
146     Q_D(QSGContext);
147     delete d->renderer;
148     delete d->rootNode;
149     cleanupTextures();
150     qDeleteAll(d->materials.values());
151     delete d->distanceFieldCacheManager;
152 }
153
154 /*!
155     Returns the scene graph engine for this context.
156
157     The main purpose of the QSGEngine is to serve as a public API
158     to the QSGContext.
159
160  */
161 QSGEngine *QSGContext::engine() const
162 {
163     return const_cast<QSGEngine *>(&d_func()->engine);
164 }
165
166 /*!
167     Schedules the texture to be cleaned up on the rendering thread
168     at a later time.
169
170     The texture can be considered as deleted after this function has
171     been called.
172   */
173 void QSGContext::scheduleTextureForCleanup(QSGTexture *texture)
174 {
175     Q_D(QSGContext);
176     d->textureMutex.lock();
177     Q_ASSERT(!d->texturesToClean.contains(texture));
178     d->texturesToClean << texture;
179     d->textureMutex.unlock();
180 }
181
182
183
184 /*!
185     Deletes all textures that have been scheduled for cleanup
186  */
187 void QSGContext::cleanupTextures()
188 {
189     Q_D(QSGContext);
190     d->textureMutex.lock();
191     qDeleteAll(d->texturesToClean);
192     d->texturesToClean.clear();
193     d->textureMutex.unlock();
194 }
195
196 /*!
197     Returns the renderer. The renderer instance is created through the adaptation layer.
198  */
199 QSGRenderer *QSGContext::renderer() const
200 {
201     Q_D(const QSGContext);
202     return d->renderer;
203 }
204
205
206 /*!
207     Returns the root node. The root node instance is only created once the scene graph
208     context becomes ready.
209  */
210 QSGRootNode *QSGContext::rootNode() const
211 {
212     Q_D(const QSGContext);
213     return d->rootNode;
214 }
215
216
217 QOpenGLContext *QSGContext::glContext() const
218 {
219     Q_D(const QSGContext);
220     return d->gl;
221 }
222
223 /*!
224     Initializes the scene graph context with the GL context \a context. This also
225     emits the ready() signal so that the QML graph can start building scene graph nodes.
226  */
227 void QSGContext::initialize(QOpenGLContext *context)
228 {
229     Q_D(QSGContext);
230
231     Q_ASSERT(!d->gl);
232
233     d->gl = context;
234
235     d->renderer = createRenderer();
236     d->renderer->setClearColor(Qt::white);
237
238     d->rootNode = new QSGRootNode();
239     d->renderer->setRootNode(d->rootNode);
240
241     emit ready();
242 }
243
244
245 /*!
246     Returns if the scene graph context is ready or not, meaning that it has a valid
247     GL context.
248  */
249 bool QSGContext::isReady() const
250 {
251     Q_D(const QSGContext);
252     return d->gl;
253 }
254
255
256 void QSGContext::renderNextFrame(QOpenGLFramebufferObject *fbo)
257 {
258     Q_D(QSGContext);
259
260     emit d->engine.beforeRendering();
261
262     cleanupTextures();
263
264     if (fbo) {
265         QSGBindableFbo bindable(fbo);
266         d->renderer->renderScene(bindable);
267     } else {
268         d->renderer->renderScene();
269     }
270
271     emit d->engine.afterRendering();
272
273 }
274
275 /*!
276     Factory function for scene graph backends of the Rectangle element.
277  */
278 QSGRectangleNode *QSGContext::createRectangleNode()
279 {
280     return new QSGDefaultRectangleNode(this);
281 }
282
283 /*!
284     Factory function for scene graph backends of the Image element.
285  */
286 QSGImageNode *QSGContext::createImageNode()
287 {
288     return new QSGDefaultImageNode;
289 }
290
291 /*!
292     Factory function for scene graph backends of the Text elements;
293  */
294 QSGGlyphNode *QSGContext::createGlyphNode()
295 {
296     Q_D(QSGContext);
297
298     // ### Do something with these before final release...
299     static bool doSubpixel = qApp->arguments().contains(QLatin1String("--text-subpixel-antialiasing"));
300     static bool doLowQualSubpixel = qApp->arguments().contains(QLatin1String("--text-subpixel-antialiasing-lowq"));
301     static bool doGray = qApp->arguments().contains(QLatin1String("--text-gray-antialiasing"));
302
303     if (d->distanceFieldDisabled) {
304         return new QSGDefaultGlyphNode;
305     } else {
306         if (!d->distanceFieldCacheManager) {
307             d->distanceFieldCacheManager = new QSGDistanceFieldGlyphCacheManager(d->gl);
308             if (doSubpixel)
309                 d->distanceFieldCacheManager->setDefaultAntialiasingMode(QSGGlyphNode::HighQualitySubPixelAntialiasing);
310             else if (doLowQualSubpixel)
311                 d->distanceFieldCacheManager->setDefaultAntialiasingMode(QSGGlyphNode::LowQualitySubPixelAntialiasing);
312             else if (doGray)
313                d->distanceFieldCacheManager->setDefaultAntialiasingMode(QSGGlyphNode::GrayAntialiasing);
314         }
315
316         QSGGlyphNode *node = new QSGDistanceFieldGlyphNode(d->distanceFieldCacheManager);
317         return node;
318     }
319 }
320
321 /*!
322     Factory function for the scene graph renderers.
323
324     The renderers are used for the toplevel renderer and once for every
325     QSGShaderEffectSource used in the QML scene.
326  */
327 QSGRenderer *QSGContext::createRenderer()
328 {
329     // ### Do something with this before release...
330     static bool doFrontToBack = qApp->arguments().contains(QLatin1String("--opaque-front-to-back"));
331     QSGDefaultRenderer *renderer = new QSGDefaultRenderer(this);
332     if (doFrontToBack) {
333         printf("QSGContext: Sorting opaque nodes front to back...\n");
334         renderer->setSortFrontToBackEnabled(true);
335     }
336     return renderer;
337 }
338
339
340
341 /*!
342     Return true if the image provider supports direct decoding of images,
343     straight into textures without going through a QImage first.
344
345     If the implementation returns true from this function, the decodeImageToTexture() function
346     will be called to read data from a QIODevice, rather than QML decoding
347     the image using QImageReader and passing the result to setImage().
348
349     \warning This function will be called from outside the GUI and rendering threads
350     and must not make use of OpenGL.
351  */
352
353 bool QSGContext::canDecodeImageToTexture() const
354 {
355     return true;
356 }
357
358
359
360 /*!
361     Decode the data in \a dev directly to a texture provider of \a requestSize size.
362     The size of the decoded data should be written to \a impsize.
363
364     If the implementation fails to decode the image data, it should return 0. The
365     image data will then be decoded normally.
366
367     \warning This function will be called from outside the GUI and renderer threads
368     and must not make use of GL calls.
369  */
370
371 QSGTexture *QSGContext::decodeImageToTexture(QIODevice *dev,
372                                              QSize *size,
373                                              const QSize &requestSize)
374 {
375     Q_UNUSED(dev);
376     Q_UNUSED(size);
377     Q_UNUSED(requestSize);
378     return 0;
379 }
380
381
382
383 /*!
384     Factory function for texture objects.
385
386     If \a image is a valid image, the QSGTexture::setImage function
387     will be called with \a image as argument.
388  */
389
390 QSGTexture *QSGContext::createTexture(const QImage &image) const
391 {
392     QSGPlainTexture *t = new QSGPlainTexture();
393     if (!image.isNull())
394         t->setImage(image);
395     return t;
396 }
397
398
399
400 /*!
401     Returns the minimum supported framebuffer object size.
402  */
403
404 QSize QSGContext::minimumFBOSize() const
405 {
406 #ifdef Q_WS_MAC
407     return QSize(33, 33);
408 #else
409     return QSize(1, 1);
410 #endif
411 }
412
413
414
415 /*!
416     Returns a material shader for the given material.
417  */
418
419 QSGMaterialShader *QSGContext::prepareMaterial(QSGMaterial *material)
420 {
421     Q_D(QSGContext);
422     QSGMaterialType *type = material->type();
423     QSGMaterialShader *shader = d->materials.value(type);
424     if (shader)
425         return shader;
426
427     shader = material->createShader();
428     shader->compile();
429     shader->initialize();
430     d->materials[type] = shader;
431
432     return shader;
433 }
434
435
436
437 /*!
438     Sets whether the scene graph should render with flashing update rectangles or not
439   */
440
441 void QSGContext::setFlashModeEnabled(bool enabled)
442 {
443     d_func()->flashMode = enabled;
444 }
445
446
447 /*!
448     Returns true if the scene graph should be rendered with flashing update rectangles
449  */
450 bool QSGContext::isFlashModeEnabled() const
451 {
452     return d_func()->flashMode;
453 }
454
455
456 /*!
457     Sets the toplevel opacity for rendering. This value will be multiplied into all
458     drawing calls where possible.
459
460     The default value is 1. Any other value will cause artifacts and is primarily
461     useful for debugging.
462  */
463 void QSGContext::setRenderAlpha(qreal renderAlpha)
464 {
465     d_func()->renderAlpha = renderAlpha;
466 }
467
468
469 /*!
470     Returns the toplevel opacity used for rendering.
471
472     The default value is 1.
473
474     \sa setRenderAlpha()
475  */
476 qreal QSGContext::renderAlpha() const
477 {
478     return d_func()->renderAlpha;
479 }
480
481
482 /*!
483     Sets whether or not the scene graph should use the distance field technique to render text
484   */
485 void QSGContext::setDistanceFieldEnabled(bool enabled)
486 {
487     d_func()->distanceFieldDisabled = !enabled;
488 }
489
490
491 /*!
492     Returns true if the scene graph uses the distance field technique to render text
493  */
494 bool QSGContext::isDistanceFieldEnabled() const
495 {
496     return !d_func()->distanceFieldDisabled;
497 }
498
499
500
501 /*!
502     Creates a new animation driver.
503  */
504
505 QAnimationDriver *QSGContext::createAnimationDriver(QObject *parent)
506 {
507     return new QAnimationDriver(parent);
508 }
509
510
511 QT_END_NAMESPACE