aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@nokia.com>2011-08-27 09:04:20 +0200
committerSamuel Rødal <samuel.rodal@nokia.com>2011-08-29 08:36:35 +0200
commit926ddffa547a9f37a67554cce810045c074172b7 (patch)
tree95a09a5579fccf1708978ceda9d0ffb9944659df /src
parent8e6ecb56e5d61ce661422779c9d9cbf22f081a34 (diff)
separated out render thread code
Change-Id: I9e440ef172055f626c908d4dd733d0243feb77c9 Reviewed-on: http://codereview.qt.nokia.com/3700 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/declarative/items/qsgcanvas.cpp176
-rw-r--r--src/declarative/items/qsgcanvas.h4
-rw-r--r--src/declarative/items/qsgcanvas_p.h79
3 files changed, 169 insertions, 90 deletions
diff --git a/src/declarative/items/qsgcanvas.cpp b/src/declarative/items/qsgcanvas.cpp
index 0d4001a393..bc642e4097 100644
--- a/src/declarative/items/qsgcanvas.cpp
+++ b/src/declarative/items/qsgcanvas.cpp
@@ -178,28 +178,38 @@ void QSGCanvas::resizeEvent(QResizeEvent *e)
d->thread->resize(size());
}
+void QSGCanvas::animationStarted()
+{
+ d_func()->thread->animationStarted();
+}
+
+void QSGCanvas::animationStopped()
+{
+ d_func()->thread->animationStopped();
+}
+
void QSGCanvas::showEvent(QShowEvent *e)
{
Q_D(QSGCanvas);
if (d->vsyncAnimations) {
if (!d->animationDriver) {
d->animationDriver = d->context->createAnimationDriver(this);
- connect(d->animationDriver, SIGNAL(started()), d->thread, SLOT(animationStarted()), Qt::DirectConnection);
- connect(d->animationDriver, SIGNAL(stopped()), d->thread, SLOT(animationStopped()), Qt::DirectConnection);
+ connect(d->animationDriver, SIGNAL(started()), this, SLOT(animationStarted()), Qt::DirectConnection);
+ connect(d->animationDriver, SIGNAL(stopped()), this, SLOT(animationStopped()), Qt::DirectConnection);
}
d->animationDriver->install();
}
if (!d->thread->isRunning()) {
- d->thread->windowSize = size();
- d->thread->startRenderThread();
+ d->thread->setWindowSize(size());
+ d->thread->startRendering();
}
}
void QSGCanvas::hideEvent(QHideEvent *e)
{
Q_D(QSGCanvas);
- d->thread->stopRenderThread();
+ d->thread->stopRendering();
}
@@ -334,8 +344,6 @@ QSGCanvasPrivate::QSGCanvasPrivate()
, mouseGrabberItem(0)
, dirtyItemList(0)
, context(0)
- , animationRunning(false)
- , renderThreadAwakened(false)
, vsyncAnimations(false)
, thread(0)
, animationDriver(0)
@@ -369,7 +377,7 @@ void QSGCanvasPrivate::init(QSGCanvas *c)
thread->d = this;
context = QSGContext::createDefaultContext();
- context->moveToThread(thread);
+ thread->moveCanvasToThread(context);
}
void QSGCanvasPrivate::sceneMouseEventForTransform(QGraphicsSceneMouseEvent &sceneEvent,
@@ -775,7 +783,7 @@ QSGCanvas::~QSGCanvas()
Q_D(QSGCanvas);
if (d->thread->isRunning()) {
- d->thread->stopRenderThread();
+ d->thread->stopRendering();
delete d->thread;
d->thread = 0;
}
@@ -831,27 +839,6 @@ bool QSGCanvas::event(QEvent *e)
{
Q_D(QSGCanvas);
- if (e->type() == QEvent::User) {
- if (!d->thread->syncAlreadyHappened)
- d->thread->sync(false);
-
- d->thread->syncAlreadyHappened = false;
-
- if (d->animationRunning && d->animationDriver) {
-#ifdef THREAD_DEBUG
- qDebug("GUI: Advancing animations...\n");
-#endif
-
- d->animationDriver->advance();
-
-#ifdef THREAD_DEBUG
- qDebug("GUI: Animations advanced...\n");
-#endif
- }
-
- return true;
- }
-
switch (e->type()) {
case QEvent::TouchBegin:
@@ -1775,26 +1762,8 @@ void QSGCanvas::maybeUpdate()
{
Q_D(QSGCanvas);
- if (d->thread && d->thread->isRunning()) {
- Q_ASSERT_X(QThread::currentThread() == QApplication::instance()->thread() || d->thread->inSync,
- "QSGCanvas::update",
- "Function can only be called from GUI thread or during QSGItem::updatePaintNode()");
-
- if (d->thread->inSync) {
- d->thread->isExternalUpdatePending = true;
-
- } else if (!d->renderThreadAwakened) {
-#ifdef THREAD_DEBUG
- printf("GUI: doing update...\n");
-#endif
- d->renderThreadAwakened = true;
- d->thread->lockInGui();
- d->thread->isExternalUpdatePending = true;
- if (d->thread->isRenderBlocked)
- d->thread->wake();
- d->thread->unlockInGui();
- }
- }
+ if (d->thread && d->thread->isRunning())
+ d->thread->maybeUpdate();
}
/*!
@@ -1876,20 +1845,26 @@ QImage QSGCanvas::grabFrameBuffer()
}
+
+void QSGCanvasRenderLoop::createGLContext()
+{
+ gl = new QGuiGLContext();
+ gl->create();
+}
+
+
void QSGCanvasRenderThread::run()
{
#ifdef THREAD_DEBUG
qDebug("QML Rendering Thread Started");
#endif
- if (!guiContext) {
- guiContext = new QGuiGLContext();
- guiContext->create();
- guiContext->makeCurrent(renderer);
-
- d->initializeSceneGraph();
+ if (!glContext()) {
+ createGLContext();
+ makeCurrent();
+ initializeSceneGraph();
} else {
- guiContext->makeCurrent(renderer);
+ makeCurrent();
}
while (!shouldExit) {
@@ -1916,7 +1891,7 @@ void QSGCanvasRenderThread::run()
#ifdef THREAD_DEBUG
printf(" RenderThread: aquired sync lock...\n");
#endif
- QApplication::postEvent(renderer, new QEvent(QEvent::User));
+ QApplication::postEvent(this, new QEvent(QEvent::User));
#ifdef THREAD_DEBUG
printf(" RenderThread: going to sleep...\n");
#endif
@@ -1929,7 +1904,7 @@ void QSGCanvasRenderThread::run()
printf(" RenderThread: Doing locked sync\n");
#endif
inSync = true;
- d->syncSceneGraph();
+ syncSceneGraph();
inSync = false;
// Wake GUI after sync to let it continue animating and event processing.
@@ -1945,7 +1920,7 @@ void QSGCanvasRenderThread::run()
printf(" RenderThread: rendering... %d x %d\n", windowSize.width(), windowSize.height());
#endif
- d->renderSceneGraph(windowSize);
+ renderSceneGraph(windowSize);
// The content of the target buffer is undefined after swap() so grab needs
// to happen before swap();
@@ -1961,8 +1936,7 @@ void QSGCanvasRenderThread::run()
printf(" RenderThread: wait for swap...\n");
#endif
- guiContext->swapBuffers(renderer);
- emit renderer->frameSwapped();//notify compositor that frame has been swapped
+ swapBuffers();
#ifdef THREAD_DEBUG
printf(" RenderThread: swap complete...\n");
#endif
@@ -1978,7 +1952,7 @@ void QSGCanvasRenderThread::run()
// but we don't want to lock an extra time.
wake();
- if (!d->animationRunning && !isExternalUpdatePending && !shouldExit && !doGrab) {
+ if (!animationRunning && !isExternalUpdatePending && !shouldExit && !doGrab) {
#ifdef THREAD_DEBUG
printf(" RenderThread: nothing to do, going to sleep...\n");
#endif
@@ -1997,7 +1971,7 @@ void QSGCanvasRenderThread::run()
printf(" RenderThread: render loop exited... Good Night!\n");
#endif
- guiContext->doneCurrent();
+ doneCurrent();
lock();
hasExited = true;
@@ -2014,6 +1988,36 @@ void QSGCanvasRenderThread::run()
+bool QSGCanvasRenderThread::event(QEvent *e)
+{
+ Q_ASSERT(QThread::currentThread() == qApp->thread());
+
+ if (e->type() == QEvent::User) {
+ if (!syncAlreadyHappened)
+ sync(false);
+
+ syncAlreadyHappened = false;
+
+ if (animationRunning && animationDriver()) {
+#ifdef THREAD_DEBUG
+ qDebug("GUI: Advancing animations...\n");
+#endif
+
+ animationDriver()->advance();
+
+#ifdef THREAD_DEBUG
+ qDebug("GUI: Animations advanced...\n");
+#endif
+ }
+
+ return true;
+ }
+
+ return QThread::event(e);
+}
+
+
+
void QSGCanvasRenderThread::exhaustSyncEvent()
{
if (isGuiBlockPending) {
@@ -2030,17 +2034,17 @@ void QSGCanvasRenderThread::sync(bool guiAlreadyLocked)
printf("GUI: sync - %s\n", guiAlreadyLocked ? "outside event" : "inside event");
#endif
if (!guiAlreadyLocked)
- d->thread->lockInGui();
+ lockInGui();
- d->renderThreadAwakened = false;
+ renderThreadAwakened = false;
- d->polishItems();
+ polishItems();
- d->thread->wake();
- d->thread->wait();
+ wake();
+ wait();
if (!guiAlreadyLocked)
- d->thread->unlockInGui();
+ unlockInGui();
}
@@ -2090,7 +2094,7 @@ void QSGCanvasRenderThread::animationStarted()
lockInGui();
- d->animationRunning = true;
+ animationRunning = true;
if (isRenderBlocked)
wake();
@@ -2107,7 +2111,7 @@ void QSGCanvasRenderThread::animationStopped()
#endif
lockInGui();
- d->animationRunning = false;
+ animationRunning = false;
unlockInGui();
}
@@ -2158,7 +2162,7 @@ void QSGCanvasRenderThread::resize(const QSize &size)
-void QSGCanvasRenderThread::startRenderThread()
+void QSGCanvasRenderThread::startRendering()
{
#ifdef THREAD_DEBUG
printf("GUI: Starting Render Thread\n");
@@ -2172,7 +2176,7 @@ void QSGCanvasRenderThread::startRenderThread()
-void QSGCanvasRenderThread::stopRenderThread()
+void QSGCanvasRenderThread::stopRendering()
{
#ifdef THREAD_DEBUG
printf("GUI: stopping render thread\n");
@@ -2247,6 +2251,30 @@ QImage QSGCanvasRenderThread::grab()
}
+
+void QSGCanvasRenderThread::maybeUpdate()
+{
+ Q_ASSERT_X(QThread::currentThread() == QApplication::instance()->thread() || inSync,
+ "QSGCanvas::update",
+ "Function can only be called from GUI thread or during QSGItem::updatePaintNode()");
+
+ if (inSync) {
+ isExternalUpdatePending = true;
+
+ } else if (!renderThreadAwakened) {
+#ifdef THREAD_DEBUG
+ printf("GUI: doing update...\n");
+#endif
+ renderThreadAwakened = true;
+ lockInGui();
+ isExternalUpdatePending = true;
+ if (isRenderBlocked)
+ wake();
+ unlockInGui();
+ }
+}
+
+
#include "moc_qsgcanvas.cpp"
QT_END_NAMESPACE
diff --git a/src/declarative/items/qsgcanvas.h b/src/declarative/items/qsgcanvas.h
index 86efdcbfdc..be6b173de9 100644
--- a/src/declarative/items/qsgcanvas.h
+++ b/src/declarative/items/qsgcanvas.h
@@ -115,10 +115,12 @@ protected:
private Q_SLOTS:
void sceneGraphChanged();
void maybeUpdate();
+ void animationStarted();
+ void animationStopped();
private:
friend class QSGItem;
- friend class QSGCanvasRenderThread;
+ friend class QSGCanvasRenderLoop;
Q_DISABLE_COPY(QSGCanvas)
};
diff --git a/src/declarative/items/qsgcanvas_p.h b/src/declarative/items/qsgcanvas_p.h
index bf65e95812..7daa1423d3 100644
--- a/src/declarative/items/qsgcanvas_p.h
+++ b/src/declarative/items/qsgcanvas_p.h
@@ -82,7 +82,7 @@ public:
class QSGCanvasPrivate;
class QTouchEvent;
-class QSGCanvasRenderThread;
+class QSGCanvasRenderLoop;
class QSGCanvasPrivate : public QWindowPrivate
{
@@ -161,12 +161,9 @@ public:
QSGContext *context;
- uint animationRunning: 1;
- uint renderThreadAwakened : 1;
-
uint vsyncAnimations : 1;
- QSGCanvasRenderThread *thread;
+ QSGCanvasRenderLoop *thread;
QSize widgetSize;
QSize viewportSize;
@@ -177,15 +174,64 @@ public:
QHash<int, QSGItem *> itemForTouchPointId;
};
+class QSGCanvasRenderLoop
+{
+public:
+ QSGCanvasRenderLoop()
+ : d(0)
+ , renderer(0)
+ , gl(0)
+ {
+ }
+ virtual ~QSGCanvasRenderLoop()
+ {
+ delete gl;
+ }
+
+ friend class QSGCanvasPrivate;
+
+ virtual void paint() = 0;
+ virtual void resize(const QSize &size) = 0;
+ virtual void startRendering() = 0;
+ virtual void stopRendering() = 0;
+ virtual QImage grab() = 0;
+ virtual void setWindowSize(const QSize &size) = 0;
+ virtual void maybeUpdate() = 0;
+ virtual bool isRunning() const = 0;
+ virtual void animationStarted() = 0;
+ virtual void animationStopped() = 0;
+ virtual void moveCanvasToThread(QSGContext *) { }
+
+protected:
+ void initializeSceneGraph() { d->initializeSceneGraph(); }
+ void syncSceneGraph() { d->syncSceneGraph(); }
+ void renderSceneGraph(const QSize &size) { d->renderSceneGraph(size); }
+ void polishItems() { d->polishItems(); }
+ QAnimationDriver *animationDriver() const { return d->animationDriver; }
+
+ inline QGuiGLContext *glContext() const { return gl; }
+ void createGLContext();
+ void makeCurrent() { gl->makeCurrent(renderer); }
+ void doneCurrent() { gl->doneCurrent(); }
+ void swapBuffers() {
+ gl->swapBuffers(renderer);
+ emit renderer->frameSwapped();
+ }
+
+private:
+ QSGCanvasPrivate *d;
+ QSGCanvas *renderer;
+ QGuiGLContext *gl;
+};
-class QSGCanvasRenderThread : public QThread
+class QSGCanvasRenderThread : public QThread, public QSGCanvasRenderLoop
{
Q_OBJECT
public:
QSGCanvasRenderThread()
: mutex(QMutex::NonRecursive)
- , guiContext(0)
+ , animationRunning(false)
, isGuiBlocked(0)
, isPaintCompleted(false)
, isGuiBlockPending(false)
@@ -196,6 +242,7 @@ public:
, doGrab(false)
, shouldExit(false)
, hasExited(false)
+ , renderThreadAwakened(false)
{}
inline void lock() { mutex.lock(); }
@@ -208,10 +255,16 @@ public:
void paint();
void resize(const QSize &size);
- void startRenderThread();
- void stopRenderThread();
+ void startRendering();
+ void stopRendering();
void exhaustSyncEvent();
void sync(bool guiAlreadyLocked);
+ bool isRunning() const { return QThread::isRunning(); }
+ void setWindowSize(const QSize &size) { windowSize = size; }
+ void maybeUpdate();
+ void moveCanvasToThread(QSGCanvas *c) { c->moveToThread(this); }
+
+ bool event(QEvent *);
QImage grab();
@@ -226,11 +279,7 @@ public:
QSize windowSize;
QSize renderedSize;
- QSGCanvas *renderer;
- QSGCanvasPrivate *d;
-
- QGuiGLContext *guiContext;
-
+ uint animationRunning: 1;
int isGuiBlocked;
uint isPaintCompleted : 1;
uint isGuiBlockPending : 1;
@@ -238,10 +287,10 @@ public:
uint isExternalUpdatePending : 1;
uint syncAlreadyHappened : 1;
uint inSync : 1;
-
uint doGrab : 1;
uint shouldExit : 1;
uint hasExited : 1;
+ uint renderThreadAwakened : 1;
QImage grabContent;