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