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