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