#include <QtGui/qmatrix4x4.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qabstractanimation.h>
+#include <QtDeclarative/qdeclarativeincubator.h>
#include <private/qdeclarativedebugtrace_p.h>
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:
, thread(0)
, animationDriver(0)
, renderTarget(0)
+ , incubationController(0)
{
}
QSGItemPrivate *rootItemPrivate = QSGItemPrivate::get(d->rootItem);
rootItemPrivate->removeFromDirtyList();
+ delete d->incubationController; d->incubationController = 0;
+
delete d->rootItem; d->rootItem = 0;
d->cleanupNodes();
}
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<QSGCanvasPrivate *>(d));
+ return d->incubationController;
+}
void QSGCanvasRenderLoop::createGLContext()
#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");
inSync = false;
// Wake GUI after sync to let it continue animating and event processing.
+ allowMainThreadProcessingFlag = true;
wake();
unlock();
#ifdef THREAD_DEBUG
class QTouchEvent;
class QSGCanvasRenderLoop;
+class QSGCanvasIncubationController;
class QSGCanvasPrivate : public QWindowPrivate
{
QOpenGLFramebufferObject *renderTarget;
QHash<int, QSGItem *> itemForTouchPointId;
+
+ mutable QSGCanvasIncubationController *incubationController;
};
class QSGCanvasRenderLoop
virtual void animationStarted() = 0;
virtual void animationStopped() = 0;
virtual void moveContextToThread(QSGContext *) { }
+ virtual bool *allowMainThreadProcessing() { return 0; }
protected:
void initializeSceneGraph() { d->initializeSceneGraph(); }
public:
QSGCanvasRenderThread()
: mutex(QMutex::NonRecursive)
+ , allowMainThreadProcessingFlag(true)
, animationRunning(false)
, isGuiBlocked(0)
, isPaintCompleted(false)
void setWindowSize(const QSize &size) { windowSize = size; }
void maybeUpdate();
void moveContextToThread(QSGContext *c) { c->moveToThread(this); }
+ bool *allowMainThreadProcessing() { return &allowMainThreadProcessingFlag; }
bool event(QEvent *);
QMutex mutex;
QWaitCondition condition;
+ bool allowMainThreadProcessingFlag;
+
QSize windowSize;
QSize renderedSize;