summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/datavisualization/engine/abstract3dcontroller.cpp9
-rw-r--r--src/datavisualization/engine/abstract3dcontroller_p.h3
-rw-r--r--src/datavisualization/engine/abstract3drenderer.cpp42
-rw-r--r--src/datavisualization/engine/abstract3drenderer_p.h9
-rw-r--r--src/datavisualization/engine/bars3drenderer.cpp2
-rw-r--r--src/datavisualization/engine/scatter3drenderer.cpp2
-rw-r--r--src/datavisualization/engine/surface3drenderer.cpp25
-rw-r--r--src/datavisualizationqml2/abstractdeclarative.cpp55
-rw-r--r--src/datavisualizationqml2/abstractdeclarative_p.h1
-rw-r--r--tests/qmlmultiwindow/qml/qmlmultiwindow/main.qml120
10 files changed, 169 insertions, 99 deletions
diff --git a/src/datavisualization/engine/abstract3dcontroller.cpp b/src/datavisualization/engine/abstract3dcontroller.cpp
index f8a1a813..37d7c08b 100644
--- a/src/datavisualization/engine/abstract3dcontroller.cpp
+++ b/src/datavisualization/engine/abstract3dcontroller.cpp
@@ -100,7 +100,7 @@ Abstract3DController::~Abstract3DController()
void Abstract3DController::destroyRenderer()
{
// Renderer can be in another thread, don't delete it directly in that case
- if (m_renderer && m_renderer->thread() != QThread::currentThread())
+ if (m_renderer && m_renderer->thread() && m_renderer->thread() != this->thread())
m_renderer->deleteLater();
else
delete m_renderer;
@@ -114,6 +114,13 @@ void Abstract3DController::destroyRenderer()
void Abstract3DController::setRenderer(Abstract3DRenderer *renderer)
{
m_renderer = renderer;
+
+ // If renderer is created in different thread than controller, make sure renderer gets
+ // destroyed before the render thread finishes.
+ if (renderer->thread() != this->thread()) {
+ QObject::connect(renderer->thread(), &QThread::finished, this,
+ &Abstract3DController::destroyRenderer, Qt::DirectConnection);
+ }
}
void Abstract3DController::addSeries(QAbstract3DSeries *series)
diff --git a/src/datavisualization/engine/abstract3dcontroller_p.h b/src/datavisualization/engine/abstract3dcontroller_p.h
index 4d7b36a3..5bb3d863 100644
--- a/src/datavisualization/engine/abstract3dcontroller_p.h
+++ b/src/datavisualization/engine/abstract3dcontroller_p.h
@@ -218,7 +218,6 @@ public:
virtual ~Abstract3DController();
inline bool isInitialized() { return (m_renderer != 0); }
- virtual void destroyRenderer();
virtual void synchDataToRenderer();
virtual void render(const GLuint defaultFboHandle = 0);
virtual void initializeOpenGL() = 0;
@@ -348,6 +347,8 @@ public:
void markSeriesItemLabelsDirty();
public slots:
+ void destroyRenderer();
+
void handleAxisTitleChanged(const QString &title);
void handleAxisLabelsChanged();
void handleAxisRangeChanged(float min, float max);
diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp
index c47e2b29..d7bad300 100644
--- a/src/datavisualization/engine/abstract3drenderer.cpp
+++ b/src/datavisualization/engine/abstract3drenderer.cpp
@@ -28,6 +28,8 @@
#include "scatter3drenderer_p.h"
#include <QtCore/qmath.h>
+#include <QtGui/QWindow>
+#include <QtCore/QThread>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -101,7 +103,11 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller)
m_scaleZWithBackground(0.0f),
m_oldCameraTarget(QVector3D(2000.0f, 2000.0f, 2000.0f)), // Just random invalid target
m_reflectionEnabled(false),
- m_reflectivity(0.5)
+ m_reflectivity(0.5),
+ m_context(0),
+ m_currentContextAtDelete(0),
+ m_currentSurfaceAtDelete(0),
+ m_dummySurfaceAtDelete(0)
{
QObject::connect(m_drawer, &Drawer::drawerChanged, this, &Abstract3DRenderer::updateTextures);
QObject::connect(this, &Abstract3DRenderer::needRender, controller,
@@ -151,10 +157,14 @@ Abstract3DRenderer::~Abstract3DRenderer()
delete m_textureHelper;
}
+
+ restoreContextAfterDelete();
}
void Abstract3DRenderer::initializeOpenGL()
{
+ m_context = QOpenGLContext::currentContext();
+
// Set OpenGL features
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
@@ -1772,6 +1782,36 @@ void Abstract3DRenderer::queriedGraphPosition(const QMatrix4x4 &projectionViewMa
m_graphPositionQueryPending = false;
}
+void Abstract3DRenderer::fixContextBeforeDelete()
+{
+ m_currentContextAtDelete = QOpenGLContext::currentContext();
+ if (m_currentContextAtDelete)
+ m_currentSurfaceAtDelete = m_currentContextAtDelete->surface();
+ if (!m_context.isNull() && m_context.data() != m_currentContextAtDelete
+ && QThread::currentThread() == this->thread()) {
+ m_dummySurfaceAtDelete = new QWindow();
+ m_dummySurfaceAtDelete->setSurfaceType(QWindow::OpenGLSurface);
+ m_dummySurfaceAtDelete->setFormat(m_context->format());
+ m_dummySurfaceAtDelete->create();
+
+ m_context->makeCurrent(m_dummySurfaceAtDelete);
+ }
+}
+
+void Abstract3DRenderer::restoreContextAfterDelete()
+{
+ if (m_currentContextAtDelete && m_currentSurfaceAtDelete
+ && m_context.data() != m_currentContextAtDelete) {
+ m_currentContextAtDelete->makeCurrent(m_currentSurfaceAtDelete);
+ } else if (m_dummySurfaceAtDelete) {
+ m_context->doneCurrent();
+ }
+ delete m_dummySurfaceAtDelete;
+ m_currentContextAtDelete = 0;
+ m_currentSurfaceAtDelete = 0;
+ m_dummySurfaceAtDelete = 0;
+}
+
void Abstract3DRenderer::calculatePolarXZ(const QVector3D &dataPos, float &x, float &z) const
{
// x is angular, z is radial
diff --git a/src/datavisualization/engine/abstract3drenderer_p.h b/src/datavisualization/engine/abstract3drenderer_p.h
index d8ca7696..1857278c 100644
--- a/src/datavisualization/engine/abstract3drenderer_p.h
+++ b/src/datavisualization/engine/abstract3drenderer_p.h
@@ -37,6 +37,8 @@
#include "seriesrendercache_p.h"
#include "customrenderitem_p.h"
+class QSurface;
+
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
class TextureHelper;
@@ -229,6 +231,9 @@ protected:
void queriedGraphPosition(const QMatrix4x4 &projectionViewMatrix, const QVector3D &scaling,
GLuint defaultFboHandle);
+ void fixContextBeforeDelete();
+ void restoreContextAfterDelete();
+
bool m_hasNegativeValues;
Q3DTheme *m_cachedTheme;
Drawer *m_drawer;
@@ -318,6 +323,10 @@ protected:
qreal m_reflectivity;
QLocale m_locale;
+ QPointer<QOpenGLContext> m_context; // Not owned
+ QOpenGLContext *m_currentContextAtDelete; // Not owned
+ QSurface *m_currentSurfaceAtDelete; // Not owned
+ QWindow *m_dummySurfaceAtDelete;
private:
friend class Abstract3DController;
diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp
index e18e4fa5..07bb5f9a 100644
--- a/src/datavisualization/engine/bars3drenderer.cpp
+++ b/src/datavisualization/engine/bars3drenderer.cpp
@@ -90,6 +90,8 @@ Bars3DRenderer::Bars3DRenderer(Bars3DController *controller)
Bars3DRenderer::~Bars3DRenderer()
{
+ fixContextBeforeDelete();
+
if (QOpenGLContext::currentContext()) {
m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer);
m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer);
diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp
index f5d0793f..8ccd0824 100644
--- a/src/datavisualization/engine/scatter3drenderer.cpp
+++ b/src/datavisualization/engine/scatter3drenderer.cpp
@@ -79,6 +79,8 @@ Scatter3DRenderer::Scatter3DRenderer(Scatter3DController *controller)
Scatter3DRenderer::~Scatter3DRenderer()
{
+ fixContextBeforeDelete();
+
if (QOpenGLContext::currentContext()) {
m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer);
m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer);
diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp
index 5daded8f..efecb0e1 100644
--- a/src/datavisualization/engine/surface3drenderer.cpp
+++ b/src/datavisualization/engine/surface3drenderer.cpp
@@ -85,6 +85,8 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
Surface3DRenderer::~Surface3DRenderer()
{
+ fixContextBeforeDelete();
+
if (QOpenGLContext::currentContext()) {
m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer);
m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer);
@@ -2879,19 +2881,12 @@ void Surface3DRenderer::initShaders(const QString &vertexShader, const QString &
Q_UNUSED(vertexShader);
Q_UNUSED(fragmentShader);
- // draw the shader for the surface according to smooth status, shadow and uniform color
- if (m_surfaceFlatShader)
- delete m_surfaceFlatShader;
- if (m_surfaceSmoothShader)
- delete m_surfaceSmoothShader;
- if (m_surfaceTexturedSmoothShader)
- delete m_surfaceTexturedSmoothShader;
- if (m_surfaceTexturedFlatShader)
- delete m_surfaceTexturedFlatShader;
- if (m_surfaceSliceFlatShader)
- delete m_surfaceSliceFlatShader;
- if (m_surfaceSliceSmoothShader)
- delete m_surfaceSliceSmoothShader;
+ delete m_surfaceFlatShader;
+ delete m_surfaceSmoothShader;
+ delete m_surfaceTexturedSmoothShader;
+ delete m_surfaceTexturedFlatShader;
+ delete m_surfaceSliceFlatShader;
+ delete m_surfaceSliceSmoothShader;
#if !defined(QT_OPENGL_ES_2)
if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) {
@@ -2924,6 +2919,7 @@ void Surface3DRenderer::initShaders(const QString &vertexShader, const QString &
} else {
m_surfaceFlatShader = 0;
m_surfaceSliceFlatShader = 0;
+ m_surfaceTexturedFlatShader = 0;
}
#else
m_surfaceSmoothShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
@@ -2983,8 +2979,7 @@ void Surface3DRenderer::initSurfaceShaders()
#if !defined(QT_OPENGL_ES_2)
void Surface3DRenderer::initDepthShader()
{
- if (m_depthShader)
- delete m_depthShader;
+ delete m_depthShader;
m_depthShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexDepth"),
QStringLiteral(":/shaders/fragmentDepth"));
m_depthShader->initialize();
diff --git a/src/datavisualizationqml2/abstractdeclarative.cpp b/src/datavisualizationqml2/abstractdeclarative.cpp
index 6c6cdb90..7e8de95c 100644
--- a/src/datavisualizationqml2/abstractdeclarative.cpp
+++ b/src/datavisualizationqml2/abstractdeclarative.cpp
@@ -62,24 +62,7 @@ AbstractDeclarative::AbstractDeclarative(QQuickItem *parent) :
AbstractDeclarative::~AbstractDeclarative()
{
-#ifdef USE_SHARED_CONTEXT
- // Context can be in another thread, don't delete it directly in that case
- if (m_contextThread && m_contextThread != m_mainThread) {
- if (m_context)
- m_context->deleteLater();
- m_context = 0;
- } else {
- delete m_context;
- }
-#else
- if (m_contextThread && m_contextThread != m_mainThread) {
- if (m_stateStore)
- m_stateStore->deleteLater();
- m_stateStore = 0;
- } else {
- delete m_stateStore;
- }
-#endif
+ destroyContext();
disconnect(this, 0, this, 0);
checkWindowList(0);
@@ -363,7 +346,6 @@ void AbstractDeclarative::activateOpenGLContext(QQuickWindow *window)
m_contextThread = QThread::currentThread();
m_contextWindow = window;
m_qtContext = currentContext;
-
m_context = new QOpenGLContext();
m_context->setFormat(m_qtContext->format());
m_context->setShareContext(m_qtContext);
@@ -371,6 +353,10 @@ void AbstractDeclarative::activateOpenGLContext(QQuickWindow *window)
m_context->makeCurrent(window);
m_controller->initializeOpenGL();
+
+ // Make sure context gets deleted.
+ QObject::connect(m_contextThread, &QThread::finished, this,
+ &AbstractDeclarative::destroyContext, Qt::DirectConnection);
} else {
m_context->makeCurrent(window);
}
@@ -392,6 +378,10 @@ void AbstractDeclarative::activateOpenGLContext(QQuickWindow *window)
m_stateStore->storeGLState();
m_controller->initializeOpenGL();
+
+ // Make sure state store gets deleted.
+ QObject::connect(m_contextThread, &QThread::finished, this,
+ &AbstractDeclarative::destroyContext, Qt::DirectConnection);
} else {
m_stateStore->storeGLState();
}
@@ -827,4 +817,31 @@ void AbstractDeclarative::windowDestroyed(QObject *obj)
windowClearList.remove(win);
}
+void AbstractDeclarative::destroyContext()
+{
+#ifdef USE_SHARED_CONTEXT
+ // Context can be in another thread, don't delete it directly in that case
+ if (m_contextThread && m_contextThread != m_mainThread) {
+ if (m_context)
+ m_context->deleteLater();
+ } else {
+ delete m_context;
+ }
+ m_context = 0;
+#else
+ if (m_contextThread && m_contextThread != m_mainThread) {
+ if (m_stateStore)
+ m_stateStore->deleteLater();
+ } else {
+ delete m_stateStore;
+ }
+ m_stateStore = 0;
+#endif
+ if (m_contextThread) {
+ QObject::disconnect(m_contextThread, &QThread::finished, this,
+ &AbstractDeclarative::destroyContext);
+ m_contextThread = 0;
+ }
+}
+
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualizationqml2/abstractdeclarative_p.h b/src/datavisualizationqml2/abstractdeclarative_p.h
index 04db21f4..0c32a4a5 100644
--- a/src/datavisualizationqml2/abstractdeclarative_p.h
+++ b/src/datavisualizationqml2/abstractdeclarative_p.h
@@ -229,6 +229,7 @@ public slots:
virtual void handleAxisYChanged(QAbstract3DAxis *axis) = 0;
virtual void handleAxisZChanged(QAbstract3DAxis *axis) = 0;
void windowDestroyed(QObject *obj);
+ void destroyContext();
protected:
virtual void mouseDoubleClickEvent(QMouseEvent *event);
diff --git a/tests/qmlmultiwindow/qml/qmlmultiwindow/main.qml b/tests/qmlmultiwindow/qml/qmlmultiwindow/main.qml
index 7dfe0bec..57d62019 100644
--- a/tests/qmlmultiwindow/qml/qmlmultiwindow/main.qml
+++ b/tests/qmlmultiwindow/qml/qmlmultiwindow/main.qml
@@ -31,19 +31,51 @@ Rectangle {
id: data
}
- Window {
- id: firstWindow
- x: 100
- y: 100
- width: 500
- height: 500
- visible: true
- Rectangle {
- id: firstRect
- color: "red"
- anchors.fill: parent
- }
- }
+ property QtObject surfaceWindowObject;
+ property string surfaceWindowStr:
+ "\n
+ import QtQuick 2.1\n
+ import QtQuick.Window 2.1\n
+ import QtQuick.Layouts 1.0\n
+ import QtDataVisualization 1.0\n
+ import \".\"\n
+ Window {\n
+ Data {\n
+ id: data\n
+ }\n
+ id: firstWindow\n
+ x: 100\n
+ y: 100\n
+ width: 500\n
+ height: 500\n
+ visible: true\n
+ Rectangle {\n
+ id: firstRect\n
+ color: \"red\"\n
+ anchors.fill: parent\n
+ Surface3D {\n
+ id: surfaceGraph\n
+ anchors.fill: parent\n
+ anchors.margins: parent.border.width\n
+ theme: Theme3D {\n
+ type: Theme3D.ThemePrimaryColors\n
+ font.pointSize: 60\n
+ }\n
+ scene.activeCamera.cameraPreset: Camera3D.CameraPresetIsometricLeftHigh\n
+ Surface3DSeries {\n
+ itemLabelFormat: \"Pop density at (@xLabel N, @zLabel E): @yLabel\"\n
+ ItemModelSurfaceDataProxy {\n
+ itemModel: data.myData\n
+ rowRole: \"row\"\n
+ columnRole: \"col\"\n
+ xPosRole: \"latitude\"\n
+ zPosRole: \"longitude\"\n
+ yPosRole: \"pop_density\"\n
+ }\n
+ }\n
+ }\n
+ }\n
+ }"
Window {
id: secondWindow
@@ -59,19 +91,6 @@ Rectangle {
}
}
- states: [
- State {
- name: "firstWindow"
- ParentChange { target: surfaceGraph; parent: firstRect; x: 0; y: 0 }
- },
- State {
- name: "secondWindow"
- ParentChange { target: surfaceGraph; parent: secondRect; x: 0; y: 0 }
- }
- ]
-
- state: "firstWindow"
-
//! [0]
GridLayout {
id: gridLayout
@@ -86,32 +105,18 @@ Rectangle {
Rectangle {
Layout.fillHeight: true
Layout.fillWidth: true
- border.color: surfaceGraph.theme.gridLineColor
border.width: 2
+ }
- Surface3D {
- id: surfaceGraph
- anchors.fill: parent
- anchors.margins: parent.border.width
- theme: Theme3D {
- type: Theme3D.ThemePrimaryColors
- font.pointSize: 60
- }
- scene.activeCamera.cameraPreset: Camera3D.CameraPresetIsometricLeftHigh
-
- Surface3DSeries {
- itemLabelFormat: "Pop density at (@xLabel N, @zLabel E): @yLabel"
- ItemModelSurfaceDataProxy {
- itemModel: data.myData
- // The surface data points are not neatly lined up in rows and columns,
- // so we define explicit row and column roles.
- rowRole: "row"
- columnRole: "col"
- xPosRole: "latitude"
- zPosRole: "longitude"
- yPosRole: "pop_density"
- }
- }
+ Timer {
+ id: windowToggleTimer
+ interval: 1000
+ running: false
+ repeat: false
+ onTriggered: {
+ if (surfaceWindowObject != null)
+ surfaceWindowObject.destroy()
+ surfaceWindowObject = Qt.createQmlObject(surfaceWindowStr, mainView)
}
}
@@ -131,13 +136,10 @@ Rectangle {
Layout.minimumWidth: parent.width / 2
Layout.fillHeight: true
Layout.fillWidth: true
- text: "Move graph between windows"
+ text: "(re)construct surface window in a loop"
onClicked: {
- if (mainView.state === "firstWindow") {
- mainView.state = "secondWindow"
- } else {
- mainView.state = "firstWindow"
- }
+ windowToggleTimer.running = true
+ windowToggleTimer.repeat = true
}
}
@@ -231,14 +233,11 @@ Rectangle {
function clearSelections() {
barGraph.clearSelection()
scatterGraph.clearSelection()
- surfaceGraph.clearSelection()
}
function resetCameras() {
- surfaceGraph.scene.activeCamera.cameraPreset = Camera3D.CameraPresetIsometricLeftHigh
scatterGraph.scene.activeCamera.cameraPreset = Camera3D.CameraPresetIsometricLeftHigh
barGraph.scene.activeCamera.cameraPreset = Camera3D.CameraPresetIsometricLeftHigh
- surfaceGraph.scene.activeCamera.zoomLevel = 100.0
scatterGraph.scene.activeCamera.zoomLevel = 100.0
barGraph.scene.activeCamera.zoomLevel = 100.0
}
@@ -246,12 +245,9 @@ Rectangle {
function toggleMeshStyle() {
if (barGraph.seriesList[0].meshSmooth === true) {
barGraph.seriesList[0].meshSmooth = false
- if (surfaceGraph.seriesList[0].flatShadingSupported)
- surfaceGraph.seriesList[0].flatShadingEnabled = true
scatterGraph.seriesList[0].meshSmooth = false
} else {
barGraph.seriesList[0].meshSmooth = true
- surfaceGraph.seriesList[0].flatShadingEnabled = false
scatterGraph.seriesList[0].meshSmooth = true
}
}