summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@digia.com>2014-02-27 11:23:17 +0200
committerMiikka Heikkinen <miikka.heikkinen@digia.com>2014-02-28 11:05:25 +0200
commit86b4e19ee160ee3e84210595db5e6af08a8b9e46 (patch)
treee1f7f1d8dbaa7cc520f7efc8b45868d29aa6c71f
parent34a7223467a45e33c1b344f1e1880bc818b66b27 (diff)
Introduce state storing for mac and android.
At least some mac and android environments do not handle shared contexts properly, leading to slowdowns and/or artifacts. Disable context sharing on mac and android, and instead store and restore relevant opengl state. Also improve renderer and context cleanup Change-Id: I8fa596b95f6ff20d53c950a34b5c28513acbc18f Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
-rw-r--r--src/datavisualization/engine/abstract3dcontroller.cpp10
-rw-r--r--src/datavisualization/engine/abstract3dcontroller_p.h1
-rw-r--r--src/datavisualization/engine/qabstract3dgraph.cpp3
-rw-r--r--src/datavisualizationqml2/abstractdeclarative.cpp96
-rw-r--r--src/datavisualizationqml2/abstractdeclarative_p.h21
-rw-r--r--src/datavisualizationqml2/datavisualizationqml2.pro8
-rw-r--r--src/datavisualizationqml2/enumtostringmap.cpp393
-rw-r--r--src/datavisualizationqml2/enumtostringmap_p.h49
-rw-r--r--src/datavisualizationqml2/glstatestore.cpp377
-rw-r--r--src/datavisualizationqml2/glstatestore_p.h99
10 files changed, 1033 insertions, 24 deletions
diff --git a/src/datavisualization/engine/abstract3dcontroller.cpp b/src/datavisualization/engine/abstract3dcontroller.cpp
index d2b59c58..acb63f0a 100644
--- a/src/datavisualization/engine/abstract3dcontroller.cpp
+++ b/src/datavisualization/engine/abstract3dcontroller.cpp
@@ -81,13 +81,19 @@ Abstract3DController::Abstract3DController(QRect initialViewport, Q3DScene *scen
Abstract3DController::~Abstract3DController()
{
+ destroyRenderer();
+ delete m_scene;
+ delete m_themeManager;
+}
+
+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())
m_renderer->deleteLater();
else
delete m_renderer;
- delete m_scene;
- delete m_themeManager;
+ m_renderer = 0;
}
/**
diff --git a/src/datavisualization/engine/abstract3dcontroller_p.h b/src/datavisualization/engine/abstract3dcontroller_p.h
index f9b6588d..5bae17d6 100644
--- a/src/datavisualization/engine/abstract3dcontroller_p.h
+++ b/src/datavisualization/engine/abstract3dcontroller_p.h
@@ -161,6 +161,7 @@ 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;
diff --git a/src/datavisualization/engine/qabstract3dgraph.cpp b/src/datavisualization/engine/qabstract3dgraph.cpp
index 1551c639..cce2c235 100644
--- a/src/datavisualization/engine/qabstract3dgraph.cpp
+++ b/src/datavisualization/engine/qabstract3dgraph.cpp
@@ -450,6 +450,9 @@ QAbstract3DGraphPrivate::QAbstract3DGraphPrivate(QAbstract3DGraph *q)
QAbstract3DGraphPrivate::~QAbstract3DGraphPrivate()
{
+ if (m_context)
+ m_context->makeCurrent(q_ptr);
+
delete m_visualController;
}
diff --git a/src/datavisualizationqml2/abstractdeclarative.cpp b/src/datavisualizationqml2/abstractdeclarative.cpp
index ce74d541..e7a5c7eb 100644
--- a/src/datavisualizationqml2/abstractdeclarative.cpp
+++ b/src/datavisualizationqml2/abstractdeclarative.cpp
@@ -21,7 +21,6 @@
#include "declarativetheme_p.h"
#include "declarativerendernode_p.h"
-#include <QtCore/QThread>
#include <QtGui/QGuiApplication>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -33,8 +32,6 @@ static QHash<QQuickWindow *, bool> windowClearList;
AbstractDeclarative::AbstractDeclarative(QQuickItem *parent) :
QQuickItem(parent),
m_controller(0),
- m_context(0),
- m_qtContext(0),
m_contextWindow(0),
m_renderMode(RenderIndirect),
#if defined(QT_OPENGL_ES_2)
@@ -43,7 +40,15 @@ AbstractDeclarative::AbstractDeclarative(QQuickItem *parent) :
m_samples(4),
#endif
m_windowSamples(0),
- m_initialisedSize(0, 0)
+ m_initialisedSize(0, 0),
+#ifdef USE_SHARED_CONTEXT
+ m_context(0),
+#else
+ m_stateStore(0),
+#endif
+ m_qtContext(0),
+ m_mainThread(QThread::currentThread()),
+ m_contextThread(0)
{
connect(this, &QQuickItem::windowChanged, this, &AbstractDeclarative::handleWindowChanged);
setAntialiasing(m_samples > 0);
@@ -54,12 +59,23 @@ AbstractDeclarative::AbstractDeclarative(QQuickItem *parent) :
AbstractDeclarative::~AbstractDeclarative()
{
-#if !defined(Q_OS_MAC)
+#ifdef USE_SHARED_CONTEXT
// Context can be in another thread, don't delete it directly in that case
- if (m_context && m_context->thread() != QThread::currentThread())
- m_context->deleteLater();
- else
+ 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
disconnect(this, 0, this, 0);
@@ -216,28 +232,75 @@ void AbstractDeclarative::setSharedController(Abstract3DController *controller)
void AbstractDeclarative::activateOpenGLContext(QQuickWindow *window)
{
-#if !defined(Q_OS_MAC)
- if (!m_context || m_contextWindow != window) {
- m_contextWindow = window;
+#ifdef USE_SHARED_CONTEXT
+ // We can assume we are not in middle of AbstractDeclarative destructor when we are here,
+ // since m_context creation is always done when this function is called from
+ // synchDataToRenderer(), which blocks main thread -> no need to mutex.
+ if (!m_context || !m_qtContext || m_contextWindow != window) {
+ QOpenGLContext *currentContext = QOpenGLContext::currentContext();
+
+ if (m_context && currentContext != m_qtContext) {
+ // If Qt context has changed, the old renderer needs to go.
+ // If the old context window no longer exists, it is okay to delete renderer
+ // in null context, as we can assume Qt context for the window is also gone.
+ m_context->makeCurrent(m_contextWindow);
+ m_controller->destroyRenderer();
+ m_context->doneCurrent(); // So that we don't delete active context
+ }
+
delete m_context;
- m_qtContext = QOpenGLContext::currentContext();
+
+ m_contextThread = QThread::currentThread();
+ m_contextWindow = window;
+ m_qtContext = currentContext;
+
m_context = new QOpenGLContext();
- m_context->setFormat(window->requestedFormat());
+ m_context->setFormat(m_qtContext->format());
m_context->setShareContext(m_qtContext);
m_context->create();
+
+ m_context->makeCurrent(window);
+ m_controller->initializeOpenGL();
+ } else {
+ m_context->makeCurrent(window);
}
- m_context->makeCurrent(window);
#else
- Q_UNUSED(window)
+ // Shared contexts don't work properly in some platforms, so just store the
+ // context state on those
+ if (!m_stateStore || !m_qtContext || m_contextWindow != window) {
+ QOpenGLContext *currentContext = QOpenGLContext::currentContext();
+
+ if (m_qtContext && currentContext != m_qtContext) {
+ // If Qt context has changed but still exists, the old renderer needs to go.
+ // If the old context window no longer exists, it is okay to delete renderer
+ // in null context (though it is likely Qt context is gone in that case, too.)
+ m_qtContext->makeCurrent(m_contextWindow);
+ m_controller->destroyRenderer();
+ currentContext->makeCurrent(window);
+ }
+
+ m_contextThread = QThread::currentThread();
+ m_contextWindow = window;
+ m_qtContext = currentContext;
+
+ delete m_stateStore;
+ m_stateStore = new GLStateStore(QOpenGLContext::currentContext());
+
+ m_stateStore->storeGLState();
+ m_controller->initializeOpenGL();
+ } else {
+ m_stateStore->storeGLState();
+ }
#endif
}
void AbstractDeclarative::doneOpenGLContext(QQuickWindow *window)
{
-#if !defined(Q_OS_MAC)
+#ifdef USE_SHARED_CONTEXT
m_qtContext->makeCurrent(window);
#else
Q_UNUSED(window)
+ m_stateStore->restoreGLState();
#endif
}
@@ -248,7 +311,6 @@ void AbstractDeclarative::synchDataToRenderer()
QQuickWindow *win = window();
activateOpenGLContext(win);
- m_controller->initializeOpenGL();
m_controller->synchDataToRenderer();
doneOpenGLContext(win);
}
diff --git a/src/datavisualizationqml2/abstractdeclarative_p.h b/src/datavisualizationqml2/abstractdeclarative_p.h
index d44a154d..ac8bf9be 100644
--- a/src/datavisualizationqml2/abstractdeclarative_p.h
+++ b/src/datavisualizationqml2/abstractdeclarative_p.h
@@ -29,15 +29,24 @@
#ifndef ABSTRACTDECLARATIVE_P_H
#define ABSTRACTDECLARATIVE_P_H
+#if !defined(Q_OS_MAC) && !defined(Q_OS_ANDROID)
+#define USE_SHARED_CONTEXT
+#endif
+
#include "datavisualizationglobal_p.h"
#include "abstract3dcontroller_p.h"
#include "qabstract3dinputhandler.h"
#include "declarativescene_p.h"
+#ifndef USE_SHARED_CONTEXT
+#include "glstatestore_p.h"
+#endif
+
#include <QtCore/QAbstractItemModel>
#include <QtQuick/QQuickItem>
#include <QtQuick/QQuickWindow>
#include <QtCore/QPointer>
+#include <QtCore/QThread>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -158,13 +167,19 @@ signals:
private:
QPointer<Abstract3DController> m_controller;
QRectF m_cachedGeometry;
- QOpenGLContext *m_context;
- QOpenGLContext *m_qtContext;
- QQuickWindow *m_contextWindow;
+ QPointer<QQuickWindow> m_contextWindow;
AbstractDeclarative::RenderingMode m_renderMode;
int m_samples;
int m_windowSamples;
QSize m_initialisedSize;
+#ifdef USE_SHARED_CONTEXT
+ QOpenGLContext *m_context;
+#else
+ GLStateStore *m_stateStore;
+#endif
+ QPointer<QOpenGLContext> m_qtContext;
+ QThread *m_mainThread;
+ QThread *m_contextThread;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractDeclarative::SelectionFlags)
diff --git a/src/datavisualizationqml2/datavisualizationqml2.pro b/src/datavisualizationqml2/datavisualizationqml2.pro
index df6c647d..ed91b111 100644
--- a/src/datavisualizationqml2/datavisualizationqml2.pro
+++ b/src/datavisualizationqml2/datavisualizationqml2.pro
@@ -26,7 +26,9 @@ SOURCES += \
declarativetheme.cpp \
declarativecolor.cpp \
declarativescene.cpp \
- declarativerendernode.cpp
+ declarativerendernode.cpp \
+ glstatestore.cpp \
+ enumtostringmap.cpp
HEADERS += \
datavisualizationqml2_plugin.h \
@@ -39,7 +41,9 @@ HEADERS += \
declarativetheme_p.h \
declarativecolor_p.h \
declarativescene_p.h \
- declarativerendernode_p.h
+ declarativerendernode_p.h \
+ glstatestore_p.h \
+ enumtostringmap_p.h
OTHER_FILES = qmldir
diff --git a/src/datavisualizationqml2/enumtostringmap.cpp b/src/datavisualizationqml2/enumtostringmap.cpp
new file mode 100644
index 00000000..fd68c6bb
--- /dev/null
+++ b/src/datavisualizationqml2/enumtostringmap.cpp
@@ -0,0 +1,393 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+#include "enumtostringmap_p.h"
+#include <QString>
+#include <QDebug>
+
+static EnumToStringMap *theInstance = 0;
+static unsigned int theInstanceCount = 0;
+
+EnumToStringMap *EnumToStringMap::newInstance()
+{
+ if (theInstance) {
+ theInstanceCount++;
+ return theInstance;
+ }
+
+ theInstance = new EnumToStringMap();
+ theInstanceCount++;
+ return theInstance;
+}
+
+void EnumToStringMap::deleteInstance()
+{
+ theInstanceCount--;
+ if (theInstanceCount <= 0) {
+ delete theInstance;
+ theInstance = 0;
+ }
+}
+
+EnumToStringMap::EnumToStringMap() :
+ m_unknown("<unknown>")
+{
+ m_map[GL_ZERO] = "ZERO/null";
+
+ m_map[GL_DEPTH_BUFFER_BIT] = "DEPTH_BUFFER_BIT";
+ m_map[GL_STENCIL_BUFFER_BIT] = "STENCIL_BUFFER_BIT";
+ m_map[GL_COLOR_BUFFER_BIT] = "COLOR_BUFFER_BIT";
+
+ m_map[GL_STENCIL_BUFFER_BIT] = "STENCIL_BUFFER_BIT";
+ m_map[GL_COLOR_BUFFER_BIT] = "COLOR_BUFFER_BIT";
+
+ m_map[GL_POINTS] = "POINTS";
+ m_map[GL_LINES] = "LINES";
+ m_map[GL_LINE_LOOP] = "LINE_LOOP";
+ m_map[GL_LINE_STRIP] = "LINE_STRIP";
+ m_map[GL_TRIANGLES] = "TRIANGLES";
+ m_map[GL_TRIANGLE_STRIP] = "TRIANGLE_STRIP";
+ m_map[GL_TRIANGLE_FAN] = "TRIANGLE_FAN";
+
+ m_map[GL_SRC_COLOR] = "SRC_COLOR";
+ m_map[GL_ONE_MINUS_SRC_COLOR] = "ONE_MINUS_SRC_COLOR";
+ m_map[GL_SRC_ALPHA] = "SRC_ALPHA";
+ m_map[GL_ONE_MINUS_SRC_ALPHA] = "ONE_MINUS_SRC_ALPHA";
+ m_map[GL_DST_ALPHA] = "DST_ALPHA";
+ m_map[GL_ONE_MINUS_DST_ALPHA] = "ONE_MINUS_DST_ALPHA";
+
+ m_map[GL_DST_COLOR] = "DST_COLOR";
+ m_map[GL_ONE_MINUS_DST_COLOR] = "ONE_MINUS_DST_COLOR";
+ m_map[GL_SRC_ALPHA_SATURATE] = "SRC_ALPHA_SATURATE";
+
+ m_map[GL_FUNC_ADD] = "FUNC_ADD";
+ m_map[GL_BLEND_EQUATION] = "BLEND_EQUATION";
+ m_map[GL_BLEND_EQUATION_RGB] = "BLEND_EQUATION_RGB";
+ m_map[GL_BLEND_EQUATION_ALPHA] = "BLEND_EQUATION_ALPHA";
+
+ m_map[GL_FUNC_SUBTRACT] = "FUNC_SUBTRACT";
+ m_map[GL_FUNC_REVERSE_SUBTRACT] = "FUNC_REVERSE_SUBTRACT";
+
+ m_map[GL_BLEND_DST_RGB] = "BLEND_DST_RGB";
+ m_map[GL_BLEND_SRC_RGB] = "BLEND_SRC_RGB";
+ m_map[GL_BLEND_DST_ALPHA] = "BLEND_DST_ALPHA";
+ m_map[GL_BLEND_SRC_ALPHA] = "BLEND_SRC_ALPHA";
+ m_map[GL_CONSTANT_COLOR] = "CONSTANT_COLOR";
+ m_map[GL_ONE_MINUS_CONSTANT_COLOR] = "ONE_MINUS_CONSTANT_COLOR";
+ m_map[GL_CONSTANT_ALPHA] = "CONSTANT_ALPHA";
+ m_map[GL_ONE_MINUS_CONSTANT_ALPHA] = "ONE_MINUS_CONSTANT_ALPHA";
+ m_map[GL_BLEND_COLOR] = "BLEND_COLOR";
+
+ m_map[GL_ARRAY_BUFFER] = "ARRAY_BUFFER";
+ m_map[GL_ELEMENT_ARRAY_BUFFER] = "ELEMENT_ARRAY_BUFFER";
+ m_map[GL_ARRAY_BUFFER_BINDING] = "ARRAY_BUFFER_BINDING";
+ m_map[GL_ELEMENT_ARRAY_BUFFER_BINDING] = "ELEMENT_ARRAY_BUFFER_BINDING";
+
+ m_map[GL_STREAM_DRAW] = "STREAM_DRAW";
+ m_map[GL_STATIC_DRAW] = "STATIC_DRAW";
+ m_map[GL_DYNAMIC_DRAW] = "DYNAMIC_DRAW";
+
+ m_map[GL_BUFFER_SIZE] = "BUFFER_SIZE";
+ m_map[GL_BUFFER_USAGE] = "BUFFER_USAGE";
+
+ m_map[GL_CURRENT_VERTEX_ATTRIB] = "CURRENT_VERTEX_ATTRIB";
+
+ m_map[GL_FRONT] = "FRONT";
+ m_map[GL_BACK] = "BACK";
+ m_map[GL_FRONT_AND_BACK] = "FRONT_AND_BACK";
+
+ m_map[GL_CULL_FACE] = "CULL_FACE";
+ m_map[GL_BLEND] = "BLEND";
+ m_map[GL_DITHER] = "DITHER";
+ m_map[GL_STENCIL_TEST] = "STENCIL_TEST";
+ m_map[GL_DEPTH_TEST] = "DEPTH_TEST";
+ m_map[GL_SCISSOR_TEST] = "SCISSOR_TEST";
+ m_map[GL_POLYGON_OFFSET_FILL] = "POLYGON_OFFSET_FILL";
+ m_map[GL_SAMPLE_ALPHA_TO_COVERAGE] = "SAMPLE_ALPHA_TO_COVERAGE";
+ m_map[GL_SAMPLE_COVERAGE] = "SAMPLE_COVERAGE";
+
+ m_map[GL_NO_ERROR] = "NO_ERROR";
+ m_map[GL_INVALID_ENUM] = "INVALID_ENUM";
+ m_map[GL_INVALID_VALUE] = "INVALID_VALUE";
+ m_map[GL_INVALID_OPERATION] = "INVALID_OPERATION";
+ m_map[GL_OUT_OF_MEMORY] = "OUT_OF_MEMORY";
+
+ m_map[GL_CW] = "CW";
+ m_map[GL_CCW] = "CCW";
+
+ m_map[GL_LINE_WIDTH] = "LINE_WIDTH";
+ m_map[GL_ALIASED_POINT_SIZE_RANGE] = "ALIASED_POINT_SIZE_RANGE";
+ m_map[GL_ALIASED_LINE_WIDTH_RANGE] = "ALIASED_LINE_WIDTH_RANGE";
+ m_map[GL_CULL_FACE_MODE] = "CULL_FACE_MODE";
+ m_map[GL_FRONT_FACE] = "FRONT_FACE";
+ m_map[GL_DEPTH_RANGE] = "DEPTH_RANGE";
+ m_map[GL_DEPTH_WRITEMASK] = "DEPTH_WRITEMASK";
+ m_map[GL_DEPTH_CLEAR_VALUE] = "DEPTH_CLEAR_VALUE";
+ m_map[GL_DEPTH_FUNC] = "DEPTH_FUNC";
+ m_map[GL_STENCIL_CLEAR_VALUE] = "STENCIL_CLEAR_VALUE";
+ m_map[GL_STENCIL_FUNC] = "STENCIL_FUNC";
+ m_map[GL_STENCIL_FAIL] = "STENCIL_FAIL";
+ m_map[GL_STENCIL_PASS_DEPTH_FAIL] = "STENCIL_PASS_DEPTH_FAIL";
+ m_map[GL_STENCIL_PASS_DEPTH_PASS] = "STENCIL_PASS_DEPTH_PASS";
+ m_map[GL_STENCIL_REF] = "STENCIL_REF";
+ m_map[GL_STENCIL_VALUE_MASK] = "STENCIL_VALUE_MASK";
+ m_map[GL_STENCIL_WRITEMASK] = "STENCIL_WRITEMASK";
+ m_map[GL_STENCIL_BACK_FUNC] = "STENCIL_BACK_FUNC";
+ m_map[GL_STENCIL_BACK_FAIL] = "STENCIL_BACK_FAIL";
+ m_map[GL_STENCIL_BACK_PASS_DEPTH_FAIL] = "STENCIL_BACK_PASS_DEPTH_FAIL";
+ m_map[GL_STENCIL_BACK_PASS_DEPTH_PASS] = "STENCIL_BACK_PASS_DEPTH_PASS";
+ m_map[GL_STENCIL_BACK_REF] = "STENCIL_BACK_REF";
+ m_map[GL_STENCIL_BACK_VALUE_MASK] = "STENCIL_BACK_VALUE_MASK";
+ m_map[GL_STENCIL_BACK_WRITEMASK] = "STENCIL_BACK_WRITEMASK";
+ m_map[GL_VIEWPORT] = "VIEWPORT";
+ m_map[GL_SCISSOR_BOX] = "SCISSOR_BOX";
+
+ m_map[GL_COLOR_CLEAR_VALUE] = "COLOR_CLEAR_VALUE";
+ m_map[GL_COLOR_WRITEMASK] = "COLOR_WRITEMASK";
+ m_map[GL_UNPACK_ALIGNMENT] = "UNPACK_ALIGNMENT";
+ m_map[GL_PACK_ALIGNMENT] = "PACK_ALIGNMENT";
+ m_map[GL_MAX_TEXTURE_SIZE] = "MAX_TEXTURE_SIZE";
+ m_map[GL_MAX_VIEWPORT_DIMS] = "MAX_VIEWPORT_DIMS";
+ m_map[GL_SUBPIXEL_BITS] = "SUBPIXEL_BITS";
+ m_map[GL_RED_BITS] = "RED_BITS";
+ m_map[GL_GREEN_BITS] = "GREEN_BITS";
+ m_map[GL_BLUE_BITS] = "BLUE_BITS";
+ m_map[GL_ALPHA_BITS] = "ALPHA_BITS";
+ m_map[GL_DEPTH_BITS] = "DEPTH_BITS";
+ m_map[GL_STENCIL_BITS] = "STENCIL_BITS";
+ m_map[GL_POLYGON_OFFSET_UNITS] = "POLYGON_OFFSET_UNITS";
+
+ m_map[GL_POLYGON_OFFSET_FACTOR] = "POLYGON_OFFSET_FACTOR";
+ m_map[GL_TEXTURE_BINDING_2D] = "TEXTURE_BINDING_2D";
+ m_map[GL_SAMPLE_BUFFERS] = "SAMPLE_BUFFERS";
+ m_map[GL_SAMPLES] = "SAMPLES";
+ m_map[GL_SAMPLE_COVERAGE_VALUE] = "SAMPLE_COVERAGE_VALUE";
+ m_map[GL_SAMPLE_COVERAGE_INVERT] = "SAMPLE_COVERAGE_INVERT";
+
+ m_map[GL_COMPRESSED_TEXTURE_FORMATS] = "COMPRESSED_TEXTURE_FORMATS";
+
+ m_map[GL_DONT_CARE] = "DONT_CARE";
+ m_map[GL_FASTEST] = "FASTEST";
+ m_map[GL_NICEST] = "NICEST";
+
+ m_map[GL_GENERATE_MIPMAP_HINT] = "GENERATE_MIPMAP_HINT";
+
+ m_map[GL_BYTE] = "BYTE";
+ m_map[GL_UNSIGNED_BYTE] = "UNSIGNED_BYTE";
+ m_map[GL_SHORT] = "SHORT";
+ m_map[GL_UNSIGNED_SHORT] = "UNSIGNED_SHORT";
+ m_map[GL_INT] = "INT";
+ m_map[GL_UNSIGNED_INT] = "UNSIGNED_INT";
+ m_map[GL_FLOAT] = "FLOAT";
+
+ m_map[GL_DEPTH_COMPONENT] = "DEPTH_COMPONENT";
+ m_map[GL_ALPHA] = "ALPHA";
+ m_map[GL_RGB] = "RGB";
+ m_map[GL_RGBA] = "RGBA";
+ m_map[GL_LUMINANCE] = "LUMINANCE";
+ m_map[GL_LUMINANCE_ALPHA] = "LUMINANCE_ALPHA";
+
+ m_map[GL_UNSIGNED_SHORT_4_4_4_4] = "UNSIGNED_SHORT_4_4_4_4";
+ m_map[GL_UNSIGNED_SHORT_5_5_5_1] = "UNSIGNED_SHORT_5_5_5_1";
+ m_map[GL_UNSIGNED_SHORT_5_6_5] = "UNSIGNED_SHORT_5_6_5";
+
+ m_map[GL_FRAGMENT_SHADER] = "FRAGMENT_SHADER";
+ m_map[GL_VERTEX_SHADER] = "VERTEX_SHADER";
+ m_map[GL_MAX_VERTEX_ATTRIBS] = "MAX_VERTEX_ATTRIBS";
+ m_map[GL_MAX_VERTEX_UNIFORM_VECTORS] = "MAX_VERTEX_UNIFORM_VECTORS";
+ m_map[GL_MAX_VARYING_VECTORS] = "MAX_VARYING_VECTORS";
+ m_map[GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS] = "MAX_COMBINED_TEXTURE_IMAGE_UNITS";
+ m_map[GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS] = "MAX_VERTEX_TEXTURE_IMAGE_UNITS";
+ m_map[GL_MAX_TEXTURE_IMAGE_UNITS] = "MAX_TEXTURE_IMAGE_UNITS";
+ m_map[GL_MAX_FRAGMENT_UNIFORM_VECTORS] = "MAX_FRAGMENT_UNIFORM_VECTORS";
+ m_map[GL_SHADER_TYPE] = "SHADER_TYPE";
+ m_map[GL_DELETE_STATUS] = "DELETE_STATUS";
+ m_map[GL_LINK_STATUS] = "LINK_STATUS";
+ m_map[GL_VALIDATE_STATUS] = "VALIDATE_STATUS";
+ m_map[GL_ATTACHED_SHADERS] = "ATTACHED_SHADERS";
+ m_map[GL_ACTIVE_UNIFORMS] = "ACTIVE_UNIFORMS";
+ m_map[GL_ACTIVE_ATTRIBUTES] = "ACTIVE_ATTRIBUTES";
+ m_map[GL_SHADING_LANGUAGE_VERSION] = "SHADING_LANGUAGE_VERSION";
+ m_map[GL_CURRENT_PROGRAM] = "CURRENT_PROGRAM";
+
+ m_map[GL_NEVER] = "NEVER";
+ m_map[GL_LESS] = "LESS";
+ m_map[GL_EQUAL] = "EQUAL";
+ m_map[GL_LEQUAL] = "LEQUAL";
+ m_map[GL_GREATER] = "GREATER";
+ m_map[GL_NOTEQUAL] = "NOTEQUAL";
+ m_map[GL_GEQUAL] = "GEQUAL";
+ m_map[GL_ALWAYS] = "ALWAYS";
+
+ m_map[GL_KEEP] = "KEEP";
+ m_map[GL_REPLACE] = "REPLACE";
+ m_map[GL_INCR] = "INCR";
+ m_map[GL_DECR] = "DECR";
+ m_map[GL_INVERT] = "INVERT";
+ m_map[GL_INCR_WRAP] = "INCR_WRAP";
+ m_map[GL_DECR_WRAP] = "DECR_WRAP";
+
+ m_map[GL_VENDOR] = "VENDOR";
+ m_map[GL_RENDERER] = "RENDERER";
+ m_map[GL_VERSION] = "VERSION";
+
+ m_map[GL_NEAREST] = "NEAREST";
+ m_map[GL_LINEAR] = "LINEAR";
+
+ m_map[GL_NEAREST_MIPMAP_NEAREST] = "NEAREST_MIPMAP_NEAREST";
+ m_map[GL_LINEAR_MIPMAP_NEAREST] = "LINEAR_MIPMAP_NEAREST";
+ m_map[GL_NEAREST_MIPMAP_LINEAR] = "NEAREST_MIPMAP_LINEAR";
+ m_map[GL_LINEAR_MIPMAP_LINEAR] = "LINEAR_MIPMAP_LINEAR";
+
+ m_map[GL_TEXTURE_MAG_FILTER] = "TEXTURE_MAG_FILTER";
+ m_map[GL_TEXTURE_MIN_FILTER] = "TEXTURE_MIN_FILTER";
+ m_map[GL_TEXTURE_WRAP_S] = "TEXTURE_WRAP_S";
+ m_map[GL_TEXTURE_WRAP_T] = "TEXTURE_WRAP_T";
+
+ m_map[GL_TEXTURE_2D] = "TEXTURE_2D";
+ m_map[GL_TEXTURE] = "TEXTURE";
+
+ m_map[GL_TEXTURE_CUBE_MAP] = "TEXTURE_CUBE_MAP";
+ m_map[GL_TEXTURE_BINDING_CUBE_MAP] = "TEXTURE_BINDING_CUBE_MAP";
+ m_map[GL_TEXTURE_CUBE_MAP_POSITIVE_X] = "TEXTURE_CUBE_MAP_POSITIVE_X";
+ m_map[GL_TEXTURE_CUBE_MAP_NEGATIVE_X] = "TEXTURE_CUBE_MAP_NEGATIVE_X";
+ m_map[GL_TEXTURE_CUBE_MAP_POSITIVE_Y] = "TEXTURE_CUBE_MAP_POSITIVE_Y";
+ m_map[GL_TEXTURE_CUBE_MAP_NEGATIVE_Y] = "TEXTURE_CUBE_MAP_NEGATIVE_Y";
+ m_map[GL_TEXTURE_CUBE_MAP_POSITIVE_Z] = "TEXTURE_CUBE_MAP_POSITIVE_Z";
+ m_map[GL_TEXTURE_CUBE_MAP_NEGATIVE_Z] = "TEXTURE_CUBE_MAP_NEGATIVE_Z";
+ m_map[GL_MAX_CUBE_MAP_TEXTURE_SIZE] = "MAX_CUBE_MAP_TEXTURE_SIZE";
+
+ m_map[GL_TEXTURE0] = "TEXTURE0";
+ m_map[GL_TEXTURE1] = "TEXTURE1";
+ m_map[GL_TEXTURE2] = "TEXTURE2";
+ m_map[GL_TEXTURE3] = "TEXTURE3";
+ m_map[GL_TEXTURE4] = "TEXTURE4";
+ m_map[GL_TEXTURE5] = "TEXTURE5";
+ m_map[GL_TEXTURE6] = "TEXTURE6";
+ m_map[GL_TEXTURE7] = "TEXTURE7";
+ m_map[GL_TEXTURE8] = "TEXTURE8";
+ m_map[GL_TEXTURE9] = "TEXTURE9";
+ m_map[GL_TEXTURE10] = "TEXTURE10";
+ m_map[GL_TEXTURE11] = "TEXTURE11";
+ m_map[GL_TEXTURE12] = "TEXTURE12";
+ m_map[GL_TEXTURE13] = "TEXTURE13";
+ m_map[GL_TEXTURE14] = "TEXTURE14";
+ m_map[GL_TEXTURE15] = "TEXTURE15";
+ m_map[GL_TEXTURE16] = "TEXTURE16";
+ m_map[GL_TEXTURE17] = "TEXTURE17";
+ m_map[GL_TEXTURE18] = "TEXTURE18";
+ m_map[GL_TEXTURE19] = "TEXTURE19";
+ m_map[GL_TEXTURE20] = "TEXTURE20";
+ m_map[GL_TEXTURE21] = "TEXTURE21";
+ m_map[GL_TEXTURE22] = "TEXTURE22";
+ m_map[GL_TEXTURE23] = "TEXTURE23";
+ m_map[GL_TEXTURE24] = "TEXTURE24";
+ m_map[GL_TEXTURE25] = "TEXTURE25";
+ m_map[GL_TEXTURE26] = "TEXTURE26";
+ m_map[GL_TEXTURE27] = "TEXTURE27";
+ m_map[GL_TEXTURE28] = "TEXTURE28";
+ m_map[GL_TEXTURE29] = "TEXTURE29";
+ m_map[GL_TEXTURE30] = "TEXTURE30";
+ m_map[GL_TEXTURE31] = "TEXTURE31";
+ m_map[GL_ACTIVE_TEXTURE] = "ACTIVE_TEXTURE";
+
+ m_map[GL_REPEAT] = "REPEAT";
+ m_map[GL_CLAMP_TO_EDGE] = "CLAMP_TO_EDGE";
+ m_map[GL_MIRRORED_REPEAT] = "MIRRORED_REPEAT";
+
+ m_map[GL_FLOAT_VEC2] = "FLOAT_VEC2";
+ m_map[GL_FLOAT_VEC3] = "FLOAT_VEC3";
+ m_map[GL_FLOAT_VEC4] = "FLOAT_VEC4";
+ m_map[GL_INT_VEC2] = "INT_VEC2";
+ m_map[GL_INT_VEC3] = "INT_VEC3";
+ m_map[GL_INT_VEC4] = "INT_VEC4";
+ m_map[GL_BOOL] = "BOOL";
+ m_map[GL_BOOL_VEC2] = "BOOL_VEC2";
+ m_map[GL_BOOL_VEC3] = "BOOL_VEC3";
+ m_map[GL_BOOL_VEC4] = "BOOL_VEC4";
+ m_map[GL_FLOAT_MAT2] = "FLOAT_MAT2";
+ m_map[GL_FLOAT_MAT3] = "FLOAT_MAT3";
+ m_map[GL_FLOAT_MAT4] = "FLOAT_MAT4";
+ m_map[GL_SAMPLER_2D] = "SAMPLER_2D";
+ m_map[GL_SAMPLER_CUBE] = "SAMPLER_CUBE";
+
+ m_map[GL_VERTEX_ATTRIB_ARRAY_ENABLED] = "VERTEX_ATTRIB_ARRAY_ENABLED";
+ m_map[GL_VERTEX_ATTRIB_ARRAY_SIZE] = "VERTEX_ATTRIB_ARRAY_SIZE";
+ m_map[GL_VERTEX_ATTRIB_ARRAY_STRIDE] = "VERTEX_ATTRIB_ARRAY_STRIDE";
+ m_map[GL_VERTEX_ATTRIB_ARRAY_TYPE] = "VERTEX_ATTRIB_ARRAY_TYPE";
+ m_map[GL_VERTEX_ATTRIB_ARRAY_NORMALIZED] = "VERTEX_ATTRIB_ARRAY_NORMALIZED";
+ m_map[GL_VERTEX_ATTRIB_ARRAY_POINTER] = "VERTEX_ATTRIB_ARRAY_POINTER";
+ m_map[GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING] = "VERTEX_ATTRIB_ARRAY_BUFFER_BINDING";
+
+ m_map[GL_COMPILE_STATUS] = "COMPILE_STATUS";
+
+ m_map[GL_LOW_FLOAT] = "LOW_FLOAT";
+ m_map[GL_MEDIUM_FLOAT] = "MEDIUM_FLOAT";
+ m_map[GL_HIGH_FLOAT] = "HIGH_FLOAT";
+ m_map[GL_LOW_INT] = "LOW_INT";
+ m_map[GL_MEDIUM_INT] = "MEDIUM_INT";
+ m_map[GL_HIGH_INT] = "HIGH_INT";
+
+ m_map[GL_FRAMEBUFFER] = "FRAMEBUFFER";
+ m_map[GL_RENDERBUFFER] = "RENDERBUFFER";
+
+ m_map[GL_RGBA4] = "RGBA4";
+ m_map[GL_RGB5_A1] = "RGB5_A1";
+ m_map[GL_RGB565] = "RGB565";
+ m_map[GL_DEPTH_COMPONENT16] = "DEPTH_COMPONENT16";
+ m_map[GL_STENCIL_INDEX] = "STENCIL_INDEX";
+ m_map[GL_STENCIL_INDEX8] = "STENCIL_INDEX8";
+
+ m_map[GL_RENDERBUFFER_WIDTH] = "RENDERBUFFER_WIDTH";
+ m_map[GL_RENDERBUFFER_HEIGHT] = "RENDERBUFFER_HEIGHT";
+ m_map[GL_RENDERBUFFER_INTERNAL_FORMAT] = "RENDERBUFFER_INTERNAL_FORMAT";
+ m_map[GL_RENDERBUFFER_RED_SIZE] = "RENDERBUFFER_RED_SIZE";
+ m_map[GL_RENDERBUFFER_GREEN_SIZE] = "RENDERBUFFER_GREEN_SIZE";
+ m_map[GL_RENDERBUFFER_BLUE_SIZE] = "RENDERBUFFER_BLUE_SIZE";
+ m_map[GL_RENDERBUFFER_ALPHA_SIZE] = "RENDERBUFFER_ALPHA_SIZE";
+ m_map[GL_RENDERBUFFER_DEPTH_SIZE] = "RENDERBUFFER_DEPTH_SIZE";
+ m_map[GL_RENDERBUFFER_STENCIL_SIZE] = "RENDERBUFFER_STENCIL_SIZE";
+
+ m_map[GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE] = "FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE";
+ m_map[GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME] = "FRAMEBUFFER_ATTACHMENT_OBJECT_NAME";
+ m_map[GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL] = "FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL";
+ m_map[GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE] = "FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE";
+
+ m_map[GL_COLOR_ATTACHMENT0] = "COLOR_ATTACHMENT0";
+ m_map[GL_DEPTH_ATTACHMENT] = "DEPTH_ATTACHMENT";
+ m_map[GL_STENCIL_ATTACHMENT] = "STENCIL_ATTACHMENT";
+
+ m_map[GL_FRAMEBUFFER_COMPLETE] = "FRAMEBUFFER_COMPLETE";
+ m_map[GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT] = "FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
+ m_map[GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT] = "FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
+ m_map[GL_FRAMEBUFFER_UNSUPPORTED] = "FRAMEBUFFER_UNSUPPORTED";
+
+ m_map[GL_FRAMEBUFFER_BINDING] = "FRAMEBUFFER_BINDING";
+ m_map[GL_RENDERBUFFER_BINDING] = "RENDERBUFFER_BINDING";
+ m_map[GL_MAX_RENDERBUFFER_SIZE] = "MAX_RENDERBUFFER_SIZE";
+
+ m_map[GL_INVALID_FRAMEBUFFER_OPERATION] = "INVALID_FRAMEBUFFER_OPERATION";
+}
+
+QString EnumToStringMap::lookUp(const GLuint value) const
+{
+ if (m_map.contains(value))
+ return m_map[value];
+
+ return QString("0x0%1").arg(value, 0, 16);
+}
+
diff --git a/src/datavisualizationqml2/enumtostringmap_p.h b/src/datavisualizationqml2/enumtostringmap_p.h
new file mode 100644
index 00000000..2206f153
--- /dev/null
+++ b/src/datavisualizationqml2/enumtostringmap_p.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the QtDataVisualization 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.
+
+#ifndef ENUMTOSTRINGMAP_P_H
+#define ENUMTOSTRINGMAP_P_H
+
+#include <QtGui/qopengl.h>
+#include <QMap>
+#include <QString>
+
+class EnumToStringMap
+{
+public:
+ static EnumToStringMap *newInstance();
+ static void deleteInstance();
+ QString lookUp(const GLuint value) const;
+
+private:
+ EnumToStringMap();
+ QMap<int, QString> m_map;
+ QString m_unknown;
+};
+
+#endif
diff --git a/src/datavisualizationqml2/glstatestore.cpp b/src/datavisualizationqml2/glstatestore.cpp
new file mode 100644
index 00000000..f053078b
--- /dev/null
+++ b/src/datavisualizationqml2/glstatestore.cpp
@@ -0,0 +1,377 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+#include "glstatestore_p.h"
+#include <QDebug>
+#include <QColor>
+#include <QFile>
+
+#ifdef VERBOSE_STATE_STORE
+static QFile *beforeFile = 0;
+static QFile *afterFile = 0;
+#endif
+
+GLStateStore::GLStateStore(QOpenGLContext *context, QObject *parent) :
+ QObject(parent),
+ QOpenGLFunctions(context)
+ #ifdef VERBOSE_STATE_STORE
+ , m_map(EnumToStringMap::newInstance())
+ #endif
+{
+ GLint maxVertexAttribs;
+ glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
+
+#ifdef VERBOSE_STATE_STORE
+ qDebug() << "GL_MAX_VERTEX_ATTRIBS: " << maxVertexAttribs;
+ if (!beforeFile) {
+ beforeFile = new QFile(QStringLiteral("state_before.txt"));
+ afterFile = new QFile(QStringLiteral("state_after.txt"));
+ beforeFile->open(QIODevice::WriteOnly);
+ afterFile->open(QIODevice::WriteOnly);
+ QDebug beforeInit(beforeFile);
+ QDebug afterInit(afterFile);
+ beforeInit << "GL states before 'context switch'" << endl;
+ afterInit << "GL states after 'context switch'" << endl;
+ }
+#endif
+
+ m_maxVertexAttribs = qMin(maxVertexAttribs, 2); // Datavis only uses 2 attribs max
+ m_vertexAttribArrayEnabledStates = new GLint[maxVertexAttribs];
+ m_vertexAttribArrayBoundBuffers = new GLint[maxVertexAttribs];
+ m_vertexAttribArraySizes = new GLint[maxVertexAttribs];
+ m_vertexAttribArrayTypes = new GLint[maxVertexAttribs];
+ m_vertexAttribArrayNormalized = new GLint[maxVertexAttribs];
+ m_vertexAttribArrayStrides = new GLint[maxVertexAttribs];
+ m_vertexAttribArrayOffsets = new GLint[maxVertexAttribs];
+
+ initGLDefaultState();
+}
+
+GLStateStore::~GLStateStore()
+{
+#ifdef VERBOSE_STATE_STORE
+ EnumToStringMap::deleteInstance();
+ m_map = 0;
+#endif
+ delete m_vertexAttribArrayEnabledStates;
+ delete m_vertexAttribArrayBoundBuffers;
+}
+
+void GLStateStore::storeGLState()
+{
+#ifdef VERBOSE_STATE_STORE
+ printCurrentState(true);
+#endif
+
+#if !defined(QT_OPENGL_ES_2)
+ glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &m_drawFramebuffer);
+ glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &m_readFramebuffer);
+#endif
+ glGetIntegerv(GL_RENDERBUFFER_BINDING, &m_renderbuffer);
+ glGetFloatv(GL_COLOR_CLEAR_VALUE, m_clearColor);
+ m_isBlendingEnabled = glIsEnabled(GL_BLEND);
+ m_isDepthTestEnabled = glIsEnabled(GL_DEPTH_TEST);
+ glGetBooleanv(GL_DEPTH_WRITEMASK, &m_isDepthWriteEnabled);
+ glGetFloatv(GL_DEPTH_CLEAR_VALUE, &m_clearDepth);
+ glGetIntegerv(GL_DEPTH_FUNC, &m_depthFunc);
+ glGetBooleanv(GL_POLYGON_OFFSET_FILL, &m_polygonOffsetFillEnabled);
+ glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &m_polygonOffsetFactor);
+ glGetFloatv(GL_POLYGON_OFFSET_UNITS, &m_polygonOffsetUnits);
+
+ glGetIntegerv(GL_CURRENT_PROGRAM, &m_currentProgram);
+ glGetIntegerv(GL_ACTIVE_TEXTURE, &m_activeTexture);
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &m_texBinding2D);
+ glGetIntegerv(GL_FRONT_FACE, &m_frontFace);
+ m_isCullFaceEnabled = glIsEnabled(GL_CULL_FACE);
+ glGetIntegerv(GL_CULL_FACE_MODE, &m_cullFaceMode);
+ glGetIntegerv(GL_BLEND_EQUATION_RGB, &m_blendEquationRGB);
+ glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &m_blendEquationAlpha);
+ glGetIntegerv(GL_BLEND_DST_ALPHA, &m_blendDestAlpha);
+ glGetIntegerv(GL_BLEND_DST_RGB, &m_blendDestRGB);
+ glGetIntegerv(GL_BLEND_SRC_ALPHA, &m_blendSrcAlpha);
+ glGetIntegerv(GL_BLEND_SRC_RGB, &m_blendSrcRGB);
+ glGetIntegerv(GL_SCISSOR_BOX, m_scissorBox);
+ m_isScissorTestEnabled = glIsEnabled(GL_SCISSOR_TEST);
+
+ glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &m_boundArrayBuffer);
+ glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &m_boundElementArrayBuffer);
+
+ for (int i = 0; i < m_maxVertexAttribs;i++) {
+ glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &m_vertexAttribArrayEnabledStates[i]);
+ glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &m_vertexAttribArrayBoundBuffers[i]);
+ glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &m_vertexAttribArraySizes[i]);
+ glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &m_vertexAttribArrayTypes[i]);
+ glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &m_vertexAttribArrayNormalized[i]);
+ glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &m_vertexAttribArrayStrides[i]);
+ }
+}
+
+#ifdef VERBOSE_STATE_STORE
+void GLStateStore::printCurrentState(bool in)
+{
+ QFile *file;
+ if (in)
+ file = beforeFile;
+ else
+ file = afterFile;
+
+ if (file->isOpen()) {
+ QDebug msg(file);
+#if !defined(QT_OPENGL_ES_2)
+ GLint drawFramebuffer;
+ GLint readFramebuffer;
+#endif
+ GLint renderbuffer;
+ GLfloat clearColor[4];
+ GLfloat clearDepth;
+ GLboolean isBlendingEnabled = glIsEnabled(GL_BLEND);
+ GLboolean isDepthTestEnabled = glIsEnabled(GL_DEPTH_TEST);
+ GLint depthFunc;
+ GLboolean isDepthWriteEnabled;
+ GLint currentProgram;
+ GLint *vertexAttribArrayEnabledStates = new GLint[m_maxVertexAttribs];
+ GLint *vertexAttribArrayBoundBuffers = new GLint[m_maxVertexAttribs];
+ GLint *vertexAttribArraySizes = new GLint[m_maxVertexAttribs];
+ GLint *vertexAttribArrayTypes = new GLint[m_maxVertexAttribs];
+ GLint *vertexAttribArrayNormalized = new GLint[m_maxVertexAttribs];
+ GLint *vertexAttribArrayStrides = new GLint[m_maxVertexAttribs];
+ GLint activeTexture;
+ GLint texBinding2D;
+ GLint arrayBufferBinding;
+ GLint frontFace;
+ GLboolean isCullFaceEnabled = glIsEnabled(GL_CULL_FACE);
+ GLint cullFaceMode;
+ GLint blendEquationRGB;
+ GLint blendEquationAlpha;
+
+ GLint blendDestAlpha;
+ GLint blendDestRGB;
+ GLint blendSrcAlpha;
+ GLint blendSrcRGB;
+ GLint scissorBox[4];
+ GLboolean isScissorTestEnabled = glIsEnabled(GL_SCISSOR_TEST);
+ GLint boundElementArrayBuffer;
+ GLboolean polygonOffsetFillEnabled;
+ GLfloat polygonOffsetFactor;
+ GLfloat polygonOffsetUnits;
+
+ glGetBooleanv(GL_DEPTH_WRITEMASK, &isDepthWriteEnabled);
+#if !defined(QT_OPENGL_ES_2)
+ glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &drawFramebuffer);
+ glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &readFramebuffer);
+#endif
+ glGetIntegerv(GL_RENDERBUFFER_BINDING, &renderbuffer);
+ glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor);
+ glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth);
+ glGetIntegerv(GL_DEPTH_FUNC, &depthFunc);
+ glGetBooleanv(GL_POLYGON_OFFSET_FILL, &polygonOffsetFillEnabled);
+ glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &polygonOffsetFactor);
+ glGetFloatv(GL_POLYGON_OFFSET_UNITS, &polygonOffsetUnits);
+
+ glGetIntegerv(GL_CURRENT_PROGRAM, &currentProgram);
+ glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture);
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &texBinding2D );
+ glGetIntegerv(GL_FRONT_FACE, &frontFace);
+ glGetIntegerv(GL_CULL_FACE_MODE, &cullFaceMode);
+ glGetIntegerv(GL_BLEND_EQUATION_RGB, &blendEquationRGB);
+ glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &blendEquationAlpha);
+ glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDestAlpha);
+ glGetIntegerv(GL_BLEND_DST_RGB, &blendDestRGB);
+ glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrcAlpha);
+ glGetIntegerv(GL_BLEND_SRC_RGB, &blendSrcRGB);
+ glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
+ glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &boundElementArrayBuffer);
+ glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &arrayBufferBinding);
+
+ for (int i = 0; i < m_maxVertexAttribs;i++) {
+ glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &vertexAttribArrayEnabledStates[i]);
+ glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &vertexAttribArrayBoundBuffers[i]);
+ glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &vertexAttribArraySizes[i]);
+ glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &vertexAttribArrayTypes[i]);
+ glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &vertexAttribArrayNormalized[i]);
+ glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &vertexAttribArrayStrides[i]);
+ }
+
+ QColor color;
+ color.setRgbF(clearColor[0], clearColor[1], clearColor[2]);
+ color.setAlphaF(clearColor[3]);
+
+#if !defined(QT_OPENGL_ES_2)
+ msg << "---" << endl;
+ msg << " GL_DRAW_FRAMEBUFFER_BINDING "<< drawFramebuffer << endl;
+ msg << " GL_READ_FRAMEBUFFER_BINDING "<< readFramebuffer << endl;
+#endif
+ msg << " GL_RENDERBUFFER_BINDING " << renderbuffer << endl;
+ msg << " GL_SCISSOR_TEST " << bool(isScissorTestEnabled) << endl;
+ msg << " GL_SCISSOR_BOX " << m_scissorBox[0] << m_scissorBox[1] << m_scissorBox[2]
+ << m_scissorBox[3] << endl;
+ msg << " GL_COLOR_CLEAR_VALUE "<< color << endl;
+ msg << " GL_DEPTH_CLEAR_VALUE "<< clearDepth << endl;
+ msg << " GL_BLEND "<< bool(isBlendingEnabled) << endl;
+ msg << " GL_BLEND_EQUATION_RGB" << m_map->lookUp(blendEquationRGB) << endl;
+ msg << " GL_BLEND_EQUATION_ALPHA" << m_map->lookUp(blendEquationAlpha) << endl;
+ msg << " GL_BLEND_DST_ALPHA" << m_map->lookUp(blendDestAlpha) << endl;
+ msg << " GL_BLEND_DST_RGB" << m_map->lookUp(blendDestRGB) << endl;
+ msg << " GL_BLEND_SRC_ALPHA" << m_map->lookUp(blendSrcAlpha) << endl;
+ msg << " GL_BLEND_SRC_RGB" << m_map->lookUp(blendSrcRGB) << endl;
+ msg << " GL_DEPTH_TEST "<< bool(isDepthTestEnabled) << endl;
+ msg << " GL_DEPTH_WRITEMASK "<< bool(isDepthWriteEnabled) << endl;
+ msg << " GL_POLYGON_OFFSET_FILL" << bool(polygonOffsetFillEnabled) << endl;
+ msg << " GL_POLYGON_OFFSET_FACTOR "<< polygonOffsetFactor << endl;
+ msg << " GL_POLYGON_OFFSET_UNITS "<< polygonOffsetUnits << endl;
+ msg << " GL_CULL_FACE "<< bool(isCullFaceEnabled) << endl;
+ msg << " GL_CULL_FACE_MODE "<< m_map->lookUp(cullFaceMode) << endl;
+ msg << " GL_DEPTH_FUNC "<< m_map->lookUp(depthFunc) << endl;
+ msg << " GL_FRONT_FACE "<< m_map->lookUp(frontFace) << endl;
+ msg << " GL_CURRENT_PROGRAM "<< currentProgram << endl;
+ msg << " GL_ACTIVE_TEXTURE "<< QString("0x%1").arg(activeTexture, 0, 16) << endl;
+ msg << " GL_TEXTURE_BINDING_2D "<< texBinding2D << endl;
+ msg << " GL_ELEMENT_ARRAY_BUFFER_BINDING "<< boundElementArrayBuffer << endl;
+ msg << " GL_ARRAY_BUFFER_BINDING "<< arrayBufferBinding << endl;
+ for (int i = 0; i < m_maxVertexAttribs;i++) {
+ msg << " GL_VERTEX_ATTRIB_ARRAY_ENABLED "<< i << " = "
+ << bool(vertexAttribArrayEnabledStates[i]) << endl;
+ msg << " GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING"<< i << " = "
+ << vertexAttribArrayBoundBuffers[i] << endl;
+ msg << " GL_VERTEX_ATTRIB_ARRAY_SIZE"<< i << " = "
+ << vertexAttribArraySizes[i] << endl;
+ msg << " GL_VERTEX_ATTRIB_ARRAY_TYPE"<< i << " = "
+ << vertexAttribArrayTypes[i] << endl;
+ msg << " GL_VERTEX_ATTRIB_ARRAY_NORMALIZED"<< i << " = "
+ << vertexAttribArrayNormalized[i] << endl;
+ msg << " GL_VERTEX_ATTRIB_ARRAY_STRIDE"<< i << " = "
+ << vertexAttribArrayStrides[i] << endl;
+ }
+ }
+}
+#endif
+
+void GLStateStore::restoreGLState()
+{
+#if !defined(QT_OPENGL_ES_2)
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, m_readFramebuffer);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_drawFramebuffer);
+#endif
+ glBindRenderbuffer(GL_RENDERBUFFER_BINDING, m_renderbuffer);
+
+ if (m_isScissorTestEnabled)
+ glEnable(GL_SCISSOR_TEST);
+ else
+ glDisable(GL_SCISSOR_TEST);
+
+ glScissor(m_scissorBox[0], m_scissorBox[1], m_scissorBox[2], m_scissorBox[3]);
+ glClearColor(m_clearColor[0], m_clearColor[1], m_clearColor[2], m_clearColor[3]);
+ glClearDepthf(m_clearDepth);
+ if (m_isBlendingEnabled)
+ glEnable(GL_BLEND);
+ else
+ glDisable(GL_BLEND);
+
+ if (m_isDepthTestEnabled)
+ glEnable(GL_DEPTH_TEST);
+ else
+ glDisable(GL_DEPTH_TEST);
+
+ if (m_isCullFaceEnabled)
+ glEnable(GL_CULL_FACE);
+ else
+ glDisable(GL_CULL_FACE);
+
+ glCullFace(m_cullFaceMode);
+
+ glBlendEquationSeparate(m_blendEquationRGB, m_blendEquationAlpha);
+ glBlendFuncSeparate(m_blendSrcRGB, m_blendDestRGB, m_blendSrcAlpha, m_blendDestAlpha);
+
+ glDepthMask(m_isDepthWriteEnabled);
+ glDepthFunc(m_depthFunc);
+ glFrontFace(m_frontFace);
+
+ if (m_polygonOffsetFillEnabled)
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ else
+ glDisable(GL_POLYGON_OFFSET_FILL);
+
+ glPolygonOffset(m_polygonOffsetFactor, m_polygonOffsetUnits);
+
+ glUseProgram(m_currentProgram);
+
+ glActiveTexture(m_activeTexture);
+ glBindTexture(GL_TEXTURE_2D, m_texBinding2D);
+
+ // Restore bound element array buffer and array buffers
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_boundElementArrayBuffer);
+ for (int i = 0; i < m_maxVertexAttribs; i++) {
+ if (m_vertexAttribArrayEnabledStates[i])
+ glEnableVertexAttribArray(i);
+ else
+ glDisableVertexAttribArray(i);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vertexAttribArrayBoundBuffers[i]);
+ glVertexAttribPointer(i, m_vertexAttribArraySizes[i],
+ m_vertexAttribArrayTypes[i],
+ m_vertexAttribArrayNormalized[i],
+ m_vertexAttribArrayStrides[i],
+ (void *) m_vertexAttribArrayOffsets[i]);
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_boundArrayBuffer);
+
+#ifdef VERBOSE_STATE_STORE
+ printCurrentState(false);
+#endif
+}
+
+void GLStateStore::initGLDefaultState()
+{
+#if !defined(QT_OPENGL_ES_2)
+ m_drawFramebuffer = 0;
+ m_readFramebuffer = 0;
+#endif
+ m_renderbuffer = 0;
+ m_clearColor[0] = m_clearColor[1] = m_clearColor[2] = m_clearColor[3] = 1.0f;
+ m_clearDepth = 1.0f;
+ m_isBlendingEnabled = GL_FALSE;
+ m_isDepthTestEnabled = GL_FALSE;
+ m_depthFunc = GL_LESS;
+ m_isDepthWriteEnabled = GL_TRUE;
+ m_currentProgram = 0;
+ m_texBinding2D = 0;
+ for (int i = 0; i < m_maxVertexAttribs;i++) {
+ m_vertexAttribArrayEnabledStates[i] = GL_FALSE;
+ m_vertexAttribArrayBoundBuffers[i] = 0;
+ m_vertexAttribArraySizes[i] = 4;
+ m_vertexAttribArrayTypes[i] = GL_FLOAT;
+ m_vertexAttribArrayNormalized[i] = GL_FALSE;
+ m_vertexAttribArrayStrides[i] = 0;
+ m_vertexAttribArrayOffsets[i] = 0;
+ }
+ m_activeTexture = GL_TEXTURE0;
+ m_frontFace = GL_CCW;
+ m_isCullFaceEnabled = false;
+ m_cullFaceMode = GL_BACK;
+ m_blendEquationRGB = GL_FUNC_ADD;
+ m_blendEquationAlpha = GL_FUNC_ADD;
+ m_scissorBox[0] = 0;
+ m_scissorBox[1] = 0;
+ m_scissorBox[2] = 0;
+ m_scissorBox[3] = 0;
+ m_isScissorTestEnabled = GL_FALSE;
+
+ m_polygonOffsetFillEnabled = GL_FALSE;
+ m_polygonOffsetFactor = 0.0;
+ m_polygonOffsetUnits = 0.0;
+}
diff --git a/src/datavisualizationqml2/glstatestore_p.h b/src/datavisualizationqml2/glstatestore_p.h
new file mode 100644
index 00000000..560598bf
--- /dev/null
+++ b/src/datavisualizationqml2/glstatestore_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the QtDataVisualization 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.
+
+#ifndef GLSTATESTORE_P_H
+#define GLSTATESTORE_P_H
+
+//#define VERBOSE_STATE_STORE
+
+#include <QObject>
+#include <QtGui/QOpenGLFunctions>
+#include <QtGui/QOpenGLContext>
+#ifdef VERBOSE_STATE_STORE
+#include "enumtostringmap_p.h"
+#endif
+
+class GLStateStore : public QObject, protected QOpenGLFunctions
+{
+ Q_OBJECT
+public:
+ explicit GLStateStore(QOpenGLContext *context, QObject *parent = 0);
+ ~GLStateStore();
+
+ void storeGLState();
+ void restoreGLState();
+ void initGLDefaultState();
+
+#ifdef VERBOSE_STATE_STORE
+ void printCurrentState(bool in);
+ EnumToStringMap *m_map;
+#endif
+
+ GLint m_scissorBox[4];
+ GLboolean m_isScissorTestEnabled;
+
+#if !defined(QT_OPENGL_ES_2)
+ GLint m_drawFramebuffer;
+ GLint m_readFramebuffer;
+#endif
+ GLint m_renderbuffer;
+ GLfloat m_clearColor[4];
+ GLfloat m_clearDepth;
+ GLboolean m_isBlendingEnabled;
+ GLboolean m_isDepthTestEnabled;
+ GLint m_depthFunc;
+ GLboolean m_isDepthWriteEnabled;
+ GLint m_currentProgram;
+ GLint m_maxVertexAttribs;
+ GLint *m_vertexAttribArrayEnabledStates;
+ GLint *m_vertexAttribArrayBoundBuffers;
+ GLint *m_vertexAttribArraySizes;
+ GLint *m_vertexAttribArrayTypes;
+ GLint *m_vertexAttribArrayNormalized;
+ GLint *m_vertexAttribArrayStrides;
+ GLint *m_vertexAttribArrayOffsets;
+
+ GLint m_activeTexture;
+ GLint m_texBinding2D;
+ GLint m_frontFace;
+ GLboolean m_isCullFaceEnabled;
+ GLint m_cullFaceMode;
+ GLint m_blendEquationRGB;
+ GLint m_blendEquationAlpha;
+ GLint m_blendDestAlpha;
+ GLint m_blendDestRGB;
+ GLint m_blendSrcAlpha;
+ GLint m_blendSrcRGB;
+ GLint m_boundArrayBuffer;
+ GLint m_boundElementArrayBuffer;
+ GLboolean m_polygonOffsetFillEnabled;
+ GLfloat m_polygonOffsetFactor;
+ GLfloat m_polygonOffsetUnits;
+};
+
+#endif