mirror of https://github.com/qt/qtdatavis3d.git
389 lines
16 KiB
C++
389 lines
16 KiB
C++
/****************************************************************************
|
|
**
|
|
** 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.reset(new GLint[maxVertexAttribs]);
|
|
m_vertexAttribArrayBoundBuffers.reset(new GLint[maxVertexAttribs]);
|
|
m_vertexAttribArraySizes.reset(new GLint[maxVertexAttribs]);
|
|
m_vertexAttribArrayTypes.reset(new GLint[maxVertexAttribs]);
|
|
m_vertexAttribArrayNormalized.reset(new GLint[maxVertexAttribs]);
|
|
m_vertexAttribArrayStrides.reset(new GLint[maxVertexAttribs]);
|
|
m_vertexAttribArrayOffsets.reset(new void *[maxVertexAttribs]);
|
|
|
|
initGLDefaultState();
|
|
}
|
|
|
|
GLStateStore::~GLStateStore()
|
|
{
|
|
#ifdef VERBOSE_STATE_STORE
|
|
EnumToStringMap::deleteInstance();
|
|
m_map = 0;
|
|
#endif
|
|
}
|
|
|
|
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);
|
|
glGetIntegerv(GL_RENDERBUFFER_BINDING, &m_renderbuffer);
|
|
#else
|
|
glGetIntegerv(GL_RENDERBUFFER, &m_renderbuffer);
|
|
#endif
|
|
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);
|
|
glGetIntegerv(GL_RENDERBUFFER_BINDING, &renderbuffer);
|
|
#else
|
|
glGetIntegerv(GL_RENDERBUFFER, &renderbuffer);
|
|
#endif
|
|
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);
|
|
glBindRenderbuffer(GL_RENDERBUFFER_BINDING, m_renderbuffer);
|
|
#else
|
|
glBindRenderbuffer(GL_RENDERBUFFER, m_renderbuffer);
|
|
#endif
|
|
|
|
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],
|
|
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;
|
|
}
|