aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@jollamobile.com>2014-07-03 12:15:46 +0200
committerGunnar Sletta <gunnar.sletta@jollamobile.com>2014-07-04 17:39:45 +0200
commit92658ebb755bda136a7e4fa455b8d116c2dd0c6f (patch)
tree60c346fa4921a8be7448f550ebda033c07e21d49
parent48dcabdb6f30d5e0c05fc1e56bb4ed4e3a96514c (diff)
Verbose fatal instead of crash when the scene graph state is invalid.
Change-Id: I9a55bcbf9e94084c0cadac561e4707d47f5f8744 Reviewed-by: Robin Burchell <robin+qt@viroteck.net>
-rw-r--r--src/quick/items/qquickshadereffectnode.cpp7
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp24
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterial.cpp15
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterialshader_p.h5
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer_p.h3
-rw-r--r--src/quick/scenegraph/util/qsgtexture.cpp25
-rw-r--r--src/quick/scenegraph/util/qsgtexture_p.h2
-rw-r--r--src/quick/scenegraph/util/qsgtexturematerial.cpp6
8 files changed, 87 insertions, 0 deletions
diff --git a/src/quick/items/qquickshadereffectnode.cpp b/src/quick/items/qquickshadereffectnode.cpp
index f1422e4502..fcf5591d01 100644
--- a/src/quick/items/qquickshadereffectnode.cpp
+++ b/src/quick/items/qquickshadereffectnode.cpp
@@ -46,6 +46,7 @@
#include <QtQuick/qsgtextureprovider.h>
#include <QtQuick/private/qsgrenderer_p.h>
#include <QtQuick/private/qsgshadersourcebuilder_p.h>
+#include <QtQuick/private/qsgtexture_p.h>
QT_BEGIN_NAMESPACE
@@ -136,6 +137,12 @@ void QQuickCustomMaterialShader::updateState(const RenderState &state, QSGMateri
functions->glActiveTexture(GL_TEXTURE0 + idx);
if (QSGTextureProvider *provider = material->textureProviders.at(idx)) {
if (QSGTexture *texture = provider->texture()) {
+
+#ifndef QT_NO_DEBUG
+ if (!qsg_safeguard_texture(texture))
+ continue;
+#endif
+
if (loc >= 0) {
QRectF r = texture->normalizedTextureSubRect();
program()->setUniformValue(loc, r.x(), r.y(), r.width(), r.height());
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index 3770461ba7..0ae0c1579b 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -56,6 +56,7 @@
#include <QtGui/QOpenGLFunctions_1_0>
#include <private/qquickprofiler_p.h>
+#include "qsgmaterialshader_p.h"
#include <algorithm>
@@ -2058,6 +2059,19 @@ void Renderer::renderMergedBatch(const Batch *batch)
program->updateState(state(dirty), material, m_currentMaterial);
+#ifndef QT_NO_DEBUG
+ if (qsg_test_and_clear_material_failure()) {
+ qDebug() << "QSGMaterial::updateState triggered an error (merged), batch will be skipped:";
+ Element *ee = e;
+ while (ee) {
+ qDebug() << " -" << ee->node;
+ ee = ee->nextInBatch;
+ }
+ QSGNodeDumper::dump(rootNode());
+ qFatal("Aborting: scene graph is invalid...");
+ }
+#endif
+
m_currentMaterial = material;
QSGGeometry* g = gn->geometry();
@@ -2165,6 +2179,16 @@ void Renderer::renderUnmergedBatch(const Batch *batch)
program->updateState(state(dirty), material, m_currentMaterial);
+#ifndef QT_NO_DEBUG
+ if (qsg_test_and_clear_material_failure()) {
+ qDebug() << "QSGMaterial::updateState() triggered an error (unmerged), batch will be skipped:";
+ qDebug() << " - offending node is" << e->node;
+ QSGNodeDumper::dump(rootNode());
+ qFatal("Aborting: scene graph is invalid...");
+ return;
+ }
+#endif
+
// We don't need to bother with asking each node for its material as they
// are all identical (compare==0) since they are in the same batch.
m_currentMaterial = material;
diff --git a/src/quick/scenegraph/coreapi/qsgmaterial.cpp b/src/quick/scenegraph/coreapi/qsgmaterial.cpp
index c4800a5cac..376aeb2423 100644
--- a/src/quick/scenegraph/coreapi/qsgmaterial.cpp
+++ b/src/quick/scenegraph/coreapi/qsgmaterial.cpp
@@ -46,6 +46,21 @@
QT_BEGIN_NAMESPACE
+#ifndef QT_NO_DEBUG
+bool qsg_material_failure = false;
+bool qsg_test_and_clear_material_failure()
+{
+ bool fail = qsg_material_failure;
+ qsg_material_failure = false;
+ return fail;
+}
+
+void qsg_set_material_failure()
+{
+ qsg_material_failure = true;
+}
+#endif
+
const char *QSGMaterialShaderPrivate::loadShaderSource(QOpenGLShader::ShaderType type) const
{
QStringList files = m_sourceFiles[type];
diff --git a/src/quick/scenegraph/coreapi/qsgmaterialshader_p.h b/src/quick/scenegraph/coreapi/qsgmaterialshader_p.h
index fc8a35c41d..43b224f9f9 100644
--- a/src/quick/scenegraph/coreapi/qsgmaterialshader_p.h
+++ b/src/quick/scenegraph/coreapi/qsgmaterialshader_p.h
@@ -56,6 +56,11 @@ public:
mutable QHash<QOpenGLShader::ShaderType, QByteArray> m_sources;
};
+#ifndef QT_NO_DEBUG
+Q_QUICK_PRIVATE_EXPORT bool qsg_test_and_clear_material_failure();
+Q_QUICK_PRIVATE_EXPORT void qsg_set_material_failure();
+#endif
+
QT_END_NAMESPACE
#endif // QSGMATERIALSHADER_P_H
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer_p.h b/src/quick/scenegraph/coreapi/qsgrenderer_p.h
index eddd38a68f..39adcc2246 100644
--- a/src/quick/scenegraph/coreapi/qsgrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgrenderer_p.h
@@ -64,6 +64,9 @@ class TextureReference;
class QSGBindable;
class QSGNodeUpdater;
+Q_QUICK_PRIVATE_EXPORT bool qsg_test_and_clear_fatal_render_error();
+Q_QUICK_PRIVATE_EXPORT void qsg_set_fatal_renderer_error();
+
class Q_QUICK_PRIVATE_EXPORT QSGRenderer : public QObject, public QOpenGLFunctions
{
Q_OBJECT
diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp
index 120a3ebf3d..e9e6c14f4e 100644
--- a/src/quick/scenegraph/util/qsgtexture.cpp
+++ b/src/quick/scenegraph/util/qsgtexture.cpp
@@ -48,6 +48,8 @@
#include <QtGui/qguiapplication.h>
#include <QtGui/qpa/qplatformnativeinterface.h>
+#include <private/qsgmaterialshader_p.h>
+
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && !defined(__UCLIBC__)
#define CAN_BACKTRACE_EXECINFO
#endif
@@ -271,6 +273,23 @@ static void qt_debug_remove_texture(QSGTexture* texture)
\internal
*/
+#ifndef QT_NO_DEBUG
+Q_GLOBAL_STATIC(QSet<QSGTexture *>, qsg_valid_texture_set)
+Q_GLOBAL_STATIC(QMutex, qsg_valid_texture_mutex)
+
+bool qsg_safeguard_texture(QSGTexture *texture)
+{
+ QMutexLocker locker(qsg_valid_texture_mutex());
+ if (!qsg_valid_texture_set()->contains(texture)) {
+ qWarning() << "Invalid texture accessed:" << (void *) texture;
+ qsg_set_material_failure();
+ glBindTexture(GL_TEXTURE_2D, 0);
+ return false;
+ }
+ return true;
+}
+#endif
+
/*!
Constructs the QSGTexture base class.
*/
@@ -280,6 +299,9 @@ QSGTexture::QSGTexture()
#ifndef QT_NO_DEBUG
if (qsg_leak_check)
qt_debug_add_texture(this);
+
+ QMutexLocker locker(qsg_valid_texture_mutex());
+ qsg_valid_texture_set()->insert(this);
#endif
}
@@ -291,6 +313,9 @@ QSGTexture::~QSGTexture()
#ifndef QT_NO_DEBUG
if (qsg_leak_check)
qt_debug_remove_texture(this);
+
+ QMutexLocker locker(qsg_valid_texture_mutex());
+ qsg_valid_texture_set()->remove(this);
#endif
}
diff --git a/src/quick/scenegraph/util/qsgtexture_p.h b/src/quick/scenegraph/util/qsgtexture_p.h
index bc81569f84..8b726e9eb8 100644
--- a/src/quick/scenegraph/util/qsgtexture_p.h
+++ b/src/quick/scenegraph/util/qsgtexture_p.h
@@ -113,6 +113,8 @@ protected:
uint m_retain_image: 1;
};
+Q_QUICK_PRIVATE_EXPORT bool qsg_safeguard_texture(QSGTexture *);
+
QT_END_NAMESPACE
#endif // QSGTEXTURE_P_H
diff --git a/src/quick/scenegraph/util/qsgtexturematerial.cpp b/src/quick/scenegraph/util/qsgtexturematerial.cpp
index afa535d322..87fcb6a186 100644
--- a/src/quick/scenegraph/util/qsgtexturematerial.cpp
+++ b/src/quick/scenegraph/util/qsgtexturematerial.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qsgtexturematerial_p.h"
+#include "qsgtexture_p.h"
#include <QtGui/qopenglshaderprogram.h>
#include <QtGui/qopenglfunctions.h>
@@ -80,6 +81,11 @@ void QSGOpaqueTextureMaterialShader::updateState(const RenderState &state, QSGMa
QSGTexture *t = tx->texture();
+#ifndef QT_NO_DEBUG
+ if (!qsg_safeguard_texture(t))
+ return;
+#endif
+
t->setFiltering(tx->filtering());
t->setHorizontalWrapMode(tx->horizontalWrapMode());