QT_BEGIN_NAMESPACE
+class QQuickCanvasNode : public QSGSimpleTextureNode
+{
+public:
+ QQuickCanvasNode() {
+ qsgnode_set_description(this, QStringLiteral("canvasnode"));
+ setOwnsTexture(true);
+ }
+};
+
+class QQuickCanvasTextureProvider : public QSGTextureProvider
+{
+public:
+ QQuickCanvasNode *node;
+ QSGTexture *texture() const Q_DECL_OVERRIDE { return node ? node->texture() : 0; }
+ void fireTextureChanged() { emit textureChanged(); }
+};
+
QQuickCanvasPixmap::QQuickCanvasPixmap(const QImage& image)
: m_pixmap(0)
, m_image(image)
QHash<QUrl, QQmlRefPointer<QQuickCanvasPixmap> > pixmaps;
QUrl baseUrl;
QMap<int, QV4::PersistentValue> animationCallbacks;
+ mutable QQuickCanvasTextureProvider *textureProvider;
+ QQuickCanvasNode *node;
};
QQuickCanvasItemPrivate::QQuickCanvasItemPrivate()
, available(false)
, renderTarget(QQuickCanvasItem::Image)
, renderStrategy(QQuickCanvasItem::Immediate)
+ , textureProvider(0)
+ , node(0)
{
implicitAntialiasing = true;
}
them in the \c onImageLoaded handler.
\endlist
+ Starting Qt 5.4, the Canvas is a
+ \l{QSGTextureProvider}{texture provider}
+ and can be used directly in \l {ShaderEffect}{ShaderEffects} and other
+ classes that consume texture providers.
+
\sa Context2D
*/
{
Q_D(QQuickCanvasItem);
delete d->context;
+ if (d->textureProvider)
+ QQuickWindowQObjectCleanupJob::schedule(window(), d->textureProvider);
}
/*!
delete d->context;
d->context = 0;
}
+ d->node = 0; // managed by the scene graph, just reset the pointer
+ if (d->textureProvider) {
+ QQuickWindowQObjectCleanupJob::schedule(window(), d->textureProvider);
+ d->textureProvider = 0;
+ }
}
void QQuickCanvasItem::invalidateSG()
Q_D(QQuickCanvasItem);
d->context->deleteLater();
d->context = 0;
+ d->node = 0; // managed by the scene graph, just reset the pointer
+ delete d->textureProvider;
+ d->textureProvider = 0;
}
void QQuickCanvasItem::componentComplete()
}
}
-class QQuickCanvasNode : public QSGSimpleTextureNode
-{
-public:
- ~QQuickCanvasNode()
- {
- delete texture();
- }
-};
-
QSGNode *QQuickCanvasItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
Q_D(QQuickCanvasItem);
if (!d->context || d->canvasWindow.size().isEmpty()) {
+ if (d->textureProvider) {
+ d->textureProvider->node = 0;
+ d->textureProvider->fireTextureChanged();
+ }
delete oldNode;
return 0;
}
QQuickCanvasNode *node = static_cast<QQuickCanvasNode*>(oldNode);
- if (!node)
+ if (!node) {
node = new QQuickCanvasNode();
+ d->node = node;
+ }
+
if (d->smooth)
node->setFiltering(QSGTexture::Linear);
QSGTexture *texture = factory->textureForNextFrame(node->texture());
if (!texture) {
delete node;
+ d->node = 0;
+ if (d->textureProvider) {
+ d->textureProvider->node = 0;
+ d->textureProvider->fireTextureChanged();
+ }
return 0;
}
node->setTexture(texture);
node->setRect(QRectF(QPoint(0, 0), d->canvasWindow.size()));
+
+ if (d->textureProvider) {
+ d->textureProvider->node = node;
+ d->textureProvider->fireTextureChanged();
+ }
return node;
}
+bool QQuickCanvasItem::isTextureProvider() const
+{
+ return true;
+}
+
+QSGTextureProvider *QQuickCanvasItem::textureProvider() const
+{
+ Q_D(const QQuickCanvasItem);
+ QQuickWindow *w = window();
+ if (!w || !w->openglContext() || QThread::currentThread() != w->openglContext()->thread()) {
+ qWarning("QQuickCanvasItem::textureProvider: can only be queried on the rendering thread of an exposed window");
+ return 0;
+ }
+ if (!d->textureProvider)
+ d->textureProvider = new QQuickCanvasTextureProvider;
+ d->textureProvider->node = d->node;
+ return d->textureProvider;
+}
+
/*!
\qmlmethod object QtQuick::Canvas::getContext(string contextId, any... args)