##// END OF EJS Templates
Accelerating lineseries with OpenGL...
Accelerating lineseries with OpenGL Added support for QAbstractSeries::useOpenGL property. When true, the series in question is drawn on a separate offscreen buffer using OpenGL and then superimposed on the chart. Currently this property is only supported for line and scatter series. Change-Id: I174fec541f9f3c23464270c1fe08f824af16a0fb Reviewed-by: Titta Heikkala <titta.heikkala@theqtcompany.com> Reviewed-by: Tomi Korpipää <tomi.korpipaa@theqtcompany.com>

File last commit:

r2820:79a856530b69
r2820:79a856530b69
Show More
glxyseriesdata.cpp
147 lines | 5.0 KiB | text/x-c | CppLexer
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd
** All rights reserved.
** For any questions to The Qt Company, please use contact form at http://qt.io
**
** This file is part of the Qt Charts module.
**
** Licensees holding valid commercial license for Qt may use this file in
** accordance with the Qt License Agreement provided with the Software
** or, alternatively, in accordance with the terms contained in a written
** agreement between you and The Qt Company.
**
** If you have questions regarding the use of this file, please use
** contact form at http://qt.io
**
****************************************************************************/
#include "private/glxyseriesdata_p.h"
#include "private/abstractdomain_p.h"
#include <QtCharts/QScatterSeries>
QT_CHARTS_BEGIN_NAMESPACE
GLXYSeriesDataManager::GLXYSeriesDataManager(QObject *parent)
: QObject(parent),
m_mapDirty(false)
{
}
GLXYSeriesDataManager::~GLXYSeriesDataManager()
{
cleanup();
}
void GLXYSeriesDataManager::setPoints(QXYSeries *series, const AbstractDomain *domain)
{
GLXYSeriesData *data = m_seriesDataMap.value(series);
if (!data) {
data = new GLXYSeriesData;
data->type = series->type();
QColor sc;
if (data->type == QAbstractSeries::SeriesTypeScatter) {
QScatterSeries *scatter = static_cast<QScatterSeries *>(series);
data->width = float(scatter->markerSize());
sc = scatter->color(); // Scatter overwrites color property
} else {
data->width = float(series->pen().widthF());
sc = series->color();
}
data->color = QVector3D(float(sc.redF()), float(sc.greenF()), float(sc.blueF()));
connect(series, &QXYSeries::penChanged, this,
&GLXYSeriesDataManager::handleSeriesPenChange);
connect(series, &QXYSeries::useOpenGLChanged, this,
&GLXYSeriesDataManager::handleSeriesOpenGLChange);
m_seriesDataMap.insert(series, data);
m_mapDirty = true;
}
QVector<float> &array = data->array;
bool logAxis = false;
foreach (QAbstractAxis* axis, series->attachedAxes()) {
if (axis->type() == QAbstractAxis::AxisTypeLogValue) {
logAxis = true;
break;
}
}
int count = series->count();
int index = 0;
array.resize(count * 2);
if (logAxis) {
// Use domain to resolve geometry points. Not as fast as shaders, but simpler that way
QVector<QPointF> geometryPoints = domain->calculateGeometryPoints(series->pointsVector());
const float height = domain->size().height();
if (geometryPoints.size()) {
for (int i = 0; i < count; i++) {
const QPointF &point = geometryPoints.at(i);
array[index++] = float(point.x());
array[index++] = float(height - point.y());
}
} else {
// If there are invalid log values, geometry points generation fails
for (int i = 0; i < count; i++) {
array[index++] = 0.0f;
array[index++] = 0.0f;
}
}
data->min = QVector2D(0, 0);
data->delta = QVector2D(domain->size().width() / 2.0f, domain->size().height() / 2.0f);
} else {
// Regular value axes, so we can do the math easily on shaders.
QVector<QPointF> seriesPoints = series->pointsVector();
for (int i = 0; i < count; i++) {
const QPointF &point = seriesPoints.at(i);
array[index++] = float(point.x());
array[index++] = float(point.y());
}
data->min = QVector2D(domain->minX(), domain->minY());
data->delta = QVector2D((domain->maxX() - domain->minX()) / 2.0f,
(domain->maxY() - domain->minY()) / 2.0f);
}
data->dirty = true;
}
void GLXYSeriesDataManager::removeSeries(const QXYSeries *series)
{
GLXYSeriesData *data = m_seriesDataMap.take(series);
if (data) {
disconnect(series, 0, this, 0);
delete data;
emit seriesRemoved(series);
m_mapDirty = true;
}
}
void GLXYSeriesDataManager::cleanup()
{
foreach (GLXYSeriesData *data, m_seriesDataMap.values())
delete data;
m_seriesDataMap.clear();
m_mapDirty = true;
// Signal all series removal by using zero as parameter
emit seriesRemoved(0);
}
void GLXYSeriesDataManager::handleSeriesPenChange()
{
QXYSeries *series = qobject_cast<QXYSeries *>(sender());
if (series) {
GLXYSeriesData *data = m_seriesDataMap.value(series);
if (data) {
QColor sc = series->color();
data->color = QVector3D(float(sc.redF()), float(sc.greenF()), float(sc.blueF()));
data->width = float(series->pen().widthF());
}
}
}
void GLXYSeriesDataManager::handleSeriesOpenGLChange()
{
QXYSeries *series = qobject_cast<QXYSeries *>(sender());
if (!series->useOpenGL())
removeSeries(series);
}
QT_CHARTS_END_NAMESPACE