diff options
author | Gunnar Sletta <gunnar.sletta@nokia.com> | 2011-08-30 08:51:45 +0200 |
---|---|---|
committer | Gunnar Sletta <gunnar.sletta@nokia.com> | 2011-08-30 08:53:31 +0200 |
commit | 5bb2164f7c8b654f2312cd0a4a814b724da292f2 (patch) | |
tree | cf43b85ca7721718811bb458764e077efeffe533 /src | |
parent | f2ad73ceb554944beb35eb8b87bab7a5a0ee9e42 (diff) |
Implement backtrace debug output of leaked textures
Change-Id: I9aeece87aae393eadd32503af5eb7cd1508a732c
Reviewed-on: http://codereview.qt.nokia.com/3849
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Gunnar Sletta <gunnar.sletta@nokia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/declarative/scenegraph/util/qsgtexture.cpp | 104 |
1 files changed, 91 insertions, 13 deletions
diff --git a/src/declarative/scenegraph/util/qsgtexture.cpp b/src/declarative/scenegraph/util/qsgtexture.cpp index d403bd6503..bec325f3bb 100644 --- a/src/declarative/scenegraph/util/qsgtexture.cpp +++ b/src/declarative/scenegraph/util/qsgtexture.cpp @@ -45,6 +45,12 @@ #include <qopenglfunctions.h> #include <private/qsgcontext_p.h> #include <qthread.h> +#include <private/qdeclarativedebugtrace_p.h> + +#if !defined(QT_NO_DEBUG) && (defined(Q_OS_LINUX) || defined(Q_OS_MAC)) +#include <execinfo.h> +#include <QHash> +#endif QT_BEGIN_NAMESPACE @@ -65,36 +71,108 @@ QSGTexturePrivate::QSGTexturePrivate() } #ifndef QT_NO_DEBUG -static int qt_texture_count = 0; -static void qt_print_texture_count() +static int qt_debug_texture_count = 0; + +#if defined(Q_OS_LINUX) || defined (Q_OS_MAC) +DEFINE_BOOL_CONFIG_OPTION(qmlDebugLeakBacktrace, QML_DEBUG_LEAK_BACKTRACE) + +#define BACKTRACE_SIZE 20 +class SGTextureTraceItem { - qDebug("Number of leaked textures: %i", qt_texture_count); - qt_texture_count = -1; -} +public: + void *backTrace[BACKTRACE_SIZE]; + size_t backTraceSize; +}; + +static QHash<QSGTexture*, SGTextureTraceItem*> qt_debug_allocated_textures; #endif +inline static void qt_debug_print_texture_count() +{ + qDebug("Number of leaked textures: %i", qt_debug_texture_count); + qt_debug_texture_count = -1; +#if defined(Q_OS_LINUX) || defined (Q_OS_MAC) + if (qmlDebugLeakBacktrace()) { + while (!qt_debug_allocated_textures.isEmpty()) { + QHash<QSGTexture*, SGTextureTraceItem*>::Iterator it = qt_debug_allocated_textures.begin(); + QSGTexture* texture = it.key(); + SGTextureTraceItem* item = it.value(); -QSGTexture::QSGTexture() - : QObject(*(new QSGTexturePrivate)) + qt_debug_allocated_textures.erase(it); + + qDebug() << "------"; + qDebug() << "Leaked" << texture << "backtrace:"; + + char** symbols = backtrace_symbols(item->backTrace, item->backTraceSize); + + if (symbols) { + for (int i=0; i<(int) item->backTraceSize; i++) + qDebug("Backtrace <%02d>: %s", i, symbols[i]); + free(symbols); + } + + qDebug() << "------"; + + delete item; + } + } +#endif +} + +inline static void qt_debug_add_texture(QSGTexture* texture) { -#ifndef QT_NO_DEBUG - ++qt_texture_count; +#if defined(Q_OS_LINUX) || defined (Q_OS_MAC) + if (qmlDebugLeakBacktrace()) { + SGTextureTraceItem* item = new SGTextureTraceItem; + item->backTraceSize = backtrace(item->backTrace, BACKTRACE_SIZE); + qt_debug_allocated_textures.insert(texture, item); + } +#endif // Q_OS_LINUX + + ++qt_debug_texture_count; + static bool atexit_registered = false; if (!atexit_registered) { - atexit(qt_print_texture_count); + atexit(qt_debug_print_texture_count); atexit_registered = true; } +} + +static void qt_debug_remove_texture(QSGTexture* texture) +{ +#if defined(Q_OS_LINUX) || defined (Q_OS_MAC) + if (qmlDebugLeakBacktrace()) { + SGTextureTraceItem* item = qt_debug_allocated_textures.value(texture, 0); + if (item) { + qt_debug_allocated_textures.remove(texture); + delete item; + } + } +#endif + + --qt_debug_texture_count; + + if (qt_debug_texture_count < 0) + qDebug("Material destroyed after qt_debug_print_texture_count() was called."); +} + +#endif // QT_NO_DEBUG + + +QSGTexture::QSGTexture() + : QObject(*(new QSGTexturePrivate)) +{ +#ifndef QT_NO_DEBUG + qt_debug_add_texture(this); #endif } QSGTexture::~QSGTexture() { #ifndef QT_NO_DEBUG - --qt_texture_count; - if (qt_texture_count < 0) - qDebug("Material destroyed after qt_print_texture_count() was called."); + qt_debug_remove_texture(this); #endif } |