{
}
-void QQuickCanvasContext::sync()
-{
-}
-
QT_END_NAMESPACE
virtual void init(QQuickCanvasItem *canvasItem, const QVariantMap &args) = 0;
virtual void prepare(const QSize& canvasSize, const QSize& tileSize, const QRect& canvasWindow, const QRect& dirtyRect, bool smooth);
-
- // Indicate this is a good time to begin composition
virtual void flush();
- // Cause render (if necessary) to surface via execution unit
- virtual void sync();
-
virtual void setV8Engine(QV8Engine *engine) = 0;
virtual v8::Handle<v8::Object> v8value() const = 0;
}
}
- if (d->contextInitialized)
- d->context->flush();
+ if (d->contextInitialized) {
+ if (d->renderStrategy == QQuickCanvasItem::Cooperative)
+ update();
+ else
+ d->context->flush();
+ }
}
QSGNode *QQuickCanvasItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
}
if (d->renderStrategy == QQuickCanvasItem::Cooperative)
- d->context->sync();
+ d->context->flush();
node->setTexture(d->context->texture());
node->setRect(QRectF(QPoint(0, 0), d->canvasWindow.size()));
\image qml-item-canvas-context.gif
*/
-QLockedCommandBuffer::QLockedCommandBuffer(QQuickContext2DCommandBuffer *b)
- : m_buffer(b)
-{
- m_buffer->lockQueue();
-}
-
-QLockedCommandBuffer::~QLockedCommandBuffer()
-{
- m_buffer->unlockQueue();
-}
-
-QQuickContext2DCommandBuffer* QLockedCommandBuffer::operator->() const
-{
- return m_buffer;
-}
Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok);
switch (m_renderTarget) {
case QQuickCanvasItem::Image:
- m_texture = new QQuickContext2DImageTexture(m_renderStrategy == QQuickCanvasItem::Threaded); // ?? || Coop
+ m_texture = new QQuickContext2DImageTexture(m_renderStrategy == QQuickCanvasItem::Threaded);
break;
case QQuickCanvasItem::FramebufferObject:
m_texture = new QQuickContext2DFBOTexture;
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::Cooperative:
- // Add to the update list in SG
- m_canvas->update(); // FIXME
+ // NOTE: On SG Thread
+ m_texture->paint();
break;
}
}
-// On SG render thread
-void QQuickContext2D::sync()
-{
- if (m_renderStrategy == QQuickCanvasItem::Cooperative)
- m_texture->paint();
-}
-
QSGDynamicTexture *QQuickContext2D::texture() const
{
return m_texture;
QImage QQuickContext2D::toImage(const QRectF& bounds)
{
+ switch (m_renderStrategy) {
+ case QQuickCanvasItem::Immediate:
+ case QQuickCanvasItem::Threaded:
+ flush();
+ break;
+ case QQuickCanvasItem::Cooperative:
+ break;
+ }
+
return m_texture->toImage(bounds);
}
}
}
+QQuickContext2DCommandBuffer* QQuickContext2D::nextBuffer()
+{
+ QMutexLocker lock(&m_bufferMutex);
+ return m_bufferQueue.isEmpty() ? 0 : m_bufferQueue.dequeue();
+}
+
QT_END_NAMESPACE
#include <QtGui/qpainterpath.h>
#include <QtCore/qstring.h>
#include <QtCore/qstack.h>
+#include <QtCore/qqueue.h>
#include <private/qv8engine_p.h>
class QQuickPixmap;
class QSGTexture;
-class QLockedCommandBuffer {
-public:
- QLockedCommandBuffer(QQuickContext2DCommandBuffer *b);
- ~QLockedCommandBuffer();
- QQuickContext2DCommandBuffer* operator->() const;
-private:
- QQuickContext2DCommandBuffer *m_buffer;
-};
class Q_QUICK_EXPORT QQuickContext2D : public QQuickCanvasContext
{
void setV8Engine(QV8Engine *eng);
QQuickCanvasItem* canvas() const { return m_canvas; }
- QLockedCommandBuffer buffer() const { return m_buffer; }
+ QQuickContext2DCommandBuffer* buffer() const { return m_buffer; }
+ QQuickContext2DCommandBuffer* nextBuffer();
+
bool bufferValid() const { return m_buffer != 0; }
void popState();
void pushState();
QQuickContext2DTexture *m_texture;
QQuickCanvasItem::RenderTarget m_renderTarget;
QQuickCanvasItem::RenderStrategy m_renderStrategy;
+ QQueue<QQuickContext2DCommandBuffer*> m_bufferQueue;
+ QMutex m_bufferMutex;
};
void QQuickContext2DTexture::paintWithoutTiles()
{
- QLockedCommandBuffer ccb = m_context->buffer();
+ QQuickContext2DCommandBuffer* ccb = m_context->nextBuffer();
- if (ccb->isEmpty())
+ if (!ccb || ccb->isEmpty())
return;
QPaintDevice* device = beginPainting();
if (!device) {
+ delete ccb;
endPainting();
return;
}
ccb->replay(&p, m_state);
ccb->clear();
+ delete ccb;
endPainting();
if (beginPainting()) {
QQuickContext2D::State oldState = m_state;
- QLockedCommandBuffer ccb = m_context->buffer();
+ 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;
compositeTile(tile);
}
ccb->clear();
+ delete ccb;
endPainting();
m_state = oldState;
markDirtyTexture();
c.toDataURL();
wait(100);
- compare(c.paintedCount, 1);
+ compare(c.paintedCount, 2);
compare(c.paintCount, 1);
c.destroy();