aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@jollamobile.com>2014-07-30 17:11:02 +0200
committerGunnar Sletta <gunnar.sletta@jollamobile.com>2014-07-31 19:39:58 +0200
commit54d32ff902292148bffa84b7fc94116d32d5d02b (patch)
tree89940c8fbdfee72c8bef7084357485d41c0f93bd /src
parent9fe218ddf604a9a31e25b55445b03ea47edc0b96 (diff)
Make canvas cleanup work propertly...
Depending on which mode we are in, we need to run cleanup on the right thread and in the right way. Image canvas doesn't contain any GL resources and can be nuked right away. The actual QSGTexture is managed by the node, so we don't need to worry about it. For FBO it is a bit more complicated. - Threaded: We create a cleanup handler that runs makeCurrent deleteTexture and doneCurrent and then release the surface on the GUI thread. - Immediate: Same as threaded, just right away - Cooperative: Schedule the texture to be deleted on the next sync. The Context doesn't have its own GL context in this case, so don't worry about it. Change-Id: I2d0ae7acfa05561faa52f3cacd767eb18cabaf02 Reviewed-by: Laszlo Agocs <laszlo.agocs@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp59
-rw-r--r--src/quick/items/context2d/qquickcontext2dtexture.cpp3
-rw-r--r--src/quick/items/context2d/qquickcontext2dtexture_p.h1
3 files changed, 61 insertions, 2 deletions
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index ab21c3c9a8..4b70934320 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -70,6 +70,8 @@
#include <private/qv4objectproto_p.h>
#include <private/qv4scopedvalue_p.h>
+#include <QtCore/QRunnable>
+
#if defined(Q_OS_QNX) || defined(Q_OS_ANDROID)
#include <ctype.h>
#endif
@@ -4001,6 +4003,34 @@ bool QQuickContext2D::isPointInPath(qreal x, qreal y) const
return contains;
}
+class QQuickContext2DThreadCleanup : public QObject
+{
+public:
+ QQuickContext2DThreadCleanup(QOpenGLContext *gl, QQuickContext2DTexture *t, QOffscreenSurface *s)
+ : context(gl), texture(t), surface(s)
+ { }
+
+ ~QQuickContext2DThreadCleanup()
+ {
+ context->makeCurrent(surface);
+ delete texture;
+ context->doneCurrent();
+ delete context;
+ surface->deleteLater();
+ }
+
+ QOpenGLContext *context;
+ QQuickContext2DTexture *texture;
+ QOffscreenSurface *surface;
+};
+
+class QQuickContext2DTextureCleanup : public QRunnable
+{
+public:
+ QQuickContext2DTexture *texture;
+ void run() Q_DECL_OVERRIDE { delete texture; }
+};
+
QQuickContext2D::QQuickContext2D(QObject *parent)
: QQuickCanvasContext(parent)
, m_buffer(new QQuickContext2DCommandBuffer)
@@ -4015,7 +4045,34 @@ QQuickContext2D::QQuickContext2D(QObject *parent)
QQuickContext2D::~QQuickContext2D()
{
delete m_buffer;
- m_texture->deleteLater();
+
+ if (m_renderTarget == QQuickCanvasItem::FramebufferObject) {
+ if (m_renderStrategy == QQuickCanvasItem::Immediate && m_glContext) {
+ Q_ASSERT(QThread::currentThread() == m_glContext->thread());
+ m_glContext->makeCurrent(m_surface.data());
+ delete m_texture;
+ m_glContext->doneCurrent();
+ delete m_glContext;
+ } else if (m_texture->isOnCustomThread()) {
+ Q_ASSERT(m_glContext);
+ QQuickContext2DThreadCleanup *cleaner = new QQuickContext2DThreadCleanup(m_glContext, m_texture, m_surface.take());
+ cleaner->moveToThread(m_texture->thread());
+ cleaner->deleteLater();
+ } else {
+ if (m_canvas->window()) {
+ QQuickContext2DTextureCleanup *c = new QQuickContext2DTextureCleanup;
+ c->texture = m_texture;
+ m_canvas->window()->scheduleRenderJob(c, QQuickWindow::AfterSynchronizingStage);
+ } else {
+ delete m_texture;
+ }
+ }
+ } else {
+ // Image based does not have GL resources, but must still be deleted
+ // on its designated thread after it has completed whatever it might
+ // currently be doing.
+ m_texture->deleteLater();
+ }
}
QV4::ReturnedValue QQuickContext2D::v4value() const
diff --git a/src/quick/items/context2d/qquickcontext2dtexture.cpp b/src/quick/items/context2d/qquickcontext2dtexture.cpp
index 0ab76b0ca5..fbfd3df324 100644
--- a/src/quick/items/context2d/qquickcontext2dtexture.cpp
+++ b/src/quick/items/context2d/qquickcontext2dtexture.cpp
@@ -414,7 +414,8 @@ QQuickContext2DFBOTexture::~QQuickContext2DFBOTexture()
delete m_multisampledFbo;
delete m_paint_device;
- QOpenGLContext::currentContext()->functions()->glDeleteTextures(2, m_displayTextures);
+ if (QOpenGLContext::currentContext())
+ QOpenGLContext::currentContext()->functions()->glDeleteTextures(2, m_displayTextures);
}
QSGTexture *QQuickContext2DFBOTexture::textureForNextFrame(QSGTexture *lastTexture)
diff --git a/src/quick/items/context2d/qquickcontext2dtexture_p.h b/src/quick/items/context2d/qquickcontext2dtexture_p.h
index cf0e8e3fa9..186863c1aa 100644
--- a/src/quick/items/context2d/qquickcontext2dtexture_p.h
+++ b/src/quick/items/context2d/qquickcontext2dtexture_p.h
@@ -107,6 +107,7 @@ public:
bool setDirtyRect(const QRect &dirtyRect);
bool canvasDestroyed();
void setOnCustomThread(bool is) { m_onCustomThread = is; }
+ bool isOnCustomThread() const { return m_onCustomThread; }
// Called during sync() on the scene graph thread while GUI is blocked.
virtual QSGTexture *textureForNextFrame(QSGTexture *lastFrame) = 0;