diff options
Diffstat (limited to 'src/quick/scenegraph')
24 files changed, 790 insertions, 4 deletions
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp index d9a298f855..94e9c81f70 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp @@ -47,6 +47,7 @@ #include "qsgsoftwarepublicnodes_p.h" #include "qsgsoftwarelayer_p.h" #include "qsgsoftwarerenderer_p.h" +#include "qsgsoftwarespritenode_p.h" #include <QtCore/QCoreApplication> #include <QtCore/QElapsedTimer> @@ -154,6 +155,11 @@ void QSGSoftwareRenderContext::renderNextFrame(QSGRenderer *renderer, uint fbo) renderer->renderScene(fbo); } +int QSGSoftwareRenderContext::maxTextureSize() const +{ + return 2048; +} + QSGRendererInterface *QSGSoftwareContext::rendererInterface(QSGRenderContext *renderContext) { Q_UNUSED(renderContext); @@ -175,6 +181,11 @@ QSGNinePatchNode *QSGSoftwareContext::createNinePatchNode() return new QSGSoftwareNinePatchNode; } +QSGSpriteNode *QSGSoftwareContext::createSpriteNode() +{ + return new QSGSoftwareSpriteNode; +} + QSGRendererInterface::GraphicsApi QSGSoftwareContext::graphicsApi() const { return Software; diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h index 9a939a0948..3c3686c268 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h @@ -75,6 +75,7 @@ public: void renderNextFrame(QSGRenderer *renderer, uint fbo) override; QSGTexture *createTexture(const QImage &image, uint flags = CreateTexture_Alpha) const override; QSGRenderer *createRenderer() override; + int maxTextureSize() const override; bool m_initialized; }; @@ -96,6 +97,7 @@ public: QSGRectangleNode *createRectangleNode() override; QSGImageNode *createImageNode() override; QSGNinePatchNode *createNinePatchNode() override; + QSGSpriteNode *createSpriteNode() override; GraphicsApi graphicsApi() const override; ShaderType shaderType() const override; diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp index 385b257e44..1b2a836dfa 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp @@ -45,6 +45,7 @@ #include "qsgsoftwarepublicnodes_p.h" #include "qsgsoftwarepainternode_p.h" #include "qsgsoftwarepixmaptexture_p.h" +#include "qsgsoftwarespritenode_p.h" #include <QtQuick/QSGSimpleRectNode> #include <QtQuick/qsgsimpletexturenode.h> @@ -89,6 +90,9 @@ QSGSoftwareRenderableNode::QSGSoftwareRenderableNode(NodeType type, QSGNode *nod case QSGSoftwareRenderableNode::SimpleImage: m_handle.simpleImageNode = static_cast<QSGImageNode*>(node); break; + case QSGSoftwareRenderableNode::SpriteNode: + m_handle.spriteNode = static_cast<QSGSoftwareSpriteNode*>(node); + break; case QSGSoftwareRenderableNode::Invalid: m_handle.simpleRectNode = nullptr; break; @@ -174,6 +178,10 @@ void QSGSoftwareRenderableNode::update() boundingRect = m_handle.simpleImageNode->rect().toRect(); break; + case QSGSoftwareRenderableNode::SpriteNode: + m_isOpaque = m_handle.spriteNode->isOpaque(); + boundingRect = m_handle.spriteNode->rect().toRect(); + break; default: break; } @@ -256,6 +264,9 @@ QRegion QSGSoftwareRenderableNode::renderNode(QPainter *painter, bool forceOpaqu case QSGSoftwareRenderableNode::SimpleImage: static_cast<QSGSoftwareImageNode *>(m_handle.simpleImageNode)->paint(painter); break; + case QSGSoftwareRenderableNode::SpriteNode: + static_cast<QSGSoftwareSpriteNode *>(m_handle.spriteNode)->paint(painter); + break; default: break; } diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h index fcbea7391a..dc224be2c0 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h @@ -67,6 +67,7 @@ class QSGSoftwarePainterNode; class QSGSoftwareInternalRectangleNode; class QSGSoftwareGlyphNode; class QSGSoftwareNinePatchNode; +class QSGSoftwareSpriteNode; class QSGSoftwareRenderableNode { @@ -81,7 +82,8 @@ public: Glyph, NinePatch, SimpleRectangle, - SimpleImage + SimpleImage, + SpriteNode }; QSGSoftwareRenderableNode(NodeType type, QSGNode *node); @@ -123,6 +125,7 @@ private: QSGSoftwareNinePatchNode *ninePatchNode; QSGRectangleNode *simpleRectangleNode; QSGImageNode *simpleImageNode; + QSGSoftwareSpriteNode *spriteNode; }; const NodeType m_nodeType; diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp index f13edb87fb..cb866bec12 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp @@ -180,6 +180,16 @@ void QSGSoftwareRenderableNodeUpdater::endVisit(QSGRootNode *) { } +bool QSGSoftwareRenderableNodeUpdater::visit(QSGSpriteNode *node) +{ + return updateRenderableNode(QSGSoftwareRenderableNode::SpriteNode, node); +} + +void QSGSoftwareRenderableNodeUpdater::endVisit(QSGSpriteNode *) +{ + +} + void QSGSoftwareRenderableNodeUpdater::updateNodes(QSGNode *node, bool isNodeRemoved) { m_opacityState.clear(); diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater_p.h index d7c12e8b02..5bc241cce1 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater_p.h +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater_p.h @@ -86,6 +86,8 @@ public: void endVisit(QSGGlyphNode *) override; bool visit(QSGRootNode *) override; void endVisit(QSGRootNode *) override; + bool visit(QSGSpriteNode *) override; + void endVisit(QSGSpriteNode *) override; void updateNodes(QSGNode *node, bool isNodeRemoved = false); diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder.cpp index ede2005918..ac00127b35 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder.cpp @@ -140,6 +140,16 @@ void QSGSoftwareRenderListBuilder::endVisit(QSGRootNode *) { } +bool QSGSoftwareRenderListBuilder::visit(QSGSpriteNode *node) +{ + return addRenderableNode(node); +} + +void QSGSoftwareRenderListBuilder::endVisit(QSGSpriteNode *) +{ + +} + bool QSGSoftwareRenderListBuilder::addRenderableNode(QSGNode *node) { auto renderableNode = m_renderer->renderableNode(node); diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder_p.h index ce538f835f..e34cc81e23 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder_p.h +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder_p.h @@ -80,6 +80,8 @@ public: void endVisit(QSGGlyphNode *) override; bool visit(QSGRootNode *) override; void endVisit(QSGRootNode *) override; + bool visit(QSGSpriteNode *) override; + void endVisit(QSGSpriteNode *) override; private: bool addRenderableNode(QSGNode *node); diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp new file mode 100644 index 0000000000..ba7bbc2d11 --- /dev/null +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** 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 "qsgsoftwarespritenode_p.h" +#include "qsgsoftwarepixmaptexture_p.h" +#include <QtGui/QPainter> + +QT_BEGIN_NAMESPACE + +QSGSoftwareSpriteNode::QSGSoftwareSpriteNode() +{ + setMaterial((QSGMaterial*)1); + setGeometry((QSGGeometry*)1); +} + +void QSGSoftwareSpriteNode::setTexture(QSGTexture *texture) +{ + m_texture = qobject_cast<QSGSoftwarePixmapTexture*>(texture); + markDirty(DirtyMaterial); +} + +void QSGSoftwareSpriteNode::setTime(float time) +{ + if (m_time != time) { + m_time = time; + markDirty(DirtyMaterial); + } +} + +void QSGSoftwareSpriteNode::setSourceA(const QPoint &source) +{ + if (m_sourceA != source) { + m_sourceA = source; + markDirty(DirtyMaterial); + } +} + +void QSGSoftwareSpriteNode::setSourceB(const QPoint &source) +{ + if (m_sourceB != source) { + m_sourceB = source; + markDirty(DirtyMaterial); + } +} + +void QSGSoftwareSpriteNode::setSpriteSize(const QSize &size) +{ + if (m_spriteSize != size) { + m_spriteSize = size; + markDirty(DirtyMaterial); + } +} + +void QSGSoftwareSpriteNode::setSheetSize(const QSize &size) +{ + if (m_sheetSize != size) { + m_sheetSize = size; + markDirty(DirtyMaterial); + } +} + +void QSGSoftwareSpriteNode::setSize(const QSizeF &size) +{ + if (m_size != size) { + m_size = size; + markDirty(DirtyGeometry); + } +} + +void QSGSoftwareSpriteNode::setFiltering(QSGTexture::Filtering filtering) +{ + Q_UNUSED(filtering); +} + +void QSGSoftwareSpriteNode::update() +{ +} + +void QSGSoftwareSpriteNode::paint(QPainter *painter) +{ + //Get the pixmap handle from the texture + if (!m_texture) + return; + + const QPixmap &pixmap = m_texture->pixmap(); + + // XXX try to do some kind of interpolation between sourceA and sourceB using time + painter->drawPixmap(QRectF(0, 0, m_size.width(), m_size.height()), + pixmap, + QRectF(m_sourceA, m_spriteSize)); +} + +bool QSGSoftwareSpriteNode::isOpaque() const +{ + return false; +} + +QRectF QSGSoftwareSpriteNode::rect() const +{ + return QRectF(0, 0, m_size.width(), m_size.height()); +} + +QT_END_NAMESPACE diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode_p.h new file mode 100644 index 0000000000..284ed3dff5 --- /dev/null +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode_p.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** 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 QSGSOFTWARESPRITENODE_H +#define QSGSOFTWARESPRITENODE_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> + +QT_BEGIN_NAMESPACE + +class QSGSoftwarePixmapTexture; +class QSGSoftwareSpriteNode : public QSGSpriteNode +{ +public: + QSGSoftwareSpriteNode(); + + void setTexture(QSGTexture *texture) override; + void setTime(float time) override; + void setSourceA(const QPoint &source) override; + void setSourceB(const QPoint &source) override; + void setSpriteSize(const QSize &size) override; + void setSheetSize(const QSize &size) override; + void setSize(const QSizeF &size) override; + void setFiltering(QSGTexture::Filtering filtering) override; + void update() override; + + void paint(QPainter *painter); + bool isOpaque() const; + QRectF rect() const; + +private: + + QSGSoftwarePixmapTexture *m_texture; + float m_time; + QPoint m_sourceA; + QPoint m_sourceB; + QSize m_spriteSize; + QSize m_sheetSize; + QSizeF m_size; + +}; + +QT_END_NAMESPACE + +#endif // QSGSOFTWARESPRITENODE_H diff --git a/src/quick/scenegraph/adaptations/software/software.pri b/src/quick/scenegraph/adaptations/software/software.pri index a8ba77c147..1933a37d48 100644 --- a/src/quick/scenegraph/adaptations/software/software.pri +++ b/src/quick/scenegraph/adaptations/software/software.pri @@ -18,7 +18,8 @@ SOURCES += \ $$PWD/qsgsoftwarerenderlistbuilder.cpp \ $$PWD/qsgsoftwarerenderloop.cpp \ $$PWD/qsgsoftwarelayer.cpp \ - $$PWD/qsgsoftwareadaptation.cpp + $$PWD/qsgsoftwareadaptation.cpp \ + $$PWD/qsgsoftwarespritenode.cpp HEADERS += \ $$PWD/qsgsoftwarecontext_p.h \ @@ -36,4 +37,5 @@ HEADERS += \ $$PWD/qsgsoftwarerenderlistbuilder_p.h \ $$PWD/qsgsoftwarerenderloop_p.h \ $$PWD/qsgsoftwarelayer_p.h \ - $$PWD/qsgsoftwareadaptation_p.h + $$PWD/qsgsoftwareadaptation_p.h \ + $$PWD/qsgsoftwarespritenode_p.h diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h index bdb8ebb0f1..00441e1544 100644 --- a/src/quick/scenegraph/qsgadaptationlayer_p.h +++ b/src/quick/scenegraph/qsgadaptationlayer_p.h @@ -81,6 +81,7 @@ class QSGPainterNode; class QSGInternalRectangleNode; class QSGGlyphNode; class QSGRootNode; +class QSGSpriteNode; class Q_QUICK_PRIVATE_EXPORT QSGNodeVisitorEx { @@ -106,6 +107,8 @@ public: virtual void endVisit(QSGGlyphNode *) = 0; virtual bool visit(QSGRootNode *) = 0; virtual void endVisit(QSGRootNode *) = 0; + virtual bool visit(QSGSpriteNode *) = 0; + virtual void endVisit(QSGSpriteNode *) = 0; void visitChildren(QSGNode *node); }; @@ -207,6 +210,23 @@ Q_SIGNALS: void scheduledUpdateCompleted(); }; +class Q_QUICK_PRIVATE_EXPORT QSGSpriteNode : public QSGVisitableNode +{ +public: + virtual void setTexture(QSGTexture *texture) = 0; + virtual void setTime(float time) = 0; + virtual void setSourceA(const QPoint &source) = 0; + virtual void setSourceB(const QPoint &source) = 0; + virtual void setSpriteSize(const QSize &size) = 0; + virtual void setSheetSize(const QSize &size) = 0; + virtual void setSize(const QSizeF &size) = 0; + virtual void setFiltering(QSGTexture::Filtering filtering) = 0; + + virtual void update() = 0; + + virtual void accept(QSGNodeVisitorEx *visitor) { if (visitor->visit(this)) visitor->visitChildren(this); visitor->endVisit(this); } +}; + class Q_QUICK_PRIVATE_EXPORT QSGGuiThreadShaderEffectManager : public QObject { Q_OBJECT diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h index e34d2c3ebf..43cf1c28ab 100644 --- a/src/quick/scenegraph/qsgcontext_p.h +++ b/src/quick/scenegraph/qsgcontext_p.h @@ -87,6 +87,7 @@ class QSGGuiThreadShaderEffectManager; class QSGRectangleNode; class QSGImageNode; class QSGNinePatchNode; +class QSGSpriteNode; Q_DECLARE_LOGGING_CATEGORY(QSG_LOG_TIME_RENDERLOOP) Q_DECLARE_LOGGING_CATEGORY(QSG_LOG_TIME_COMPILATION) @@ -126,6 +127,8 @@ public: virtual void setAttachToGraphicsContext(bool attach) { Q_UNUSED(attach); } + virtual int maxTextureSize() const = 0; + void registerFontengineForCleanup(QFontEngine *engine); Q_SIGNALS: @@ -174,6 +177,7 @@ public: virtual QSGGuiThreadShaderEffectManager *createGuiThreadShaderEffectManager(); virtual QSGShaderEffectNode *createShaderEffectNode(QSGRenderContext *renderContext, QSGGuiThreadShaderEffectManager *mgr); + virtual QSGSpriteNode *createSpriteNode() = 0; virtual QAnimationDriver *createAnimationDriver(QObject *parent); virtual QSize minimumFBOSize() const; diff --git a/src/quick/scenegraph/qsgdefaultcontext.cpp b/src/quick/scenegraph/qsgdefaultcontext.cpp index 6324d84883..6964b74dc8 100644 --- a/src/quick/scenegraph/qsgdefaultcontext.cpp +++ b/src/quick/scenegraph/qsgdefaultcontext.cpp @@ -52,6 +52,7 @@ #include <QtQuick/private/qsgdefaultrectanglenode_p.h> #include <QtQuick/private/qsgdefaultimagenode_p.h> #include <QtQuick/private/qsgdefaultninepatchnode_p.h> +#include <QtQuick/private/qsgdefaultspritenode_p.h> #include <QtGui/QOpenGLContext> #include <QtGui/QOpenGLFramebufferObject> @@ -257,6 +258,11 @@ QSGNinePatchNode *QSGDefaultContext::createNinePatchNode() return new QSGDefaultNinePatchNode; } +QSGSpriteNode *QSGDefaultContext::createSpriteNode() +{ + return new QSGDefaultSpriteNode; +} + QSGRendererInterface::GraphicsApi QSGDefaultContext::graphicsApi() const { return OpenGL; diff --git a/src/quick/scenegraph/qsgdefaultcontext_p.h b/src/quick/scenegraph/qsgdefaultcontext_p.h index 908934d28c..88db5e1e9a 100644 --- a/src/quick/scenegraph/qsgdefaultcontext_p.h +++ b/src/quick/scenegraph/qsgdefaultcontext_p.h @@ -76,6 +76,7 @@ public: QSGRectangleNode *createRectangleNode() override; QSGImageNode *createImageNode() override; QSGNinePatchNode *createNinePatchNode() override; + QSGSpriteNode *createSpriteNode() override; void setDistanceFieldEnabled(bool enabled); bool isDistanceFieldEnabled() const; diff --git a/src/quick/scenegraph/qsgdefaultrendercontext_p.h b/src/quick/scenegraph/qsgdefaultrendercontext_p.h index bc653565cf..0aed46b658 100644 --- a/src/quick/scenegraph/qsgdefaultrendercontext_p.h +++ b/src/quick/scenegraph/qsgdefaultrendercontext_p.h @@ -93,7 +93,7 @@ public: static QSGDefaultRenderContext *from(QOpenGLContext *context); bool hasBrokenIndexBufferObjects() const { return m_brokenIBOs; } - int maxTextureSize() const { return m_maxTextureSize; } + int maxTextureSize() const override { return m_maxTextureSize; } protected: QOpenGLContext *m_gl; diff --git a/src/quick/scenegraph/qsgdefaultspritenode.cpp b/src/quick/scenegraph/qsgdefaultspritenode.cpp new file mode 100644 index 0000000000..89b26f8660 --- /dev/null +++ b/src/quick/scenegraph/qsgdefaultspritenode.cpp @@ -0,0 +1,303 @@ +/**************************************************************************** +** +** 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 "qsgdefaultspritenode_p.h" + +#include <QtQuick/QSGMaterial> +#include <QtGui/QOpenGLShaderProgram> + +QT_BEGIN_NAMESPACE + +struct SpriteVertex { + float x; + float y; + float tx; + float ty; +}; + +struct SpriteVertices { + SpriteVertex v1; + SpriteVertex v2; + SpriteVertex v3; + SpriteVertex v4; +}; + +class QQuickSpriteMaterial : public QSGMaterial +{ +public: + QQuickSpriteMaterial(); + ~QQuickSpriteMaterial(); + QSGMaterialType *type() const override { static QSGMaterialType type; return &type; } + QSGMaterialShader *createShader() const override; + int compare(const QSGMaterial *other) const override + { + return this - static_cast<const QQuickSpriteMaterial *>(other); + } + + QSGTexture *texture; + + float animT; + float animX1; + float animY1; + float animX2; + float animY2; + float animW; + float animH; +}; + +QQuickSpriteMaterial::QQuickSpriteMaterial() + : texture(0) + , animT(0.0f) + , animX1(0.0f) + , animY1(0.0f) + , animX2(0.0f) + , animY2(0.0f) + , animW(1.0f) + , animH(1.0f) +{ + setFlag(Blending, true); +} + +QQuickSpriteMaterial::~QQuickSpriteMaterial() +{ + delete texture; +} + +class SpriteMaterialData : public QSGMaterialShader +{ +public: + SpriteMaterialData() + : QSGMaterialShader() + { + setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/scenegraph/shaders/sprite.vert")); + setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/sprite.frag")); + } + + void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *) Q_DECL_OVERRIDE + { + QQuickSpriteMaterial *m = static_cast<QQuickSpriteMaterial *>(newEffect); + m->texture->bind(); + + program()->setUniformValue(m_opacity_id, state.opacity()); + program()->setUniformValue(m_animData_id, m->animW, m->animH, m->animT); + program()->setUniformValue(m_animPos_id, m->animX1, m->animY1, m->animX2, m->animY2); + + if (state.isMatrixDirty()) + program()->setUniformValue(m_matrix_id, state.combinedMatrix()); + } + + void initialize() Q_DECL_OVERRIDE { + m_matrix_id = program()->uniformLocation("qt_Matrix"); + m_opacity_id = program()->uniformLocation("qt_Opacity"); + m_animData_id = program()->uniformLocation("animData"); + m_animPos_id = program()->uniformLocation("animPos"); + } + + char const *const *attributeNames() const Q_DECL_OVERRIDE { + static const char *attr[] = { + "vPos", + "vTex", + 0 + }; + return attr; + } + + int m_matrix_id; + int m_opacity_id; + int m_animData_id; + int m_animPos_id; +}; + +QSGMaterialShader *QQuickSpriteMaterial::createShader() const +{ + return new SpriteMaterialData; +} + +static QSGGeometry::Attribute Sprite_Attributes[] = { + QSGGeometry::Attribute::create(0, 2, QSGGeometry::TypeFloat, true), // pos + QSGGeometry::Attribute::create(1, 2, QSGGeometry::TypeFloat), // tex +}; + +static QSGGeometry::AttributeSet Sprite_AttributeSet = +{ + 2, // Attribute Count + (2+2) * sizeof(float), + Sprite_Attributes +}; + +QSGDefaultSpriteNode::QSGDefaultSpriteNode() + : m_material(new QQuickSpriteMaterial) + , m_geometryDirty(true) + , m_sheetSize(QSize(64, 64)) +{ + // Setup geometry data + m_geometry = new QSGGeometry(Sprite_AttributeSet, 4, 6); + m_geometry->setDrawingMode(QSGGeometry::DrawTriangles); + quint16 *indices = m_geometry->indexDataAsUShort(); + indices[0] = 0; + indices[1] = 1; + indices[2] = 2; + indices[3] = 1; + indices[4] = 3; + indices[5] = 2; + + setGeometry(m_geometry); + setMaterial(m_material); + setFlag(OwnsGeometry, true); + setFlag(OwnsMaterial, true); +} + +void QSGDefaultSpriteNode::setTexture(QSGTexture *texture) +{ + m_material->texture = texture; + m_geometryDirty = true; + markDirty(DirtyMaterial); +} + +void QSGDefaultSpriteNode::setTime(float time) +{ + m_material->animT = time; + markDirty(DirtyMaterial); +} + +void QSGDefaultSpriteNode::setSourceA(const QPoint &source) +{ + if (m_sourceA != source) { + m_sourceA = source; + m_material->animX1 = static_cast<float>(source.x()) / m_sheetSize.width(); + m_material->animY1 = static_cast<float>(source.y()) / m_sheetSize.height(); + markDirty(DirtyMaterial); + } +} + +void QSGDefaultSpriteNode::setSourceB(const QPoint &source) +{ + if (m_sourceB != source) { + m_sourceB = source; + m_material->animX2 = static_cast<float>(source.x()) / m_sheetSize.width(); + m_material->animY2 = static_cast<float>(source.y()) / m_sheetSize.height(); + markDirty(DirtyMaterial); + } +} + +void QSGDefaultSpriteNode::setSpriteSize(const QSize &size) +{ + if (m_spriteSize != size) { + m_spriteSize = size; + m_material->animW = static_cast<float>(size.width()) / m_sheetSize.width(); + m_material->animH = static_cast<float>(size.height()) / m_sheetSize.height(); + markDirty(DirtyMaterial); + } + +} + +void QSGDefaultSpriteNode::setSheetSize(const QSize &size) +{ + if (m_sheetSize != size) { + m_sheetSize = size; + + // Update all dependent properties + m_material->animX1 = static_cast<float>(m_sourceA.x()) / m_sheetSize.width(); + m_material->animY1 = static_cast<float>(m_sourceA.y()) / m_sheetSize.height(); + m_material->animX2 = static_cast<float>(m_sourceB.x()) / m_sheetSize.width(); + m_material->animY2 = static_cast<float>(m_sourceB.y()) / m_sheetSize.height(); + m_material->animW = static_cast<float>(m_spriteSize.width()) / m_sheetSize.width(); + m_material->animH = static_cast<float>(m_spriteSize.height()) / m_sheetSize.height(); + markDirty(DirtyMaterial); + } +} + +void QSGDefaultSpriteNode::setSize(const QSizeF &size) +{ + if (m_size != size) { + m_size = size; + m_geometryDirty = true; + } +} + +void QSGDefaultSpriteNode::setFiltering(QSGTexture::Filtering filtering) +{ + m_material->texture->setFiltering(filtering); + markDirty(DirtyMaterial); +} + +void QSGDefaultSpriteNode::update() +{ + if (m_geometryDirty) { + updateGeometry(); + m_geometryDirty = false; + } +} + +void QSGDefaultSpriteNode::updateGeometry() +{ + if (!m_material->texture) + return; + + SpriteVertices *p = (SpriteVertices *) m_geometry->vertexData(); + + QRectF texRect = m_material->texture->normalizedTextureSubRect(); + + p->v1.tx = texRect.topLeft().x(); + p->v1.ty = texRect.topLeft().y(); + + p->v2.tx = texRect.topRight().x(); + p->v2.ty = texRect.topRight().y(); + + p->v3.tx = texRect.bottomLeft().x(); + p->v3.ty = texRect.bottomLeft().y(); + + p->v4.tx = texRect.bottomRight().x(); + p->v4.ty = texRect.bottomRight().y(); + + p->v1.x = 0; + p->v1.y = 0; + + p->v2.x = m_size.width(); + p->v2.y = 0; + + p->v3.x = 0; + p->v3.y = m_size.height(); + + p->v4.x = m_size.width(); + p->v4.y = m_size.height(); + markDirty(DirtyGeometry); +} + +QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgdefaultspritenode_p.h b/src/quick/scenegraph/qsgdefaultspritenode_p.h new file mode 100644 index 0000000000..cb76bf8d83 --- /dev/null +++ b/src/quick/scenegraph/qsgdefaultspritenode_p.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** 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 QSGDEFAULTSPRITENODE_H +#define QSGDEFAULTSPRITENODE_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> + +QT_BEGIN_NAMESPACE +class QQuickSpriteMaterial; +class QSGDefaultSpriteNode : public QSGSpriteNode +{ +public: + QSGDefaultSpriteNode(); + + void setTexture(QSGTexture *texture) override; + void setTime(float time) override; + void setSourceA(const QPoint &source) override; + void setSourceB(const QPoint &source) override; + void setSpriteSize(const QSize &size) override; + void setSheetSize(const QSize &size) override; + void setSize(const QSizeF &size) override; + void setFiltering(QSGTexture::Filtering filtering) override; + void update() override; +private: + void updateGeometry(); + + QQuickSpriteMaterial *m_material; + QSGGeometry *m_geometry; + bool m_geometryDirty; + QPoint m_sourceA; + QPoint m_sourceB; + QSize m_spriteSize; + QSize m_sheetSize; + QSizeF m_size; +}; + +QT_END_NAMESPACE + +#endif // QSGDEFAULTSPRITENODE_H diff --git a/src/quick/scenegraph/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri index 5b13b7449a..4ef8b0f638 100644 --- a/src/quick/scenegraph/scenegraph.pri +++ b/src/quick/scenegraph/scenegraph.pri @@ -115,6 +115,7 @@ contains(QT_CONFIG, opengl(es1|es2)?) { $$PWD/qsgdefaultinternalrectanglenode.cpp \ $$PWD/qsgdefaultrendercontext.cpp \ $$PWD/qsgdefaultcontext.cpp \ + $$PWD/qsgdefaultspritenode.cpp \ $$PWD/util/qsgdefaultpainternode.cpp \ $$PWD/util/qsgdefaultrectanglenode.cpp \ $$PWD/util/qsgdefaultimagenode.cpp \ @@ -130,6 +131,7 @@ contains(QT_CONFIG, opengl(es1|es2)?) { $$PWD/qsgdefaultglyphnode_p_p.h \ $$PWD/qsgdefaultinternalimagenode_p.h \ $$PWD/qsgdefaultinternalrectanglenode_p.h \ + $$PWD/qsgdefaultspritenode_p.h \ $$PWD/qsgdefaultrendercontext_p.h \ $$PWD/qsgdefaultcontext_p.h \ $$PWD/util/qsgdefaultpainternode_p.h \ diff --git a/src/quick/scenegraph/scenegraph.qrc b/src/quick/scenegraph/scenegraph.qrc index ef6da71334..0687530be1 100644 --- a/src/quick/scenegraph/scenegraph.qrc +++ b/src/quick/scenegraph/scenegraph.qrc @@ -68,5 +68,9 @@ <file>shaders/vertexcolor_core.vert</file> <file>shaders/visualization.vert</file> <file>shaders/visualization.frag</file> + <file>shaders/sprite.frag</file> + <file>shaders/sprite.vert</file> + <file>shaders/sprite_core.frag</file> + <file>shaders/sprite_core.vert</file> </qresource> </RCC> diff --git a/src/quick/scenegraph/shaders/sprite.frag b/src/quick/scenegraph/shaders/sprite.frag new file mode 100644 index 0000000000..e1fcb0f006 --- /dev/null +++ b/src/quick/scenegraph/shaders/sprite.frag @@ -0,0 +1,12 @@ +uniform sampler2D _qt_texture; +uniform lowp float qt_Opacity; + +varying highp vec4 fTexS; +varying lowp float progress; + +void main() +{ + gl_FragColor = mix(texture2D(_qt_texture, fTexS.xy), + texture2D(_qt_texture, fTexS.zw), + progress) * qt_Opacity; +}
\ No newline at end of file diff --git a/src/quick/scenegraph/shaders/sprite.vert b/src/quick/scenegraph/shaders/sprite.vert new file mode 100644 index 0000000000..fc826f60b4 --- /dev/null +++ b/src/quick/scenegraph/shaders/sprite.vert @@ -0,0 +1,23 @@ +attribute highp vec2 vPos; +attribute highp vec2 vTex; + +uniform highp vec3 animData;// w,h(premultiplied of anim), interpolation progress +uniform highp vec4 animPos;//x,y, x,y (two frames for interpolation) + +uniform highp mat4 qt_Matrix; + +varying highp vec4 fTexS; +varying lowp float progress; + +void main() +{ + progress = animData.z; + + // Calculate frame location in texture + fTexS.xy = animPos.xy + vTex.xy * animData.xy; + + // Next frame is also passed, for interpolation + fTexS.zw = animPos.zw + vTex.xy * animData.xy; + + gl_Position = qt_Matrix * vec4(vPos.x, vPos.y, 0, 1); +}
\ No newline at end of file diff --git a/src/quick/scenegraph/shaders/sprite_core.frag b/src/quick/scenegraph/shaders/sprite_core.frag new file mode 100644 index 0000000000..c1087a8754 --- /dev/null +++ b/src/quick/scenegraph/shaders/sprite_core.frag @@ -0,0 +1,16 @@ +#version 150 core + +in vec4 fTexS; +in float progress; + +out vec4 fragColor; + +uniform sampler2D _qt_texture; +uniform float qt_Opacity; + +void main() +{ + fragColor = mix(texture(_qt_texture, fTexS.xy), + texture(_qt_texture, fTexS.zw), + progress) * qt_Opacity; +}
\ No newline at end of file diff --git a/src/quick/scenegraph/shaders/sprite_core.vert b/src/quick/scenegraph/shaders/sprite_core.vert new file mode 100644 index 0000000000..5027bf03fc --- /dev/null +++ b/src/quick/scenegraph/shaders/sprite_core.vert @@ -0,0 +1,24 @@ +#version 150 core + +in vec2 vPos; +in vec2 vTex; + +out vec4 fTexS; +out float progress; + +uniform vec3 animData; // w,h(premultiplied of anim), interpolation progress +uniform vec4 animPos; // x,y, x,y (two frames for interpolation) +uniform mat4 qt_Matrix; + +void main() +{ + progress = animData.z; + + // Calculate frame location in texture + fTexS.xy = animPos.xy + vTex.xy * animData.xy; + + // Next frame is also passed, for interpolation + fTexS.zw = animPos.zw + vTex.xy * animData.xy; + + gl_Position = qt_Matrix * vec4(vPos.x, vPos.y, 0, 1); +}
\ No newline at end of file |