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

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