1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "glstatestore_p.h"
5#include <QDebug>
6#include <QColor>
7#include <QFile>
8
9#ifdef VERBOSE_STATE_STORE
10static QFile *beforeFile = 0;
11static QFile *afterFile = 0;
12#endif
13
14QT_BEGIN_NAMESPACE
15
16GLStateStore::GLStateStore(QOpenGLContext *context, QObject *parent) :
17 QObject(parent),
18 QOpenGLFunctions(context)
19 #ifdef VERBOSE_STATE_STORE
20 , m_map(EnumToStringMap::newInstance())
21 #endif
22{
23 GLint maxVertexAttribs;
24 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, params: &maxVertexAttribs);
25
26#ifdef VERBOSE_STATE_STORE
27 qDebug() << "GL_MAX_VERTEX_ATTRIBS: " << maxVertexAttribs;
28 if (!beforeFile) {
29 beforeFile = new QFile(QStringLiteral("state_before.txt"));
30 afterFile = new QFile(QStringLiteral("state_after.txt"));
31 beforeFile->open(QIODevice::WriteOnly);
32 afterFile->open(QIODevice::WriteOnly);
33 QDebug beforeInit(beforeFile);
34 QDebug afterInit(afterFile);
35 beforeInit << "GL states before 'context switch'" << endl;
36 afterInit << "GL states after 'context switch'" << endl;
37 }
38#endif
39
40 m_maxVertexAttribs = qMin(a: maxVertexAttribs, b: 2); // Datavis only uses 2 attribs max
41 m_vertexAttribArrayEnabledStates.reset(other: new GLint[maxVertexAttribs]);
42 m_vertexAttribArrayBoundBuffers.reset(other: new GLint[maxVertexAttribs]);
43 m_vertexAttribArraySizes.reset(other: new GLint[maxVertexAttribs]);
44 m_vertexAttribArrayTypes.reset(other: new GLint[maxVertexAttribs]);
45 m_vertexAttribArrayNormalized.reset(other: new GLint[maxVertexAttribs]);
46 m_vertexAttribArrayStrides.reset(other: new GLint[maxVertexAttribs]);
47 m_vertexAttribArrayOffsets.reset(other: new void *[maxVertexAttribs]);
48
49 initGLDefaultState();
50}
51
52GLStateStore::~GLStateStore()
53{
54#ifdef VERBOSE_STATE_STORE
55 EnumToStringMap::deleteInstance();
56 m_map = 0;
57#endif
58}
59
60void GLStateStore::storeGLState()
61{
62#ifdef VERBOSE_STATE_STORE
63 printCurrentState(true);
64#endif
65
66#if !QT_CONFIG(opengles2)
67 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, params: &m_drawFramebuffer);
68 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, params: &m_readFramebuffer);
69 glGetIntegerv(GL_RENDERBUFFER_BINDING, params: &m_renderbuffer);
70#endif
71 glGetFloatv(GL_COLOR_CLEAR_VALUE, params: m_clearColor);
72 m_isBlendingEnabled = glIsEnabled(GL_BLEND);
73 m_isDepthTestEnabled = glIsEnabled(GL_DEPTH_TEST);
74 glGetBooleanv(GL_DEPTH_WRITEMASK, params: &m_isDepthWriteEnabled);
75 glGetFloatv(GL_DEPTH_CLEAR_VALUE, params: &m_clearDepth);
76 glGetIntegerv(GL_DEPTH_FUNC, params: &m_depthFunc);
77 glGetBooleanv(GL_POLYGON_OFFSET_FILL, params: &m_polygonOffsetFillEnabled);
78 glGetFloatv(GL_POLYGON_OFFSET_FACTOR, params: &m_polygonOffsetFactor);
79 glGetFloatv(GL_POLYGON_OFFSET_UNITS, params: &m_polygonOffsetUnits);
80
81 glGetIntegerv(GL_CURRENT_PROGRAM, params: &m_currentProgram);
82 glGetIntegerv(GL_ACTIVE_TEXTURE, params: &m_activeTexture);
83 glGetIntegerv(GL_TEXTURE_BINDING_2D, params: &m_texBinding2D);
84 glGetIntegerv(GL_FRONT_FACE, params: &m_frontFace);
85 m_isCullFaceEnabled = glIsEnabled(GL_CULL_FACE);
86 glGetIntegerv(GL_CULL_FACE_MODE, params: &m_cullFaceMode);
87 glGetIntegerv(GL_BLEND_EQUATION_RGB, params: &m_blendEquationRGB);
88 glGetIntegerv(GL_BLEND_EQUATION_ALPHA, params: &m_blendEquationAlpha);
89 glGetIntegerv(GL_BLEND_DST_ALPHA, params: &m_blendDestAlpha);
90 glGetIntegerv(GL_BLEND_DST_RGB, params: &m_blendDestRGB);
91 glGetIntegerv(GL_BLEND_SRC_ALPHA, params: &m_blendSrcAlpha);
92 glGetIntegerv(GL_BLEND_SRC_RGB, params: &m_blendSrcRGB);
93 glGetIntegerv(GL_SCISSOR_BOX, params: m_scissorBox);
94 m_isScissorTestEnabled = glIsEnabled(GL_SCISSOR_TEST);
95
96 glGetIntegerv(GL_ARRAY_BUFFER_BINDING, params: &m_boundArrayBuffer);
97 glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, params: &m_boundElementArrayBuffer);
98
99 for (int i = 0; i < m_maxVertexAttribs;i++) {
100 glGetVertexAttribiv(index: i, GL_VERTEX_ATTRIB_ARRAY_ENABLED,
101 params: &m_vertexAttribArrayEnabledStates[i]);
102 glGetVertexAttribiv(index: i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING,
103 params: &m_vertexAttribArrayBoundBuffers[i]);
104 glGetVertexAttribiv(index: i, GL_VERTEX_ATTRIB_ARRAY_SIZE, params: &m_vertexAttribArraySizes[i]);
105 glGetVertexAttribiv(index: i, GL_VERTEX_ATTRIB_ARRAY_TYPE, params: &m_vertexAttribArrayTypes[i]);
106 glGetVertexAttribiv(index: i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED,
107 params: &m_vertexAttribArrayNormalized[i]);
108 glGetVertexAttribiv(index: i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, params: &m_vertexAttribArrayStrides[i]);
109 }
110}
111
112#ifdef VERBOSE_STATE_STORE
113void GLStateStore::printCurrentState(bool in)
114{
115 QFile *file;
116 if (in)
117 file = beforeFile;
118 else
119 file = afterFile;
120
121 if (file->isOpen()) {
122 QDebug msg(file);
123#if !QT_CONFIG(opengles2)
124 GLint drawFramebuffer;
125 GLint readFramebuffer;
126 GLint renderbuffer;
127#endif
128 GLfloat clearColor[4];
129 GLfloat clearDepth;
130 GLboolean isBlendingEnabled = glIsEnabled(GL_BLEND);
131 GLboolean isDepthTestEnabled = glIsEnabled(GL_DEPTH_TEST);
132 GLint depthFunc;
133 GLboolean isDepthWriteEnabled;
134 GLint currentProgram;
135 GLint *vertexAttribArrayEnabledStates = new GLint[m_maxVertexAttribs];
136 GLint *vertexAttribArrayBoundBuffers = new GLint[m_maxVertexAttribs];
137 GLint *vertexAttribArraySizes = new GLint[m_maxVertexAttribs];
138 GLint *vertexAttribArrayTypes = new GLint[m_maxVertexAttribs];
139 GLint *vertexAttribArrayNormalized = new GLint[m_maxVertexAttribs];
140 GLint *vertexAttribArrayStrides = new GLint[m_maxVertexAttribs];
141 GLint activeTexture;
142 GLint texBinding2D;
143 GLint arrayBufferBinding;
144 GLint frontFace;
145 GLboolean isCullFaceEnabled = glIsEnabled(GL_CULL_FACE);
146 GLint cullFaceMode;
147 GLint blendEquationRGB;
148 GLint blendEquationAlpha;
149
150 GLint blendDestAlpha;
151 GLint blendDestRGB;
152 GLint blendSrcAlpha;
153 GLint blendSrcRGB;
154 GLint scissorBox[4];
155 GLboolean isScissorTestEnabled = glIsEnabled(GL_SCISSOR_TEST);
156 GLint boundElementArrayBuffer;
157 GLboolean polygonOffsetFillEnabled;
158 GLfloat polygonOffsetFactor;
159 GLfloat polygonOffsetUnits;
160
161 glGetBooleanv(GL_DEPTH_WRITEMASK, &isDepthWriteEnabled);
162#if !QT_CONFIG(opengles2)
163 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &drawFramebuffer);
164 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &readFramebuffer);
165 glGetIntegerv(GL_RENDERBUFFER_BINDING, &renderbuffer);
166#endif
167 glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor);
168 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth);
169 glGetIntegerv(GL_DEPTH_FUNC, &depthFunc);
170 glGetBooleanv(GL_POLYGON_OFFSET_FILL, &polygonOffsetFillEnabled);
171 glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &polygonOffsetFactor);
172 glGetFloatv(GL_POLYGON_OFFSET_UNITS, &polygonOffsetUnits);
173
174 glGetIntegerv(GL_CURRENT_PROGRAM, &currentProgram);
175 glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture);
176 glGetIntegerv(GL_TEXTURE_BINDING_2D, &texBinding2D );
177 glGetIntegerv(GL_FRONT_FACE, &frontFace);
178 glGetIntegerv(GL_CULL_FACE_MODE, &cullFaceMode);
179 glGetIntegerv(GL_BLEND_EQUATION_RGB, &blendEquationRGB);
180 glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &blendEquationAlpha);
181 glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDestAlpha);
182 glGetIntegerv(GL_BLEND_DST_RGB, &blendDestRGB);
183 glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrcAlpha);
184 glGetIntegerv(GL_BLEND_SRC_RGB, &blendSrcRGB);
185 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
186 glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &boundElementArrayBuffer);
187 glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &arrayBufferBinding);
188
189 for (int i = 0; i < m_maxVertexAttribs;i++) {
190 glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED,
191 &vertexAttribArrayEnabledStates[i]);
192 glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING,
193 &vertexAttribArrayBoundBuffers[i]);
194 glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &vertexAttribArraySizes[i]);
195 glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &vertexAttribArrayTypes[i]);
196 glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED,
197 &vertexAttribArrayNormalized[i]);
198 glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &vertexAttribArrayStrides[i]);
199 }
200
201 QColor color;
202 color.setRgbF(clearColor[0], clearColor[1], clearColor[2]);
203 color.setAlphaF(clearColor[3]);
204
205#if !QT_CONFIG(opengles2)
206 msg << "---" << endl;
207 msg << " GL_DRAW_FRAMEBUFFER_BINDING "<< drawFramebuffer << endl;
208 msg << " GL_READ_FRAMEBUFFER_BINDING "<< readFramebuffer << endl;
209 msg << " GL_RENDERBUFFER_BINDING " << renderbuffer << endl;
210#endif
211 msg << " GL_SCISSOR_TEST " << bool(isScissorTestEnabled) << endl;
212 msg << " GL_SCISSOR_BOX " << m_scissorBox[0] << m_scissorBox[1] << m_scissorBox[2]
213 << m_scissorBox[3] << endl;
214 msg << " GL_COLOR_CLEAR_VALUE "<< color << endl;
215 msg << " GL_DEPTH_CLEAR_VALUE "<< clearDepth << endl;
216 msg << " GL_BLEND "<< bool(isBlendingEnabled) << endl;
217 msg << " GL_BLEND_EQUATION_RGB" << m_map->lookUp(blendEquationRGB) << endl;
218 msg << " GL_BLEND_EQUATION_ALPHA" << m_map->lookUp(blendEquationAlpha) << endl;
219 msg << " GL_BLEND_DST_ALPHA" << m_map->lookUp(blendDestAlpha) << endl;
220 msg << " GL_BLEND_DST_RGB" << m_map->lookUp(blendDestRGB) << endl;
221 msg << " GL_BLEND_SRC_ALPHA" << m_map->lookUp(blendSrcAlpha) << endl;
222 msg << " GL_BLEND_SRC_RGB" << m_map->lookUp(blendSrcRGB) << endl;
223 msg << " GL_DEPTH_TEST "<< bool(isDepthTestEnabled) << endl;
224 msg << " GL_DEPTH_WRITEMASK "<< bool(isDepthWriteEnabled) << endl;
225 msg << " GL_POLYGON_OFFSET_FILL" << bool(polygonOffsetFillEnabled) << endl;
226 msg << " GL_POLYGON_OFFSET_FACTOR "<< polygonOffsetFactor << endl;
227 msg << " GL_POLYGON_OFFSET_UNITS "<< polygonOffsetUnits << endl;
228 msg << " GL_CULL_FACE "<< bool(isCullFaceEnabled) << endl;
229 msg << " GL_CULL_FACE_MODE "<< m_map->lookUp(cullFaceMode) << endl;
230 msg << " GL_DEPTH_FUNC "<< m_map->lookUp(depthFunc) << endl;
231 msg << " GL_FRONT_FACE "<< m_map->lookUp(frontFace) << endl;
232 msg << " GL_CURRENT_PROGRAM "<< currentProgram << endl;
233 msg << " GL_ACTIVE_TEXTURE "<< QString("0x%1").arg(activeTexture, 0, 16) << endl;
234 msg << " GL_TEXTURE_BINDING_2D "<< texBinding2D << endl;
235 msg << " GL_ELEMENT_ARRAY_BUFFER_BINDING "<< boundElementArrayBuffer << endl;
236 msg << " GL_ARRAY_BUFFER_BINDING "<< arrayBufferBinding << endl;
237 for (int i = 0; i < m_maxVertexAttribs;i++) {
238 msg << " GL_VERTEX_ATTRIB_ARRAY_ENABLED "<< i << " = "
239 << bool(vertexAttribArrayEnabledStates[i]) << endl;
240 msg << " GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING"<< i << " = "
241 << vertexAttribArrayBoundBuffers[i] << endl;
242 msg << " GL_VERTEX_ATTRIB_ARRAY_SIZE"<< i << " = "
243 << vertexAttribArraySizes[i] << endl;
244 msg << " GL_VERTEX_ATTRIB_ARRAY_TYPE"<< i << " = "
245 << vertexAttribArrayTypes[i] << endl;
246 msg << " GL_VERTEX_ATTRIB_ARRAY_NORMALIZED"<< i << " = "
247 << vertexAttribArrayNormalized[i] << endl;
248 msg << " GL_VERTEX_ATTRIB_ARRAY_STRIDE"<< i << " = "
249 << vertexAttribArrayStrides[i] << endl;
250 }
251 }
252}
253#endif
254
255void GLStateStore::restoreGLState()
256{
257#if !QT_CONFIG(opengles2)
258 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer: m_readFramebuffer);
259 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: m_drawFramebuffer);
260 glBindRenderbuffer(GL_RENDERBUFFER_BINDING, renderbuffer: m_renderbuffer);
261#endif
262
263 if (m_isScissorTestEnabled)
264 glEnable(GL_SCISSOR_TEST);
265 else
266 glDisable(GL_SCISSOR_TEST);
267
268 glScissor(x: m_scissorBox[0], y: m_scissorBox[1], width: m_scissorBox[2], height: m_scissorBox[3]);
269 glClearColor(red: m_clearColor[0], green: m_clearColor[1], blue: m_clearColor[2], alpha: m_clearColor[3]);
270 glClearDepthf(depth: m_clearDepth);
271 if (m_isBlendingEnabled)
272 glEnable(GL_BLEND);
273 else
274 glDisable(GL_BLEND);
275
276 if (m_isDepthTestEnabled)
277 glEnable(GL_DEPTH_TEST);
278 else
279 glDisable(GL_DEPTH_TEST);
280
281 if (m_isCullFaceEnabled)
282 glEnable(GL_CULL_FACE);
283 else
284 glDisable(GL_CULL_FACE);
285
286 glCullFace(mode: m_cullFaceMode);
287
288 glBlendEquationSeparate(modeRGB: m_blendEquationRGB, modeAlpha: m_blendEquationAlpha);
289 glBlendFuncSeparate(srcRGB: m_blendSrcRGB, dstRGB: m_blendDestRGB, srcAlpha: m_blendSrcAlpha, dstAlpha: m_blendDestAlpha);
290
291 glDepthMask(flag: m_isDepthWriteEnabled);
292 glDepthFunc(func: m_depthFunc);
293 glFrontFace(mode: m_frontFace);
294
295 if (m_polygonOffsetFillEnabled)
296 glEnable(GL_POLYGON_OFFSET_FILL);
297 else
298 glDisable(GL_POLYGON_OFFSET_FILL);
299
300 glPolygonOffset(factor: m_polygonOffsetFactor, units: m_polygonOffsetUnits);
301
302 glUseProgram(program: m_currentProgram);
303
304 glActiveTexture(texture: m_activeTexture);
305 glBindTexture(GL_TEXTURE_2D, texture: m_texBinding2D);
306
307 // Restore bound element array buffer and array buffers
308 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer: m_boundElementArrayBuffer);
309 for (int i = 0; i < m_maxVertexAttribs; i++) {
310 if (m_vertexAttribArrayEnabledStates[i])
311 glEnableVertexAttribArray(index: i);
312 else
313 glDisableVertexAttribArray(index: i);
314
315 glBindBuffer(GL_ARRAY_BUFFER, buffer: m_vertexAttribArrayBoundBuffers[i]);
316 glVertexAttribPointer(indx: i, size: m_vertexAttribArraySizes[i],
317 type: m_vertexAttribArrayTypes[i],
318 normalized: m_vertexAttribArrayNormalized[i],
319 stride: m_vertexAttribArrayStrides[i],
320 ptr: m_vertexAttribArrayOffsets[i]);
321 }
322
323 glBindBuffer(GL_ARRAY_BUFFER, buffer: m_boundArrayBuffer);
324
325#ifdef VERBOSE_STATE_STORE
326 printCurrentState(false);
327#endif
328}
329
330void GLStateStore::initGLDefaultState()
331{
332#if !QT_CONFIG(opengles2)
333 m_drawFramebuffer = 0;
334 m_readFramebuffer = 0;
335 m_renderbuffer = 0;
336#endif
337 m_clearColor[0] = m_clearColor[1] = m_clearColor[2] = m_clearColor[3] = 1.0f;
338 m_clearDepth = 1.0f;
339 m_isBlendingEnabled = GL_FALSE;
340 m_isDepthTestEnabled = GL_FALSE;
341 m_depthFunc = GL_LESS;
342 m_isDepthWriteEnabled = GL_TRUE;
343 m_currentProgram = 0;
344 m_texBinding2D = 0;
345 for (int i = 0; i < m_maxVertexAttribs;i++) {
346 m_vertexAttribArrayEnabledStates[i] = GL_FALSE;
347 m_vertexAttribArrayBoundBuffers[i] = 0;
348 m_vertexAttribArraySizes[i] = 4;
349 m_vertexAttribArrayTypes[i] = GL_FLOAT;
350 m_vertexAttribArrayNormalized[i] = GL_FALSE;
351 m_vertexAttribArrayStrides[i] = 0;
352 m_vertexAttribArrayOffsets[i] = 0;
353 }
354 m_activeTexture = GL_TEXTURE0;
355 m_frontFace = GL_CCW;
356 m_isCullFaceEnabled = false;
357 m_cullFaceMode = GL_BACK;
358 m_blendEquationRGB = GL_FUNC_ADD;
359 m_blendEquationAlpha = GL_FUNC_ADD;
360 m_scissorBox[0] = 0;
361 m_scissorBox[1] = 0;
362 m_scissorBox[2] = 0;
363 m_scissorBox[3] = 0;
364 m_isScissorTestEnabled = GL_FALSE;
365
366 m_polygonOffsetFillEnabled = GL_FALSE;
367 m_polygonOffsetFactor = 0.0;
368 m_polygonOffsetUnits = 0.0;
369}
370
371QT_END_NAMESPACE
372

source code of qtdatavis3d/src/datavisualizationqml/glstatestore.cpp