1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
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>
52 #include <QtQuick/private/qsgtexture_p.h>
53 #include <QtQuick/private/qquickpixmapcache_p.h>
55 #include <QGuiApplication>
56 #include <QOpenGLContext>
57 #include <QtGui/qopenglframebufferobject.h>
59 #include <private/qqmlglobal_p.h>
61 #include <QtQuick/private/qsgtexture_p.h>
62 #include <QtGui/private/qguiapplication_p.h>
63 #include <qpa/qplatformintegration.h>
65 #include <qpa/qplatformsharedgraphicscache.h>
67 #include <private/qobject_p.h>
70 DEFINE_BOOL_CONFIG_OPTION(qmlFlashMode, QML_FLASH_MODE)
71 DEFINE_BOOL_CONFIG_OPTION(qmlTranslucentMode, QML_TRANSLUCENT_MODE)
72 DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
75 Comments about this class from Gunnar:
77 The QSGContext class is right now two things.. The first is the
78 adaptation layer and central storage ground for all the things
79 in the scene graph, like textures and materials. This part really
80 belongs inside the scene graph coreapi.
82 The other part is the QML adaptation classes, like how to implement
83 rectangle nodes. This is not part of the scene graph core API, but
84 more part of the QML adaptation of scene graph.
86 If we ever move the scene graph core API into its own thing, this class
87 needs to be split in two. Right now its one because we're lazy when it comes
88 to defining plugin interfaces..
94 class QSGContextPrivate : public QObjectPrivate
99 , depthStencilBufferManager(0)
100 , distanceFieldCacheManager(0)
102 , distanceFieldAntialiasing(QSGGlyphNode::HighQualitySubPixelAntialiasing)
104 , distanceFieldAntialiasing(QSGGlyphNode::GrayAntialiasing)
106 , flashMode(qmlFlashMode())
107 , distanceFieldDisabled(qmlDisableDistanceField())
109 renderAlpha = qmlTranslucentMode() ? 0.5 : 1;
118 QHash<QSGMaterialType *, QSGMaterialShader *> materials;
120 QHash<QQuickTextureFactory *, QSGTexture *> textures;
121 QSGDepthStencilBufferManager *depthStencilBufferManager;
122 QSGDistanceFieldGlyphCacheManager *distanceFieldCacheManager;
124 QSGDistanceFieldGlyphNode::AntialiasingMode distanceFieldAntialiasing;
128 bool distanceFieldDisabled;
131 class QSGTextureCleanupEvent : public QEvent
134 QSGTextureCleanupEvent(QSGTexture *t) : QEvent(QEvent::User), texture(t) { }
135 ~QSGTextureCleanupEvent() { delete texture; }
142 \brief The QSGContext holds the scene graph entry points for one QML engine.
144 The context is not ready for use until it has a QOpenGLContext. Once that happens,
145 the scene graph population can start.
150 QSGContext::QSGContext(QObject *parent) :
151 QObject(*(new QSGContextPrivate), parent)
154 static bool doSubpixel = qApp->arguments().contains(QLatin1String("--text-subpixel-antialiasing"));
155 static bool doLowQualSubpixel = qApp->arguments().contains(QLatin1String("--text-subpixel-antialiasing-lowq"));
156 static bool doGray = qApp->arguments().contains(QLatin1String("--text-gray-antialiasing"));
158 d->distanceFieldAntialiasing = QSGGlyphNode::HighQualitySubPixelAntialiasing;
159 else if (doLowQualSubpixel)
160 d->distanceFieldAntialiasing = QSGGlyphNode::LowQualitySubPixelAntialiasing;
162 d->distanceFieldAntialiasing = QSGGlyphNode::GrayAntialiasing;
166 QSGContext::~QSGContext()
173 void QSGContext::invalidate()
176 d->textureMutex.lock();
177 qDeleteAll(d->textures.values());
179 d->textureMutex.unlock();
180 qDeleteAll(d->materials.values());
181 d->materials.clear();
182 delete d->depthStencilBufferManager;
183 d->depthStencilBufferManager = 0;
184 delete d->distanceFieldCacheManager;
185 d->distanceFieldCacheManager = 0;
193 QSGTexture *QSGContext::textureForFactory(QQuickTextureFactory *factory, QQuickWindow *window)
199 d->textureMutex.lock();
200 QSGTexture *texture = d->textures.value(factory);
202 if (QQuickDefaultTextureFactory *dtf = qobject_cast<QQuickDefaultTextureFactory *>(factory))
203 texture = createTexture(dtf->image());
205 texture = factory->createTexture(window);
206 d->textures.insert(factory, texture);
207 connect(factory, SIGNAL(destroyed(QObject *)), this, SLOT(textureFactoryDestroyed(QObject *)), Qt::DirectConnection);
209 d->textureMutex.unlock();
214 void QSGContext::textureFactoryDestroyed(QObject *o)
217 QQuickTextureFactory *f = static_cast<QQuickTextureFactory *>(o);
219 d->textureMutex.lock();
220 QSGTexture *t = d->textures.take(f);
221 d->textureMutex.unlock();
224 if (t->thread() == thread())
227 QCoreApplication::postEvent(this, new QSGTextureCleanupEvent(t));
232 QOpenGLContext *QSGContext::glContext() const
234 Q_D(const QSGContext);
239 Initializes the scene graph context with the GL context \a context. This also
240 emits the ready() signal so that the QML graph can start building scene graph nodes.
242 void QSGContext::initialize(QOpenGLContext *context)
254 Returns if the scene graph context is ready or not, meaning that it has a valid
257 bool QSGContext::isReady() const
259 Q_D(const QSGContext);
264 void QSGContext::renderNextFrame(QSGRenderer *renderer, GLuint fboId)
267 QSGBindableFboId bindable(fboId);
268 renderer->renderScene(bindable);
270 renderer->renderScene();
276 Factory function for scene graph backends of the Rectangle element.
278 QSGRectangleNode *QSGContext::createRectangleNode()
280 return new QSGDefaultRectangleNode;
284 Factory function for scene graph backends of the Image element.
286 QSGImageNode *QSGContext::createImageNode()
288 return new QSGDefaultImageNode;
292 Factory function for scene graph backends of the distance-field glyph cache.
294 QSGDistanceFieldGlyphCache *QSGContext::distanceFieldGlyphCache(const QRawFont &font)
298 if (!d->distanceFieldCacheManager)
299 d->distanceFieldCacheManager = new QSGDistanceFieldGlyphCacheManager;
301 QSGDistanceFieldGlyphCache *cache = d->distanceFieldCacheManager->cache(font);
303 QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
304 if (platformIntegration != 0
305 && platformIntegration->hasCapability(QPlatformIntegration::SharedGraphicsCache)) {
306 QFontEngine *fe = QRawFontPrivate::get(font)->fontEngine;
307 if (!fe->faceId().filename.isEmpty()) {
308 QByteArray keyName = fe->faceId().filename;
309 if (font.style() != QFont::StyleNormal)
310 keyName += QByteArray(" I");
311 if (font.weight() != QFont::Normal)
312 keyName += ' ' + QByteArray::number(font.weight());
313 keyName += QByteArray(" DF");
314 QPlatformSharedGraphicsCache *sharedGraphicsCache =
315 platformIntegration->createPlatformSharedGraphicsCache(keyName);
317 if (sharedGraphicsCache != 0) {
318 sharedGraphicsCache->ensureCacheInitialized(keyName,
319 QPlatformSharedGraphicsCache::OpenGLTexture,
320 QPlatformSharedGraphicsCache::Alpha8);
322 cache = new QSGSharedDistanceFieldGlyphCache(keyName,
324 d->distanceFieldCacheManager,
331 cache = new QSGDefaultDistanceFieldGlyphCache(d->distanceFieldCacheManager, glContext(), font);
332 d->distanceFieldCacheManager->insertCache(font, cache);
338 Factory function for scene graph backends of the Text elements which supports native
339 text rendering. Used in special cases where native look and feel is a main objective.
341 QSGGlyphNode *QSGContext::createNativeGlyphNode()
343 return new QSGDefaultGlyphNode;
347 Factory function for scene graph backends of the Text elements;
349 QSGGlyphNode *QSGContext::createGlyphNode()
353 if (d->distanceFieldDisabled) {
354 return createNativeGlyphNode();
356 QSGDistanceFieldGlyphNode *node = new QSGDistanceFieldGlyphNode(this);
357 node->setPreferredAntialiasingMode(d->distanceFieldAntialiasing);
363 Factory function for the scene graph renderers.
365 The renderers are used for the toplevel renderer and once for every
366 QQuickShaderEffectSource used in the QML scene.
368 QSGRenderer *QSGContext::createRenderer()
370 return new QSGDefaultRenderer(this);
376 QSurfaceFormat QSGContext::defaultSurfaceFormat() const
378 QSurfaceFormat format;
379 format.setDepthBufferSize(24);
380 format.setStencilBufferSize(8);
381 format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
387 Factory function for texture objects.
389 If \a image is a valid image, the QSGTexture::setImage function
390 will be called with \a image as argument.
393 QSGTexture *QSGContext::createTexture(const QImage &image) const
395 QSGPlainTexture *t = new QSGPlainTexture();
404 Returns the minimum supported framebuffer object size.
407 QSize QSGContext::minimumFBOSize() const
410 return QSize(33, 33);
419 Returns a shared pointer to a depth stencil buffer that can be used with \a fbo.
421 QSharedPointer<QSGDepthStencilBuffer> QSGContext::depthStencilBufferForFbo(QOpenGLFramebufferObject *fbo)
425 return QSharedPointer<QSGDepthStencilBuffer>();
426 QSGDepthStencilBufferManager *manager = depthStencilBufferManager();
427 QSGDepthStencilBuffer::Format format;
428 format.size = fbo->size();
429 format.samples = fbo->format().samples();
430 format.attachments = QSGDepthStencilBuffer::DepthAttachment | QSGDepthStencilBuffer::StencilAttachment;
431 QSharedPointer<QSGDepthStencilBuffer> buffer = manager->bufferForFormat(format);
432 if (buffer.isNull()) {
433 buffer = QSharedPointer<QSGDepthStencilBuffer>(new QSGDefaultDepthStencilBuffer(d->gl, format));
434 manager->insertBuffer(buffer);
440 Returns a pointer to the context's depth/stencil buffer manager. This is useful for custom
441 implementations of \l depthStencilBufferForFbo().
443 QSGDepthStencilBufferManager *QSGContext::depthStencilBufferManager()
448 if (!d->depthStencilBufferManager)
449 d->depthStencilBufferManager = new QSGDepthStencilBufferManager(d->gl);
450 return d->depthStencilBufferManager;
455 Returns a material shader for the given material.
458 QSGMaterialShader *QSGContext::prepareMaterial(QSGMaterial *material)
461 QSGMaterialType *type = material->type();
462 QSGMaterialShader *shader = d->materials.value(type);
466 shader = material->createShader();
468 shader->initialize();
469 d->materials[type] = shader;
477 Sets whether the scene graph should render with flashing update rectangles or not
480 void QSGContext::setFlashModeEnabled(bool enabled)
482 d_func()->flashMode = enabled;
487 Returns true if the scene graph should be rendered with flashing update rectangles
489 bool QSGContext::isFlashModeEnabled() const
491 return d_func()->flashMode;
496 Sets the toplevel opacity for rendering. This value will be multiplied into all
497 drawing calls where possible.
499 The default value is 1. Any other value will cause artifacts and is primarily
500 useful for debugging.
502 void QSGContext::setRenderAlpha(qreal renderAlpha)
504 d_func()->renderAlpha = renderAlpha;
509 Returns the toplevel opacity used for rendering.
511 The default value is 1.
515 qreal QSGContext::renderAlpha() const
517 return d_func()->renderAlpha;
522 Sets whether or not the scene graph should use the distance field technique to render text
524 void QSGContext::setDistanceFieldEnabled(bool enabled)
526 d_func()->distanceFieldDisabled = !enabled;
531 Returns true if the scene graph uses the distance field technique to render text
533 bool QSGContext::isDistanceFieldEnabled() const
535 return !d_func()->distanceFieldDisabled;
541 Creates a new animation driver.
544 QAnimationDriver *QSGContext::createAnimationDriver(QObject *parent)
546 return new QAnimationDriver(parent);