834f336394f480ac22c94d14b35ecb4d89af1b67
[profile/ivi/qtdeclarative.git] / src / quick / scenegraph / qsgcontext.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
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 <QtQuick/private/qsgcontext_p.h>
43 #include <QtQuick/private/qsgdefaultrenderer_p.h>
44 #include <QtQuick/private/qsgdistancefieldutil_p.h>
45 #include <QtQuick/private/qsgdefaultdistancefieldglyphcache_p.h>
46 #include <QtQuick/private/qsgdefaultrectanglenode_p.h>
47 #include <QtQuick/private/qsgdefaultimagenode_p.h>
48 #include <QtQuick/private/qsgdefaultglyphnode_p.h>
49 #include <QtQuick/private/qsgdistancefieldglyphnode_p.h>
50 #include <QtQuick/private/qsgshareddistancefieldglyphcache_p.h>
51
52 #include <QtQuick/private/qsgtexture_p.h>
53 #include <QtQuick/private/qdeclarativepixmapcache_p.h>
54
55 #include <QGuiApplication>
56 #include <QOpenGLContext>
57
58 #include <QDeclarativeImageProvider>
59 #include <private/qdeclarativeglobal_p.h>
60
61 #include <QtQuick/private/qsgtexture_p.h>
62 #include <QtGui/private/qguiapplication_p.h>
63
64 #include <QtGui/qplatformsharedgraphicscache_qpa.h>
65
66 #include <private/qobject_p.h>
67 #include <qmutex.h>
68
69 DEFINE_BOOL_CONFIG_OPTION(qmlFlashMode, QML_FLASH_MODE)
70 DEFINE_BOOL_CONFIG_OPTION(qmlTranslucentMode, QML_TRANSLUCENT_MODE)
71 DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
72
73 /*
74     Comments about this class from Gunnar:
75
76     The QSGContext class is right now two things.. The first is the
77     adaptation layer and central storage ground for all the things
78     in the scene graph, like textures and materials. This part really
79     belongs inside the scene graph coreapi.
80
81     The other part is the QML adaptation classes, like how to implement
82     rectangle nodes. This is not part of the scene graph core API, but
83     more part of the QML adaptation of scene graph.
84
85     If we ever move the scene graph core API into its own thing, this class
86     needs to be split in two. Right now its one because we're lazy when it comes
87     to defining plugin interfaces..
88 */
89
90
91 QT_BEGIN_NAMESPACE
92
93 class QSGContextPrivate : public QObjectPrivate
94 {
95 public:
96     QSGContextPrivate()
97         : gl(0)
98         , distanceFieldCacheManager(0)
99         , flashMode(qmlFlashMode())
100         , distanceFieldDisabled(qmlDisableDistanceField())
101     {
102         renderAlpha = qmlTranslucentMode() ? 0.5 : 1;
103     }
104
105     ~QSGContextPrivate()
106     {
107     }
108
109     QOpenGLContext *gl;
110
111     QHash<QSGMaterialType *, QSGMaterialShader *> materials;
112     QHash<QDeclarativeTextureFactory *, QSGTexture *> textures;
113
114     QSGDistanceFieldGlyphCacheManager *distanceFieldCacheManager;
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 }
137
138
139 QSGContext::~QSGContext()
140 {
141     invalidate();
142 }
143
144
145
146 void QSGContext::invalidate()
147 {
148     Q_D(QSGContext);
149     qDeleteAll(d->textures.values());
150     d->textures.clear();
151     qDeleteAll(d->materials.values());
152     d->materials.clear();
153     delete d->distanceFieldCacheManager;
154     d->distanceFieldCacheManager = 0;
155
156     d->gl = 0;
157
158     emit invalidated();
159 }
160
161
162 QSGTexture *QSGContext::textureForFactory(QDeclarativeTextureFactory *factory)
163 {
164     Q_D(QSGContext);
165     if (!factory)
166         return 0;
167
168     QSGTexture *texture = d->textures.value(factory);
169     if (!texture) {
170         if (QDeclarativeDefaultTextureFactory *dtf = qobject_cast<QDeclarativeDefaultTextureFactory *>(factory))
171             texture = createTexture(dtf->image());
172         else
173             texture = factory->createTexture();
174         d->textures.insert(factory, texture);
175         connect(factory, SIGNAL(destroyed(QObject *)), this, SLOT(textureFactoryDestroyed(QObject *)));
176     }
177     return texture;
178 }
179
180
181 void QSGContext::textureFactoryDestroyed(QObject *o)
182 {
183     Q_D(QSGContext);
184     QDeclarativeTextureFactory *f = static_cast<QDeclarativeTextureFactory *>(o);
185
186     // This function will only be called on the scene graph thread, so it is
187     // safe to directly delete the texture here.
188     delete d->textures.take(f);
189 }
190
191
192 QOpenGLContext *QSGContext::glContext() const
193 {
194     Q_D(const QSGContext);
195     return d->gl;
196 }
197
198 /*!
199     Initializes the scene graph context with the GL context \a context. This also
200     emits the ready() signal so that the QML graph can start building scene graph nodes.
201  */
202 void QSGContext::initialize(QOpenGLContext *context)
203 {
204     Q_D(QSGContext);
205
206     Q_ASSERT(!d->gl);
207     d->gl = context;
208
209     emit initialized();
210 }
211
212
213 /*!
214     Returns if the scene graph context is ready or not, meaning that it has a valid
215     GL context.
216  */
217 bool QSGContext::isReady() const
218 {
219     Q_D(const QSGContext);
220     return d->gl;
221 }
222
223
224 void QSGContext::renderNextFrame(QSGRenderer *renderer, QOpenGLFramebufferObject *fbo)
225 {
226     if (fbo) {
227         QSGBindableFbo bindable(fbo);
228         renderer->renderScene(bindable);
229     } else {
230         renderer->renderScene();
231     }
232
233 }
234
235 /*!
236     Factory function for scene graph backends of the Rectangle element.
237  */
238 QSGRectangleNode *QSGContext::createRectangleNode()
239 {
240     return new QSGDefaultRectangleNode(this);
241 }
242
243 /*!
244     Factory function for scene graph backends of the Image element.
245  */
246 QSGImageNode *QSGContext::createImageNode()
247 {
248     return new QSGDefaultImageNode;
249 }
250
251 /*!
252     Factory function for scene graph backends of the distance-field glyph cache.
253  */
254 QSGDistanceFieldGlyphCache *QSGContext::createDistanceFieldGlyphCache(const QRawFont &font)
255 {
256     Q_D(QSGContext);
257
258     QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
259     if (platformIntegration != 0
260         && platformIntegration->hasCapability(QPlatformIntegration::SharedGraphicsCache)) {
261         QFontEngine *fe = QRawFontPrivate::get(font)->fontEngine;
262         if (!fe->faceId().filename.isEmpty()) {
263             QByteArray keyName = fe->faceId().filename;
264             if (font.style() != QFont::StyleNormal)
265                 keyName += QByteArray(" I");
266             if (font.weight() != QFont::Normal)
267                 keyName += " " + QByteArray::number(font.weight());
268             keyName += QByteArray(" DF");
269             QPlatformSharedGraphicsCache *sharedGraphicsCache =
270                     platformIntegration->createPlatformSharedGraphicsCache(keyName);
271
272             if (sharedGraphicsCache != 0) {
273                 sharedGraphicsCache->ensureCacheInitialized(keyName,
274                                                             QPlatformSharedGraphicsCache::OpenGLTexture,
275                                                             QPlatformSharedGraphicsCache::Alpha8);
276
277                 return new QSGSharedDistanceFieldGlyphCache(keyName,
278                                                             sharedGraphicsCache,
279                                                             d->distanceFieldCacheManager,
280                                                             glContext(),
281                                                             font);
282             }
283         }
284     }
285
286     return new QSGDefaultDistanceFieldGlyphCache(d->distanceFieldCacheManager, glContext(), font);
287 }
288
289 /*!
290     Factory function for scene graph backends of the Text elements;
291  */
292 QSGGlyphNode *QSGContext::createGlyphNode()
293 {
294     Q_D(QSGContext);
295
296     // ### Do something with these before final release...
297     static bool doSubpixel = qApp->arguments().contains(QLatin1String("--text-subpixel-antialiasing"));
298     static bool doLowQualSubpixel = qApp->arguments().contains(QLatin1String("--text-subpixel-antialiasing-lowq"));
299     static bool doGray = qApp->arguments().contains(QLatin1String("--text-gray-antialiasing"));
300
301     if (d->distanceFieldDisabled) {
302         return new QSGDefaultGlyphNode;
303     } else {
304         if (!d->distanceFieldCacheManager) {
305             d->distanceFieldCacheManager = new QSGDistanceFieldGlyphCacheManager(this);
306             if (doSubpixel)
307                 d->distanceFieldCacheManager->setDefaultAntialiasingMode(QSGGlyphNode::HighQualitySubPixelAntialiasing);
308             else if (doLowQualSubpixel)
309                 d->distanceFieldCacheManager->setDefaultAntialiasingMode(QSGGlyphNode::LowQualitySubPixelAntialiasing);
310             else if (doGray)
311                d->distanceFieldCacheManager->setDefaultAntialiasingMode(QSGGlyphNode::GrayAntialiasing);
312         }
313
314         QSGGlyphNode *node = new QSGDistanceFieldGlyphNode(d->distanceFieldCacheManager);
315         return node;
316     }
317 }
318
319 /*!
320     Factory function for the scene graph renderers.
321
322     The renderers are used for the toplevel renderer and once for every
323     QQuickShaderEffectSource used in the QML scene.
324  */
325 QSGRenderer *QSGContext::createRenderer()
326 {
327     // ### Do something with this before release...
328     static bool doFrontToBack = qApp->arguments().contains(QLatin1String("--opaque-front-to-back"));
329     QSGDefaultRenderer *renderer = new QSGDefaultRenderer(this);
330     if (doFrontToBack) {
331         printf("QSGContext: Sorting opaque nodes front to back...\n");
332         renderer->setSortFrontToBackEnabled(true);
333     }
334     return renderer;
335 }
336
337
338
339
340 QSurfaceFormat QSGContext::defaultSurfaceFormat() const
341 {
342     QSurfaceFormat format;
343     format.setDepthBufferSize(24);
344     format.setStencilBufferSize(8);
345     format.setSamples(16);
346     return format;
347 }
348
349
350 /*!
351     Factory function for texture objects.
352
353     If \a image is a valid image, the QSGTexture::setImage function
354     will be called with \a image as argument.
355  */
356
357 QSGTexture *QSGContext::createTexture(const QImage &image) const
358 {
359     QSGPlainTexture *t = new QSGPlainTexture();
360     if (!image.isNull())
361         t->setImage(image);
362     return t;
363 }
364
365
366
367 /*!
368     Returns the minimum supported framebuffer object size.
369  */
370
371 QSize QSGContext::minimumFBOSize() const
372 {
373 #ifdef Q_OS_MAC
374     return QSize(33, 33);
375 #else
376     return QSize(1, 1);
377 #endif
378 }
379
380
381
382 /*!
383     Returns a material shader for the given material.
384  */
385
386 QSGMaterialShader *QSGContext::prepareMaterial(QSGMaterial *material)
387 {
388     Q_D(QSGContext);
389     QSGMaterialType *type = material->type();
390     QSGMaterialShader *shader = d->materials.value(type);
391     if (shader)
392         return shader;
393
394     shader = material->createShader();
395     shader->compile();
396     shader->initialize();
397     d->materials[type] = shader;
398
399     return shader;
400 }
401
402
403
404 /*!
405     Sets whether the scene graph should render with flashing update rectangles or not
406   */
407
408 void QSGContext::setFlashModeEnabled(bool enabled)
409 {
410     d_func()->flashMode = enabled;
411 }
412
413
414 /*!
415     Returns true if the scene graph should be rendered with flashing update rectangles
416  */
417 bool QSGContext::isFlashModeEnabled() const
418 {
419     return d_func()->flashMode;
420 }
421
422
423 /*!
424     Sets the toplevel opacity for rendering. This value will be multiplied into all
425     drawing calls where possible.
426
427     The default value is 1. Any other value will cause artifacts and is primarily
428     useful for debugging.
429  */
430 void QSGContext::setRenderAlpha(qreal renderAlpha)
431 {
432     d_func()->renderAlpha = renderAlpha;
433 }
434
435
436 /*!
437     Returns the toplevel opacity used for rendering.
438
439     The default value is 1.
440
441     \sa setRenderAlpha()
442  */
443 qreal QSGContext::renderAlpha() const
444 {
445     return d_func()->renderAlpha;
446 }
447
448
449 /*!
450     Sets whether or not the scene graph should use the distance field technique to render text
451   */
452 void QSGContext::setDistanceFieldEnabled(bool enabled)
453 {
454     d_func()->distanceFieldDisabled = !enabled;
455 }
456
457
458 /*!
459     Returns true if the scene graph uses the distance field technique to render text
460  */
461 bool QSGContext::isDistanceFieldEnabled() const
462 {
463     return !d_func()->distanceFieldDisabled;
464 }
465
466
467
468 /*!
469     Creates a new animation driver.
470  */
471
472 QAnimationDriver *QSGContext::createAnimationDriver(QObject *parent)
473 {
474     return new QAnimationDriver(parent);
475 }
476
477
478 QT_END_NAMESPACE