diff options
Diffstat (limited to 'src/quick/scenegraph/qsgcontext.cpp')
-rw-r--r-- | src/quick/scenegraph/qsgcontext.cpp | 591 |
1 files changed, 297 insertions, 294 deletions
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index bb8e3c4b36..afde7939f2 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -72,11 +72,8 @@ #include <private/qqmlprofilerservice_p.h> -DEFINE_BOOL_CONFIG_OPTION(qmlFlashMode, QML_FLASH_MODE) -DEFINE_BOOL_CONFIG_OPTION(qmlTranslucentMode, QML_TRANSLUCENT_MODE) DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD) - /* Comments about this class from Gunnar: @@ -94,51 +91,38 @@ DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD) to defining plugin interfaces.. */ - QT_BEGIN_NAMESPACE class QSGContextPrivate : public QObjectPrivate { public: QSGContextPrivate() - : gl(0) - , depthStencilBufferManager(0) - , distanceFieldCacheManager(0) - #if !defined(QT_OPENGL_ES) || defined(QT_OPENGL_ES_2_ANGLE) - , distanceFieldAntialiasing(QSGGlyphNode::HighQualitySubPixelAntialiasing) - #else - , distanceFieldAntialiasing(QSGGlyphNode::GrayAntialiasing) - #endif - , atlasManager(0) - , flashMode(qmlFlashMode()) + : antialiasingMethod(QSGContext::UndecidedAntialiasing) , distanceFieldDisabled(qmlDisableDistanceField()) - , msaa(false) + , distanceFieldAntialiasing( +#if !defined(QT_OPENGL_ES) || defined(QT_OPENGL_ES_2_ANGLE) + QSGGlyphNode::HighQualitySubPixelAntialiasing +#else + QSGGlyphNode::GrayAntialiasing +#endif + ) { - renderAlpha = qmlTranslucentMode() ? 0.5 : 1; } ~QSGContextPrivate() { } - QOpenGLContext *gl; - - QMutex textureMutex; - QHash<QQuickTextureFactory *, QSGTexture *> textures; - QSGDepthStencilBufferManager *depthStencilBufferManager; - QSGDistanceFieldGlyphCacheManager *distanceFieldCacheManager; - - QSGDistanceFieldGlyphNode::AntialiasingMode distanceFieldAntialiasing; - - QSGAtlasTexture::Manager *atlasManager; - - bool flashMode; - float renderAlpha; + QMutex mutex; + QSGContext::AntialiasingMethod antialiasingMethod; bool distanceFieldDisabled; + QSGDistanceFieldGlyphNode::AntialiasingMode distanceFieldAntialiasing; - bool msaa; + static QOpenGLContext *sharedOpenGLContext; }; +QOpenGLContext *QSGContextPrivate::sharedOpenGLContext = 0; + class QSGTextureCleanupEvent : public QEvent { public: @@ -188,144 +172,190 @@ QSGContext::QSGContext(QObject *parent) : QSGContext::~QSGContext() { - invalidate(); } +/*! + * This function is used by the Qt WebEngine to set up context sharing + * across multiple windows. Do not use it for any other purpose. + */ +void QSGContext::setSharedOpenGLContext(QOpenGLContext *context) +{ + QSGContextPrivate::sharedOpenGLContext = context; +} +QOpenGLContext *QSGContext::sharedOpenGLContext() +{ + return QSGContextPrivate::sharedOpenGLContext; +} -void QSGContext::invalidate() +void QSGContext::renderContextInitialized(QSGRenderContext *renderContext) { Q_D(QSGContext); - d->textureMutex.lock(); - qDeleteAll(d->textures.values()); - d->textures.clear(); - d->textureMutex.unlock(); - delete d->depthStencilBufferManager; - d->depthStencilBufferManager = 0; - delete d->distanceFieldCacheManager; - d->distanceFieldCacheManager = 0; - d->gl = 0; - - emit invalidated(); - - /* The cleanup of the atlas textures is a bit intruiging. - As part of the cleanup in the threaded render loop, we - do: - 1. call this function - 2. call QCoreApp::sendPostedEvents() to immediately process - any pending deferred deletes. - 3. delete the GL context. - As textures need the atlas manager while cleaning up, the - manager needs to be cleaned up after the textures, so - we post a deleteLater here at the very bottom so it gets - deferred deleted last. - - Another alternative would be to use a QPointer in - QSGAtlasTexture::Texture, but this seemed simpler. - */ + d->mutex.lock(); + if (d->antialiasingMethod == UndecidedAntialiasing) { + QByteArray aaType = qgetenv("QSG_ANTIALIASING_METHOD"); + if (aaType == "msaa") { + d->antialiasingMethod = MsaaAntialiasing; + } else if (aaType == "vertex") { + d->antialiasingMethod = VertexAntialiasing; + } else { + if (renderContext->openglContext()->format().samples() > 0) + d->antialiasingMethod = MsaaAntialiasing; + else + d->antialiasingMethod = VertexAntialiasing; + } + } - if (d->atlasManager) { - d->atlasManager->deleteLater(); - d->atlasManager = 0; + static bool dumped = false; + if (!dumped && qEnvironmentVariableIsSet("QSG_INFO")) { + dumped = true; + qDebug() << "GL_VENDOR: " << (const char *) glGetString(GL_VENDOR); + qDebug() << "GL_RENDERER: " << (const char *) glGetString(GL_RENDERER); + qDebug() << "GL_VERSION: " << (const char *) glGetString(GL_VERSION); + qDebug() << "GL_EXTENSIONS:\n " << QByteArray((const char *) glGetString(GL_EXTENSIONS)).replace(" ", "\n ").constData(); } + + d->mutex.unlock(); } +void QSGContext::renderContextInvalidated(QSGRenderContext *) +{ +} -QSGTexture *QSGContext::textureForFactory(QQuickTextureFactory *factory, QQuickWindow *window) +/*! + Factory function for scene graph backends of the Rectangle element. + */ +QSGRectangleNode *QSGContext::createRectangleNode() { Q_D(QSGContext); - if (!factory) - return 0; - - d->textureMutex.lock(); - QSGTexture *texture = d->textures.value(factory); - if (!texture) { - if (QQuickDefaultTextureFactory *dtf = qobject_cast<QQuickDefaultTextureFactory *>(factory)) - texture = createTexture(dtf->image()); - else - texture = factory->createTexture(window); - d->textures.insert(factory, texture); - connect(factory, SIGNAL(destroyed(QObject *)), this, SLOT(textureFactoryDestroyed(QObject *)), Qt::DirectConnection); - } - d->textureMutex.unlock(); - return texture; + return d->antialiasingMethod == MsaaAntialiasing + ? new QSGMultisampleAntialiasing::RectangleNode + : new QSGDefaultRectangleNode; } +/*! + Factory function for scene graph backends of the Image element. + */ +QSGImageNode *QSGContext::createImageNode() +{ + Q_D(QSGContext); + return d->antialiasingMethod == MsaaAntialiasing + ? new QSGMultisampleAntialiasing::ImageNode + : new QSGDefaultImageNode; +} -void QSGContext::textureFactoryDestroyed(QObject *o) +/*! + Factory function for scene graph backends of the Text elements which supports native + text rendering. Used in special cases where native look and feel is a main objective. +*/ +QSGGlyphNode *QSGContext::createNativeGlyphNode(QSGRenderContext *rc) { +#if defined(QT_OPENGL_ES) && !defined(QT_OPENGL_ES_2_ANGLE) Q_D(QSGContext); - QQuickTextureFactory *f = static_cast<QQuickTextureFactory *>(o); + if (d->distanceFieldDisabled) + return new QSGDefaultGlyphNode; + else + return createGlyphNode(rc); +#else + Q_UNUSED(rc); + return new QSGDefaultGlyphNode; +#endif +} - d->textureMutex.lock(); - QSGTexture *t = d->textures.take(f); - d->textureMutex.unlock(); +/*! + Factory function for scene graph backends of the Text elements; + */ +QSGGlyphNode *QSGContext::createGlyphNode(QSGRenderContext *rc) +{ + Q_D(QSGContext); - if (t) { - if (t->thread() == thread()) - t->deleteLater(); - else - QCoreApplication::postEvent(this, new QSGTextureCleanupEvent(t)); + if (d->distanceFieldDisabled) { + return createNativeGlyphNode(rc); + } else { + QSGDistanceFieldGlyphNode *node = new QSGDistanceFieldGlyphNode(rc); + node->setPreferredAntialiasingMode(d->distanceFieldAntialiasing); + return node; } } - -QOpenGLContext *QSGContext::glContext() const +QSurfaceFormat QSGContext::defaultSurfaceFormat() const { - Q_D(const QSGContext); - return d->gl; + QSurfaceFormat format; + format.setDepthBufferSize(24); + format.setStencilBufferSize(8); + if (QQuickWindow::hasDefaultAlphaBuffer()) + format.setAlphaBufferSize(8); + format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); + return format; } /*! - Initializes the scene graph context with the GL context \a context. This also - emits the ready() signal so that the QML graph can start building scene graph nodes. + Returns the minimum supported framebuffer object size. */ -void QSGContext::initialize(QOpenGLContext *context) + +QSize QSGContext::minimumFBOSize() const { - Q_D(QSGContext); +#ifdef Q_OS_MAC + return QSize(33, 33); +#else + return QSize(1, 1); +#endif +} - QByteArray aaType = qgetenv("QSG_ANTIALIASING_METHOD"); - if (aaType == "msaa") { - d->msaa = true; - } else if (aaType == "vertex") { - d->msaa = false; - } else { - if (context->format().samples() > 0) - d->msaa = true; - else - d->msaa = false; - } - // Sanity check the surface format, in case it was overridden by the application - QSurfaceFormat requested = defaultSurfaceFormat(); - QSurfaceFormat actual = context->format(); - if (requested.depthBufferSize() > 0 && actual.depthBufferSize() <= 0) - qWarning("QSGContext::initialize: depth buffer support missing, expect rendering errors"); - if (requested.stencilBufferSize() > 0 && actual.stencilBufferSize() <= 0) - qWarning("QSGContext::initialize: stencil buffer support missing, expect rendering errors"); - d->atlasManager = new QSGAtlasTexture::Manager(); +/*! + Sets whether or not the scene graph should use the distance field technique to render text + */ +void QSGContext::setDistanceFieldEnabled(bool enabled) +{ + d_func()->distanceFieldDisabled = !enabled; +} - Q_ASSERT(!d->gl); - d->gl = context; - emit initialized(); +/*! + Returns true if the scene graph uses the distance field technique to render text + */ +bool QSGContext::isDistanceFieldEnabled() const +{ + return !d_func()->distanceFieldDisabled; } + + /*! - Returns if the scene graph context is ready or not, meaning that it has a valid - GL context. + Creates a new animation driver. */ -bool QSGContext::isReady() const + +QAnimationDriver *QSGContext::createAnimationDriver(QObject *parent) { - Q_D(const QSGContext); - return d->gl; + return new QAnimationDriver(parent); } +QSGRenderContext::QSGRenderContext(QSGContext *context) + : m_gl(0) + , m_sg(context) + , m_atlasManager(0) + , m_depthStencilManager(0) + , m_distanceFieldCacheManager(0) + , m_brokenIBOs(false) + , m_serializedRender(false) +{ +} -void QSGContext::renderNextFrame(QSGRenderer *renderer, GLuint fboId) +QSGRenderContext::~QSGRenderContext() { + invalidate(); +} + +static QBasicMutex qsg_framerender_mutex; + +void QSGRenderContext::renderNextFrame(QSGRenderer *renderer, GLuint fboId) +{ + if (m_serializedRender) + qsg_framerender_mutex.lock(); + if (fboId) { QSGBindableFboId bindable(fboId); renderer->renderScene(bindable); @@ -333,39 +363,20 @@ void QSGContext::renderNextFrame(QSGRenderer *renderer, GLuint fboId) renderer->renderScene(); } -} + if (m_serializedRender) + qsg_framerender_mutex.unlock(); -/*! - Factory function for scene graph backends of the Rectangle element. - */ -QSGRectangleNode *QSGContext::createRectangleNode() -{ - Q_D(QSGContext); - return d->msaa ? new QSGMultisampleAntialiasing::RectangleNode - : new QSGDefaultRectangleNode; -} - -/*! - Factory function for scene graph backends of the Image element. - */ -QSGImageNode *QSGContext::createImageNode() -{ - Q_D(QSGContext); - return d->msaa ? new QSGMultisampleAntialiasing::ImageNode - : new QSGDefaultImageNode; } /*! Factory function for scene graph backends of the distance-field glyph cache. */ -QSGDistanceFieldGlyphCache *QSGContext::distanceFieldGlyphCache(const QRawFont &font) +QSGDistanceFieldGlyphCache *QSGRenderContext::distanceFieldGlyphCache(const QRawFont &font) { - Q_D(QSGContext); - - if (!d->distanceFieldCacheManager) - d->distanceFieldCacheManager = new QSGDistanceFieldGlyphCacheManager; + if (!m_distanceFieldCacheManager) + m_distanceFieldCacheManager = new QSGDistanceFieldGlyphCacheManager; - QSGDistanceFieldGlyphCache *cache = d->distanceFieldCacheManager->cache(font); + QSGDistanceFieldGlyphCache *cache = m_distanceFieldCacheManager->cache(font); if (!cache) { QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration(); if (platformIntegration != 0 @@ -387,125 +398,125 @@ QSGDistanceFieldGlyphCache *QSGContext::distanceFieldGlyphCache(const QRawFont & QPlatformSharedGraphicsCache::Alpha8); cache = new QSGSharedDistanceFieldGlyphCache(keyName, - sharedGraphicsCache, - d->distanceFieldCacheManager, - glContext(), - font); + sharedGraphicsCache, + m_distanceFieldCacheManager, + openglContext(), + font); } } } if (!cache) - cache = new QSGDefaultDistanceFieldGlyphCache(d->distanceFieldCacheManager, glContext(), font); - d->distanceFieldCacheManager->insertCache(font, cache); + cache = new QSGDefaultDistanceFieldGlyphCache(m_distanceFieldCacheManager, openglContext(), font); + m_distanceFieldCacheManager->insertCache(font, cache); } + return cache; } -/*! - Factory function for scene graph backends of the Text elements which supports native - text rendering. Used in special cases where native look and feel is a main objective. -*/ -QSGGlyphNode *QSGContext::createNativeGlyphNode() +#define QSG_RENDERCONTEXT_PROPERTY "_q_sgrendercontext" + +QSGRenderContext *QSGRenderContext::from(QOpenGLContext *context) { -#if defined(QT_OPENGL_ES) && !defined(QT_OPENGL_ES_2_ANGLE) - Q_D(QSGContext); - if (d->distanceFieldDisabled) - return new QSGDefaultGlyphNode; - else - return createGlyphNode(); -#else - return new QSGDefaultGlyphNode; -#endif + return qobject_cast<QSGRenderContext *>(context->property(QSG_RENDERCONTEXT_PROPERTY).value<QObject *>()); } -/*! - Factory function for scene graph backends of the Text elements; - */ -QSGGlyphNode *QSGContext::createGlyphNode() +void QSGRenderContext::registerFontengineForCleanup(QFontEngine *engine) { - Q_D(QSGContext); - - if (d->distanceFieldDisabled) { - return createNativeGlyphNode(); - } else { - QSGDistanceFieldGlyphNode *node = new QSGDistanceFieldGlyphNode(this); - node->setPreferredAntialiasingMode(d->distanceFieldAntialiasing); - return node; - } + m_fontEnginesToClean << engine; } /*! - Factory function for the scene graph renderers. - - The renderers are used for the toplevel renderer and once for every - QQuickShaderEffectSource used in the QML scene. + Initializes the scene graph render context with the GL context \a context. This also + emits the ready() signal so that the QML graph can start building scene graph nodes. */ -QSGRenderer *QSGContext::createRenderer() +void QSGRenderContext::initialize(QOpenGLContext *context) { - return new QSGBatchRenderer::Renderer(this); -} - - + // Sanity check the surface format, in case it was overridden by the application + QSurfaceFormat requested = m_sg->defaultSurfaceFormat(); + QSurfaceFormat actual = context->format(); + if (requested.depthBufferSize() > 0 && actual.depthBufferSize() <= 0) + qWarning("QSGContext::initialize: depth buffer support missing, expect rendering errors"); + if (requested.stencilBufferSize() > 0 && actual.stencilBufferSize() <= 0) + qWarning("QSGContext::initialize: stencil buffer support missing, expect rendering errors"); + if (!m_atlasManager) + m_atlasManager = new QSGAtlasTexture::Manager(); + + Q_ASSERT_X(!m_gl, "QSGRenderContext::initialize", "already initialized!"); + m_gl = context; + m_gl->setProperty(QSG_RENDERCONTEXT_PROPERTY, QVariant::fromValue(this)); + m_sg->renderContextInitialized(this); + +#ifdef Q_OS_LINUX + const char *vendor = (const char *) glGetString(GL_VENDOR); + if (strstr(vendor, "nouveau")) + m_brokenIBOs = true; + const char *renderer = (const char *) glGetString(GL_RENDERER); + if (strstr(renderer, "llvmpipe")) + m_serializedRender = true; +#endif -QSurfaceFormat QSGContext::defaultSurfaceFormat() const -{ - QSurfaceFormat format; - format.setDepthBufferSize(24); - format.setStencilBufferSize(8); - if (QQuickWindow::hasDefaultAlphaBuffer()) - format.setAlphaBufferSize(8); - format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); - return format; + emit initialized(); } - -/*! - Factory function for texture objects. - - If \a image is a valid image, the QSGTexture::setImage function - will be called with \a image as argument. - */ - -QSGTexture *QSGContext::createTexture(const QImage &image) const +void QSGRenderContext::invalidate() { - Q_D(const QSGContext); - QSGTexture *at = d->atlasManager->create(image); - if (at) - return at; - return createTextureNoAtlas(image); -} + if (!m_gl) + return; + + qDeleteAll(m_textures.values()); + m_textures.clear(); + + /* The cleanup of the atlas textures is a bit intriguing. + As part of the cleanup in the threaded render loop, we + do: + 1. call this function + 2. call QCoreApp::sendPostedEvents() to immediately process + any pending deferred deletes. + 3. delete the GL context. + + As textures need the atlas manager while cleaning up, the + manager needs to be cleaned up after the textures, so + we post a deleteLater here at the very bottom so it gets + deferred deleted last. + + Another alternative would be to use a QPointer in + QSGAtlasTexture::Texture, but this seemed simpler. + */ + m_atlasManager->invalidate(); + m_atlasManager->deleteLater(); + m_atlasManager = 0; + + // The following piece of code will read/write to the font engine's caches, + // potentially from different threads. However, this is safe because this + // code is only called from QQuickWindow's shutdown which is called + // only when the GUI is blocked, and multiple threads will call it in + // sequence. (see qsgdefaultglyphnode_p.cpp's init()) + for (QSet<QFontEngine *>::const_iterator it = m_fontEnginesToClean.constBegin(), + end = m_fontEnginesToClean.constEnd(); it != end; ++it) { + (*it)->clearGlyphCache(m_gl); + } + m_fontEnginesToClean.clear(); -QSGTexture *QSGContext::createTextureNoAtlas(const QImage &image) const -{ - QSGPlainTexture *t = new QSGPlainTexture(); - if (!image.isNull()) - t->setImage(image); - return t; -} + delete m_depthStencilManager; + m_depthStencilManager = 0; -/*! - Returns the minimum supported framebuffer object size. - */ - -QSize QSGContext::minimumFBOSize() const -{ -#ifdef Q_OS_MAC - return QSize(33, 33); -#else - return QSize(1, 1); -#endif -} + delete m_distanceFieldCacheManager; + m_distanceFieldCacheManager = 0; + m_gl->setProperty(QSG_RENDERCONTEXT_PROPERTY, QVariant()); + m_gl = 0; + m_sg->renderContextInvalidated(this); + emit invalidated(); +} /*! Returns a shared pointer to a depth stencil buffer that can be used with \a fbo. */ -QSharedPointer<QSGDepthStencilBuffer> QSGContext::depthStencilBufferForFbo(QOpenGLFramebufferObject *fbo) +QSharedPointer<QSGDepthStencilBuffer> QSGRenderContext::depthStencilBufferForFbo(QOpenGLFramebufferObject *fbo) { - Q_D(QSGContext); - if (!d->gl) + if (!m_gl) return QSharedPointer<QSGDepthStencilBuffer>(); QSGDepthStencilBufferManager *manager = depthStencilBufferManager(); QSGDepthStencilBuffer::Format format; @@ -514,7 +525,7 @@ QSharedPointer<QSGDepthStencilBuffer> QSGContext::depthStencilBufferForFbo(QOpen format.attachments = QSGDepthStencilBuffer::DepthAttachment | QSGDepthStencilBuffer::StencilAttachment; QSharedPointer<QSGDepthStencilBuffer> buffer = manager->bufferForFormat(format); if (buffer.isNull()) { - buffer = QSharedPointer<QSGDepthStencilBuffer>(new QSGDefaultDepthStencilBuffer(d->gl, format)); + buffer = QSharedPointer<QSGDepthStencilBuffer>(new QSGDefaultDepthStencilBuffer(m_gl, format)); manager->insertBuffer(buffer); } return buffer; @@ -524,89 +535,81 @@ QSharedPointer<QSGDepthStencilBuffer> QSGContext::depthStencilBufferForFbo(QOpen Returns a pointer to the context's depth/stencil buffer manager. This is useful for custom implementations of \l depthStencilBufferForFbo(). */ -QSGDepthStencilBufferManager *QSGContext::depthStencilBufferManager() +QSGDepthStencilBufferManager *QSGRenderContext::depthStencilBufferManager() { - Q_D(QSGContext); - if (!d->gl) + if (!m_gl) return 0; - if (!d->depthStencilBufferManager) - d->depthStencilBufferManager = new QSGDepthStencilBufferManager(d->gl); - return d->depthStencilBufferManager; + if (!m_depthStencilManager) + m_depthStencilManager = new QSGDepthStencilBufferManager(m_gl); + return m_depthStencilManager; } /*! - Sets whether the scene graph should render with flashing update rectangles or not - */ - -void QSGContext::setFlashModeEnabled(bool enabled) -{ - d_func()->flashMode = enabled; -} - + Factory function for texture objects. -/*! - Returns true if the scene graph should be rendered with flashing update rectangles + If \a image is a valid image, the QSGTexture::setImage function + will be called with \a image as argument. */ -bool QSGContext::isFlashModeEnabled() const + +QSGTexture *QSGRenderContext::createTexture(const QImage &image) const { - return d_func()->flashMode; + QSGTexture *t = m_atlasManager->create(image); + if (t) + return t; + return createTextureNoAtlas(image); } - -/*! - Sets the toplevel opacity for rendering. This value will be multiplied into all - drawing calls where possible. - - The default value is 1. Any other value will cause artifacts and is primarily - useful for debugging. - */ -void QSGContext::setRenderAlpha(qreal renderAlpha) +QSGTexture *QSGRenderContext::createTextureNoAtlas(const QImage &image) const { - d_func()->renderAlpha = renderAlpha; + QSGPlainTexture *t = new QSGPlainTexture(); + if (!image.isNull()) + t->setImage(image); + return t; } - /*! - Returns the toplevel opacity used for rendering. - - The default value is 1. + Factory function for the scene graph renderers. - \sa setRenderAlpha() + The renderers are used for the toplevel renderer and once for every + QQuickShaderEffectSource used in the QML scene. */ -qreal QSGContext::renderAlpha() const +QSGRenderer *QSGRenderContext::createRenderer() { - return d_func()->renderAlpha; + return new QSGBatchRenderer::Renderer(this); } - -/*! - Sets whether or not the scene graph should use the distance field technique to render text - */ -void QSGContext::setDistanceFieldEnabled(bool enabled) +QSGTexture *QSGRenderContext::textureForFactory(QQuickTextureFactory *factory, QQuickWindow *window) { - d_func()->distanceFieldDisabled = !enabled; -} + if (!factory) + return 0; + m_mutex.lock(); + QSGTexture *texture = m_textures.value(factory); + m_mutex.unlock(); -/*! - Returns true if the scene graph uses the distance field technique to render text - */ -bool QSGContext::isDistanceFieldEnabled() const -{ - return !d_func()->distanceFieldDisabled; -} - + if (!texture) { + if (QQuickDefaultTextureFactory *dtf = qobject_cast<QQuickDefaultTextureFactory *>(factory)) + texture = createTexture(dtf->image()); + else + texture = factory->createTexture(window); + m_mutex.lock(); + m_textures.insert(factory, texture); + m_mutex.unlock(); -/*! - Creates a new animation driver. - */ + connect(factory, SIGNAL(destroyed(QObject *)), this, SLOT(textureFactoryDestroyed(QObject *)), Qt::DirectConnection); + } + return texture; +} -QAnimationDriver *QSGContext::createAnimationDriver(QObject *parent) +void QSGRenderContext::textureFactoryDestroyed(QObject *o) { - return new QAnimationDriver(parent); + m_mutex.lock(); + QSGTexture *t = m_textures.take(static_cast<QQuickTextureFactory *>(o)); + m_mutex.unlock(); + if (t) + t->deleteLater(); } - QT_END_NAMESPACE |