aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/context2d
diff options
context:
space:
mode:
authorCharles Yin <yinyunqiao@gmail.com>2012-06-06 07:09:07 +1000
committerQt by Nokia <qt-info@nokia.com>2012-07-31 07:44:12 +0200
commit4236e7f7ee1d78c5adfebe719afb8b8a6dcd094b (patch)
tree9889d51119657f74951ad7642dc6a89c8c0d068b /src/quick/items/context2d
parent9b671727010ccc45cc51840630b159cd34dd983d (diff)
Refactor context2d thread logic
1. Use QQuickContext2DRenderThread for Threaded rendering 2. Make FBO target works with all render strategies 3. Remove some unnessary locks, call texture methods by invoking meta calls 4. Run existing tests with all render targets and strategies (except Cooperative) Change-Id: I0db5c91d848b86bcc1536c30d7a5804b66a817f1 Reviewed-by: Yunqiao Yin <charles.yin@nokia.com>
Diffstat (limited to 'src/quick/items/context2d')
-rw-r--r--src/quick/items/context2d/qquickcanvasitem.cpp25
-rw-r--r--src/quick/items/context2d/qquickcanvasitem_p.h2
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp86
-rw-r--r--src/quick/items/context2d/qquickcontext2d_p.h10
-rw-r--r--src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp5
-rw-r--r--src/quick/items/context2d/qquickcontext2dtexture.cpp274
-rw-r--r--src/quick/items/context2d/qquickcontext2dtexture_p.h45
7 files changed, 158 insertions, 289 deletions
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp
index 939e7b4fba..16f08d3a3a 100644
--- a/src/quick/items/context2d/qquickcanvasitem.cpp
+++ b/src/quick/items/context2d/qquickcanvasitem.cpp
@@ -545,7 +545,6 @@ void QQuickCanvasItem::setRenderStrategy(QQuickCanvasItem::RenderStrategy strate
qmlInfo(this) << "Canvas:renderStrategy not changeable once context is active.";
return;
}
-
d->renderStrategy = strategy;
emit renderStrategyChanged();
}
@@ -603,6 +602,16 @@ void QQuickCanvasItem::geometryChanged(const QRectF &newGeometry, const QRectF &
requestPaint();
}
+void QQuickCanvasItem::releaseResources()
+{
+ Q_D(QQuickCanvasItem);
+
+ if (d->context) {
+ delete d->context;
+ d->context = 0;
+ }
+}
+
void QQuickCanvasItem::componentComplete()
{
QQuickItem::componentComplete();
@@ -678,17 +687,9 @@ QSGNode *QQuickCanvasItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
if (!d->contextInitialized)
return 0;
- class CanvasTextureNode : public QSGSimpleTextureNode
- {
- public:
- CanvasTextureNode() : QSGSimpleTextureNode() {}
- ~CanvasTextureNode() {delete texture();}
- };
-
- CanvasTextureNode *node = static_cast<CanvasTextureNode*>(oldNode);
- if (!node) {
- node = new CanvasTextureNode;
- }
+ QSGSimpleTextureNode *node = static_cast<QSGSimpleTextureNode*>(oldNode);
+ if (!node)
+ node = new QSGSimpleTextureNode;
if (d->renderStrategy == QQuickCanvasItem::Cooperative)
d->context->flush();
diff --git a/src/quick/items/context2d/qquickcanvasitem_p.h b/src/quick/items/context2d/qquickcanvasitem_p.h
index 4e592bcba7..be95c4a775 100644
--- a/src/quick/items/context2d/qquickcanvasitem_p.h
+++ b/src/quick/items/context2d/qquickcanvasitem_p.h
@@ -177,7 +177,7 @@ protected:
void updatePolish();
QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
-
+ void releaseResources();
private:
Q_DECLARE_PRIVATE(QQuickCanvasItem)
Q_INVOKABLE void delayedCreate();
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index f448c3fdfb..40a9b8e34c 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -63,8 +63,6 @@
#include <QtCore/qnumeric.h>
#include <private/qquickwindow_p.h>
#include <private/qquickwindowmanager_p.h>
-#include <QtGui/private/qguiapplication_p.h>
-#include <qpa/qplatformintegration.h>
#ifdef Q_OS_QNX
#include <ctype.h>
@@ -3265,6 +3263,11 @@ static int textAlignOffset(QQuickContext2D::TextAlignType value, const QFontMetr
return offset;
}
+void QQuickContext2D::setGrabbedImage(const QImage& grab)
+{
+ m_grabbedImage = grab;
+ m_grabbed = true;
+}
QQmlRefPointer<QQuickCanvasPixmap> QQuickContext2D::createPixmap(const QUrl& url)
{
@@ -3347,12 +3350,15 @@ QQuickContext2D::QQuickContext2D(QObject *parent)
, m_windowManager(0)
, m_surface(0)
, m_glContext(0)
+ , m_thread(0)
+ , m_grabbed(false)
{
}
QQuickContext2D::~QQuickContext2D()
{
delete m_buffer;
+ m_texture->deleteLater();
}
v8::Handle<v8::Object> QQuickContext2D::v8value() const
@@ -3378,15 +3384,10 @@ void QQuickContext2D::init(QQuickCanvasItem *canvasItem, const QVariantMap &args
switch (m_renderTarget) {
case QQuickCanvasItem::Image:
- m_texture = new QQuickContext2DImageTexture(m_renderStrategy == QQuickCanvasItem::Threaded);
+ m_texture = new QQuickContext2DImageTexture;
break;
case QQuickCanvasItem::FramebufferObject:
- {
m_texture = new QQuickContext2DFBOTexture;
- // No BufferQueueingOpenGL, falls back to Cooperative mode
- if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::BufferQueueingOpenGL))
- m_renderStrategy = QQuickCanvasItem::Cooperative;
- }
break;
}
@@ -3396,7 +3397,9 @@ void QQuickContext2D::init(QQuickCanvasItem *canvasItem, const QVariantMap &args
m_texture->setCanvasSize(canvasItem->canvasSize().toSize());
m_texture->setSmooth(canvasItem->smooth());
- QThread *renderThread = QThread::currentThread();
+ m_thread = QThread::currentThread();
+
+ QThread *renderThread = m_thread;
QThread *sceneGraphThread = window->openglContext() ? window->openglContext()->thread() : 0;
if (m_renderStrategy == QQuickCanvasItem::Threaded)
@@ -3404,6 +3407,9 @@ void QQuickContext2D::init(QQuickCanvasItem *canvasItem, const QVariantMap &args
else if (m_renderStrategy == QQuickCanvasItem::Cooperative)
renderThread = sceneGraphThread;
+ if (renderThread && renderThread != QThread::currentThread())
+ m_texture->moveToThread(renderThread);
+
if (m_renderTarget == QQuickCanvasItem::FramebufferObject && renderThread != sceneGraphThread) {
QOpenGLContext *cc = QQuickWindowPrivate::get(window)->context->glContext();
m_surface = window;
@@ -3421,32 +3427,24 @@ void QQuickContext2D::init(QQuickCanvasItem *canvasItem, const QVariantMap &args
void QQuickContext2D::prepare(const QSize& canvasSize, const QSize& tileSize, const QRect& canvasWindow, const QRect& dirtyRect, bool smooth)
{
- m_texture->canvasChanged(canvasSize, tileSize, canvasWindow, dirtyRect, smooth);
+ QMetaObject::invokeMethod(m_texture,
+ "canvasChanged",
+ Qt::AutoConnection,
+ Q_ARG(QSize, canvasSize),
+ Q_ARG(QSize, tileSize),
+ Q_ARG(QRect, canvasWindow),
+ Q_ARG(QRect, dirtyRect),
+ Q_ARG(bool, smooth));
}
void QQuickContext2D::flush()
{
- if (!m_buffer->isEmpty()) {
- QMutexLocker lock(&m_bufferMutex);
- m_bufferQueue.enqueue(m_buffer);
- m_buffer = new QQuickContext2DCommandBuffer;
- } else
- return;
-
- switch (m_renderStrategy) {
- case QQuickCanvasItem::Immediate:
- // Cause the texture to consume paint commands immediately
- m_texture->paint();
- break;
- case QQuickCanvasItem::Threaded:
- // wake up thread to consume paint commands
- m_texture->paint();
- break;
- case QQuickCanvasItem::Cooperative:
- // NOTE: On SG Thread
- m_texture->paint();
- break;
- }
+ if (m_buffer)
+ QMetaObject::invokeMethod(m_texture,
+ "paint",
+ Qt::AutoConnection,
+ Q_ARG(QQuickContext2DCommandBuffer*, m_buffer));
+ m_buffer = new QQuickContext2DCommandBuffer();
}
QSGDynamicTexture *QQuickContext2D::texture() const
@@ -3456,16 +3454,22 @@ QSGDynamicTexture *QQuickContext2D::texture() const
QImage QQuickContext2D::toImage(const QRectF& bounds)
{
- switch (m_renderStrategy) {
- case QQuickCanvasItem::Immediate:
- case QQuickCanvasItem::Threaded:
- flush();
- break;
- case QQuickCanvasItem::Cooperative:
- break;
+ flush();
+ if (m_texture->thread() == QThread::currentThread())
+ m_texture->grabImage(bounds);
+ else if (m_renderStrategy == QQuickCanvasItem::Cooperative) {
+ qWarning() << "Pixel read back is not support in Cooperative mode, please try Theaded or Immediate mode";
+ return QImage();
+ } else {
+ QMetaObject::invokeMethod(m_texture,
+ "grabImage",
+ Qt::BlockingQueuedConnection,
+ Q_ARG(QRectF, bounds));
}
-
- return m_texture->toImage(bounds);
+ QImage img = m_grabbedImage;
+ m_grabbedImage = QImage();
+ m_grabbed = false;
+ return img;
}
@@ -3696,7 +3700,7 @@ void QQuickContext2D::setV8Engine(QV8Engine *engine)
QQuickContext2DCommandBuffer* QQuickContext2D::nextBuffer()
{
- QMutexLocker lock(&m_bufferMutex);
+ QMutexLocker lock(&m_mutex);
return m_bufferQueue.isEmpty() ? 0 : m_bufferQueue.dequeue();
}
diff --git a/src/quick/items/context2d/qquickcontext2d_p.h b/src/quick/items/context2d/qquickcontext2d_p.h
index e2952ca580..295be051ba 100644
--- a/src/quick/items/context2d/qquickcontext2d_p.h
+++ b/src/quick/items/context2d/qquickcontext2d_p.h
@@ -53,7 +53,7 @@
#include <QtCore/qstack.h>
#include <QtCore/qqueue.h>
#include <private/qv8engine_p.h>
-
+#include <QtCore/QWaitCondition>
//#define QQUICKCONTEXT2D_DEBUG //enable this for just DEBUG purpose!
@@ -172,6 +172,7 @@ public:
void prepare(const QSize& canvasSize, const QSize& tileSize, const QRect& canvasWindow, const QRect& dirtyRect, bool smooth);
void flush();
void sync();
+ QThread *thread() const {return m_thread;}
QSGDynamicTexture *texture() const;
QImage toImage(const QRectF& bounds);
@@ -228,6 +229,7 @@ public:
QOpenGLContext *glContext() { return m_glContext; }
QSurface *surface() { return m_surface; }
+ void setGrabbedImage(const QImage& grab);
State state;
QStack<QQuickContext2D::State> m_stateStack;
@@ -246,7 +248,11 @@ public:
QQuickCanvasItem::RenderTarget m_renderTarget;
QQuickCanvasItem::RenderStrategy m_renderStrategy;
QQueue<QQuickContext2DCommandBuffer*> m_bufferQueue;
- QMutex m_bufferMutex;
+ QThread *m_thread;
+ QImage m_grabbedImage;
+ bool m_grabbed:1;
+
+ QMutex m_mutex;
};
diff --git a/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
index 196981d971..47f7e1a90d 100644
--- a/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
+++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
@@ -499,6 +499,11 @@ QQuickContext2DCommandBuffer::QQuickContext2DCommandBuffer()
, imageIdx(0)
, pixmapIdx(0)
{
+ static bool registered = false;
+ if (!registered) {
+ qRegisterMetaType<QQuickContext2DCommandBuffer*>("QQuickContext2DCommandBuffer*");
+ registered = true;
+ }
}
diff --git a/src/quick/items/context2d/qquickcontext2dtexture.cpp b/src/quick/items/context2d/qquickcontext2dtexture.cpp
index 2cb183d715..a315d30f8f 100644
--- a/src/quick/items/context2d/qquickcontext2dtexture.cpp
+++ b/src/quick/items/context2d/qquickcontext2dtexture.cpp
@@ -50,7 +50,6 @@
#include <QOpenGLFramebufferObject>
#include <QOpenGLFramebufferObjectFormat>
#include <QtCore/QThread>
-#include <QtCore/QCoreApplication>
QT_BEGIN_NAMESPACE
@@ -88,19 +87,14 @@ struct GLAcquireContext {
QOpenGLContext *ctx;
};
-Q_GLOBAL_STATIC(QThread, globalCanvasThreadRenderInstance)
-
-
QQuickContext2DTexture::QQuickContext2DTexture()
: m_context(0)
, m_item(0)
, m_dirtyCanvas(false)
, m_canvasWindowChanged(false)
, m_dirtyTexture(false)
- , m_threadRendering(false)
, m_smooth(false)
, m_tiledCanvas(false)
- , m_doGrabImage(false)
, m_painting(false)
{
}
@@ -117,12 +111,9 @@ QSize QQuickContext2DTexture::textureSize() const
void QQuickContext2DTexture::markDirtyTexture()
{
- const bool inGrab = m_doGrabImage;
-
m_dirtyTexture = true;
updateTexture();
- if (!inGrab)
- emit textureChanged();
+ emit textureChanged();
}
bool QQuickContext2DTexture::setCanvasSize(const QSize &size)
@@ -185,8 +176,6 @@ bool QQuickContext2DTexture::setDirtyRect(const QRect &r)
void QQuickContext2DTexture::canvasChanged(const QSize& canvasSize, const QSize& tileSize, const QRect& canvasWindow, const QRect& dirtyRect, bool smooth)
{
- lock();
-
QSize ts = tileSize;
if (ts.width() > canvasSize.width())
ts.setWidth(canvasSize.width());
@@ -209,20 +198,15 @@ void QQuickContext2DTexture::canvasChanged(const QSize& canvasSize, const QSize&
setDirtyRect(dirtyRect);
setSmooth(smooth);
-
- unlock();
}
-void QQuickContext2DTexture::paintWithoutTiles()
+void QQuickContext2DTexture::paintWithoutTiles(QQuickContext2DCommandBuffer *ccb)
{
- QQuickContext2DCommandBuffer* ccb = m_context->nextBuffer();
-
if (!ccb || ccb->isEmpty())
return;
QPaintDevice* device = beginPainting();
if (!device) {
- delete ccb;
endPainting();
return;
}
@@ -238,100 +222,58 @@ void QQuickContext2DTexture::paintWithoutTiles()
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
ccb->replay(&p, m_state);
- ccb->clear();
- delete ccb;
-
endPainting();
-
markDirtyTexture();
}
bool QQuickContext2DTexture::canvasDestroyed()
{
- bool noCanvas = false;
- lock();
- noCanvas = m_item == 0;
- unlock();
- return noCanvas;
+ return m_item == 0;
}
-void QQuickContext2DTexture::paint()
+void QQuickContext2DTexture::paint(QQuickContext2DCommandBuffer *ccb)
{
- if (canvasDestroyed())
+ if (canvasDestroyed()) {
+ delete ccb;
return;
+ }
GLAcquireContext currentContext(m_context->glContext(), m_context->surface());
- if (m_threadRendering && QThread::currentThread() != globalCanvasThreadRenderInstance()) {
- Q_ASSERT(thread() == globalCanvasThreadRenderInstance());
- QMetaObject::invokeMethod(this, "paint", Qt::QueuedConnection);
+ if (!m_tiledCanvas) {
+ paintWithoutTiles(ccb);
+ delete ccb;
return;
}
- if (!m_tiledCanvas) {
- paintWithoutTiles();
- } else {
- lock();
- QRect tiledRegion = createTiles(m_canvasWindow.intersected(QRect(QPoint(0, 0), m_canvasSize)));
- unlock();
-
- if (!tiledRegion.isEmpty()) {
- if (m_threadRendering && !m_doGrabImage) {
- QRect dirtyRect;
-
- lock();
- foreach (QQuickContext2DTile* tile, m_tiles) {
- if (tile->dirty()) {
- if (dirtyRect.isEmpty())
- dirtyRect = tile->rect();
- else
- dirtyRect |= tile->rect();
- }
- }
- unlock();
+ QRect tiledRegion = createTiles(m_canvasWindow.intersected(QRect(QPoint(0, 0), m_canvasSize)));
+ if (!tiledRegion.isEmpty()) {
+ QRect dirtyRect;
+ foreach (QQuickContext2DTile* tile, m_tiles) {
+ if (tile->dirty()) {
+ if (dirtyRect.isEmpty())
+ dirtyRect = tile->rect();
+ else
+ dirtyRect |= tile->rect();
}
+ }
- if (beginPainting()) {
- QQuickContext2D::State oldState = m_state;
- QQuickContext2DCommandBuffer* ccb = m_context->nextBuffer();
- if (!ccb || ccb->isEmpty()) {
- endPainting();
- delete ccb;
- return;
- }
- foreach (QQuickContext2DTile* tile, m_tiles) {
- bool dirtyTile = false, dirtyCanvas = false, smooth = false;
-
- lock();
- dirtyTile = tile->dirty();
- smooth = m_smooth;
- dirtyCanvas = m_dirtyCanvas;
- unlock();
-
- //canvas size or tile size may change during painting tiles
- if (dirtyCanvas) {
- if (m_threadRendering)
- QMetaObject::invokeMethod(this, "paint", Qt::QueuedConnection);
- endPainting();
- return;
- } else if (dirtyTile) {
- ccb->replay(tile->createPainter(smooth), oldState);
- tile->drawFinished();
- lock();
- tile->markDirty(false);
- unlock();
- }
-
- compositeTile(tile);
+ if (beginPainting()) {
+ QQuickContext2D::State oldState = m_state;
+ foreach (QQuickContext2DTile* tile, m_tiles) {
+ if (tile->dirty()) {
+ ccb->replay(tile->createPainter(m_smooth), oldState);
+ tile->drawFinished();
+ tile->markDirty(false);
}
- ccb->clear();
- delete ccb;
- endPainting();
- m_state = oldState;
- markDirtyTexture();
+ compositeTile(tile);
}
+ endPainting();
+ m_state = oldState;
+ markDirtyTexture();
}
}
+ delete ccb;
}
QRect QQuickContext2DTexture::tiledRect(const QRectF& window, const QSize& tileSize)
@@ -438,11 +380,15 @@ QQuickContext2DFBOTexture::QQuickContext2DFBOTexture()
, m_multisampledFbo(0)
, m_paint_device(0)
{
- m_threadRendering = false;
}
QQuickContext2DFBOTexture::~QQuickContext2DFBOTexture()
{
+ if (m_multisampledFbo)
+ m_multisampledFbo->release();
+ else if (m_fbo)
+ m_fbo->release();
+
delete m_fbo;
delete m_multisampledFbo;
delete m_paint_device;
@@ -477,14 +423,7 @@ int QQuickContext2DFBOTexture::textureId() const
bool QQuickContext2DFBOTexture::updateTexture()
{
bool textureUpdated = m_dirtyTexture;
-
m_dirtyTexture = false;
-
- if (m_doGrabImage) {
- grabImage();
- m_condition.wakeOne();
- m_doGrabImage = false;
- }
return textureUpdated;
}
@@ -493,13 +432,6 @@ QQuickContext2DTile* QQuickContext2DFBOTexture::createTile() const
return new QQuickContext2DFBOTile();
}
-void QQuickContext2DFBOTexture::grabImage()
-{
- if (m_fbo) {
- m_grabedImage = m_fbo->toImage();
- }
-}
-
bool QQuickContext2DFBOTexture::doMultisampling() const
{
static bool extensionsChecked = false;
@@ -515,27 +447,22 @@ bool QQuickContext2DFBOTexture::doMultisampling() const
return multisamplingSupported && m_smooth;
}
-QImage QQuickContext2DFBOTexture::toImage(const QRectF& region)
+void QQuickContext2DFBOTexture::grabImage(const QRectF& rf)
{
- const unsigned long context2d_wait_max = 5000;
+ Q_ASSERT(rf.isValid());
- m_doGrabImage = true;
- if (m_item) // forces a call to updatePaintNode (repaints)
- m_item->update();
+ if (!m_fbo) {
+ m_context->setGrabbedImage(QImage());
+ return;
+ }
QImage grabbed;
- m_mutex.lock();
- bool ok = m_condition.wait(&m_mutex, context2d_wait_max);
-
- if (!ok)
- grabbed = QImage();
+ {
+ GLAcquireContext ctx(m_context->glContext(), m_context->surface());
+ grabbed = m_fbo->toImage().mirrored().copy(rf.toRect());
+ }
- if (region.isValid())
- grabbed = m_grabedImage.copy(region.toRect());
- else
- grabbed = m_grabedImage;
- m_grabedImage = QImage();
- return grabbed;
+ m_context->setGrabbedImage(grabbed);
}
void QQuickContext2DFBOTexture::compositeTile(QQuickContext2DTile* tile)
@@ -551,15 +478,17 @@ void QQuickContext2DFBOTexture::compositeTile(QQuickContext2DTile* tile)
QOpenGLFramebufferObject::blitFramebuffer(m_fbo, target, t->fbo(), source);
}
}
+
QQuickCanvasItem::RenderTarget QQuickContext2DFBOTexture::renderTarget() const
{
return QQuickCanvasItem::FramebufferObject;
}
+
QPaintDevice* QQuickContext2DFBOTexture::beginPainting()
{
QQuickContext2DTexture::beginPainting();
- if (m_canvasWindow.size().isEmpty() && !m_threadRendering) {
+ if (m_canvasWindow.size().isEmpty()) {
delete m_fbo;
delete m_multisampledFbo;
delete m_paint_device;
@@ -615,78 +544,27 @@ QPaintDevice* QQuickContext2DFBOTexture::beginPainting()
void QQuickContext2DFBOTexture::endPainting()
{
QQuickContext2DTexture::endPainting();
- if (m_multisampledFbo) {
+ if (m_multisampledFbo)
QOpenGLFramebufferObject::blitFramebuffer(m_fbo, m_multisampledFbo);
- m_multisampledFbo->release();
- } else if (m_fbo)
- m_fbo->release();
-}
-void qt_quit_context2d_render_thread()
-{
- QThread* thread = globalCanvasThreadRenderInstance();
-
- if (thread->isRunning()) {
- thread->exit(0);
- thread->wait(1000);
- }
}
-QQuickContext2DImageTexture::QQuickContext2DImageTexture(bool threadRendering)
+QQuickContext2DImageTexture::QQuickContext2DImageTexture()
: QQuickContext2DTexture()
- , m_texture(new QSGPlainTexture())
+ , m_texture(0)
{
- m_texture->setOwnsTexture(true);
- m_texture->setHasMipmaps(false);
-
- m_threadRendering = threadRendering;
-
- if (m_threadRendering) {
- QThread* thread = globalCanvasThreadRenderInstance();
- moveToThread(thread);
-
- if (!thread->isRunning()) {
- qAddPostRoutine(qt_quit_context2d_render_thread); // XXX: change this method
- thread->start();
- }
- }
}
QQuickContext2DImageTexture::~QQuickContext2DImageTexture()
{
- delete m_texture;
+ if (m_texture && m_texture->thread() != QThread::currentThread())
+ m_texture->deleteLater();
+ else
+ delete m_texture;
}
int QQuickContext2DImageTexture::textureId() const
{
- return m_texture->textureId();
-}
-
-void QQuickContext2DImageTexture::lock()
-{
- if (m_threadRendering)
- m_mutex.lock();
-}
-void QQuickContext2DImageTexture::unlock()
-{
- if (m_threadRendering)
- m_mutex.unlock();
-}
-
-void QQuickContext2DImageTexture::wait()
-{
- if (m_threadRendering)
- m_waitCondition.wait(&m_mutex);
-}
-
-void QQuickContext2DImageTexture::wake()
-{
- if (m_threadRendering)
- m_waitCondition.wakeOne();
-}
-
-bool QQuickContext2DImageTexture::supportDirectRendering() const
-{
- return !m_threadRendering;
+ return imageTexture()->textureId();
}
QQuickCanvasItem::RenderTarget QQuickContext2DImageTexture::renderTarget() const
@@ -696,14 +574,14 @@ QQuickCanvasItem::RenderTarget QQuickContext2DImageTexture::renderTarget() const
void QQuickContext2DImageTexture::bind()
{
- m_texture->bind();
+ imageTexture()->bind();
}
bool QQuickContext2DImageTexture::updateTexture()
{
bool textureUpdated = m_dirtyTexture;
if (m_dirtyTexture) {
- m_texture->setImage(m_image);
+ imageTexture()->setImage(m_image);
m_dirtyTexture = false;
}
return textureUpdated;
@@ -714,26 +592,23 @@ QQuickContext2DTile* QQuickContext2DImageTexture::createTile() const
return new QQuickContext2DImageTile();
}
-void QQuickContext2DImageTexture::grabImage(const QRect& r)
+void QQuickContext2DImageTexture::grabImage(const QRectF& rf)
{
- m_doGrabImage = true;
- paint();
- m_doGrabImage = false;
- m_grabedImage = m_image.copy(r);
+ Q_ASSERT(rf.isValid());
+ Q_ASSERT(m_context);
+ QImage grabbed = m_image.copy(rf.toRect());
+ m_context->setGrabbedImage(grabbed);
}
-QImage QQuickContext2DImageTexture::toImage(const QRectF& rect)
+QSGPlainTexture *QQuickContext2DImageTexture::imageTexture() const
{
- QRect r = rect.isValid() ? rect.toRect() : QRect(QPoint(0, 0), m_canvasWindow.size());
- if (threadRendering()) {
- wake();
- QMetaObject::invokeMethod(this, "grabImage", Qt::BlockingQueuedConnection, Q_ARG(QRect, r));
- } else {
- QMetaObject::invokeMethod(this, "grabImage", Qt::DirectConnection, Q_ARG(QRect, r));
+ if (!m_texture) {
+ QQuickContext2DImageTexture *that = const_cast<QQuickContext2DImageTexture *>(this);
+ that->m_texture = new QSGPlainTexture;
+ that->m_texture->setOwnsTexture(true);
+ that->m_texture->setHasMipmaps(false);
}
- QImage image = m_grabedImage;
- m_grabedImage = QImage();
- return image;
+ return m_texture;
}
QPaintDevice* QQuickContext2DImageTexture::beginPainting()
@@ -762,14 +637,11 @@ void QQuickContext2DImageTexture::compositeTile(QQuickContext2DTile* tile)
source.moveTo(source.topLeft() - t->rect().topLeft());
target.moveTo(target.topLeft() - m_canvasWindow.topLeft());
- lock();
m_painter.begin(&m_image);
m_painter.setCompositionMode(QPainter::CompositionMode_Source);
m_painter.drawImage(target, t->image(), source);
m_painter.end();
- unlock();
}
}
QT_END_NAMESPACE
-
diff --git a/src/quick/items/context2d/qquickcontext2dtexture_p.h b/src/quick/items/context2d/qquickcontext2dtexture_p.h
index 81b239dc16..684185572c 100644
--- a/src/quick/items/context2d/qquickcontext2dtexture_p.h
+++ b/src/quick/items/context2d/qquickcontext2dtexture_p.h
@@ -70,15 +70,7 @@ public:
virtual bool hasAlphaChannel() const {return true;}
virtual bool hasMipmaps() const {return false;}
virtual QSize textureSize() const;
- virtual void lock() {}
- virtual void unlock() {}
- virtual void wait() {}
- virtual void wake() {}
- bool threadRendering() const {return m_threadRendering;}
- virtual bool supportThreadRendering() const = 0;
- virtual bool supportDirectRendering() const = 0;
virtual QQuickCanvasItem::RenderTarget renderTarget() const = 0;
- virtual QImage toImage(const QRectF& region = QRectF()) = 0;
static QRect tiledRect(const QRectF& window, const QSize& tileSize);
bool setCanvasSize(const QSize &size);
@@ -86,18 +78,20 @@ public:
bool setCanvasWindow(const QRect& canvasWindow);
void setSmooth(bool smooth);
bool setDirtyRect(const QRect &dirtyRect);
- virtual void canvasChanged(const QSize& canvasSize, const QSize& tileSize, const QRect& canvasWindow, const QRect& dirtyRect, bool smooth);
bool canvasDestroyed();
+
Q_SIGNALS:
void textureChanged();
public Q_SLOTS:
void markDirtyTexture();
void setItem(QQuickCanvasItem* item);
- void paint();
+ void canvasChanged(const QSize& canvasSize, const QSize& tileSize, const QRect& canvasWindow, const QRect& dirtyRect, bool smooth);
+ void paint(QQuickContext2DCommandBuffer *ccb);
+ virtual void grabImage(const QRectF& region = QRectF()) = 0;
protected:
- void paintWithoutTiles();
+ void paintWithoutTiles(QQuickContext2DCommandBuffer *ccb);
virtual QPaintDevice* beginPainting() {m_painting = true; return 0; }
virtual void endPainting() {m_painting = false;}
virtual QQuickContext2DTile* createTile() const = 0;
@@ -120,10 +114,8 @@ protected:
uint m_dirtyCanvas : 1;
uint m_canvasWindowChanged : 1;
uint m_dirtyTexture : 1;
- uint m_threadRendering : 1;
uint m_smooth : 1;
uint m_tiledCanvas : 1;
- uint m_doGrabImage : 1;
uint m_painting : 1;
};
@@ -137,23 +129,19 @@ public:
virtual int textureId() const;
virtual bool updateTexture();
virtual QQuickContext2DTile* createTile() const;
- virtual QImage toImage(const QRectF& region = QRectF());
virtual QPaintDevice* beginPainting();
virtual void endPainting();
QRectF normalizedTextureSubRect() const;
- virtual bool supportThreadRendering() const {return false;}
- virtual bool supportDirectRendering() const {return false;}
virtual QQuickCanvasItem::RenderTarget renderTarget() const;
virtual void compositeTile(QQuickContext2DTile* tile);
virtual void bind();
QSize adjustedTileSize(const QSize &ts);
-private Q_SLOTS:
- void grabImage();
+public Q_SLOTS:
+ virtual void grabImage(const QRectF& region = QRectF());
private:
bool doMultisampling() const;
- QImage m_grabedImage;
QOpenGLFramebufferObject *m_fbo;
QOpenGLFramebufferObject *m_multisampledFbo;
QMutex m_mutex;
@@ -168,31 +156,24 @@ class QQuickContext2DImageTexture : public QQuickContext2DTexture
Q_OBJECT
public:
- QQuickContext2DImageTexture(bool threadRendering = true);
+ QQuickContext2DImageTexture();
~QQuickContext2DImageTexture();
virtual int textureId() const;
virtual void bind();
- virtual bool supportThreadRendering() const {return true;}
- virtual bool supportDirectRendering() const;
+
virtual QQuickCanvasItem::RenderTarget renderTarget() const;
- virtual void lock();
- virtual void unlock();
- virtual void wait();
- virtual void wake();
virtual bool updateTexture();
virtual QQuickContext2DTile* createTile() const;
- virtual QImage toImage(const QRectF& region = QRectF());
virtual QPaintDevice* beginPainting();
virtual void compositeTile(QQuickContext2DTile* tile);
-private Q_SLOTS:
- void grabImage(const QRect& r);
+public Q_SLOTS:
+ virtual void grabImage(const QRectF& region = QRectF());
+
private:
+ QSGPlainTexture *imageTexture() const;
QImage m_image;
- QImage m_grabedImage;
- QMutex m_mutex;
- QWaitCondition m_waitCondition;
QPainter m_painter;
QSGPlainTexture* m_texture;
};