diff options
author | Gunnar Sletta <gunnar.sletta@jollamobile.com> | 2014-07-03 12:15:46 +0200 |
---|---|---|
committer | Gunnar Sletta <gunnar.sletta@jollamobile.com> | 2014-07-04 17:39:45 +0200 |
commit | 92658ebb755bda136a7e4fa455b8d116c2dd0c6f (patch) | |
tree | 60c346fa4921a8be7448f550ebda033c07e21d49 | |
parent | 48dcabdb6f30d5e0c05fc1e56bb4ed4e3a96514c (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.cpp | 7 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 24 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgmaterial.cpp | 15 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgmaterialshader_p.h | 5 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgrenderer_p.h | 3 | ||||
-rw-r--r-- | src/quick/scenegraph/util/qsgtexture.cpp | 25 | ||||
-rw-r--r-- | src/quick/scenegraph/util/qsgtexture_p.h | 2 | ||||
-rw-r--r-- | src/quick/scenegraph/util/qsgtexturematerial.cpp | 6 |
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()); |