summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Nichols <andy.nichols@qt.io>2016-08-08 17:07:43 +0200
committerAndy Nichols <andy.nichols@qt.io>2016-08-10 07:47:22 +0000
commit3e5aaffb763d143c55f2b90d4b01773bd9f2d388 (patch)
tree69990bd0d49c31c19849036190f4d61a7fc44f25
parent5513c45893e55163932937cc21ab743967600365 (diff)
Re-enable QML plugin for QtQuick Software backend
There needed to be a bit of re-plumbing but now it is again possible to use the software renderer with QtCharts in QtQuick 2. The declarativerendernode now can be other backends than OpenGL if needed, while also not spreading around uncessary references to OpenGL classes. Task-number: QTBUG-55193 Change-Id: I68a44c66c3bfc02f7cf808b21dc83979ed151b59 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
-rw-r--r--src/chartsqml2/chartsqml2.pro11
-rw-r--r--src/chartsqml2/declarativeabstractrendernode.h55
-rw-r--r--src/chartsqml2/declarativechart.cpp19
-rw-r--r--src/chartsqml2/declarativechartnode.cpp79
-rw-r--r--src/chartsqml2/declarativechartnode.h20
-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.pro2
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
}