466ae5919eff69c41676d921055622aa5b0c6a13
[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     QQuickShaderEffectSource 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 QSurfaceFormat QSGContext::defaultSurfaceFormat() const
384 {
385     QSurfaceFormat format;
386     format.setDepthBufferSize(24);
387     format.setStencilBufferSize(8);
388     format.setSamples(16);
389     return format;
390 }
391
392
393 /*!
394     Factory function for texture objects.
395
396     If \a image is a valid image, the QSGTexture::setImage function
397     will be called with \a image as argument.
398  */
399
400 QSGTexture *QSGContext::createTexture(const QImage &image) const
401 {
402     QSGPlainTexture *t = new QSGPlainTexture();
403     if (!image.isNull())
404         t->setImage(image);
405     return t;
406 }
407
408
409
410 /*!
411     Returns the minimum supported framebuffer object size.
412  */
413
414 QSize QSGContext::minimumFBOSize() const
415 {
416 #ifdef Q_WS_MAC
417     return QSize(33, 33);
418 #else
419     return QSize(1, 1);
420 #endif
421 }
422
423
424
425 /*!
426     Returns a material shader for the given material.
427  */
428
429 QSGMaterialShader *QSGContext::prepareMaterial(QSGMaterial *material)
430 {
431     Q_D(QSGContext);
432     QSGMaterialType *type = material->type();
433     QSGMaterialShader *shader = d->materials.value(type);
434     if (shader)
435         return shader;
436
437     shader = material->createShader();
438     shader->compile();
439     shader->initialize();
440     d->materials[type] = shader;
441
442     return shader;
443 }
444
445
446
447 /*!
448     Sets whether the scene graph should render with flashing update rectangles or not
449   */
450
451 void QSGContext::setFlashModeEnabled(bool enabled)
452 {
453     d_func()->flashMode = enabled;
454 }
455
456
457 /*!
458     Returns true if the scene graph should be rendered with flashing update rectangles
459  */
460 bool QSGContext::isFlashModeEnabled() const
461 {
462     return d_func()->flashMode;
463 }
464
465
466 /*!
467     Sets the toplevel opacity for rendering. This value will be multiplied into all
468     drawing calls where possible.
469
470     The default value is 1. Any other value will cause artifacts and is primarily
471     useful for debugging.
472  */
473 void QSGContext::setRenderAlpha(qreal renderAlpha)
474 {
475     d_func()->renderAlpha = renderAlpha;
476 }
477
478
479 /*!
480     Returns the toplevel opacity used for rendering.
481
482     The default value is 1.
483
484     \sa setRenderAlpha()
485  */
486 qreal QSGContext::renderAlpha() const
487 {
488     return d_func()->renderAlpha;
489 }
490
491
492 /*!
493     Sets whether or not the scene graph should use the distance field technique to render text
494   */
495 void QSGContext::setDistanceFieldEnabled(bool enabled)
496 {
497     d_func()->distanceFieldDisabled = !enabled;
498 }
499
500
501 /*!
502     Returns true if the scene graph uses the distance field technique to render text
503  */
504 bool QSGContext::isDistanceFieldEnabled() const
505 {
506     return !d_func()->distanceFieldDisabled;
507 }
508
509
510
511 /*!
512     Creates a new animation driver.
513  */
514
515 QAnimationDriver *QSGContext::createAnimationDriver(QObject *parent)
516 {
517     return new QAnimationDriver(parent);
518 }
519
520
521 QT_END_NAMESPACE