diff options
author | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2014-05-09 16:25:58 +0200 |
---|---|---|
committer | Gunnar Sletta <gunnar.sletta@jollamobile.com> | 2014-05-10 11:53:47 +0200 |
commit | 66646dd8c37adb488a79ab274b2396a649674e6d (patch) | |
tree | b0f5ac752a52cec3de1d47692e09295197622dcd /src/quick/scenegraph | |
parent | da15ea0f3b5805db657f13060c21efa78f10cde2 (diff) | |
parent | d82a17b929dd88fe76258b0f801beaa1b2ee343e (diff) |
Merge remote-tracking branch 'origin/stable' into dev
Conflicts:
.qmake.conf
src/plugins/accessible/quick/quick.pro
src/quick/items/qquickpincharea.cpp
src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
src/quick/scenegraph/qsgthreadedrenderloop.cpp
Manually adjusted for TestHTTPServer constructor change:
tests/auto/quick/qquickimage/tst_qquickimage.cpp
Change-Id: I5e58a7c08ea92d6fc5e3bce98571c54f7b2ce08f
Diffstat (limited to 'src/quick/scenegraph')
22 files changed, 204 insertions, 117 deletions
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index f525c83009..c9115f35fc 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -758,6 +758,8 @@ Renderer::Renderer(QSGRenderContext *ctx) , m_tmpOpaqueElements(16) , m_rebuild(FullRebuild) , m_zRange(0) + , m_renderOrderRebuildLower(-1) + , m_renderOrderRebuildUpper(-1) , m_currentMaterial(0) , m_currentShader(0) , m_currentClip(0) @@ -1422,8 +1424,11 @@ void Renderer::invalidateBatchAndOverlappingRenderOrders(Batch *batch) Q_ASSERT(batch); Q_ASSERT(batch->first); - int first = batch->first->order; - int last = batch->lastOrderInBatch; + if (m_renderOrderRebuildLower < 0 || batch->first->order < m_renderOrderRebuildLower) + m_renderOrderRebuildLower = batch->first->order; + if (m_renderOrderRebuildUpper < 0 || batch->lastOrderInBatch > m_renderOrderRebuildUpper) + m_renderOrderRebuildUpper = batch->lastOrderInBatch; + batch->invalidate(); for (int i=0; i<m_alphaBatches.size(); ++i) { @@ -1431,7 +1436,7 @@ void Renderer::invalidateBatchAndOverlappingRenderOrders(Batch *batch) if (b->first) { int bf = b->first->order; int bl = b->lastOrderInBatch; - if (bl > first && bf < last) + if (bl > m_renderOrderRebuildLower && bf < m_renderOrderRebuildUpper) b->invalidate(); } } @@ -1444,7 +1449,7 @@ void Renderer::invalidateBatchAndOverlappingRenderOrders(Batch *batch) */ void Renderer::cleanupBatches(QDataBuffer<Batch *> *batches) { if (batches->size()) { - std::sort(&batches->first(), &batches->last() + 1, qsg_sort_batch_is_valid); + std::stable_sort(&batches->first(), &batches->last() + 1, qsg_sort_batch_is_valid); int count = 0; while (count < batches->size() && batches->at(count)->first) ++count; @@ -2190,7 +2195,7 @@ void Renderer::renderUnmergedBatch(const Batch *batch) if (g->drawingMode() == GL_LINE_STRIP || g->drawingMode() == GL_LINE_LOOP || g->drawingMode() == GL_LINES) glLineWidth(g->lineWidth()); #if !defined(QT_OPENGL_ES_2) - else if (g->drawingMode() == GL_POINTS) + else if (!QOpenGLContext::currentContext()->isOpenGLES() && g->drawingMode() == GL_POINTS) glPointSize(g->lineWidth()); #endif @@ -2430,6 +2435,8 @@ void Renderer::render() renderBatches(); m_rebuild = 0; + m_renderOrderRebuildLower = -1; + m_renderOrderRebuildUpper = -1; if (m_visualizeMode != VisualizeNothing) visualize(); diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h index 96b99a2918..89a33cb8c4 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h @@ -506,6 +506,8 @@ private: uint m_rebuild; qreal m_zRange; + int m_renderOrderRebuildLower; + int m_renderOrderRebuildUpper; GLuint m_bufferStrategy; int m_batchNodeThreshold; diff --git a/src/quick/scenegraph/coreapi/qsggeometry.cpp b/src/quick/scenegraph/coreapi/qsggeometry.cpp index 40e0a014ab..43ff1b6240 100644 --- a/src/quick/scenegraph/coreapi/qsggeometry.cpp +++ b/src/quick/scenegraph/coreapi/qsggeometry.cpp @@ -286,6 +286,9 @@ const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_ColoredPoint2D() \sa QSGGeometryNode, {Scene Graph - Custom Geometry} + \note All classes with QSG prefix should be used solely on the scene graph's + rendering thread. See \l {Scene Graph and Rendering} for more information. + */ /*! diff --git a/src/quick/scenegraph/coreapi/qsgmaterial.cpp b/src/quick/scenegraph/coreapi/qsgmaterial.cpp index 4954fe20bb..22fe29959e 100644 --- a/src/quick/scenegraph/coreapi/qsgmaterial.cpp +++ b/src/quick/scenegraph/coreapi/qsgmaterial.cpp @@ -166,8 +166,8 @@ static bool qsg_leak_check = !qgetenv("QML_LEAK_CHECK").isEmpty(); }; \endcode - \warning Instances of QSGMaterialShader belongs to the Scene Graph rendering - thread, and cannot be used from the GUI thread. + \note All classes with QSG prefix should be used solely on the scene graph's + rendering thread. See \l {Scene Graph and Rendering} for more information. */ @@ -550,6 +550,9 @@ static void qt_print_material_count() \ingroup qtquick-scenegraph-materials It serves no purpose outside the QSGMaterial::type() function. + + \note All classes with QSG prefix should be used solely on the scene graph's + rendering thread. See \l {Scene Graph and Rendering} for more information. */ /*! @@ -585,8 +588,8 @@ static void qt_print_material_count() }; \endcode - \warning Instances of QSGMaterial belongs to the Scene Graph rendering thread, - and cannot be used from the GUI thread. + \note All classes with QSG prefix should be used solely on the scene graph's + rendering thread. See \l {Scene Graph and Rendering} for more information. */ /*! diff --git a/src/quick/scenegraph/coreapi/qsgnode.cpp b/src/quick/scenegraph/coreapi/qsgnode.cpp index 5c196b252c..b0a4f20149 100644 --- a/src/quick/scenegraph/coreapi/qsgnode.cpp +++ b/src/quick/scenegraph/coreapi/qsgnode.cpp @@ -99,8 +99,8 @@ static void qt_print_node_count() together. Nodes in a blocked subtree will not be preprocessed() and not rendered. - \warning Anything related to QSGNode should happen on the scene graph - rendering thread. + \note All classes with QSG prefix should be used solely on the scene graph's + rendering thread. See \l {Scene Graph and Rendering} for more information. */ /*! @@ -683,6 +683,9 @@ void qsgnode_set_description(QSGNode *node, const QString &description) The QSGBasicGeometryNode class should not be used by itself. It is only encapsulates shared functionality between the QSGGeometryNode and QSGClipNode classes. + + \note All classes with QSG prefix should be used solely on the scene graph's + rendering thread. See \l {Scene Graph and Rendering} for more information. */ @@ -824,6 +827,9 @@ void QSGBasicGeometryNode::setGeometry(QSGGeometry *geometry) to avoid an extra operation in the fragment shader can have significant performance impact on embedded graphics chips. The opaque material is optional. + \note All classes with QSG prefix should be used solely on the scene graph's + rendering thread. See \l {Scene Graph and Rendering} for more information. + \sa QSGGeometry, QSGMaterial, QSGSimpleMaterial */ @@ -1036,6 +1042,9 @@ void QSGGeometryNode::setInheritedOpacity(qreal opacity) Clip nodes must have a geometry before they can be added to the scene graph. Clipping is usually implemented by using the stencil buffer. + + \note All classes with QSG prefix should be used solely on the scene graph's + rendering thread. See \l {Scene Graph and Rendering} for more information. */ @@ -1127,6 +1136,10 @@ void QSGClipNode::setClipRect(const QRectF &rect) transformations. However, because the renderer optimizes for 2D use-cases rather than 3D use-cases, rendering a scene with full 3D transformations needs to be done with some care. + + \note All classes with QSG prefix should be used solely on the scene graph's + rendering thread. See \l {Scene Graph and Rendering} for more information. + */ @@ -1264,6 +1277,8 @@ void QSGRootNode::notifyNodeChange(QSGNode *node, DirtyState state) be marked as blocked, causing isSubtreeBlocked() to return true. This is done for performance reasons. + \note All classes with QSG prefix should be used solely on the scene graph's + rendering thread. See \l {Scene Graph and Rendering} for more information. */ diff --git a/src/quick/scenegraph/coreapi/qsgrenderer_p.h b/src/quick/scenegraph/coreapi/qsgrenderer_p.h index 55c9444365..eddd38a68f 100644 --- a/src/quick/scenegraph/coreapi/qsgrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgrenderer_p.h @@ -134,6 +134,8 @@ public: virtual void setCustomRenderMode(const QByteArray &) { }; + void clearChangedFlag() { m_changed_emitted = false; } + Q_SIGNALS: void sceneGraphChanged(); // Add, remove, ChangeFlags changes... diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index 9f7818a442..64506d1c26 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -99,13 +99,8 @@ public: QSGContextPrivate() : antialiasingMethod(QSGContext::UndecidedAntialiasing) , distanceFieldDisabled(qmlDisableDistanceField()) - , distanceFieldAntialiasing( -#if !defined(QT_OPENGL_ES) || defined(QT_OPENGL_ES_2_ANGLE) - QSGGlyphNode::HighQualitySubPixelAntialiasing -#else - QSGGlyphNode::GrayAntialiasing -#endif - ) + , distanceFieldAntialiasing(QSGGlyphNode::HighQualitySubPixelAntialiasing) + , distanceFieldAntialiasingDecided(false) { } @@ -117,12 +112,9 @@ public: QSGContext::AntialiasingMethod antialiasingMethod; bool distanceFieldDisabled; QSGDistanceFieldGlyphNode::AntialiasingMode distanceFieldAntialiasing; - - static QOpenGLContext *sharedOpenGLContext; + bool distanceFieldAntialiasingDecided; }; -QOpenGLContext *QSGContextPrivate::sharedOpenGLContext = 0; - class QSGTextureCleanupEvent : public QEvent { public: @@ -161,6 +153,8 @@ QSGContext::QSGContext(QObject *parent) : { Q_D(QSGContext); QByteArray mode = qgetenv("QSG_DISTANCEFIELD_ANTIALIASING"); + if (!mode.isEmpty()) + d->distanceFieldAntialiasingDecided = true; if (mode == "subpixel") d->distanceFieldAntialiasing = QSGGlyphNode::HighQualitySubPixelAntialiasing; else if (mode == "subpixel-lowq") @@ -179,20 +173,6 @@ QSGRenderContext *QSGContext::createRenderContext() return new QSGRenderContext(this); } -/*! - * 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::renderContextInitialized(QSGRenderContext *renderContext) { Q_D(QSGContext); @@ -212,6 +192,17 @@ void QSGContext::renderContextInitialized(QSGRenderContext *renderContext) } } + // With OpenGL ES, except for Angle on Windows, use GrayAntialiasing, unless + // some value had been requested explicitly. This could not be decided + // before without a context. Now the context is ready. + if (!d->distanceFieldAntialiasingDecided) { + d->distanceFieldAntialiasingDecided = true; +#ifndef Q_OS_WIN + if (renderContext->openglContext()->isOpenGLES()) + d->distanceFieldAntialiasing = QSGGlyphNode::GrayAntialiasing; +#endif + } + static bool dumped = false; if (!dumped && qEnvironmentVariableIsSet("QSG_INFO")) { dumped = true; diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h index 2ab78ce289..ac372b9718 100644 --- a/src/quick/scenegraph/qsgcontext_p.h +++ b/src/quick/scenegraph/qsgcontext_p.h @@ -168,9 +168,6 @@ public: virtual QSize minimumFBOSize() const; virtual QSurfaceFormat defaultSurfaceFormat() const; - static void setSharedOpenGLContext(QOpenGLContext *context); - static QOpenGLContext *sharedOpenGLContext(); - void setDistanceFieldEnabled(bool enabled); bool isDistanceFieldEnabled() const; diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp index a625eebd5d..48b405467b 100644 --- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp +++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp @@ -231,7 +231,8 @@ void QSGDefaultDistanceFieldGlyphCache::createTexture(TextureInfo *texInfo, int glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); #if !defined(QT_OPENGL_ES_2) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + if (!QOpenGLContext::currentContext()->isOpenGLES()) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); const GLint internalFormat = isCoreProfile() ? GL_R8 : GL_ALPHA; const GLenum format = isCoreProfile() ? GL_RED : GL_ALPHA; #else @@ -373,7 +374,8 @@ void QSGDefaultDistanceFieldGlyphCache::resizeTexture(TextureInfo *texInfo, int glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); #if !defined(QT_OPENGL_ES_2) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + if (!ctx->isOpenGLES()) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); #endif glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, oldWidth, oldHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); diff --git a/src/quick/scenegraph/qsgdefaultimagenode.cpp b/src/quick/scenegraph/qsgdefaultimagenode.cpp index 926c0c1f4a..d925b1c7c4 100644 --- a/src/quick/scenegraph/qsgdefaultimagenode.cpp +++ b/src/quick/scenegraph/qsgdefaultimagenode.cpp @@ -307,13 +307,11 @@ void QSGDefaultImageNode::preprocess() markDirty(DirtyMaterial); } -#ifdef QT_OPENGL_ES_2 inline static bool isPowerOfTwo(int x) { // Assumption: x >= 1 return x == (x & -x); } -#endif namespace { struct X { float x, tx; }; @@ -360,15 +358,18 @@ void QSGDefaultImageNode::updateGeometry() bool hasTiles = hTiles != 1 || vTiles != 1; bool fullTexture = innerSourceRect == QRectF(0, 0, 1, 1); -#ifdef QT_OPENGL_ES_2 - QOpenGLContext *ctx = QOpenGLContext::currentContext(); - bool npotSupported = ctx->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat); - QSize size = t->textureSize(); - bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height()); - bool wrapSupported = npotSupported || !isNpot; -#else bool wrapSupported = true; + + QOpenGLContext *ctx = QOpenGLContext::currentContext(); +#ifndef QT_OPENGL_ES_2 + if (ctx->isOpenGLES()) #endif + { + bool npotSupported = ctx->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat); + QSize size = t->textureSize(); + const bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height()); + wrapSupported = npotSupported || !isNpot; + } // An image can be rendered as a single quad if: // - There are no margins, and either: diff --git a/src/quick/scenegraph/qsgdefaultrectanglenode.cpp b/src/quick/scenegraph/qsgdefaultrectanglenode.cpp index 810a503cee..467f454d0f 100644 --- a/src/quick/scenegraph/qsgdefaultrectanglenode.cpp +++ b/src/quick/scenegraph/qsgdefaultrectanglenode.cpp @@ -289,10 +289,22 @@ void QSGDefaultRectangleNode::update() if (m_dirty_geometry) { updateGeometry(); m_dirty_geometry = false; + + QSGNode::DirtyState state = QSGNode::DirtyGeometry; + // smoothed material is always blended, so no change in material state + if (material() == &m_material) { + bool wasBlending = (m_material.flags() & QSGMaterial::Blending); + bool isBlending = (m_gradient_stops.size() > 0 && !m_gradient_is_opaque) + || (m_color.alpha() < 255 && m_color.alpha() != 0) + || (m_pen_width > 0 && m_border_color.alpha() < 255); + if (wasBlending != isBlending) { + m_material.setFlag(QSGMaterial::Blending, isBlending); + state |= QSGNode::DirtyMaterial; + } + } + + markDirty(state); } - m_material.setFlag(QSGMaterial::Blending, (m_gradient_stops.size() > 0 && !m_gradient_is_opaque) - || (m_color.alpha() < 255 && m_color.alpha() != 0) - || (m_pen_width > 0 && m_border_color.alpha() < 255)); } void QSGDefaultRectangleNode::updateGeometry() @@ -770,8 +782,6 @@ void QSGDefaultRectangleNode::updateGeometry() Q_ASSERT(outerAATail == indexCount); } } - - markDirty(DirtyGeometry); } diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index 00e67aa944..38de4a5c39 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -45,7 +45,6 @@ #include <QtCore/QCoreApplication> #include <QtCore/QTime> -#include <QtCore/QScopedPointer> #include <QtCore/QLibraryInfo> #include <QtCore/private/qabstractanimation_p.h> @@ -82,12 +81,27 @@ extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_ DEFINE_BOOL_CONFIG_OPTION(qmlNoThreadedRenderer, QML_BAD_GUI_RENDER_LOOP); DEFINE_BOOL_CONFIG_OPTION(qmlForceThreadedRenderer, QML_FORCE_THREADED_RENDERER); // Might trigger graphics driver threading bugs, use at own risk -Q_GLOBAL_STATIC(QScopedPointer<QSGRenderLoop>, s_renderLoopInstance); +QSGRenderLoop *QSGRenderLoop::s_instance = 0; QSGRenderLoop::~QSGRenderLoop() { } +void QSGRenderLoop::cleanup() +{ + if (!s_instance) + return; + foreach (QQuickWindow *w, s_instance->windows()) { + QQuickWindowPrivate *wd = QQuickWindowPrivate::get(w); + if (wd->windowManager == s_instance) { + s_instance->windowDestroyed(w); + wd->windowManager = 0; + } + } + delete s_instance; + s_instance = 0; +} + class QSGGuiThreadRenderLoop : public QSGRenderLoop { Q_OBJECT @@ -148,8 +162,8 @@ bool QSGRenderLoop::useConsistentTiming() QSGRenderLoop *QSGRenderLoop::instance() { - if (s_renderLoopInstance->isNull()) { - s_renderLoopInstance->reset(QSGContext::createWindowManager()); + if (!s_instance) { + s_instance = QSGContext::createWindowManager(); bool info = qEnvironmentVariableIsSet("QSG_INFO"); @@ -159,7 +173,7 @@ QSGRenderLoop *QSGRenderLoop::instance() qDebug() << "QSG: using fixed animation steps"; } - if (s_renderLoopInstance->isNull()) { + if (!s_instance) { enum RenderLoopType { BasicRenderLoop, @@ -191,26 +205,28 @@ QSGRenderLoop *QSGRenderLoop::instance() switch (loopType) { case ThreadedRenderLoop: if (info) qDebug() << "QSG: threaded render loop"; - s_renderLoopInstance->reset(new QSGThreadedRenderLoop()); + s_instance = new QSGThreadedRenderLoop(); break; case WindowsRenderLoop: if (info) qDebug() << "QSG: windows render loop"; - s_renderLoopInstance->reset(new QSGWindowsRenderLoop()); + s_instance = new QSGWindowsRenderLoop(); break; default: if (info) qDebug() << "QSG: basic render loop"; - s_renderLoopInstance->reset(new QSGGuiThreadRenderLoop()); + s_instance = new QSGGuiThreadRenderLoop(); break; } } + + qAddPostRoutine(QSGRenderLoop::cleanup); } - return s_renderLoopInstance->data(); + return s_instance; } void QSGRenderLoop::setInstance(QSGRenderLoop *instance) { - Q_ASSERT(s_renderLoopInstance->isNull()); - s_renderLoopInstance->reset(instance); + Q_ASSERT(!s_instance); + s_instance = instance; } void QSGRenderLoop::handleContextCreationFailure(QQuickWindow *window, @@ -295,6 +311,8 @@ void QSGGuiThreadRenderLoop::windowDestroyed(QQuickWindow *window) QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); delete gl; gl = 0; + } else if (window == gl->surface()) { + gl->doneCurrent(); } } @@ -311,10 +329,10 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window) if (!gl) { gl = new QOpenGLContext(); gl->setFormat(window->requestedFormat()); - if (QSGContext::sharedOpenGLContext()) - gl->setShareContext(QSGContext::sharedOpenGLContext()); + if (QOpenGLContextPrivate::globalShareContext()) + gl->setShareContext(QOpenGLContextPrivate::globalShareContext()); if (!gl->create()) { - const bool isEs = gl->isES(); + const bool isEs = gl->isOpenGLES(); delete gl; gl = 0; handleContextCreationFailure(window, isEs); @@ -361,7 +379,7 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window) renderTime = renderTimer.nsecsElapsed() - syncTime; if (data.grabOnly) { - grabContent = qt_gl_read_framebuffer(window->size(), false, false); + grabContent = qt_gl_read_framebuffer(window->size() * window->devicePixelRatio(), false, false); data.grabOnly = false; } diff --git a/src/quick/scenegraph/qsgrenderloop_p.h b/src/quick/scenegraph/qsgrenderloop_p.h index 2418af4157..8d5312b188 100644 --- a/src/quick/scenegraph/qsgrenderloop_p.h +++ b/src/quick/scenegraph/qsgrenderloop_p.h @@ -44,6 +44,7 @@ #include <QtGui/QImage> #include <private/qtquickglobal_p.h> +#include <QtCore/QSet> QT_BEGIN_NAMESPACE @@ -78,6 +79,10 @@ public: virtual void releaseResources(QQuickWindow *window) = 0; + void addWindow(QQuickWindow *win) { m_windows.insert(win); } + void removeWindow(QQuickWindow *win) { m_windows.remove(win); } + QSet<QQuickWindow *> windows() const { return m_windows; } + // ### make this less of a singleton static QSGRenderLoop *instance(); static void setInstance(QSGRenderLoop *instance); @@ -86,11 +91,18 @@ public: virtual bool interleaveIncubation() const { return false; } + static void cleanup(); + Q_SIGNALS: void timeToIncubate(); protected: void handleContextCreationFailure(QQuickWindow *window, bool isEs); + +private: + static QSGRenderLoop *s_instance; + + QSet<QQuickWindow *> m_windows; }; QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index a5b46b7c75..1ba54ea19e 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -62,6 +62,7 @@ #include <private/qquickanimatorcontroller_p.h> #include <private/qquickprofiler_p.h> +#include <private/qqmldebugservice_p.h> /* Overall design: @@ -428,7 +429,7 @@ bool QSGRenderThread::event(QEvent *e) QQuickWindowPrivate::get(window)->renderSceneGraph(windowSize); QSG_RT_DEBUG(" - grabbing result..."); - *ce->image = qt_gl_read_framebuffer(windowSize, false, false); + *ce->image = qt_gl_read_framebuffer(windowSize * window->devicePixelRatio(), false, false); } QSG_RT_DEBUG(" - waking gui to handle grab result"); waitCondition.wakeOne(); @@ -513,6 +514,10 @@ void QSGRenderThread::sync(bool inExpose) if (current) { QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); bool hadRenderer = d->renderer != 0; + // If the scene graph was touched since the last sync() make sure it sends the + // changed signal. + if (d->renderer) + d->renderer->clearChangedFlag(); d->syncSceneGraph(); if (!hadRenderer && d->renderer) { QSG_RT_DEBUG(" - renderer was created, hooking up changed signal"); @@ -663,6 +668,8 @@ void QSGRenderThread::run() animatorDriver = sgrc->sceneGraphContext()->createAnimationDriver(0); animatorDriver->install(); QUnifiedTimer::instance(true)->setConsistentTiming(QSGRenderLoop::useConsistentTiming()); + if (QQmlDebugService::isDebuggingEnabled()) + QQuickProfiler::registerAnimationCallback(); while (active) { @@ -791,8 +798,6 @@ void QSGThreadedRenderLoop::startOrStopAnimationTimer() } } - - /* Removes this window from the list of tracked windowes in this window manager. hide() will trigger obscure, which in turn will @@ -873,6 +878,7 @@ void QSGThreadedRenderLoop::handleExposure(QQuickWindow *window) QSG_GUI_DEBUG(window, " - adding window to list"); Window win; win.window = window; + win.actualWindowFormat = window->format(); win.thread = new QSGRenderThread(this, QQuickWindowPrivate::get(window)->context); win.timerId = 0; win.updateDuringSync = false; @@ -899,11 +905,11 @@ void QSGThreadedRenderLoop::handleExposure(QQuickWindow *window) if (!w->thread->gl) { w->thread->gl = new QOpenGLContext(); - if (QSGContext::sharedOpenGLContext()) - w->thread->gl->setShareContext(QSGContext::sharedOpenGLContext()); + if (QOpenGLContextPrivate::globalShareContext()) + w->thread->gl->setShareContext(QOpenGLContextPrivate::globalShareContext()); w->thread->gl->setFormat(w->window->requestedFormat()); if (!w->thread->gl->create()) { - const bool isEs = w->thread->gl->isES(); + const bool isEs = w->thread->gl->isOpenGLES(); delete w->thread->gl; w->thread->gl = 0; handleContextCreationFailure(w->window, isEs); @@ -1045,7 +1051,7 @@ void QSGThreadedRenderLoop::releaseResources(Window *w, bool inDestructor) if (!window->handle()) { QSG_GUI_DEBUG(window, " - using fallback surface"); fallback = new QOffscreenSurface(); - fallback->setFormat(window->requestedFormat()); + fallback->setFormat(w->actualWindowFormat); fallback->create(); } diff --git a/src/quick/scenegraph/qsgthreadedrenderloop_p.h b/src/quick/scenegraph/qsgthreadedrenderloop_p.h index 970bd63040..b86b3c73a4 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop_p.h +++ b/src/quick/scenegraph/qsgthreadedrenderloop_p.h @@ -87,6 +87,7 @@ private: struct Window { QQuickWindow *window; QSGRenderThread *thread; + QSurfaceFormat actualWindowFormat; int timerId; uint updateDuringSync : 1; }; diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp index 32f52417bb..dc12d00490 100644 --- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp +++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp @@ -179,11 +179,11 @@ void QSGWindowsRenderLoop::show(QQuickWindow *window) RLDEBUG(" - creating GL context"); m_gl = new QOpenGLContext(); m_gl->setFormat(window->requestedFormat()); - if (QSGContext::sharedOpenGLContext()) - m_gl->setShareContext(QSGContext::sharedOpenGLContext()); + if (QOpenGLContextPrivate::globalShareContext()) + m_gl->setShareContext(QOpenGLContextPrivate::globalShareContext()); bool created = m_gl->create(); if (!created) { - const bool isEs = m_gl->isES(); + const bool isEs = m_gl->isOpenGLES(); delete m_gl; m_gl = 0; handleContextCreationFailure(window, isEs); @@ -341,7 +341,7 @@ QImage QSGWindowsRenderLoop::grab(QQuickWindow *window) d->syncSceneGraph(); d->renderSceneGraph(window->size()); - QImage image = qt_gl_read_framebuffer(window->size(), false, false); + QImage image = qt_gl_read_framebuffer(window->size() * window->devicePixelRatio(), false, false); return image; } diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp index 99d1d60258..1ff7d11162 100644 --- a/src/quick/scenegraph/util/qsgatlastexture.cpp +++ b/src/quick/scenegraph/util/qsgatlastexture.cpp @@ -143,7 +143,13 @@ Atlas::Atlas(const QSize &size) , m_allocated(false) { -#ifdef QT_OPENGL_ES + m_internalFormat = GL_RGBA; + m_externalFormat = GL_BGRA; + +#ifndef QT_OPENGL_ES + if (QOpenGLContext::currentContext()->isOpenGLES()) { +#endif + #if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK) QString *deviceName = static_cast<QString *>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("AndroidDeviceName")); @@ -153,7 +159,7 @@ Atlas::Atlas(const QSize &size) || deviceName->compare(QStringLiteral("samsung SM-T215"), Qt::CaseInsensitive) == 0); #else static bool wrongfullyReportsBgra8888Support = false; -#endif +#endif // ANDROID const char *ext = (const char *) glGetString(GL_EXTENSIONS); if (!wrongfullyReportsBgra8888Support @@ -165,13 +171,13 @@ Atlas::Atlas(const QSize &size) } else if (strstr(ext, "GL_APPLE_texture_format_BGRA8888")) { m_internalFormat = GL_RGBA; m_externalFormat = GL_BGRA; -#endif +#endif // IOS } else { m_internalFormat = m_externalFormat = GL_RGBA; } -#else - m_internalFormat = GL_RGBA; - m_externalFormat = GL_BGRA; + +#ifndef QT_OPENGL_ES + } #endif m_use_bgra_fallback = qEnvironmentVariableIsSet("QSG_ATLAS_USE_BGRA_FALLBACK"); @@ -326,7 +332,8 @@ void Atlas::bind(QSGTexture::Filtering filtering) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); #if !defined(QT_OPENGL_ES_2) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + if (!QOpenGLContext::currentContext()->isOpenGLES()) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); #endif glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_size.width(), m_size.height(), 0, m_externalFormat, GL_UNSIGNED_BYTE, 0); diff --git a/src/quick/scenegraph/util/qsgdepthstencilbuffer.cpp b/src/quick/scenegraph/util/qsgdepthstencilbuffer.cpp index 59bde0d602..f5a75fd627 100644 --- a/src/quick/scenegraph/util/qsgdepthstencilbuffer.cpp +++ b/src/quick/scenegraph/util/qsgdepthstencilbuffer.cpp @@ -75,8 +75,6 @@ void QSGDepthStencilBuffer::detach() GL_RENDERBUFFER, 0); } -// ###TODO Remove once using Khronos OpenGL headers -#if defined(QT_OPENGL_ES_2) #ifndef GL_DEPTH24_STENCIL8_OES #define GL_DEPTH24_STENCIL8_OES 0x88F0 #endif @@ -84,7 +82,6 @@ void QSGDepthStencilBuffer::detach() #ifndef GL_DEPTH_COMPONENT24_OES #define GL_DEPTH_COMPONENT24_OES 0x81A6 #endif -#endif QSGDefaultDepthStencilBuffer::QSGDefaultDepthStencilBuffer(QOpenGLContext *context, const Format &format) : QSGDepthStencilBuffer(context, format) @@ -117,12 +114,10 @@ QSGDefaultDepthStencilBuffer::QSGDefaultDepthStencilBuffer(QOpenGLContext *conte if (!m_depthBuffer && (format.attachments & DepthAttachment)) { m_functions.glGenRenderbuffers(1, &m_depthBuffer); m_functions.glBindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer); -#ifdef QT_OPENGL_ES - const GLenum internalFormat = m_functions.hasOpenGLExtension(QOpenGLExtensions::Depth24) + GLenum internalFormat = GL_DEPTH_COMPONENT; + if (context->isOpenGLES()) + internalFormat = m_functions.hasOpenGLExtension(QOpenGLExtensions::Depth24) ? GL_DEPTH_COMPONENT24_OES : GL_DEPTH_COMPONENT16; -#else - const GLenum internalFormat = GL_DEPTH_COMPONENT; -#endif if (format.samples && m_functions.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)) { m_functions.glRenderbufferStorageMultisample(GL_RENDERBUFFER, format.samples, internalFormat, width, height); @@ -136,7 +131,7 @@ QSGDefaultDepthStencilBuffer::QSGDefaultDepthStencilBuffer(QOpenGLContext *conte #ifdef QT_OPENGL_ES const GLenum internalFormat = GL_STENCIL_INDEX8; #else - const GLenum internalFormat = GL_STENCIL_INDEX; + const GLenum internalFormat = context->isOpenGLES() ? GL_STENCIL_INDEX8 : GL_STENCIL_INDEX; #endif if (format.samples && m_functions.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)) { m_functions.glRenderbufferStorageMultisample(GL_RENDERBUFFER, format.samples, diff --git a/src/quick/scenegraph/util/qsgsimplematerial.cpp b/src/quick/scenegraph/util/qsgsimplematerial.cpp index a247b37d77..ada4dd6c4f 100644 --- a/src/quick/scenegraph/util/qsgsimplematerial.cpp +++ b/src/quick/scenegraph/util/qsgsimplematerial.cpp @@ -142,6 +142,9 @@ the unique QSGSimpleMaterialShader implementation must be instantiated with a unique C++ type. + \note All classes with QSG prefix should be used solely on the scene graph's + rendering thread. See \l {Scene Graph and Rendering} for more information. + \sa {Scene Graph - Simple Material} */ @@ -244,6 +247,9 @@ \inmodule QtQuick + \note All classes with QSG prefix should be used solely on the scene graph's + rendering thread. See \l {Scene Graph and Rendering} for more information. + \sa QSGSimpleMaterialShader */ diff --git a/src/quick/scenegraph/util/qsgsimpletexturenode.cpp b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp index 47cb82d01b..bbf115fa2a 100644 --- a/src/quick/scenegraph/util/qsgsimpletexturenode.cpp +++ b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp @@ -107,6 +107,8 @@ QSGSimpleTextureNode::QSGSimpleTextureNode() setGeometry(&m_geometry); setMaterial(&m_material); setOpaqueMaterial(&m_opaque_material); + m_material.setMipmapFiltering(QSGTexture::None); + m_opaque_material.setMipmapFiltering(QSGTexture::None); #ifdef QSG_RUNTIME_DESCRIPTION qsgnode_set_description(this, QLatin1String("simpletexture")); #endif diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp index 3bbcb0c112..cd0b64fe49 100644 --- a/src/quick/scenegraph/util/qsgtexture.cpp +++ b/src/quick/scenegraph/util/qsgtexture.cpp @@ -39,8 +39,6 @@ ** ****************************************************************************/ -#define GL_GLEXT_PROTOTYPES - #include "qsgtexture_p.h" #include <qopenglfunctions.h> #include <QtQuick/private/qsgcontext_p.h> @@ -83,7 +81,7 @@ static QElapsedTimer qsg_renderer_timer; QT_BEGIN_NAMESPACE -#if !defined(QT_NO_DEBUG) && defined(QT_OPENGL_ES_2) +#ifndef QT_NO_DEBUG inline static bool isPowerOfTwo(int x) { // Assumption: x >= 1 @@ -237,6 +235,9 @@ static void qt_debug_remove_texture(QSGTexture* texture) the function removedFromAtlas() can be used to extract a non-atlassed copy. + \note All classes with QSG prefix should be used solely on the scene graph's + rendering thread. See \l {Scene Graph and Rendering} for more information. + \sa {Scene Graph - Rendering FBOs}, {Scene Graph - Rendering FBOs in a thread} */ @@ -514,7 +515,7 @@ void QSGTexture::updateBindOptions(bool force) } if (force || d->wrapChanged) { -#if !defined(QT_NO_DEBUG) && defined(QT_OPENGL_ES_2) +#ifndef QT_NO_DEBUG if (d->horizontalWrap == Repeat || d->verticalWrap == Repeat) { bool npotSupported = QOpenGLFunctions(QOpenGLContext::currentContext()).hasOpenGLFeature(QOpenGLFunctions::NPOTTextures); QSize size = textureSize(); @@ -566,6 +567,7 @@ void QSGPlainTexture::setImage(const QImage &image) m_has_alpha = image.hasAlphaChannel(); m_dirty_texture = true; m_dirty_bind_options = true; + m_mipmaps_generated = false; } int QSGPlainTexture::textureId() const @@ -686,7 +688,10 @@ void QSGPlainTexture::bind() externalFormat = GL_BGRA; #ifdef QT_OPENGL_ES internalFormat = GL_BGRA; -#endif +#else + if (context->isOpenGLES()) + internalFormat = GL_BGRA; +#endif // QT_OPENGL_ES } else if (!wrongfullyReportsBgra8888Support && (context->hasExtension(QByteArrayLiteral("GL_EXT_texture_format_BGRA8888")) || context->hasExtension(QByteArrayLiteral("GL_IMG_texture_format_BGRA8888")))) { @@ -765,6 +770,9 @@ void QSGPlainTexture::bind() To update the content of the texture, call updateTexture() explicitly. Simply calling bind() will not update the texture. + + \note All classes with QSG prefix should be used solely on the scene graph's + rendering thread. See \l {Scene Graph and Rendering} for more information. */ diff --git a/src/quick/scenegraph/util/qsgtexturematerial.cpp b/src/quick/scenegraph/util/qsgtexturematerial.cpp index df55404504..afa535d322 100644 --- a/src/quick/scenegraph/util/qsgtexturematerial.cpp +++ b/src/quick/scenegraph/util/qsgtexturematerial.cpp @@ -46,13 +46,11 @@ QT_BEGIN_NAMESPACE -#ifdef QT_OPENGL_ES_2 inline static bool isPowerOfTwo(int x) { // Assumption: x >= 1 return x == (x & -x); } -#endif QSGMaterialType QSGOpaqueTextureMaterialShader::type; @@ -83,19 +81,20 @@ void QSGOpaqueTextureMaterialShader::updateState(const RenderState &state, QSGMa QSGTexture *t = tx->texture(); t->setFiltering(tx->filtering()); -#ifdef QT_OPENGL_ES_2 - bool npotSupported = QOpenGLFunctions(const_cast<QOpenGLContext *>(state.context())).hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat); - QSize size = t->textureSize(); - bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height()); - if (!npotSupported && isNpot) { - t->setHorizontalWrapMode(QSGTexture::ClampToEdge); - t->setVerticalWrapMode(QSGTexture::ClampToEdge); - } else -#endif - { - t->setHorizontalWrapMode(tx->horizontalWrapMode()); - t->setVerticalWrapMode(tx->verticalWrapMode()); + + t->setHorizontalWrapMode(tx->horizontalWrapMode()); + t->setVerticalWrapMode(tx->verticalWrapMode()); + bool npotSupported = const_cast<QOpenGLContext *>(state.context()) + ->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat); + if (!npotSupported) { + QSize size = t->textureSize(); + const bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height()); + if (isNpot) { + t->setHorizontalWrapMode(QSGTexture::ClampToEdge); + t->setVerticalWrapMode(QSGTexture::ClampToEdge); + } } + t->setMipmapFiltering(tx->mipmapFiltering()); if (oldTx == 0 || oldTx->texture()->textureId() != t->textureId()) @@ -153,7 +152,7 @@ void QSGOpaqueTextureMaterialShader::updateState(const RenderState &state, QSGMa QSGOpaqueTextureMaterial::QSGOpaqueTextureMaterial() : m_texture(0) , m_filtering(QSGTexture::Nearest) - , m_mipmap_filtering(QSGTexture::Nearest) + , m_mipmap_filtering(QSGTexture::None) , m_horizontal_wrap(QSGTexture::ClampToEdge) , m_vertical_wrap(QSGTexture::ClampToEdge) { |