diff options
author | Laszlo Agocs <laszlo.agocs@theqtcompany.com> | 2016-05-02 11:41:46 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@theqtcompany.com> | 2016-05-03 10:12:36 +0000 |
commit | 3551093f426ef7bbc222b543f573d5d341a43d8e (patch) | |
tree | c86c0d68c99ae1047e809c9a77ad4c2f4dc7e21e /src | |
parent | dc5b2fd31ccf36f5f6e0ec3a7222bda023c6b1eb (diff) |
D3D12: Painter node
Only supports QImage backing.
As a bonus add some notes to the Context2D docs too.
Change-Id: I18457a1f766d2f136c6864ec06fe596668d5e726
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/scenegraph/d3d12/d3d12.pro | 6 | ||||
-rw-r--r-- | src/plugins/scenegraph/d3d12/qsgd3d12context.cpp | 10 | ||||
-rw-r--r-- | src/plugins/scenegraph/d3d12/qsgd3d12context_p.h | 2 | ||||
-rw-r--r-- | src/plugins/scenegraph/d3d12/qsgd3d12painternode.cpp | 256 | ||||
-rw-r--r-- | src/plugins/scenegraph/d3d12/qsgd3d12painternode_p.h | 119 | ||||
-rw-r--r-- | src/plugins/scenegraph/d3d12/qsgd3d12rendercontext.cpp | 4 | ||||
-rw-r--r-- | src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode.cpp | 2 | ||||
-rw-r--r-- | src/plugins/scenegraph/d3d12/qsgd3d12texture.cpp | 5 | ||||
-rw-r--r-- | src/plugins/scenegraph/d3d12/qsgd3d12texture_p.h | 5 | ||||
-rw-r--r-- | src/quick/items/context2d/qquickcanvasitem.cpp | 26 | ||||
-rw-r--r-- | src/quick/items/qquickpainteditem.cpp | 27 |
11 files changed, 427 insertions, 35 deletions
diff --git a/src/plugins/scenegraph/d3d12/d3d12.pro b/src/plugins/scenegraph/d3d12/d3d12.pro index 4ca62bc1a8..6ba18acf22 100644 --- a/src/plugins/scenegraph/d3d12/d3d12.pro +++ b/src/plugins/scenegraph/d3d12/d3d12.pro @@ -23,7 +23,8 @@ SOURCES += \ $$PWD/qsgd3d12glyphnode.cpp \ $$PWD/qsgd3d12glyphcache.cpp \ $$PWD/qsgd3d12layer.cpp \ - $$PWD/qsgd3d12shadereffectnode.cpp + $$PWD/qsgd3d12shadereffectnode.cpp \ + $$PWD/qsgd3d12painternode.cpp NO_PCH_SOURCES += \ $$PWD/qsgd3d12engine.cpp @@ -44,7 +45,8 @@ HEADERS += \ $$PWD/qsgd3d12glyphnode_p.h \ $$PWD/qsgd3d12glyphcache_p.h \ $$PWD/qsgd3d12layer_p.h \ - $$PWD/qsgd3d12shadereffectnode_p.h + $$PWD/qsgd3d12shadereffectnode_p.h \ + $$PWD/qsgd3d12painternode_p.h LIBS += -ldxgi -ld3d12 -ld3dcompiler diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12context.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12context.cpp index 9144794d87..8a0e1a04f7 100644 --- a/src/plugins/scenegraph/d3d12/qsgd3d12context.cpp +++ b/src/plugins/scenegraph/d3d12/qsgd3d12context.cpp @@ -44,6 +44,7 @@ #include "qsgd3d12glyphnode_p.h" #include "qsgd3d12layer_p.h" #include "qsgd3d12shadereffectnode_p.h" +#include "qsgd3d12painternode_p.h" QT_BEGIN_NAMESPACE @@ -64,17 +65,16 @@ QSGImageNode *QSGD3D12Context::createImageNode() QSGPainterNode *QSGD3D12Context::createPainterNode(QQuickPaintedItem *item) { - Q_UNUSED(item); - Q_UNREACHABLE(); - return nullptr; + return new QSGD3D12PainterNode(item); } -QSGGlyphNode *QSGD3D12Context::createGlyphNode(QSGRenderContext *rc, bool preferNativeGlyphNode) +QSGGlyphNode *QSGD3D12Context::createGlyphNode(QSGRenderContext *renderContext, bool preferNativeGlyphNode) { Q_UNUSED(preferNativeGlyphNode); // ### distance field text rendering is not supported atm - return new QSGD3D12GlyphNode(static_cast<QSGD3D12RenderContext *>(rc)); + QSGD3D12RenderContext *rc = static_cast<QSGD3D12RenderContext *>(renderContext); + return new QSGD3D12GlyphNode(rc); } QSGNinePatchNode *QSGD3D12Context::createNinePatchNode() diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12context_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12context_p.h index 56952519a1..0564c4edac 100644 --- a/src/plugins/scenegraph/d3d12/qsgd3d12context_p.h +++ b/src/plugins/scenegraph/d3d12/qsgd3d12context_p.h @@ -64,7 +64,7 @@ public: QSGRectangleNode *createRectangleNode() override; QSGImageNode *createImageNode() override; QSGPainterNode *createPainterNode(QQuickPaintedItem *item) override; - QSGGlyphNode *createGlyphNode(QSGRenderContext *rc, bool preferNativeGlyphNode) override; + QSGGlyphNode *createGlyphNode(QSGRenderContext *renderContext, bool preferNativeGlyphNode) override; QSGNinePatchNode *createNinePatchNode() override; QSGLayer *createLayer(QSGRenderContext *renderContext) override; QSGGuiThreadShaderEffectManager *createGuiThreadShaderEffectManager() override; diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12painternode.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12painternode.cpp new file mode 100644 index 0000000000..7837c3a2d3 --- /dev/null +++ b/src/plugins/scenegraph/d3d12/qsgd3d12painternode.cpp @@ -0,0 +1,256 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgd3d12painternode_p.h" +#include "qsgd3d12rendercontext_p.h" +#include "qsgd3d12engine_p.h" +#include <private/qquickitem_p.h> +#include <qmath.h> + +QT_BEGIN_NAMESPACE + +QSGD3D12PainterTexture::QSGD3D12PainterTexture(QSGD3D12Engine *engine) + : QSGD3D12Texture(engine) +{ +} + +void QSGD3D12PainterTexture::bind() +{ + if (m_image.isNull()) { + if (!m_id) { + m_id = m_engine->genTexture(); + m_engine->createTexture(m_id, QSize(16, 16), QImage::Format_RGB32, 0); + } + } else if (m_image.size() != lastSize) { + lastSize = m_image.size(); + if (m_id) + m_engine->releaseTexture(m_id); + m_id = m_engine->genTexture(); + m_engine->createTexture(m_id, m_image.size(), m_image.format(), QSGD3D12Engine::TextureWithAlpha); + m_engine->queueTextureUpload(m_id, m_image); + } else if (!dirty.isEmpty()) { + const int bpl = m_image.bytesPerLine(); + const uchar *p = m_image.constBits() + dirty.y() * bpl + dirty.x() * 4; + QImage subImg(p, dirty.width(), dirty.height(), bpl, QImage::Format_ARGB32_Premultiplied); + m_engine->queueTextureUpload(m_id, subImg, dirty.topLeft()); + } + + dirty = QRect(); + + m_engine->useTexture(m_id); +} + +QSGD3D12PainterNode::QSGD3D12PainterNode(QQuickPaintedItem *item) + : m_item(item), + m_engine(static_cast<QSGD3D12RenderContext *>(QQuickItemPrivate::get(item)->sceneGraphRenderContext())->engine()), + m_texture(new QSGD3D12PainterTexture(m_engine)), + m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4), + m_dirtyGeometry(false), + m_dirtyContents(false) +{ + m_material.setFlag(QSGMaterial::Blending); + m_material.setTexture(m_texture); + setMaterial(&m_material); + setGeometry(&m_geometry); +} + +QSGD3D12PainterNode::~QSGD3D12PainterNode() +{ + delete m_texture; +} + +void QSGD3D12PainterNode::setPreferredRenderTarget(QQuickPaintedItem::RenderTarget) +{ + // always QImage-based +} + +void QSGD3D12PainterNode::setSize(const QSize &size) +{ + if (m_size == size) + return; + + m_size = size; + m_dirtyGeometry = true; +} + +void QSGD3D12PainterNode::setDirty(const QRect &dirtyRect) +{ + m_dirtyRect = dirtyRect; + m_dirtyContents = true; + markDirty(DirtyMaterial); +} + +void QSGD3D12PainterNode::setOpaquePainting(bool) +{ + // ignored +} + +void QSGD3D12PainterNode::setLinearFiltering(bool linearFiltering) +{ + m_material.setFiltering(linearFiltering ? QSGTexture::Linear : QSGTexture::Nearest); + markDirty(DirtyMaterial); +} + +void QSGD3D12PainterNode::setMipmapping(bool) +{ + // ### not yet +} + +void QSGD3D12PainterNode::setSmoothPainting(bool s) +{ + if (m_smoothPainting == s) + return; + + m_smoothPainting = s; + m_dirtyContents = true; + markDirty(DirtyMaterial); +} + +void QSGD3D12PainterNode::setFillColor(const QColor &c) +{ + if (m_fillColor == c) + return; + + m_fillColor = c; + m_dirtyContents = true; + markDirty(DirtyMaterial); +} + +void QSGD3D12PainterNode::setContentsScale(qreal s) +{ + if (m_contentsScale == s) + return; + + m_contentsScale = s; + m_dirtyContents = true; + markDirty(DirtyMaterial); +} + +void QSGD3D12PainterNode::setFastFBOResizing(bool) +{ + // nope +} + +void QSGD3D12PainterNode::setTextureSize(const QSize &size) +{ + if (m_textureSize == size) + return; + + m_textureSize = size; + m_dirtyGeometry = true; +} + +QImage QSGD3D12PainterNode::toImage() const +{ + return *m_texture->image(); +} + +void QSGD3D12PainterNode::update() +{ + if (m_dirtyGeometry) { + m_dirtyGeometry = false; + QRectF src(0, 0, 1, 1); + QRectF dst(QPointF(0, 0), m_size); + QSGGeometry::updateTexturedRectGeometry(&m_geometry, dst, src); + markDirty(DirtyGeometry); + } + + QImage *img = m_texture->image(); + if (img->size() != m_textureSize) { + *img = QImage(m_textureSize, QImage::Format_ARGB32_Premultiplied); + img->fill(Qt::transparent); + m_dirtyContents = true; + } + + if (m_dirtyContents) { + m_dirtyContents = false; + if (!img->isNull()) { + QRect dirtyRect = m_dirtyRect.isNull() ? QRect(QPoint(0, 0), m_size) : m_dirtyRect; + QPainter painter; + painter.begin(img); + if (m_smoothPainting) + painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); + + QRect clipRect; + QRect dirtyTextureRect; + + if (m_contentsScale == 1) { + float scaleX = m_textureSize.width() / (float) m_size.width(); + float scaleY = m_textureSize.height() / (float) m_size.height(); + painter.scale(scaleX, scaleY); + clipRect = dirtyRect; + dirtyTextureRect = QRectF(dirtyRect.x() * scaleX, + dirtyRect.y() * scaleY, + dirtyRect.width() * scaleX, + dirtyRect.height() * scaleY).toAlignedRect(); + } else { + painter.scale(m_contentsScale, m_contentsScale); + QRect sclip(qFloor(dirtyRect.x() / m_contentsScale), + qFloor(dirtyRect.y() / m_contentsScale), + qCeil(dirtyRect.width() / m_contentsScale + dirtyRect.x() / m_contentsScale + - qFloor(dirtyRect.x() / m_contentsScale)), + qCeil(dirtyRect.height() / m_contentsScale + dirtyRect.y() / m_contentsScale + - qFloor(dirtyRect.y() / m_contentsScale))); + clipRect = sclip; + dirtyTextureRect = dirtyRect; + } + + // only clip if we were originally updating only a subrect + if (!m_dirtyRect.isNull()) + painter.setClipRect(clipRect); + + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.fillRect(clipRect, m_fillColor); + painter.setCompositionMode(QPainter::CompositionMode_SourceOver); + + m_item->paint(&painter); + painter.end(); + + m_texture->dirty = dirtyTextureRect; + } + m_dirtyRect = QRect(); + } +} + +QSGTexture *QSGD3D12PainterNode::texture() const +{ + return m_texture; +} + +QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12painternode_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12painternode_p.h new file mode 100644 index 0000000000..67246cc3cd --- /dev/null +++ b/src/plugins/scenegraph/d3d12/qsgd3d12painternode_p.h @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGD3D12PAINTERNODE_P_H +#define QSGD3D12PAINTERNODE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <private/qsgadaptationlayer_p.h> +#include "qsgd3d12texture_p.h" +#include "qsgd3d12builtinmaterials_p.h" + +QT_BEGIN_NAMESPACE + +class QSGD3D12Engine; + +class QSGD3D12PainterTexture : public QSGD3D12Texture +{ +public: + QSGD3D12PainterTexture(QSGD3D12Engine *engine); + + void bind() override; + + QImage *image() { return &m_image; } + + QRect dirty; + +private: + QSize lastSize; +}; + +class QSGD3D12PainterNode : public QSGPainterNode +{ +public: + QSGD3D12PainterNode(QQuickPaintedItem *item); + ~QSGD3D12PainterNode(); + + void setPreferredRenderTarget(QQuickPaintedItem::RenderTarget target) override; + void setSize(const QSize &size) override; + void setDirty(const QRect &dirtyRect = QRect()) override; + void setOpaquePainting(bool opaque) override; + void setLinearFiltering(bool linearFiltering) override; + void setMipmapping(bool mipmapping) override; + void setSmoothPainting(bool s) override; + void setFillColor(const QColor &c) override; + void setContentsScale(qreal s) override; + void setFastFBOResizing(bool dynamic) override; + void setTextureSize(const QSize &size) override; + + QImage toImage() const override; + void update() override; + QSGTexture *texture() const override; + +private: + QQuickPaintedItem *m_item; + QSGD3D12Engine *m_engine; + QSGD3D12PainterTexture *m_texture; + QSize m_size; + QSize m_textureSize; + float m_contentsScale = 1; + bool m_smoothPainting = false; + QColor m_fillColor = Qt::transparent; + QRect m_dirtyRect; + + QSGGeometry m_geometry; + QSGD3D12TextureMaterial m_material; + + uint m_dirtyGeometry : 1; + uint m_dirtyContents : 1; +}; + +QT_END_NAMESPACE + +#endif // QSGD3D12PAINTERNODE_P_H diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext.cpp index ab590b95c5..8a4fd678e7 100644 --- a/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext.cpp +++ b/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext.cpp @@ -92,11 +92,11 @@ QSGTexture *QSGD3D12RenderContext::createTexture(const QImage &image, uint flags { Q_ASSERT(m_engine); QSGD3D12Texture *t = new QSGD3D12Texture(m_engine); - t->setImage(image, flags); + t->create(image, flags); return t; } - QSGRenderer *QSGD3D12RenderContext::createRenderer() +QSGRenderer *QSGD3D12RenderContext::createRenderer() { return new QSGD3D12Renderer(this); } diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode.cpp index dbdc876930..b4288c2ef5 100644 --- a/src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode.cpp +++ b/src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode.cpp @@ -495,7 +495,7 @@ QSGD3D12Material::UpdateResults QSGD3D12ShaderEffectMaterial::updatePipeline(con dummy = new QSGD3D12Texture(node->renderContext()->engine()); QImage img(128, 128, QImage::Format_ARGB32_Premultiplied); img.fill(0); - dummy->setImage(img, QSGRenderContext::CreateTexture_Alpha); + dummy->create(img, QSGRenderContext::CreateTexture_Alpha); } tv.filter = QSGD3D12TextureView::FilterNearest; tv.addressModeHoriz = QSGD3D12TextureView::AddressWrap; diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12texture.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12texture.cpp index 75dccba744..ce0c0e53dd 100644 --- a/src/plugins/scenegraph/d3d12/qsgd3d12texture.cpp +++ b/src/plugins/scenegraph/d3d12/qsgd3d12texture.cpp @@ -43,7 +43,7 @@ QT_BEGIN_NAMESPACE -void QSGD3D12Texture::setImage(const QImage &image, uint flags) +void QSGD3D12Texture::create(const QImage &image, uint flags) { // ### atlas? @@ -51,7 +51,6 @@ void QSGD3D12Texture::setImage(const QImage &image, uint flags) m_alphaWanted = alphaRequest && image.hasAlphaChannel(); m_image = image; - m_size = image.size(); m_id = m_engine->genTexture(); Q_ASSERT(m_id); @@ -75,7 +74,7 @@ int QSGD3D12Texture::textureId() const QSize QSGD3D12Texture::textureSize() const { - return m_size; + return m_image.size(); } bool QSGD3D12Texture::hasAlphaChannel() const diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12texture_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12texture_p.h index b9d53dd1e6..06013d4bea 100644 --- a/src/plugins/scenegraph/d3d12/qsgd3d12texture_p.h +++ b/src/plugins/scenegraph/d3d12/qsgd3d12texture_p.h @@ -64,7 +64,7 @@ public: QSGD3D12Texture(QSGD3D12Engine *engine) : m_engine(engine) { } ~QSGD3D12Texture(); - void setImage(const QImage &image, uint flags); + void create(const QImage &image, uint flags); int textureId() const override; QSize textureSize() const override; @@ -75,14 +75,13 @@ public: SIZE_T srv() const; -private: +protected: QSGD3D12Engine *m_engine; QImage m_image; bool m_createPending = false; bool m_createdWithMipMaps = false; uint m_id = 0; bool m_alphaWanted = false; - QSize m_size; }; QT_END_NAMESPACE diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp index 6603d8158d..f654261cb2 100644 --- a/src/quick/items/context2d/qquickcanvasitem.cpp +++ b/src/quick/items/context2d/qquickcanvasitem.cpp @@ -255,17 +255,18 @@ QQuickCanvasItemPrivate::~QQuickCanvasItemPrivate() The Canvas item supports two render targets: \c Canvas.Image and \c Canvas.FramebufferObject. - The \c Canvas.Image render target is a \a QImage object. This render - target supports background thread rendering, allowing complex or long - running painting to be executed without blocking the UI. + The \c Canvas.Image render target is a \a QImage object. This render target + supports background thread rendering, allowing complex or long running + painting to be executed without blocking the UI. This is the only render + target that is supported by all Qt Quick backends. The Canvas.FramebufferObject render target utilizes OpenGL hardware acceleration rather than rendering into system memory, which in many cases - results in faster rendering. Canvas.FramebufferObject relies on the - OpenGL extensions \c GL_EXT_framebuffer_multisample and - \c GL_EXT_framebuffer_blit for antialiasing. It will also use more - graphics memory when rendering strategy is anything other than - Canvas.Cooperative. + results in faster rendering. Canvas.FramebufferObject relies on the OpenGL + extensions \c GL_EXT_framebuffer_multisample and \c GL_EXT_framebuffer_blit + for antialiasing. It will also use more graphics memory when rendering + strategy is anything other than Canvas.Cooperative. Framebuffer objects may + not be available with Qt Quick backends other than OpenGL. The default render target is Canvas.Image and the default renderStrategy is Canvas.Immediate. @@ -300,7 +301,14 @@ QQuickCanvasItemPrivate::~QQuickCanvasItemPrivate() and can be used directly in \l {ShaderEffect}{ShaderEffects} and other classes that consume texture providers. - \sa Context2D + \note In general large canvases, frequent updates, and animation should be + avoided with the Canvas.Image render target. This is because with + accelerated graphics APIs each update will lead to a texture upload. Also, + if possible, prefer QQuickPaintedItem and implement drawing in C++ via + QPainter instead of the more expensive and likely less performing + JavaScript and Context2D approach. + + \sa Context2D QQuickPaintedItem */ QQuickCanvasItem::QQuickCanvasItem(QQuickItem *parent) diff --git a/src/quick/items/qquickpainteditem.cpp b/src/quick/items/qquickpainteditem.cpp index e4a20b9787..5813b4b115 100644 --- a/src/quick/items/qquickpainteditem.cpp +++ b/src/quick/items/qquickpainteditem.cpp @@ -63,13 +63,14 @@ public: \inmodule QtQuick - The QQuickPaintedItem makes it possible to use the QPainter API with the QML Scene Graph. - It sets up a textured rectangle in the Scene Graph and uses a QPainter to paint - onto the texture. The render target can be either a QImage or a QOpenGLFramebufferObject. - When the render target is a QImage, QPainter first renders into the image then - the content is uploaded to the texture. - When a QOpenGLFramebufferObject is used, QPainter paints directly onto the texture. - Call update() to trigger a repaint. + The QQuickPaintedItem makes it possible to use the QPainter API with the + QML Scene Graph. It sets up a textured rectangle in the Scene Graph and + uses a QPainter to paint onto the texture. The render target can be either + a QImage or, when OpenGL is in use, a QOpenGLFramebufferObject. When the + render target is a QImage, QPainter first renders into the image then the + content is uploaded to the texture. When a QOpenGLFramebufferObject is + used, QPainter paints directly onto the texture. Call update() to trigger a + repaint. To enable QPainter to do anti-aliased rendering, use setAntialiasing(). @@ -78,6 +79,10 @@ public: public function: paint(), which implements the actual painting. The painting will be inside the rectangle spanning from 0,0 to width(),height(). + + \note It important to understand the performance implications such items + can incur. See QQuickPaintedItem::RenderTarget and + QQuickPaintedItem::renderTarget. */ /*! @@ -172,8 +177,6 @@ QQuickPaintedItem::~QQuickPaintedItem() is processed by the QML Scene Graph when the next frame is rendered. The item will only be redrawn if it is visible. - Note that calling this function will trigger a repaint of the whole scene. - \sa paint() */ void QQuickPaintedItem::update(const QRect &rect) @@ -499,6 +502,12 @@ void QQuickPaintedItem::setFillColor(const QColor &c) the QQuickPaintedItem::FramebufferObject render target if the item gets resized often. By default, the render target is QQuickPaintedItem::Image. + + \note Some Qt Quick backends may not support all render target options. For + example, it is likely that non-OpenGL backends will lack support for + QQuickPaintedItem::FramebufferObject and + QQuickPaintedItem::InvertedYFramebufferObject. Requesting these will then + be ignored. */ QQuickPaintedItem::RenderTarget QQuickPaintedItem::renderTarget() const { |