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, QQuickCanvas *canvas)
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(canvas);
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);
386 Factory function for texture objects.
388 If \a image is a valid image, the QSGTexture::setImage function
389 will be called with \a image as argument.
392 QSGTexture *QSGContext::createTexture(const QImage &image) const
394 QSGPlainTexture *t = new QSGPlainTexture();
403 Returns the minimum supported framebuffer object size.
406 QSize QSGContext::minimumFBOSize() const
409 return QSize(33, 33);
418 Returns a shared pointer to a depth stencil buffer that can be used with \a fbo.
420 QSharedPointer<QSGDepthStencilBuffer> QSGContext::depthStencilBufferForFbo(QOpenGLFramebufferObject *fbo)
424 return QSharedPointer<QSGDepthStencilBuffer>();
425 QSGDepthStencilBufferManager *manager = depthStencilBufferManager();
426 QSGDepthStencilBuffer::Format format;
427 format.size = fbo->size();
428 format.samples = fbo->format().samples();
429 format.attachments = QSGDepthStencilBuffer::DepthAttachment | QSGDepthStencilBuffer::StencilAttachment;
430 QSharedPointer<QSGDepthStencilBuffer> buffer = manager->bufferForFormat(format);
431 if (buffer.isNull()) {
432 buffer = QSharedPointer<QSGDepthStencilBuffer>(new QSGDefaultDepthStencilBuffer(d->gl, format));
433 manager->insertBuffer(buffer);
439 Returns a pointer to the context's depth/stencil buffer manager. This is useful for custom
440 implementations of \l depthStencilBufferForFbo().
442 QSGDepthStencilBufferManager *QSGContext::depthStencilBufferManager()
447 if (!d->depthStencilBufferManager)
448 d->depthStencilBufferManager = new QSGDepthStencilBufferManager(d->gl);
449 return d->depthStencilBufferManager;
454 Returns a material shader for the given material.
457 QSGMaterialShader *QSGContext::prepareMaterial(QSGMaterial *material)
460 QSGMaterialType *type = material->type();
461 QSGMaterialShader *shader = d->materials.value(type);
465 shader = material->createShader();
467 shader->initialize();
468 d->materials[type] = shader;
476 Sets whether the scene graph should render with flashing update rectangles or not
479 void QSGContext::setFlashModeEnabled(bool enabled)
481 d_func()->flashMode = enabled;
486 Returns true if the scene graph should be rendered with flashing update rectangles
488 bool QSGContext::isFlashModeEnabled() const
490 return d_func()->flashMode;
495 Sets the toplevel opacity for rendering. This value will be multiplied into all
496 drawing calls where possible.
498 The default value is 1. Any other value will cause artifacts and is primarily
499 useful for debugging.
501 void QSGContext::setRenderAlpha(qreal renderAlpha)
503 d_func()->renderAlpha = renderAlpha;
508 Returns the toplevel opacity used for rendering.
510 The default value is 1.
514 qreal QSGContext::renderAlpha() const
516 return d_func()->renderAlpha;
521 Sets whether or not the scene graph should use the distance field technique to render text
523 void QSGContext::setDistanceFieldEnabled(bool enabled)
525 d_func()->distanceFieldDisabled = !enabled;
530 Returns true if the scene graph uses the distance field technique to render text
532 bool QSGContext::isDistanceFieldEnabled() const
534 return !d_func()->distanceFieldDisabled;
540 Creates a new animation driver.
543 QAnimationDriver *QSGContext::createAnimationDriver(QObject *parent)
545 return new QAnimationDriver(parent);