]> git.cworth.org Git - vogl/blob - src/voglcommon/vogl_general_context_state.cpp
- Adding snapshot/restore support for indeded variants of GL_BLEND
[vogl] / src / voglcommon / vogl_general_context_state.cpp
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26 // File: vogl_geranl_context_state.cpp
27 #include "vogl_common.h"
28 #include "vogl_general_context_state.h"
29 #include "vogl_console.h"
30
31 #include "gl_pname_defs.h"
32
33 // TODO: Indexed versions of glGet's
34 // TODO: Add GL4 types
35 // TODO: pixel maps
36 // TODO: current list mode?
37
38 //#define DEBUG_CHECK_FOR_UNPROCESSED_STATES
39
40 //----------------------------------------------------------------------------------------------------------------------
41 // GL get related tables
42 //----------------------------------------------------------------------------------------------------------------------
43 struct gl_get_def
44 {
45     GLenum m_enum_val;
46     uint m_min_ver;
47     uint m_max_ver;
48     const char *m_pExtension;
49     GLenum m_enum_val_max;
50 };
51
52 static const gl_get_def g_vogl_get_defs[] =
53     {
54 // versions are encoded in bytes: 0xMMmm MM=major mm=minor
55 #define DEFINE_GL_GET(sym, min_ver, max_ver) \
56     {                                        \
57         sym, min_ver, max_ver, NULL, GL_NONE \
58     }                                        \
59     ,
60 #define DEFINE_GL_GET_EXT(sym, min_ver, max_ver, ext) \
61     {                                                 \
62         sym, min_ver, max_ver, ext, GL_NONE           \
63     }                                                 \
64     ,
65 #define DEFINE_GL_INDEXED_GET(sym, min_ver, max_ver, max_sym) \
66     {                                                         \
67         sym, min_ver, max_ver, NULL, max_sym                  \
68     }                                                         \
69     ,
70 #define DEFINE_GL_INDEXED_GET_EXT(sym, min_ver, max_ver, max_sym, ext) \
71     {                                                                  \
72         sym, min_ver, max_ver, ext, max_sym                            \
73     }                                                                  \
74     ,
75 #include "gl_gets.inc"
76 #undef DEFINE_GL_GET
77     };
78
79 #define VOGL_GET_DEF_MAX_SUPPORTED_VERSION VOGL_CREATE_GL_VERSION(4, 3, 0)
80 #define VOGL_GET_DEF_MAX_VERSION VOGL_CREATE_GL_VERSION(9, 9, 0)
81
82 //----------------------------------------------------------------------------------------------------------------------
83 // client active texture and active texture dependent enums
84 // From 2.1 docs:
85 // "When the ARB_multitexture extension is supported, or the GL version is 1.3 or
86 // greater, the following parameters return the associated value for the active
87 // texture unit: GL_CURRENT_RASTER_TEXTURE_COORDS, GL_TEXTURE_1D,
88 // GL_TEXTURE_BINDING_1D, GL_TEXTURE_2D, GL_TEXTURE_BINDING_2D, GL_TEXTURE_3D,
89 // GL_TEXTURE_BINDING_3D, GL_TEXTURE_GEN_S, GL_TEXTURE_GEN_T, GL_TEXTURE_GEN_R,
90 // GL_TEXTURE_GEN_Q, GL_TEXTURE_MATRIX, and GL_TEXTURE_STACK_DEPTH.
91 // Likewise, the following parameters return the associated value for the active
92 // client texture unit:
93 // GL_TEXTURE_COORD_ARRAY, GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING,
94 // GL_TEXTURE_COORD_ARRAY_SIZE, GL_TEXTURE_COORD_ARRAY_STRIDE,
95 // GL_TEXTURE_COORD_ARRAY_TYPE.
96 //----------------------------------------------------------------------------------------------------------------------
97 static const GLenum g_vogl_client_active_texture_dependent_enums[] =
98     {
99         GL_TEXTURE_COORD_ARRAY,
100         GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING,
101         GL_TEXTURE_COORD_ARRAY_SIZE,
102         GL_TEXTURE_COORD_ARRAY_STRIDE,
103         GL_TEXTURE_COORD_ARRAY_TYPE,
104         GL_TEXTURE_COORD_ARRAY_POINTER
105     };
106 //----------------------------------------------------------------------------------------------------------------------
107 static const GLenum g_vogl_active_texture_dependent_enums[] =
108     {
109         // These are limited to the max # of combined texture units
110         GL_TEXTURE_1D,
111         GL_TEXTURE_BINDING_1D,
112         GL_TEXTURE_2D,
113         GL_TEXTURE_BINDING_2D,
114         GL_TEXTURE_3D,
115         GL_TEXTURE_BINDING_3D,
116         GL_TEXTURE_CUBE_MAP,
117         GL_TEXTURE_BINDING_CUBE_MAP,
118         GL_TEXTURE_CUBE_MAP_ARRAY,
119         GL_TEXTURE_BINDING_CUBE_MAP_ARRAY,
120         GL_TEXTURE_RECTANGLE,
121         GL_TEXTURE_BINDING_RECTANGLE,
122         GL_TEXTURE_BUFFER,
123         GL_TEXTURE_BINDING_BUFFER,
124         GL_TEXTURE_1D_ARRAY,
125         GL_TEXTURE_BINDING_1D_ARRAY,
126         GL_TEXTURE_2D_ARRAY,
127         GL_TEXTURE_BINDING_2D_ARRAY,
128         GL_TEXTURE_2D_MULTISAMPLE,
129         GL_TEXTURE_BINDING_2D_MULTISAMPLE,
130         GL_TEXTURE_2D_MULTISAMPLE_ARRAY,
131         GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY,
132         GL_SAMPLER_BINDING, // needed here for the gets, but not the sets
133
134         // These are limited to the max # of texture units
135         GL_CURRENT_RASTER_TEXTURE_COORDS,
136         GL_TEXTURE_GEN_S,
137         GL_TEXTURE_GEN_T,
138         GL_TEXTURE_GEN_R,
139         GL_TEXTURE_GEN_Q,
140         GL_TEXTURE_MATRIX,
141         GL_TRANSPOSE_TEXTURE_MATRIX,
142         GL_CURRENT_TEXTURE_COORDS,
143         GL_TEXTURE_STACK_DEPTH
144     };
145
146 //----------------------------------------------------------------------------------------------------------------------
147 // vogl_gl_enum_is_dependent_on_active_texture
148 //----------------------------------------------------------------------------------------------------------------------
149 bool vogl_gl_enum_is_dependent_on_active_texture(GLenum enum_val)
150 {
151     VOGL_FUNC_TRACER
152
153     return (utils::find_value_in_array(enum_val, g_vogl_active_texture_dependent_enums) >= 0);
154 }
155
156 //----------------------------------------------------------------------------------------------------------------------
157 // vogl_gl_enum_is_dependent_on_client_active_texture
158 //----------------------------------------------------------------------------------------------------------------------
159 bool vogl_gl_enum_is_dependent_on_client_active_texture(GLenum enum_val)
160 {
161     VOGL_FUNC_TRACER
162
163     return (utils::find_value_in_array(enum_val, g_vogl_client_active_texture_dependent_enums) >= 0);
164 }
165
166 //----------------------------------------------------------------------------------------------------------------------
167 // inverse table
168 //----------------------------------------------------------------------------------------------------------------------
169 class gl_get_desc
170 {
171 public:
172     gl_get_desc()
173     {
174         VOGL_FUNC_TRACER
175
176         init();
177     }
178
179     void init()
180     {
181         VOGL_FUNC_TRACER
182
183         for (uint i = 0; i < VOGL_ARRAY_SIZE(g_vogl_get_defs); i++)
184             m_gl_enum_to_get_def_index.insert(g_vogl_get_defs[i].m_enum_val, i);
185     }
186
187     inline uint get_total() const
188     {
189         return VOGL_ARRAY_SIZE(g_vogl_get_defs);
190     }
191
192     inline GLenum get_enum_val(uint index) const
193     {
194         return get_desc(index).m_enum_val;
195     }
196     inline uint get_min_vers(uint index) const
197     {
198         uint packed_ver = get_desc(index).m_min_ver;
199         VOGL_ASSERT(packed_ver <= 0xFF);
200         return VOGL_CREATE_GL_VERSION(packed_ver >> 4, packed_ver & 0xF, 0);
201     }
202     inline uint get_max_vers(uint index) const
203     {
204         uint packed_ver = get_desc(index).m_max_ver;
205         VOGL_ASSERT(packed_ver <= 0xFF);
206         return VOGL_CREATE_GL_VERSION(packed_ver >> 4, packed_ver & 0xF, 0);
207     }
208     inline const char *get_extension(uint index)
209     {
210         return get_desc(index).m_pExtension;
211     }
212     inline uint get_enum_val_max(uint index) const
213     {
214         return get_desc(index).m_enum_val_max;
215     }
216
217     inline int find_gl_enum(GLenum enum_val) const
218     {
219         VOGL_FUNC_TRACER
220
221         if (enum_val > cUINT32_MAX)
222             return vogl::cInvalidIndex;
223
224         gl_enum_to_get_def_index_hash_map::const_iterator it(m_gl_enum_to_get_def_index.find(static_cast<uint>(enum_val)));
225         if (it == m_gl_enum_to_get_def_index.end())
226             return vogl::cInvalidIndex;
227
228         return it->second;
229     }
230
231     inline bool is_gl_enum_indexed_by_client_active_texture(GLenum val) const
232     {
233         VOGL_FUNC_TRACER
234
235         for (uint i = 0; i < VOGL_ARRAY_SIZE(g_vogl_client_active_texture_dependent_enums); i++)
236             if (g_vogl_client_active_texture_dependent_enums[i] == val)
237                 return true;
238         return false;
239     }
240
241 private:
242     typedef vogl::hash_map<GLenum, uint> gl_enum_to_get_def_index_hash_map;
243     gl_enum_to_get_def_index_hash_map m_gl_enum_to_get_def_index;
244
245     const gl_get_def &get_desc(uint index) const
246     {
247         return g_vogl_get_defs[vogl::math::open_range_check<uint>(index, get_total())];
248     }
249 };
250
251 static gl_get_desc g_get_desc;
252
253 //----------------------------------------------------------------------------------------------------------------------
254 // struct snapshot_context_info
255 //----------------------------------------------------------------------------------------------------------------------
256 class vogl_snapshot_context_info
257 {
258 public:
259     vogl_snapshot_context_info()
260     {
261     }
262
263     vogl_snapshot_context_info(const vogl_context_info &context_info)
264     {
265         init(context_info);
266     }
267
268     void init(const vogl_context_info &context_info)
269     {
270         VOGL_FUNC_TRACER
271
272         m_can_use_glGetBooleani_v = (GL_ENTRYPOINT(glGetBooleani_v) != NULL) && (context_info.get_version() >= VOGL_GL_VERSION_3_0);
273         m_can_use_glGetIntegeri_v = (GL_ENTRYPOINT(glGetIntegeri_v) != NULL) && (context_info.get_version() >= VOGL_GL_VERSION_3_0);
274         m_can_use_glGetInteger64v = (GL_ENTRYPOINT(glGetInteger64v) != NULL) && ((context_info.get_version() >= VOGL_GL_VERSION_3_2) || context_info.supports_extension("GL_ARB_sync"));
275         m_can_use_glGetInteger64i_v = (GL_ENTRYPOINT(glGetInteger64i_v) != NULL) && (context_info.get_version() >= VOGL_GL_VERSION_3_2);
276         m_can_use_glGetFloati_v = (GL_ENTRYPOINT(glGetFloati_v) != NULL) && (context_info.get_version() >= VOGL_GL_VERSION_4_1);
277         m_can_use_glGetDoublei_v = (GL_ENTRYPOINT(glGetDoublei_v) != NULL) && ((context_info.get_version() >= VOGL_GL_VERSION_4_3) || context_info.supports_extension("GL_ARB_viewport_array"));
278         m_can_use_glGetPointerv = (GL_ENTRYPOINT(glGetPointerv) != NULL) && !context_info.is_core_profile();
279
280         m_max_texture_units = 0;
281         m_max_texture_coords = 0;
282
283         if (!context_info.is_core_profile())
284         {
285             GL_ENTRYPOINT(glGetIntegerv)(GL_MAX_TEXTURE_UNITS, &m_max_texture_units);
286             GL_ENTRYPOINT(glGetIntegerv)(GL_MAX_TEXTURE_COORDS, &m_max_texture_coords);
287         }
288
289         m_max_combined_texture_coords = 0;
290         GL_ENTRYPOINT(glGetIntegerv)(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &m_max_combined_texture_coords);
291
292         m_max_draw_buffers = 0;
293         if (context_info.get_version() >= VOGL_GL_VERSION_2_0)
294         {
295             GL_ENTRYPOINT(glGetIntegerv)(GL_MAX_DRAW_BUFFERS, &m_max_draw_buffers);
296         }
297
298         m_max_vertex_attribs = 0;
299         GL_ENTRYPOINT(glGetIntegerv)(GL_MAX_VERTEX_ATTRIBS, &m_max_vertex_attribs);
300
301         VOGL_CHECK_GL_ERROR;
302     }
303
304     bool m_can_use_glGetBooleani_v;
305     bool m_can_use_glGetIntegeri_v;
306     bool m_can_use_glGetInteger64v;
307     bool m_can_use_glGetInteger64i_v;
308     bool m_can_use_glGetFloati_v;
309     bool m_can_use_glGetDoublei_v;
310     bool m_can_use_glGetPointerv;
311
312     GLint m_max_texture_units;
313     GLint m_max_texture_coords;
314     GLint m_max_combined_texture_coords;
315     GLint m_max_draw_buffers;
316     GLint m_max_vertex_attribs;
317 };
318
319 //----------------------------------------------------------------------------------------------------------------------
320 // vogl_general_context_state::vogl_general_context_state
321 //----------------------------------------------------------------------------------------------------------------------
322 vogl_general_context_state::vogl_general_context_state()
323     : vogl_state_vector()
324 {
325     VOGL_FUNC_TRACER
326 }
327
328 //----------------------------------------------------------------------------------------------------------------------
329 // vogl_general_context_state::restore_buffer_binding
330 //----------------------------------------------------------------------------------------------------------------------
331 bool vogl_general_context_state::restore_buffer_binding(GLenum binding_enum, GLenum set_enum, vogl_handle_remapper &remapper) const
332 {
333     VOGL_FUNC_TRACER
334
335     uint buffer = 0;
336     if (get(binding_enum, 0, &buffer, 1, false))
337     {
338         buffer = static_cast<uint>(remapper.remap_handle(VOGL_NAMESPACE_BUFFERS, buffer));
339
340         GL_ENTRYPOINT(glBindBuffer)(set_enum, 0);
341         VOGL_CHECK_GL_ERROR;
342
343         GL_ENTRYPOINT(glBindBuffer)(set_enum, buffer);
344         VOGL_CHECK_GL_ERROR;
345
346         return true;
347     }
348
349     return false;
350 }
351
352 //----------------------------------------------------------------------------------------------------------------------
353 // vogl_general_context_state::restore_buffer_binding_range
354 //----------------------------------------------------------------------------------------------------------------------
355 bool vogl_general_context_state::restore_buffer_binding_range(GLenum binding_enum, GLenum start_enum, GLenum size_enum, GLenum set_enum, uint index, bool indexed_variant, vogl_handle_remapper &remapper) const
356 {
357     VOGL_FUNC_TRACER
358
359     uint64_t start, size = 0;
360     uint buffer = 0;
361     if (get(binding_enum, index, &buffer, 1, indexed_variant) &&
362         get(start_enum, index, &start, 1, indexed_variant) &&
363         get(size_enum, index, &size, 1, indexed_variant))
364     {
365         if (buffer)
366         {
367             buffer = static_cast<uint>(remapper.remap_handle(VOGL_NAMESPACE_BUFFERS, buffer));
368
369             if ((!start) && (!size))
370             {
371                 GL_ENTRYPOINT(glBindBufferBase)(set_enum, index, buffer);
372                 VOGL_CHECK_GL_ERROR;
373             }
374             else
375             {
376                 GL_ENTRYPOINT(glBindBufferRange)(set_enum, index, buffer, (GLintptr)start, (GLsizeiptr)size);
377                 VOGL_CHECK_GL_ERROR;
378             }
379         }
380
381         return true;
382     }
383
384     return false;
385 }
386
387 //----------------------------------------------------------------------------------------------------------------------
388 // vogl_general_context_state::can_snapshot_state
389 //----------------------------------------------------------------------------------------------------------------------
390 bool vogl_general_context_state::can_snapshot_state(const vogl_context_info &context_info, vogl_snapshot_context_info &context, uint get_desc_index)
391 {
392     VOGL_FUNC_TRACER
393
394     const GLenum enum_val = g_get_desc.get_enum_val(get_desc_index);
395     const uint min_vers = g_get_desc.get_min_vers(get_desc_index);
396     const uint max_vers = g_get_desc.get_max_vers(get_desc_index);
397     const char *pExtension = g_get_desc.get_extension(get_desc_index);
398     if (pExtension)
399     {
400         if (!context_info.supports_extension(pExtension))
401             return false;
402     }
403
404     VOGL_ASSERT(min_vers >= VOGL_CREATE_GL_VERSION(1, 0, 0));
405     VOGL_ASSERT(min_vers < VOGL_CREATE_GL_VERSION(9, 9, 0));
406     VOGL_ASSERT(max_vers >= VOGL_CREATE_GL_VERSION(1, 0, 0));
407     VOGL_ASSERT(max_vers <= VOGL_CREATE_GL_VERSION(9, 9, 0));
408
409     if (context_info.get_version() < min_vers)
410         return false;
411     else if ((context_info.is_core_profile()) && (max_vers < VOGL_GET_DEF_MAX_VERSION))
412     {
413         if (context_info.get_version() > max_vers)
414             return false;
415     }
416
417     if ((enum_val >= GL_DRAW_BUFFER0) && (enum_val <= GL_DRAW_BUFFER15))
418     {
419         if (enum_val >= static_cast<GLenum>(GL_DRAW_BUFFER0 + context.m_max_draw_buffers))
420             return false;
421     }
422
423     return true;
424 }
425
426 //----------------------------------------------------------------------------------------------------------------------
427 // vogl_general_context_state::snapshot_state
428 //----------------------------------------------------------------------------------------------------------------------
429 bool vogl_general_context_state::snapshot_state(const vogl_context_info &context_info, vogl_snapshot_context_info &context, uint get_desc_index, uint index, bool indexed_variant)
430 {
431     VOGL_FUNC_TRACER
432
433     VOGL_NOTE_UNUSED(context_info);
434
435     const GLenum enum_val = g_get_desc.get_enum_val(get_desc_index);
436
437     const char *pName = g_gl_enums.find_name(enum_val);
438
439     int pname_def_index = g_gl_enums.find_pname_def_index(enum_val);
440     if (pname_def_index < 0)
441     {
442         vogl_warning_printf("Unable to find pname def for GL enum %s\n", pName);
443         return false;
444     }
445
446     const gl_pname_def_t &pname_def = g_gl_pname_defs[pname_def_index];
447
448     VOGL_ASSERT(pname_def.m_gl_enum == enum_val);
449
450     bool has_get = false, has_geti = false;
451     if (pname_def.m_pFuncs[0])
452     {
453         if (!vogl_strcmp(pname_def.m_pFuncs, "glGet"))
454             has_get = true;
455         else if (!vogl_strcmp(pname_def.m_pFuncs, "glGetI"))
456             has_geti = true;
457         else if (!vogl_strcmp(pname_def.m_pFuncs, "glGet,glGetI"))
458         {
459             has_get = true;
460             has_geti = true;
461         }
462         else
463         {
464             console::error("%s: Unrecognized pname func \"%s\" in pname table\n", VOGL_METHOD_NAME, pname_def.m_pFuncs);
465         }
466     }
467
468     if (!has_get && !has_geti)
469     {
470         //printf("! %s\n", pname_def.m_pName);
471         return false;
472     }
473
474     if ((!indexed_variant) && (!has_get))
475     {
476         VOGL_ASSERT_ALWAYS;
477         return false;
478     }
479
480     if ((indexed_variant) && (!has_geti))
481     {
482         VOGL_ASSERT_ALWAYS;
483         return false;
484     }
485
486     vogl_state_data trial_state_data;
487
488     vogl_state_type state_type = static_cast<vogl_state_type>(pname_def.m_type);
489
490     uint n = g_gl_enums.get_pname_count(enum_val);
491     if (!n)
492         return false;
493
494     switch (state_type)
495     {
496         case 'B':
497         {
498             GLboolean *p = trial_state_data.init_and_get_data_ptr<GLboolean>(enum_val, index, n, state_type, indexed_variant);
499             if (indexed_variant)
500             {
501                 GL_ENTRYPOINT(glGetBooleani_v)(enum_val, index, p);
502             }
503             else
504             {
505                 GL_ENTRYPOINT(glGetBooleanv)(enum_val, p);
506             }
507
508             break;
509         }
510         case 'E':
511         {
512             GLenum *p = trial_state_data.init_and_get_data_ptr<GLenum>(enum_val, index, n, state_type, indexed_variant);
513             if (indexed_variant)
514             {
515                 GL_ENTRYPOINT(glGetIntegeri_v)(enum_val, index, reinterpret_cast<GLint *>(p));
516             }
517             else
518             {
519                 GL_ENTRYPOINT(glGetIntegerv)(enum_val, reinterpret_cast<GLint *>(p));
520             }
521
522             if (enum_val == GL_CULL_FACE_MODE)
523             {
524                 switch (*p)
525                 {
526                     case GL_FRONT:
527                     case GL_BACK:
528                     case GL_FRONT_AND_BACK:
529                         break;
530                     default:
531                     {
532                         console::error("%s: GL_CULL_FACE_MODE is 0x%X, which is not valid! Forcing it to GL_BACK.\n", VOGL_METHOD_NAME, *p);
533                         *p = GL_BACK;
534                         break;
535                     }
536                 }
537             }
538
539             break;
540         }
541         case 'I':
542         case 'U':
543         {
544             int32 *p = trial_state_data.init_and_get_data_ptr<int32>(enum_val, index, n, state_type, indexed_variant);
545             VOGL_ASSERT(!p[0]);
546
547             if (indexed_variant)
548             {
549                 GL_ENTRYPOINT(glGetIntegeri_v)(enum_val, index, p);
550             }
551             else
552             {
553                 GL_ENTRYPOINT(glGetIntegerv)(enum_val, p);
554             }
555
556             // Sanity check to find GL_DRAW_INDIRECT_BUFFER_BINDING remapping problem.
557             switch (enum_val)
558             {
559                 case GL_ARRAY_BUFFER_BINDING:
560                 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
561                 case GL_PIXEL_PACK_BUFFER_BINDING:
562                 case GL_PIXEL_UNPACK_BUFFER_BINDING:
563                 case GL_COPY_READ_BUFFER_BINDING:
564                 case GL_COPY_WRITE_BUFFER_BINDING:
565                 case GL_DRAW_INDIRECT_BUFFER_BINDING:
566                 case GL_DISPATCH_INDIRECT_BUFFER_BINDING:
567                 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
568                 case GL_UNIFORM_BUFFER_BINDING:
569                 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
570                 case GL_SHADER_STORAGE_BUFFER_BINDING:
571                 case GL_VERTEX_ARRAY_BUFFER_BINDING:
572                 case GL_COLOR_ARRAY_BUFFER_BINDING:
573                 case GL_INDEX_ARRAY_BUFFER_BINDING:
574                 case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING:
575                 case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
576                 case GL_FOG_COORD_ARRAY_BUFFER_BINDING:
577                 case GL_NORMAL_ARRAY_BUFFER_BINDING:
578                 case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING:
579                 case GL_SAMPLER_BINDING:
580                 case GL_CURRENT_QUERY:
581                 case GL_CURRENT_PROGRAM:
582                 case GL_PROGRAM_PIPELINE_BINDING:
583                 case GL_RENDERBUFFER_BINDING:
584                 case GL_READ_FRAMEBUFFER_BINDING:
585                 case GL_DRAW_FRAMEBUFFER_BINDING:
586                 case GL_VERTEX_ARRAY_BINDING:
587                 case GL_TEXTURE_BINDING_BUFFER:
588                 case GL_TEXTURE_BINDING_RECTANGLE:
589                 case GL_TEXTURE_BINDING_CUBE_MAP_ARRAY:
590                 case GL_TEXTURE_BINDING_CUBE_MAP:
591                 case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
592                 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
593                 case GL_TEXTURE_BINDING_2D_ARRAY:
594                 case GL_TEXTURE_BINDING_1D_ARRAY:
595                 case GL_TEXTURE_BINDING_1D:
596                 case GL_TEXTURE_BINDING_2D:
597                 case GL_TEXTURE_BINDING_3D:
598                 {
599                     int handle = *p;
600                     if (handle < 0)
601                     {
602                         vogl_error_printf("%s: Driver has returned a negative handle (%i) for state %s, slamming it to 0!\n", VOGL_METHOD_NAME, handle, pname_def.m_pName);
603                         *p = 0;
604                     }
605                     else if (handle > 0xFFFF)
606                     {
607                         // We know this pname is unreliable on AMD right now.
608                         if (enum_val == GL_DRAW_INDIRECT_BUFFER_BINDING)
609                         {
610                             vogl_error_printf("%s: Driver has returned a probably bogus handle (%i) for state %s, slamming it to 0!\n", VOGL_METHOD_NAME, handle, pname_def.m_pName);
611                             *p = 0;
612                         }
613                         else
614                         {
615                             vogl_warning_printf("%s: Driver has returned a potentially bogus handle (%i) for state %s!\n", VOGL_METHOD_NAME, handle, pname_def.m_pName);
616                         }
617                     }
618                     break;
619                 }
620                 default:
621                     break;
622             }
623
624             break;
625         }
626         case 'i':
627         case 'u':
628         {
629             if (!context.m_can_use_glGetInteger64v)
630                 return false;
631
632             GLint64 *p = trial_state_data.init_and_get_data_ptr<GLint64>(enum_val, index, n, state_type, indexed_variant);
633             if (indexed_variant)
634             {
635                 GL_ENTRYPOINT(glGetInteger64i_v)(enum_val, index, p);
636             }
637             else
638             {
639                 GL_ENTRYPOINT(glGetInteger64v)(enum_val, p);
640             }
641
642             break;
643         }
644         case 'F':
645         {
646             float *p = trial_state_data.init_and_get_data_ptr<float>(enum_val, index, n, state_type, indexed_variant);
647             if (indexed_variant)
648             {
649                 GL_ENTRYPOINT(glGetFloati_v)(enum_val, index, p);
650             }
651             else
652             {
653                 GL_ENTRYPOINT(glGetFloatv)(enum_val, p);
654             }
655             break;
656         }
657         case 'D':
658         {
659             double *p = trial_state_data.init_and_get_data_ptr<double>(enum_val, index, n, state_type, indexed_variant);
660             if (indexed_variant)
661             {
662                 GL_ENTRYPOINT(glGetDoublei_v)(enum_val, index, p);
663             }
664             else
665             {
666                 GL_ENTRYPOINT(glGetDoublev)(enum_val, p);
667             }
668             break;
669         }
670         case 'P':
671         {
672             if (!context.m_can_use_glGetPointerv)
673                 return false;
674
675             if (indexed_variant)
676             {
677                 // This is a legacy/compat API.
678                 VOGL_ASSERT_ALWAYS;
679
680                 indexed_variant = false;
681             }
682
683             if (n > 16)
684             {
685                 VOGL_ASSERT_ALWAYS;
686                 return false;
687             }
688
689             void *p[17];
690             p[16] = (void *)0xCFCFCFCF;
691
692             GL_ENTRYPOINT(glGetPointerv)(enum_val, p);
693
694             VOGL_ASSERT(p[16] == (void *)0xCFCFCFCF);
695
696             uint64_t *q = trial_state_data.init_and_get_data_ptr<uint64_t>(enum_val, index, n, state_type, indexed_variant);
697             for (uint i = 0; i < n; i++)
698                 q[i] = reinterpret_cast<uint64_t>(p[i]);
699
700             break;
701         }
702         default:
703         {
704             vogl_warning_printf("Unknown pname type for GL enum %s\n", pName);
705             return false;
706         }
707     }
708
709     bool gl_get_failed = vogl_check_gl_error();
710     if (gl_get_failed)
711     {
712         vogl_warning_printf("Failed retrieving GL state for GL enum %s\n", pName);
713         return false;
714     }
715
716     trial_state_data.debug_check();
717
718     if (!insert(trial_state_data))
719         vogl_warning_printf("%s: vogl_state_vector::deserialize: Ignoring duplicate state 0x%X index %u\n", VOGL_METHOD_NAME, trial_state_data.get_enum_val(), trial_state_data.get_index());
720
721     return true;
722 }
723
724 //----------------------------------------------------------------------------------------------------------------------
725 // vogl_general_context_state::snapshot_active_queries
726 //----------------------------------------------------------------------------------------------------------------------
727 static const GLenum g_query_targets[] = { GL_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED, GL_TIME_ELAPSED, GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_PRIMITIVES_GENERATED };
728
729 bool vogl_general_context_state::snapshot_active_queries(const vogl_context_info &context_info)
730 {
731     VOGL_FUNC_TRACER
732
733     if (context_info.get_version() < VOGL_GL_VERSION_2_0)
734         return true;
735
736     //TODO: Add GL4 types
737
738     GLint handle = 0;
739
740     GL_ENTRYPOINT(glGetQueryiv)(GL_SAMPLES_PASSED, GL_CURRENT_QUERY, &handle);
741     VOGL_CHECK_GL_ERROR;
742     if (!insert(vogl_state_data(GL_CURRENT_QUERY, GL_SAMPLES_PASSED, &handle, sizeof(handle), false)))
743         return false;
744
745     if (context_info.supports_extension("GL_ARB_occlusion_query2") || (context_info.get_version() >= VOGL_GL_VERSION_3_3))
746     {
747         handle = 0;
748         GL_ENTRYPOINT(glGetQueryiv)(GL_ANY_SAMPLES_PASSED, GL_CURRENT_QUERY, &handle);
749         VOGL_CHECK_GL_ERROR;
750
751         if (!insert(vogl_state_data(GL_CURRENT_QUERY, GL_ANY_SAMPLES_PASSED, &handle, sizeof(handle), false)))
752             return false;
753     }
754
755     if (context_info.supports_extension("GL_NV_transform_feedback") || (context_info.get_version() >= VOGL_GL_VERSION_3_3))
756     {
757         handle = 0;
758         GL_ENTRYPOINT(glGetQueryiv)(GL_PRIMITIVES_GENERATED, GL_CURRENT_QUERY, &handle);
759         VOGL_CHECK_GL_ERROR;
760
761         if (!insert(vogl_state_data(GL_CURRENT_QUERY, GL_PRIMITIVES_GENERATED, &handle, sizeof(handle), false)))
762             return false;
763
764         handle = 0;
765         GL_ENTRYPOINT(glGetQueryiv)(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_CURRENT_QUERY, &handle);
766         VOGL_CHECK_GL_ERROR;
767
768         if (!insert(vogl_state_data(GL_CURRENT_QUERY, GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, &handle, sizeof(handle), false)))
769             return false;
770     }
771
772     if (context_info.supports_extension("GL_ARB_timer_query") || (context_info.get_version() >= VOGL_GL_VERSION_3_3))
773     {
774         handle = 0;
775         GL_ENTRYPOINT(glGetQueryiv)(GL_TIME_ELAPSED, GL_CURRENT_QUERY, &handle);
776         VOGL_CHECK_GL_ERROR;
777
778         if (!insert(vogl_state_data(GL_CURRENT_QUERY, GL_TIME_ELAPSED, &handle, sizeof(handle), false)))
779             return false;
780     }
781
782     return true;
783 }
784
785 //----------------------------------------------------------------------------------------------------------------------
786 // vogl_general_context_state::snapshot
787 //----------------------------------------------------------------------------------------------------------------------
788 bool vogl_general_context_state::snapshot(const vogl_context_info &context_info)
789 {
790     VOGL_FUNC_TRACER
791
792     VOGL_ASSERT(context_info.is_valid());
793
794     bool prev_gl_error = vogl_check_gl_error();
795     VOGL_ASSERT(!prev_gl_error);
796
797     vogl_snapshot_context_info snapshot_context_info(context_info);
798
799     prev_gl_error = vogl_check_gl_error();
800     VOGL_ASSERT(!prev_gl_error);
801
802     m_states.clear();
803
804     for (uint get_desc_index = 0; get_desc_index < g_get_desc.get_total(); get_desc_index++)
805     {
806         const GLenum enum_val = g_get_desc.get_enum_val(get_desc_index);
807
808         const bool is_dependent_on_client_active_texture = vogl_gl_enum_is_dependent_on_client_active_texture(enum_val);
809         const bool is_dependent_on_active_texture = vogl_gl_enum_is_dependent_on_active_texture(enum_val);
810         if ((is_dependent_on_client_active_texture) || (is_dependent_on_active_texture))
811             continue;
812
813         if (!can_snapshot_state(context_info, snapshot_context_info, get_desc_index))
814             continue;
815
816         GLenum enum_val_max = g_get_desc.get_enum_val_max(get_desc_index);
817         if (enum_val_max == GL_NONE)
818             snapshot_state(context_info, snapshot_context_info, get_desc_index, 0, false);
819         else
820         {
821             uint max_indices = vogl_get_gl_integer(enum_val_max);
822             VOGL_CHECK_GL_ERROR;
823
824             for (uint i = 0; i < max_indices; i++)
825                 snapshot_state(context_info, snapshot_context_info, get_desc_index, i, true);
826         }
827     }
828
829     if (!context_info.is_core_profile())
830     {
831         // client active texture dependent glGet's
832         GLint prev_client_active_texture = 0;
833         GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &prev_client_active_texture);
834
835         prev_gl_error = vogl_check_gl_error();
836         VOGL_ASSERT(!prev_gl_error);
837
838         const uint max_client_texture_coords = snapshot_context_info.m_max_texture_coords;
839         VOGL_ASSERT(max_client_texture_coords);
840
841         for (uint texcoord_index = 0; texcoord_index < max_client_texture_coords; texcoord_index++)
842         {
843             GL_ENTRYPOINT(glClientActiveTexture)(GL_TEXTURE0 + texcoord_index);
844
845             prev_gl_error = vogl_check_gl_error();
846             VOGL_ASSERT(!prev_gl_error);
847
848             for (uint get_desc_index = 0; get_desc_index < g_get_desc.get_total(); get_desc_index++)
849             {
850                 const GLenum enum_val = g_get_desc.get_enum_val(get_desc_index);
851
852                 const bool is_dependent_on_client_active_texture = vogl_gl_enum_is_dependent_on_client_active_texture(enum_val);
853                 if (!is_dependent_on_client_active_texture)
854                     continue;
855
856                 if (can_snapshot_state(context_info, snapshot_context_info, get_desc_index))
857                     snapshot_state(context_info, snapshot_context_info, get_desc_index, texcoord_index, false);
858             }
859         }
860
861         GL_ENTRYPOINT(glClientActiveTexture)(prev_client_active_texture);
862
863         prev_gl_error = vogl_check_gl_error();
864         VOGL_ASSERT(!prev_gl_error);
865     }
866
867     // active texture dependent glGet's
868     GLint prev_active_texture = 0;
869     GL_ENTRYPOINT(glGetIntegerv)(GL_ACTIVE_TEXTURE, &prev_active_texture);
870
871     prev_gl_error = vogl_check_gl_error();
872     VOGL_ASSERT(!prev_gl_error);
873
874     // FIXME: Test on core profiles (that'll be fun)
875     const uint max_texture_coords = math::maximum<uint>(snapshot_context_info.m_max_texture_coords, snapshot_context_info.m_max_combined_texture_coords);
876     VOGL_ASSERT(max_texture_coords);
877
878     for (uint texcoord_index = 0; texcoord_index < max_texture_coords; texcoord_index++)
879     {
880         GL_ENTRYPOINT(glActiveTexture)(GL_TEXTURE0 + texcoord_index);
881
882         prev_gl_error = vogl_check_gl_error();
883         VOGL_ASSERT(!prev_gl_error);
884
885         for (uint get_desc_index = 0; get_desc_index < g_get_desc.get_total(); get_desc_index++)
886         {
887             const GLenum enum_val = g_get_desc.get_enum_val(get_desc_index);
888
889             const bool is_dependent_on_active_texture = vogl_gl_enum_is_dependent_on_active_texture(enum_val);
890             if (!is_dependent_on_active_texture)
891                 continue;
892
893             // skip the stuff that's limited by the max texture coords
894             if ((enum_val == GL_CURRENT_RASTER_TEXTURE_COORDS) ||
895                 (enum_val == GL_CURRENT_TEXTURE_COORDS) ||
896                 (enum_val == GL_TEXTURE_GEN_S) ||
897                 (enum_val == GL_TEXTURE_GEN_T) ||
898                 (enum_val == GL_TEXTURE_GEN_Q) ||
899                 (enum_val == GL_TEXTURE_GEN_R) ||
900                 (enum_val == GL_TEXTURE_MATRIX) ||
901                 (enum_val == GL_TRANSPOSE_TEXTURE_MATRIX) ||
902                 (enum_val == GL_TEXTURE_STACK_DEPTH))
903             {
904                 if (static_cast<int>(texcoord_index) >= snapshot_context_info.m_max_texture_coords)
905                     continue;
906             }
907
908             if (can_snapshot_state(context_info, snapshot_context_info, get_desc_index))
909                 snapshot_state(context_info, snapshot_context_info, get_desc_index, texcoord_index, false);
910         }
911     }
912
913     GL_ENTRYPOINT(glActiveTexture)(prev_active_texture);
914
915     snapshot_active_queries(context_info);
916
917     prev_gl_error = vogl_check_gl_error();
918     VOGL_ASSERT(!prev_gl_error);
919
920     return true;
921 }
922
923 //----------------------------------------------------------------------------------------------------------------------
924 // vogl_state_data::restore
925 // TODO: Holy methods of doom, split this up!
926 //----------------------------------------------------------------------------------------------------------------------
927 bool vogl_general_context_state::restore(const vogl_context_info &context_info, vogl_handle_remapper &remapper, vogl_persistent_restore_state &persistent_state) const
928 {
929     VOGL_FUNC_TRACER
930
931     VOGL_ASSERT(context_info.is_valid());
932
933     VOGL_NOTE_UNUSED(context_info);
934
935 #ifdef DEBUG_CHECK_FOR_UNPROCESSED_STATES
936     vogl::vector<vogl_state_id> processed_states;
937     processed_states.reserve(m_states.size());
938 #define ADD_PROCESSED_STATE(e, i) processed_states.push_back(vogl_state_id(e, i, false));
939 #define ADD_PROCESSED_STATE_INDEXED_VARIANT(e, i) processed_states.push_back(vogl_state_id(e, i, true));
940 #else
941 #define ADD_PROCESSED_STATE(e, i) \
942     do                            \
943     {                             \
944     } while (0)
945 #define ADD_PROCESSED_STATE_INDEXED_VARIANT(e, i) \
946     do                                            \
947     {                                             \
948     } while (0)
949 #endif
950
951     GLint prev_client_active_texture = 0;
952     if (!context_info.is_core_profile())
953     {
954         GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &prev_client_active_texture);
955     }
956
957     GLint prev_active_texture = 0;
958     GL_ENTRYPOINT(glGetIntegerv)(GL_ACTIVE_TEXTURE, &prev_active_texture);
959
960     GLint prev_array_buffer_binding = 0;
961     GL_ENTRYPOINT(glGetIntegerv)(GL_ARRAY_BUFFER_BINDING, &prev_array_buffer_binding);
962
963     VOGL_CHECK_GL_ERROR;
964
965     for (const_iterator it = begin(); it != end(); ++it)
966     {
967         const vogl_state_data &state = it->second;
968
969         const GLenum enum_val = state.get_enum_val();
970         const uint index = state.get_index();
971
972         if (enum_val == GL_CLIENT_ACTIVE_TEXTURE)
973         {
974             prev_client_active_texture = state.get_element<int>(0);
975             ADD_PROCESSED_STATE(enum_val, index);
976             continue;
977         }
978         else if (enum_val == GL_ACTIVE_TEXTURE)
979         {
980             prev_active_texture = state.get_element<int>(0);
981             ADD_PROCESSED_STATE(enum_val, index);
982             continue;
983         }
984         else if (enum_val == GL_ARRAY_BUFFER_BINDING)
985         {
986             prev_array_buffer_binding = state.get_element<uint>(0);
987             prev_array_buffer_binding = static_cast<GLuint>(remapper.remap_handle(VOGL_NAMESPACE_BUFFERS, prev_array_buffer_binding));
988             ADD_PROCESSED_STATE(enum_val, index);
989             continue;
990         }
991         else if (enum_val == GL_SAMPLER_BINDING)
992         {
993             // sampler objects - put this here to avoid the active texture set
994             GLuint sampler_object = state.get_element<GLuint>(0);
995             sampler_object = static_cast<GLuint>(remapper.remap_handle(VOGL_NAMESPACE_SAMPLERS, sampler_object));
996
997             GL_ENTRYPOINT(glBindSampler)(index, sampler_object);
998             VOGL_CHECK_GL_ERROR;
999
1000             ADD_PROCESSED_STATE(enum_val, index);
1001             continue;
1002         }
1003
1004         if (vogl_gl_enum_is_dependent_on_active_texture(enum_val))
1005         {
1006             GL_ENTRYPOINT(glActiveTexture)(GL_TEXTURE0 + index);
1007             VOGL_CHECK_GL_ERROR;
1008
1009             ADD_PROCESSED_STATE(enum_val, index);
1010         }
1011         else if (vogl_gl_enum_is_dependent_on_client_active_texture(enum_val))
1012         {
1013             GL_ENTRYPOINT(glClientActiveTexture)(GL_TEXTURE0 + index);
1014             VOGL_CHECK_GL_ERROR;
1015
1016             ADD_PROCESSED_STATE(enum_val, index);
1017         }
1018
1019         if ((state.get_data_type() == cSTGLboolean) && (state.get_num_elements() == 1))
1020         {
1021             // glEnableClientState/DisableClientState or glEnable/glDisable
1022             GLboolean boolean_val = state.get_element<GLboolean>(0);
1023
1024             switch (enum_val)
1025             {
1026                 case GL_COLOR_ARRAY:
1027                 case GL_EDGE_FLAG_ARRAY:
1028                 case GL_FOG_COORD_ARRAY:
1029                 case GL_INDEX_ARRAY:
1030                 case GL_NORMAL_ARRAY:
1031                 case GL_SECONDARY_COLOR_ARRAY:
1032                 case GL_TEXTURE_COORD_ARRAY:
1033                 case GL_VERTEX_ARRAY:
1034                 {
1035                     if (boolean_val)
1036                         GL_ENTRYPOINT(glEnableClientState)(enum_val);
1037                     else
1038                         GL_ENTRYPOINT(glDisableClientState)(enum_val);
1039                     ADD_PROCESSED_STATE(enum_val, index);
1040                     break;
1041                 }
1042                 case GL_ALPHA_TEST:
1043                 case GL_AUTO_NORMAL:
1044                 case GL_BLEND:
1045                 case GL_CLIP_DISTANCE0: // same as CLIP_PLANE0, etc.
1046                 case GL_CLIP_DISTANCE1:
1047                 case GL_CLIP_DISTANCE2:
1048                 case GL_CLIP_DISTANCE3:
1049                 case GL_CLIP_DISTANCE4:
1050                 case GL_CLIP_DISTANCE5:
1051                 case GL_CLIP_DISTANCE6:
1052                 case GL_CLIP_DISTANCE7:
1053                 case GL_COLOR_LOGIC_OP:
1054                 case GL_COLOR_MATERIAL:
1055                 case GL_COLOR_SUM:
1056                 case GL_COLOR_TABLE:
1057                 case GL_CONVOLUTION_1D:
1058                 case GL_CONVOLUTION_2D:
1059                 case GL_CULL_FACE:
1060                 case GL_DEBUG_OUTPUT:
1061                 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
1062                 case GL_DEPTH_CLAMP:
1063                 case GL_DEPTH_TEST:
1064                 case GL_DITHER:
1065                 case GL_FOG:
1066                 case GL_FRAMEBUFFER_SRGB:
1067                 case GL_HISTOGRAM:
1068                 case GL_INDEX_LOGIC_OP:
1069                 case GL_LIGHT0:
1070                 case GL_LIGHT1:
1071                 case GL_LIGHT2:
1072                 case GL_LIGHT3:
1073                 case GL_LIGHT4:
1074                 case GL_LIGHT5:
1075                 case GL_LIGHT6:
1076                 case GL_LIGHT7:
1077                 case GL_LIGHTING:
1078                 case GL_LINE_SMOOTH:
1079                 case GL_LINE_STIPPLE:
1080                 case GL_MAP1_COLOR_4:
1081                 case GL_MAP1_INDEX:
1082                 case GL_MAP1_NORMAL:
1083                 case GL_MAP1_TEXTURE_COORD_1:
1084                 case GL_MAP1_TEXTURE_COORD_2:
1085                 case GL_MAP1_TEXTURE_COORD_3:
1086                 case GL_MAP1_TEXTURE_COORD_4:
1087                 case GL_MAP1_VERTEX_3:
1088                 case GL_MAP1_VERTEX_4:
1089                 case GL_MAP2_COLOR_4:
1090                 case GL_MAP2_INDEX:
1091                 case GL_MAP2_NORMAL:
1092                 case GL_MAP2_TEXTURE_COORD_1:
1093                 case GL_MAP2_TEXTURE_COORD_2:
1094                 case GL_MAP2_TEXTURE_COORD_3:
1095                 case GL_MAP2_TEXTURE_COORD_4:
1096                 case GL_MAP2_VERTEX_3:
1097                 case GL_MAP2_VERTEX_4:
1098                 case GL_MINMAX:
1099                 case GL_MULTISAMPLE:
1100                 case GL_NORMALIZE:
1101                 case GL_POINT_SMOOTH:
1102                 case GL_POINT_SPRITE:
1103                 case GL_POLYGON_OFFSET_FILL:
1104                 case GL_POLYGON_OFFSET_LINE:
1105                 case GL_POLYGON_OFFSET_POINT:
1106                 case GL_POLYGON_SMOOTH:
1107                 case GL_POLYGON_STIPPLE:
1108                 case GL_POST_COLOR_MATRIX_COLOR_TABLE:
1109                 case GL_POST_CONVOLUTION_COLOR_TABLE:
1110                 case GL_PRIMITIVE_RESTART:
1111                 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
1112                 case GL_PROGRAM_POINT_SIZE: // same as GL_VERTEX_PROGRAM_POINT_SIZE
1113                 case GL_RASTERIZER_DISCARD:
1114                 case GL_RESCALE_NORMAL:
1115                 case GL_SAMPLE_ALPHA_TO_COVERAGE:
1116                 case GL_SAMPLE_ALPHA_TO_ONE:
1117                 case GL_SAMPLE_COVERAGE:
1118                 case GL_SAMPLE_MASK:
1119                 case GL_SAMPLE_SHADING:
1120                 case GL_SCISSOR_TEST:
1121                 case GL_SEPARABLE_2D:
1122                 case GL_STENCIL_TEST:
1123                 case GL_TEXTURE_1D:
1124                 case GL_TEXTURE_2D:
1125                 case GL_TEXTURE_3D:
1126                 case GL_TEXTURE_CUBE_MAP:
1127                 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1128                 case GL_TEXTURE_GEN_Q:
1129                 case GL_TEXTURE_GEN_R:
1130                 case GL_TEXTURE_GEN_S:
1131                 case GL_TEXTURE_GEN_T:
1132                 case GL_VERTEX_PROGRAM_TWO_SIDE:
1133                 case GL_VERTEX_PROGRAM_ARB:
1134                 case GL_FRAGMENT_PROGRAM_ARB:
1135                 {
1136                     if (boolean_val)
1137                         GL_ENTRYPOINT(glEnable)(enum_val);
1138                     else
1139                         GL_ENTRYPOINT(glDisable)(enum_val);
1140                     ADD_PROCESSED_STATE(enum_val, index);
1141                     break;
1142                 }
1143                 case GL_EDGE_FLAG:
1144                 {
1145                     GL_ENTRYPOINT(glEdgeFlag)(boolean_val);
1146                     ADD_PROCESSED_STATE(enum_val, index);
1147                     break;
1148                 }
1149                 case GL_LIGHT_MODEL_LOCAL_VIEWER:
1150                 case GL_LIGHT_MODEL_TWO_SIDE:
1151                 {
1152                     GL_ENTRYPOINT(glLightModeli)(enum_val, boolean_val);
1153                     ADD_PROCESSED_STATE(enum_val, index);
1154                     break;
1155                 }
1156                 case GL_MAP_COLOR:
1157                 case GL_MAP_STENCIL:
1158                 {
1159                     GL_ENTRYPOINT(glPixelTransferi)(enum_val, boolean_val);
1160                     ADD_PROCESSED_STATE(enum_val, index);
1161                     break;
1162                 }
1163                 case GL_PACK_LSB_FIRST:
1164                 case GL_PACK_SWAP_BYTES:
1165                 case GL_UNPACK_LSB_FIRST:
1166                 case GL_UNPACK_SWAP_BYTES:
1167                 {
1168                     GL_ENTRYPOINT(glPixelStorei)(enum_val, boolean_val);
1169                     ADD_PROCESSED_STATE(enum_val, index);
1170                     break;
1171                 }
1172                 case GL_COLOR_WRITEMASK:
1173                 case GL_DEPTH_WRITEMASK:
1174                 case GL_SAMPLE_COVERAGE_INVERT:
1175                 {
1176                     // handled below
1177                     break;
1178                 }
1179                 case GL_INDEX_MODE:
1180                 case GL_RGBA_MODE:
1181                 case GL_DOUBLEBUFFER:
1182                 case GL_STEREO:
1183                 case GL_SHADER_COMPILER:
1184                 {
1185                     // Not a user changable state
1186                     ADD_PROCESSED_STATE(enum_val, index);
1187                     break;
1188                 }
1189                 default:
1190                 {
1191                     vogl_debug_printf("%s: FIXME: Don't know how to hande boolean GLenum 0x%04X %s\n", VOGL_METHOD_NAME, enum_val, g_gl_enums.find_name(enum_val));
1192                     break;
1193                 }
1194             }
1195
1196             VOGL_CHECK_GL_ERROR;
1197         }
1198         else
1199         {
1200             switch (enum_val)
1201             {
1202                 case GL_VERTEX_ARRAY_BUFFER_BINDING:
1203                 case GL_COLOR_ARRAY_BUFFER_BINDING:
1204                 case GL_INDEX_ARRAY_BUFFER_BINDING:
1205                 case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING:
1206                 case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
1207                 case GL_FOG_COORD_ARRAY_BUFFER_BINDING:
1208                 case GL_NORMAL_ARRAY_BUFFER_BINDING:
1209                 case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING:
1210                 {
1211                     // Client side arrays
1212                     // TODO: Unfortunately, all this crap is tied to VAO state, except for client side arrays.
1213
1214                     uint client_side_array_index;
1215                     for (client_side_array_index = 0; client_side_array_index < VOGL_NUM_CLIENT_SIDE_ARRAY_DESCS; client_side_array_index++)
1216                         if (g_vogl_client_side_array_descs[client_side_array_index].m_get_binding == enum_val)
1217                             break;
1218
1219                     VOGL_VERIFY(client_side_array_index < VOGL_NUM_CLIENT_SIDE_ARRAY_DESCS);
1220
1221                     const vogl_client_side_array_desc_t &array_desc = g_vogl_client_side_array_descs[client_side_array_index];
1222
1223                     uint binding = state.get_element<uint>(0);
1224                     binding = static_cast<uint>(remapper.remap_handle(VOGL_NAMESPACE_BUFFERS, binding));
1225
1226                     int size = 0, stride = 0;
1227                     GLenum type = 0;
1228                     void *pPtr = NULL;
1229
1230                     bool success = get(array_desc.m_get_pointer, index, &pPtr);
1231                     if ((success) && (!binding))
1232                     {
1233                         pPtr = reinterpret_cast<void *>(remapper.remap_vertex_array_ptr(static_cast<vogl_client_side_array_desc_id_t>(client_side_array_index), index, reinterpret_cast<vogl_trace_ptr_value>(pPtr)));
1234                         ADD_PROCESSED_STATE(array_desc.m_get_pointer, index);
1235                     }
1236
1237                     if (array_desc.m_get_size)
1238                     {
1239                         if (!get(array_desc.m_get_size, index, &size))
1240                             success = false;
1241                         else
1242                             ADD_PROCESSED_STATE(array_desc.m_get_size, index);
1243                     }
1244
1245                     if (!get(array_desc.m_get_stride, index, &stride))
1246                         success = false;
1247                     else
1248                         ADD_PROCESSED_STATE(array_desc.m_get_stride, index);
1249
1250                     if (array_desc.m_get_type)
1251                     {
1252                         if (!get(array_desc.m_get_type, index, &type))
1253                             success = false;
1254                         else
1255                             ADD_PROCESSED_STATE(array_desc.m_get_type, index);
1256                     }
1257
1258                     if (success)
1259                     {
1260                         GL_ENTRYPOINT(glBindBuffer)(GL_ARRAY_BUFFER, binding);
1261
1262                         switch (enum_val)
1263                         {
1264                             case GL_VERTEX_ARRAY_BUFFER_BINDING:
1265                                 GL_ENTRYPOINT(glVertexPointer)(size, type, stride, pPtr);
1266                                 break;
1267                             case GL_COLOR_ARRAY_BUFFER_BINDING:
1268                                 GL_ENTRYPOINT(glColorPointer)(size, type, stride, pPtr);
1269                                 break;
1270                             case GL_INDEX_ARRAY_BUFFER_BINDING:
1271                                 GL_ENTRYPOINT(glIndexPointer)(type, stride, pPtr);
1272                                 break;
1273                             case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING:
1274                                 GL_ENTRYPOINT(glSecondaryColorPointer)(size, type, stride, pPtr);
1275                                 break;
1276                             case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
1277                                 GL_ENTRYPOINT(glTexCoordPointer)(size, type, stride, pPtr);
1278                                 break;
1279                             case GL_FOG_COORD_ARRAY_BUFFER_BINDING:
1280                                 GL_ENTRYPOINT(glFogCoordPointer)(type, stride, pPtr);
1281                                 break;
1282                             case GL_NORMAL_ARRAY_BUFFER_BINDING:
1283                                 GL_ENTRYPOINT(glNormalPointer)(type, stride, pPtr);
1284                                 break;
1285                             case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING:
1286                                 GL_ENTRYPOINT(glEdgeFlagPointer)(stride, pPtr);
1287                                 break;
1288                         }
1289                     }
1290
1291                     VOGL_CHECK_GL_ERROR;
1292
1293                     ADD_PROCESSED_STATE(enum_val, index);
1294
1295                     break;
1296                 }
1297                 case GL_TEXTURE_BINDING_1D:
1298                 {
1299                     uint binding = state.get_element<uint>(0);
1300                     binding = static_cast<uint>(remapper.remap_handle(VOGL_NAMESPACE_TEXTURES, binding));
1301                     GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_1D, binding);
1302                     VOGL_CHECK_GL_ERROR;
1303                     ADD_PROCESSED_STATE(enum_val, index);
1304                     break;
1305                 }
1306                 case GL_TEXTURE_BINDING_2D:
1307                 {
1308                     uint binding = state.get_element<uint>(0);
1309                     binding = static_cast<uint>(remapper.remap_handle(VOGL_NAMESPACE_TEXTURES, binding));
1310                     GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_2D, binding);
1311                     VOGL_CHECK_GL_ERROR;
1312                     ADD_PROCESSED_STATE(enum_val, index);
1313                     break;
1314                 }
1315                 case GL_TEXTURE_BINDING_3D:
1316                 {
1317                     uint binding = state.get_element<uint>(0);
1318                     binding = static_cast<uint>(remapper.remap_handle(VOGL_NAMESPACE_TEXTURES, binding));
1319                     GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_3D, binding);
1320                     VOGL_CHECK_GL_ERROR;
1321                     ADD_PROCESSED_STATE(enum_val, index);
1322                     break;
1323                 }
1324                 case GL_TEXTURE_BINDING_1D_ARRAY:
1325                 {
1326                     uint binding = state.get_element<uint>(0);
1327                     binding = static_cast<uint>(remapper.remap_handle(VOGL_NAMESPACE_TEXTURES, binding));
1328                     GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_1D_ARRAY, binding);
1329                     VOGL_CHECK_GL_ERROR;
1330                     ADD_PROCESSED_STATE(enum_val, index);
1331                     break;
1332                 }
1333                 case GL_TEXTURE_BINDING_2D_ARRAY:
1334                 {
1335                     uint binding = state.get_element<uint>(0);
1336                     binding = static_cast<uint>(remapper.remap_handle(VOGL_NAMESPACE_TEXTURES, binding));
1337                     GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_2D_ARRAY, binding);
1338                     VOGL_CHECK_GL_ERROR;
1339                     ADD_PROCESSED_STATE(enum_val, index);
1340                     break;
1341                 }
1342                 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
1343                 {
1344                     uint binding = state.get_element<uint>(0);
1345                     binding = static_cast<uint>(remapper.remap_handle(VOGL_NAMESPACE_TEXTURES, binding));
1346                     GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_2D_MULTISAMPLE, binding);
1347                     VOGL_CHECK_GL_ERROR;
1348                     ADD_PROCESSED_STATE(enum_val, index);
1349                     break;
1350                 }
1351                 case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
1352                 {
1353                     uint binding = state.get_element<uint>(0);
1354                     binding = static_cast<uint>(remapper.remap_handle(VOGL_NAMESPACE_TEXTURES, binding));
1355                     GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, binding);
1356                     VOGL_CHECK_GL_ERROR;
1357                     ADD_PROCESSED_STATE(enum_val, index);
1358                     break;
1359                 }
1360                 case GL_TEXTURE_BINDING_CUBE_MAP:
1361                 {
1362                     uint binding = state.get_element<uint>(0);
1363                     binding = static_cast<uint>(remapper.remap_handle(VOGL_NAMESPACE_TEXTURES, binding));
1364                     GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_CUBE_MAP, binding);
1365                     VOGL_CHECK_GL_ERROR;
1366                     ADD_PROCESSED_STATE(enum_val, index);
1367                     break;
1368                 }
1369                 case GL_TEXTURE_BINDING_CUBE_MAP_ARRAY:
1370                 {
1371                     uint binding = state.get_element<uint>(0);
1372                     binding = static_cast<uint>(remapper.remap_handle(VOGL_NAMESPACE_TEXTURES, binding));
1373                     GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_CUBE_MAP_ARRAY, binding);
1374                     VOGL_CHECK_GL_ERROR;
1375                     ADD_PROCESSED_STATE(enum_val, index);
1376                     break;
1377                 }
1378                 case GL_TEXTURE_BINDING_RECTANGLE:
1379                 {
1380                     uint binding = state.get_element<uint>(0);
1381                     binding = static_cast<uint>(remapper.remap_handle(VOGL_NAMESPACE_TEXTURES, binding));
1382                     GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_RECTANGLE, binding);
1383                     VOGL_CHECK_GL_ERROR;
1384                     ADD_PROCESSED_STATE(enum_val, index);
1385                     break;
1386                 }
1387                 case GL_TEXTURE_BINDING_BUFFER:
1388                 {
1389                     uint binding = state.get_element<uint>(0);
1390                     binding = static_cast<uint>(remapper.remap_handle(VOGL_NAMESPACE_TEXTURES, binding));
1391                     GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_BUFFER, binding);
1392                     VOGL_CHECK_GL_ERROR;
1393                     ADD_PROCESSED_STATE(enum_val, index);
1394                     break;
1395                 }
1396             } // switch (enum_val)
1397
1398         } // if (state.m_data_type == cSTGLboolean)
1399
1400     } // state_index
1401
1402     // vao binding
1403     GLuint vao_binding;
1404     if (get(GL_VERTEX_ARRAY_BINDING, 0, &vao_binding))
1405     {
1406         vao_binding = static_cast<uint>(remapper.remap_handle(VOGL_NAMESPACE_VERTEX_ARRAYS, vao_binding));
1407         GL_ENTRYPOINT(glBindVertexArray)(vao_binding);
1408         VOGL_CHECK_GL_ERROR;
1409         ADD_PROCESSED_STATE(GL_VERTEX_ARRAY_BINDING, 0);
1410     }
1411
1412     // blend func separate
1413     GLenum src_rgb, src_alpha;
1414     GLenum dst_rgb, dst_alpha;
1415     if (get(GL_BLEND_SRC_RGB, 0, &src_rgb) && get(GL_BLEND_SRC_ALPHA, 0, &src_alpha) && get(GL_BLEND_DST_RGB, 0, &dst_rgb) && get(GL_BLEND_DST_ALPHA, 0, &dst_alpha))
1416     {
1417         GL_ENTRYPOINT(glBlendFuncSeparate)(src_rgb, dst_rgb, src_alpha, dst_alpha);
1418         VOGL_CHECK_GL_ERROR;
1419         ADD_PROCESSED_STATE(GL_BLEND_SRC, 0);
1420         ADD_PROCESSED_STATE(GL_BLEND_DST, 0);
1421         ADD_PROCESSED_STATE(GL_BLEND_SRC_RGB, 0);
1422         ADD_PROCESSED_STATE(GL_BLEND_SRC_ALPHA, 0);
1423         ADD_PROCESSED_STATE(GL_BLEND_DST_RGB, 0);
1424         ADD_PROCESSED_STATE(GL_BLEND_DST_ALPHA, 0);
1425     }
1426
1427     // blend color
1428     float blend_color[4];
1429     if (get(GL_BLEND_COLOR, 0, blend_color, 4))
1430     {
1431         GL_ENTRYPOINT(glBlendColor)(blend_color[0], blend_color[1], blend_color[2], blend_color[3]);
1432         VOGL_CHECK_GL_ERROR;
1433         ADD_PROCESSED_STATE(GL_BLEND_COLOR, 0);
1434     }
1435
1436     // blend equation separate
1437     GLenum blend_equation_rgb = 0, blend_equation_alpha = 0;
1438     if (get(GL_BLEND_EQUATION_RGB, 0, &blend_equation_rgb) && get(GL_BLEND_EQUATION_ALPHA, 0, &blend_equation_alpha))
1439     {
1440         GL_ENTRYPOINT(glBlendEquationSeparate)(blend_equation_rgb, blend_equation_alpha);
1441         VOGL_CHECK_GL_ERROR;
1442         ADD_PROCESSED_STATE(GL_BLEND_EQUATION_RGB, 0);
1443         ADD_PROCESSED_STATE(GL_BLEND_EQUATION_ALPHA, 0);
1444     }
1445
1446     // clear color
1447     float clear_color[4];
1448     if (get(GL_COLOR_CLEAR_VALUE, 0, clear_color, 4))
1449     {
1450         GL_ENTRYPOINT(glClearColor)(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
1451         VOGL_CHECK_GL_ERROR;
1452         ADD_PROCESSED_STATE(GL_COLOR_CLEAR_VALUE, 0);
1453     }
1454
1455     // logic op
1456     GLenum logic_op_mode;
1457     if (get(GL_LOGIC_OP_MODE, 0, &logic_op_mode))
1458     {
1459         GL_ENTRYPOINT(glLogicOp)(logic_op_mode);
1460         VOGL_CHECK_GL_ERROR;
1461         ADD_PROCESSED_STATE(GL_LOGIC_OP_MODE, 0);
1462     }
1463
1464     // color mask
1465     // TODO: Implement indexed version
1466     bool color_mask[4];
1467     if (get(GL_COLOR_WRITEMASK, 0, color_mask, 4))
1468     {
1469         GL_ENTRYPOINT(glColorMask)(color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
1470         VOGL_CHECK_GL_ERROR;
1471         ADD_PROCESSED_STATE(GL_COLOR_WRITEMASK, 0);
1472     }
1473
1474     // cull face mode
1475     GLenum cull_face_mode;
1476     if (get(GL_CULL_FACE_MODE, 0, &cull_face_mode))
1477     {
1478         GL_ENTRYPOINT(glCullFace)(cull_face_mode);
1479         VOGL_CHECK_GL_ERROR;
1480         ADD_PROCESSED_STATE(GL_CULL_FACE_MODE, 0);
1481     }
1482
1483     // front face
1484     GLenum front_face;
1485     if (get(GL_FRONT_FACE, 0, &front_face))
1486     {
1487         GL_ENTRYPOINT(glFrontFace)(front_face);
1488         VOGL_CHECK_GL_ERROR;
1489         ADD_PROCESSED_STATE(GL_FRONT_FACE, 0);
1490     }
1491
1492     // depth clear value
1493     double depth_clear_val;
1494     if (get(GL_DEPTH_CLEAR_VALUE, 0, &depth_clear_val))
1495     {
1496         GL_ENTRYPOINT(glClearDepth)(depth_clear_val);
1497         VOGL_CHECK_GL_ERROR;
1498         ADD_PROCESSED_STATE(GL_DEPTH_CLEAR_VALUE, 0);
1499     }
1500
1501     // min sample shading
1502     float min_sample_shading;
1503     if (get(GL_MIN_SAMPLE_SHADING_VALUE, 0, &min_sample_shading))
1504     {
1505         GL_ENTRYPOINT(glMinSampleShading)(min_sample_shading);
1506         VOGL_CHECK_GL_ERROR;
1507         ADD_PROCESSED_STATE(GL_MIN_SAMPLE_SHADING_VALUE, 0);
1508     }
1509
1510     // depth func
1511     GLenum depth_func;
1512     if (get(GL_DEPTH_FUNC, 0, &depth_func))
1513     {
1514         GL_ENTRYPOINT(glDepthFunc)(depth_func);
1515         VOGL_CHECK_GL_ERROR;
1516         ADD_PROCESSED_STATE(GL_DEPTH_FUNC, 0);
1517     }
1518
1519     // depth range
1520     double depth_range[2];
1521     if (get(GL_DEPTH_RANGE, 0, depth_range, 2))
1522     {
1523         GL_ENTRYPOINT(glDepthRange)(depth_range[0], depth_range[1]);
1524         VOGL_CHECK_GL_ERROR;
1525         ADD_PROCESSED_STATE(GL_DEPTH_RANGE, 0);
1526     }
1527
1528     // depth mask
1529     bool depth_mask;
1530     if (get(GL_DEPTH_WRITEMASK, 0, &depth_mask))
1531     {
1532         GL_ENTRYPOINT(glDepthMask)(depth_mask != 0);
1533         VOGL_CHECK_GL_ERROR;
1534         ADD_PROCESSED_STATE(GL_DEPTH_WRITEMASK, 0);
1535     }
1536
1537     // draw framebuffer binding
1538     uint draw_framebuffer_binding = 0;
1539     if (get(GL_DRAW_FRAMEBUFFER_BINDING, 0, &draw_framebuffer_binding))
1540     {
1541         draw_framebuffer_binding = static_cast<uint>(remapper.remap_handle(VOGL_NAMESPACE_FRAMEBUFFERS, draw_framebuffer_binding));
1542
1543         GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, draw_framebuffer_binding);
1544         VOGL_CHECK_GL_ERROR;
1545         ADD_PROCESSED_STATE(GL_DRAW_FRAMEBUFFER_BINDING, 0);
1546     }
1547
1548     // read framebuffer binding
1549     uint read_framebuffer_binding = 0;
1550     if (get(GL_READ_FRAMEBUFFER_BINDING, 0, &read_framebuffer_binding))
1551     {
1552         read_framebuffer_binding = static_cast<uint>(remapper.remap_handle(VOGL_NAMESPACE_FRAMEBUFFERS, read_framebuffer_binding));
1553
1554         GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, read_framebuffer_binding);
1555         VOGL_CHECK_GL_ERROR;
1556         ADD_PROCESSED_STATE(GL_READ_FRAMEBUFFER_BINDING, 0);
1557     }
1558
1559     // draw buffer
1560     GLenum draw_buffer;
1561     if (get(GL_DRAW_BUFFER, 0, &draw_buffer))
1562     {
1563         GL_ENTRYPOINT(glDrawBuffer)(draw_buffer);
1564         VOGL_CHECK_GL_ERROR;
1565         ADD_PROCESSED_STATE(GL_DRAW_BUFFER, 0);
1566     }
1567
1568     // draw buffers
1569     const uint MAX_DRAW_BUFFERS = 16;
1570
1571     GLenum draw_buffers[MAX_DRAW_BUFFERS];
1572     utils::zero_object(draw_buffers);
1573
1574     uint draw_buffer_index;
1575     for (draw_buffer_index = 0; draw_buffer_index < MAX_DRAW_BUFFERS; draw_buffer_index++)
1576     {
1577         if (!get(GL_DRAW_BUFFER0 + draw_buffer_index, 0, &draw_buffers[draw_buffer_index]))
1578             break;
1579
1580         ADD_PROCESSED_STATE(GL_DRAW_BUFFER0 + draw_buffer_index, 0);
1581     }
1582
1583     if (draw_buffer_index)
1584     {
1585         int num_actual_draw_buffers;
1586         for (num_actual_draw_buffers = MAX_DRAW_BUFFERS - 1; num_actual_draw_buffers >= 0; num_actual_draw_buffers--)
1587             if (draw_buffers[num_actual_draw_buffers])
1588                 break;
1589
1590         VOGL_ASSERT(num_actual_draw_buffers >= 0);
1591         num_actual_draw_buffers++;
1592
1593         if (num_actual_draw_buffers == 1)
1594         {
1595             GL_ENTRYPOINT(glDrawBuffer)(draw_buffers[0]);
1596             VOGL_CHECK_GL_ERROR;
1597         }
1598         else
1599         {
1600             for (int i = 0; i < num_actual_draw_buffers; i++)
1601             {
1602                 VOGL_ASSERT((utils::is_not_in_set<GLenum, GLenum>(draw_buffers[i], GL_FRONT, GL_BACK, GL_LEFT, GL_RIGHT, GL_FRONT_AND_BACK)));
1603             }
1604
1605             GL_ENTRYPOINT(glDrawBuffers)(num_actual_draw_buffers, draw_buffers);
1606             VOGL_CHECK_GL_ERROR;
1607         }
1608     }
1609
1610     // read buffer
1611     GLenum read_buffer = 0;
1612     if (get(GL_READ_BUFFER, 0, &read_buffer))
1613     {
1614         GL_ENTRYPOINT(glReadBuffer)(read_buffer);
1615         VOGL_CHECK_GL_ERROR;
1616         ADD_PROCESSED_STATE(GL_READ_BUFFER, 0);
1617     }
1618
1619     // renderbuffer binding
1620     uint renderbuffer_binding = 0;
1621     if (get(GL_RENDERBUFFER_BINDING, 0, &renderbuffer_binding))
1622     {
1623         renderbuffer_binding = static_cast<uint>(remapper.remap_handle(VOGL_NAMESPACE_RENDER_BUFFERS, renderbuffer_binding));
1624
1625         GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, renderbuffer_binding);
1626         VOGL_CHECK_GL_ERROR;
1627         ADD_PROCESSED_STATE(GL_RENDERBUFFER_BINDING, 0);
1628     }
1629
1630     // line width
1631     float line_width;
1632     if (get(GL_LINE_WIDTH, 0, &line_width))
1633     {
1634         GL_ENTRYPOINT(glLineWidth)(line_width);
1635         VOGL_CHECK_GL_ERROR;
1636         ADD_PROCESSED_STATE(GL_LINE_WIDTH, 0);
1637     }
1638
1639     // point fade threshold
1640     float point_fade_threshold_size;
1641     if (get(GL_POINT_FADE_THRESHOLD_SIZE, 0, &point_fade_threshold_size))
1642     {
1643         GL_ENTRYPOINT(glPointParameterf)(GL_POINT_FADE_THRESHOLD_SIZE, point_fade_threshold_size);
1644         VOGL_CHECK_GL_ERROR;
1645         ADD_PROCESSED_STATE(GL_POINT_FADE_THRESHOLD_SIZE, 0);
1646     }
1647
1648     // point dist atten
1649     float point_distance_atten[3];
1650     if (get(GL_POINT_DISTANCE_ATTENUATION, 0, point_distance_atten, 3))
1651     {
1652         GL_ENTRYPOINT(glPointParameterfv)(GL_POINT_DISTANCE_ATTENUATION, point_distance_atten);
1653         VOGL_CHECK_GL_ERROR;
1654         ADD_PROCESSED_STATE(GL_POINT_DISTANCE_ATTENUATION, 0);
1655     }
1656
1657     // point sprite coord origin
1658     GLenum point_sprite_coord_origin = 0;
1659     if (get(GL_POINT_SPRITE_COORD_ORIGIN, 0, &point_sprite_coord_origin))
1660     {
1661         GL_ENTRYPOINT(glPointParameteri)(GL_POINT_SPRITE_COORD_ORIGIN, point_sprite_coord_origin);
1662         VOGL_CHECK_GL_ERROR;
1663         ADD_PROCESSED_STATE(GL_POINT_SPRITE_COORD_ORIGIN, 0);
1664     }
1665
1666     // point size min
1667     float point_size_min;
1668     if (get(GL_POINT_SIZE_MIN, 0, &point_size_min))
1669     {
1670         GL_ENTRYPOINT(glPointParameterf)(GL_POINT_SIZE_MIN, point_size_min);
1671         VOGL_CHECK_GL_ERROR;
1672         ADD_PROCESSED_STATE(GL_POINT_SIZE_MIN, 0);
1673     }
1674
1675     // point size max
1676     float point_size_max;
1677     if (get(GL_POINT_SIZE_MAX, 0, &point_size_max))
1678     {
1679         GL_ENTRYPOINT(glPointParameterf)(GL_POINT_SIZE_MAX, point_size_max);
1680         VOGL_CHECK_GL_ERROR;
1681         ADD_PROCESSED_STATE(GL_POINT_SIZE_MAX, 0);
1682     }
1683
1684     // provoking vertex
1685     GLenum provoking_vertex = 0;
1686     if (get(GL_PROVOKING_VERTEX, 0, &provoking_vertex))
1687     {
1688         GL_ENTRYPOINT(glProvokingVertex)(provoking_vertex);
1689         VOGL_CHECK_GL_ERROR;
1690         ADD_PROCESSED_STATE(GL_PROVOKING_VERTEX, 0);
1691     }
1692
1693     // point size
1694     float point_size;
1695     if (get(GL_POINT_SIZE, 0, &point_size))
1696     {
1697         GL_ENTRYPOINT(glPointSize)(point_size);
1698         VOGL_CHECK_GL_ERROR;
1699         ADD_PROCESSED_STATE(GL_POINT_SIZE, 0);
1700     }
1701
1702     // polygon offset
1703     float polygon_offset_factor, polygon_offset_units;
1704     if (get(GL_POLYGON_OFFSET_FACTOR, 0, &polygon_offset_factor) && get(GL_POLYGON_OFFSET_UNITS, 0, &polygon_offset_units))
1705     {
1706         GL_ENTRYPOINT(glPolygonOffset)(polygon_offset_factor, polygon_offset_units);
1707         VOGL_CHECK_GL_ERROR;
1708         ADD_PROCESSED_STATE(GL_POLYGON_OFFSET_FACTOR, 0);
1709         ADD_PROCESSED_STATE(GL_POLYGON_OFFSET_UNITS, 0);
1710     }
1711
1712     // polygon mode
1713     GLenum polygon_mode[2] = { 0, 0 };
1714     if (get(GL_POLYGON_MODE, 0, polygon_mode, 2))
1715     {
1716         GL_ENTRYPOINT(glPolygonMode)(GL_FRONT, polygon_mode[0]);
1717         GL_ENTRYPOINT(glPolygonMode)(GL_BACK, polygon_mode[1]);
1718         VOGL_CHECK_GL_ERROR;
1719         ADD_PROCESSED_STATE(GL_POLYGON_MODE, 0);
1720     }
1721
1722     // sample coverage
1723     float sample_coverage;
1724     bool sample_invert;
1725     if (get(GL_SAMPLE_COVERAGE_VALUE, 0, &sample_coverage) && get(GL_SAMPLE_COVERAGE_INVERT, 0, &sample_invert))
1726     {
1727         GL_ENTRYPOINT(glSampleCoverage)(sample_coverage, sample_invert);
1728         VOGL_CHECK_GL_ERROR;
1729         ADD_PROCESSED_STATE(GL_SAMPLE_COVERAGE_VALUE, 0);
1730         ADD_PROCESSED_STATE(GL_SAMPLE_COVERAGE_INVERT, 0);
1731     }
1732
1733     // viewport
1734     int viewport[4] = { 0, 0, 0, 0 };
1735     if (get(GL_VIEWPORT, 0, viewport, 4))
1736     {
1737         GL_ENTRYPOINT(glViewport)(viewport[0], viewport[1], viewport[2], viewport[3]);
1738         VOGL_CHECK_GL_ERROR;
1739         ADD_PROCESSED_STATE(GL_VIEWPORT, 0);
1740     }
1741
1742     // scissor
1743     int scissor[4] = { 0, 0, 0, 0 };
1744     if (get(GL_SCISSOR_BOX, 0, scissor, 4))
1745     {
1746         GL_ENTRYPOINT(glScissor)(scissor[0], scissor[1], scissor[2], scissor[3]);
1747         VOGL_CHECK_GL_ERROR;
1748         ADD_PROCESSED_STATE(GL_SCISSOR_BOX, 0);
1749     }
1750
1751     // stencil op separate
1752     GLenum stencil_fail = 0, stencil_dp_pass = 0, stencil_dp_fail = 0;
1753     if (get(GL_STENCIL_FAIL, 0, &stencil_fail) && get(GL_STENCIL_PASS_DEPTH_PASS, 0, &stencil_dp_pass) && get(GL_STENCIL_PASS_DEPTH_FAIL, 0, &stencil_dp_fail))
1754     {
1755         GL_ENTRYPOINT(glStencilOpSeparate)(GL_FRONT, stencil_fail, stencil_dp_fail, stencil_dp_pass);
1756         VOGL_CHECK_GL_ERROR;
1757         ADD_PROCESSED_STATE(GL_STENCIL_FAIL, 0);
1758         ADD_PROCESSED_STATE(GL_STENCIL_PASS_DEPTH_PASS, 0);
1759         ADD_PROCESSED_STATE(GL_STENCIL_PASS_DEPTH_FAIL, 0);
1760     }
1761
1762     if (get(GL_STENCIL_BACK_FAIL, 0, &stencil_fail) && get(GL_STENCIL_BACK_PASS_DEPTH_PASS, 0, &stencil_dp_pass) && get(GL_STENCIL_BACK_PASS_DEPTH_FAIL, 0, &stencil_dp_fail))
1763     {
1764         GL_ENTRYPOINT(glStencilOpSeparate)(GL_BACK, stencil_fail, stencil_dp_fail, stencil_dp_pass);
1765         VOGL_CHECK_GL_ERROR;
1766         ADD_PROCESSED_STATE(GL_STENCIL_BACK_FAIL, 0);
1767         ADD_PROCESSED_STATE(GL_STENCIL_BACK_PASS_DEPTH_PASS, 0);
1768         ADD_PROCESSED_STATE(GL_STENCIL_BACK_PASS_DEPTH_FAIL, 0);
1769     }
1770
1771     // stencil func separate
1772     GLenum stencil_func = 0;
1773     GLint stencil_ref = 0;
1774     GLuint stencil_mask = 0;
1775
1776     if (get(GL_STENCIL_FUNC, 0, &stencil_func) && get(GL_STENCIL_REF, 0, &stencil_ref) && get(GL_STENCIL_VALUE_MASK, 0, &stencil_mask))
1777     {
1778         GL_ENTRYPOINT(glStencilFuncSeparate)(GL_FRONT, stencil_func, stencil_ref, stencil_mask);
1779         VOGL_CHECK_GL_ERROR;
1780         ADD_PROCESSED_STATE(GL_STENCIL_FUNC, 0);
1781         ADD_PROCESSED_STATE(GL_STENCIL_REF, 0);
1782         ADD_PROCESSED_STATE(GL_STENCIL_VALUE_MASK, 0);
1783     }
1784
1785     if (get(GL_STENCIL_BACK_FUNC, 0, &stencil_func) && get(GL_STENCIL_BACK_REF, 0, &stencil_ref) && get(GL_STENCIL_BACK_VALUE_MASK, 0, &stencil_mask))
1786     {
1787         GL_ENTRYPOINT(glStencilFuncSeparate)(GL_BACK, stencil_func, stencil_ref, stencil_mask);
1788         VOGL_CHECK_GL_ERROR;
1789         ADD_PROCESSED_STATE(GL_STENCIL_BACK_FUNC, 0);
1790         ADD_PROCESSED_STATE(GL_STENCIL_BACK_REF, 0);
1791         ADD_PROCESSED_STATE(GL_STENCIL_BACK_VALUE_MASK, 0);
1792     }
1793
1794     // stencil writemask separate
1795     GLuint stencil_writemask = 0;
1796     if (get(GL_STENCIL_WRITEMASK, 0, &stencil_writemask))
1797     {
1798         GL_ENTRYPOINT(glStencilMaskSeparate)(GL_FRONT, stencil_writemask);
1799         VOGL_CHECK_GL_ERROR;
1800         ADD_PROCESSED_STATE(GL_STENCIL_WRITEMASK, 0);
1801     }
1802
1803     if (get(GL_STENCIL_BACK_WRITEMASK, 0, &stencil_writemask))
1804     {
1805         GL_ENTRYPOINT(glStencilMaskSeparate)(GL_BACK, stencil_writemask);
1806         VOGL_CHECK_GL_ERROR;
1807         ADD_PROCESSED_STATE(GL_STENCIL_BACK_WRITEMASK, 0);
1808     }
1809
1810     GLenum color_material_face, color_material_parameter;
1811     if (get(GL_COLOR_MATERIAL_FACE, 0, &color_material_face) && get(GL_COLOR_MATERIAL_PARAMETER, 0, &color_material_parameter))
1812     {
1813         GL_ENTRYPOINT(glColorMaterial)(color_material_face, color_material_parameter);
1814         VOGL_CHECK_GL_ERROR;
1815         ADD_PROCESSED_STATE(GL_COLOR_MATERIAL_FACE, 0);
1816         ADD_PROCESSED_STATE(GL_COLOR_MATERIAL_PARAMETER, 0);
1817     }
1818
1819     // buffer bindings
1820     restore_buffer_binding(GL_COPY_READ_BUFFER_BINDING, GL_COPY_READ_BUFFER, remapper);
1821     ADD_PROCESSED_STATE(GL_COPY_READ_BUFFER_BINDING, 0);
1822
1823     restore_buffer_binding(GL_COPY_WRITE_BUFFER_BINDING, GL_COPY_WRITE_BUFFER, remapper);
1824     ADD_PROCESSED_STATE(GL_COPY_WRITE_BUFFER_BINDING, 0);
1825
1826     restore_buffer_binding(GL_DRAW_INDIRECT_BUFFER_BINDING, GL_DRAW_INDIRECT_BUFFER, remapper);
1827     ADD_PROCESSED_STATE(GL_DRAW_INDIRECT_BUFFER_BINDING, 0);
1828
1829     restore_buffer_binding(GL_DISPATCH_INDIRECT_BUFFER_BINDING, GL_DISPATCH_INDIRECT_BUFFER, remapper);
1830     ADD_PROCESSED_STATE(GL_DISPATCH_INDIRECT_BUFFER_BINDING, 0);
1831
1832     restore_buffer_binding(GL_PIXEL_PACK_BUFFER_BINDING, GL_PIXEL_PACK_BUFFER, remapper);
1833     ADD_PROCESSED_STATE(GL_PIXEL_PACK_BUFFER_BINDING, 0);
1834
1835     restore_buffer_binding(GL_PIXEL_UNPACK_BUFFER_BINDING, GL_PIXEL_UNPACK_BUFFER, remapper);
1836     ADD_PROCESSED_STATE(GL_PIXEL_UNPACK_BUFFER_BINDING, 0);
1837
1838     restore_buffer_binding(GL_ELEMENT_ARRAY_BUFFER_BINDING, GL_ELEMENT_ARRAY_BUFFER, remapper);
1839     ADD_PROCESSED_STATE(GL_ELEMENT_ARRAY_BUFFER_BINDING, 0);
1840
1841     // restore transform feedback targets
1842     for (uint i = 0; i < context_info.get_max_transform_feedback_separate_attribs(); i++)
1843     {
1844         restore_buffer_binding_range(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_TRANSFORM_FEEDBACK_BUFFER_START, GL_TRANSFORM_FEEDBACK_BUFFER_SIZE, GL_TRANSFORM_FEEDBACK_BUFFER, i, true, remapper);
1845         ADD_PROCESSED_STATE_INDEXED_VARIANT(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, i);
1846         ADD_PROCESSED_STATE_INDEXED_VARIANT(GL_TRANSFORM_FEEDBACK_BUFFER_START, i);
1847         ADD_PROCESSED_STATE_INDEXED_VARIANT(GL_TRANSFORM_FEEDBACK_BUFFER_SIZE, i);
1848     }
1849
1850     restore_buffer_binding(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_TRANSFORM_FEEDBACK_BUFFER, remapper);
1851     ADD_PROCESSED_STATE(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, 0);
1852
1853     // restore uniform buffer binding target, and the indexed variants
1854     for (uint i = 0; i < context_info.get_max_uniform_buffer_bindings(); i++)
1855     {
1856         restore_buffer_binding_range(GL_UNIFORM_BUFFER_BINDING, GL_UNIFORM_BUFFER_START, GL_UNIFORM_BUFFER_SIZE, GL_UNIFORM_BUFFER, i, true, remapper);
1857         ADD_PROCESSED_STATE_INDEXED_VARIANT(GL_UNIFORM_BUFFER_BINDING, i);
1858         ADD_PROCESSED_STATE_INDEXED_VARIANT(GL_UNIFORM_BUFFER_START, i);
1859         ADD_PROCESSED_STATE_INDEXED_VARIANT(GL_UNIFORM_BUFFER_SIZE, i);
1860     }
1861
1862     restore_buffer_binding(GL_UNIFORM_BUFFER_BINDING, GL_UNIFORM_BUFFER, remapper);
1863     ADD_PROCESSED_STATE(GL_UNIFORM_BUFFER_BINDING, 0);
1864
1865     // Restore indexed blending state (we've already restored the global state, which sets all the indexed states)
1866     for (uint i = 0; i < context_info.get_max_draw_buffers(); i++)
1867     {
1868         GLint enabled = 0;
1869         if (get(GL_BLEND, i, &enabled, 1, true))
1870         {
1871             if (enabled)
1872             {
1873                 GL_ENTRYPOINT(glEnablei)(GL_BLEND, i);
1874                 VOGL_CHECK_GL_ERROR;
1875             }
1876             else
1877             {
1878                 GL_ENTRYPOINT(glDisablei)(GL_BLEND, i);
1879                 VOGL_CHECK_GL_ERROR;
1880             }
1881         }
1882     }
1883
1884     // TODO: these GL4 guys have indexed and offset/size variants
1885     restore_buffer_binding(GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_ATOMIC_COUNTER_BUFFER, remapper);
1886     ADD_PROCESSED_STATE(GL_ATOMIC_COUNTER_BUFFER_BINDING, 0);
1887
1888     restore_buffer_binding(GL_SHADER_STORAGE_BUFFER_BINDING, GL_SHADER_STORAGE_BUFFER, remapper);
1889     ADD_PROCESSED_STATE(GL_SHADER_STORAGE_BUFFER_BINDING, 0);
1890
1891     // pixel transfer settings
1892     static const GLenum s_pixel_transfer_pnames[] =
1893         {
1894             GL_INDEX_SHIFT, GL_INDEX_OFFSET, GL_RED_SCALE, GL_GREEN_SCALE, GL_BLUE_SCALE, GL_ALPHA_SCALE, GL_DEPTH_SCALE,
1895             GL_RED_BIAS, GL_GREEN_BIAS, GL_BLUE_BIAS, GL_ALPHA_BIAS, GL_DEPTH_BIAS, GL_POST_COLOR_MATRIX_RED_SCALE,
1896             GL_POST_COLOR_MATRIX_GREEN_SCALE, GL_POST_COLOR_MATRIX_BLUE_SCALE, GL_POST_COLOR_MATRIX_ALPHA_SCALE,
1897             GL_POST_COLOR_MATRIX_RED_BIAS, GL_POST_COLOR_MATRIX_GREEN_BIAS, GL_POST_COLOR_MATRIX_BLUE_BIAS,
1898             GL_POST_COLOR_MATRIX_ALPHA_BIAS, GL_POST_CONVOLUTION_RED_SCALE, GL_POST_CONVOLUTION_GREEN_SCALE,
1899             GL_POST_CONVOLUTION_BLUE_SCALE, GL_POST_CONVOLUTION_ALPHA_SCALE, GL_POST_CONVOLUTION_RED_BIAS,
1900             GL_POST_CONVOLUTION_GREEN_BIAS, GL_POST_CONVOLUTION_BLUE_BIAS, GL_POST_CONVOLUTION_ALPHA_BIAS
1901         };
1902
1903     for (uint i = 0; i < VOGL_ARRAY_SIZE(s_pixel_transfer_pnames); i++)
1904     {
1905         GLenum enum_val = s_pixel_transfer_pnames[i];
1906
1907         int pname_def_index = g_gl_enums.find_pname_def_index(enum_val);
1908         if (pname_def_index < 0)
1909         {
1910             vogl_warning_printf("Unable to find pname def for GL enum %s\n", g_gl_enums.find_name(enum_val));
1911             continue;
1912         }
1913
1914         const gl_pname_def_t &pname_def = g_gl_pname_defs[pname_def_index];
1915
1916         VOGL_VERIFY(pname_def.m_count == 1);
1917
1918         if (pname_def.m_type == cSTInt32)
1919         {
1920             int val;
1921             if (get(enum_val, 0, &val))
1922             {
1923                 GL_ENTRYPOINT(glPixelTransferi)(enum_val, val);
1924                 VOGL_CHECK_GL_ERROR;
1925                 ADD_PROCESSED_STATE(enum_val, 0);
1926             }
1927         }
1928         else if (pname_def.m_type == cSTFloat)
1929         {
1930             float val;
1931             if (get(enum_val, 0, &val))
1932             {
1933                 GL_ENTRYPOINT(glPixelTransferf)(enum_val, val);
1934                 VOGL_CHECK_GL_ERROR;
1935                 ADD_PROCESSED_STATE(enum_val, 0);
1936             }
1937         }
1938         else
1939         {
1940             VOGL_VERIFY(0);
1941         }
1942     }
1943
1944     // fog states
1945     static const GLenum s_fog_pnames[] = { GL_FOG_MODE, GL_FOG_DENSITY, GL_FOG_START, GL_FOG_END, GL_FOG_INDEX, GL_FOG_COLOR, GL_FOG_COORD_SRC };
1946
1947     for (uint i = 0; i < VOGL_ARRAY_SIZE(s_fog_pnames); i++)
1948     {
1949         GLenum enum_val = s_fog_pnames[i];
1950
1951         int pname_def_index = g_gl_enums.find_pname_def_index(enum_val);
1952         if (pname_def_index < 0)
1953         {
1954             vogl_warning_printf("Unable to find pname def for GL enum %s\n", g_gl_enums.find_name(enum_val));
1955             continue;
1956         }
1957
1958         const gl_pname_def_t &pname_def = g_gl_pname_defs[pname_def_index];
1959
1960         switch (pname_def.m_type)
1961         {
1962             case cSTFloat:
1963             {
1964                 VOGL_ASSERT(pname_def.m_count <= 4);
1965                 float v[4];
1966                 if (get(enum_val, 0, v, 4))
1967                 {
1968                     if (pname_def.m_count > 1)
1969                         GL_ENTRYPOINT(glFogfv)(enum_val, v);
1970                     else
1971                         GL_ENTRYPOINT(glFogf)(enum_val, v[0]);
1972                     VOGL_CHECK_GL_ERROR;
1973                     ADD_PROCESSED_STATE(enum_val, 0);
1974                 }
1975                 break;
1976             }
1977             case cSTInt32:
1978             {
1979                 VOGL_VERIFY(pname_def.m_count == 1);
1980                 int v;
1981                 if (get(enum_val, 0, &v))
1982                 {
1983                     GL_ENTRYPOINT(glFogi)(enum_val, v);
1984                     VOGL_CHECK_GL_ERROR;
1985                     ADD_PROCESSED_STATE(enum_val, 0);
1986                 }
1987                 break;
1988             }
1989             case cSTGLenum:
1990             {
1991                 VOGL_VERIFY(pname_def.m_count == 1);
1992                 GLenum v;
1993                 if (get(enum_val, 0, &v))
1994                 {
1995                     GL_ENTRYPOINT(glFogi)(enum_val, v);
1996                     VOGL_CHECK_GL_ERROR;
1997                     ADD_PROCESSED_STATE(enum_val, 0);
1998                 }
1999                 break;
2000             }
2001             default:
2002             {
2003                 VOGL_VERIFY(0);
2004                 break;
2005             }
2006         }
2007     }
2008
2009     // hints
2010     static GLenum s_hint_pnames[] = { GL_GENERATE_MIPMAP_HINT, GL_FOG_HINT, GL_FRAGMENT_SHADER_DERIVATIVE_HINT, GL_LINE_SMOOTH_HINT, GL_POLYGON_SMOOTH_HINT, GL_TEXTURE_COMPRESSION_HINT, GL_PERSPECTIVE_CORRECTION_HINT, GL_POINT_SMOOTH_HINT };
2011     for (uint i = 0; i < VOGL_ARRAY_SIZE(s_hint_pnames); i++)
2012     {
2013         GLenum enum_val = s_hint_pnames[i];
2014         GLenum val;
2015         if (get(enum_val, 0, &val))
2016         {
2017             GL_ENTRYPOINT(glHint)(enum_val, val);
2018             VOGL_CHECK_GL_ERROR;
2019             ADD_PROCESSED_STATE(enum_val, 0);
2020         }
2021     }
2022
2023     // primitive restart index
2024     uint prim_restart_index;
2025     if (get(GL_PRIMITIVE_RESTART_INDEX, 0, &prim_restart_index))
2026     {
2027         GL_ENTRYPOINT(glPrimitiveRestartIndex)(prim_restart_index);
2028         VOGL_CHECK_GL_ERROR;
2029         ADD_PROCESSED_STATE(GL_PRIMITIVE_RESTART_INDEX, 0);
2030     }
2031
2032     // alpha func
2033     GLenum alpha_func;
2034     float alpha_ref;
2035     if (get(GL_ALPHA_TEST_FUNC, 0, &alpha_func) && get(GL_ALPHA_TEST_REF, 0, &alpha_ref))
2036     {
2037         GL_ENTRYPOINT(glAlphaFunc)(alpha_func, alpha_ref);
2038         VOGL_CHECK_GL_ERROR;
2039         ADD_PROCESSED_STATE(GL_ALPHA_TEST_FUNC, 0);
2040         ADD_PROCESSED_STATE(GL_ALPHA_TEST_REF, 0);
2041     }
2042
2043     // clear index value
2044     int clear_index;
2045     if (get(GL_INDEX_CLEAR_VALUE, 0, &clear_index))
2046     {
2047         GL_ENTRYPOINT(glClearIndex)(static_cast<float>(clear_index));
2048         VOGL_CHECK_GL_ERROR;
2049         ADD_PROCESSED_STATE(GL_INDEX_CLEAR_VALUE, 0);
2050     }
2051
2052     // index writemask
2053     int index_writemask;
2054     if (get(GL_INDEX_WRITEMASK, 0, &index_writemask))
2055     {
2056         GL_ENTRYPOINT(glIndexMask)(index_writemask);
2057         VOGL_CHECK_GL_ERROR;
2058         ADD_PROCESSED_STATE(GL_INDEX_WRITEMASK, 0);
2059     }
2060
2061     // line stipple
2062     int line_stipple_pattern, line_stipple_repeat;
2063     if (get(GL_LINE_STIPPLE_PATTERN, 0, &line_stipple_pattern) && get(GL_LINE_STIPPLE_REPEAT, 0, &line_stipple_repeat))
2064     {
2065         GL_ENTRYPOINT(glLineStipple)(line_stipple_repeat, line_stipple_pattern);
2066         VOGL_CHECK_GL_ERROR;
2067         ADD_PROCESSED_STATE(GL_LINE_STIPPLE_PATTERN, 0);
2068         ADD_PROCESSED_STATE(GL_LINE_STIPPLE_REPEAT, 0);
2069     }
2070
2071     // list base
2072     int list_base;
2073     if (get(GL_LIST_BASE, 0, &list_base))
2074     {
2075         GL_ENTRYPOINT(glListBase)(list_base);
2076         VOGL_CHECK_GL_ERROR;
2077         ADD_PROCESSED_STATE(GL_LIST_BASE, 0);
2078     }
2079
2080     // matrix mode
2081     GLenum matrix_mode;
2082     if (get(GL_MATRIX_MODE, 0, &matrix_mode))
2083     {
2084         GL_ENTRYPOINT(glMatrixMode)(matrix_mode);
2085         VOGL_CHECK_GL_ERROR;
2086         ADD_PROCESSED_STATE(GL_MATRIX_MODE, 0);
2087     }
2088
2089     // shade model
2090     GLenum shade_model;
2091     if (get(GL_SHADE_MODEL, 0, &shade_model))
2092     {
2093         GL_ENTRYPOINT(glShadeModel)(shade_model);
2094         VOGL_CHECK_GL_ERROR;
2095         ADD_PROCESSED_STATE(GL_SHADE_MODEL, 0);
2096     }
2097
2098     // pixel zoom
2099     float zoom_x, zoom_y;
2100     if (get(GL_ZOOM_X, 0, &zoom_x) && get(GL_ZOOM_Y, 0, &zoom_y))
2101     {
2102         GL_ENTRYPOINT(glPixelZoom)(zoom_x, zoom_y);
2103         VOGL_CHECK_GL_ERROR;
2104         ADD_PROCESSED_STATE(GL_ZOOM_X, 0);
2105         ADD_PROCESSED_STATE(GL_ZOOM_Y, 0);
2106     }
2107
2108     // stencil clear value
2109     int stencil_clear_value;
2110     if (get(GL_STENCIL_CLEAR_VALUE, 0, &stencil_clear_value))
2111     {
2112         GL_ENTRYPOINT(glClearStencil)(stencil_clear_value);
2113         VOGL_CHECK_GL_ERROR;
2114         ADD_PROCESSED_STATE(GL_STENCIL_CLEAR_VALUE, 0);
2115     }
2116
2117     // pixel store
2118     static const GLenum s_pixel_store_pnames[] =
2119         {
2120             GL_UNPACK_ALIGNMENT, GL_UNPACK_ROW_LENGTH, GL_UNPACK_SKIP_PIXELS, GL_UNPACK_SKIP_ROWS, GL_UNPACK_IMAGE_HEIGHT, GL_UNPACK_SKIP_IMAGES,
2121             GL_PACK_ALIGNMENT, GL_PACK_IMAGE_HEIGHT, GL_PACK_ROW_LENGTH, GL_PACK_SKIP_IMAGES, GL_PACK_SKIP_PIXELS, GL_PACK_SKIP_ROWS
2122         };
2123
2124     for (uint i = 0; i < VOGL_ARRAY_SIZE(s_pixel_store_pnames); i++)
2125     {
2126         GLenum enum_val = s_pixel_store_pnames[i];
2127
2128         int pname_def_index = g_gl_enums.find_pname_def_index(enum_val);
2129         if (pname_def_index < 0)
2130         {
2131             vogl_warning_printf("Unable to find pname def for GL enum %s\n", g_gl_enums.find_name(enum_val));
2132             continue;
2133         }
2134
2135         const gl_pname_def_t &pname_def = g_gl_pname_defs[pname_def_index];
2136
2137         VOGL_VERIFY((pname_def.m_type == cSTInt32) && (pname_def.m_count == 1));
2138
2139         int val;
2140         if (get(enum_val, 0, &val))
2141         {
2142             GL_ENTRYPOINT(glPixelStorei)(enum_val, val);
2143             VOGL_CHECK_GL_ERROR;
2144             ADD_PROCESSED_STATE(enum_val, 0);
2145         }
2146     }
2147
2148     // program pipeline binding
2149     uint program_pipeline_binding;
2150     if (get(GL_PROGRAM_PIPELINE_BINDING, 0, &program_pipeline_binding))
2151     {
2152         // is this correct?
2153         program_pipeline_binding = static_cast<uint>(remapper.remap_handle(VOGL_NAMESPACE_PIPELINES, program_pipeline_binding));
2154         GL_ENTRYPOINT(glBindProgramPipeline)(program_pipeline_binding);
2155         VOGL_CHECK_GL_ERROR;
2156         ADD_PROCESSED_STATE(GL_PROGRAM_PIPELINE_BINDING, 0);
2157     }
2158
2159     // accum clear value
2160     float accum_clear_value[4];
2161     if (get(GL_ACCUM_CLEAR_VALUE, 0, accum_clear_value, 4))
2162     {
2163         GL_ENTRYPOINT(glClearAccum)(accum_clear_value[0], accum_clear_value[1], accum_clear_value[2], accum_clear_value[3]);
2164         VOGL_CHECK_GL_ERROR;
2165         ADD_PROCESSED_STATE(GL_ACCUM_CLEAR_VALUE, 0);
2166     }
2167
2168     float light_model_ambient[4];
2169     if (get(GL_LIGHT_MODEL_AMBIENT, 0, light_model_ambient, 4))
2170     {
2171         GL_ENTRYPOINT(glLightModelfv)(GL_LIGHT_MODEL_AMBIENT, light_model_ambient);
2172         VOGL_CHECK_GL_ERROR;
2173         ADD_PROCESSED_STATE(GL_LIGHT_MODEL_AMBIENT, 0);
2174     }
2175
2176     GLenum light_model_color_control;
2177     if (get(GL_LIGHT_MODEL_COLOR_CONTROL, 0, &light_model_color_control))
2178     {
2179         GL_ENTRYPOINT(glLightModeli)(GL_LIGHT_MODEL_COLOR_CONTROL, light_model_color_control);
2180         VOGL_CHECK_GL_ERROR;
2181         ADD_PROCESSED_STATE(GL_LIGHT_MODEL_COLOR_CONTROL, 0);
2182     }
2183
2184     // current program
2185     uint cur_trace_program;
2186     if (get(GL_CURRENT_PROGRAM, 0, &cur_trace_program))
2187     {
2188         uint cur_program = static_cast<uint>(remapper.remap_handle(VOGL_NAMESPACE_PROGRAMS, cur_trace_program));
2189         GL_ENTRYPOINT(glUseProgram)(cur_program);
2190         VOGL_CHECK_GL_ERROR;
2191         ADD_PROCESSED_STATE(GL_CURRENT_PROGRAM, 0);
2192     }
2193
2194     int attrib_stack_depth;
2195     if (get(GL_ATTRIB_STACK_DEPTH, 0, &attrib_stack_depth) && attrib_stack_depth)
2196     {
2197         vogl_warning_printf("%s: Attribute stack is not empty and cannot be restored\n", VOGL_METHOD_NAME);
2198         ADD_PROCESSED_STATE(GL_ATTRIB_STACK_DEPTH, 0);
2199     }
2200
2201     int client_attrib_stack_depth;
2202     if (get(GL_CLIENT_ATTRIB_STACK_DEPTH, 0, &client_attrib_stack_depth) && client_attrib_stack_depth)
2203     {
2204         vogl_warning_printf("%s: Client attribute stack is not empty and cannot be restored\n", VOGL_METHOD_NAME);
2205         ADD_PROCESSED_STATE(GL_CLIENT_ATTRIB_STACK_DEPTH, 0);
2206     }
2207
2208     int selection_buffer_size = 0;
2209     if (get(GL_SELECTION_BUFFER_SIZE, 0, &selection_buffer_size) && (selection_buffer_size))
2210     {
2211         if ((!persistent_state.m_pSelect_buffer) || (!persistent_state.m_pSelect_buffer->try_resize(selection_buffer_size)))
2212         {
2213             vogl_warning_printf("%s: Unable to restore selection buffer\n", VOGL_METHOD_NAME);
2214         }
2215         else
2216         {
2217             GL_ENTRYPOINT(glSelectBuffer)(selection_buffer_size, persistent_state.m_pSelect_buffer->get_ptr());
2218             VOGL_CHECK_GL_ERROR;
2219         }
2220     }
2221
2222     int name_stack_depth;
2223     if (get(GL_NAME_STACK_DEPTH, 0, &name_stack_depth) && name_stack_depth)
2224     {
2225         GL_ENTRYPOINT(glRenderMode)(GL_SELECT);
2226         VOGL_CHECK_GL_ERROR;
2227
2228         GL_ENTRYPOINT(glInitNames)();
2229         VOGL_CHECK_GL_ERROR;
2230
2231         for (int i = 0; i < name_stack_depth; i++)
2232             GL_ENTRYPOINT(glPushName)(i + 1); // push anything
2233
2234         VOGL_CHECK_GL_ERROR;
2235
2236         GL_ENTRYPOINT(glRenderMode)(GL_RENDER);
2237         VOGL_CHECK_GL_ERROR;
2238
2239         ADD_PROCESSED_STATE(GL_NAME_STACK_DEPTH, 0);
2240     }
2241
2242     // render mode
2243     GLenum render_mode;
2244     if (get(GL_RENDER_MODE, 0, &render_mode))
2245     {
2246         GL_ENTRYPOINT(glRenderMode)(render_mode);
2247         VOGL_CHECK_GL_ERROR;
2248         ADD_PROCESSED_STATE(GL_RENDER_MODE, 0);
2249     }
2250
2251     // current color
2252     vec4F cur_color(0.0f);
2253     if (get(GL_CURRENT_COLOR, 0, cur_color.get_ptr(), 4))
2254     {
2255         GL_ENTRYPOINT(glColor4f)(cur_color[0], cur_color[1], cur_color[2], cur_color[3]);
2256         ADD_PROCESSED_STATE(GL_CURRENT_COLOR, 0);
2257     }
2258
2259     vec3F cur_normal(0.0f);
2260     if (get(GL_CURRENT_NORMAL, 0, cur_normal.get_ptr(), 3))
2261     {
2262         GL_ENTRYPOINT(glNormal3f)(cur_normal[0], cur_normal[1], cur_normal[2]);
2263         ADD_PROCESSED_STATE(GL_CURRENT_NORMAL, 0);
2264     }
2265
2266     float cur_index = 0;
2267     if (get(GL_CURRENT_INDEX, 0, &cur_index, 1))
2268     {
2269         GL_ENTRYPOINT(glIndexf)(cur_index);
2270         ADD_PROCESSED_STATE(GL_CURRENT_INDEX, 0);
2271     }
2272
2273     float cur_fog_coord = 0;
2274     if (get(GL_CURRENT_FOG_COORD, 0, &cur_fog_coord, 1))
2275     {
2276         GL_ENTRYPOINT(glFogCoordf)(cur_fog_coord);
2277         ADD_PROCESSED_STATE(GL_CURRENT_FOG_COORD, 0);
2278     }
2279
2280     vec4F cur_secondary_color(0.0f);
2281     if (get(GL_CURRENT_SECONDARY_COLOR, 0, cur_secondary_color.get_ptr(), 4))
2282     {
2283         GL_ENTRYPOINT(glSecondaryColor3f)(cur_secondary_color[0], cur_secondary_color[1], cur_secondary_color[2]);
2284         ADD_PROCESSED_STATE(GL_CURRENT_SECONDARY_COLOR, 0);
2285     }
2286
2287     vec4F cur_raster_position(0.0f);
2288     if (get(GL_CURRENT_RASTER_POSITION, 0, cur_raster_position.get_ptr(), 4))
2289     {
2290         GL_ENTRYPOINT(glRasterPos4f)(cur_raster_position[0], cur_raster_position[1], cur_raster_position[2], cur_raster_position[3]);
2291         ADD_PROCESSED_STATE(GL_CURRENT_RASTER_POSITION, 0);
2292     }
2293
2294     // I don't know what we can do about these, or if we even care.
2295     ADD_PROCESSED_STATE(GL_CURRENT_RASTER_POSITION_VALID, 0);
2296     ADD_PROCESSED_STATE(GL_CURRENT_RASTER_COLOR, 0);
2297     ADD_PROCESSED_STATE(GL_CURRENT_RASTER_DISTANCE, 0);
2298     ADD_PROCESSED_STATE(GL_CURRENT_RASTER_INDEX, 0);
2299     //ADD_PROCESSED_STATE(GL_CURRENT_RASTER_SECONDARY_COLOR, 0); // can't retrieve on AMD's v13 drivers
2300
2301     // TODO: pixel maps?
2302
2303     //----------------------------------------
2304
2305     // begin any active queries
2306
2307     for (uint i = 0; i < VOGL_ARRAY_SIZE(g_query_targets); i++)
2308     {
2309         const GLenum target = g_query_targets[i];
2310
2311         GLuint query_handle = 0;
2312         if (get(GL_CURRENT_QUERY, target, &query_handle))
2313         {
2314             ADD_PROCESSED_STATE(GL_CURRENT_QUERY, target);
2315
2316             if (query_handle)
2317             {
2318                 query_handle = static_cast<GLuint>(remapper.remap_handle(VOGL_NAMESPACE_QUERIES, query_handle));
2319
2320                 if (query_handle)
2321                 {
2322                     GL_ENTRYPOINT(glBeginQuery)(target, query_handle);
2323                     VOGL_CHECK_GL_ERROR;
2324                 }
2325             }
2326         }
2327     }
2328
2329     //----------------------------------------
2330
2331     GL_ENTRYPOINT(glBindBuffer)(GL_ARRAY_BUFFER, 0);
2332     VOGL_CHECK_GL_ERROR;
2333
2334     GL_ENTRYPOINT(glBindBuffer)(GL_ARRAY_BUFFER, prev_array_buffer_binding);
2335     VOGL_CHECK_GL_ERROR;
2336
2337     if (!context_info.is_core_profile())
2338     {
2339         GL_ENTRYPOINT(glClientActiveTexture)(prev_client_active_texture);
2340         VOGL_CHECK_GL_ERROR;
2341     }
2342
2343     GL_ENTRYPOINT(glActiveTexture)(prev_active_texture);
2344     VOGL_CHECK_GL_ERROR;
2345
2346 #ifdef DEBUG_CHECK_FOR_UNPROCESSED_STATES
2347
2348 #define NOTE_UNUSED(x) ADD_PROCESSED_STATE(x, 0);
2349
2350     NOTE_UNUSED(GL_SUBPIXEL_BITS)
2351     NOTE_UNUSED(GL_VIEWPORT_SUBPIXEL_BITS)
2352     NOTE_UNUSED(GL_RED_BITS)
2353     NOTE_UNUSED(GL_INDEX_BITS)
2354     NOTE_UNUSED(GL_GREEN_BITS)
2355     NOTE_UNUSED(GL_DEPTH_BITS)
2356     NOTE_UNUSED(GL_BLUE_BITS)
2357     NOTE_UNUSED(GL_ALPHA_BITS)
2358     NOTE_UNUSED(GL_ACCUM_ALPHA_BITS)
2359     NOTE_UNUSED(GL_ACCUM_BLUE_BITS)
2360     NOTE_UNUSED(GL_ACCUM_GREEN_BITS)
2361     NOTE_UNUSED(GL_ACCUM_RED_BITS)
2362     NOTE_UNUSED(GL_STENCIL_BITS)
2363     NOTE_UNUSED(GL_ATTRIB_STACK_DEPTH)
2364     NOTE_UNUSED(GL_CLIENT_ATTRIB_STACK_DEPTH)
2365     //NOTE_UNUSED(GL_COLOR_MATRIX_STACK_DEPTH) // can't retrieve on AMD v13 drivers
2366     NOTE_UNUSED(GL_DEBUG_GROUP_STACK_DEPTH)
2367     NOTE_UNUSED(GL_MAX_ATTRIB_STACK_DEPTH)
2368     NOTE_UNUSED(GL_MAX_CLIENT_ATTRIB_STACK_DEPTH)
2369     NOTE_UNUSED(GL_MAX_COLOR_MATRIX_STACK_DEPTH)
2370     NOTE_UNUSED(GL_MAX_DEBUG_GROUP_STACK_DEPTH)
2371     NOTE_UNUSED(GL_MAX_MODELVIEW_STACK_DEPTH)
2372     NOTE_UNUSED(GL_MAX_NAME_STACK_DEPTH)
2373     NOTE_UNUSED(GL_MAX_PROJECTION_STACK_DEPTH)
2374     NOTE_UNUSED(GL_MAX_TEXTURE_STACK_DEPTH)
2375     NOTE_UNUSED(GL_MAX_3D_TEXTURE_SIZE)
2376     NOTE_UNUSED(GL_MAX_ARRAY_TEXTURE_LAYERS)
2377     NOTE_UNUSED(GL_MAX_CLIP_PLANES)
2378     NOTE_UNUSED(GL_MAX_COLOR_ATTACHMENTS)
2379     NOTE_UNUSED(GL_MAX_COLOR_TEXTURE_SAMPLES)
2380     NOTE_UNUSED(GL_MAX_COMBINED_ATOMIC_COUNTERS)
2381     NOTE_UNUSED(GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS)
2382     NOTE_UNUSED(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS)
2383     NOTE_UNUSED(GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS)
2384     NOTE_UNUSED(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS)
2385     NOTE_UNUSED(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS)
2386     NOTE_UNUSED(GL_MAX_COMBINED_UNIFORM_BLOCKS)
2387     NOTE_UNUSED(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS)
2388     NOTE_UNUSED(GL_MAX_COMPUTE_ATOMIC_COUNTERS)
2389     NOTE_UNUSED(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS)
2390     NOTE_UNUSED(GL_MAX_COMPUTE_LOCAL_INVOCATIONS)
2391     NOTE_UNUSED(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS)
2392     NOTE_UNUSED(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS)
2393     NOTE_UNUSED(GL_MAX_COMPUTE_UNIFORM_BLOCKS)
2394     NOTE_UNUSED(GL_MAX_COMPUTE_UNIFORM_COMPONENTS)
2395     NOTE_UNUSED(GL_MAX_CUBE_MAP_TEXTURE_SIZE)
2396     NOTE_UNUSED(GL_MAX_DEPTH_TEXTURE_SAMPLES)
2397     NOTE_UNUSED(GL_MAX_DRAW_BUFFERS)
2398     NOTE_UNUSED(GL_MAX_DUAL_SOURCE_DRAW_BUFFERS)
2399     NOTE_UNUSED(GL_MAX_ELEMENTS_INDICES)
2400     NOTE_UNUSED(GL_MAX_ELEMENTS_VERTICES)
2401     NOTE_UNUSED(GL_MAX_ELEMENT_INDEX)
2402     NOTE_UNUSED(GL_MAX_EVAL_ORDER)
2403     NOTE_UNUSED(GL_MAX_FRAGMENT_ATOMIC_COUNTERS)
2404     NOTE_UNUSED(GL_MAX_FRAGMENT_INPUT_COMPONENTS)
2405     NOTE_UNUSED(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS)
2406     NOTE_UNUSED(GL_MAX_FRAGMENT_UNIFORM_BLOCKS)
2407     NOTE_UNUSED(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS)
2408     NOTE_UNUSED(GL_MAX_FRAGMENT_UNIFORM_VECTORS)
2409     NOTE_UNUSED(GL_MAX_FRAMEBUFFER_HEIGHT)
2410     NOTE_UNUSED(GL_MAX_FRAMEBUFFER_LAYERS)
2411     NOTE_UNUSED(GL_MAX_FRAMEBUFFER_SAMPLES)
2412     NOTE_UNUSED(GL_MAX_FRAMEBUFFER_WIDTH)
2413     NOTE_UNUSED(GL_MAX_GEOMETRY_ATOMIC_COUNTERS)
2414     NOTE_UNUSED(GL_MAX_GEOMETRY_INPUT_COMPONENTS)
2415     NOTE_UNUSED(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS)
2416     NOTE_UNUSED(GL_MAX_GEOMETRY_OUTPUT_VERTICES)
2417     NOTE_UNUSED(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS)
2418     NOTE_UNUSED(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS)
2419     NOTE_UNUSED(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS)
2420     NOTE_UNUSED(GL_MAX_GEOMETRY_UNIFORM_BLOCKS)
2421     NOTE_UNUSED(GL_MAX_GEOMETRY_UNIFORM_COMPONENTS)
2422     NOTE_UNUSED(GL_MAX_INTEGER_SAMPLES)
2423     NOTE_UNUSED(GL_MAX_LABEL_LENGTH)
2424     NOTE_UNUSED(GL_MAX_LIGHTS)
2425     NOTE_UNUSED(GL_MAX_LIST_NESTING)
2426     NOTE_UNUSED(GL_MAX_PIXEL_MAP_TABLE)
2427     NOTE_UNUSED(GL_MAX_PROGRAM_TEXEL_OFFSET)
2428     NOTE_UNUSED(GL_MAX_RECTANGLE_TEXTURE_SIZE)
2429     NOTE_UNUSED(GL_MAX_RENDERBUFFER_SIZE)
2430     NOTE_UNUSED(GL_MAX_SAMPLE_MASK_WORDS)
2431     NOTE_UNUSED(GL_MAX_SERVER_WAIT_TIMEOUT)
2432     NOTE_UNUSED(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS)
2433     NOTE_UNUSED(GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS)
2434     NOTE_UNUSED(GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS)
2435     NOTE_UNUSED(GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS)
2436     NOTE_UNUSED(GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS)
2437     NOTE_UNUSED(GL_MAX_TEXTURE_BUFFER_SIZE)
2438     NOTE_UNUSED(GL_MAX_TEXTURE_COORDS)
2439     NOTE_UNUSED(GL_MAX_TEXTURE_IMAGE_UNITS)
2440     NOTE_UNUSED(GL_MAX_TEXTURE_LOD_BIAS)
2441     NOTE_UNUSED(GL_MAX_TEXTURE_SIZE)
2442     NOTE_UNUSED(GL_MAX_TEXTURE_UNITS)
2443     NOTE_UNUSED(GL_MAX_UNIFORM_BLOCK_SIZE)
2444     NOTE_UNUSED(GL_MAX_UNIFORM_BUFFER_BINDINGS)
2445     NOTE_UNUSED(GL_MAX_UNIFORM_LOCATIONS)
2446     NOTE_UNUSED(GL_MAX_VARYING_FLOATS)
2447     NOTE_UNUSED(GL_MAX_VARYING_VECTORS)
2448     NOTE_UNUSED(GL_MAX_VERTEX_ATOMIC_COUNTERS)
2449     NOTE_UNUSED(GL_MAX_VERTEX_ATTRIBS)
2450     NOTE_UNUSED(GL_MAX_VERTEX_ATTRIB_BINDINGS)
2451     NOTE_UNUSED(GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET)
2452     NOTE_UNUSED(GL_MAX_VERTEX_OUTPUT_COMPONENTS)
2453     NOTE_UNUSED(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS)
2454     NOTE_UNUSED(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS)
2455     NOTE_UNUSED(GL_MAX_VERTEX_UNIFORM_BLOCKS)
2456     NOTE_UNUSED(GL_MAX_VERTEX_UNIFORM_COMPONENTS)
2457     NOTE_UNUSED(GL_MAX_VERTEX_UNIFORM_VECTORS)
2458     NOTE_UNUSED(GL_MAX_VIEWPORTS)
2459     NOTE_UNUSED(GL_MAX_VIEWPORT_DIMS)
2460     NOTE_UNUSED(GL_MODELVIEW_STACK_DEPTH)
2461     NOTE_UNUSED(GL_NAME_STACK_DEPTH)
2462     NOTE_UNUSED(GL_PROJECTION_STACK_DEPTH)
2463     NOTE_UNUSED(GL_COLOR_MATRIX)
2464     NOTE_UNUSED(GL_AUX_BUFFERS)
2465     NOTE_UNUSED(GL_COMPRESSED_TEXTURE_FORMATS)
2466     NOTE_UNUSED(GL_CONTEXT_FLAGS)
2467     NOTE_UNUSED(GL_FEEDBACK_BUFFER_POINTER)
2468     NOTE_UNUSED(GL_FEEDBACK_BUFFER_SIZE)
2469     NOTE_UNUSED(GL_FEEDBACK_BUFFER_TYPE)
2470     NOTE_UNUSED(GL_IMPLEMENTATION_COLOR_READ_FORMAT)
2471     NOTE_UNUSED(GL_IMPLEMENTATION_COLOR_READ_TYPE)
2472     NOTE_UNUSED(GL_LAYER_PROVOKING_VERTEX)
2473     NOTE_UNUSED(GL_MIN_MAP_BUFFER_ALIGNMENT)
2474     NOTE_UNUSED(GL_MIN_PROGRAM_TEXEL_OFFSET)
2475     NOTE_UNUSED(GL_MINOR_VERSION)
2476     NOTE_UNUSED(GL_MAJOR_VERSION)
2477     NOTE_UNUSED(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT)
2478     NOTE_UNUSED(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT)
2479     NOTE_UNUSED(GL_ALIASED_LINE_WIDTH_RANGE)
2480     NOTE_UNUSED(GL_ALIASED_POINT_SIZE_RANGE)
2481     NOTE_UNUSED(GL_LINE_WIDTH_GRANULARITY)
2482     NOTE_UNUSED(GL_LINE_WIDTH_RANGE)
2483     NOTE_UNUSED(GL_MAP1_GRID_DOMAIN)
2484     NOTE_UNUSED(GL_MAP1_GRID_SEGMENTS)
2485     NOTE_UNUSED(GL_MAP2_GRID_DOMAIN)
2486     NOTE_UNUSED(GL_MAP2_GRID_SEGMENTS)
2487     NOTE_UNUSED(GL_MODELVIEW_MATRIX)
2488     NOTE_UNUSED(GL_NUM_COMPRESSED_TEXTURE_FORMATS)
2489     NOTE_UNUSED(GL_NUM_EXTENSIONS)
2490     NOTE_UNUSED(GL_NUM_PROGRAM_BINARY_FORMATS)
2491     NOTE_UNUSED(GL_NUM_SHADER_BINARY_FORMATS)
2492     NOTE_UNUSED(GL_POINT_SIZE_GRANULARITY)
2493     NOTE_UNUSED(GL_POINT_SIZE_RANGE)
2494     NOTE_UNUSED(GL_POST_COLOR_MATRIX_COLOR_TABLE)
2495     NOTE_UNUSED(GL_PROGRAM_BINARY_FORMATS)
2496     NOTE_UNUSED(GL_PROJECTION_MATRIX)
2497     NOTE_UNUSED(GL_SAMPLES)
2498     NOTE_UNUSED(GL_SAMPLE_BUFFERS)
2499     NOTE_UNUSED(GL_SELECTION_BUFFER_POINTER)
2500     //NOTE_UNUSED(GL_SELECTION_BUFFER_SIZE)
2501     NOTE_UNUSED(GL_TIMESTAMP)
2502     NOTE_UNUSED(GL_TRANSPOSE_COLOR_MATRIX)
2503     NOTE_UNUSED(GL_TRANSPOSE_MODELVIEW_MATRIX)
2504     NOTE_UNUSED(GL_TRANSPOSE_PROJECTION_MATRIX)
2505     NOTE_UNUSED(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT)
2506     NOTE_UNUSED(GL_VIEWPORT_BOUNDS_RANGE)
2507     NOTE_UNUSED(GL_VIEWPORT_INDEX_PROVOKING_VERTEX)
2508 #undef NOTE_UNUSED
2509
2510     for (const_iterator it = begin(); it != end(); ++it)
2511     {
2512         const vogl_state_data &state = it->second;
2513
2514         uint i;
2515         for (i = 0; i < processed_states.size(); i++)
2516             if (state.get_id() == processed_states[i])
2517                 break;
2518
2519         if (i == processed_states.size())
2520         {
2521             vogl_debug_printf("Didn't process state: %s index: %u indexed_variant: %u\n", g_gl_enums.find_name(state.get_enum_val()), state.get_index(), state.get_indexed_variant());
2522         }
2523     }
2524 #endif
2525
2526     return true;
2527 }
2528
2529 bool vogl_general_context_state::remap_handles(vogl_handle_remapper &remapper)
2530 {
2531     VOGL_FUNC_TRACER
2532
2533     for (state_map::iterator it = m_states.begin(); it != m_states.end(); ++it)
2534     {
2535         vogl_state_data &state = it->second;
2536
2537         const GLenum enum_val = state.get_enum_val();
2538         const uint index = state.get_index();
2539         VOGL_NOTE_UNUSED(index);
2540
2541         vogl_namespace_t handle_namespace = VOGL_NAMESPACE_INVALID;
2542
2543         switch (enum_val)
2544         {
2545             case GL_ARRAY_BUFFER_BINDING:
2546             case GL_ELEMENT_ARRAY_BUFFER_BINDING:
2547             case GL_PIXEL_PACK_BUFFER_BINDING:
2548             case GL_PIXEL_UNPACK_BUFFER_BINDING:
2549             case GL_COPY_READ_BUFFER_BINDING:
2550             case GL_COPY_WRITE_BUFFER_BINDING:
2551             case GL_DRAW_INDIRECT_BUFFER_BINDING:
2552             case GL_DISPATCH_INDIRECT_BUFFER_BINDING:
2553             case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2554             case GL_UNIFORM_BUFFER_BINDING:
2555             case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2556             case GL_SHADER_STORAGE_BUFFER_BINDING:
2557
2558             case GL_VERTEX_ARRAY_BUFFER_BINDING:
2559             case GL_COLOR_ARRAY_BUFFER_BINDING:
2560             case GL_INDEX_ARRAY_BUFFER_BINDING:
2561             case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING:
2562             case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
2563             case GL_FOG_COORD_ARRAY_BUFFER_BINDING:
2564             case GL_NORMAL_ARRAY_BUFFER_BINDING:
2565             case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING:
2566                 handle_namespace = VOGL_NAMESPACE_BUFFERS;
2567                 break;
2568
2569             case GL_SAMPLER_BINDING:
2570                 handle_namespace = VOGL_NAMESPACE_SAMPLERS;
2571                 break;
2572
2573             case GL_CURRENT_QUERY:
2574                 handle_namespace = VOGL_NAMESPACE_QUERIES;
2575                 break;
2576
2577             case GL_CURRENT_PROGRAM:
2578                 handle_namespace = VOGL_NAMESPACE_PROGRAMS;
2579                 break;
2580
2581             case GL_PROGRAM_PIPELINE_BINDING:
2582                 handle_namespace = VOGL_NAMESPACE_PIPELINES;
2583                 break;
2584
2585             case GL_RENDERBUFFER_BINDING:
2586                 handle_namespace = VOGL_NAMESPACE_RENDER_BUFFERS;
2587                 break;
2588
2589             case GL_READ_FRAMEBUFFER_BINDING:
2590             case GL_DRAW_FRAMEBUFFER_BINDING:
2591                 handle_namespace = VOGL_NAMESPACE_FRAMEBUFFERS;
2592                 break;
2593
2594             case GL_VERTEX_ARRAY_BINDING:
2595                 handle_namespace = VOGL_NAMESPACE_VERTEX_ARRAYS;
2596                 break;
2597
2598             case GL_TEXTURE_BINDING_BUFFER:
2599             case GL_TEXTURE_BINDING_RECTANGLE:
2600             case GL_TEXTURE_BINDING_CUBE_MAP_ARRAY:
2601             case GL_TEXTURE_BINDING_CUBE_MAP:
2602             case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
2603             case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
2604             case GL_TEXTURE_BINDING_2D_ARRAY:
2605             case GL_TEXTURE_BINDING_1D_ARRAY:
2606             case GL_TEXTURE_BINDING_1D:
2607             case GL_TEXTURE_BINDING_2D:
2608             case GL_TEXTURE_BINDING_3D:
2609                 handle_namespace = VOGL_NAMESPACE_TEXTURES;
2610                 break;
2611         }
2612
2613         if (handle_namespace == VOGL_NAMESPACE_INVALID)
2614             continue;
2615
2616         if ((state.get_num_elements() != 1) || ((state.get_data_type() != cSTInt32) && (state.get_data_type() != cSTUInt32)))
2617         {
2618             VOGL_ASSERT_ALWAYS;
2619             continue;
2620         }
2621
2622         GLuint handle;
2623         state.get_uint(&handle);
2624
2625         if (handle)
2626         {
2627             handle = static_cast<GLuint>(remapper.remap_handle(handle_namespace, handle));
2628
2629             state.get_element<GLuint>(0) = handle;
2630         }
2631     }
2632
2633     return true;
2634 }
2635
2636 // TODO: Move this to separate file
2637 vogl_polygon_stipple_state::vogl_polygon_stipple_state()
2638     : m_valid(false)
2639 {
2640     VOGL_FUNC_TRACER
2641
2642     utils::zero_object(m_pattern);
2643 }
2644
2645 vogl_polygon_stipple_state::~vogl_polygon_stipple_state()
2646 {
2647     VOGL_FUNC_TRACER
2648 }
2649
2650 bool vogl_polygon_stipple_state::snapshot(const vogl_context_info &context_info)
2651 {
2652     VOGL_FUNC_TRACER
2653
2654     VOGL_NOTE_UNUSED(context_info);
2655
2656     VOGL_CHECK_GL_ERROR;
2657
2658     clear();
2659
2660     vogl_scoped_state_saver pixelstore_state_saver(cGSTPixelStore);
2661     vogl_reset_pixel_store_states();
2662
2663     GL_ENTRYPOINT(glGetPolygonStipple)(m_pattern);
2664     VOGL_CHECK_GL_ERROR;
2665
2666     m_valid = true;
2667
2668     return true;
2669 }
2670
2671 bool vogl_polygon_stipple_state::restore(const vogl_context_info &context_info) const
2672 {
2673     VOGL_FUNC_TRACER
2674
2675     VOGL_NOTE_UNUSED(context_info);
2676
2677     if (!m_valid)
2678         return false;
2679
2680     VOGL_CHECK_GL_ERROR;
2681
2682     vogl_scoped_state_saver pixelstore_state_saver(cGSTPixelStore);
2683     vogl_reset_pixel_store_states();
2684
2685     GL_ENTRYPOINT(glPolygonStipple)(m_pattern);
2686     VOGL_CHECK_GL_ERROR;
2687
2688     return true;
2689 }
2690
2691 void vogl_polygon_stipple_state::clear()
2692 {
2693     VOGL_FUNC_TRACER
2694
2695     m_valid = false;
2696     utils::zero_object(m_pattern);
2697 }
2698
2699 bool vogl_polygon_stipple_state::serialize(json_node &node, vogl_blob_manager &blob_manager) const
2700 {
2701     VOGL_FUNC_TRACER
2702
2703     VOGL_NOTE_UNUSED(blob_manager);
2704
2705     if (!m_valid)
2706         return false;
2707
2708     json_node &arr_node = node.add_array("pattern");
2709     for (uint i = 0; i < VOGL_ARRAY_SIZE(m_pattern); i++)
2710         arr_node.add_value(m_pattern[i]);
2711
2712     return true;
2713 }
2714
2715 bool vogl_polygon_stipple_state::deserialize(const json_node &node, const vogl_blob_manager &blob_manager)
2716 {
2717     VOGL_FUNC_TRACER
2718
2719     VOGL_NOTE_UNUSED(blob_manager);
2720
2721     clear();
2722
2723     const json_node *pArr_node = node.find_child_array("pattern");
2724     if (!pArr_node)
2725         return false;
2726
2727     if (!pArr_node->are_all_children_values())
2728         return false;
2729
2730     // An earlier version wrote the wrong size, so ignore that data.
2731     if (pArr_node->size() == VOGL_ARRAY_SIZE(m_pattern))
2732     {
2733         for (uint i = 0; i < VOGL_ARRAY_SIZE(m_pattern); i++)
2734             m_pattern[i] = static_cast<uint8>(pArr_node->value_as_uint32(i));
2735     }
2736     else
2737     {
2738         vogl_warning_printf("%s: Polygon stipple data is not valid in this older trace file so it's being ignored - please recapture (sorry)\n", VOGL_METHOD_NAME);
2739     }
2740
2741     m_valid = true;
2742
2743     return true;
2744 }
2745
2746 uint vogl_polygon_stipple_state::get_num_pattern_rows() const
2747 {
2748     return 32;
2749 }
2750
2751 uint32 vogl_polygon_stipple_state::get_pattern_row(uint row_index) const
2752 {
2753     VOGL_ASSERT(row_index < 32);
2754
2755     return m_pattern[4 * row_index] | (m_pattern[4 * row_index + 1] << 8U) | (m_pattern[4 * row_index + 2] << 16U) | (m_pattern[4 * row_index + 3] << 24U);
2756 }