From: Aaron Kennedy Date: Fri, 30 Sep 2011 04:26:56 +0000 (+1000) Subject: Add a QSGCanvas incubation controller X-Git-Tag: qt-v5.0.0-alpha1~1518 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f07805ff56f9a2236f22ed7614aa8c4fc0dfdb46;p=profile%2Fivi%2Fqtdeclarative.git Add a QSGCanvas incubation controller Change-Id: I0324c32240746b013eeefaae2dfaa390d6e777e5 Task-number: QTBUG-21151 Reviewed-on: http://codereview.qt-project.org/5828 Reviewed-by: Aaron Kennedy --- diff --git a/src/declarative/items/qsgcanvas.cpp b/src/declarative/items/qsgcanvas.cpp index cdef37f..2ced204 100644 --- a/src/declarative/items/qsgcanvas.cpp +++ b/src/declarative/items/qsgcanvas.cpp @@ -60,6 +60,7 @@ #include #include #include +#include #include @@ -78,6 +79,45 @@ void QSGCanvasPrivate::updateFocusItemTransform() qApp->inputPanel()->setInputItemTransform(QSGItemPrivate::get(focus)->itemToCanvasTransform()); } +class QSGCanvasIncubationController : public QObject, public QDeclarativeIncubationController +{ +public: + QSGCanvasIncubationController(QSGCanvasPrivate *canvas) + : m_canvas(canvas), m_eventSent(false) {} + +protected: + virtual bool event(QEvent *e) + { + if (e->type() == QEvent::User) { + Q_ASSERT(m_eventSent); + + bool *amtp = m_canvas->thread->allowMainThreadProcessing(); + while (incubatingObjectCount()) { + if (amtp) + incubateWhile(amtp); + else + incubateFor(5); + QCoreApplication::processEvents(); + } + + m_eventSent = false; + } + return QObject::event(e); + } + + virtual void incubatingObjectCountChanged(int count) + { + if (count && !m_eventSent) { + m_eventSent = true; + QCoreApplication::postEvent(this, new QEvent(QEvent::User)); + } + } + +private: + QSGCanvasPrivate *m_canvas; + bool m_eventSent; +}; + class QSGCanvasPlainRenderLoop : public QObject, public QSGCanvasRenderLoop { public: @@ -416,6 +456,7 @@ QSGCanvasPrivate::QSGCanvasPrivate() , thread(0) , animationDriver(0) , renderTarget(0) + , incubationController(0) { } @@ -792,6 +833,8 @@ QSGCanvas::~QSGCanvas() QSGItemPrivate *rootItemPrivate = QSGItemPrivate::get(d->rootItem); rootItemPrivate->removeFromDirtyList(); + delete d->incubationController; d->incubationController = 0; + delete d->rootItem; d->rootItem = 0; d->cleanupNodes(); } @@ -1830,6 +1873,21 @@ QImage QSGCanvas::grabFrameBuffer() return d->thread ? d->thread->grab() : QImage(); } +/*! + Returns an incubation controller that splices incubation between frames + for this canvas. QSGView automatically installs this controller for you. + + The controller is owned by the canvas and will be destroyed when the canvas + is deleted. +*/ +QDeclarativeIncubationController *QSGCanvas::incubationController() const +{ + Q_D(const QSGCanvas); + + if (!d->incubationController) + d->incubationController = new QSGCanvasIncubationController(const_cast(d)); + return d->incubationController; +} void QSGCanvasRenderLoop::createGLContext() @@ -1878,6 +1936,7 @@ void QSGCanvasRenderThread::run() #ifdef THREAD_DEBUG printf(" RenderThread: aquired sync lock...\n"); #endif + allowMainThreadProcessingFlag = false; QCoreApplication::postEvent(this, new QEvent(QEvent::User)); #ifdef THREAD_DEBUG printf(" RenderThread: going to sleep...\n"); @@ -1895,6 +1954,7 @@ void QSGCanvasRenderThread::run() inSync = false; // Wake GUI after sync to let it continue animating and event processing. + allowMainThreadProcessingFlag = true; wake(); unlock(); #ifdef THREAD_DEBUG diff --git a/src/declarative/items/qsgcanvas.h b/src/declarative/items/qsgcanvas.h index a2bb278..094fe40 100644 --- a/src/declarative/items/qsgcanvas.h +++ b/src/declarative/items/qsgcanvas.h @@ -56,6 +56,7 @@ class QSGItem; class QSGEngine; class QSGCanvasPrivate; class QOpenGLFramebufferObject; +class QDeclarativeIncubationController; class Q_DECLARATIVE_EXPORT QSGCanvas : public QWindow { @@ -85,6 +86,8 @@ public: void setRenderTarget(QOpenGLFramebufferObject *fbo); QOpenGLFramebufferObject *renderTarget() const; + QDeclarativeIncubationController *incubationController() const; + Q_SIGNALS: void frameSwapped(); void sceneGraphInitialized(); diff --git a/src/declarative/items/qsgcanvas_p.h b/src/declarative/items/qsgcanvas_p.h index 6a8e0a0..4a53e6b 100644 --- a/src/declarative/items/qsgcanvas_p.h +++ b/src/declarative/items/qsgcanvas_p.h @@ -84,6 +84,7 @@ class QSGCanvasPrivate; class QTouchEvent; class QSGCanvasRenderLoop; +class QSGCanvasIncubationController; class QSGCanvasPrivate : public QWindowPrivate { @@ -167,6 +168,8 @@ public: QOpenGLFramebufferObject *renderTarget; QHash itemForTouchPointId; + + mutable QSGCanvasIncubationController *incubationController; }; class QSGCanvasRenderLoop @@ -196,6 +199,7 @@ public: virtual void animationStarted() = 0; virtual void animationStopped() = 0; virtual void moveContextToThread(QSGContext *) { } + virtual bool *allowMainThreadProcessing() { return 0; } protected: void initializeSceneGraph() { d->initializeSceneGraph(); } @@ -226,6 +230,7 @@ class QSGCanvasRenderThread : public QThread, public QSGCanvasRenderLoop public: QSGCanvasRenderThread() : mutex(QMutex::NonRecursive) + , allowMainThreadProcessingFlag(true) , animationRunning(false) , isGuiBlocked(0) , isPaintCompleted(false) @@ -258,6 +263,7 @@ public: void setWindowSize(const QSize &size) { windowSize = size; } void maybeUpdate(); void moveContextToThread(QSGContext *c) { c->moveToThread(this); } + bool *allowMainThreadProcessing() { return &allowMainThreadProcessingFlag; } bool event(QEvent *); @@ -271,6 +277,8 @@ public: QMutex mutex; QWaitCondition condition; + bool allowMainThreadProcessingFlag; + QSize windowSize; QSize renderedSize; diff --git a/src/declarative/items/qsgview.cpp b/src/declarative/items/qsgview.cpp index 236fd4e..7d9a451 100644 --- a/src/declarative/items/qsgview.cpp +++ b/src/declarative/items/qsgview.cpp @@ -62,9 +62,13 @@ DEFINE_BOOL_CONFIG_OPTION(frameRateDebug, QML_SHOW_FRAMERATE) void QSGViewPrivate::init() { + Q_Q(QSGView); + QDeclarativeEnginePrivate::get(&engine)->sgContext = QSGCanvasPrivate::context; - QDeclarativeInspectorService::instance()->addView(q_func()); + engine.setIncubationController(q->incubationController()); + + QDeclarativeInspectorService::instance()->addView(q); } QSGViewPrivate::QSGViewPrivate()