diff options
-rw-r--r-- | src/chartsqml2/chartsqml2.pro | 11 | ||||
-rw-r--r-- | src/chartsqml2/declarativeabstractrendernode.h | 55 | ||||
-rw-r--r-- | src/chartsqml2/declarativechart.cpp | 19 | ||||
-rw-r--r-- | src/chartsqml2/declarativechartnode.cpp | 79 | ||||
-rw-r--r-- | src/chartsqml2/declarativechartnode.h | 20 | ||||
-rw-r--r-- | src/chartsqml2/declarativeopenglrendernode.cpp (renamed from src/chartsqml2/declarativerendernode.cpp) | 59 | ||||
-rw-r--r-- | src/chartsqml2/declarativeopenglrendernode.h (renamed from src/chartsqml2/declarativerendernode.h) | 27 | ||||
-rw-r--r-- | src/src.pro | 2 |
8 files changed, 173 insertions, 99 deletions
diff --git a/src/chartsqml2/chartsqml2.pro b/src/chartsqml2/chartsqml2.pro index 310eed87..57407e4d 100644 --- a/src/chartsqml2/chartsqml2.pro +++ b/src/chartsqml2/chartsqml2.pro @@ -25,7 +25,6 @@ SOURCES += \ declarativepolarchart.cpp \ declarativeboxplotseries.cpp \ declarativechartnode.cpp \ - declarativerendernode.cpp \ declarativecandlestickseries.cpp HEADERS += \ @@ -44,8 +43,14 @@ HEADERS += \ declarativepolarchart.h \ declarativeboxplotseries.h \ declarativechartnode.h \ - declarativerendernode.h \ - declarativecandlestickseries.h + declarativecandlestickseries.h \ + declarativeabstractrendernode.h + +contains(QT_CONFIG, opengl) { + SOURCES += declarativeopenglrendernode.cpp + HEADERS += declarativeopenglrendernode.h +} + load(qml_plugin) diff --git a/src/chartsqml2/declarativeabstractrendernode.h b/src/chartsqml2/declarativeabstractrendernode.h new file mode 100644 index 00000000..afc8c354 --- /dev/null +++ b/src/chartsqml2/declarativeabstractrendernode.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Charts module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DECLARATIVEABSTRACTRENDERNODE_H +#define DECLARATIVEABSTRACTRENDERNODE_H + +#include <QtCharts/QChartGlobal> +#include <QtQuick/QSGNode> +#include <QtQuick/QQuickWindow> +#include <private/glxyseriesdata_p.h> + +QT_CHARTS_BEGIN_NAMESPACE + +class DeclarativeAbstractRenderNode : public QSGRootNode +{ +public: + DeclarativeAbstractRenderNode() {} + + virtual void setTextureSize(const QSize &textureSize) = 0; + virtual QSize textureSize() const = 0; + virtual void setRect(const QRectF &rect) = 0; + virtual void setSeriesData(bool mapDirty, const GLXYDataMap &dataMap) = 0; + +}; + +QT_CHARTS_END_NAMESPACE + + +#endif // DECLARATIVEABSTRACTRENDERNODE_H diff --git a/src/chartsqml2/declarativechart.cpp b/src/chartsqml2/declarativechart.cpp index 66b47722..4dfc3d5d 100644 --- a/src/chartsqml2/declarativechart.cpp +++ b/src/chartsqml2/declarativechart.cpp @@ -38,7 +38,7 @@ #include "declarativecandlestickseries.h" #include "declarativescatterseries.h" #include "declarativechartnode.h" -#include "declarativerendernode.h" +#include "declarativeabstractrendernode.h" #include <QtCharts/QBarCategoryAxis> #include <QtCharts/QValueAxis> #include <QtCharts/QLogValueAxis> @@ -60,6 +60,7 @@ #include <QtWidgets/QApplication> #include <QtCore/QTimer> #include <QtCore/QThread> +#include <QtQuick/QQuickWindow> QT_CHARTS_BEGIN_NAMESPACE @@ -521,16 +522,12 @@ QSGNode *DeclarativeChart::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdateP if (!node) { node = new DeclarativeChartNode(window()); - if (node->glRenderNode()) { - connect(window(), &QQuickWindow::beforeRendering, - node->glRenderNode(), &DeclarativeRenderNode::render); - } } const QRectF &bRect = boundingRect(); - // Update GL data - if (node->glRenderNode() && (m_glXYDataManager->dataMap().size() || m_glXYDataManager->mapDirty())) { + // Update renderNode data + if (node->renderNode() && (m_glXYDataManager->dataMap().size() || m_glXYDataManager->mapDirty())) { const QRectF &plotArea = m_chart->plotArea(); const QSizeF &chartAreaSize = m_chart->size(); @@ -546,11 +543,11 @@ QSGNode *DeclarativeChart::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdateP normalizedHeight * bRect.height()); const QSize &adjustedPlotSize = adjustedPlotArea.size().toSize(); - if (adjustedPlotSize != node->glRenderNode()->textureSize()) - node->glRenderNode()->setTextureSize(adjustedPlotSize); + if (adjustedPlotSize != node->renderNode()->textureSize()) + node->renderNode()->setTextureSize(adjustedPlotSize); - node->glRenderNode()->setRect(adjustedPlotArea); - node->glRenderNode()->setSeriesData(m_glXYDataManager->mapDirty(), + node->renderNode()->setRect(adjustedPlotArea); + node->renderNode()->setSeriesData(m_glXYDataManager->mapDirty(), m_glXYDataManager->dataMap()); // Clear dirty flags from original xy data diff --git a/src/chartsqml2/declarativechartnode.cpp b/src/chartsqml2/declarativechartnode.cpp index 3742b8c5..7019ed58 100644 --- a/src/chartsqml2/declarativechartnode.cpp +++ b/src/chartsqml2/declarativechartnode.cpp @@ -28,62 +28,67 @@ ****************************************************************************/ #include "declarativechartnode.h" -#include "declarativerendernode.h" -#include <QtGui/QOpenGLContext> -#include <QtGui/QOpenGLFunctions> -#include <QtGui/QOpenGLFramebufferObjectFormat> -#include <QtGui/QOpenGLFramebufferObject> -#include <QOpenGLShaderProgram> -#include <QtGui/QOpenGLBuffer> +#include "declarativeabstractrendernode.h" + +#include <QtQuick/QQuickWindow> +#include <QtQuick/QSGImageNode> +#include <QtQuick/QSGRendererInterface> + +#ifndef QT_NO_OPENGL +# include "declarativeopenglrendernode.h" +#endif QT_CHARTS_BEGIN_NAMESPACE // This node handles displaying of the chart itself DeclarativeChartNode::DeclarativeChartNode(QQuickWindow *window) : - QSGSimpleTextureNode(), - m_texture(0), + QSGRootNode(), m_window(window), - m_textureOptions(0), - m_textureSize(1, 1), - m_glRenderNode(0) + m_renderNode(nullptr), + m_imageNode(nullptr) { - // Our texture node must have a texture, so use a default one pixel texture - QImage dummyImage(QSize(1, 1), QImage::Format_ARGB32); - uchar *imageData = dummyImage.bits(); - imageData[0] = 0; - imageData[1] = 0; - imageData[2] = 0; - imageData[3] = 0; - QQuickWindow::CreateTextureOptions defaultTextureOptions = QQuickWindow::CreateTextureOptions( - QQuickWindow::TextureHasAlphaChannel | QQuickWindow::TextureOwnsGLTexture); - m_texture = m_window->createTextureFromImage(dummyImage, defaultTextureOptions); + // Create a DeclarativeRenderNode for correct QtQuick Backend +#ifndef QT_NO_OPENGL + if (m_window->rendererInterface()->graphicsApi() == QSGRendererInterface::OpenGL) + m_renderNode = new DeclarativeOpenGLRenderNode(m_window); +#endif - setTexture(m_texture); - setFiltering(QSGTexture::Linear); - - if (QOpenGLContext::currentContext()) { - // Create child node for rendering GL graphics - m_glRenderNode = new DeclarativeRenderNode(m_window); - m_glRenderNode->setFlag(OwnedByParent); - appendChildNode(m_glRenderNode); - m_glRenderNode->setRect(0, 0, 0, 0); // Hide child node by default + if (m_renderNode) { + m_renderNode->setFlag(OwnedByParent); + appendChildNode(m_renderNode); + m_renderNode->setRect(QRectF(0, 0, 0, 0)); // Hide child node by default } } DeclarativeChartNode::~DeclarativeChartNode() { - delete m_texture; } // Must be called on render thread and in context void DeclarativeChartNode::createTextureFromImage(const QImage &chartImage) { - if (chartImage.size() != m_textureSize) - m_textureSize = chartImage.size(); + static auto const defaultTextureOptions = QQuickWindow::CreateTextureOptions(QQuickWindow::TextureHasAlphaChannel | + QQuickWindow::TextureOwnsGLTexture); + + auto texture = m_window->createTextureFromImage(chartImage, defaultTextureOptions); + // Create Image node if needed + if (!m_imageNode) { + m_imageNode = m_window->createImageNode(); + m_imageNode->setFlag(OwnedByParent); + m_imageNode->setOwnsTexture(true); + prependChildNode(m_imageNode); + } + m_imageNode->setTexture(texture); + if (!m_rect.isEmpty()) + m_imageNode->setRect(m_rect); +} + +void DeclarativeChartNode::setRect(const QRectF &rect) +{ + m_rect = rect; - delete m_texture; - m_texture = m_window->createTextureFromImage(chartImage, m_textureOptions); - setTexture(m_texture); + if (m_imageNode) + m_imageNode->setRect(rect); } QT_CHARTS_END_NAMESPACE diff --git a/src/chartsqml2/declarativechartnode.h b/src/chartsqml2/declarativechartnode.h index b718864c..c93307fc 100644 --- a/src/chartsqml2/declarativechartnode.h +++ b/src/chartsqml2/declarativechartnode.h @@ -31,29 +31,29 @@ #define DECLARATIVECHARTNODE_P_H #include <QtCharts/QChartGlobal> -#include <QtQuick/QSGSimpleTextureNode> +#include <QtQuick/QSGNode> #include <QtQuick/QQuickWindow> -#include <QtGui/QOpenGLFunctions> +#include <QtQuick/QSGImageNode> QT_CHARTS_BEGIN_NAMESPACE -class DeclarativeRenderNode; - -class DeclarativeChartNode : public QSGSimpleTextureNode, QOpenGLFunctions +class DeclarativeAbstractRenderNode; +class DeclarativeChartNode : public QSGRootNode { public: DeclarativeChartNode(QQuickWindow *window); ~DeclarativeChartNode(); void createTextureFromImage(const QImage &chartImage); - DeclarativeRenderNode *glRenderNode() const { return m_glRenderNode; } + DeclarativeAbstractRenderNode *renderNode() const { return m_renderNode; } + + void setRect(const QRectF &rect); private: - QSGTexture *m_texture; + QRectF m_rect; QQuickWindow *m_window; - QQuickWindow::CreateTextureOptions m_textureOptions; - QSize m_textureSize; - DeclarativeRenderNode *m_glRenderNode; + DeclarativeAbstractRenderNode *m_renderNode; + QSGImageNode *m_imageNode; }; QT_CHARTS_END_NAMESPACE diff --git a/src/chartsqml2/declarativerendernode.cpp b/src/chartsqml2/declarativeopenglrendernode.cpp index c11f6b00..0799e36c 100644 --- a/src/chartsqml2/declarativerendernode.cpp +++ b/src/chartsqml2/declarativeopenglrendernode.cpp @@ -27,7 +27,7 @@ ** ****************************************************************************/ -#include "declarativerendernode.h" +#include "declarativeopenglrendernode.h" #include <QtGui/QOpenGLContext> #include <QtGui/QOpenGLFunctions> @@ -45,10 +45,10 @@ QT_CHARTS_BEGIN_NAMESPACE // This node draws the xy series data on a transparent background using OpenGL. // It is used as a child node of the chart node. -DeclarativeRenderNode::DeclarativeRenderNode(QQuickWindow *window) : +DeclarativeOpenGLRenderNode::DeclarativeOpenGLRenderNode(QQuickWindow *window) : QObject(), - QSGSimpleTextureNode(), m_texture(0), + m_imageNode(nullptr), m_window(window), m_textureOptions(QQuickWindow::TextureHasAlphaChannel), m_textureSize(1, 1), @@ -64,23 +64,11 @@ DeclarativeRenderNode::DeclarativeRenderNode(QQuickWindow *window) : { initializeOpenGLFunctions(); - // Our texture node must have a texture, so use a default one pixel texture - GLuint defaultTexture = 0; - glGenTextures(1, &defaultTexture); - glBindTexture(GL_TEXTURE_2D, defaultTexture); - uchar buf[4] = { 0, 0, 0, 0 }; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &buf); - - QQuickWindow::CreateTextureOptions defaultTextureOptions = QQuickWindow::CreateTextureOptions( - QQuickWindow::TextureHasAlphaChannel | QQuickWindow::TextureOwnsGLTexture); - m_texture = m_window->createTextureFromId(defaultTexture, QSize(1, 1), defaultTextureOptions); - - setTexture(m_texture); - setFiltering(QSGTexture::Linear); - setTextureCoordinatesTransform(QSGSimpleTextureNode::MirrorVertically); + connect(m_window, &QQuickWindow::beforeRendering, + this, &DeclarativeOpenGLRenderNode::render); } -DeclarativeRenderNode::~DeclarativeRenderNode() +DeclarativeOpenGLRenderNode::~DeclarativeOpenGLRenderNode() { delete m_texture; delete m_fbo; @@ -109,7 +97,7 @@ static const char *fragmentSource = "}\n"; // Must be called on render thread and in context -void DeclarativeRenderNode::initGL() +void DeclarativeOpenGLRenderNode::initGL() { recreateFBO(); @@ -146,7 +134,7 @@ void DeclarativeRenderNode::initGL() m_program->release(); } -void DeclarativeRenderNode::recreateFBO() +void DeclarativeOpenGLRenderNode::recreateFBO() { QOpenGLFramebufferObjectFormat fboFormat; fboFormat.setAttachment(QOpenGLFramebufferObject::NoAttachment); @@ -157,13 +145,22 @@ void DeclarativeRenderNode::recreateFBO() delete m_texture; m_texture = m_window->createTextureFromId(m_fbo->texture(), m_textureSize, m_textureOptions); - setTexture(m_texture); + if (!m_imageNode) { + m_imageNode = m_window->createImageNode(); + m_imageNode->setFiltering(QSGTexture::Linear); + m_imageNode->setTextureCoordinatesTransform(QSGImageNode::MirrorVertically); + m_imageNode->setFlag(OwnedByParent); + if (!m_rect.isEmpty()) + m_imageNode->setRect(m_rect); + appendChildNode(m_imageNode); + } + m_imageNode->setTexture(m_texture); m_recreateFbo = false; } // Must be called on render thread and in context -void DeclarativeRenderNode::setTextureSize(const QSize &size) +void DeclarativeOpenGLRenderNode::setTextureSize(const QSize &size) { m_textureSize = size; m_recreateFbo = true; @@ -171,7 +168,7 @@ void DeclarativeRenderNode::setTextureSize(const QSize &size) } // Must be called on render thread while gui thread is blocked, and in context -void DeclarativeRenderNode::setSeriesData(bool mapDirty, const GLXYDataMap &dataMap) +void DeclarativeOpenGLRenderNode::setSeriesData(bool mapDirty, const GLXYDataMap &dataMap) { if (mapDirty) { // Series have changed, recreate map, but utilize old data where feasible @@ -213,7 +210,15 @@ void DeclarativeRenderNode::setSeriesData(bool mapDirty, const GLXYDataMap &data m_renderNeeded = true; } -void DeclarativeRenderNode::renderGL() +void DeclarativeOpenGLRenderNode::setRect(const QRectF &rect) +{ + m_rect = rect; + + if (m_imageNode) + m_imageNode->setRect(rect); +} + +void DeclarativeOpenGLRenderNode::renderGL() { glClearColor(0, 0, 0, 0); @@ -281,7 +286,7 @@ void DeclarativeRenderNode::renderGL() } // Must be called on render thread as response to beforeRendering signal -void DeclarativeRenderNode::render() +void DeclarativeOpenGLRenderNode::render() { if (m_renderNeeded) { if (m_xyDataMap.size()) { @@ -291,7 +296,7 @@ void DeclarativeRenderNode::render() recreateFBO(); renderGL(); } else { - if (rect() != QRectF()) { + if (m_imageNode && m_imageNode->rect() != QRectF()) { glClearColor(0, 0, 0, 0); m_fbo->bind(); glClear(GL_COLOR_BUFFER_BIT); @@ -304,7 +309,7 @@ void DeclarativeRenderNode::render() } } -void DeclarativeRenderNode::cleanXYSeriesResources(const QXYSeries *series) +void DeclarativeOpenGLRenderNode::cleanXYSeriesResources(const QXYSeries *series) { if (series) { delete m_seriesBufferMap.take(series); diff --git a/src/chartsqml2/declarativerendernode.h b/src/chartsqml2/declarativeopenglrendernode.h index b21fa20b..09ce64c6 100644 --- a/src/chartsqml2/declarativerendernode.h +++ b/src/chartsqml2/declarativeopenglrendernode.h @@ -27,13 +27,16 @@ ** ****************************************************************************/ -#ifndef DECLARATIVERENDERNODE_P_H -#define DECLARATIVERENDERNODE_P_H +#ifndef DECLARATIVEOPENGLRENDERNODE_P_H +#define DECLARATIVEOPENGLRENDERNODE_P_H + +#include "declarativeabstractrendernode.h" #include <QtCharts/QChartGlobal> #include <private/glxyseriesdata_p.h> -#include <QtQuick/QSGSimpleTextureNode> +#include <QtQuick/QSGImageNode> #include <QtQuick/QQuickWindow> +#include <QtGui/QOpenGLShaderProgram> #include <QtGui/QOpenGLVertexArrayObject> #include <QtGui/QOpenGLFunctions> #include <QtGui/QOpenGLFramebufferObject> @@ -41,17 +44,19 @@ QT_CHARTS_BEGIN_NAMESPACE -class DeclarativeRenderNode : public QObject, public QSGSimpleTextureNode, QOpenGLFunctions +class DeclarativeOpenGLRenderNode : public QObject, public DeclarativeAbstractRenderNode, QOpenGLFunctions { Q_OBJECT public: - DeclarativeRenderNode(QQuickWindow *window); - ~DeclarativeRenderNode(); + DeclarativeOpenGLRenderNode(QQuickWindow *window); + ~DeclarativeOpenGLRenderNode(); void initGL(); - QSize textureSize() const { return m_textureSize; } - void setTextureSize(const QSize &size); - void setSeriesData(bool mapDirty, const GLXYDataMap &dataMap); + QSize textureSize() const override { return m_textureSize; } + void setTextureSize(const QSize &size) override; + + void setSeriesData(bool mapDirty, const GLXYDataMap &dataMap) override; + void setRect(const QRectF &rect) override; public Q_SLOTS: void render(); @@ -62,6 +67,7 @@ private: void cleanXYSeriesResources(const QXYSeries *series); QSGTexture *m_texture; + QSGImageNode *m_imageNode; QQuickWindow *m_window; QQuickWindow::CreateTextureOptions m_textureOptions; QSize m_textureSize; @@ -78,8 +84,9 @@ private: QOpenGLVertexArrayObject m_vao; QHash<const QAbstractSeries *, QOpenGLBuffer *> m_seriesBufferMap; bool m_renderNeeded; + QRectF m_rect; }; QT_CHARTS_END_NAMESPACE -#endif // DECLARATIVERENDERNODE_P_H +#endif // DECLARATIVEOPENGLRENDERNODE_P_H diff --git a/src/src.pro b/src/src.pro index af3dcd3b..507c9f56 100644 --- a/src/src.pro +++ b/src/src.pro @@ -1,6 +1,6 @@ TEMPLATE = subdirs CONFIG += ordered SUBDIRS += charts -qtHaveModule(quick):contains(QT_CONFIG, opengl) { +qtHaveModule(quick) { SUBDIRS += chartsqml2 } |