aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@digia.com>2014-05-09 16:25:58 +0200
committerGunnar Sletta <gunnar.sletta@jollamobile.com>2014-05-10 11:53:47 +0200
commit66646dd8c37adb488a79ab274b2396a649674e6d (patch)
treeb0f5ac752a52cec3de1d47692e09295197622dcd /src/quick/scenegraph
parentda15ea0f3b5805db657f13060c21efa78f10cde2 (diff)
parentd82a17b929dd88fe76258b0f801beaa1b2ee343e (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')
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp17
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h2
-rw-r--r--src/quick/scenegraph/coreapi/qsggeometry.cpp3
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterial.cpp11
-rw-r--r--src/quick/scenegraph/coreapi/qsgnode.cpp19
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer_p.h2
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp41
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h3
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp6
-rw-r--r--src/quick/scenegraph/qsgdefaultimagenode.cpp19
-rw-r--r--src/quick/scenegraph/qsgdefaultrectanglenode.cpp20
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp48
-rw-r--r--src/quick/scenegraph/qsgrenderloop_p.h12
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp20
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop_p.h1
-rw-r--r--src/quick/scenegraph/qsgwindowsrenderloop.cpp8
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture.cpp21
-rw-r--r--src/quick/scenegraph/util/qsgdepthstencilbuffer.cpp13
-rw-r--r--src/quick/scenegraph/util/qsgsimplematerial.cpp6
-rw-r--r--src/quick/scenegraph/util/qsgsimpletexturenode.cpp2
-rw-r--r--src/quick/scenegraph/util/qsgtexture.cpp18
-rw-r--r--src/quick/scenegraph/util/qsgtexturematerial.cpp29
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)
{