aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/context2d/qquickcontext2dtexture.cpp
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/qquickcontext2dtexture.cpp
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/qquickcontext2dtexture.cpp')
-rw-r--r--src/quick/items/context2d/qquickcontext2dtexture.cpp274
1 files changed, 73 insertions, 201 deletions
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
-