diff options
author | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2014-02-27 11:23:17 +0200 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2014-02-28 11:05:25 +0200 |
commit | 86b4e19ee160ee3e84210595db5e6af08a8b9e46 (patch) | |
tree | e1f7f1d8dbaa7cc520f7efc8b45868d29aa6c71f /src | |
parent | 34a7223467a45e33c1b344f1e1880bc818b66b27 (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>
Diffstat (limited to 'src')
-rw-r--r-- | src/datavisualization/engine/abstract3dcontroller.cpp | 10 | ||||
-rw-r--r-- | src/datavisualization/engine/abstract3dcontroller_p.h | 1 | ||||
-rw-r--r-- | src/datavisualization/engine/qabstract3dgraph.cpp | 3 | ||||
-rw-r--r-- | src/datavisualizationqml2/abstractdeclarative.cpp | 96 | ||||
-rw-r--r-- | src/datavisualizationqml2/abstractdeclarative_p.h | 21 | ||||
-rw-r--r-- | src/datavisualizationqml2/datavisualizationqml2.pro | 8 | ||||
-rw-r--r-- | src/datavisualizationqml2/enumtostringmap.cpp | 393 | ||||
-rw-r--r-- | src/datavisualizationqml2/enumtostringmap_p.h | 49 | ||||
-rw-r--r-- | src/datavisualizationqml2/glstatestore.cpp | 377 | ||||
-rw-r--r-- | src/datavisualizationqml2/glstatestore_p.h | 99 |
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, ¤tProgram); + 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 |