aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@jollamobile.com>2014-08-01 11:22:31 +0200
committerGunnar Sletta <gunnar.sletta@jollamobile.com>2014-08-01 23:17:44 +0200
commit76859e50d4b986fb88c2f193a70fd9b40963c59a (patch)
tree510d5553d472017e343fc1ca755ea7e313313d39
parent557d73575978b873bb01ea791ae237fa6067fa7f (diff)
More QQuickCanvas cleanup handling.
Avoid calling into QQuickContext2D from QQuickContext2DTexture after QQuickContext2D has been deleted. We acheive this by 1. Giving the texture a direct pointer to the gl context and and surface, so that it doesn't need to go through m_context to get to them (which may have been deleted). 2. Protect access to QQuickContext2DTexture::m_context with a mutex and make sure it is set to 0 in a safe manner when the QQuickContext2D object is deleted. Change-Id: Ie0a30f9fc46f844224838a7cdf2f28a62e8ce322 Reviewed-by: Laszlo Agocs <laszlo.agocs@digia.com>
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp12
-rw-r--r--src/quick/items/context2d/qquickcontext2d_p.h3
-rw-r--r--src/quick/items/context2d/qquickcontext2dtexture.cpp50
-rw-r--r--src/quick/items/context2d/qquickcontext2dtexture_p.h10
4 files changed, 47 insertions, 28 deletions
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index 8858958dbc..7964f650d6 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -4084,6 +4084,8 @@ public:
QOffscreenSurface *surface;
};
+QMutex QQuickContext2D::mutex;
+
QQuickContext2D::QQuickContext2D(QObject *parent)
: QQuickCanvasContext(parent)
, m_buffer(new QQuickContext2DCommandBuffer)
@@ -4097,6 +4099,8 @@ QQuickContext2D::QQuickContext2D(QObject *parent)
QQuickContext2D::~QQuickContext2D()
{
+ mutex.lock();
+ m_texture->setItem(0);
delete m_buffer;
if (m_renderTarget == QQuickCanvasItem::FramebufferObject) {
@@ -4120,6 +4124,7 @@ QQuickContext2D::~QQuickContext2D()
// currently be doing.
m_texture->deleteLater();
}
+ mutex.unlock();
}
QV4::ReturnedValue QQuickContext2D::v4value() const
@@ -4190,6 +4195,7 @@ void QQuickContext2D::init(QQuickCanvasItem *canvasItem, const QVariantMap &args
m_glContext->setShareContext(cc);
if (renderThread != QThread::currentThread())
m_glContext->moveToThread(renderThread);
+ m_texture->initializeOpenGL(m_glContext, m_surface.data());
}
connect(m_texture, SIGNAL(textureChanged()), SIGNAL(textureChanged()));
@@ -4379,10 +4385,4 @@ void QQuickContext2D::setV8Engine(QV8Engine *engine)
}
}
-QQuickContext2DCommandBuffer* QQuickContext2D::nextBuffer()
-{
- QMutexLocker lock(&m_mutex);
- return m_bufferQueue.isEmpty() ? 0 : m_bufferQueue.dequeue();
-}
-
QT_END_NAMESPACE
diff --git a/src/quick/items/context2d/qquickcontext2d_p.h b/src/quick/items/context2d/qquickcontext2d_p.h
index bd1a83ce08..c679bc33cb 100644
--- a/src/quick/items/context2d/qquickcontext2d_p.h
+++ b/src/quick/items/context2d/qquickcontext2d_p.h
@@ -185,7 +185,6 @@ public:
QQuickCanvasItem* canvas() const { return m_canvas; }
QQuickContext2DCommandBuffer* buffer() const { return m_buffer; }
- QQuickContext2DCommandBuffer* nextBuffer();
bool bufferValid() const { return m_buffer != 0; }
void popState();
@@ -255,7 +254,7 @@ public:
QImage m_grabbedImage;
bool m_grabbed:1;
- QMutex m_mutex;
+ static QMutex mutex;
};
diff --git a/src/quick/items/context2d/qquickcontext2dtexture.cpp b/src/quick/items/context2d/qquickcontext2dtexture.cpp
index 4007713152..c8bea6f97e 100644
--- a/src/quick/items/context2d/qquickcontext2dtexture.cpp
+++ b/src/quick/items/context2d/qquickcontext2dtexture.cpp
@@ -90,6 +90,8 @@ struct GLAcquireContext {
QQuickContext2DTexture::QQuickContext2DTexture()
: m_context(0)
+ , m_gl(0)
+ , m_surface(0)
, m_item(0)
, m_canvasWindowChanged(false)
, m_dirtyTexture(false)
@@ -146,8 +148,12 @@ void QQuickContext2DTexture::setAntialiasing(bool antialiasing)
void QQuickContext2DTexture::setItem(QQuickCanvasItem* item)
{
m_item = item;
- m_context = (QQuickContext2D*)item->rawContext(); // FIXME
- m_state = m_context->state;
+ if (m_item) {
+ m_context = (QQuickContext2D*) item->rawContext(); // FIXME
+ m_state = m_context->state;
+ } else {
+ m_context = 0;
+ }
}
bool QQuickContext2DTexture::setCanvasWindow(const QRect& r)
@@ -239,12 +245,15 @@ bool QQuickContext2DTexture::canvasDestroyed()
void QQuickContext2DTexture::paint(QQuickContext2DCommandBuffer *ccb)
{
+ QQuickContext2D::mutex.lock();
if (canvasDestroyed()) {
delete ccb;
+ QQuickContext2D::mutex.unlock();
return;
}
+ QQuickContext2D::mutex.unlock();
- GLAcquireContext currentContext(m_context->glContext(), m_context->surface());
+ GLAcquireContext currentContext(m_gl, m_surface);
if (!m_tiledCanvas) {
paintWithoutTiles(ccb);
@@ -434,7 +443,7 @@ QSGTexture *QQuickContext2DFBOTexture::textureForNextFrame(QSGTexture *lastTextu
}
if (m_dirtyTexture) {
- if (!m_context->glContext()) {
+ if (!m_gl) {
// on a rendering thread, use the fbo directly...
texture->setTextureId(m_fbo->texture());
} else {
@@ -492,18 +501,18 @@ bool QQuickContext2DFBOTexture::doMultisampling() const
void QQuickContext2DFBOTexture::grabImage(const QRectF& rf)
{
Q_ASSERT(rf.isValid());
- if (!m_fbo) {
- m_context->setGrabbedImage(QImage());
- return;
- }
-
- QImage grabbed;
- {
- GLAcquireContext ctx(m_context->glContext(), m_context->surface());
- grabbed = m_fbo->toImage().mirrored().copy(rf.toRect());
+ QQuickContext2D::mutex.lock();
+ if (m_context) {
+ if (!m_fbo) {
+ m_context->setGrabbedImage(QImage());
+ } else {
+ QImage grabbed;
+ GLAcquireContext ctx(m_gl, m_surface);
+ grabbed = m_fbo->toImage().mirrored().copy(rf.toRect());
+ m_context->setGrabbedImage(grabbed);
+ }
}
-
- m_context->setGrabbedImage(grabbed);
+ QQuickContext2D::mutex.unlock();
}
void QQuickContext2DFBOTexture::compositeTile(QQuickContext2DTile* tile)
@@ -586,7 +595,7 @@ void QQuickContext2DFBOTexture::endPainting()
if (m_multisampledFbo)
QOpenGLFramebufferObject::blitFramebuffer(m_fbo, m_multisampledFbo);
- if (m_context->glContext()) {
+ if (m_gl) {
/* When rendering happens on the render thread, the fbo's texture is
* used directly for display. If we are on the GUI thread or a
* dedicated Canvas render thread, we need to decouple the FBO from
@@ -641,9 +650,12 @@ QQuickContext2DTile* QQuickContext2DImageTexture::createTile() const
void QQuickContext2DImageTexture::grabImage(const QRectF& rf)
{
Q_ASSERT(rf.isValid());
- Q_ASSERT(m_context);
- QImage grabbed = m_displayImage.copy(rf.toRect());
- m_context->setGrabbedImage(grabbed);
+ QQuickContext2D::mutex.lock();
+ if (m_context) {
+ QImage grabbed = m_displayImage.copy(rf.toRect());
+ m_context->setGrabbedImage(grabbed);
+ }
+ QQuickContext2D::mutex.unlock();
}
QSGTexture *QQuickContext2DImageTexture::textureForNextFrame(QSGTexture *last)
diff --git a/src/quick/items/context2d/qquickcontext2dtexture_p.h b/src/quick/items/context2d/qquickcontext2dtexture_p.h
index 186863c1aa..e41a4809e4 100644
--- a/src/quick/items/context2d/qquickcontext2dtexture_p.h
+++ b/src/quick/items/context2d/qquickcontext2dtexture_p.h
@@ -113,6 +113,11 @@ public:
virtual QSGTexture *textureForNextFrame(QSGTexture *lastFrame) = 0;
bool event(QEvent *e);
+ void initializeOpenGL(QOpenGLContext *gl, QOffscreenSurface *s) {
+ m_gl = gl;
+ m_surface = s;
+ }
+
Q_SIGNALS:
void textureChanged();
@@ -135,7 +140,10 @@ protected:
QRect createTiles(const QRect& window);
QList<QQuickContext2DTile*> m_tiles;
- QQuickContext2D* m_context;
+ QQuickContext2D *m_context;
+
+ QOpenGLContext *m_gl;
+ QSurface *m_surface;
QQuickContext2D::State m_state;