From 3c5c6f6309d99286a3ecbbce014eb158f4f4013d Mon Sep 17 00:00:00 2001 From: Andy Nichols Date: Tue, 19 Aug 2014 16:15:09 +0200 Subject: Add support for rendering QQuickPaintedItem Change-Id: I80dbd2003f53e21fa35ebd270ecc92cc03628454 Reviewed-by: Lars Knoll --- softwarecontext/context.cpp | 6 ++ softwarecontext/context.h | 1 + softwarecontext/painternode.cpp | 178 +++++++++++++++++++++++++++++++++++ softwarecontext/painternode.h | 93 ++++++++++++++++++ softwarecontext/renderingvisitor.cpp | 12 +++ softwarecontext/renderingvisitor.h | 2 + softwarecontext/softwarecontext.pro | 6 +- 7 files changed, 296 insertions(+), 2 deletions(-) create mode 100644 softwarecontext/painternode.cpp create mode 100644 softwarecontext/painternode.h diff --git a/softwarecontext/context.cpp b/softwarecontext/context.cpp index 2bf4e7f0fc..1a8b07b1b4 100644 --- a/softwarecontext/context.cpp +++ b/softwarecontext/context.cpp @@ -22,6 +22,7 @@ #include "rectanglenode.h" #include "imagenode.h" +#include "painternode.h" #include "pixmaptexture.h" #include "glyphnode.h" #include "ninepatchnode.h" @@ -141,6 +142,11 @@ QSGImageNode *Context::createImageNode() return new ImageNode(); } +QSGPainterNode *Context::createPainterNode(QQuickPaintedItem *item) +{ + return new PainterNode(item); +} + QSGGlyphNode *Context::createGlyphNode(QSGRenderContext *rc, bool preferNativeGlyphNode) { Q_UNUSED(rc); diff --git a/softwarecontext/context.h b/softwarecontext/context.h index 0a64ca0a06..0e685fdfa9 100644 --- a/softwarecontext/context.h +++ b/softwarecontext/context.h @@ -86,6 +86,7 @@ public: virtual QSGRectangleNode *createRectangleNode(); virtual QSGImageNode *createImageNode(); + virtual QSGPainterNode *createPainterNode(QQuickPaintedItem *item); virtual QSGGlyphNode *createGlyphNode(QSGRenderContext *rc, bool preferNativeGlyphNode); virtual QSGNinePatchNode *createNinePatchNode(); virtual QSGLayer *createLayer(QSGRenderContext *renderContext); diff --git a/softwarecontext/painternode.cpp b/softwarecontext/painternode.cpp new file mode 100644 index 0000000000..714368b675 --- /dev/null +++ b/softwarecontext/painternode.cpp @@ -0,0 +1,178 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt SceneGraph Raster Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "painternode.h" +#include + +PainterNode::PainterNode(QQuickPaintedItem *item) + : QSGPainterNode() + , m_preferredRenderTarget(QQuickPaintedItem::Image) + , m_actualRenderTarget(QQuickPaintedItem::Image) + , m_item(item) + , m_dirtyContents(false) + , m_opaquePainting(false) + , m_linear_filtering(false) + , m_mipmapping(false) + , m_smoothPainting(false) + , m_extensionsChecked(false) + , m_multisamplingSupported(false) + , m_fastFBOResizing(false) + , m_fillColor(Qt::transparent) + , m_contentsScale(1.0) + , m_dirtyGeometry(false) +{ + setMaterial((QSGMaterial*)1); + setGeometry((QSGGeometry*)1); +} + +void PainterNode::setPreferredRenderTarget(QQuickPaintedItem::RenderTarget target) +{ + if (m_preferredRenderTarget == target) + return; + + m_preferredRenderTarget = target; +} + +void PainterNode::setSize(const QSize &size) +{ + if (size == m_size) + return; + + m_size = size; + + m_dirtyGeometry = true; +} + +void PainterNode::setDirty(const QRect &dirtyRect) +{ + m_dirtyContents = true; + m_dirtyRect = dirtyRect; + markDirty(DirtyMaterial); +} + +void PainterNode::setOpaquePainting(bool opaque) +{ + if (opaque == m_opaquePainting) + return; + + m_opaquePainting = opaque; +} + +void PainterNode::setLinearFiltering(bool linearFiltering) +{ + if (linearFiltering == m_linear_filtering) + return; + + m_linear_filtering = linearFiltering; +} + +void PainterNode::setMipmapping(bool mipmapping) +{ + if (mipmapping == m_mipmapping) + return; + + m_mipmapping = mipmapping; +} + +void PainterNode::setSmoothPainting(bool s) +{ + if (s == m_smoothPainting) + return; + + m_smoothPainting = s; +} + +void PainterNode::setFillColor(const QColor &c) +{ + if (c == m_fillColor) + return; + + m_fillColor = c; + markDirty(DirtyMaterial); +} + +void PainterNode::setContentsScale(qreal s) +{ + if (s == m_contentsScale) + return; + + m_contentsScale = s; + markDirty(DirtyMaterial); +} + +void PainterNode::setFastFBOResizing(bool dynamic) +{ + m_fastFBOResizing = dynamic; +} + +QImage PainterNode::toImage() const +{ + return m_pixmap.toImage(); +} + +void PainterNode::update() +{ + if (m_dirtyGeometry) { + m_pixmap = QPixmap(m_size); + if (!m_opaquePainting) + m_pixmap.fill(Qt::transparent); + } + + if (m_dirtyContents) + paint(); + + m_dirtyGeometry = false; + m_dirtyContents = false; +} + +void PainterNode::paint(QPainter *painter) +{ + painter->drawPixmap(0, 0, m_size.width(), m_size.height(), m_pixmap); +} + +void PainterNode::paint() +{ + QRect dirtyRect = m_dirtyRect.isNull() ? QRect(0, 0, m_size.width(), m_size.height()) : m_dirtyRect; + + QPainter painter; + + painter.begin(&m_pixmap); + if (m_smoothPainting) { + painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); + } + + 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))); + + if (!m_dirtyRect.isNull()) + painter.setClipRect(sclip); + + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.fillRect(sclip, m_fillColor); + painter.setCompositionMode(QPainter::CompositionMode_SourceOver); + + m_item->paint(&painter); + painter.end(); + + m_dirtyRect = QRect(); +} diff --git a/softwarecontext/painternode.h b/softwarecontext/painternode.h new file mode 100644 index 0000000000..046ae93d15 --- /dev/null +++ b/softwarecontext/painternode.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt SceneGraph Raster Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef PAINTERNODE_H +#define PAINTERNODE_H + +#include +#include + +#include + +class PainterNode : public QSGPainterNode +{ +public: + PainterNode(QQuickPaintedItem *item); + + void setPreferredRenderTarget(QQuickPaintedItem::RenderTarget target); + + void setSize(const QSize &size); + QSize size() const { return m_size; } + + void setDirty(const QRect &dirtyRect = QRect()); + + void setOpaquePainting(bool opaque); + bool opaquePainting() const { return m_opaquePainting; } + + void setLinearFiltering(bool linearFiltering); + bool linearFiltering() const { return m_linear_filtering; } + + void setMipmapping(bool mipmapping); + bool mipmapping() const { return m_mipmapping; } + + void setSmoothPainting(bool s); + bool smoothPainting() const { return m_smoothPainting; } + + void setFillColor(const QColor &c); + QColor fillColor() const { return m_fillColor; } + + void setContentsScale(qreal s); + qreal contentsScale() const { return m_contentsScale; } + + void setFastFBOResizing(bool dynamic); + bool fastFBOResizing() const { return m_fastFBOResizing; } + + QImage toImage() const; + void update(); + + void paint(QPainter *painter); + + void paint(); + +private: + + QQuickPaintedItem::RenderTarget m_preferredRenderTarget; + QQuickPaintedItem::RenderTarget m_actualRenderTarget; + + QQuickPaintedItem *m_item; + + QPixmap m_pixmap; + + QSize m_size; + bool m_dirtyContents; + QRect m_dirtyRect; + bool m_opaquePainting; + bool m_linear_filtering; + bool m_mipmapping; + bool m_smoothPainting; + bool m_extensionsChecked; + bool m_multisamplingSupported; + bool m_fastFBOResizing; + QColor m_fillColor; + qreal m_contentsScale; + + bool m_dirtyGeometry; +}; + +#endif // PAINTERNODE_H diff --git a/softwarecontext/renderingvisitor.cpp b/softwarecontext/renderingvisitor.cpp index f64139eab0..f90b23850e 100644 --- a/softwarecontext/renderingvisitor.cpp +++ b/softwarecontext/renderingvisitor.cpp @@ -23,6 +23,7 @@ #include "rectanglenode.h" #include "glyphnode.h" #include "ninepatchnode.h" +#include "painternode.h" RenderingVisitor::RenderingVisitor(QPainter *painter) : painter(painter) @@ -92,6 +93,17 @@ void RenderingVisitor::endVisit(QSGImageNode *) { } +bool RenderingVisitor::visit(QSGPainterNode *node) +{ + static_cast(node)->paint(painter); + return true; +} + +void RenderingVisitor::endVisit(QSGPainterNode *node) +{ + +} + bool RenderingVisitor::visit(QSGRectangleNode *node) { static_cast(node)->paint(painter); diff --git a/softwarecontext/renderingvisitor.h b/softwarecontext/renderingvisitor.h index 397c2053c2..d65faa4293 100644 --- a/softwarecontext/renderingvisitor.h +++ b/softwarecontext/renderingvisitor.h @@ -37,6 +37,8 @@ public: virtual void endVisit(QSGOpacityNode *node); virtual bool visit(QSGImageNode *node); virtual void endVisit(QSGImageNode *node); + virtual bool visit(QSGPainterNode *node); + virtual void endVisit(QSGPainterNode *node); virtual bool visit(QSGRectangleNode *node); virtual void endVisit(QSGRectangleNode *node); virtual bool visit(QSGGlyphNode *node); diff --git a/softwarecontext/softwarecontext.pro b/softwarecontext/softwarecontext.pro index 61607a13cf..d60260c1eb 100644 --- a/softwarecontext/softwarecontext.pro +++ b/softwarecontext/softwarecontext.pro @@ -16,7 +16,8 @@ SOURCES += \ renderingvisitor.cpp \ ninepatchnode.cpp \ softwarelayer.cpp \ - threadedrenderloop.cpp + threadedrenderloop.cpp \ + painternode.cpp HEADERS += \ context.h \ @@ -29,7 +30,8 @@ HEADERS += \ renderingvisitor.h \ ninepatchnode.h \ softwarelayer.h \ - threadedrenderloop.h + threadedrenderloop.h \ + painternode.h OTHER_FILES += softwarecontext.json -- cgit v1.2.3