]> git.cworth.org Git - vogl/blob - src/voglcommon/vogl_gl_replayer.cpp
0df3d49b2b0ff15ff54e71ece80cd7ec708ae193
[vogl] / src / voglcommon / vogl_gl_replayer.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_gl_replayer.cpp
27 #include "vogl_gl_replayer.h"
28 #include "vogl_general_context_state.h"
29 #include "vogl_sync_object.h"
30 #include "vogl_trace_file_writer.h"
31 #include "vogl_texture_format.h"
32 #include "gl_glx_replay_helper_macros.inc"
33 #include "vogl_backtrace.h"
34
35 #define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
36 #include "vogl_miniz.h"
37
38 #include "vogl_timer.h"
39 #include "vogl_file_utils.h"
40 #include "vogl_map.h"
41 #include "vogl_vector.h"
42
43 #define VOGL_GL_REPLAYER_ARRAY_OVERRUN_BYTE_MAGIC 129
44 #define VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC 0x12345678
45 #define VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC -999999.0f
46
47 //----------------------------------------------------------------------------------------------------------------------
48 // glInterleavedArrays helper table
49 //----------------------------------------------------------------------------------------------------------------------
50 struct interleaved_array_desc_entry_t
51 {
52     uint fmt;
53     bool et;
54     bool ec;
55     bool en;
56     uint st;
57     uint sc;
58     uint sv;
59     uint tc;
60     uint pc;
61     uint pn;
62     uint pv;
63     uint s;
64 };
65
66 #define _2f (sizeof(GLfloat) * 2)
67 #define _3f (sizeof(GLfloat) * 3)
68 #define _4f (sizeof(GLfloat) * 4)
69 #define _5f (sizeof(GLfloat) * 5)
70 #define _6f (sizeof(GLfloat) * 6)
71 #define _7f (sizeof(GLfloat) * 7)
72 #define _8f (sizeof(GLfloat) * 8)
73 #define _9f (sizeof(GLfloat) * 9)
74 #define _10f (sizeof(GLfloat) * 10)
75 #define _11f (sizeof(GLfloat) * 11)
76 #define _12f (sizeof(GLfloat) * 12)
77 #define _15f (sizeof(GLfloat) * 15)
78 #define _c (sizeof(GL_UNSIGNED_BYTE) * 4)
79
80 static const interleaved_array_desc_entry_t vogl_g_interleaved_array_descs[] =
81     {
82         // format                               et              ec                      en       st sc sv tc                                                    pc  pn  pv               s
83         { GL_V2F, false, false, false, 0, 0, 2, 0, 0, 0, 0, _2f },
84         { GL_V3F, false, false, false, 0, 0, 3, 0, 0, 0, 0, _3f },
85         { GL_C4UB_V2F, false, true, false, 0, 4, 2, GL_UNSIGNED_BYTE, 0, 0, _c, _c + _2f },
86         { GL_C4UB_V3F, false, true, false, 0, 4, 3, GL_UNSIGNED_BYTE, 0, 0, _c, _c + _3f },
87         { GL_C3F_V3F, false, true, false, 0, 3, 3, GL_FLOAT, 0, 0, _3f, _6f },
88         { GL_N3F_V3F, false, false, true, 0, 0, 3, 0, 0, 0, _3f, _6f },
89         { GL_C4F_N3F_V3F, false, true, true, 0, 4, 3, GL_FLOAT, 0, _4f, _7f, _10f },
90         { GL_T2F_V3F, true, false, false, 2, 0, 3, 0, 0, 0, _2f, _5f },
91         { GL_T4F_V4F, true, false, false, 4, 0, 4, 0, 0, 0, _4f, _8f },
92         { GL_T2F_C4UB_V3F, true, true, false, 2, 4, 3, GL_UNSIGNED_BYTE, _2f, 0, _c + _2f, _c + _5f },
93         { GL_T2F_C3F_V3F, true, true, false, 2, 3, 3, GL_FLOAT, 0, _2f, _5f, _8f },
94         { GL_T2F_N3F_V3F, true, false, true, 2, 0, 3, 0, 0, _2f, _5f, _8f },
95         { GL_T2F_C4F_N3F_V3F, true, true, true, 2, 4, 3, GL_FLOAT, _2f, _6f, _9f, _12f },
96         { GL_T4F_C4F_N3F_V4F, true, true, true, 4, 4, 4, GL_FLOAT, _4f, _8f, _11f, _15f }
97     };
98
99 #undef _2f
100 #undef _3f
101 #undef _4f
102 #undef _5f
103 #undef _6f
104 #undef _7f
105 #undef _8f
106 #undef _9f
107 #undef _10f
108 #undef _11f
109 #undef _12f
110 #undef _15f
111 #undef _c
112
113 #define VOGL_INTERLEAVED_ARRAY_SIZE (sizeof(vogl_g_interleaved_array_descs) / sizeof(vogl_g_interleaved_array_descs[0]))
114
115 //----------------------------------------------------------------------------------------------------------------------
116 // vogl_replayer::vogl_replayer
117 //----------------------------------------------------------------------------------------------------------------------
118 vogl_gl_replayer::vogl_gl_replayer()
119     : m_flags(0),
120       m_swap_sleep_time(0),
121       m_dump_framebuffer_on_draw_prefix("screenshot"),
122       m_screenshot_prefix("screenshot"),
123       m_dump_framebuffer_on_draw_frame_index(-1),
124       m_dump_framebuffer_on_draw_first_gl_call_index(-1),
125       m_dump_framebuffer_on_draw_last_gl_call_index(-1),
126       m_ctypes_packet(&m_trace_gl_ctypes),
127       m_trace_pointer_size_in_bytes(0),
128       m_trace_pointer_size_in_uints(0),
129       m_temp_gl_packet(&m_trace_gl_ctypes),
130       m_temp2_gl_packet(&m_trace_gl_ctypes),
131       m_pCur_gl_packet(NULL),
132       m_pWindow(NULL),
133       m_pending_make_current_packet(&m_trace_gl_ctypes),
134       m_pending_window_resize_width(0),
135       m_pending_window_resize_height(0),
136       m_pending_window_resize_attempt_counter(false),
137       m_frame_index(0),
138       m_total_swaps(0),
139       m_last_parsed_call_counter(-1),
140       m_last_processed_call_counter(-1),
141       m_cur_trace_context(0),
142       m_cur_replay_context(NULL),
143       m_pCur_context_state(NULL),
144       m_frame_draw_counter(0),
145       m_frame_draw_counter_kill_threshold(cUINT64_MAX),
146       m_is_valid(false),
147       m_pBlob_manager(NULL),
148       m_pPending_snapshot(NULL),
149       m_delete_pending_snapshot_after_applying(false),
150       m_replay_to_trace_remapper(*this)
151 {
152     VOGL_FUNC_TRACER
153
154     m_trace_gl_ctypes.init();
155 }
156
157 //----------------------------------------------------------------------------------------------------------------------
158 // vogl_replayer::~vogl_replayer
159 //----------------------------------------------------------------------------------------------------------------------
160 vogl_gl_replayer::~vogl_gl_replayer()
161 {
162     VOGL_FUNC_TRACER
163
164     deinit();
165 }
166
167 //----------------------------------------------------------------------------------------------------------------------
168 // vogl_replayer::init
169 //----------------------------------------------------------------------------------------------------------------------
170 bool vogl_gl_replayer::init(uint flags, vogl_replay_window *pWindow, const vogl_trace_stream_start_of_file_packet &sof_packet, const vogl_blob_manager &blob_manager)
171 {
172     VOGL_FUNC_TRACER
173
174     if (m_is_valid)
175         deinit();
176
177     if ((!pWindow) || (!pWindow->is_opened()))
178     {
179         VOGL_ASSERT_ALWAYS;
180         return false;
181     }
182
183     if ((sof_packet.m_pointer_sizes != sizeof(uint32)) && (sof_packet.m_pointer_sizes != sizeof(uint64_t)))
184     {
185         vogl_error_printf("%s: Invalid trace pointer size (%u)\n", VOGL_METHOD_NAME, m_sof_packet.m_pointer_sizes);
186         return false;
187     }
188
189     m_pBlob_manager = &blob_manager;
190     m_flags = flags;
191     m_pWindow = pWindow;
192
193     m_sof_packet = sof_packet;
194     m_trace_pointer_size_in_bytes = m_sof_packet.m_pointer_sizes;
195     m_trace_pointer_size_in_uints = m_sof_packet.m_pointer_sizes / sizeof(uint);
196
197     m_trace_gl_ctypes.init();
198     m_trace_gl_ctypes.change_pointer_sizes(m_trace_pointer_size_in_bytes);
199
200     if (!m_pWindow->is_opened())
201     {
202         const uint initial_window_width = 1024;
203         const uint initial_window_height = 768;
204         if (!m_pWindow->open(initial_window_width, initial_window_height))
205         {
206             vogl_error_printf("%s: Failed opening window!\n", VOGL_METHOD_NAME);
207             return false;
208         }
209     }
210
211     m_pCur_gl_packet = NULL;
212
213     m_frame_index = 0;
214     m_total_swaps = 0;
215     m_last_parsed_call_counter = 0;
216     m_last_processed_call_counter = 0;
217
218     m_pending_make_current_packet.clear();
219     m_pending_window_resize_width = 0;
220     m_pending_window_resize_height = 0;
221     m_pending_window_resize_attempt_counter = 0;
222
223     m_at_frame_boundary = true;
224
225     m_cur_trace_context = 0;
226     m_cur_replay_context = 0;
227     m_pCur_context_state = NULL;
228
229     m_contexts.clear();
230
231     m_frame_draw_counter = 0;
232     m_frame_draw_counter_kill_threshold = cUINT64_MAX;
233
234     m_is_valid = true;
235
236     return true;
237 }
238
239 //----------------------------------------------------------------------------------------------------------------------
240 // vogl_replayer::deinit
241 //----------------------------------------------------------------------------------------------------------------------
242 void vogl_gl_replayer::deinit()
243 {
244     VOGL_FUNC_TRACER
245
246     destroy_pending_snapshot();
247     destroy_contexts();
248
249     // TODO: Make a 1st class snapshot cache class
250     for (uint i = 0; i < m_snapshots.size(); i++)
251         vogl_delete(m_snapshots[i].m_pSnapshot);
252     m_snapshots.clear();
253
254     m_ctypes_packet.reset();
255
256     m_pCur_gl_packet = NULL;
257
258     m_frame_index = 0;
259     m_total_swaps = 0;
260     m_last_parsed_call_counter = 0;
261     m_last_processed_call_counter = 0;
262
263     m_pending_make_current_packet.clear();
264     m_pending_window_resize_width = 0;
265     m_pending_window_resize_height = 0;
266     m_pending_window_resize_attempt_counter = 0;
267
268     m_at_frame_boundary = true;
269
270     m_cur_trace_context = 0;
271     m_cur_replay_context = 0;
272     m_pCur_context_state = NULL;
273
274     m_frame_draw_counter = 0;
275     m_frame_draw_counter_kill_threshold = cUINT32_MAX;
276
277     m_pBlob_manager = NULL;
278
279     m_flags = 0;
280     m_swap_sleep_time = 0;
281     m_dump_framebuffer_on_draw_prefix = "screenshot";
282     m_screenshot_prefix = "screenshot";
283     m_backbuffer_hash_filename.clear();
284     m_dump_framebuffer_on_draw_frame_index = -1;
285     m_dump_framebuffer_on_draw_first_gl_call_index = -1;
286     m_dump_framebuffer_on_draw_last_gl_call_index = -1;
287
288     m_dump_frontbuffer_filename.clear();
289
290     m_is_valid = false;
291 }
292
293 //----------------------------------------------------------------------------------------------------------------------
294 // vogl_gl_replayer::dump_trace_gl_packet_debug_info
295 //----------------------------------------------------------------------------------------------------------------------
296 void vogl_gl_replayer::dump_trace_gl_packet_debug_info(const vogl_trace_gl_entrypoint_packet &gl_packet)
297 {
298     VOGL_FUNC_TRACER
299
300     vogl_debug_printf("Trace packet: Total size %u, Param size: %u, Client mem size %u, Name value size %u, call %" PRIu64 ", ID: %s (%u), Thread ID: 0x%" PRIX64 ", Trace Context: 0x%" PRIX64 "\n",
301                      gl_packet.m_size,
302                      gl_packet.m_param_size,
303                      gl_packet.m_client_memory_size,
304                      gl_packet.m_name_value_map_size,
305                      gl_packet.m_call_counter,
306                      g_vogl_entrypoint_descs[gl_packet.m_entrypoint_id].m_pName,
307                      gl_packet.m_entrypoint_id,
308                      gl_packet.m_thread_id,
309                      gl_packet.m_context_handle);
310 }
311
312 //----------------------------------------------------------------------------------------------------------------------
313 // vogl_gl_replayer::dump_packet_as_func_call
314 //----------------------------------------------------------------------------------------------------------------------
315 void vogl_gl_replayer::dump_packet_as_func_call(const vogl_trace_packet& trace_packet)
316 {
317     VOGL_FUNC_TRACER
318
319     dynamic_string str;
320     str.reserve(128);
321     if (!trace_packet.pretty_print(str, false))
322         vogl_error_printf("%s: packet pretty print failed!\n", VOGL_METHOD_NAME);
323     else
324         vogl_debug_printf("%s\n", str.get_ptr());
325 }
326
327 //----------------------------------------------------------------------------------------------------------------------
328 // vogl_replayer::process_next_packet
329 //----------------------------------------------------------------------------------------------------------------------
330 vogl_gl_replayer::status_t vogl_gl_replayer::process_next_packet(const vogl_trace_packet &gl_packet)
331 {
332     // TODO: Fix const correctness
333     return process_gl_entrypoint_packet((vogl_trace_packet &)gl_packet);
334 }
335
336 //----------------------------------------------------------------------------------------------------------------------
337 // vogl_replayer::process_next_packet
338 //----------------------------------------------------------------------------------------------------------------------
339 vogl_gl_replayer::status_t vogl_gl_replayer::process_next_packet(vogl_trace_file_reader &trace_reader)
340 {
341     VOGL_FUNC_TRACER
342
343     vogl_trace_file_reader::trace_file_reader_status_t read_status = trace_reader.read_next_packet();
344     if (read_status == vogl_trace_file_reader::cEOF)
345     {
346         vogl_message_printf("At trace file EOF\n");
347         return cStatusAtEOF;
348     }
349     else if (read_status != vogl_trace_file_reader::cOK)
350     {
351         vogl_error_printf("Failed reading from trace file\n");
352         return cStatusHardFailure;
353     }
354
355     status_t status = cStatusOK;
356
357     switch (trace_reader.get_packet_type())
358     {
359         case cTSPTSOF:
360         {
361             // just ignore it
362             break;
363         }
364         case cTSPTGLEntrypoint:
365         {
366             if (!m_temp_gl_packet.deserialize(trace_reader.get_packet_buf().get_ptr(), trace_reader.get_packet_buf().size(), false))
367             {
368                 vogl_error_printf("Failed deserializing GL entrypoint packet\n");
369                 status = cStatusHardFailure;
370                 break;
371             }
372
373             status = process_next_packet(m_temp_gl_packet);
374
375             break;
376         }
377         case cTSPTEOF:
378         {
379             vogl_message_printf("Encountered EOF packet in trace file\n");
380             status = cStatusAtEOF;
381             break;
382         }
383         default:
384         {
385             vogl_error_printf("Encountered unknown packet type in trace file\n");
386             status = cStatusSoftFailure;
387             break;
388         }
389     }
390
391     if (status < 0)
392     {
393         vogl_error_printf("%s: %s failure processing GL entrypoint packet\n", VOGL_METHOD_NAME, (status == cStatusHardFailure) ? "Hard" : "Soft");
394     }
395
396     return status;
397 }
398
399 //----------------------------------------------------------------------------------------------------------------------
400 // vogl_replayer::process_pending_window_resize
401 //----------------------------------------------------------------------------------------------------------------------
402 vogl_gl_replayer::status_t vogl_gl_replayer::process_pending_window_resize(bool *pApplied_snapshot)
403 {
404     VOGL_FUNC_TRACER
405
406     if (pApplied_snapshot)
407         *pApplied_snapshot = false;
408
409     status_t status = cStatusOK;
410
411     if (get_has_pending_window_resize())
412     {
413         status = process_frame_check_for_pending_window_resize();
414         if (status != cStatusOK)
415             return status;
416     }
417
418     if (m_pPending_snapshot)
419     {
420         if (pApplied_snapshot)
421             *pApplied_snapshot = true;
422
423         status_t status = process_applying_pending_snapshot();
424         if (status != cStatusOK)
425             return status;
426     }
427
428     return cStatusOK;
429 }
430
431 //----------------------------------------------------------------------------------------------------------------------
432 // vogl_replayer::process_frame
433 //----------------------------------------------------------------------------------------------------------------------
434 vogl_gl_replayer::status_t vogl_gl_replayer::process_frame(vogl_trace_file_reader &trace_reader)
435 {
436     VOGL_FUNC_TRACER
437
438     status_t status = cStatusOK;
439
440     for (;;)
441     {
442         status = process_next_packet(trace_reader);
443         if ((status == cStatusNextFrame) || (status == cStatusResizeWindow) || (status == cStatusAtEOF) || (status == cStatusHardFailure))
444             break;
445     }
446
447     return status;
448 }
449
450 //----------------------------------------------------------------------------------------------------------------------
451 // vogl_replayer::process_event
452 //----------------------------------------------------------------------------------------------------------------------
453 bool vogl_gl_replayer::update_window_dimensions()
454 {
455     VOGL_FUNC_TRACER
456
457     m_pWindow->update_dimensions();
458
459     return true;
460 }
461
462 //----------------------------------------------------------------------------------------------------------------------
463 // vogl_gl_replayer::dump_frontbuffer_screenshot_before_next_swap
464 //----------------------------------------------------------------------------------------------------------------------
465 bool vogl_gl_replayer::dump_frontbuffer_screenshot_before_next_swap(const dynamic_string &filename)
466 {
467     m_dump_frontbuffer_filename = filename;
468
469     return true;
470 }
471
472 //----------------------------------------------------------------------------------------------------------------------
473 // vogl_gl_replayer::dump_frontbuffer_to_file
474 //----------------------------------------------------------------------------------------------------------------------
475 bool vogl_gl_replayer::dump_frontbuffer_to_file(const dynamic_string &filename)
476 {
477     if ((!m_is_valid) || (!m_pWindow))
478     {
479         VOGL_ASSERT_ALWAYS;
480         return false;
481     }
482
483     uint width = 0, height = 0;
484     m_pWindow->get_actual_dimensions(width, height);
485
486     m_screenshot_buffer.resize(width * height * 3);
487
488     bool success = vogl_copy_buffer_to_image(m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size(), width, height, GL_RGB, GL_UNSIGNED_BYTE, false, 0, GL_FRONT);
489     if (!success)
490     {
491         vogl_error_printf("%s: Failed calling glReadPixels() to take frontbuffer screenshot!\n", VOGL_METHOD_NAME);
492         return false;
493     }
494
495     size_t png_size = 0;
496     void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(m_screenshot_buffer.get_ptr(), width, height, 3, &png_size, 1, true);
497
498     success = file_utils::write_buf_to_file(filename.get_ptr(), pPNG_data, png_size);
499     if (!success)
500     {
501         vogl_error_printf("%s: Failed writing PNG screenshot to file \"%s\"\n", filename.get_ptr(), VOGL_METHOD_NAME);
502     }
503     else
504     {
505         vogl_message_printf("Wrote PNG screenshot to file \"%s\"\n", filename.get_ptr());
506     }
507
508     mz_free(pPNG_data);
509
510     return success;
511 }
512
513 //----------------------------------------------------------------------------------------------------------------------
514 // vogl_replayer::trigger_pending_window_resize
515 //----------------------------------------------------------------------------------------------------------------------
516 vogl_gl_replayer::status_t vogl_gl_replayer::trigger_pending_window_resize(uint win_width, uint win_height)
517 {
518     VOGL_FUNC_TRACER
519
520     m_pending_window_resize_width = win_width;
521     m_pending_window_resize_height = win_height;
522     m_pending_window_resize_attempt_counter = 0;
523     m_time_since_pending_window_resize.start();
524
525     m_pWindow->resize(win_width, win_height);
526
527     if (m_flags & cGLReplayerVerboseMode)
528         vogl_debug_printf("%s: Waiting for window to resize to %ux%u\n", VOGL_METHOD_NAME, win_width, win_height);
529
530     return cStatusResizeWindow;
531 }
532
533 //----------------------------------------------------------------------------------------------------------------------
534 // vogl_replayer::clear_pending_window_resize
535 //----------------------------------------------------------------------------------------------------------------------
536 void vogl_gl_replayer::clear_pending_window_resize()
537 {
538     VOGL_FUNC_TRACER
539
540     m_pending_window_resize_width = 0;
541     m_pending_window_resize_height = 0;
542     m_pending_window_resize_attempt_counter = 0;
543 }
544
545 //----------------------------------------------------------------------------------------------------------------------
546 // vogl_replayer::process_frame_check_for_pending_window_resize
547 //----------------------------------------------------------------------------------------------------------------------
548 vogl_gl_replayer::status_t vogl_gl_replayer::process_frame_check_for_pending_window_resize()
549 {
550     VOGL_FUNC_TRACER
551
552     const uint cMaxSecsToWait = 5;
553
554     if (!get_has_pending_window_resize())
555         return cStatusOK;
556
557     if (m_pending_window_resize_attempt_counter >= cMaxSecsToWait)
558     {
559         vogl_warning_printf("Waited too long for window to resize to %ux%u, giving up and continuing replay\n", get_pending_window_resize_width(), get_pending_winow_resize_height());
560
561         clear_pending_window_resize();
562
563         return cStatusOK;
564     }
565
566     uint win_width = 0, win_height = 0;
567     m_pWindow->get_actual_dimensions(win_width, win_height);
568
569     if ((win_width != get_pending_window_resize_width()) ||
570         (win_height != get_pending_winow_resize_height()))
571     {
572         if (m_time_since_pending_window_resize.get_elapsed_secs() < 1.0f)
573         {
574             // sleep 1ms, then retry
575             vogl_sleep(1);
576             return cStatusResizeWindow;
577         }
578
579         // What could possibly go wrong?
580         m_pending_window_resize_attempt_counter++;
581         if (m_pending_window_resize_attempt_counter < cMaxSecsToWait)
582         {
583             m_pWindow->resize(get_pending_window_resize_width(), get_pending_winow_resize_height());
584
585             m_time_since_pending_window_resize.start();
586
587             vogl_warning_printf("Waiting up to 5 secs for window to resize to %ux%u\n", get_pending_window_resize_width(), get_pending_winow_resize_height());
588             return cStatusResizeWindow;
589         }
590     }
591
592     clear_pending_window_resize();
593     m_pWindow->update_dimensions();
594
595     return cStatusOK;
596 }
597
598 //----------------------------------------------------------------------------------------------------------------------
599 // vogl_replayer::destroy_pending_snapshot
600 //----------------------------------------------------------------------------------------------------------------------
601 void vogl_gl_replayer::destroy_pending_snapshot()
602 {
603     VOGL_FUNC_TRACER
604
605     if (m_pPending_snapshot)
606     {
607         if (m_delete_pending_snapshot_after_applying)
608         {
609             // Ensure the snapshot cache can't be pointing to the snapshot, just to be safe.
610             // TODO: Make this a real class damn it.
611             for (uint i = 0; i < m_snapshots.size(); i++)
612             {
613                 if (m_snapshots[i].m_pSnapshot == m_pPending_snapshot)
614                 {
615                     m_snapshots.erase(i);
616                     break;
617                 }
618             }
619
620             vogl_delete(const_cast<vogl_gl_state_snapshot *>(m_pPending_snapshot));
621         }
622
623         m_pPending_snapshot = NULL;
624     }
625
626     m_delete_pending_snapshot_after_applying = false;
627 }
628
629 //----------------------------------------------------------------------------------------------------------------------
630 // vogl_replayer::check_gl_error
631 // Returns *true* on error, just like vogl_check_gl_error()
632 //----------------------------------------------------------------------------------------------------------------------
633 bool vogl_gl_replayer::check_gl_error_internal(bool quietly, const char *pFile, uint line, const char *pFunc)
634 {
635     VOGL_FUNC_TRACER
636
637     bool status = false;
638     for (;;)
639     {
640         // http://www.opengl.org/sdk/docs/man/xhtml/glGetError.xml
641         // "Thus, glGetError should always be called in a loop, until it returns GL_NO_ERROR, if all error flags are to be reset."
642         GLenum gl_err = GL_ENTRYPOINT(glGetError)();
643         if (gl_err == GL_NO_ERROR)
644             break;
645
646         if (!quietly)
647         {
648             process_entrypoint_warning("%s: GL error: 0x%08X (%u): %s (Called from File: %s Line: %u Func: %s)\n", VOGL_METHOD_NAME, gl_err, gl_err, g_gl_enums.find_name("ErrorCode", gl_err), pFile ? pFile : "?", line, pFunc ? pFunc : "?");
649         }
650
651         status = true;
652     }
653
654     return status;
655 }
656
657 //----------------------------------------------------------------------------------------------------------------------
658 // vogl_replayer::clear_contexts
659 //----------------------------------------------------------------------------------------------------------------------
660 void vogl_gl_replayer::clear_contexts()
661 {
662     VOGL_FUNC_TRACER
663
664     for (context_hash_map::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
665     {
666         context_state *pContext_state = it->second;
667         it->second = NULL;
668         vogl_delete(pContext_state);
669     }
670
671     m_contexts.clear();
672
673     m_cur_trace_context = 0;
674     m_cur_replay_context = NULL;
675     m_pCur_context_state = NULL;
676 }
677
678 //----------------------------------------------------------------------------------------------------------------------
679 // vogl_replayer::destroy_contexts
680 //----------------------------------------------------------------------------------------------------------------------
681 void vogl_gl_replayer::destroy_contexts()
682 {
683     VOGL_FUNC_TRACER
684
685     if ((m_contexts.size()) && (m_pWindow->get_display()) && (GL_ENTRYPOINT(glXMakeCurrent)) && (GL_ENTRYPOINT(glXDestroyContext)))
686     {
687         GL_ENTRYPOINT(glXMakeCurrent)(m_pWindow->get_display(), (GLXDrawable)NULL, NULL);
688
689         vogl::vector<context_state *> contexts_to_destroy;
690         for (context_hash_map::const_iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
691             contexts_to_destroy.push_back(it->second);
692
693         // Delete "tail" contexts (ones that are not referenced by any other context) in sharegroups first.
694         while (contexts_to_destroy.size())
695         {
696             for (int i = 0; i < static_cast<int>(contexts_to_destroy.size()); i++)
697             {
698                 context_state *pContext_state = contexts_to_destroy[i];
699
700                 vogl_trace_ptr_value trace_context = pContext_state->m_context_desc.get_trace_context();
701
702                 bool skip_context = false;
703                 for (int j = 0; j < static_cast<int>(contexts_to_destroy.size()); j++)
704                 {
705                     if (i == j)
706                         continue;
707
708                     if (contexts_to_destroy[j]->m_context_desc.get_trace_share_context() == trace_context)
709                     {
710                         skip_context = true;
711                         break;
712                     }
713                 }
714
715                 if (skip_context)
716                     continue;
717
718                 // This context may have been the sharegroup's root and could have been already deleted.
719                 if (!pContext_state->m_deleted)
720                 {
721                     GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), pContext_state->m_replay_context);
722                 }
723
724                 contexts_to_destroy.erase(i);
725                 i--;
726             }
727         }
728     }
729
730     clear_contexts();
731 }
732
733 //----------------------------------------------------------------------------------------------------------------------
734 // vogl_replayer::define_new_context
735 //----------------------------------------------------------------------------------------------------------------------
736 vogl_gl_replayer::context_state *vogl_gl_replayer::define_new_context(
737     vogl_trace_context_ptr_value trace_context, GLXContext replay_context, vogl_trace_context_ptr_value trace_share_context, GLboolean direct, gl_entrypoint_id_t creation_func, const int *pAttrib_list, uint attrib_list_size)
738 {
739     VOGL_FUNC_TRACER
740
741     if ((!trace_context) || (!replay_context))
742     {
743         VOGL_ASSERT_ALWAYS;
744         return NULL;
745     }
746
747     context_state *pContext_state = vogl_new(context_state, *this);
748
749     pContext_state->m_trace_context = trace_context;
750     pContext_state->m_replay_context = replay_context;
751
752     pContext_state->m_context_desc.init(creation_func, direct, trace_context, trace_share_context, vogl_context_attribs(pAttrib_list, attrib_list_size));
753
754     if (trace_share_context)
755     {
756         for (context_hash_map::const_iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
757         {
758             if (trace_share_context == it->first)
759             {
760                 context_state *pShare_context = it->second;
761                 while (!pShare_context->is_root_context())
762                     pShare_context = pShare_context->m_pShared_state;
763
764                 pContext_state->m_pShared_state = pShare_context;
765                 pContext_state->m_pShared_state->m_ref_count++;
766
767                 break;
768             }
769         }
770
771         if (!pContext_state->m_pShared_state)
772         {
773             process_entrypoint_error("%s: Unable to find trace share context handle 0x%" PRIX64 "!\n", VOGL_METHOD_NAME, trace_share_context);
774         }
775     }
776
777     m_contexts.insert(trace_context, pContext_state);
778
779     return pContext_state;
780 }
781
782 //----------------------------------------------------------------------------------------------------------------------
783 // vogl_replayer::remap_context
784 //----------------------------------------------------------------------------------------------------------------------
785 GLXContext vogl_gl_replayer::remap_context(vogl_trace_context_ptr_value trace_context)
786 {
787     VOGL_FUNC_TRACER
788
789     if (!trace_context)
790         return NULL;
791
792     context_hash_map::iterator it = m_contexts.find(trace_context);
793     return (it == m_contexts.end()) ? NULL : it->second->m_replay_context;
794 }
795
796 //----------------------------------------------------------------------------------------------------------------------
797 // vogl_replayer::destroy_context
798 //----------------------------------------------------------------------------------------------------------------------
799 bool vogl_gl_replayer::destroy_context(vogl_trace_context_ptr_value trace_context)
800 {
801     VOGL_FUNC_TRACER
802
803     VOGL_ASSERT(trace_context);
804
805     context_hash_map::iterator it = m_contexts.find(trace_context);
806     if (it == m_contexts.end())
807         return false;
808
809     context_state *pContext_state = it->second;
810     VOGL_ASSERT(pContext_state->m_ref_count >= 1);
811     VOGL_ASSERT(!pContext_state->m_deleted);
812
813     if (pContext_state->is_share_context())
814     {
815         VOGL_ASSERT(pContext_state->m_ref_count == 1);
816
817         context_state *pShare_context = pContext_state->m_pShared_state;
818         VOGL_ASSERT(pShare_context->m_ref_count >= 1);
819
820         pShare_context->m_ref_count--;
821         if (!pShare_context->m_ref_count)
822         {
823             VOGL_ASSERT(pShare_context->m_deleted);
824
825             vogl_trace_context_ptr_value trace_share_context = pShare_context->m_context_desc.get_trace_context();
826
827             vogl_delete(pShare_context);
828
829             bool removed = m_contexts.erase(trace_share_context);
830             VOGL_NOTE_UNUSED(removed);
831             VOGL_ASSERT(removed);
832         }
833
834         vogl_delete(pContext_state);
835
836         bool removed = m_contexts.erase(trace_context);
837         VOGL_NOTE_UNUSED(removed);
838         VOGL_ASSERT(removed);
839     }
840     else
841     {
842         pContext_state->m_deleted = true;
843         pContext_state->m_ref_count--;
844
845         if (!pContext_state->m_ref_count)
846         {
847             it->second = NULL;
848
849             vogl_delete(pContext_state);
850
851             bool removed = m_contexts.erase(trace_context);
852             VOGL_NOTE_UNUSED(removed);
853             VOGL_ASSERT(removed);
854         }
855     }
856
857     return true;
858 }
859
860 //----------------------------------------------------------------------------------------------------------------------
861 // vogl_replayer::set_client_side_array_data
862 // glVertexPointer, glNormalPointer, etc. client side data
863 //----------------------------------------------------------------------------------------------------------------------
864 bool vogl_gl_replayer::set_client_side_array_data(const key_value_map &map, GLuint start, GLuint end, GLuint basevertex)
865 {
866     VOGL_FUNC_TRACER
867
868     // TODO: Add early out
869     GLint prev_client_active_texture = 0;
870     GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &prev_client_active_texture);
871
872     const uint tex_coords = math::minimum<uint>(m_pCur_context_state->m_context_info.is_core_profile() ? m_pCur_context_state->m_context_info.get_max_texture_units() : m_pCur_context_state->m_context_info.get_max_texture_coords(), VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS);
873
874     for (uint client_array_iter = 0; client_array_iter < VOGL_NUM_CLIENT_SIDE_ARRAY_DESCS; client_array_iter++)
875     {
876         const vogl_client_side_array_desc_t &desc = g_vogl_client_side_array_descs[client_array_iter];
877
878         const bool is_texcoord_array = (client_array_iter == vogl_texcoord_pointer_array_id);
879
880         uint n = 1;
881         uint base_key_index = 0x1000 + client_array_iter;
882
883         // Special case texcoord pointers, which are accessed via the client active texture.
884         if (is_texcoord_array)
885         {
886             n = tex_coords;
887             base_key_index = 0x2000;
888         }
889
890         for (uint inner_iter = 0; inner_iter < n; inner_iter++)
891         {
892             uint key_index = base_key_index + inner_iter;
893
894             const uint8_vec *pVertex_blob = map.get_blob(static_cast<uint16>(key_index));
895             // TODO: Check for case where blob (or map) is not present, but they still access client side data, this is a bad error
896             if (!pVertex_blob)
897                 continue;
898
899             if (is_texcoord_array)
900             {
901                 GL_ENTRYPOINT(glClientActiveTexture)(GL_TEXTURE0 + inner_iter);
902             }
903
904             GLboolean is_enabled = GL_ENTRYPOINT(glIsEnabled)(desc.m_is_enabled);
905             if (!is_enabled)
906                 continue;
907
908             GLint binding = 0;
909             GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_binding, &binding);
910             if (binding)
911                 continue;
912
913             GLvoid *ptr = NULL;
914             GL_ENTRYPOINT(glGetPointerv)(desc.m_get_pointer, &ptr);
915             if (!ptr)
916                 continue;
917
918             uint8_vec &array_data = is_texcoord_array ? m_client_side_texcoord_data[inner_iter] : m_client_side_array_data[client_array_iter];
919             if (ptr != array_data.get_ptr())
920             {
921                 VOGL_ASSERT_ALWAYS;
922                 return false;
923             }
924
925             GLint type = GL_BOOL;
926             if (desc.m_get_type)
927             {
928                 GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_type, &type);
929             }
930
931             GLint stride = 0;
932             GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_stride, &stride);
933
934             GLint size = 1;
935             if (desc.m_get_size)
936             {
937                 GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_size, &size);
938             }
939
940             uint type_size = vogl_get_gl_type_size(type);
941             if (!type_size)
942             {
943                 process_entrypoint_error("%s: Can't determine type size of enabled client side array set by func %s\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName);
944                 continue;
945             }
946
947             if ((desc.m_entrypoint == VOGL_ENTRYPOINT_glIndexPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glIndexPointerEXT) ||
948                 (desc.m_entrypoint == VOGL_ENTRYPOINT_glFogCoordPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glFogCoordPointerEXT) ||
949                 (desc.m_entrypoint == VOGL_ENTRYPOINT_glEdgeFlagPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glEdgeFlagPointerEXT))
950             {
951                 size = 1;
952             }
953             else if ((desc.m_entrypoint == VOGL_ENTRYPOINT_glNormalPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glNormalPointerEXT))
954             {
955                 size = 3;
956             }
957             else if ((size < 1) && (size > 4))
958             {
959                 process_entrypoint_error("%s: Size of client side array set by func %s must be between 1 and 4\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName);
960                 continue;
961             }
962
963             if (!stride)
964                 stride = type_size * size;
965
966             uint first_vertex_ofs = (start + basevertex) * stride;
967             uint last_vertex_ofs = (end + basevertex) * stride;
968             uint vertex_data_size = (last_vertex_ofs + stride) - first_vertex_ofs;
969             uint total_data_size = last_vertex_ofs + stride;
970
971 #if 0
972                         if (!pVertex_blob)
973                         {
974                                 process_entrypoint_error("%s: Failed finding client side vertex data blob set by func %s \n", VOGL_METHOD_NAME,  g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName);
975                                 continue;
976                         }
977 #endif
978
979             uint8_vec temp_blob;
980             if (vertex_data_size != pVertex_blob->size())
981             {
982                 process_entrypoint_error("%s: %s will access more client side data (%u bytes) than stored in the trace (%u bytes), using what is in the trace and using zeros for the rest\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName, vertex_data_size, pVertex_blob->size());
983                 temp_blob = *pVertex_blob;
984                 temp_blob.resize(vertex_data_size);
985                 pVertex_blob = &temp_blob;
986             }
987
988             uint bytes_remaining_at_end = math::maximum<int>(0, (int)VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE - (int)first_vertex_ofs);
989             uint bytes_to_copy = math::minimum<uint>(pVertex_blob->size(), bytes_remaining_at_end);
990             if (bytes_to_copy != pVertex_blob->size())
991             {
992                 // Can't resize buffer, it could move and that would invalidate any VAO pointer bindings.
993                 process_entrypoint_error("%s: %s accesses too much client side data (%u bytes), increase VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName, first_vertex_ofs + total_data_size);
994             }
995
996             VOGL_ASSERT((first_vertex_ofs + bytes_to_copy) <= array_data.size());
997
998             memcpy(array_data.get_ptr() + first_vertex_ofs, pVertex_blob->get_ptr(), bytes_to_copy);
999         }
1000     }
1001
1002     GL_ENTRYPOINT(glClientActiveTexture)(prev_client_active_texture);
1003
1004     return true;
1005 }
1006
1007 //----------------------------------------------------------------------------------------------------------------------
1008 // vogl_replayer::set_client_side_vertex_attrib_array_data
1009 // glVertexAttrib client side data
1010 //----------------------------------------------------------------------------------------------------------------------
1011 bool vogl_gl_replayer::set_client_side_vertex_attrib_array_data(const key_value_map &map, GLuint start, GLuint end, GLuint basevertex)
1012 {
1013     VOGL_FUNC_TRACER
1014
1015     // TODO: Add early out
1016
1017     for (int vertex_attrib_index = 0; vertex_attrib_index < static_cast<int>(m_pCur_context_state->m_context_info.get_max_vertex_attribs()); vertex_attrib_index++)
1018     {
1019         const uint8_vec *pVertex_blob = map.get_blob(static_cast<uint16>(vertex_attrib_index));
1020
1021         // TODO: Check for case where blob (or map) is not present, but they still access client side data, this is a bad error
1022         if (!pVertex_blob)
1023             continue;
1024
1025         GLint enabled = 0;
1026         GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled);
1027         if (!enabled)
1028             continue;
1029
1030         GLint cur_buf = 0;
1031         GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &cur_buf);
1032         if (cur_buf)
1033             continue;
1034
1035         GLvoid *attrib_ptr = NULL;
1036         GL_ENTRYPOINT(glGetVertexAttribPointerv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_POINTER, &attrib_ptr);
1037         if (!attrib_ptr)
1038             continue;
1039
1040         if (attrib_ptr != m_client_side_vertex_attrib_data[vertex_attrib_index].get_ptr())
1041         {
1042             VOGL_ASSERT_ALWAYS;
1043             continue;
1044         }
1045
1046         GLint attrib_size = 0;
1047         GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_SIZE, &attrib_size);
1048
1049         GLint attrib_type = 0;
1050         GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_TYPE, &attrib_type);
1051
1052         GLint attrib_stride = 0;
1053         GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &attrib_stride);
1054
1055 #if 0
1056                 if (!pVertex_blob)
1057                 {
1058                         process_entrypoint_error("%s: Failed finding client side vertex data blob for generic vertex attrib %u\n", VOGL_METHOD_NAME, vertex_attrib_index);
1059                         continue;
1060                 }
1061 #endif
1062
1063         uint num_comps = 4;
1064         if ((attrib_size != GL_BGRA) && (attrib_size < 1) && (attrib_size > 4))
1065         {
1066             process_entrypoint_error("%s: Enabled vertex attribute index %i has invalid size 0x%0X\n", VOGL_METHOD_NAME, vertex_attrib_index, attrib_size);
1067             continue;
1068         }
1069         if ((attrib_size >= 1) && (attrib_size <= 4))
1070             num_comps = attrib_size;
1071
1072         uint type_size = vogl_get_gl_type_size(attrib_type);
1073         if (!type_size)
1074         {
1075             process_entrypoint_error("%s: Vertex attribute index %i has unsupported type 0x%0X\n", VOGL_METHOD_NAME, vertex_attrib_index, attrib_type);
1076             continue;
1077         }
1078
1079         uint stride = attrib_stride ? attrib_stride : (type_size * num_comps);
1080
1081         uint first_vertex_ofs = (start + basevertex) * stride;
1082         uint last_vertex_ofs = (end + basevertex) * stride;
1083         uint vertex_data_size = (last_vertex_ofs + stride) - first_vertex_ofs;
1084         uint total_data_size = last_vertex_ofs + stride;
1085
1086         uint8_vec temp_blob;
1087         if (vertex_data_size != pVertex_blob->size())
1088         {
1089             process_entrypoint_error("%s: Vertex attribute index %i will access more client side data (%u bytes) than stored in the trace (%u bytes), using what is in the trace and using zeros for the rest\n", VOGL_METHOD_NAME, vertex_attrib_index, vertex_data_size, pVertex_blob->size());
1090             temp_blob = *pVertex_blob;
1091             temp_blob.resize(vertex_data_size);
1092             pVertex_blob = &temp_blob;
1093         }
1094
1095         uint bytes_remaining_at_end = math::maximum<int>(0, (int)VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE - (int)first_vertex_ofs);
1096         uint bytes_to_copy = math::minimum<uint>(pVertex_blob->size(), bytes_remaining_at_end);
1097         if (bytes_to_copy != pVertex_blob->size())
1098         {
1099             // Can't resize buffer, it could move and that would invalidate any VAO pointer bindings.
1100             process_entrypoint_error("%s: Vertex attribute index %i accesses too much client side data (%u bytes), increase VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE\n", VOGL_METHOD_NAME, vertex_attrib_index, first_vertex_ofs + total_data_size);
1101         }
1102
1103         VOGL_ASSERT((first_vertex_ofs + bytes_to_copy) <= m_client_side_vertex_attrib_data[vertex_attrib_index].size());
1104
1105         memcpy(m_client_side_vertex_attrib_data[vertex_attrib_index].get_ptr() + first_vertex_ofs, pVertex_blob->get_ptr(), bytes_to_copy);
1106     }
1107
1108     return true;
1109 }
1110
1111 //----------------------------------------------------------------------------------------------------------------------
1112 // vogl_replayer::draw_elements_client_side_array_setup
1113 //----------------------------------------------------------------------------------------------------------------------
1114 bool vogl_gl_replayer::draw_elements_client_side_array_setup(
1115     GLenum mode,
1116     GLuint start,
1117     GLuint end,
1118     GLsizei count,
1119     GLenum type,
1120     vogl_trace_ptr_value trace_indices_ptr_value, const GLvoid *&pIndices,
1121     GLint basevertex,
1122     bool has_valid_start_end,
1123     bool indexed)
1124 {
1125     VOGL_FUNC_TRACER
1126
1127     VOGL_NOTE_UNUSED(mode);
1128
1129     pIndices = NULL;
1130
1131     GLuint element_array_buffer = 0;
1132     uint index_size = 0;
1133     if (indexed)
1134     {
1135         index_size = vogl_get_gl_type_size(type);
1136         if (!index_size)
1137         {
1138             process_entrypoint_error("%s: Invalid type parameter 0x%08X\n", VOGL_METHOD_NAME, type);
1139             return false;
1140         }
1141
1142         element_array_buffer = vogl_get_bound_gl_buffer(GL_ELEMENT_ARRAY_BUFFER);
1143         if (element_array_buffer)
1144         {
1145             // trace_indices_ptr_value is actually an offset into the buffer, not a real trace ptr
1146             pIndices = reinterpret_cast<GLvoid *>(trace_indices_ptr_value);
1147         }
1148     }
1149
1150     if (count <= 0)
1151     {
1152         process_entrypoint_warning("%s: count parameter is <= 0 (%i)\n", VOGL_METHOD_NAME, count);
1153         return true;
1154     }
1155
1156     const key_value_map &map = m_pCur_gl_packet->get_key_value_map();
1157     if (!map.size())
1158     {
1159         if ((indexed) && (!element_array_buffer) && (trace_indices_ptr_value))
1160         {
1161             process_entrypoint_error("%s: No element array buffer is bound, but key value map doesn't have an indices blob. Can't remap indices pointer!\n", VOGL_METHOD_NAME);
1162             if (trace_indices_ptr_value)
1163             {
1164                 // We can't remap the pointer to valid memory, so give up.
1165                 return false;
1166             }
1167         }
1168
1169         // TODO: Check for client side array usage but no data in blob (which would be a desync or error)
1170         return true;
1171     }
1172
1173     // TODO: If a VAO is bound, client side data isn't supported according to this:
1174     // http://www.opengl.org/registry/specs/ARB/vertex_array_object.txt
1175
1176     //GLint current_vertex_array_binding = 0;
1177     //ACTUAL_GL_ENTRYPOINT(glGetIntegerv)(GL_VERTEX_ARRAY_BINDING, &current_vertex_array_binding);
1178
1179     if ((indexed) && (!element_array_buffer))
1180     {
1181         const uint8_vec *pIndices_vec = map.get_blob(string_hash("indices"));
1182         if (!pIndices_vec)
1183         {
1184             process_entrypoint_error("%s: No element array buffer is bound, but key value map doesn't have an indices blob\n", VOGL_METHOD_NAME);
1185             return false;
1186         }
1187
1188         pIndices = pIndices_vec->get_ptr();
1189         if (!pIndices)
1190         {
1191             process_entrypoint_error("%s: No element array buffer is bound, but key value map has an empty indices blob\n", VOGL_METHOD_NAME);
1192             return false;
1193         }
1194
1195         if ((pIndices_vec->size() / index_size) != static_cast<uint>(count))
1196         {
1197             process_entrypoint_error("%s: Client side index data blob stored in packet is too small (wanted %u indices, got %u indices)\n", VOGL_METHOD_NAME, count, pIndices_vec->size() / index_size);
1198             return false;
1199         }
1200     }
1201
1202     if ((indexed) && (!has_valid_start_end))
1203     {
1204         uint total_index_data_size = count * index_size;
1205
1206         const uint8 *pIndices_to_scan = static_cast<const uint8 *>(pIndices);
1207
1208         if (element_array_buffer)
1209         {
1210             if (m_index_data.size() < total_index_data_size)
1211                 m_index_data.resize(total_index_data_size);
1212
1213             pIndices_to_scan = m_index_data.get_ptr();
1214
1215             check_gl_error();
1216
1217             GL_ENTRYPOINT(glGetBufferSubData)(GL_ELEMENT_ARRAY_BUFFER, (GLintptr)pIndices, total_index_data_size, m_index_data.get_ptr());
1218
1219             if (check_gl_error())
1220             {
1221                 process_entrypoint_warning("%s: GL error while trying to retrieve index buffer data\n", VOGL_METHOD_NAME);
1222
1223                 memset(m_index_data.get_ptr(), 0, total_index_data_size);
1224             }
1225         }
1226
1227         start = cUINT32_MAX;
1228         end = 0;
1229
1230         for (int i = 0; i < count; i++)
1231         {
1232             uint v;
1233
1234             if (type == GL_UNSIGNED_BYTE)
1235                 v = pIndices_to_scan[i];
1236             else if (type == GL_UNSIGNED_SHORT)
1237                 v = reinterpret_cast<const uint16 *>(pIndices_to_scan)[i];
1238             else if (type == GL_UNSIGNED_INT)
1239                 v = reinterpret_cast<const uint32 *>(pIndices_to_scan)[i];
1240             else
1241             {
1242                 process_entrypoint_error("%s: Invalid index type\n", VOGL_METHOD_NAME);
1243                 return false;
1244             }
1245
1246             start = math::minimum(start, v);
1247             end = math::maximum(end, v);
1248         }
1249
1250         has_valid_start_end = true;
1251     }
1252
1253     if (!set_client_side_array_data(map, start, end, basevertex))
1254         return false;
1255
1256     if (!set_client_side_vertex_attrib_array_data(map, start, end, basevertex))
1257         return false;
1258
1259     return true;
1260 }
1261
1262 //----------------------------------------------------------------------------------------------------------------------
1263 // vogl_replayer::determine_uniform_replay_location
1264 //----------------------------------------------------------------------------------------------------------------------
1265 GLint vogl_gl_replayer::determine_uniform_replay_location(GLuint trace_program, GLint trace_location)
1266 {
1267     VOGL_FUNC_TRACER
1268
1269     GLint replay_location = trace_location;
1270
1271     glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_program);
1272     if (it == get_shared_state()->m_glsl_program_hash_map.end())
1273     {
1274         process_entrypoint_warning("%s: Failed looking up current trace program in GLSL program hash map\n", VOGL_METHOD_NAME);
1275     }
1276     else
1277     {
1278         glsl_program_state &state = it->second;
1279
1280         uniform_location_hash_map::const_iterator loc_it = state.m_uniform_locations.find(trace_location);
1281         if (loc_it == state.m_uniform_locations.end())
1282         {
1283             process_entrypoint_warning("%s: Failed looking up uniform location index\n", VOGL_METHOD_NAME);
1284         }
1285         else
1286         {
1287             replay_location = loc_it->second;
1288         }
1289     }
1290     return replay_location;
1291 }
1292
1293 //----------------------------------------------------------------------------------------------------------------------
1294 // vogl_replayer::process_entrypoint_print_summary_context
1295 //----------------------------------------------------------------------------------------------------------------------
1296 void vogl_gl_replayer::process_entrypoint_print_summary_context(eConsoleMessageType msg_type)
1297 {
1298     VOGL_FUNC_TRACER
1299
1300     if (!m_pCur_gl_packet)
1301         return;
1302
1303     console::printf(msg_type, "While processing GL entrypoint packet func %s, frame %u, swaps %u, GL call counter %" PRIu64 ", packet start trace context 0x%" PRIX64 ", cur trace context 0x%" PRIX64 ", trace thread 0x%" PRIX64 ":\n",
1304                     g_vogl_entrypoint_descs[m_pCur_gl_packet->get_entrypoint_id()].m_pName,
1305                     m_frame_index, m_total_swaps,
1306                     m_pCur_gl_packet->get_entrypoint_packet().m_call_counter,
1307                     m_pCur_gl_packet->get_entrypoint_packet().m_context_handle,
1308                     m_cur_trace_context,
1309                     m_pCur_gl_packet->get_entrypoint_packet().m_thread_id);
1310
1311 #if 0
1312         dynamic_string_array backtrace;
1313         if (get_printable_backtrace(backtrace))
1314         {
1315                 console::printf("Backtrace:\n");
1316                 for (uint i = 0; i < backtrace.size(); i++)
1317                         console::printf("%s\n", backtrace[i].get_ptr());
1318         }
1319 #endif
1320 }
1321
1322 //----------------------------------------------------------------------------------------------------------------------
1323 // vogl_replayer::print_detailed_context
1324 //----------------------------------------------------------------------------------------------------------------------
1325 void vogl_gl_replayer::print_detailed_context(eConsoleMessageType msg_type)
1326 {
1327     VOGL_FUNC_TRACER
1328
1329     json_node node;
1330
1331     vogl_loose_file_blob_manager blob_file_manager;
1332     blob_file_manager.init(cBMFWritable);
1333
1334     vogl_trace_packet::json_serialize_params serialize_params;
1335     serialize_params.m_output_basename = "replay_error";
1336     serialize_params.m_cur_frame = m_frame_index;
1337     serialize_params.m_blob_file_size_threshold = 1024;
1338     serialize_params.m_pBlob_manager = (m_flags & cGLReplayerDumpPacketBlobFilesOnError) ? &blob_file_manager : NULL;
1339     m_pCur_gl_packet->json_serialize(node, serialize_params);
1340
1341     dynamic_string node_str;
1342     node.serialize(node_str, true, 0);
1343     console::printf(msg_type, "Packet at call counter %" PRIu64 " as JSON:\n%s\n", m_pCur_gl_packet->get_entrypoint_packet().m_call_counter, node_str.get_ptr());
1344 }
1345
1346 //----------------------------------------------------------------------------------------------------------------------
1347 // vogl_replayer::process_entrypoint_msg_print_detailed_context
1348 //----------------------------------------------------------------------------------------------------------------------
1349 void vogl_gl_replayer::process_entrypoint_msg_print_detailed_context(eConsoleMessageType msg_type)
1350 {
1351     VOGL_FUNC_TRACER
1352
1353     if (!m_pCur_gl_packet)
1354         return;
1355
1356     dump_packet_as_func_call(*m_pCur_gl_packet);
1357
1358     if (!(m_flags & cGLReplayerDumpPacketsOnError))
1359         return;
1360
1361     print_detailed_context(msg_type);
1362 }
1363
1364 //----------------------------------------------------------------------------------------------------------------------
1365 // vogl_replayer::process_entrypoint_info
1366 //----------------------------------------------------------------------------------------------------------------------
1367 void vogl_gl_replayer::process_entrypoint_info(const char *pFmt, ...)
1368 {
1369     VOGL_FUNC_TRACER
1370
1371     process_entrypoint_print_summary_context(cInfoConsoleMessage);
1372
1373     va_list args;
1374     va_start(args, pFmt);
1375     console::vprintf(cInfoConsoleMessage, pFmt, args);
1376     va_end(args);
1377
1378     process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1379 }
1380
1381 //----------------------------------------------------------------------------------------------------------------------
1382 // vogl_replayer::process_entrypoint_message
1383 //----------------------------------------------------------------------------------------------------------------------
1384 void vogl_gl_replayer::process_entrypoint_message(const char *pFmt, ...)
1385 {
1386     VOGL_FUNC_TRACER
1387
1388     process_entrypoint_print_summary_context(cMessageConsoleMessage);
1389
1390     va_list args;
1391     va_start(args, pFmt);
1392     console::vprintf(cMessageConsoleMessage, pFmt, args);
1393     va_end(args);
1394
1395     process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1396 }
1397
1398 //----------------------------------------------------------------------------------------------------------------------
1399 // vogl_replayer::process_entrypoint_warning
1400 //----------------------------------------------------------------------------------------------------------------------
1401 void vogl_gl_replayer::process_entrypoint_warning(const char *pFmt, ...)
1402 {
1403     VOGL_FUNC_TRACER
1404
1405     process_entrypoint_print_summary_context(cWarningConsoleMessage);
1406
1407     va_list args;
1408     va_start(args, pFmt);
1409     console::vprintf(cWarningConsoleMessage, pFmt, args);
1410     va_end(args);
1411
1412     process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1413 }
1414
1415 //----------------------------------------------------------------------------------------------------------------------
1416 // vogl_replayer::process_entrypoint_error
1417 //----------------------------------------------------------------------------------------------------------------------
1418 void vogl_gl_replayer::process_entrypoint_error(const char *pFmt, ...)
1419 {
1420     VOGL_FUNC_TRACER
1421
1422     process_entrypoint_print_summary_context(cErrorConsoleMessage);
1423
1424     va_list args;
1425     va_start(args, pFmt);
1426     console::vprintf(cErrorConsoleMessage, pFmt, args);
1427     va_end(args);
1428
1429     process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1430 }
1431
1432 //----------------------------------------------------------------------------------------------------------------------
1433 // vogl_replayer::switch_contexts
1434 //----------------------------------------------------------------------------------------------------------------------
1435 vogl_gl_replayer::status_t vogl_gl_replayer::switch_contexts(vogl_trace_context_ptr_value trace_context)
1436 {
1437     VOGL_FUNC_TRACER
1438
1439     // HACK HACK
1440     //if (m_pCur_gl_packet->get_call_counter() == 25583)
1441     //    vogl_debug_break();
1442
1443     //vogl_trace_context_ptr_value trace_context = gl_packet.m_context_handle;
1444     if (trace_context == m_cur_trace_context)
1445         return cStatusOK;
1446
1447     if (m_flags & cGLReplayerDebugMode)
1448     {
1449         process_entrypoint_message("%s: Forcing context switch via glXMakeCurrent, from current trace context 0x%" PRIX64 " to new context 0x%" PRIX64 "\n", VOGL_METHOD_NAME, cast_val_to_uint64(m_cur_trace_context), cast_val_to_uint64(trace_context));
1450     }
1451
1452     // pContext_state will be NULL if they are unmapping!
1453     context_state *pContext_state = get_trace_context_state(trace_context);
1454     GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
1455
1456     const Display *dpy = m_pWindow->get_display();
1457     GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
1458
1459     Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
1460     if (!result)
1461     {
1462         process_entrypoint_error("%s: Failed switching current trace context to 0x%" PRIX64 "\n", VOGL_METHOD_NAME, trace_context);
1463         return cStatusHardFailure;
1464     }
1465
1466     m_cur_trace_context = trace_context;
1467     m_cur_replay_context = replay_context;
1468     m_pCur_context_state = pContext_state;
1469
1470     return cStatusOK;
1471 }
1472
1473 //----------------------------------------------------------------------------------------------------------------------
1474 // vogl_replayer::debug_callback_arb
1475 //----------------------------------------------------------------------------------------------------------------------
1476 void vogl_gl_replayer::debug_callback_arb(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *pUser_param)
1477 {
1478     VOGL_FUNC_TRACER
1479
1480     VOGL_NOTE_UNUSED(length);
1481
1482     char final_message[4096];
1483
1484     context_state *pContext_state = (context_state *)(pUser_param);
1485
1486     vogl_format_debug_output_arb(final_message, sizeof(final_message), source, type, id, severity, reinterpret_cast<const char *>(message));
1487
1488     if (pContext_state)
1489     {
1490         vogl_warning_printf("%s: Trace context: 0x%" PRIX64 ", Replay context 0x%" PRIX64 ", Last trace call counter: %" PRIu64 "\n%s\n", VOGL_FUNCTION_NAME,
1491                            cast_val_to_uint64(pContext_state->m_trace_context), cast_val_to_uint64(pContext_state->m_replay_context), cast_val_to_uint64(pContext_state->m_last_call_counter), final_message);
1492     }
1493     else
1494     {
1495         vogl_warning_printf("%s: %s\n", VOGL_FUNCTION_NAME, final_message);
1496     }
1497 }
1498
1499 //----------------------------------------------------------------------------------------------------------------------
1500 // vogl_replayer::is_extension_supported
1501 //----------------------------------------------------------------------------------------------------------------------
1502 bool vogl_gl_replayer::is_extension_supported(const char *pExt)
1503 {
1504     VOGL_FUNC_TRACER
1505
1506     if ((m_pCur_context_state) && (m_pCur_context_state->m_context_info.is_valid()))
1507     {
1508         return m_pCur_context_state->m_context_info.supports_extension(pExt);
1509     }
1510
1511     VOGL_ASSERT_ALWAYS;
1512
1513     return true;
1514 }
1515
1516 //----------------------------------------------------------------------------------------------------------------------
1517 // vogl_replayer::context_state::handle_context_made_current
1518 //----------------------------------------------------------------------------------------------------------------------
1519 bool vogl_gl_replayer::context_state::handle_context_made_current()
1520 {
1521     VOGL_FUNC_TRACER
1522
1523     if (m_has_been_made_current)
1524         return true;
1525
1526     VOGL_CHECK_GL_ERROR;
1527
1528     m_has_been_made_current = true;
1529
1530     if (!m_context_info.init(m_context_desc))
1531     {
1532         vogl_error_printf("%s: vogl_context_info::init() failed!\n", VOGL_METHOD_NAME);
1533         return false;
1534     }
1535
1536     if (!m_context_info.get_max_vertex_attribs())
1537     {
1538         vogl_warning_printf("%s: GL_MAX_VERTEX_ATTRIBS is 0\n", VOGL_METHOD_NAME);
1539     }
1540     else if (m_context_info.get_max_vertex_attribs() >= VOGL_MAX_SUPPORTED_GL_VERTEX_ATTRIBUTES)
1541     {
1542         vogl_error_printf("%s: GL_MAX_VERTEX_ATTRIBS is too large, max supported is %u. Please increase VOGL_MAX_SUPPORTED_GL_VERTEX_ATTRIBUTES.\n", VOGL_METHOD_NAME, VOGL_MAX_SUPPORTED_GL_VERTEX_ATTRIBUTES);
1543         return false;
1544     }
1545
1546     if (m_replayer.m_flags & cGLReplayerLowLevelDebugMode)
1547     {
1548         vogl_debug_printf("%s: Creating dummy handles\n", VOGL_METHOD_NAME);
1549
1550         // HACK HACK
1551         // Generate a bunch of replay handles, so the trace and replay namespaces are totally different to shake out handle or target remapping bugs
1552         // TODO: All more object types
1553         vogl::vector<GLuint> dummy_handles(65536);
1554
1555         GL_ENTRYPOINT(glGenTextures)(4000, dummy_handles.get_ptr());
1556         GL_ENTRYPOINT(glGenBuffers)(6000, dummy_handles.get_ptr());
1557         GL_ENTRYPOINT(glGenLists)(8000);
1558         GL_ENTRYPOINT(glGenQueries)(10000, dummy_handles.get_ptr());
1559
1560         GL_ENTRYPOINT(glGenVertexArrays)(12000, dummy_handles.get_ptr());
1561         GL_ENTRYPOINT(glGenProgramsARB)(14000, dummy_handles.get_ptr());
1562         GL_ENTRYPOINT(glGenFramebuffers)(16000, dummy_handles.get_ptr());
1563         GL_ENTRYPOINT(glGenSamplers)(18000, dummy_handles.get_ptr());
1564         GL_ENTRYPOINT(glGenRenderbuffers)(20000, dummy_handles.get_ptr());
1565
1566         for (uint i = 0; i < 22000; i++)
1567             GL_ENTRYPOINT(glCreateProgram)();
1568
1569         vogl_debug_printf("%s: Finished creating dummy handles\n", VOGL_METHOD_NAME);
1570     }
1571
1572     VOGL_CHECK_GL_ERROR;
1573
1574     return true;
1575 }
1576
1577 //----------------------------------------------------------------------------------------------------------------------
1578 // vogl_replayer::handle_context_made_current
1579 //----------------------------------------------------------------------------------------------------------------------
1580 bool vogl_gl_replayer::handle_context_made_current()
1581 {
1582     VOGL_FUNC_TRACER
1583
1584     if (!m_pCur_context_state->handle_context_made_current())
1585         return false;
1586
1587     if ((m_pCur_context_state->m_context_info.is_debug_context()) && (GL_ENTRYPOINT(glDebugMessageCallbackARB)) && (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_debug_output")))
1588     {
1589         GL_ENTRYPOINT(glDebugMessageCallbackARB)(debug_callback_arb, (GLvoid *)m_pCur_context_state);
1590         GL_ENTRYPOINT(glEnable)(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
1591         check_gl_error();
1592     }
1593
1594     if (m_flags & cGLReplayerVerboseMode)
1595     {
1596         vogl_debug_printf("%s: Trace context: 0x%" PRIX64 ", replay context 0x%" PRIX64 ", GL_VERSION: %s\n",
1597                          VOGL_METHOD_NAME,
1598                          (uint64_t)m_cur_trace_context,
1599                          (uint64_t)m_cur_replay_context,
1600                          m_pCur_context_state->m_context_info.get_version_str().get_ptr());
1601     }
1602
1603     return true;
1604 }
1605
1606 //----------------------------------------------------------------------------------------------------------------------
1607 // vogl_replayer::dump_context_attrib_list
1608 //----------------------------------------------------------------------------------------------------------------------
1609 void vogl_gl_replayer::dump_context_attrib_list(const int *pAttrib_list, uint size)
1610 {
1611     VOGL_FUNC_TRACER
1612
1613     if (!pAttrib_list)
1614     {
1615         vogl_debug_printf("Attrib list is NULL\n");
1616         return;
1617     }
1618     vogl_debug_printf("Context attribs:\n");
1619
1620     uint ofs = 0;
1621     for (;;)
1622     {
1623         if (ofs >= size)
1624         {
1625             vogl_error_printf("%s: Attrib list ended prematurely (must end in a 0 key)\n", VOGL_METHOD_NAME);
1626             break;
1627         }
1628
1629         uint key = pAttrib_list[ofs];
1630         if (!key)
1631             break;
1632         ofs++;
1633
1634         if (ofs >= size)
1635         {
1636             vogl_error_printf("%s: Attrib list ended prematurely (must end in a 0 key)\n", VOGL_METHOD_NAME);
1637             break;
1638         }
1639
1640         uint value = pAttrib_list[ofs];
1641         ofs++;
1642
1643         vogl_debug_printf("Key: %s (0x%08X), Value: 0x%08X\n", g_gl_enums.find_name(key, "GLX"), key, value);
1644     }
1645     vogl_debug_printf("End of context attribs\n");
1646 }
1647
1648 //----------------------------------------------------------------------------------------------------------------------
1649 // vogl_replayer::find_attrib_key
1650 //----------------------------------------------------------------------------------------------------------------------
1651 int vogl_gl_replayer::find_attrib_key(const vogl::vector<int> &attrib_list, int key_to_find)
1652 {
1653     VOGL_FUNC_TRACER
1654
1655     uint ofs = 0;
1656     while (ofs < attrib_list.size())
1657     {
1658         int key = attrib_list[ofs];
1659         if (!key)
1660             break;
1661
1662         if (++ofs >= attrib_list.size())
1663         {
1664             process_entrypoint_warning("%s: Failed parsing attrib list, this call is probably going to fail\n", VOGL_METHOD_NAME);
1665             break;
1666         }
1667
1668         if (key == key_to_find)
1669             return ofs;
1670         ofs++;
1671     }
1672
1673     return -1;
1674 }
1675
1676 //----------------------------------------------------------------------------------------------------------------------
1677 // vogl_replayer::create_context_attribs
1678 //----------------------------------------------------------------------------------------------------------------------
1679 vogl_gl_replayer::status_t vogl_gl_replayer::create_context_attribs(
1680     vogl_trace_context_ptr_value trace_context, Display *dpy, GLXFBConfig config, vogl_trace_context_ptr_value trace_share_context, GLXContext replay_share_context, Bool direct,
1681     const int *pTrace_attrib_list, int trace_attrib_list_size, bool expecting_attribs)
1682 {
1683     VOGL_FUNC_TRACER
1684
1685     vogl::vector<int> temp_attrib_list;
1686
1687     if ((pTrace_attrib_list) && (trace_attrib_list_size))
1688     {
1689         temp_attrib_list.append(pTrace_attrib_list, trace_attrib_list_size);
1690         if (temp_attrib_list.back() != 0)
1691         {
1692             process_entrypoint_warning("%s: attrib list does not end with 0\n", VOGL_METHOD_NAME);
1693         }
1694     }
1695     else
1696     {
1697         if (expecting_attribs)
1698         {
1699             if (m_flags & cGLReplayerVerboseMode)
1700                 process_entrypoint_message("%s: No attrib list found in trace, assuming an attrib list ending with 0\n", VOGL_METHOD_NAME);
1701         }
1702
1703         temp_attrib_list.push_back(0);
1704     }
1705
1706     if (m_flags & cGLReplayerForceDebugContexts)
1707     {
1708         // See http://www.opengl.org/registry/specs/ARB/glx_create_context.txt
1709         int context_flags_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_FLAGS_ARB);
1710         if (context_flags_ofs < 0)
1711         {
1712             temp_attrib_list.back() = GLX_CONTEXT_FLAGS_ARB;
1713             temp_attrib_list.push_back(GLX_CONTEXT_DEBUG_BIT_ARB);
1714             temp_attrib_list.push_back(0);
1715
1716             if (m_flags & cGLReplayerVerboseMode)
1717                 process_entrypoint_warning("%s: Appending GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB to attrib list to enable debug context\n", VOGL_METHOD_NAME);
1718         }
1719         else
1720         {
1721             temp_attrib_list[context_flags_ofs] |= GLX_CONTEXT_DEBUG_BIT_ARB;
1722
1723             if (m_flags & cGLReplayerVerboseMode)
1724                 process_entrypoint_warning("%s: Slamming on GLX_CONTEXT_DEBUG_BIT_ARB bit to enable debug context\n", VOGL_METHOD_NAME);
1725         }
1726
1727         int context_major_version_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_MAJOR_VERSION_ARB);
1728         int context_minor_version_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_MINOR_VERSION_ARB);
1729
1730         bool slammed_up_to_3_0 = false;
1731         if (context_major_version_ofs < 0)
1732         {
1733 // Don't slam up if they haven't requested a specific GL version, the driver will give us the most recent version that is backwards compatible with 1.0 (i.e. 4.3 for NVidia's current dirver).
1734 #if 0
1735                         temp_attrib_list.back() = GLX_CONTEXT_MAJOR_VERSION_ARB;
1736                         temp_attrib_list.push_back(3);
1737                         temp_attrib_list.push_back(0);
1738
1739                         slammed_up_to_3_0 = true;
1740 #endif
1741         }
1742         else if (temp_attrib_list[context_major_version_ofs] < 3)
1743         {
1744             temp_attrib_list[context_major_version_ofs] = 3;
1745
1746             slammed_up_to_3_0 = true;
1747         }
1748
1749         if (slammed_up_to_3_0)
1750         {
1751             if (context_minor_version_ofs < 0)
1752             {
1753                 temp_attrib_list.back() = GLX_CONTEXT_MINOR_VERSION_ARB;
1754                 temp_attrib_list.push_back(0);
1755                 temp_attrib_list.push_back(0);
1756             }
1757             else
1758             {
1759                 temp_attrib_list[context_minor_version_ofs] = 0;
1760             }
1761
1762             process_entrypoint_warning("%s: Forcing GL context version up to 3.0 due to debug context usage\n", VOGL_METHOD_NAME);
1763         }
1764     }
1765
1766     const int *pAttrib_list = temp_attrib_list.get_ptr();
1767     const uint attrib_list_size = temp_attrib_list.size();
1768
1769     if (m_flags & cGLReplayerVerboseMode)
1770         dump_context_attrib_list(pAttrib_list, attrib_list_size);
1771
1772     GLXContext replay_context = GL_ENTRYPOINT(glXCreateContextAttribsARB)(dpy, config, replay_share_context, direct, pAttrib_list);
1773     if (!replay_context)
1774     {
1775         if (trace_context)
1776         {
1777             process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
1778             return cStatusHardFailure;
1779         }
1780         else
1781         {
1782             process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
1783         }
1784     }
1785
1786     if (replay_context)
1787     {
1788         if (trace_context)
1789         {
1790             context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateContextAttribsARB, pAttrib_list, attrib_list_size);
1791             VOGL_NOTE_UNUSED(pContext_state);
1792         }
1793         else
1794         {
1795             GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
1796         }
1797     }
1798
1799     return cStatusOK;
1800 }
1801
1802 //----------------------------------------------------------------------------------------------------------------------
1803 // vogl_replayer::process_pending_make_current
1804 //----------------------------------------------------------------------------------------------------------------------
1805 vogl_gl_replayer::status_t vogl_gl_replayer::process_pending_make_current()
1806 {
1807     VOGL_FUNC_TRACER
1808
1809     if (!m_pending_make_current_packet.is_valid())
1810         return cStatusOK;
1811
1812     vogl_trace_packet &gl_packet = m_pending_make_current_packet;
1813
1814     Bool trace_result = gl_packet.get_return_value<Bool>();
1815
1816     gl_entrypoint_id_t entrypoint_id = gl_packet.get_entrypoint_id();
1817     VOGL_ASSERT((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) || (entrypoint_id == VOGL_ENTRYPOINT_glXMakeContextCurrent));
1818
1819     // pContext_state will be NULL if they are unmapping!
1820     vogl_trace_ptr_value trace_context = gl_packet.get_param_ptr_value((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) ? 2 : 3);
1821     context_state *pContext_state = get_trace_context_state(trace_context);
1822     GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
1823
1824     if ((trace_context) && (!replay_context))
1825     {
1826         process_entrypoint_error("%s, Failed remapping GL context\n", VOGL_METHOD_NAME);
1827         m_pending_make_current_packet.clear();
1828         return cStatusHardFailure;
1829     }
1830
1831     const Display *dpy = m_pWindow->get_display();
1832     GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
1833
1834     Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
1835     if (!result)
1836     {
1837         if (trace_result)
1838         {
1839             process_entrypoint_error("%s: Failed making context current, but in the trace this call succeeded!\n", VOGL_METHOD_NAME);
1840             m_pending_make_current_packet.clear();
1841             return cStatusHardFailure;
1842         }
1843         else
1844         {
1845             process_entrypoint_warning("%s: Failed making context current, in the trace this call also failed\n", VOGL_METHOD_NAME);
1846         }
1847     }
1848     else
1849     {
1850         m_cur_trace_context = trace_context;
1851         m_cur_replay_context = replay_context;
1852         m_pCur_context_state = pContext_state;
1853
1854         if (!trace_result)
1855         {
1856             process_entrypoint_warning("%s: Context was successfuly made current, but this operation failed in the trace\n", VOGL_METHOD_NAME);
1857         }
1858
1859         if (m_cur_replay_context)
1860         {
1861             int viewport_x = gl_packet.get_key_value_map().get_int(string_hash("viewport_x"));
1862             int viewport_y = gl_packet.get_key_value_map().get_int(string_hash("viewport_y"));
1863             int viewport_width = gl_packet.get_key_value_map().get_int(string_hash("viewport_width"));
1864             int viewport_height = gl_packet.get_key_value_map().get_int(string_hash("viewport_height"));
1865             int win_width = gl_packet.get_key_value_map().get_int(string_hash("win_width"));
1866             int win_height = gl_packet.get_key_value_map().get_int(string_hash("win_height"));
1867
1868             if (!m_pCur_context_state->m_has_been_made_current)
1869             {
1870                 vogl_printf("glXMakeCurrent(): Trace Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
1871                            viewport_x, viewport_y,
1872                            viewport_width, viewport_height,
1873                            win_width, win_height);
1874             }
1875
1876             GLint cur_viewport[4];
1877             GL_ENTRYPOINT(glGetIntegerv)(GL_VIEWPORT, cur_viewport);
1878
1879             uint cur_win_width = 0, cur_win_height = 0;
1880             m_pWindow->get_actual_dimensions(cur_win_width, cur_win_height);
1881
1882             if (!m_pCur_context_state->m_has_been_made_current)
1883             {
1884                 vogl_printf("glXMakeCurrent(): Replay Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
1885                            cur_viewport[0], cur_viewport[1],
1886                            cur_viewport[2], cur_viewport[3],
1887                            cur_win_width, cur_win_height);
1888             }
1889
1890             if ((cur_viewport[0] != viewport_x) || (cur_viewport[1] != viewport_y) || (cur_viewport[2] != viewport_width) || (cur_viewport[3] != viewport_height))
1891             {
1892                 process_entrypoint_warning("%s: Replay viewport differs from traces!\n", VOGL_METHOD_NAME);
1893             }
1894
1895             if (!handle_context_made_current())
1896                 return cStatusHardFailure;
1897         }
1898     }
1899
1900     m_last_processed_call_counter = gl_packet.get_call_counter();
1901
1902     m_pending_make_current_packet.clear();
1903
1904     return cStatusOK;
1905 }
1906
1907 //----------------------------------------------------------------------------------------------------------------------
1908 // vogl_process_internal_trace_command_ctypes_packet
1909 //----------------------------------------------------------------------------------------------------------------------
1910 bool vogl_process_internal_trace_command_ctypes_packet(const key_value_map &kvm, const vogl_ctypes &ctypes)
1911 {
1912     VOGL_FUNC_TRACER
1913
1914     // TODO: Implement the code to map trace ctypes to replay ctypes. That's going to be fun.
1915     int num_trace_ctypes = kvm.get_int("num_ctypes");
1916     VOGL_VERIFY(num_trace_ctypes == VOGL_NUM_CTYPES);
1917
1918     // TODO: This just verifies that the replayer's idea of each ctype matches the tracer's.
1919     // This will need to be revisited once we port to other OS's.
1920     // TODO: Move the ctypes crap into the SOF packet or something, it's not easy to deal with this packet on the fly.
1921     for (int ctype_iter = 0; ctype_iter < num_trace_ctypes; ctype_iter++)
1922     {
1923         const vogl_ctype_desc_t &desc = ctypes[static_cast<vogl_ctype_t>(ctype_iter)];
1924
1925         uint base_index = ctype_iter << 8;
1926         dynamic_string name(kvm.get_string(base_index++));
1927         dynamic_string ctype(kvm.get_string(base_index++));
1928         int size = kvm.get_int(base_index++);
1929         uint loki_type_flags = kvm.get_uint(base_index++);
1930         bool is_pointer = kvm.get_bool(base_index++);
1931         bool is_opaque_pointer = kvm.get_bool(base_index++);
1932         bool is_pointer_diff = kvm.get_bool(base_index++);
1933         bool is_opaque_type = kvm.get_bool(base_index++);
1934
1935         VOGL_VERIFY(name.compare(desc.m_pName, true) == 0);
1936         VOGL_VERIFY(ctype.compare(desc.m_pCType, true) == 0);
1937         if (!desc.m_is_opaque_type)
1938         {
1939             VOGL_VERIFY(size == desc.m_size);
1940         }
1941
1942         const uint loki_type_check_mask = ~(LOKI_TYPE_BITMASK(LOKI_IS_SIGNED_LONG) | LOKI_TYPE_BITMASK(LOKI_IS_UNSIGNED_LONG));
1943         VOGL_VERIFY((loki_type_flags & loki_type_check_mask) == (desc.m_loki_type_flags & loki_type_check_mask));
1944
1945         VOGL_VERIFY(is_pointer == desc.m_is_pointer);
1946         VOGL_VERIFY(is_opaque_pointer == desc.m_is_opaque_pointer);
1947         VOGL_VERIFY(is_pointer_diff == desc.m_is_pointer_diff);
1948         VOGL_VERIFY(is_opaque_type == desc.m_is_opaque_type);
1949     }
1950
1951     return true;
1952 }
1953
1954 //----------------------------------------------------------------------------------------------------------------------
1955 // vogl_replayer::process_internal_trace_command
1956 //----------------------------------------------------------------------------------------------------------------------
1957 vogl_gl_replayer::status_t vogl_gl_replayer::process_internal_trace_command(const vogl_trace_gl_entrypoint_packet &gl_packet)
1958 {
1959     VOGL_FUNC_TRACER
1960
1961     VOGL_NOTE_UNUSED(gl_packet);
1962
1963     GLuint cmd = m_pCur_gl_packet->get_param_value<GLuint>(0);
1964     GLuint size = m_pCur_gl_packet->get_param_value<GLuint>(1);
1965     VOGL_NOTE_UNUSED(size);
1966     vogl_trace_ptr_value trace_data_ptr_value = m_pCur_gl_packet->get_param_ptr_value(2);
1967     VOGL_NOTE_UNUSED(trace_data_ptr_value);
1968
1969     vogl_gl_replayer::status_t status = cStatusOK;
1970
1971     switch (cmd)
1972     {
1973         case cITCRDemarcation:
1974         {
1975             break;
1976         }
1977         case cITCRKeyValueMap:
1978         {
1979             const key_value_map &kvm = m_pCur_gl_packet->get_key_value_map();
1980
1981             dynamic_string cmd_type(kvm.get_string("command_type"));
1982             if (cmd_type == "state_snapshot")
1983             {
1984                 dynamic_string text_id(kvm.get_string("id"));
1985                 dynamic_string binary_id(kvm.get_string("binary_id"));
1986                 if (text_id.is_empty() && binary_id.is_empty())
1987                 {
1988                     process_entrypoint_error("%s: Missing id and binary_id fields in glInternalTraceCommandRAD key_value_map command type: \"%s\"\n", VOGL_METHOD_NAME, cmd_type.get_ptr());
1989                     return cStatusHardFailure;
1990                 }
1991
1992                 dynamic_string id_to_use(text_id.is_empty() ? binary_id : text_id);
1993
1994                 // TODO: Make a 1st class snapshot cache class
1995                 // TODO: This could fail if the user hand modifies the snapshot in some way - add an option to disable caching.
1996                 vogl_gl_state_snapshot *pSnapshot = NULL;
1997                 if (m_flags & cGLReplayerSnapshotCaching)
1998                 {
1999                     for (uint snapshot_index = 0; snapshot_index < m_snapshots.size(); snapshot_index++)
2000                     {
2001                         if (!m_snapshots[snapshot_index].m_name.compare(id_to_use, false))
2002                         {
2003                             pSnapshot = m_snapshots[snapshot_index].m_pSnapshot;
2004                             if (snapshot_index)
2005                             {
2006                                 snapshot_cache_entry cache_entry(m_snapshots[snapshot_index]);
2007                                 m_snapshots.erase(snapshot_index);
2008                                 m_snapshots.insert(0, cache_entry);
2009                             }
2010                             break;
2011                         }
2012                     }
2013                 }
2014
2015                 if (!pSnapshot)
2016                 {
2017                     timed_scope ts("Deserialize snapshot time");
2018
2019                     if (!m_pBlob_manager)
2020                     {
2021                         process_entrypoint_error("%s: Failed reading snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2022                         return cStatusHardFailure;
2023                     }
2024
2025                     uint8_vec snapshot_data;
2026
2027                     if (!m_pBlob_manager->get(id_to_use, snapshot_data) || (snapshot_data.is_empty()))
2028                     {
2029                         process_entrypoint_error("%s: Failed reading snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2030                         return cStatusHardFailure;
2031                     }
2032
2033                     vogl_message_printf("%s: Deserializing state snapshot \"%s\", %u bytes\n", VOGL_METHOD_NAME, id_to_use.get_ptr(), snapshot_data.size());
2034
2035                     json_document doc;
2036
2037                     bool success;
2038                     if (id_to_use == text_id)
2039                         success = doc.deserialize(reinterpret_cast<const char *>(snapshot_data.get_ptr()), snapshot_data.size());
2040                     else
2041                         success = doc.binary_deserialize(snapshot_data);
2042                     if (!success || (!doc.get_root()))
2043                     {
2044                         process_entrypoint_error("%s: Failed deserializing JSON snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2045                         return cStatusHardFailure;
2046                     }
2047
2048                     pSnapshot = vogl_new(vogl_gl_state_snapshot);
2049                     if (!pSnapshot->deserialize(*doc.get_root(), *m_pBlob_manager, &m_trace_gl_ctypes))
2050                     {
2051                         vogl_delete(pSnapshot);
2052                         pSnapshot = NULL;
2053
2054                         process_entrypoint_error("%s: Failed deserializing snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2055                         return cStatusHardFailure;
2056                     }
2057
2058                     if (m_flags & cGLReplayerSnapshotCaching)
2059                     {
2060                         snapshot_cache_entry new_cache_entry;
2061                         new_cache_entry.m_name = id_to_use;
2062                         new_cache_entry.m_pSnapshot = pSnapshot;
2063                         m_snapshots.insert(0, new_cache_entry);
2064
2065                         // FIXME: Even 3-4 snapshots in memory may be too much in 32-bit mode for some large apps.
2066                         while (m_snapshots.size() > 3)
2067                         {
2068                             vogl_delete(m_snapshots.back().m_pSnapshot);
2069                             m_snapshots.resize(m_snapshots.size() - 1);
2070                         }
2071                     }
2072                 }
2073
2074                 status = begin_applying_snapshot(pSnapshot, (m_flags & cGLReplayerSnapshotCaching) ? false : true);
2075
2076                 if ((status != cStatusOK) && (status != cStatusResizeWindow))
2077                 {
2078                     if (m_flags & cGLReplayerSnapshotCaching)
2079                     {
2080                         VOGL_ASSERT(m_snapshots[0].m_pSnapshot == pSnapshot);
2081
2082                         vogl_delete(m_snapshots[0].m_pSnapshot);
2083                         m_snapshots.erase(0U);
2084                     }
2085
2086                     if (m_flags & cGLReplayerSnapshotCaching)
2087                     {
2088                         vogl_delete(pSnapshot);
2089                         pSnapshot = NULL;
2090                     }
2091
2092                     process_entrypoint_error("%s: Failed applying GL snapshot from blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2093                     return status;
2094                 }
2095
2096                 vogl_message_printf("%s: Successfully applied GL state snapshot from blob \"%s\"\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2097             }
2098             else if (cmd_type == "ctypes")
2099             {
2100                 m_ctypes_packet = *m_pCur_gl_packet;
2101
2102                 if (!vogl_process_internal_trace_command_ctypes_packet(kvm, m_trace_gl_ctypes))
2103                     return cStatusHardFailure;
2104             }
2105             else if (cmd_type == "entrypoints")
2106             {
2107                 // TODO
2108             }
2109             else
2110             {
2111                 process_entrypoint_warning("%s: Unknown glInternalTraceCommandRAD key_value_map command type: \"%s\"\n", VOGL_METHOD_NAME, cmd_type.get_ptr());
2112             }
2113             break;
2114         }
2115         default:
2116         {
2117             process_entrypoint_warning("%s: Unknown glInternalTraceCommandRAD command type: %u\n", VOGL_METHOD_NAME, cmd);
2118             break;
2119         }
2120     }
2121
2122     return status;
2123 }
2124
2125 //----------------------------------------------------------------------------------------------------------------------
2126 // vogl_replayer::check_program_binding_shadow
2127 //----------------------------------------------------------------------------------------------------------------------
2128 bool vogl_gl_replayer::check_program_binding_shadow()
2129 {
2130     VOGL_FUNC_TRACER
2131
2132     if (!m_pCur_context_state)
2133         return true;
2134
2135     // Make sure shadow is good
2136     GLint actual_current_replay_program = 0;
2137     GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &actual_current_replay_program);
2138     check_gl_error();
2139
2140     if (m_pCur_context_state->m_cur_replay_program == static_cast<GLuint>(actual_current_replay_program))
2141         return true;
2142
2143     // OK, on AMD it plays games with GL_CURRENT_PROGRAM when the currently bound program is deleted. Check for this scenario.
2144     bool is_still_program = GL_ENTRYPOINT(glIsProgram)(m_pCur_context_state->m_cur_replay_program) != 0;
2145     if ((!check_gl_error()) && (is_still_program))
2146     {
2147         GLint marked_for_deletion = GL_FALSE;
2148         GL_ENTRYPOINT(glGetProgramiv)(m_pCur_context_state->m_cur_replay_program, GL_DELETE_STATUS, &marked_for_deletion);
2149
2150         if ((!check_gl_error()) && (marked_for_deletion))
2151             return true;
2152     }
2153
2154     VOGL_VERIFY(0);
2155     return false;
2156 }
2157
2158 //----------------------------------------------------------------------------------------------------------------------
2159 // vogl_replayer::handle_use_program
2160 //----------------------------------------------------------------------------------------------------------------------
2161 void vogl_gl_replayer::handle_use_program(GLuint trace_handle, gl_entrypoint_id_t entrypoint_id)
2162 {
2163     VOGL_FUNC_TRACER
2164
2165     // TODO: This code assumes the non-ARB entrypoints are being used, which works fine on NV but who knows what'll happen on other drivers.
2166     check_program_binding_shadow();
2167
2168     GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2169     VOGL_ASSERT(!trace_handle || get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_PROGRAM_OBJECT);
2170     VOGL_ASSERT(!trace_handle || get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_PROGRAM_OBJECT);
2171
2172     // For safety, absorb any previous error.
2173     check_gl_error();
2174
2175     GLuint prev_replay_program = m_pCur_context_state->m_cur_replay_program;
2176     GLuint prev_trace_program = m_pCur_context_state->m_cur_trace_program;
2177
2178     bool prev_is_program = false;
2179     GLint prev_link_status = false;
2180     GLint prev_is_marked_for_deletion = false;
2181     vogl::growable_array<GLuint, 8> prev_attached_replay_shaders;
2182
2183     if ((prev_replay_program) && (replay_handle != prev_replay_program))
2184     {
2185         prev_is_program = GL_ENTRYPOINT(glIsProgram)(prev_replay_program);
2186         check_gl_error_quietly();
2187
2188         if (prev_is_program)
2189         {
2190             GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_DELETE_STATUS, &prev_is_marked_for_deletion);
2191             check_gl_error_quietly();
2192
2193             GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_LINK_STATUS, &prev_link_status);
2194             check_gl_error_quietly();
2195
2196             if (prev_is_marked_for_deletion)
2197             {
2198                 // The currently bound program is marked for deletion, so record which shaders are attached to it in case the program is actually deleted by the driver on the UseProgram() call.
2199                 GLint num_attached_shaders = 0;
2200                 GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_ATTACHED_SHADERS, &num_attached_shaders);
2201                 check_gl_error_quietly();
2202
2203                 if (num_attached_shaders)
2204                 {
2205                     prev_attached_replay_shaders.resize(num_attached_shaders);
2206
2207                     GLsizei actual_count = 0;
2208                     GL_ENTRYPOINT(glGetAttachedShaders)(prev_replay_program, num_attached_shaders, &actual_count, prev_attached_replay_shaders.get_ptr());
2209                     check_gl_error_quietly();
2210
2211                     VOGL_ASSERT(actual_count == num_attached_shaders);
2212                 }
2213             }
2214         }
2215     }
2216
2217     if (entrypoint_id == VOGL_ENTRYPOINT_glUseProgram)
2218         GL_ENTRYPOINT(glUseProgram)(replay_handle);
2219     else
2220         GL_ENTRYPOINT(glUseProgramObjectARB)(replay_handle);
2221
2222     // Can't shadow if glUseProgram failed.
2223     if (check_gl_error())
2224         return;
2225
2226     if ((prev_replay_program) && (prev_replay_program != replay_handle))
2227     {
2228         bool is_prev_still_program = GL_ENTRYPOINT(glIsProgram)(prev_replay_program);
2229         if (!is_prev_still_program)
2230         {
2231             VOGL_ASSERT(prev_is_program);
2232             VOGL_ASSERT(prev_is_marked_for_deletion);
2233
2234             // The previously bound program is really dead now, kill it from our tables and also check up on any shaders it was attached to.
2235             bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(prev_trace_program);
2236             VOGL_ASSERT(was_deleted);
2237             VOGL_NOTE_UNUSED(was_deleted);
2238
2239             was_deleted = get_shared_state()->m_glsl_program_hash_map.erase(prev_trace_program);
2240             VOGL_ASSERT(was_deleted);
2241
2242             was_deleted = get_shared_state()->m_shadow_state.m_linked_programs.remove_snapshot(prev_replay_program);
2243             if ((prev_link_status) && (!was_deleted))
2244             {
2245                 VOGL_ASSERT_ALWAYS;
2246             }
2247
2248             for (uint i = 0; i < prev_attached_replay_shaders.size(); i++)
2249             {
2250                 GLuint replay_shader_handle = prev_attached_replay_shaders[i];
2251
2252                 bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_shader_handle);
2253                 check_gl_error_quietly();
2254
2255                 if (is_still_shader)
2256                     continue;
2257
2258                 if (!get_shared_state()->m_shadow_state.m_objs.contains_inv(replay_shader_handle))
2259                 {
2260                     // We didn't create this shader handle, the AMD driver did on a program binary link, so ignore it.
2261                     continue;
2262                 }
2263
2264                 // The attached shader is now really dead.
2265                 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_shader_handle) == VOGL_SHADER_OBJECT);
2266                 if (!get_shared_state()->m_shadow_state.m_objs.erase_inv(replay_shader_handle))
2267                 {
2268                     process_entrypoint_error("%s: Failed finding attached GL shader %u in objects hash table, while handling the actual deletion of trace program %u replay program %u\n", VOGL_METHOD_NAME, replay_shader_handle, prev_trace_program, prev_replay_program);
2269                 }
2270             }
2271         }
2272     }
2273
2274     m_pCur_context_state->m_cur_replay_program = replay_handle;
2275     m_pCur_context_state->m_cur_trace_program = trace_handle;
2276 }
2277
2278 //----------------------------------------------------------------------------------------------------------------------
2279 // vogl_replayer::handle_delete_program
2280 //----------------------------------------------------------------------------------------------------------------------
2281 void vogl_gl_replayer::handle_delete_program(GLuint trace_handle)
2282 {
2283     VOGL_FUNC_TRACER
2284
2285     check_program_binding_shadow();
2286
2287     // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2288
2289     GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2290     VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_PROGRAM_OBJECT);
2291     VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_PROGRAM_OBJECT);
2292
2293     context_state *pContext_shareroot = m_pCur_context_state->m_pShared_state;
2294     for (context_hash_map::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
2295     {
2296         if (it->first == m_pCur_context_state->m_context_desc.get_trace_context())
2297             continue;
2298
2299         context_state *pContext = it->second;
2300         if (pContext->m_pShared_state == pContext_shareroot)
2301         {
2302             if (pContext->m_cur_trace_program == trace_handle)
2303             {
2304                 process_entrypoint_error("%s: Trace program %u replay program %u is being deleted on context 0x%" PRIx64 ", but it's currently bound to trace context 0x%" PRIx64 "! This scenario is not currently supported with sharelists.\n",
2305                                          VOGL_METHOD_NAME, trace_handle, replay_handle,
2306                                          cast_val_to_uint64(m_pCur_context_state->m_context_desc.get_trace_context()),
2307                                          cast_val_to_uint64(it->first));
2308             }
2309         }
2310     }
2311
2312     bool is_program = GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0;
2313     check_gl_error_quietly();
2314
2315     vogl::growable_array<GLuint, 8> attached_replay_shaders;
2316
2317     if ((is_program) && (replay_handle))
2318     {
2319         GLint num_attached_shaders = 0;
2320         GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_ATTACHED_SHADERS, &num_attached_shaders);
2321         check_gl_error_quietly();
2322
2323         if (num_attached_shaders)
2324         {
2325             attached_replay_shaders.resize(num_attached_shaders);
2326
2327             GLsizei actual_count = 0;
2328             GL_ENTRYPOINT(glGetAttachedShaders)(replay_handle, num_attached_shaders, &actual_count, attached_replay_shaders.get_ptr());
2329             check_gl_error_quietly();
2330
2331             VOGL_ASSERT(actual_count == num_attached_shaders);
2332         }
2333     }
2334
2335     GL_ENTRYPOINT(glDeleteProgram)(replay_handle);
2336
2337     bool deletion_succeeded = !check_gl_error();
2338     if (!deletion_succeeded)
2339     {
2340         VOGL_ASSERT(!is_program);
2341
2342         process_entrypoint_warning("%s: Failed deleting program, trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2343         return;
2344     }
2345
2346     if (!replay_handle)
2347         return;
2348
2349     bool is_still_program = GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0;
2350     check_gl_error_quietly();
2351
2352     GLint marked_for_deletion = 0;
2353     if (is_still_program)
2354     {
2355         // It must still be bound to the context, or referred to in some other way that we don't know about.
2356         GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_DELETE_STATUS, &marked_for_deletion);
2357         bool delete_status_check_succeeded = !check_gl_error_quietly();
2358
2359         VOGL_VERIFY(delete_status_check_succeeded);
2360         VOGL_VERIFY(marked_for_deletion);
2361     }
2362     else if (!is_still_program)
2363     {
2364         VOGL_ASSERT(is_program);
2365
2366         // The program is really gone now.
2367         bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_handle);
2368         VOGL_ASSERT(was_deleted);
2369         VOGL_NOTE_UNUSED(was_deleted);
2370
2371         was_deleted = get_shared_state()->m_glsl_program_hash_map.erase(trace_handle);
2372         VOGL_ASSERT(was_deleted);
2373
2374         get_shared_state()->m_shadow_state.m_linked_programs.remove_snapshot(replay_handle);
2375
2376         if (m_pCur_context_state->m_cur_replay_program == replay_handle)
2377         {
2378             // This shouldn't happen - if the program is still bound to the context then it should still be a program.
2379             VOGL_ASSERT_ALWAYS;
2380             m_pCur_context_state->m_cur_replay_program = 0;
2381             m_pCur_context_state->m_cur_trace_program = 0;
2382         }
2383
2384         for (uint i = 0; i < attached_replay_shaders.size(); i++)
2385         {
2386             GLuint replay_shader_handle = attached_replay_shaders[i];
2387
2388             bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_shader_handle) != 0;
2389             check_gl_error_quietly();
2390
2391             if (is_still_shader)
2392                 continue;
2393
2394             if (!get_shared_state()->m_shadow_state.m_objs.contains_inv(replay_shader_handle))
2395             {
2396                 // We didn't create this shader handle, the AMD driver did on a program binary link, so ignore it.
2397                 continue;
2398             }
2399
2400             // The attached shader is now really dead.
2401             VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_shader_handle) == VOGL_SHADER_OBJECT);
2402             if (!get_shared_state()->m_shadow_state.m_objs.erase_inv(replay_shader_handle))
2403             {
2404                 process_entrypoint_error("%s: Failed finding attached GL shader %u in objects hash table, while handling the actual deletion of trace program %u replay program %u\n", VOGL_METHOD_NAME, replay_shader_handle, trace_handle, replay_handle);
2405             }
2406         }
2407     }
2408 }
2409
2410 //----------------------------------------------------------------------------------------------------------------------
2411 // vogl_replayer::handle_delete_shader
2412 //----------------------------------------------------------------------------------------------------------------------
2413 void vogl_gl_replayer::handle_delete_shader(GLuint trace_handle)
2414 {
2415     VOGL_FUNC_TRACER
2416
2417     check_program_binding_shadow();
2418
2419     check_gl_error();
2420
2421     // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2422
2423     GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2424     VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_SHADER_OBJECT);
2425     VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_SHADER_OBJECT);
2426
2427     GL_ENTRYPOINT(glDeleteShader)(replay_handle);
2428
2429     bool deletion_succeeded = !check_gl_error();
2430     if (!deletion_succeeded)
2431     {
2432         process_entrypoint_warning("%s: Failed deleting shader, trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2433         return;
2434     }
2435
2436     if (!replay_handle)
2437         return;
2438
2439     bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_handle);
2440     check_gl_error_quietly();
2441
2442     if (!is_still_shader)
2443     {
2444         // The shader is really gone.
2445         bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_handle);
2446         VOGL_ASSERT(was_deleted);
2447         VOGL_NOTE_UNUSED(was_deleted);
2448     }
2449     else
2450     {
2451         GLint marked_for_deletion = 0;
2452         GL_ENTRYPOINT(glGetShaderiv)(replay_handle, GL_DELETE_STATUS, &marked_for_deletion);
2453         check_gl_error_quietly();
2454
2455         VOGL_VERIFY(marked_for_deletion);
2456
2457         // The shader is attached to a live program object (which may or may not be actually in the marked_as_deleted state)
2458         // we'll get around to it when the program object is deleted, or when they remove the program object from the current state.
2459     }
2460 }
2461
2462 //----------------------------------------------------------------------------------------------------------------------
2463 // vogl_replayer::handle_detach_shader
2464 //----------------------------------------------------------------------------------------------------------------------
2465 void vogl_gl_replayer::handle_detach_shader(gl_entrypoint_id_t entrypoint_id)
2466 {
2467     GLuint trace_program = m_pCur_gl_packet->get_param_value<GLuint>(0);
2468     GLuint replay_program = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_program);
2469
2470     GLuint trace_shader = m_pCur_gl_packet->get_param_value<GLuint>(1);
2471     GLuint replay_shader = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_shader);
2472
2473     check_gl_error();
2474
2475     // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2476
2477     GLboolean was_shader = GL_ENTRYPOINT(glIsShader)(replay_shader);
2478     check_gl_error_quietly();
2479
2480     GLint marked_for_deletion = 0;
2481     GL_ENTRYPOINT(glGetShaderiv)(replay_shader, GL_DELETE_STATUS, &marked_for_deletion);
2482     check_gl_error_quietly();
2483
2484     if (entrypoint_id == VOGL_ENTRYPOINT_glDetachObjectARB)
2485         GL_ENTRYPOINT(glDetachObjectARB)(replay_program, replay_shader);
2486     else
2487     {
2488         VOGL_ASSERT(entrypoint_id == VOGL_ENTRYPOINT_glDetachShader);
2489         GL_ENTRYPOINT(glDetachShader)(replay_program, replay_shader);
2490     }
2491
2492     bool detach_failed = check_gl_error();
2493
2494     GLboolean is_shader = GL_ENTRYPOINT(glIsShader)(replay_shader);
2495     check_gl_error_quietly();
2496
2497     if (!detach_failed)
2498     {
2499         if ((marked_for_deletion) && (was_shader) && (!is_shader))
2500         {
2501             // The shader is really gone now.
2502             bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_shader);
2503             VOGL_ASSERT(was_deleted);
2504             VOGL_NOTE_UNUSED(was_deleted);
2505         }
2506     }
2507 }
2508
2509 //----------------------------------------------------------------------------------------------------------------------
2510 // vogl_gl_replayer::handle_link_program
2511 //----------------------------------------------------------------------------------------------------------------------
2512 void vogl_gl_replayer::handle_link_program(gl_entrypoint_id_t entrypoint_id)
2513 {
2514     check_gl_error();
2515
2516     GLuint trace_handle = m_pCur_gl_packet->get_param_value<GLuint>(0);
2517     GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2518
2519     GLboolean is_program = GL_ENTRYPOINT(glIsProgram)(replay_handle);
2520     check_gl_error();
2521     if (!is_program)
2522     {
2523         process_entrypoint_warning("%s: Handle is not a program, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2524     }
2525
2526     const json_document *pDoc = m_pCur_gl_packet->get_key_value_map().get_json_document("metadata");
2527
2528     if (!pDoc)
2529     {
2530         process_entrypoint_warning("%s: JSON metadata document is missing, program will be linked without setting its attributes or initializing the uniform location shadow, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2531     }
2532     else if ((pDoc) && (!pDoc->is_object()))
2533     {
2534         process_entrypoint_warning("%s: JSON metadata document must be an object, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2535         pDoc = NULL;
2536     }
2537
2538     int trace_active_attributes = 0;
2539     int trace_active_uniforms = 0;
2540     int trace_active_uniform_blocks = 0;
2541     int trace_link_status = 1;
2542
2543     VOGL_NOTE_UNUSED(trace_active_uniforms);
2544     VOGL_NOTE_UNUSED(trace_active_uniform_blocks);
2545
2546     if (pDoc)
2547     {
2548         const json_node &doc_root = *pDoc->get_root();
2549
2550         trace_link_status = doc_root.value_as_int("link_status");
2551         trace_active_attributes = doc_root.value_as_int("total_active_attributes");
2552         trace_active_uniforms = doc_root.value_as_int("total_active_uniforms");
2553         trace_active_uniform_blocks = doc_root.value_as_int("active_uniform_blocks");
2554
2555         const json_node *pAttrib_node = doc_root.find_child_array("active_attribs");
2556         if (pAttrib_node)
2557         {
2558             for (uint i = 0; i < pAttrib_node->size(); i++)
2559             {
2560                 const json_node *pAttrib = pAttrib_node->get_child(i);
2561                 if (!pAttrib)
2562                 {
2563                     VOGL_ASSERT_ALWAYS;
2564                     continue;
2565                 }
2566
2567                 const char *pName = pAttrib->value_as_string_ptr("name");
2568                 int attrib_loc = pAttrib->value_as_int("location", -1);
2569
2570                 if ((pName) && (pName[0]) && (attrib_loc >= 0))
2571                 {
2572                     if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2573                         GL_ENTRYPOINT(glBindAttribLocationARB)(replay_handle, attrib_loc, pName);
2574                     else
2575                         GL_ENTRYPOINT(glBindAttribLocation)(replay_handle, attrib_loc, reinterpret_cast<const GLchar *>(pName));
2576
2577                     check_gl_error();
2578                 }
2579             }
2580         }
2581
2582         const json_node *pOutputs_object = doc_root.find_child_array("active_outputs");
2583         if (pOutputs_object)
2584         {
2585             for (uint i = 0; i < pOutputs_object->size(); i++)
2586             {
2587                 const json_node *pOutput_node = pOutputs_object->get_child(i);
2588                 if (!pOutput_node)
2589                     continue;
2590
2591                 dynamic_string name(pOutput_node->value_as_string("name"));
2592                 if ((name.is_empty()) || (name.begins_with("gl_", true)))
2593                     continue;
2594
2595                 int location = pOutput_node->value_as_int("location");
2596                 int location_index = pOutput_node->value_as_int("location_index");
2597
2598                 if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_blend_func_extended") && GL_ENTRYPOINT(glBindFragDataLocationIndexed))
2599                 {
2600                     GL_ENTRYPOINT(glBindFragDataLocationIndexed)(replay_handle, location, location_index, reinterpret_cast<const GLchar *>(name.get_ptr()));
2601                 }
2602                 else
2603                 {
2604                     if (location_index)
2605                         process_entrypoint_error("%s: GL_ARB_blend_func_extended is not supported, but trace program %u GL program %u uses a non-zero location index\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2606
2607                     GL_ENTRYPOINT(glBindFragDataLocation)(replay_handle, location, reinterpret_cast<const GLchar *>(name.get_ptr()));
2608                 }
2609
2610                 check_gl_error();
2611             }
2612         }
2613
2614         GLenum transform_feedback_mode = vogl_get_json_value_as_enum(doc_root, "transform_feedback_mode");
2615         GLint num_varyings = doc_root.value_as_int("transform_feedback_num_varyings");
2616         if (num_varyings)
2617         {
2618             const json_node *pTransform_feedback_varyings = doc_root.find_child_array("transform_feedback_varyings");
2619             if (pTransform_feedback_varyings)
2620             {
2621                 dynamic_string_array names;
2622
2623                 for (uint i = 0; i < pTransform_feedback_varyings->size(); i++)
2624                 {
2625                     const json_node *pVarying_node = pTransform_feedback_varyings->get_child(i);
2626                     if (!pVarying_node)
2627                         continue;
2628
2629                     GLint index = pVarying_node->value_as_int("index");
2630                     if (index < 0)
2631                         continue;
2632
2633                     dynamic_string name(pVarying_node->value_as_string("name"));
2634
2635                     //GLsizei size(pVarying_node->value_as_int("size"));
2636                     //GLenum type(vogl_get_json_value_as_enum(*pVarying_node, "type"));
2637
2638                     names.ensure_element_is_valid(index);
2639                     names[index] = name;
2640                 }
2641
2642                 vogl::vector<GLchar *> varyings(names.size());
2643                 for (uint i = 0; i < names.size(); i++)
2644                     varyings[i] = (GLchar *)(names[i].get_ptr());
2645
2646                 GL_ENTRYPOINT(glTransformFeedbackVaryings)(replay_handle, varyings.size(), varyings.get_ptr(), transform_feedback_mode);
2647                 check_gl_error();
2648             }
2649         }
2650     }
2651
2652     switch (entrypoint_id)
2653     {
2654         case VOGL_ENTRYPOINT_glLinkProgram:
2655         {
2656             GL_ENTRYPOINT(glLinkProgram)(replay_handle);
2657             break;
2658         }
2659         case VOGL_ENTRYPOINT_glLinkProgramARB:
2660         {
2661             GL_ENTRYPOINT(glLinkProgramARB)(replay_handle);
2662             break;
2663         }
2664         case VOGL_ENTRYPOINT_glProgramBinary:
2665         {
2666             GL_ENTRYPOINT(glProgramBinary)(replay_handle, m_pCur_gl_packet->get_param_value<GLenum>(1), m_pCur_gl_packet->get_param_client_memory<GLvoid>(2), m_pCur_gl_packet->get_param_value<GLsizei>(3));
2667             break;
2668         }
2669         default:
2670         {
2671             VOGL_ASSERT_ALWAYS;
2672             return;
2673         }
2674     }
2675
2676     check_gl_error();
2677
2678     GLint replay_link_status = 0;
2679     GLint replay_active_attributes = 0;
2680     if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2681     {
2682         GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_LINK_STATUS_ARB, &replay_link_status);
2683         check_gl_error();
2684
2685         GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &replay_active_attributes);
2686         check_gl_error();
2687     }
2688     else
2689     {
2690         GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_LINK_STATUS, &replay_link_status);
2691         check_gl_error();
2692
2693         GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_ACTIVE_ATTRIBUTES, &replay_active_attributes);
2694         check_gl_error();
2695     }
2696
2697     if ((replay_link_status) || (!get_shared_state()->m_shadow_state.m_linked_programs.find_snapshot(replay_handle)))
2698     {
2699         bool success;
2700         if (entrypoint_id == VOGL_ENTRYPOINT_glProgramBinary)
2701             success = get_shared_state()->m_shadow_state.m_linked_programs.add_snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, replay_handle, m_pCur_gl_packet->get_param_value<GLenum>(1), m_pCur_gl_packet->get_param_client_memory<GLvoid>(2), m_pCur_gl_packet->get_param_value<GLsizei>(3));
2702         else
2703             success = get_shared_state()->m_shadow_state.m_linked_programs.add_snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, replay_handle);
2704
2705         if (!success)
2706             process_entrypoint_warning("%s: Failed inserting into link time program shadow, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2707     }
2708
2709     if ((pDoc) && (replay_link_status != trace_link_status))
2710     {
2711         process_entrypoint_warning("%s: Trace link status (%i) differs from replay link status (%i), trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_link_status, replay_link_status, trace_handle, replay_handle);
2712     }
2713
2714     if (!replay_link_status)
2715     {
2716         vogl::vector<GLchar> log;
2717
2718         if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2719         {
2720             GLsizei length = 0;
2721             GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
2722             check_gl_error();
2723
2724             if (length)
2725             {
2726                 log.resize(length);
2727
2728                 GLint actual_length = 0;
2729                 GL_ENTRYPOINT(glGetInfoLogARB)(replay_handle, log.size(), &actual_length, reinterpret_cast<GLcharARB *>(log.get_ptr()));
2730                 check_gl_error();
2731             }
2732         }
2733         else
2734         {
2735             GLint length = 0;
2736             GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_INFO_LOG_LENGTH, &length);
2737             check_gl_error();
2738
2739             if (length)
2740             {
2741                 log.resize(length);
2742
2743                 GL_ENTRYPOINT(glGetShaderInfoLog)(replay_handle, log.size(), &length, log.get_ptr());
2744                 check_gl_error();
2745             }
2746         }
2747
2748         if ((log.size()) && (log[0]))
2749         {
2750             process_entrypoint_message("%s: Info log for trace object %u, replay object %u:\n%s\n", VOGL_METHOD_NAME, trace_handle, replay_handle, log.get_ptr());
2751         }
2752     }
2753
2754     if ((pDoc) && (replay_active_attributes != trace_active_attributes))
2755     {
2756         process_entrypoint_warning("%s: Number of trace active attributes (%i) differs from number of replay active attributes (%i) after linking program, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_active_attributes, replay_active_attributes, trace_handle, replay_handle);
2757     }
2758
2759     const json_node *pUniforms_node = pDoc ? pDoc->get_root()->find_child_array("active_uniforms") : NULL;
2760
2761     if (pUniforms_node)
2762     {
2763         glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
2764         if (it == get_shared_state()->m_glsl_program_hash_map.end())
2765             it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
2766         glsl_program_state &prog_state = it->second;
2767
2768         for (uint i = 0; i < pUniforms_node->size(); i++)
2769         {
2770             const json_node *pUniform = pUniforms_node->get_child(i);
2771             if (!pUniform)
2772             {
2773                 VOGL_ASSERT_ALWAYS;
2774                 continue;
2775             }
2776
2777             const char *pName = pUniform->value_as_string_ptr("name");
2778             if (!pName)
2779             {
2780                 VOGL_ASSERT_ALWAYS;
2781                 continue;
2782             }
2783             int trace_loc = pUniform->value_as_int("location");
2784             int trace_array_size = pUniform->value_as_int("size");
2785             //int trace_type = pUniform->value_as_int("type");
2786
2787             VOGL_ASSERT(trace_array_size >= 1);
2788
2789             if ((trace_loc < 0) || (trace_array_size <= 0))
2790                 continue;
2791
2792             if (trace_array_size > 1)
2793             {
2794                 dynamic_string element_name;
2795                 for (int i = 0; i < trace_array_size; i++)
2796                 {
2797                     element_name = pName;
2798                     int start_bracket_ofs = element_name.find_right('[');
2799                     if (start_bracket_ofs >= 0)
2800                         element_name.left(start_bracket_ofs);
2801                     element_name.format_append("[%u]", i);
2802
2803                     GLint element_trace_loc = trace_loc + i;
2804                     GLint element_replay_loc;
2805                     if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2806                         element_replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, reinterpret_cast<const GLcharARB *>(element_name.get_ptr()));
2807                     else
2808                         element_replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, reinterpret_cast<const GLchar *>(element_name.get_ptr()));
2809                     check_gl_error();
2810
2811                     if (element_replay_loc < 0)
2812                     {
2813                         process_entrypoint_warning("%s: glGetUniformLocation: Trace active array uniform %s trace location %i trace array size %i is not active during replay, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, element_name.get_ptr(), trace_loc, trace_array_size, trace_handle, replay_handle);
2814                     }
2815                     else
2816                     {
2817                         prog_state.m_uniform_locations.erase(element_trace_loc);
2818                         prog_state.m_uniform_locations.insert(element_trace_loc, element_replay_loc);
2819                     }
2820                 }
2821             }
2822             else if (trace_array_size == 1)
2823             {
2824                 GLint replay_loc;
2825                 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2826                     replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, reinterpret_cast<const GLcharARB *>(pName));
2827                 else
2828                     replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, reinterpret_cast<const GLchar *>(pName));
2829                 check_gl_error();
2830
2831                 if (replay_loc < 0)
2832                 {
2833                     process_entrypoint_warning("%s: glGetUniformLocation: Trace active uniform %s trace location %i is not active during replay, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, pName, trace_loc, trace_handle, replay_handle);
2834                 }
2835                 else
2836                 {
2837                     prog_state.m_uniform_locations.erase(trace_loc);
2838                     prog_state.m_uniform_locations.insert(trace_loc, replay_loc);
2839                 }
2840             }
2841         } // i
2842     }
2843 }
2844
2845 //----------------------------------------------------------------------------------------------------------------------
2846 // vogl_gl_replayer::post_draw_call
2847 // Called after each draw call or blit.
2848 //----------------------------------------------------------------------------------------------------------------------
2849 vogl_gl_replayer::status_t vogl_gl_replayer::post_draw_call()
2850 {
2851     VOGL_FUNC_TRACER
2852
2853     if (m_pCur_context_state->m_inside_gl_begin)
2854         return cStatusOK;
2855
2856     if (check_gl_error())
2857         return cStatusGLError;
2858
2859     bool is_draw = vogl_is_draw_entrypoint(m_pCur_gl_packet->get_entrypoint_id());
2860
2861     if ((m_flags & cGLReplayerDumpShadersOnDraw) && (is_draw))
2862     {
2863         dump_current_shaders();
2864     }
2865
2866     if (m_flags & cGLReplayerDumpFramebufferOnDraws)
2867     {
2868         bool should_dump = false;
2869
2870         if (m_dump_framebuffer_on_draw_frame_index != -1)
2871         {
2872             if (m_frame_index == m_dump_framebuffer_on_draw_frame_index)
2873                 should_dump = true;
2874         }
2875         else if ((m_dump_framebuffer_on_draw_first_gl_call_index >= 0) && (m_dump_framebuffer_on_draw_last_gl_call_index >= 0))
2876         {
2877             should_dump = math::is_within_closed_range<uint64_t>(m_last_parsed_call_counter, m_dump_framebuffer_on_draw_first_gl_call_index, m_dump_framebuffer_on_draw_last_gl_call_index);
2878         }
2879         else
2880         {
2881             should_dump = true;
2882         }
2883
2884         if (should_dump)
2885         {
2886             dump_current_framebuffer();
2887         }
2888     }
2889
2890     m_frame_draw_counter += is_draw;
2891
2892     return cStatusOK;
2893 }
2894
2895 //----------------------------------------------------------------------------------------------------------------------
2896 // vogl_gl_replayer::dump_framebuffer
2897 //----------------------------------------------------------------------------------------------------------------------
2898 bool vogl_gl_replayer::dump_framebuffer(uint width, uint height, GLuint read_framebuffer, GLenum read_buffer, GLenum internal_format, uint orig_samples, GLuint replay_texture, GLuint replay_rbo)
2899 {
2900     VOGL_FUNC_TRACER
2901
2902     uint trace_read_framebuffer = 0;
2903     if (read_framebuffer)
2904     {
2905         gl_handle_hash_map::const_iterator it = get_context_state()->m_framebuffers.search_table_for_value(read_framebuffer);
2906         if (it != get_context_state()->m_framebuffers.end())
2907             trace_read_framebuffer = it->second;
2908     }
2909
2910     uint trace_texture = replay_texture;
2911     if (replay_texture)
2912     {
2913         if (!get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_texture, trace_texture))
2914             vogl_warning_printf("%s: Failed finding GL handle %u in texture handle shadow!\n", VOGL_METHOD_NAME, replay_texture);
2915     }
2916
2917     uint trace_rbo = 0;
2918     if (replay_rbo)
2919     {
2920         if (!get_shared_state()->m_shadow_state.m_rbos.map_inv_handle_to_handle(replay_rbo, trace_rbo))
2921             vogl_error_printf("%s: Failed finding GL handle %u in RBO handle shadow!\n", VOGL_METHOD_NAME, replay_rbo);
2922     }
2923
2924     m_screenshot_buffer.resize(width * height * 3);
2925
2926     bool success = vogl_copy_buffer_to_image(m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size(), width, height, GL_RGB, GL_UNSIGNED_BYTE, false, read_framebuffer, read_buffer, 0);
2927
2928     if (!success)
2929     {
2930         process_entrypoint_warning("%s: vogl_copy_buffer_to_image() failed!\n", VOGL_METHOD_NAME);
2931         return false;
2932     }
2933
2934     size_t png_size = 0;
2935     void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(m_screenshot_buffer.get_ptr(), width, height, 3, &png_size, 1, true);
2936
2937     dynamic_string screenshot_filename(cVarArg, "%s_GLCTR%08llu_%s_FR%06u_DCTR%05llu_W%04i_H%04i_FBO%04u_%s",
2938                                        m_dump_framebuffer_on_draw_prefix.get_ptr(),
2939                                        (unsigned long long)m_pCur_gl_packet->get_call_counter(),
2940                                        g_vogl_entrypoint_descs[m_pCur_gl_packet->get_entrypoint_id()].m_pName,
2941                                        m_frame_index,
2942                                        (unsigned long long)m_frame_draw_counter,
2943                                        width, height,
2944                                        trace_read_framebuffer,
2945                                        g_gl_enums.find_gl_name(read_buffer));
2946
2947     if (internal_format != GL_NONE)
2948     {
2949         screenshot_filename += "_";
2950         screenshot_filename += g_gl_enums.find_gl_image_format_name(internal_format);
2951     }
2952
2953     if (orig_samples != 0)
2954         screenshot_filename += dynamic_string(cVarArg, "_MSAA%u", orig_samples);
2955     if (replay_texture)
2956         screenshot_filename += dynamic_string(cVarArg, "_TEX%04u", replay_texture);
2957     if (replay_rbo)
2958         screenshot_filename += dynamic_string(cVarArg, "_RBO%04u", replay_rbo);
2959
2960     screenshot_filename += ".png";
2961
2962     file_utils::create_directories(file_utils::get_pathname(screenshot_filename.get_ptr()), false);
2963
2964     if (!file_utils::write_buf_to_file(screenshot_filename.get_ptr(), pPNG_data, png_size))
2965     {
2966         process_entrypoint_error("%s: Failed writing framebuffer screenshot to file \"%s\"\n", VOGL_METHOD_NAME, screenshot_filename.get_ptr());
2967         success = false;
2968     }
2969     else
2970     {
2971         vogl_printf("%s: Wrote framebuffer screenshot to file \"%s\"\n", VOGL_METHOD_NAME, screenshot_filename.get_ptr());
2972     }
2973
2974     mz_free(pPNG_data);
2975
2976     return success;
2977 }
2978
2979 //----------------------------------------------------------------------------------------------------------------------
2980 // vogl_gl_replayer::dump_current_framebuffer
2981 //----------------------------------------------------------------------------------------------------------------------
2982 void vogl_gl_replayer::dump_current_framebuffer()
2983 {
2984     VOGL_FUNC_TRACER
2985
2986     uint draw_framebuffer_binding = vogl_get_gl_integer(GL_DRAW_FRAMEBUFFER_BINDING);
2987
2988     uint max_draw_buffers = vogl_get_gl_integer(GL_MAX_DRAW_BUFFERS);
2989     if (!max_draw_buffers)
2990     {
2991         process_entrypoint_warning("%s: GL_MAX_DRAW_BUFFERS is 0\n", VOGL_METHOD_NAME);
2992         return;
2993     }
2994
2995     //GL_COLOR_ATTACHMENT0-GL_COLOR_ATTACHMENT15, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT
2996
2997     vogl::vector<GLenum> draw_buffers(max_draw_buffers);
2998     for (uint i = 0; i < max_draw_buffers; i++)
2999         draw_buffers[i] = vogl_get_gl_integer(GL_DRAW_BUFFER0 + i);
3000
3001     if (!draw_framebuffer_binding)
3002     {
3003         for (uint i = 0; i < max_draw_buffers; i++)
3004             if (draw_buffers[i] != GL_NONE)
3005                 dump_framebuffer(m_pWindow->get_width(), m_pWindow->get_height(), 0, draw_buffers[i], GL_NONE, 0, 0, 0);
3006         return;
3007     }
3008
3009     // TODO: We should probably keep around a persistent set of per-context (or sharelist) remappers
3010     vogl_framebuffer_state fbo_state;
3011     if (!fbo_state.snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, draw_framebuffer_binding, GL_NONE))
3012     {
3013         process_entrypoint_warning("%s: Unable to snapshot current FBO %u\n", VOGL_METHOD_NAME, draw_framebuffer_binding);
3014         return;
3015     }
3016
3017     for (uint i = 0; i < draw_buffers.size(); i++)
3018     {
3019         if (draw_buffers[i] == GL_NONE)
3020             continue;
3021
3022         const vogl_framebuffer_attachment *pAttachment = fbo_state.get_attachments().find_value(draw_buffers[i]);
3023         if (!pAttachment)
3024         {
3025             process_entrypoint_warning("%s: Can't find draw buffer %s in currently bound FBO %u\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(draw_buffers[i]), draw_framebuffer_binding);
3026             continue;
3027         }
3028
3029         if (pAttachment->get_type() == GL_FRAMEBUFFER_DEFAULT)
3030             continue;
3031         else if (pAttachment->get_type() == GL_RENDERBUFFER)
3032         {
3033             GLuint rbo_handle = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
3034             if (!rbo_handle)
3035                 continue;
3036
3037             vogl_renderbuffer_state rbo_state;
3038             if (!rbo_state.snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, rbo_handle, GL_NONE))
3039             {
3040                 process_entrypoint_warning("%s: Failed getting RBO %u's' state!\n", VOGL_METHOD_NAME, rbo_handle);
3041                 continue;
3042             }
3043
3044             if (rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_DEPTH_SIZE) || rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_STENCIL_SIZE))
3045                 continue;
3046
3047             uint width = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_WIDTH);
3048             uint height = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_HEIGHT);
3049             uint samples = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_SAMPLES);
3050             GLenum internal_format = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_INTERNAL_FORMAT);
3051
3052             if ((!width) || (!height) || (!internal_format))
3053             {
3054                 process_entrypoint_warning("%s: Unable to determine FBO %u color attachment %u's RBO %u's dimensions\n", VOGL_METHOD_NAME, draw_framebuffer_binding, i, rbo_handle);
3055                 continue;
3056             }
3057
3058             if (samples > 1)
3059             {
3060                 vogl_scoped_binding_state orig_framebuffers(GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER, GL_RENDERBUFFER);
3061
3062                 GLuint temp_rbo = 0;
3063                 GL_ENTRYPOINT(glGenRenderbuffers)(1, &temp_rbo);
3064                 check_gl_error();
3065
3066                 if (!temp_rbo)
3067                     continue;
3068
3069                 GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, temp_rbo);
3070                 check_gl_error();
3071
3072                 GL_ENTRYPOINT(glRenderbufferStorage)(GL_RENDERBUFFER, internal_format, width, height);
3073                 check_gl_error();
3074
3075                 GLuint temp_fbo = 0;
3076                 GL_ENTRYPOINT(glGenFramebuffers)(1, &temp_fbo);
3077                 check_gl_error();
3078
3079                 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, temp_fbo);
3080                 check_gl_error();
3081
3082                 GL_ENTRYPOINT(glFramebufferRenderbuffer)(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, temp_rbo);
3083                 check_gl_error();
3084
3085                 GLenum draw_buf = GL_COLOR_ATTACHMENT0;
3086                 GL_ENTRYPOINT(glDrawBuffers)(1, &draw_buf);
3087                 check_gl_error();
3088
3089                 GL_ENTRYPOINT(glReadBuffer)(GL_NONE);
3090                 check_gl_error();
3091
3092                 GLenum cur_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_DRAW_FRAMEBUFFER);
3093                 check_gl_error();
3094
3095                 if (cur_status == GL_FRAMEBUFFER_COMPLETE)
3096                 {
3097                     GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, draw_framebuffer_binding);
3098                     check_gl_error();
3099
3100                     // Save the framebuffer's readbuffer (it's per-framebuffer state, not context state).
3101                     vogl_scoped_state_saver state_saver(cGSTReadBuffer);
3102
3103                     GL_ENTRYPOINT(glReadBuffer)(draw_buffers[i]);
3104                     check_gl_error();
3105
3106                     GL_ENTRYPOINT(glBlitFramebuffer)(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3107
3108                     if (!check_gl_error())
3109                         dump_framebuffer(width, height, temp_fbo, GL_COLOR_ATTACHMENT0, internal_format, samples, 0, rbo_handle);
3110                     else
3111                     {
3112                         process_entrypoint_warning("%s: Failed downsampling FBO %u color attachment %u's RBO %u to temporary RBO\n", VOGL_METHOD_NAME, draw_framebuffer_binding, i, rbo_handle);
3113                     }
3114                 }
3115
3116                 GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, 0);
3117                 check_gl_error();
3118
3119                 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, 0);
3120                 check_gl_error();
3121
3122                 GL_ENTRYPOINT(glDeleteFramebuffers)(1, &temp_fbo);
3123                 check_gl_error();
3124
3125                 GL_ENTRYPOINT(glDeleteRenderbuffers)(1, &temp_rbo);
3126                 check_gl_error();
3127             }
3128             else
3129             {
3130                 dump_framebuffer(width, height, draw_framebuffer_binding, draw_buffers[i], internal_format, 0, 0, rbo_handle);
3131             }
3132         }
3133         else if (pAttachment->get_type() == GL_TEXTURE)
3134         {
3135             GLuint tex_handle = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
3136             if (!tex_handle)
3137             {
3138                 process_entrypoint_warning("%s: Current FBO %u has a invalid object name\n", VOGL_METHOD_NAME, draw_framebuffer_binding);
3139                 continue;
3140             }
3141
3142             GLenum target = get_shared_state()->m_shadow_state.m_textures.get_target_inv(tex_handle);
3143             if (target == GL_NONE)
3144             {
3145                 process_entrypoint_warning("%s: Current FBO %u first color attachment's type is GL_TEXTURE, but unable to determine the texture's target type, GL texture handle %u\n", VOGL_METHOD_NAME, draw_framebuffer_binding, tex_handle);
3146                 continue;
3147             }
3148
3149             if ((target == GL_TEXTURE_CUBE_MAP) || (target == GL_TEXTURE_CUBE_MAP_ARRAY))
3150                 target = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE);
3151
3152             if (!utils::is_in_set<GLenum, GLenum>(target, GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_ARRAY))
3153             {
3154                 process_entrypoint_warning("%s: Unsupported FBO attachment texture target type (%s), GL texture handle %u\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(target), tex_handle);
3155                 continue;
3156             }
3157
3158             uint level = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL);
3159             uint layer = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER);
3160             VOGL_NOTE_UNUSED(layer);
3161
3162             GLint width = 0, height = 0, samples = 0;
3163             GLenum internal_format = GL_NONE;
3164
3165             {
3166                 vogl_scoped_binding_state binding_saver;
3167                 binding_saver.save_textures();
3168
3169                 GL_ENTRYPOINT(glBindTexture)(target, tex_handle);
3170                 check_gl_error();
3171
3172                 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_WIDTH, &width);
3173                 check_gl_error();
3174
3175                 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_HEIGHT, &height);
3176                 check_gl_error();
3177
3178                 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_INTERNAL_FORMAT, reinterpret_cast<GLint *>(&internal_format));
3179                 check_gl_error();
3180
3181                 if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_texture_multisample"))
3182                 {
3183                     GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_SAMPLES, &samples);
3184                     check_gl_error();
3185                 }
3186             }
3187
3188             if ((!width) || (!height))
3189             {
3190                 process_entrypoint_warning("%s: Unable to determine FBO %u color attachment %u's texture %u's dimensions\n", VOGL_METHOD_NAME, draw_framebuffer_binding, i, tex_handle);
3191                 continue;
3192             }
3193
3194             if (samples > 1)
3195             {
3196                 process_entrypoint_warning("%s: Can't dump multisample texture FBO attachments yet\n", VOGL_METHOD_NAME);
3197                 continue;
3198             }
3199
3200             dump_framebuffer(width, height, draw_framebuffer_binding, draw_buffers[i], internal_format, 0, tex_handle, 0);
3201         }
3202     }
3203 }
3204
3205 //----------------------------------------------------------------------------------------------------------------------
3206 // vogl_gl_replayer::dump_current_shaders
3207 //----------------------------------------------------------------------------------------------------------------------
3208 void vogl_gl_replayer::dump_current_shaders()
3209 {
3210     VOGL_FUNC_TRACER
3211
3212     if (!m_pCur_context_state)
3213         return;
3214
3215     check_gl_error();
3216
3217     const GLuint replay_program = m_pCur_context_state->m_cur_replay_program;
3218
3219     // Get the current program.
3220     GLuint current_program = 0;
3221     GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, (GLint *)(&current_program));
3222     check_gl_error();
3223
3224     VOGL_ASSERT(replay_program == current_program);
3225
3226     if (!current_program)
3227         return;
3228
3229     // Get the attached shaders.
3230     GLsizei attached_shader_count = -1;
3231     GL_ENTRYPOINT(glGetProgramiv)(replay_program, GL_ATTACHED_SHADERS, &attached_shader_count);
3232     check_gl_error();
3233
3234     if (!attached_shader_count)
3235         return;
3236
3237     vogl::vector<GLuint> shaders(attached_shader_count);
3238     GLsizei actual_shader_count = 0;
3239     GL_ENTRYPOINT(glGetAttachedShaders)(replay_program,
3240                                         attached_shader_count,
3241                                         &actual_shader_count,
3242                                         shaders.get_ptr());
3243     check_gl_error();
3244
3245     VOGL_ASSERT(attached_shader_count == actual_shader_count); // Sanity check.
3246
3247     vogl_printf("Trace context 0x%" PRIx64 ", GL draw counter %" PRIu64 ", frame %u, replay program %u trace program %u has %d attached shaders:\n",
3248                cast_val_to_uint64(m_cur_trace_context), m_last_parsed_call_counter, m_frame_index,
3249                replay_program, m_pCur_context_state->m_cur_trace_program,
3250                attached_shader_count);
3251
3252     // Get source from shaders.
3253     vogl::vector<GLchar> source; // Shared buffer for each iteration.
3254     for (GLsizei i = 0; i < attached_shader_count; ++i)
3255     {
3256         const GLuint shader = shaders[i];
3257         GLint shader_type = 0;
3258         GL_ENTRYPOINT(glGetShaderiv)(shader, GL_SHADER_TYPE, &shader_type);
3259         check_gl_error();
3260
3261         vogl_printf("\n%s: %u\n", g_gl_enums.find_gl_name(shader_type), shader);
3262
3263         GLint source_length = -1; // Includes NUL terminator.
3264         GL_ENTRYPOINT(glGetShaderiv)(shader, GL_SHADER_SOURCE_LENGTH, &source_length);
3265         check_gl_error();
3266
3267         VOGL_ASSERT(source_length > 0);
3268
3269         source.resize(source_length);
3270         GLint actual_length = 0; // Excludes NUL terminator!
3271         GL_ENTRYPOINT(glGetShaderSource)(shader, source_length, &actual_length, source.get_ptr());
3272         check_gl_error();
3273
3274         VOGL_ASSERT(source_length == actual_length + 1); // Sanity check.
3275         vogl_printf("%.*s\n", source_length, source.get_const_ptr());
3276     }
3277     vogl_printf("========\n");
3278 }
3279
3280 //----------------------------------------------------------------------------------------------------------------------
3281 // vogl_gl_replayer::handle_ShaderSource
3282 // Handle ShaderSource and ShaderSourceARB.
3283 //----------------------------------------------------------------------------------------------------------------------
3284 vogl_gl_replayer::status_t vogl_gl_replayer::handle_ShaderSource(GLhandleARB trace_object,
3285                                                                GLsizei count,
3286                                                                const vogl_client_memory_array trace_strings_glchar_ptr_array,
3287                                                                const GLint *pTrace_lengths)
3288 {
3289     VOGL_FUNC_TRACER
3290
3291     GLhandleARB replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
3292
3293     // m_pCur_gl_packet->get_param_client_memory_data_size(2) / sizeof(const GLchar *);
3294     const uint trace_strings_count = trace_strings_glchar_ptr_array.size();
3295     const uint trace_lengths_count = m_pCur_gl_packet->get_param_client_memory_data_size(3) / sizeof(const GLint);
3296
3297     if ((trace_strings_glchar_ptr_array.get_ptr()) &&
3298         (trace_strings_count != static_cast<uint>(count)))
3299     {
3300         process_entrypoint_error("%s: Trace strings array has an invalid count (expected %u, got %u)\n",
3301                                  VOGL_METHOD_NAME, count, trace_strings_count);
3302         return cStatusHardFailure;
3303     }
3304
3305     if ((pTrace_lengths) && (trace_lengths_count != static_cast<uint>(count)))
3306     {
3307         process_entrypoint_error("%s: Trace lengths array has an invalid count (expected %u, got %u)\n",
3308                                  VOGL_METHOD_NAME, count, trace_lengths_count);
3309         return cStatusHardFailure;
3310     }
3311
3312     vogl::vector<const GLcharARB *> strings(count);
3313     vogl::vector<GLint> lengths(count);
3314
3315     const key_value_map &map = m_pCur_gl_packet->get_key_value_map();
3316
3317     vogl::vector<uint8_vec> blobs(count);
3318
3319     for (GLsizei i = 0; i < count; i++)
3320     {
3321         strings[i] = NULL;
3322         if ((trace_strings_glchar_ptr_array.get_ptr()) &&
3323             (trace_strings_glchar_ptr_array.get_element<vogl_trace_ptr_value>(i) != 0))
3324         {
3325             strings[i] = "";
3326         }
3327
3328         lengths[i] = pTrace_lengths ? pTrace_lengths[i] : 0;
3329
3330         key_value_map::const_iterator it = map.find(i);
3331         if (it == map.end())
3332         {
3333             if (lengths[i] > 0)
3334             {
3335                 process_entrypoint_error("%s: Failed finding blob for non-empty string %i in packet's key value map\n",
3336                                          VOGL_METHOD_NAME, i);
3337                 return cStatusHardFailure;
3338             }
3339             continue;
3340         }
3341
3342         const uint8_vec *pBlob = it->second.get_blob();
3343         if (!pBlob)
3344         {
3345             process_entrypoint_error("%s: Can't convert string %i to a blob\n", VOGL_METHOD_NAME, i);
3346             return cStatusHardFailure;
3347         }
3348
3349         blobs[i] = *pBlob;
3350         uint8_vec &blob = blobs[i];
3351
3352         if ((pTrace_lengths) && (pTrace_lengths[i] >= 0))
3353         {
3354             if (static_cast<uint>(pTrace_lengths[i]) != blob.size())
3355             {
3356                 process_entrypoint_warning("%s: Length value (%u) stored in length array at index %u doesn't match string %u's length - changing to match\n", VOGL_METHOD_NAME, pTrace_lengths[i], i, blob.size());
3357                 lengths[i] = blob.size();
3358             }
3359         }
3360         else
3361         {
3362             if ((blob.size()) && (blob.back() != '\0'))
3363             {
3364                 process_entrypoint_warning("%s: String %u doesn't end in 0 terminator - appending terminator\n", VOGL_METHOD_NAME, i);
3365
3366                 blob.push_back('\0');
3367             }
3368
3369             VOGL_ASSERT(blob.size() &&
3370                           (blob.back() == '\0') &&
3371                           (blob.size() == (1 + vogl_strlen(reinterpret_cast<const char *>(blob.get_ptr())))));
3372         }
3373
3374         strings[i] = reinterpret_cast<const GLcharARB *>(blob.get_ptr());
3375     }
3376
3377     if (m_pCur_gl_packet->get_entrypoint_id() == VOGL_ENTRYPOINT_glShaderSource)
3378     {
3379         GL_ENTRYPOINT(glShaderSource)(replay_object,
3380                                       count,
3381                                       trace_strings_glchar_ptr_array.get_ptr() ? (GLchar * const *)strings.get_ptr() : NULL,
3382                                       pTrace_lengths ? lengths.get_ptr() : NULL);
3383     }
3384     else
3385     {
3386         GL_ENTRYPOINT(glShaderSourceARB)(replay_object,
3387                                          count,
3388                                          trace_strings_glchar_ptr_array.get_ptr() ? strings.get_ptr() : NULL,
3389                                          pTrace_lengths ? lengths.get_ptr() : NULL);
3390     }
3391     return cStatusOK;
3392 }
3393
3394 //----------------------------------------------------------------------------------------------------------------------
3395 // vogl_gl_replayer::display_list_bind_callback
3396 // handle is in the trace namespace
3397 //----------------------------------------------------------------------------------------------------------------------
3398 void vogl_gl_replayer::display_list_bind_callback(vogl_namespace_t handle_namespace, GLenum target, GLuint handle, void *pOpaque)
3399 {
3400     VOGL_FUNC_TRACER
3401
3402     vogl_gl_replayer *pReplayer = static_cast<vogl_gl_replayer *>(pOpaque);
3403
3404     if (handle_namespace == VOGL_NAMESPACE_TEXTURES)
3405     {
3406         if ((handle) && (target != GL_NONE))
3407         {
3408             // A conditional update because we can't really test to see if the bind inside the display list really succeeded.
3409             pReplayer->get_shared_state()->m_shadow_state.m_textures.conditional_update(handle, GL_NONE, target);
3410         }
3411     }
3412     else
3413     {
3414         // TODO - right now the display list whitelist doens't let anything else get bound.
3415         pReplayer->process_entrypoint_warning("%s: Unsupported bind in display lists, namespace %s target %s trace handle %u\n", VOGL_FUNCTION_NAME, vogl_get_namespace_name(handle_namespace), g_gl_enums.find_gl_name(target), handle);
3416     }
3417 }
3418
3419 //----------------------------------------------------------------------------------------------------------------------
3420 // Helper macros - slightly simplifies hand-generating entrypoints with EXT/ARB/etc. variants
3421 //----------------------------------------------------------------------------------------------------------------------
3422 #define SWITCH_GL_ENTRYPOINT2(e0, e1, ...)                 \
3423     if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3424         result = GL_ENTRYPOINT(e0)(__VA_ARGS__);           \
3425     else                                                   \
3426         result = GL_ENTRYPOINT(e1)(__VA_ARGS__);
3427
3428 #define SWITCH_GL_ENTRYPOINT3(e0, e1, e2, ...)                  \
3429     if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0))      \
3430         result = GL_ENTRYPOINT(e0)(__VA_ARGS__);                \
3431     else if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e1)) \
3432         result = GL_ENTRYPOINT(e1)(__VA_ARGS__);                \
3433     else                                                        \
3434         result = GL_ENTRYPOINT(e2)(__VA_ARGS__);
3435
3436 #define SWITCH_GL_ENTRYPOINT2_VOID(e0, e1, ...)            \
3437     if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3438         GL_ENTRYPOINT(e0)(__VA_ARGS__);                    \
3439     else                                                   \
3440         GL_ENTRYPOINT(e1)(__VA_ARGS__);
3441
3442 #define SWITCH_GL_ENTRYPOINT3_VOID(e0, e1, e2, ...)             \
3443     if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0))      \
3444         GL_ENTRYPOINT(e0)(__VA_ARGS__);                         \
3445     else if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e1)) \
3446         GL_ENTRYPOINT(e1)(__VA_ARGS__);                         \
3447     else                                                        \
3448         GL_ENTRYPOINT(e2)(__VA_ARGS__);
3449
3450 //----------------------------------------------------------------------------------------------------------------------
3451 // vogl_replayer::process_gl_entrypoint_packet
3452 // This will be called during replaying, or when building display lists during state restoring.
3453 //----------------------------------------------------------------------------------------------------------------------
3454 vogl_gl_replayer::status_t vogl_gl_replayer::process_gl_entrypoint_packet(vogl_trace_packet& trace_packet)
3455 {
3456     m_pCur_gl_packet = &trace_packet;
3457
3458     status_t status = cStatusOK;
3459
3460     if (m_pPending_snapshot)
3461     {
3462         status = process_applying_pending_snapshot();
3463         if (status != cStatusOK)
3464             return status;
3465     }
3466
3467     if (m_pending_make_current_packet.is_valid())
3468     {
3469         status = process_pending_make_current();
3470         if (status != cStatusOK)
3471             return status;
3472     }
3473
3474     const vogl_trace_gl_entrypoint_packet &entrypoint_packet = trace_packet.get_entrypoint_packet();
3475
3476     m_last_parsed_call_counter = entrypoint_packet.m_call_counter;
3477
3478     status = process_gl_entrypoint_packet_internal(trace_packet);
3479
3480     if (status != cStatusResizeWindow)
3481         m_last_processed_call_counter = entrypoint_packet.m_call_counter;
3482
3483     m_pCur_gl_packet = NULL;
3484
3485     return status;
3486 }
3487
3488 //----------------------------------------------------------------------------------------------------------------------
3489 // vogl_replayer::process_gl_entrypoint_packet_internal
3490 // This will be called during replaying, or when building display lists during state restoring.
3491 //----------------------------------------------------------------------------------------------------------------------
3492 vogl_gl_replayer::status_t vogl_gl_replayer::process_gl_entrypoint_packet_internal(vogl_trace_packet& trace_packet)
3493 {
3494     VOGL_FUNC_TRACER
3495
3496     m_at_frame_boundary = false;
3497
3498     const vogl_trace_gl_entrypoint_packet &gl_entrypoint_packet = trace_packet.get_entrypoint_packet();
3499     const gl_entrypoint_id_t entrypoint_id = trace_packet.get_entrypoint_id();
3500
3501     if (m_flags & cGLReplayerDebugMode)
3502         dump_trace_gl_packet_debug_info(gl_entrypoint_packet);
3503
3504     if (m_flags & cGLReplayerDebugMode)
3505         dump_packet_as_func_call(trace_packet);
3506
3507     if (m_flags & cGLReplayerDumpAllPackets)
3508         print_detailed_context(cDebugConsoleMessage);
3509
3510     if (entrypoint_id == VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
3511         return process_internal_trace_command(gl_entrypoint_packet);
3512
3513     status_t status = cStatusOK;
3514
3515     if (gl_entrypoint_packet.m_context_handle != m_cur_trace_context)
3516     {
3517         status = switch_contexts(gl_entrypoint_packet.m_context_handle);
3518         if (status != cStatusOK)
3519             return status;
3520     }
3521
3522     bool processed_glx_packet = true;
3523     switch (entrypoint_id)
3524     {
3525         case VOGL_ENTRYPOINT_glXDestroyContext:
3526         {
3527             const Display *dpy = m_pWindow->get_display();
3528
3529             vogl_trace_context_ptr_value trace_context = trace_packet.get_param_ptr_value(1);
3530             GLXContext replay_context = remap_context(trace_context);
3531
3532             if ((trace_context) && (!replay_context))
3533             {
3534                 process_entrypoint_error("%s: Failed remapping GL trace context 0x%" PRIx64 "\n", VOGL_METHOD_NAME, (uint64_t)trace_context);
3535                 return cStatusHardFailure;
3536             }
3537
3538             if (trace_context == m_cur_trace_context)
3539             {
3540                 process_entrypoint_warning("%s: glXDestroyContext() called while trace context 0x%" PRIx64 " is still current, forcing it to not be current\n",
3541                                            VOGL_METHOD_NAME, (uint64_t)trace_context);
3542
3543                 m_cur_trace_context = 0;
3544                 m_cur_replay_context = 0;
3545                 m_pCur_context_state = NULL;
3546             }
3547
3548             GL_ENTRYPOINT(glXDestroyContext)(dpy, replay_context);
3549
3550             destroy_context(trace_context);
3551
3552             break;
3553         }
3554         case VOGL_ENTRYPOINT_glXMakeCurrent:
3555         case VOGL_ENTRYPOINT_glXMakeContextCurrent:
3556         {
3557             Bool trace_result = trace_packet.get_return_value<Bool>();
3558
3559             vogl_trace_context_ptr_value trace_context = trace_packet.get_param_ptr_value((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) ? 2 : 3);
3560
3561             // pContext_state can be NULL!
3562             context_state *pContext_state = get_trace_context_state(trace_context);
3563             GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
3564
3565             if ((trace_context) && (!replay_context))
3566             {
3567                 process_entrypoint_error("%s, Failed remapping GL context\n", VOGL_METHOD_NAME);
3568                 return cStatusHardFailure;
3569             }
3570
3571             int viewport_x = trace_packet.get_key_value_map().get_int(string_hash("viewport_x"));
3572             VOGL_NOTE_UNUSED(viewport_x);
3573             int viewport_y = trace_packet.get_key_value_map().get_int(string_hash("viewport_y"));
3574             VOGL_NOTE_UNUSED(viewport_y);
3575             int viewport_width = trace_packet.get_key_value_map().get_int(string_hash("viewport_width"));
3576             VOGL_NOTE_UNUSED(viewport_width);
3577             int viewport_height = trace_packet.get_key_value_map().get_int(string_hash("viewport_height"));
3578             VOGL_NOTE_UNUSED(viewport_height);
3579             int win_width = trace_packet.get_key_value_map().get_int(string_hash("win_width"));
3580             int win_height = trace_packet.get_key_value_map().get_int(string_hash("win_height"));
3581
3582             // We may need to defer the make current until the window is the proper size, because the initial GL viewport's state depends on the Window size. Ugh.
3583             if ((trace_context) && (trace_result))
3584             {
3585                 if ((win_width) && (win_height))
3586                 {
3587                     if (!(m_flags & cGLReplayerLockWindowDimensions))
3588                     {
3589                         if ((m_pWindow->get_width() != win_width) || (m_pWindow->get_height() != win_height))
3590                         {
3591                             m_pending_make_current_packet = *m_pCur_gl_packet;
3592
3593                             status = trigger_pending_window_resize(win_width, win_height);
3594
3595                             vogl_printf("%s: Deferring glXMakeCurrent() until window resizes to %ux%u\n", VOGL_METHOD_NAME, win_width, win_height);
3596                         }
3597                     }
3598                 }
3599             }
3600
3601             if (status != cStatusResizeWindow)
3602             {
3603                 const Display *dpy = m_pWindow->get_display();
3604                 GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
3605
3606                 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
3607                 if (!result)
3608                 {
3609                     if (trace_result)
3610                     {
3611                         process_entrypoint_error("%s: Failed making context current, but in the trace this call succeeded!\n", VOGL_METHOD_NAME);
3612                         return cStatusHardFailure;
3613                     }
3614                     else
3615                     {
3616                         process_entrypoint_warning("%s: Failed making context current, in the trace this call also failed\n", VOGL_METHOD_NAME);
3617                     }
3618                 }
3619                 else
3620                 {
3621                     m_cur_trace_context = trace_context;
3622                     m_cur_replay_context = replay_context;
3623                     m_pCur_context_state = pContext_state;
3624
3625                     if (!trace_result)
3626                     {
3627                         process_entrypoint_warning("%s: Context was successfuly made current, but this operation failed in the trace\n", VOGL_METHOD_NAME);
3628                     }
3629
3630 #if 0
3631                                 vogl_printf("glXMakeCurrent(): Trace Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
3632                                            viewport_x, viewport_y,
3633                                            viewport_width, viewport_height,
3634                                            win_width, win_height);
3635 #endif
3636
3637                     if (m_cur_replay_context)
3638                     {
3639                         if (!handle_context_made_current())
3640                             return cStatusHardFailure;
3641                     }
3642                 }
3643             }
3644
3645             break;
3646         }
3647         case VOGL_ENTRYPOINT_glXQueryVersion:
3648         {
3649             int major = 0, minor = 0;
3650             Bool status = GL_ENTRYPOINT(glXQueryVersion)(m_pWindow->get_display(), &major, &minor);
3651             process_entrypoint_message("%s: glXQueryVersion returned major %u minor %u status %u, trace recorded major %u minor %u status %u\n", VOGL_METHOD_NAME, major, minor, status,
3652                                        *trace_packet.get_param_client_memory<int>(1),
3653                                        *trace_packet.get_param_client_memory<int>(2),
3654                                        trace_packet.get_return_value<Bool>());
3655
3656             break;
3657         }
3658         case VOGL_ENTRYPOINT_glXChooseFBConfig:
3659         {
3660             // TODO
3661             break;
3662         }
3663         case VOGL_ENTRYPOINT_glXGetFBConfigAttrib:
3664         {
3665             // TODO
3666             break;
3667         }
3668         case VOGL_ENTRYPOINT_glXGetVisualFromFBConfig:
3669         {
3670             // TODO
3671             break;
3672         }
3673         case VOGL_ENTRYPOINT_glXGetProcAddress:
3674         case VOGL_ENTRYPOINT_glXGetProcAddressARB:
3675         {
3676             const GLubyte *procName = trace_packet.get_param_client_memory<GLubyte>(0);
3677             vogl_trace_ptr_value trace_func_ptr_value = trace_packet.get_return_ptr_value();
3678
3679             void *pFunc = (void *)GL_ENTRYPOINT(glXGetProcAddress)(procName);
3680
3681             if ((pFunc != NULL) != (trace_func_ptr_value != 0))
3682             {
3683                 process_entrypoint_warning("%s: glXGetProcAddress of function %s %s in the replay, but %s in the trace\n", VOGL_METHOD_NAME,
3684                                            (const char *)procName,
3685                                            (pFunc != NULL) ? "succeeded" : "failed",
3686                                            (trace_func_ptr_value != 0) ? "succeeded" : "failed");
3687             }
3688
3689             break;
3690         }
3691         case VOGL_ENTRYPOINT_glXCreateNewContext:
3692         {
3693             Display *dpy = m_pWindow->get_display();
3694             GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3695             int render_type = trace_packet.get_param_value<GLint>(2);
3696
3697             vogl_trace_context_ptr_value trace_share_context = trace_packet.get_param_ptr_value(3);
3698             GLXContext replay_share_context = remap_context(trace_share_context);
3699
3700             if ((trace_share_context) && (!replay_share_context))
3701             {
3702                 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3703             }
3704
3705             Bool direct = trace_packet.get_param_value<Bool>(4);
3706             vogl_trace_context_ptr_value trace_context = trace_packet.get_return_ptr_value();
3707
3708             if (m_flags & cGLReplayerForceDebugContexts)
3709             {
3710                 process_entrypoint_warning("%s: glxCreateNewContext() called but we're trying to force debug contexts, which requires us to call glXCreateContextAttribsARB(). This may fail if the user has called glXCreateWindow().\n", VOGL_METHOD_NAME);
3711
3712                 status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, NULL, 0, false);
3713                 if (status != cStatusOK)
3714                     return status;
3715             }
3716             else
3717             {
3718                 GLXContext replay_context = GL_ENTRYPOINT(glXCreateNewContext)(dpy, fb_config, render_type, replay_share_context, direct);
3719
3720                 if (!replay_context)
3721                 {
3722                     if (trace_context)
3723                     {
3724                         process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
3725                         return cStatusHardFailure;
3726                     }
3727                     else
3728                     {
3729                         process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
3730                     }
3731                 }
3732
3733                 if (replay_context)
3734                 {
3735                     if (trace_context)
3736                     {
3737                         context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateNewContext, NULL, 0);
3738                         VOGL_NOTE_UNUSED(pContext_state);
3739                     }
3740                     else
3741                     {
3742                         GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
3743                     }
3744                 }
3745             }
3746
3747             break;
3748         }
3749         case VOGL_ENTRYPOINT_glXCreateContext:
3750         {
3751             Display *dpy = m_pWindow->get_display();
3752
3753             vogl_trace_context_ptr_value trace_share_context = trace_packet.get_param_ptr_value(2);
3754             GLXContext replay_share_context = remap_context(trace_share_context);
3755
3756             if ((trace_share_context) && (!replay_share_context))
3757             {
3758                 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3759             }
3760
3761             GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3762             Bool direct = trace_packet.get_param_value<Bool>(3);
3763             vogl_trace_context_ptr_value trace_context = trace_packet.get_return_ptr_value();
3764
3765             if (m_flags & cGLReplayerForceDebugContexts)
3766             {
3767                 status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, NULL, 0, false);
3768                 if (status != cStatusOK)
3769                     return status;
3770             }
3771             else
3772             {
3773                 XVisualInfo *pVisual_info = GL_ENTRYPOINT(glXGetVisualFromFBConfig)(dpy, fb_config);
3774
3775                 GLXContext replay_context = GL_ENTRYPOINT(glXCreateContext)(dpy, pVisual_info, replay_share_context, direct);
3776
3777                 if (!replay_context)
3778                 {
3779                     if (trace_context)
3780                     {
3781                         process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
3782                         return cStatusHardFailure;
3783                     }
3784                     else
3785                     {
3786                         process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
3787                     }
3788                 }
3789
3790                 if (replay_context)
3791                 {
3792                     if (trace_context)
3793                     {
3794                         context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateContext, NULL, 0);
3795                         VOGL_NOTE_UNUSED(pContext_state);
3796                     }
3797                     else
3798                     {
3799                         GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
3800                     }
3801                 }
3802             }
3803
3804             break;
3805         }
3806         case VOGL_ENTRYPOINT_glXCreateContextAttribsARB:
3807         {
3808             Display *dpy = m_pWindow->get_display();
3809             GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3810
3811             vogl_trace_ptr_value trace_share_context = trace_packet.get_param_ptr_value(2);
3812             GLXContext replay_share_context = remap_context(trace_share_context);
3813
3814             if ((trace_share_context) && (!replay_share_context))
3815             {
3816                 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3817             }
3818
3819             Bool direct = trace_packet.get_param_value<Bool>(3);
3820             const int *pTrace_attrib_list = static_cast<const int *>(trace_packet.get_param_client_memory_ptr(4));
3821             const uint trace_attrib_list_size = trace_packet.get_param_client_memory_data_size(4) / sizeof(int);
3822
3823             vogl_trace_ptr_value trace_context = trace_packet.get_return_ptr_value();
3824
3825             status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, pTrace_attrib_list, trace_attrib_list_size, true);
3826             if (status != cStatusOK)
3827                 return status;
3828
3829             break;
3830         }
3831         case VOGL_ENTRYPOINT_glXSwapBuffers:
3832         {
3833             check_program_binding_shadow();
3834
3835             if (m_flags & cGLReplayerLowLevelDebugMode)
3836             {
3837                 if (!validate_program_and_shader_handle_tables())
3838                     vogl_warning_printf("%s: Failed validating program/shaders against handle mapping tables\n", VOGL_METHOD_NAME);
3839                 if (!validate_textures())
3840                     vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
3841             }
3842
3843             const Display *dpy = m_pWindow->get_display();
3844             GLXDrawable drawable = m_pWindow->get_xwindow();
3845
3846             if ((m_flags & cGLReplayerHashBackbuffer) || (m_flags & cGLReplayerDumpScreenshots) || (m_flags & cGLReplayerDumpBackbufferHashes))
3847             {
3848                 snapshot_backbuffer();
3849             }
3850
3851             if (m_dump_frontbuffer_filename.has_content())
3852             {
3853                 dump_frontbuffer_to_file(m_dump_frontbuffer_filename);
3854                 m_dump_frontbuffer_filename.clear();
3855             }
3856
3857             GL_ENTRYPOINT(glXSwapBuffers)(dpy, drawable);
3858
3859             if (m_swap_sleep_time)
3860                 vogl_sleep(m_swap_sleep_time);
3861
3862             status = cStatusNextFrame;
3863
3864             m_at_frame_boundary = true;
3865
3866             if (m_flags & cGLReplayerDebugMode)
3867             {
3868                 vogl_debug_printf("%s: glXSwapBuffers() processed at end of frame %u, swap %u, last GL call counter %" PRIu64 "\n", VOGL_METHOD_NAME, m_frame_index, m_total_swaps, m_last_parsed_call_counter);
3869             }
3870
3871             m_frame_index++;
3872             m_total_swaps++;
3873
3874             m_frame_draw_counter = 0;
3875
3876             int win_width = trace_packet.get_key_value_map().get_int(string_hash("win_width"));
3877             int win_height = trace_packet.get_key_value_map().get_int(string_hash("win_height"));
3878             if ((win_width) && (win_height))
3879             {
3880                 if (!(m_flags & cGLReplayerLockWindowDimensions))
3881                 {
3882                     if ((win_width != m_pWindow->get_width()) || (win_height != m_pWindow->get_height()))
3883                     {
3884                         // TODO: This resize might need to be deferred until the window system actually resizes the window.
3885                         //m_pWindow->resize(win_width, win_height);
3886                         trigger_pending_window_resize(win_width, win_height);
3887
3888                         vogl_printf("%s: Resizing window after swap to %ux%u\n", VOGL_METHOD_NAME, win_width, win_height);
3889                     }
3890                 }
3891             }
3892
3893             break;
3894         }
3895         case VOGL_ENTRYPOINT_glXWaitX:
3896         {
3897             VOGL_REPLAY_LOAD_PARAMS_HELPER_glXWaitX;
3898
3899             VOGL_REPLAY_CALL_GL_HELPER_glXWaitX;
3900
3901             break;
3902         }
3903         case VOGL_ENTRYPOINT_glXWaitGL:
3904         {
3905             VOGL_REPLAY_LOAD_PARAMS_HELPER_glXWaitGL;
3906
3907             VOGL_REPLAY_CALL_GL_HELPER_glXWaitGL;
3908
3909             break;
3910         }
3911         case VOGL_ENTRYPOINT_glXIsDirect:
3912         {
3913             const Display *dpy = m_pWindow->get_display();
3914
3915             vogl_trace_ptr_value trace_context = trace_packet.get_param_ptr_value(1);
3916             GLXContext replay_context = remap_context(trace_context);
3917
3918             Bool replay_is_direct = GL_ENTRYPOINT(glXIsDirect)(dpy, replay_context);
3919             Bool trace_is_direct = trace_packet.get_return_value<Bool>();
3920
3921             if (replay_is_direct != trace_is_direct)
3922             {
3923                 process_entrypoint_warning("%s: glXIsDirect() returned different results while replaying (%u) vs tracing (%u)!\n", VOGL_METHOD_NAME, replay_is_direct, trace_is_direct);
3924             }
3925
3926             break;
3927         }
3928         case VOGL_ENTRYPOINT_glXGetCurrentContext:
3929         {
3930             GLXContext replay_context = GL_ENTRYPOINT(glXGetCurrentContext)();
3931             vogl_trace_ptr_value trace_context = trace_packet.get_return_ptr_value();
3932
3933             if ((replay_context != 0) != (trace_context != 0))
3934             {
3935                 process_entrypoint_warning("%s: glXGetCurrentContext() returned different results while replaying (0x%" PRIX64 ") vs tracing (0x%" PRIX64 ")!\n", VOGL_METHOD_NAME, (uint64_t)replay_context, (uint64_t)trace_context);
3936             }
3937
3938             break;
3939         }
3940         case VOGL_ENTRYPOINT_glXCreateWindow:
3941         case VOGL_ENTRYPOINT_glXDestroyWindow:
3942         case VOGL_ENTRYPOINT_glXChooseVisual:
3943         case VOGL_ENTRYPOINT_glXGetCurrentDisplay:
3944         case VOGL_ENTRYPOINT_glXQueryDrawable:
3945         case VOGL_ENTRYPOINT_glXQueryExtension:
3946         case VOGL_ENTRYPOINT_glXQueryExtensionsString:
3947         case VOGL_ENTRYPOINT_glXSwapIntervalEXT:
3948         case VOGL_ENTRYPOINT_glXSwapIntervalSGI:
3949         case VOGL_ENTRYPOINT_glXGetCurrentDrawable:
3950         case VOGL_ENTRYPOINT_glXGetCurrentReadDrawable:
3951         case VOGL_ENTRYPOINT_glXQueryContext:
3952         case VOGL_ENTRYPOINT_glXGetClientString:
3953         case VOGL_ENTRYPOINT_glXGetConfig:
3954         case VOGL_ENTRYPOINT_glXGetFBConfigs:
3955         {
3956             // TODO
3957             break;
3958         }
3959         default:
3960         {
3961             processed_glx_packet = false;
3962             break;
3963         }
3964     }
3965
3966     if (processed_glx_packet)
3967     {
3968         // TODO: Check for GLX errors?
3969         return status;
3970     }
3971
3972     if (!m_cur_replay_context)
3973     {
3974         process_entrypoint_error("%s: Trace contains a GL call with no current context! Skipping call.\n", VOGL_METHOD_NAME);
3975         return cStatusSoftFailure;
3976     }
3977
3978     VOGL_ASSERT(m_pCur_context_state);
3979     m_pCur_context_state->m_last_call_counter = m_last_parsed_call_counter;
3980
3981 #ifdef VOGL_BUILD_DEBUG
3982     VOGL_ASSERT(get_trace_context_state(m_cur_trace_context) == m_pCur_context_state);
3983 #endif
3984
3985     // Add call to current display list
3986     if ((get_context_state()->is_composing_display_list()) && (g_vogl_entrypoint_descs[entrypoint_id].m_is_listable))
3987     {
3988         if (!vogl_display_list_state::is_call_listable(entrypoint_id, trace_packet))
3989         {
3990             if (!g_vogl_entrypoint_descs[entrypoint_id].m_whitelisted_for_displaylists)
3991                 process_entrypoint_error("%s: Failed serializing trace packet into display list shadow! Call is not listable.\n", VOGL_FUNCTION_NAME);
3992             else
3993                 process_entrypoint_warning("%s: Failed serializing trace packet into display list shadow! Call with these parameters is not listable.\n", VOGL_FUNCTION_NAME);
3994         }
3995         else
3996         {
3997             if (!get_shared_state()->m_shadow_state.m_display_lists.add_packet_to_list(get_context_state()->m_current_display_list_handle, entrypoint_id, trace_packet))
3998             {
3999                 process_entrypoint_warning("%s: Failed adding current packet to display list shadow!\n", VOGL_METHOD_NAME);
4000             }
4001         }
4002     }
4003
4004     switch (entrypoint_id)
4005     {
4006 // ----- Create simple auto-generated replay funcs - voglgen creates this inc file from the funcs in gl_glx_simple_replay_funcs.txt
4007 // These simple GL entrypoints only take value params that don't require handle remapping, or simple pointers to client memory
4008 // (typically pointers to fixed size buffers, or params directly controlling the size of buffers).
4009 #define VOGL_SIMPLE_REPLAY_FUNC_BEGIN(name, num_params) \
4010     case VOGL_ENTRYPOINT_##name:                        \
4011     { if (!GL_ENTRYPOINT(name)) { process_entrypoint_error("vogl_gl_replayer::process_gl_entrypoint_packet_internal: Can't call NULL GL entrypoint %s (maybe a missing extension?)\n", #name); } else \
4012     GL_ENTRYPOINT(name)(
4013 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_VALUE(type, index) trace_packet.get_param_value<type>(index)
4014 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_SEPERATOR ,
4015 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_CLIENT_MEMORY(type, index) trace_packet.get_param_client_memory<type>(index)
4016 #define VOGL_SIMPLE_REPLAY_FUNC_END(name) ); \
4017     break;                                  \
4018     }
4019 #include "gl_glx_simple_replay_funcs.inc"
4020 #undef VOGL_SIMPLE_REPLAY_FUNC_BEGIN
4021 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_VALUE
4022 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_SEPERATOR
4023 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_CLIENT_MEMORY
4024 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_END
4025         // -----
4026         case VOGL_ENTRYPOINT_glXUseXFont:
4027         {
4028             const key_value_map &key_value_map = trace_packet.get_key_value_map();
4029
4030             const dynamic_string *pFont_name = key_value_map.get_string_ptr("font_name");
4031             if ((!pFont_name) || (pFont_name->is_empty()))
4032             {
4033                 process_entrypoint_warning("%s: Couldn't find font_name key, or key was empty - unable to call glXUseXFont()!\n", VOGL_METHOD_NAME);
4034             }
4035             else
4036             {
4037                 XFontStruct *pFont = XLoadQueryFont(m_pWindow->get_display(), pFont_name->get_ptr());
4038                 if (!pFont)
4039                 {
4040                     process_entrypoint_warning("%s: Couldn't load X font %s  - unable to call glXUseXFont()!\n", VOGL_METHOD_NAME, pFont_name->get_ptr());
4041                 }
4042                 else
4043                 {
4044                     GLint first = trace_packet.get_param_value<int>(1);
4045                     GLint count = trace_packet.get_param_value<int>(2);
4046                     int trace_list_base = trace_packet.get_param_value<int>(3);
4047                     GLuint replay_list_base = map_handle(get_shared_state()->m_lists, trace_list_base);
4048
4049                     GL_ENTRYPOINT(glXUseXFont)(pFont->fid, first, count, replay_list_base);
4050
4051                     XFreeFont(m_pWindow->get_display(), pFont);
4052
4053                     if (get_context_state()->is_composing_display_list())
4054                     {
4055                         process_entrypoint_warning("%s: glXUseXFont() called while composing a display list!\n", VOGL_METHOD_NAME);
4056                     }
4057                     else
4058                     {
4059                         if (!get_shared_state()->m_shadow_state.m_display_lists.glx_font(pFont_name->get_ptr(), first, count, trace_list_base))
4060                         {
4061                             process_entrypoint_warning("%s: Failed updating display list shadow\n", VOGL_METHOD_NAME);
4062                         }
4063                     }
4064                 }
4065             }
4066
4067             break;
4068         }
4069         case VOGL_ENTRYPOINT_glBlitFramebufferEXT:
4070         {
4071             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBlitFramebufferEXT;
4072
4073             VOGL_REPLAY_CALL_GL_HELPER_glBlitFramebufferEXT;
4074
4075             if ((status = post_draw_call()) != cStatusOK)
4076                 return status;
4077
4078             break;
4079         }
4080         case VOGL_ENTRYPOINT_glBlitFramebuffer:
4081         {
4082             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBlitFramebuffer;
4083
4084             VOGL_REPLAY_CALL_GL_HELPER_glBlitFramebuffer;
4085
4086             if ((status = post_draw_call()) != cStatusOK)
4087                 return status;
4088
4089             break;
4090         }
4091         case VOGL_ENTRYPOINT_glBegin:
4092         {
4093             if (m_pCur_context_state->m_inside_gl_begin)
4094             {
4095                 process_entrypoint_warning("%s: Got a glBegin while already inside a glBegin\n", VOGL_METHOD_NAME);
4096             }
4097             m_pCur_context_state->m_inside_gl_begin = true;
4098
4099             g_vogl_actual_gl_entrypoints.m_glBegin(trace_packet.get_param_value<GLenum>(0));
4100
4101             break;
4102         }
4103         case VOGL_ENTRYPOINT_glEnd:
4104         {
4105             if (!m_pCur_context_state->m_inside_gl_begin)
4106             {
4107                 process_entrypoint_warning("%s: Got glEnd without a matching glBegin\n", VOGL_METHOD_NAME);
4108             }
4109             m_pCur_context_state->m_inside_gl_begin = false;
4110
4111             g_vogl_actual_gl_entrypoints.m_glEnd();
4112
4113             if ((status = post_draw_call()) != cStatusOK)
4114                 return status;
4115
4116             break;
4117         }
4118         case VOGL_ENTRYPOINT_glGetError:
4119         {
4120             // TODO: Compare trace error vs. replay error
4121
4122             break;
4123         }
4124         case VOGL_ENTRYPOINT_glGetStringi:
4125         {
4126             if (!benchmark_mode())
4127             {
4128                 const GLubyte *pStr = GL_ENTRYPOINT(glGetStringi)(
4129                     trace_packet.get_param_value<GLenum>(0),
4130                     trace_packet.get_param_value<GLuint>(1));
4131                 VOGL_NOTE_UNUSED(pStr);
4132
4133                 // TODO: Compare vs. trace's?
4134             }
4135
4136             break;
4137         }
4138         case VOGL_ENTRYPOINT_glGetString:
4139         {
4140             if (!benchmark_mode())
4141             {
4142                 const GLubyte *pStr = GL_ENTRYPOINT(glGetString)(
4143                     trace_packet.get_param_value<GLenum>(0));
4144                 VOGL_NOTE_UNUSED(pStr);
4145
4146                 // TODO: Compare vs. trace's?
4147             }
4148
4149             break;
4150         }
4151         case VOGL_ENTRYPOINT_glGenFramebuffers:
4152         case VOGL_ENTRYPOINT_glGenFramebuffersEXT:
4153         {
4154             if (!gen_handles(get_context_state()->m_framebuffers,
4155                              trace_packet.get_param_value<GLsizei>(0),
4156                              static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)),
4157                              (entrypoint_id == VOGL_ENTRYPOINT_glGenFramebuffers) ? GL_ENTRYPOINT(glGenFramebuffers) : GL_ENTRYPOINT(glGenFramebuffersEXT), NULL))
4158                 return cStatusHardFailure;
4159
4160             break;
4161         }
4162         case VOGL_ENTRYPOINT_glBindFramebuffer:
4163         case VOGL_ENTRYPOINT_glBindFramebufferEXT:
4164         {
4165             GLenum target = trace_packet.get_param_value<GLenum>(0);
4166             GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
4167
4168             GLuint replay_handle = map_handle(get_context_state()->m_framebuffers, trace_handle);
4169
4170             SWITCH_GL_ENTRYPOINT2_VOID(glBindFramebuffer, glBindFramebufferEXT, target, replay_handle);
4171
4172             break;
4173         }
4174         case VOGL_ENTRYPOINT_glGetRenderbufferParameterivEXT:
4175         case VOGL_ENTRYPOINT_glGetRenderbufferParameteriv:
4176         {
4177             if (!benchmark_mode())
4178             {
4179                 GLenum target = trace_packet.get_param_value<GLenum>(0);
4180                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
4181                 GLint *pTrace_params = trace_packet.get_param_client_memory<GLint>(2);
4182                 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
4183                 uint trace_params_count = trace_params_size / sizeof(GLint);
4184
4185                 int n = g_gl_enums.get_pname_count(pname);
4186                 if (n <= 0)
4187                 {
4188                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
4189                     return cStatusSoftFailure;
4190                 }
4191                 else if (n < static_cast<int>(trace_params_count))
4192                 {
4193                     process_entrypoint_error("%s: Expected %i GLint's for GL pname 0x%08X, but trace only contains %i GLint's\n", VOGL_METHOD_NAME, n, pname, trace_params_count);
4194                     return cStatusSoftFailure;
4195                 }
4196                 else
4197                 {
4198                     vogl::growable_array<GLint, 16> params(n + 1);
4199                     params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4200
4201                     SWITCH_GL_ENTRYPOINT2_VOID(glGetRenderbufferParameteriv, glGetRenderbufferParameterivEXT, target, pname, params.get_ptr());
4202
4203                     VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
4204
4205                     if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLint)) != 0)
4206                     {
4207                         process_entrypoint_warning("%s: Replay's returned GLint data differed from trace's, pname %s target %s\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(pname), g_gl_enums.find_gl_name(target));
4208                     }
4209                 }
4210             }
4211
4212             break;
4213         }
4214         case VOGL_ENTRYPOINT_glCheckFramebufferStatus:
4215         case VOGL_ENTRYPOINT_glCheckFramebufferStatusEXT:
4216         {
4217             GLenum result;
4218             SWITCH_GL_ENTRYPOINT2(glCheckFramebufferStatus, glCheckFramebufferStatusEXT, trace_packet.get_param_value<GLenum>(0));
4219
4220             GLenum trace_status = trace_packet.get_return_value<GLenum>();
4221             if (result != trace_status)
4222             {
4223                 process_entrypoint_warning("%s: glCheckFramebufferStatus returned status 0x%08X during trace, but status 0x%08X during replay\n", VOGL_METHOD_NAME, trace_status, result);
4224             }
4225             break;
4226         }
4227         case VOGL_ENTRYPOINT_glDeleteFramebuffers:
4228         {
4229             delete_handles(get_context_state()->m_framebuffers, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteFramebuffers));
4230             break;
4231         }
4232         case VOGL_ENTRYPOINT_glDeleteFramebuffersEXT:
4233         {
4234             delete_handles(get_context_state()->m_framebuffers, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteFramebuffersEXT));
4235             break;
4236         }
4237         case VOGL_ENTRYPOINT_glFramebufferTexture:
4238         {
4239             GLenum target = trace_packet.get_param_value<GLenum>(0);
4240             GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4241             GLuint trace_texture = trace_packet.get_param_value<GLuint>(2);
4242             GLuint replay_texture = trace_texture;
4243             GLint level = trace_packet.get_param_value<GLint>(3);
4244
4245             if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4246             {
4247                 if (trace_texture)
4248                     process_entrypoint_warning("%s: Couldn't map trace texture ID %u to GL texture ID, using trace texture ID instead\n", VOGL_METHOD_NAME, trace_texture);
4249             }
4250
4251             GL_ENTRYPOINT(glFramebufferTexture)(target, attachment, replay_texture, level);
4252
4253             break;
4254         }
4255         case VOGL_ENTRYPOINT_glFramebufferTextureLayer:
4256         case VOGL_ENTRYPOINT_glFramebufferTextureLayerEXT:
4257         {
4258             GLenum target = trace_packet.get_param_value<GLenum>(0);
4259             GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4260             GLuint trace_texture = trace_packet.get_param_value<GLuint>(2);
4261             GLuint replay_texture = trace_texture;
4262             GLint level = trace_packet.get_param_value<GLint>(3);
4263             GLint layer = trace_packet.get_param_value<GLint>(4);
4264
4265             if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4266             {
4267                 if (trace_texture)
4268                     process_entrypoint_warning("%s: Couldn't map trace texture ID %u to GL texture ID, using trace texture ID instead\n", VOGL_METHOD_NAME, trace_texture);
4269             }
4270
4271             SWITCH_GL_ENTRYPOINT2_VOID(glFramebufferTextureLayer, glFramebufferTextureLayerEXT, target, attachment, replay_texture, level, layer);
4272
4273             break;
4274         }
4275         case VOGL_ENTRYPOINT_glFramebufferTexture1DEXT:
4276         case VOGL_ENTRYPOINT_glFramebufferTexture1D:
4277         case VOGL_ENTRYPOINT_glFramebufferTexture2DEXT:
4278         case VOGL_ENTRYPOINT_glFramebufferTexture2D:
4279         case VOGL_ENTRYPOINT_glFramebufferTexture3DEXT:
4280         case VOGL_ENTRYPOINT_glFramebufferTexture3D:
4281         {
4282             GLenum target = trace_packet.get_param_value<GLenum>(0);
4283             GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4284             GLenum textarget = trace_packet.get_param_value<GLenum>(2);
4285             GLuint trace_texture = trace_packet.get_param_value<GLuint>(3);
4286             GLuint replay_texture = trace_texture;
4287             GLint level = trace_packet.get_param_value<GLint>(4);
4288
4289             if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4290             {
4291                 if (trace_texture)
4292                     process_entrypoint_warning("%s: Couldn't map trace texture ID %u to GL texture ID, using trace texture ID instead\n", VOGL_METHOD_NAME, trace_texture);
4293             }
4294
4295             switch (entrypoint_id)
4296             {
4297                 case VOGL_ENTRYPOINT_glFramebufferTexture1DEXT:
4298                     GL_ENTRYPOINT(glFramebufferTexture1DEXT)(target, attachment, textarget, replay_texture, level);
4299                     break;
4300                 case VOGL_ENTRYPOINT_glFramebufferTexture1D:
4301                     GL_ENTRYPOINT(glFramebufferTexture1D)(target, attachment, textarget, replay_texture, level);
4302                     break;
4303                 case VOGL_ENTRYPOINT_glFramebufferTexture2DEXT:
4304                     GL_ENTRYPOINT(glFramebufferTexture2DEXT)(target, attachment, textarget, replay_texture, level);
4305                     break;
4306                 case VOGL_ENTRYPOINT_glFramebufferTexture2D:
4307                     GL_ENTRYPOINT(glFramebufferTexture2D)(target, attachment, textarget, replay_texture, level);
4308                     break;
4309                 case VOGL_ENTRYPOINT_glFramebufferTexture3DEXT:
4310                     GL_ENTRYPOINT(glFramebufferTexture3DEXT)(target, attachment, textarget, replay_texture, level, trace_packet.get_param_value<GLint>(5));
4311                     break;
4312                 case VOGL_ENTRYPOINT_glFramebufferTexture3D:
4313                     GL_ENTRYPOINT(glFramebufferTexture3D)(target, attachment, textarget, replay_texture, level, trace_packet.get_param_value<GLint>(5));
4314                     break;
4315                 default:
4316                     break;
4317             }
4318
4319             break;
4320         }
4321         case VOGL_ENTRYPOINT_glGenTextures:
4322         {
4323             if (!gen_handles(get_shared_state()->m_shadow_state.m_textures, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glGenTextures), NULL, GL_NONE))
4324                 return cStatusHardFailure;
4325             break;
4326         }
4327         case VOGL_ENTRYPOINT_glGenTexturesEXT:
4328         {
4329             if (!gen_handles(get_shared_state()->m_shadow_state.m_textures, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glGenTexturesEXT), NULL, GL_NONE))
4330                 return cStatusHardFailure;
4331             break;
4332         }
4333         case VOGL_ENTRYPOINT_glDeleteTextures:
4334         {
4335             delete_handles(get_shared_state()->m_shadow_state.m_textures, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteTextures));
4336             break;
4337         }
4338         case VOGL_ENTRYPOINT_glDeleteTexturesEXT:
4339         {
4340             delete_handles(get_shared_state()->m_shadow_state.m_textures, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteTexturesEXT));
4341             break;
4342         }
4343         case VOGL_ENTRYPOINT_glBindMultiTextureEXT:
4344         {
4345             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindMultiTextureEXT;
4346
4347             GLuint trace_texture = texture;
4348             map_handle(get_shared_state()->m_shadow_state.m_textures, trace_texture, texture);
4349
4350             if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4351                 check_gl_error();
4352
4353             VOGL_REPLAY_CALL_GL_HELPER_glBindMultiTextureEXT;
4354
4355             if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4356             {
4357                 if (!check_gl_error())
4358                     get_shared_state()->m_shadow_state.m_textures.update(trace_texture, texture, target);
4359             }
4360
4361             break;
4362         }
4363         case VOGL_ENTRYPOINT_glBindTexture:
4364         case VOGL_ENTRYPOINT_glBindTextureEXT:
4365         {
4366             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindTexture;
4367
4368             GLuint trace_texture = texture;
4369             map_handle(get_shared_state()->m_shadow_state.m_textures, trace_texture, texture);
4370
4371             if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4372                 check_gl_error();
4373
4374             SWITCH_GL_ENTRYPOINT2_VOID(glBindTexture, glBindTextureEXT, target, texture);
4375
4376             if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4377             {
4378                 if (!check_gl_error())
4379                     get_shared_state()->m_shadow_state.m_textures.update(trace_texture, texture, target);
4380             }
4381
4382             break;
4383         }
4384         case VOGL_ENTRYPOINT_glBindSampler:
4385         {
4386             GLuint replay_handle = map_handle(get_shared_state()->m_sampler_objects, trace_packet.get_param_value<GLuint>(1));
4387             GL_ENTRYPOINT(glBindSampler)(trace_packet.get_param_value<GLuint>(0), replay_handle);
4388             break;
4389         }
4390         case VOGL_ENTRYPOINT_glDeleteSamplers:
4391         {
4392             delete_handles(get_shared_state()->m_sampler_objects, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteSamplers));
4393             break;
4394         }
4395         case VOGL_ENTRYPOINT_glGenSamplers:
4396         {
4397             if (!gen_handles(get_shared_state()->m_sampler_objects, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glGenSamplers), NULL))
4398                 return cStatusHardFailure;
4399             break;
4400         }
4401
4402         case VOGL_ENTRYPOINT_glSamplerParameterf:
4403         {
4404             VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterf;
4405             sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4406             VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterf;
4407             break;
4408         }
4409         case VOGL_ENTRYPOINT_glSamplerParameteri:
4410         {
4411             VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameteri;
4412             sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4413             VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameteri;
4414             break;
4415         }
4416         case VOGL_ENTRYPOINT_glSamplerParameterfv:
4417         {
4418             VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterfv;
4419             sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4420             VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterfv;
4421             break;
4422         }
4423         case VOGL_ENTRYPOINT_glSamplerParameteriv:
4424         {
4425             VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameteriv;
4426             sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4427             VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameteriv;
4428             break;
4429         }
4430         case VOGL_ENTRYPOINT_glSamplerParameterIiv:
4431         {
4432             VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterIiv;
4433             sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4434             VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterIiv;
4435             break;
4436         }
4437         case VOGL_ENTRYPOINT_glSamplerParameterIuiv:
4438         {
4439             VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterIuiv;
4440             sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4441             VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterIuiv;
4442             break;
4443         }
4444         case VOGL_ENTRYPOINT_glGenBuffers:
4445         case VOGL_ENTRYPOINT_glGenBuffersARB:
4446         {
4447             uint n = trace_packet.get_param_value<GLsizei>(0);
4448             const GLuint *pTrace_handles = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4449
4450             if (entrypoint_id == VOGL_ENTRYPOINT_glGenBuffers)
4451             {
4452                 if (!gen_handles(get_shared_state()->m_buffers, n, pTrace_handles, GL_ENTRYPOINT(glGenBuffers), NULL))
4453                     return cStatusHardFailure;
4454             }
4455             else
4456             {
4457                 if (!gen_handles(get_shared_state()->m_buffers, n, pTrace_handles, GL_ENTRYPOINT(glGenBuffersARB), NULL))
4458                     return cStatusHardFailure;
4459             }
4460
4461             if (pTrace_handles)
4462             {
4463                 for (uint i = 0; i < n; i++)
4464                 {
4465                     if (pTrace_handles[i])
4466                         get_shared_state()->m_buffer_targets.insert(pTrace_handles[i], GL_NONE);
4467                 }
4468             }
4469
4470             break;
4471         }
4472         case VOGL_ENTRYPOINT_glDeleteBuffers:
4473         case VOGL_ENTRYPOINT_glDeleteBuffersARB:
4474         {
4475             GLsizei trace_n = trace_packet.get_param_value<GLsizei>(0);
4476             const GLuint *pTrace_ids = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4477             uint trace_ids_count = trace_packet.get_param_client_memory_data_size(1);
4478
4479             if ((pTrace_ids) && (static_cast<GLsizei>(trace_ids_count) < trace_n))
4480             {
4481                 process_entrypoint_warning("%s: trace_ids trace array is too small\n", VOGL_METHOD_NAME);
4482                 return cStatusHardFailure;
4483             }
4484
4485             for (GLsizei iter = 0; iter < trace_n; iter++)
4486             {
4487                 GLuint trace_id = pTrace_ids[iter];
4488                 if (!trace_id)
4489                     continue;
4490
4491                 if (!get_shared_state()->m_buffer_targets.erase(trace_id))
4492                 {
4493                     process_entrypoint_warning("%s: Couldn't find trace buffer id %u in buffer target map!\n", VOGL_METHOD_NAME, trace_id);
4494                 }
4495
4496                 gl_handle_hash_map::const_iterator it = get_shared_state()->m_buffers.find(trace_id);
4497                 if (it == get_shared_state()->m_buffers.end())
4498                 {
4499                     process_entrypoint_warning("%s: Couldn't map trace buffer id %u to GL buffer id\n", VOGL_METHOD_NAME, trace_id);
4500                     continue;
4501                 }
4502
4503                 GLuint replay_id = it->second;
4504
4505                 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
4506
4507                 for (uint i = 0; i < mapped_bufs.size(); i++)
4508                 {
4509                     if (mapped_bufs[i].m_buffer == replay_id)
4510                     {
4511                         process_entrypoint_warning("%s: glDeleteBuffers() called on mapped trace buffer %u GL buffer %u\n", VOGL_METHOD_NAME, trace_id, replay_id);
4512
4513                         mapped_bufs.erase_unordered(i);
4514                         break;
4515                     }
4516                 }
4517             }
4518
4519             if (entrypoint_id == VOGL_ENTRYPOINT_glDeleteBuffers)
4520                 delete_handles(get_shared_state()->m_buffers, trace_n, pTrace_ids, GL_ENTRYPOINT(glDeleteBuffers));
4521             else
4522                 delete_handles(get_shared_state()->m_buffers, trace_n, pTrace_ids, GL_ENTRYPOINT(glDeleteBuffersARB));
4523
4524             break;
4525         }
4526         case VOGL_ENTRYPOINT_glGenProgramsARB:
4527         {
4528             // arb program objects
4529             VOGL_REPLAY_LOAD_PARAMS_HELPER_glGenProgramsARB;
4530
4531             if (!gen_handles(get_shared_state()->m_arb_programs, n, pTrace_programs, GL_ENTRYPOINT(glGenProgramsARB), NULL))
4532                 return cStatusHardFailure;
4533
4534             for (GLsizei i = 0; (pTrace_programs) && (i < n); i++)
4535                 if (pTrace_programs[i])
4536                     get_shared_state()->m_arb_program_targets.insert(pTrace_programs[i], GL_NONE);
4537
4538             break;
4539         }
4540         case VOGL_ENTRYPOINT_glDeleteProgramsARB:
4541         {
4542             // arb program objects
4543             VOGL_REPLAY_LOAD_PARAMS_HELPER_glDeleteProgramsARB;
4544
4545             for (GLsizei i = 0; (pTrace_programs) && (i < n); i++)
4546                 get_shared_state()->m_arb_program_targets.erase(pTrace_programs[i]);
4547
4548             delete_handles(get_shared_state()->m_arb_programs, n, pTrace_programs, GL_ENTRYPOINT(glDeleteProgramsARB));
4549             break;
4550         }
4551         case VOGL_ENTRYPOINT_glBindProgramARB:
4552         {
4553             // arb program objects
4554             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindProgramARB;
4555
4556             GLuint trace_program = program;
4557             gl_handle_hash_map::const_iterator it;
4558             if (program)
4559             {
4560                 it = get_shared_state()->m_arb_programs.find(program);
4561                 if (it != get_shared_state()->m_arb_programs.end())
4562                     program = it->second;
4563                 else
4564                     process_entrypoint_warning("%s: Couldn't map trace handle %u to GL handle, using trace handle instead (handle may not have been genned)\n", VOGL_METHOD_NAME, program);
4565             }
4566
4567             check_gl_error();
4568
4569             VOGL_REPLAY_CALL_GL_HELPER_glBindProgramARB;
4570
4571             if (!check_gl_error() && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4572             {
4573                 if (trace_program)
4574                 {
4575                     if (it == get_shared_state()->m_arb_programs.end())
4576                         get_shared_state()->m_arb_programs.insert(trace_program, program);
4577
4578                     get_shared_state()->m_arb_program_targets[trace_program] = target;
4579                 }
4580             }
4581             else
4582             {
4583                 process_entrypoint_warning("%s: GL error while binding ARB program, trace handle %u GL handle %u target %s\n", VOGL_METHOD_NAME, trace_program, program, g_gl_enums.find_gl_name(target));
4584                 return cStatusGLError;
4585             }
4586
4587             break;
4588         }
4589         case VOGL_ENTRYPOINT_glIsProgramARB:
4590         {
4591             if (!benchmark_mode())
4592             {
4593                 VOGL_REPLAY_LOAD_PARAMS_HELPER_glIsProgramARB;
4594
4595                 GLuint trace_program = program;
4596                 program = map_handle(get_shared_state()->m_arb_programs, program);
4597
4598                 GLboolean replay_result = VOGL_REPLAY_CALL_GL_HELPER_glIsProgramARB;
4599                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4600
4601                 if (trace_result != replay_result)
4602                     process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u, trace ARB program: %u replay ARB program %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result), trace_program, program);
4603             }
4604
4605             break;
4606         }
4607         case VOGL_ENTRYPOINT_glGenQueries:
4608         case VOGL_ENTRYPOINT_glGenQueriesARB:
4609         {
4610             GLsizei n = trace_packet.get_param_value<GLsizei>(0);
4611             vogl::growable_array<GLuint, 16> replay_handles(n);
4612
4613             if (!gen_handles(get_shared_state()->m_queries, n, static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), (entrypoint_id == VOGL_ENTRYPOINT_glGenQueries) ? GL_ENTRYPOINT(glGenQueries) : GL_ENTRYPOINT(glGenQueriesARB), replay_handles.get_ptr()))
4614                 return cStatusHardFailure;
4615
4616             for (GLsizei i = 0; i < n; i++)
4617                 get_shared_state()->m_query_targets[replay_handles[i]] = GL_NONE;
4618
4619             break;
4620         }
4621         case VOGL_ENTRYPOINT_glDeleteQueries:
4622         case VOGL_ENTRYPOINT_glDeleteQueriesARB:
4623         {
4624             GLsizei n = trace_packet.get_param_value<GLsizei>(0);
4625             const GLuint *pTrace_ids = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4626
4627             if (pTrace_ids)
4628             {
4629                 for (GLsizei i = 0; i < n; i++)
4630                 {
4631                     GLuint trace_id = pTrace_ids[i];
4632                     if (!trace_id)
4633                         continue;
4634                     gl_handle_hash_map::const_iterator it(get_shared_state()->m_queries.find(trace_id));
4635                     if (it != get_shared_state()->m_queries.end())
4636                         get_shared_state()->m_query_targets.erase(it->second);
4637                 }
4638             }
4639
4640             if (entrypoint_id == VOGL_ENTRYPOINT_glDeleteQueries)
4641                 delete_handles(get_shared_state()->m_queries, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteQueries));
4642             else
4643                 delete_handles(get_shared_state()->m_queries, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteQueriesARB));
4644
4645             break;
4646         }
4647         case VOGL_ENTRYPOINT_glGenRenderbuffersEXT:
4648         {
4649             if (!gen_handles(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glGenRenderbuffersEXT), NULL, GL_NONE))
4650                 return cStatusHardFailure;
4651             break;
4652         }
4653         case VOGL_ENTRYPOINT_glGenRenderbuffers:
4654         {
4655             if (!gen_handles(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glGenRenderbuffers), NULL, GL_NONE))
4656                 return cStatusHardFailure;
4657             break;
4658         }
4659         case VOGL_ENTRYPOINT_glDeleteRenderbuffersEXT:
4660         {
4661             delete_handles(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteRenderbuffersEXT));
4662             break;
4663         }
4664         case VOGL_ENTRYPOINT_glDeleteRenderbuffers:
4665         {
4666             delete_handles(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteRenderbuffers));
4667             break;
4668         }
4669         case VOGL_ENTRYPOINT_glIsRenderbuffer:
4670         {
4671             if (!benchmark_mode())
4672             {
4673                 GLboolean replay_result = GL_ENTRYPOINT(glIsRenderbuffer)(map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(0)));
4674                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4675                 if (replay_result != trace_result)
4676                 {
4677                     process_entrypoint_warning("%s: Replay's returned GLboolean data differed from trace's (got %i, expected %i)\n", VOGL_METHOD_NAME, replay_result, replay_result);
4678                 }
4679             }
4680             break;
4681         }
4682         case VOGL_ENTRYPOINT_glIsRenderbufferEXT:
4683         {
4684             if (!benchmark_mode())
4685             {
4686                 GLboolean replay_result = GL_ENTRYPOINT(glIsRenderbufferEXT)(map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(0)));
4687                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4688                 if (replay_result != trace_result)
4689                 {
4690                     process_entrypoint_warning("%s: Replay's returned GLboolean data differed from trace's (got %i, expected %i)\n", VOGL_METHOD_NAME, replay_result, replay_result);
4691                 }
4692             }
4693             break;
4694         }
4695         case VOGL_ENTRYPOINT_glBindRenderbufferEXT:
4696         {
4697             GL_ENTRYPOINT(glBindRenderbufferEXT)(trace_packet.get_param_value<GLenum>(0), map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(1)));
4698             break;
4699         }
4700         case VOGL_ENTRYPOINT_glBindRenderbuffer:
4701         {
4702             GL_ENTRYPOINT(glBindRenderbuffer)(trace_packet.get_param_value<GLenum>(0), map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(1)));
4703             break;
4704         }
4705         case VOGL_ENTRYPOINT_glFramebufferRenderbufferEXT:
4706         {
4707             GL_ENTRYPOINT(glFramebufferRenderbufferEXT)(
4708                 trace_packet.get_param_value<GLenum>(0),
4709                 trace_packet.get_param_value<GLenum>(1),
4710                 trace_packet.get_param_value<GLenum>(2),
4711                 map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(3)));
4712             break;
4713         }
4714         case VOGL_ENTRYPOINT_glFramebufferRenderbuffer:
4715         {
4716             GL_ENTRYPOINT(glFramebufferRenderbuffer)(
4717                 trace_packet.get_param_value<GLenum>(0),
4718                 trace_packet.get_param_value<GLenum>(1),
4719                 trace_packet.get_param_value<GLenum>(2),
4720                 map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(3)));
4721             break;
4722         }
4723         case VOGL_ENTRYPOINT_glUseProgramObjectARB:
4724         case VOGL_ENTRYPOINT_glUseProgram:
4725         {
4726             GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
4727             handle_use_program(trace_handle, entrypoint_id);
4728             break;
4729         }
4730         case VOGL_ENTRYPOINT_glProgramParameteri:
4731         case VOGL_ENTRYPOINT_glProgramParameteriARB:
4732         case VOGL_ENTRYPOINT_glProgramParameteriEXT:
4733         {
4734             VOGL_REPLAY_LOAD_PARAMS_HELPER_glProgramParameteri;
4735
4736             program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4737
4738             if (entrypoint_id == VOGL_ENTRYPOINT_glProgramParameteriARB)
4739                 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteriARB;
4740             else if (entrypoint_id == VOGL_ENTRYPOINT_glProgramParameteriEXT)
4741                 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteriEXT;
4742             else
4743                 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteri;
4744
4745             break;
4746         }
4747         case VOGL_ENTRYPOINT_glBindFragDataLocation:
4748         case VOGL_ENTRYPOINT_glBindFragDataLocationEXT:
4749         {
4750             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindFragDataLocation;
4751
4752             program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4753
4754             if (entrypoint_id == VOGL_ENTRYPOINT_glBindFragDataLocation)
4755                 VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocation;
4756             else
4757                 VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocationEXT;
4758
4759             break;
4760         }
4761         case VOGL_ENTRYPOINT_glBindFragDataLocationIndexed:
4762         {
4763             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindFragDataLocationIndexed;
4764
4765             program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4766
4767             VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocationIndexed;
4768
4769             break;
4770         }
4771         case VOGL_ENTRYPOINT_glValidateProgramARB:
4772         {
4773             VOGL_REPLAY_LOAD_PARAMS_HELPER_glValidateProgramARB;
4774
4775             programObj = map_handle(get_shared_state()->m_shadow_state.m_objs, programObj);
4776
4777             VOGL_REPLAY_CALL_GL_HELPER_glValidateProgramARB;
4778
4779             break;
4780         }
4781         case VOGL_ENTRYPOINT_glValidateProgram:
4782         {
4783             VOGL_REPLAY_LOAD_PARAMS_HELPER_glValidateProgram;
4784
4785             program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4786
4787             VOGL_REPLAY_CALL_GL_HELPER_glValidateProgram;
4788
4789             break;
4790         }
4791         case VOGL_ENTRYPOINT_glCreateProgram:
4792         case VOGL_ENTRYPOINT_glCreateProgramObjectARB:
4793         {
4794             GLuint trace_handle = trace_packet.get_return_value<GLuint>();
4795             if (trace_handle)
4796             {
4797                 GLuint replay_handle;
4798
4799                 if (entrypoint_id == VOGL_ENTRYPOINT_glCreateProgram)
4800                     replay_handle = GL_ENTRYPOINT(glCreateProgram)();
4801                 else
4802                     replay_handle = GL_ENTRYPOINT(glCreateProgramObjectARB)();
4803
4804                 VOGL_ASSERT(!replay_handle || (GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0));
4805
4806                 if (!gen_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle, replay_handle, VOGL_PROGRAM_OBJECT))
4807                     return cStatusHardFailure;
4808             }
4809             break;
4810         }
4811         case VOGL_ENTRYPOINT_glDeleteProgram:
4812         {
4813             GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
4814             handle_delete_program(trace_handle);
4815
4816             break;
4817         }
4818         case VOGL_ENTRYPOINT_glDeleteObjectARB:
4819         {
4820             GLuint trace_handle = trace_packet.get_param_value<GLenum>(0);
4821             GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle);
4822
4823             if (target == VOGL_SHADER_OBJECT)
4824                 handle_delete_shader(trace_handle);
4825             else if (target == VOGL_PROGRAM_OBJECT)
4826                 handle_delete_program(trace_handle);
4827             else
4828             {
4829                 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
4830
4831                 process_entrypoint_error("%s: Failed determining if trace handle %u relay handle %u is a shader or program -- unable to delete object!\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
4832                 return cStatusSoftFailure;
4833             }
4834
4835             break;
4836         }
4837         case VOGL_ENTRYPOINT_glDeleteShader:
4838         {
4839             GLuint trace_shader = trace_packet.get_param_value<GLuint>(0);
4840             handle_delete_shader(trace_shader);
4841
4842             break;
4843         }
4844         case VOGL_ENTRYPOINT_glCreateShader:
4845         case VOGL_ENTRYPOINT_glCreateShaderObjectARB:
4846         {
4847             GLuint trace_handle = trace_packet.get_return_value<GLuint>();
4848             if (trace_handle)
4849             {
4850                 GLuint replay_handle;
4851
4852                 if (entrypoint_id == VOGL_ENTRYPOINT_glCreateShader)
4853                     replay_handle = GL_ENTRYPOINT(glCreateShader)(trace_packet.get_param_value<GLenum>(0));
4854                 else
4855                     replay_handle = GL_ENTRYPOINT(glCreateShaderObjectARB)(trace_packet.get_param_value<GLenum>(0));
4856
4857                 VOGL_ASSERT(!replay_handle || (GL_ENTRYPOINT(glIsShader)(replay_handle) != 0));
4858
4859                 if (!gen_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle, replay_handle, VOGL_SHADER_OBJECT))
4860                     return cStatusHardFailure;
4861             }
4862             break;
4863         }
4864         case VOGL_ENTRYPOINT_glAttachShader:
4865         {
4866             GL_ENTRYPOINT(glAttachShader)(
4867                 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)),
4868                 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(1)));
4869             break;
4870         }
4871         case VOGL_ENTRYPOINT_glAttachObjectARB:
4872         {
4873             GL_ENTRYPOINT(glAttachObjectARB)(
4874                 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4875                 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(1)));
4876             break;
4877         }
4878         case VOGL_ENTRYPOINT_glDetachShader:
4879         {
4880             handle_detach_shader(entrypoint_id);
4881
4882             break;
4883         }
4884         case VOGL_ENTRYPOINT_glDetachObjectARB:
4885         {
4886             GLhandleARB trace_object_handle = trace_packet.get_param_value<GLhandleARB>(1);
4887
4888             GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target(trace_object_handle);
4889
4890             if (target == VOGL_SHADER_OBJECT)
4891                 handle_detach_shader(entrypoint_id);
4892             else
4893             {
4894                 GLuint replay_object_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object_handle);
4895                 GL_ENTRYPOINT(glDetachObjectARB)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)), replay_object_handle);
4896             }
4897
4898             break;
4899         }
4900         case VOGL_ENTRYPOINT_glBindAttribLocation:
4901         {
4902             GL_ENTRYPOINT(glBindAttribLocation)(
4903                 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)),
4904                 trace_packet.get_param_value<GLuint>(1),
4905                 trace_packet.get_param_client_memory<GLchar>(2));
4906             break;
4907         }
4908         case VOGL_ENTRYPOINT_glBindAttribLocationARB:
4909         {
4910             GL_ENTRYPOINT(glBindAttribLocationARB)(
4911                 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4912                 trace_packet.get_param_value<GLuint>(1),
4913                 trace_packet.get_param_client_memory<GLcharARB>(2));
4914             break;
4915         }
4916         case VOGL_ENTRYPOINT_glGetObjectParameterivARB:
4917         {
4918             if (!benchmark_mode())
4919             {
4920                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
4921                 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
4922
4923                 int n = g_gl_enums.get_pname_count(pname);
4924                 if (n <= 0)
4925                 {
4926                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
4927                     return cStatusSoftFailure;
4928                 }
4929                 else
4930                 {
4931                     vogl::growable_array<GLint, 16> params(n + 1);
4932                     params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4933
4934                     GL_ENTRYPOINT(glGetObjectParameterivARB)(
4935                         map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4936                         pname,
4937                         params.get_ptr());
4938
4939                     VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
4940
4941                     if (memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
4942                     {
4943                         process_entrypoint_warning("%s: Replay's returned GLint data differed from trace's, pname %s\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(pname));
4944                     }
4945                 }
4946             }
4947             break;
4948         }
4949         case VOGL_ENTRYPOINT_glGetBufferParameteriv:
4950         {
4951             if (!benchmark_mode())
4952             {
4953                 GLenum target = trace_packet.get_param_value<GLenum>(0);
4954                 GLenum value = trace_packet.get_param_value<GLenum>(1);
4955                 const GLint *pTrace_data = trace_packet.get_param_client_memory<GLint>(2);
4956
4957                 int n = g_gl_enums.get_pname_count(value);
4958                 if (n <= 0)
4959                 {
4960                     process_entrypoint_error("%s: Can't determine count of GL value 0x%08X\n", VOGL_METHOD_NAME, value);
4961                     return cStatusSoftFailure;
4962                 }
4963                 else
4964                 {
4965                     vogl::growable_array<GLint, 16> data(n + 1);
4966                     data[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4967
4968                     GL_ENTRYPOINT(glGetBufferParameteriv)(target, value, data.get_ptr());
4969
4970                     VOGL_VERIFY(data[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
4971
4972                     GLint trace_data = pTrace_data ? pTrace_data[0] : -1;
4973                     if (data[0] != trace_data)
4974                     {
4975                         process_entrypoint_warning("%s: Replay's returned GLint differed from trace's!\n", VOGL_METHOD_NAME);
4976                         vogl_warning_printf("Trace data: %i, Replay data: %i\n", trace_data, data[0]);
4977                     }
4978                 }
4979             }
4980
4981             break;
4982         }
4983
4984         case VOGL_ENTRYPOINT_glGetBufferPointerv:
4985         {
4986             if (!benchmark_mode())
4987             {
4988                 GLvoid *pReplay_ptr = NULL;
4989                 GL_ENTRYPOINT(glGetBufferPointerv)(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLenum>(1), &pReplay_ptr);
4990
4991                 vogl_client_memory_array trace_void_ptr_array = trace_packet.get_param_client_memory_array(2);
4992                 vogl_trace_ptr_value first_trace_ptr = trace_void_ptr_array.get_ptr() ? trace_void_ptr_array.get_element<vogl_trace_ptr_value>(0) : 0;
4993
4994                 if ((pReplay_ptr != NULL) != (first_trace_ptr != 0))
4995                 {
4996                     process_entrypoint_warning("%s: First replay's returned GLvoid* differed from trace's!\n", VOGL_METHOD_NAME);
4997                     vogl_warning_printf("Trace: 0x%" PRIx64 ", Replay: 0x%" PRIx64 "\n", first_trace_ptr, reinterpret_cast<uint64_t>(pReplay_ptr));
4998                 }
4999             }
5000
5001             break;
5002         }
5003         case VOGL_ENTRYPOINT_glShaderSource:
5004         case VOGL_ENTRYPOINT_glShaderSourceARB:
5005         {
5006             const status_t status = handle_ShaderSource(trace_packet.get_param_value<GLhandleARB>(0),
5007                                                         trace_packet.get_param_value<GLsizei>(1),
5008                                                         trace_packet.get_param_client_memory_array(2),
5009                                                         trace_packet.get_param_client_memory<const GLint>(3));
5010             if (status != cStatusOK)
5011                 return status;
5012             break;
5013         }
5014         case VOGL_ENTRYPOINT_glGetProgramInfoLog:
5015         {
5016             GLuint trace_object = trace_packet.get_param_value<GLuint>(0);
5017             GLuint replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
5018
5019             GLint length = -1;
5020             GL_ENTRYPOINT(glGetProgramiv)(replay_object, GL_INFO_LOG_LENGTH, &length);
5021             if (length < 0)
5022             {
5023                 process_entrypoint_error("%s: Failed retrieving info log length for trace object %u, reply object %u\n", VOGL_METHOD_NAME, trace_object, replay_object);
5024                 return cStatusSoftFailure;
5025             }
5026             else
5027             {
5028                 vogl::vector<GLchar> log(length);
5029
5030                 GLsizei actual_length = 0;
5031                 GL_ENTRYPOINT(glGetProgramInfoLog)(replay_object, length, &actual_length, log.get_ptr());
5032
5033                 if (actual_length)
5034                 {
5035                     process_entrypoint_message("%s: Info log for trace object %u, replay object %u:\n%s\n", VOGL_METHOD_NAME, trace_object, replay_object, log.get_ptr());
5036                 }
5037             }
5038
5039             break;
5040         }
5041         case VOGL_ENTRYPOINT_glGetPointerv:
5042         {
5043             if (!benchmark_mode())
5044             {
5045                 GLvoid *ptr = NULL;
5046                 GL_ENTRYPOINT(glGetPointerv)(trace_packet.get_param_value<GLenum>(0), &ptr);
5047
5048                 // TODO: Differ vs. trace's in some way?
5049             }
5050
5051             break;
5052         }
5053         case VOGL_ENTRYPOINT_glGetInfoLogARB:
5054         {
5055             GLhandleARB trace_object = trace_packet.get_param_value<GLhandleARB>(0);
5056             GLhandleARB replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
5057
5058             GLsizei length = -1;
5059             GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
5060             if (length < 0)
5061             {
5062                 process_entrypoint_error("%s: Failed retrieving info log length for trace object %u, reply object %u\n", VOGL_METHOD_NAME, trace_object, replay_object);
5063                 return cStatusSoftFailure;
5064             }
5065             else
5066             {
5067                 vogl::vector<GLcharARB> log(length);
5068
5069                 GLsizei actual_length = 0;
5070                 GL_ENTRYPOINT(glGetInfoLogARB)(replay_object, length, &actual_length, log.get_ptr());
5071
5072                 if (actual_length)
5073                 {
5074                     process_entrypoint_message("%s: Info log for trace object %u, replay object %u:\n%s\n", VOGL_METHOD_NAME, trace_object, replay_object, log.get_ptr());
5075                 }
5076             }
5077
5078             break;
5079         }
5080         case VOGL_ENTRYPOINT_glGetUniformLocation:
5081         {
5082             GLhandleARB trace_handle = trace_packet.get_param_value<GLhandleARB>(0);
5083             GLhandleARB replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5084             GLint trace_loc = trace_packet.get_return_value<GLint>();
5085
5086             if (replay_handle)
5087             {
5088                 const GLchar *pName = trace_packet.get_param_client_memory<GLchar>(1);
5089
5090                 GLint replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, pName);
5091                 if (replay_loc < 0)
5092                 {
5093                     if (trace_loc >= 0)
5094                         process_entrypoint_warning("%s: glGetUniformLocation: Function succeeded during trace, but failed during replay! (name: %s trace_handle: %u, trace_loc: %i)\n", VOGL_METHOD_NAME, (const char *)pName, trace_handle, trace_loc);
5095                 }
5096                 else
5097                 {
5098                     if (trace_loc < 0)
5099                         process_entrypoint_warning("%s: glGetUniformLocation: Function failed during trace, but succeeded during replay! (name: %s trace_handle: %u, trace_loc: %i)\n", VOGL_METHOD_NAME, (const char *)pName, trace_handle, trace_loc);
5100                     else
5101                     {
5102                         glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
5103                         if (it == get_shared_state()->m_glsl_program_hash_map.end())
5104                             it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
5105
5106                         glsl_program_state &state = it->second;
5107                         state.m_uniform_locations.erase(trace_loc);
5108                         state.m_uniform_locations.insert(trace_loc, replay_loc);
5109                     }
5110                 }
5111             }
5112
5113             break;
5114         }
5115         case VOGL_ENTRYPOINT_glGetUniformLocationARB:
5116         {
5117             GLhandleARB trace_handle = trace_packet.get_param_value<GLhandleARB>(0);
5118             GLhandleARB replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5119             GLint trace_loc = trace_packet.get_return_value<GLint>();
5120
5121             if (replay_handle)
5122             {
5123                 const GLcharARB *pName = trace_packet.get_param_client_memory<GLcharARB>(1);
5124
5125                 GLint replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, pName);
5126                 if (replay_loc < 0)
5127                 {
5128                     if (trace_loc >= 0)
5129                         process_entrypoint_warning("%s: glGetUniformLocationARB: Function succeeded during trace, but failed during replay! (name: %s trace_handle: %u, trace_loc: %i)\n", VOGL_METHOD_NAME, (const char *)pName, trace_handle, trace_loc);
5130                 }
5131                 else
5132                 {
5133                     if (trace_loc < 0)
5134                         process_entrypoint_warning("%s: glGetUniformLocationARB: Function failed during trace, but succeeded during replay! (name: %s trace_handle: %u, trace_loc: %i)\n", VOGL_METHOD_NAME, (const char *)pName, trace_handle, trace_loc);
5135                     else
5136                     {
5137                         glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
5138                         if (it == get_shared_state()->m_glsl_program_hash_map.end())
5139                             it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
5140
5141                         glsl_program_state &state = it->second;
5142                         state.m_uniform_locations.erase(trace_loc);
5143                         state.m_uniform_locations.insert(trace_loc, replay_loc);
5144                     }
5145                 }
5146             }
5147
5148             break;
5149         }
5150         case VOGL_ENTRYPOINT_glGetActiveAttrib:
5151         case VOGL_ENTRYPOINT_glGetActiveUniform:
5152         {
5153             if (!benchmark_mode())
5154             {
5155                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5156                 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5157
5158                 GLuint index = trace_packet.get_param_value<GLuint>(1);
5159                 GLsizei bufSize = trace_packet.get_param_value<GLsizei>(2);
5160
5161                 GLsizei *pTrace_length = trace_packet.get_param_client_memory<GLsizei>(3);
5162                 GLint *pTrace_size = trace_packet.get_param_client_memory<GLint>(4);
5163                 GLenum *pTrace_type = trace_packet.get_param_client_memory<GLenum>(5);
5164                 GLchar *pTrace_name = trace_packet.get_param_client_memory<GLchar>(6);
5165
5166                 vogl::growable_array<GLchar, 1024> name_buf(bufSize + 1); // + 1 guarantees non-empty and null terminated
5167
5168                 GLsizei len = 0;
5169                 GLint size = 0;
5170                 GLenum type = 0;
5171
5172                 if (entrypoint_id == VOGL_ENTRYPOINT_glGetActiveAttrib)
5173                     GL_ENTRYPOINT(glGetActiveAttrib)(replay_handle, index, bufSize, &len, &size, &type, name_buf.get_ptr());
5174                 else
5175                     GL_ENTRYPOINT(glGetActiveUniform)(replay_handle, index, bufSize, &len, &size, &type, name_buf.get_ptr());
5176
5177                 bool mismatch = false;
5178
5179                 GLsizei trace_len = 0;
5180                 if (pTrace_length)
5181                 {
5182                     trace_len = pTrace_length[0];
5183                     if (trace_len != len)
5184                         mismatch = true;
5185                 }
5186
5187                 GLint trace_size = 0;
5188                 if (pTrace_size)
5189                 {
5190                     trace_size = pTrace_size[0];
5191                     if (trace_size != size)
5192                         mismatch = true;
5193                 }
5194
5195                 GLenum trace_type = 0;
5196                 if (pTrace_type)
5197                 {
5198                     trace_type = pTrace_type[0];
5199                     if (trace_type != type)
5200                         mismatch = true;
5201                 }
5202
5203                 if ((bufSize) && (pTrace_name))
5204                 {
5205                     uint n = vogl_strlen((const char *)pTrace_name) + 1;
5206                     if (bufSize < (GLsizei)n)
5207                         mismatch = true;
5208                     else if (memcmp(name_buf.get_ptr(), pTrace_name, n) != 0)
5209                         mismatch = true;
5210                 }
5211
5212                 if (mismatch)
5213                 {
5214                     process_entrypoint_warning("%s: Replay of %s returned data differed from trace's\n", VOGL_METHOD_NAME, trace_packet.get_entrypoint_desc().m_pName);
5215                     vogl_warning_printf("Trace handle: %u, index: %u, bufSize: %u, trace_len: %u, trace_type: %u, name: %s\n",
5216                                        (uint)trace_handle, (uint)index, (uint)bufSize, (uint)trace_len, (uint)trace_type, (pTrace_name != NULL) ? (const char *)pTrace_name : "");
5217                     vogl_warning_printf("GL handle: %u, index: %u, bufSize: %u, trace_len: %u, trace_type: %u, name: %s\n",
5218                                        (uint)replay_handle, (uint)index, (uint)bufSize, (uint)len, (uint)type, name_buf.get_ptr());
5219                 }
5220             }
5221
5222             break;
5223         }
5224         case VOGL_ENTRYPOINT_glGetAttachedShaders:
5225         {
5226             if (!benchmark_mode())
5227             {
5228                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5229                 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5230
5231                 GLsizei max_count = trace_packet.get_param_value<GLsizei>(1);
5232                 GLsizei count = 0;
5233                 vogl::growable_array<GLuint, 16> shaders(max_count);
5234
5235                 GL_ENTRYPOINT(glGetAttachedShaders)(replay_handle, trace_packet.get_param_value<GLsizei>(1), &count, shaders.get_ptr());
5236
5237                 // TODO: Diff results
5238             }
5239
5240             break;
5241         }
5242         case VOGL_ENTRYPOINT_glGetAttribLocation:
5243         {
5244             if (!benchmark_mode())
5245             {
5246                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5247                 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5248
5249                 const GLchar *pName = trace_packet.get_param_client_memory<GLchar>(1);
5250
5251                 GLint replay_result = GL_ENTRYPOINT(glGetAttribLocation)(replay_handle, pName);
5252                 GLint trace_result = trace_packet.get_return_value<GLint>();
5253
5254                 if (replay_result != trace_result)
5255                 {
5256                     process_entrypoint_warning("%s: Replay of %s returned data differed from trace's\n", VOGL_METHOD_NAME, trace_packet.get_entrypoint_desc().m_pName);
5257                     vogl_warning_printf("Trace value: %i, replay: %i\n", trace_result, replay_result);
5258                 }
5259             }
5260
5261             break;
5262         }
5263         case VOGL_ENTRYPOINT_glGetProgramivARB:
5264         {
5265             if (!benchmark_mode())
5266             {
5267                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5268                 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
5269                 uint params_size = trace_packet.get_param_client_memory_data_size(2);
5270                 uint params_count = params_size / sizeof(GLint);
5271
5272                 int n = g_gl_enums.get_pname_count(pname);
5273                 if (n <= 0)
5274                 {
5275                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5276                     return cStatusSoftFailure;
5277                 }
5278                 else
5279                 {
5280                     vogl::growable_array<GLint, 16> params(n + 1);
5281                     params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5282
5283                     GL_ENTRYPOINT(glGetProgramivARB)(
5284                         trace_packet.get_param_value<GLenum>(0),
5285                         pname,
5286                         params.get_ptr());
5287
5288                     VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5289
5290                     if (params_count != static_cast<uint>(n))
5291                     {
5292                         process_entrypoint_warning("%s: Size of replay's params array differs from trace's\n", VOGL_METHOD_NAME);
5293                     }
5294                     else if (pParams && memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
5295                     {
5296                         process_entrypoint_warning("%s: Replay's returned GLint data differed from trace's, pname %s\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(pname));
5297                     }
5298                 }
5299             }
5300
5301             break;
5302         }
5303         case VOGL_ENTRYPOINT_glGetProgramiv:
5304         {
5305             if (!benchmark_mode())
5306             {
5307                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5308                 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5309
5310                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5311
5312                 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
5313                 uint params_size = trace_packet.get_param_client_memory_data_size(2);
5314                 uint params_count = params_size / sizeof(GLint);
5315
5316                 int n = g_gl_enums.get_pname_count(pname);
5317                 if (n <= 0)
5318                 {
5319                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5320                     return cStatusSoftFailure;
5321                 }
5322                 else
5323                 {
5324                     vogl::growable_array<GLint, 16> params(n + 1);
5325                     params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5326
5327                     GL_ENTRYPOINT(glGetProgramiv)(
5328                         replay_handle,
5329                         pname,
5330                         params.get_ptr());
5331
5332                     VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5333
5334                     if (params_count != static_cast<uint>(n))
5335                     {
5336                         process_entrypoint_warning("%s: Size of replay's params array differs from trace's\n", VOGL_METHOD_NAME);
5337                     }
5338                     else if (pParams && memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
5339                     {
5340                         process_entrypoint_warning("%s: Replay's returned GLint data differed from trace's, pname %s\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(pname));
5341                     }
5342                 }
5343             }
5344
5345             break;
5346         }
5347         case VOGL_ENTRYPOINT_glLinkProgram:
5348         case VOGL_ENTRYPOINT_glLinkProgramARB:
5349         case VOGL_ENTRYPOINT_glProgramBinary:
5350         {
5351             handle_link_program(entrypoint_id);
5352
5353             break;
5354         }
5355         case VOGL_ENTRYPOINT_glCompileShader:
5356         {
5357             GL_ENTRYPOINT(glCompileShader)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)));
5358             break;
5359         }
5360         case VOGL_ENTRYPOINT_glCompileShaderARB:
5361         {
5362             GL_ENTRYPOINT(glCompileShaderARB)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)));
5363             break;
5364         }
5365         case VOGL_ENTRYPOINT_glGetShaderiv:
5366         {
5367             if (!benchmark_mode())
5368             {
5369                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5370                 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5371
5372                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5373                 GLint params = 0;
5374
5375                 const GLint *pClient_params = trace_packet.get_param_client_memory<GLint>(2);
5376
5377                 GL_ENTRYPOINT(glGetShaderiv)(replay_handle, pname, &params);
5378
5379                 if ((pClient_params) && (*pClient_params != params))
5380                 {
5381                     process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
5382                     vogl_warning_printf("Trace data: %i, Replay data: %i\n", pClient_params ? *pClient_params : 0, params);
5383                 }
5384             }
5385
5386             break;
5387         }
5388         case VOGL_ENTRYPOINT_glGetShaderInfoLog:
5389         {
5390             GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5391             GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5392
5393             GLsizei trace_max_length = trace_packet.get_param_value<GLsizei>(1);
5394             const GLsizei *pTrace_length = trace_packet.get_param_client_memory<GLsizei>(2);
5395             VOGL_NOTE_UNUSED(pTrace_length);
5396             const GLchar *pTrace_info_log = trace_packet.get_param_client_memory<GLchar>(3);
5397             VOGL_NOTE_UNUSED(pTrace_info_log);
5398
5399             vogl::growable_array<GLchar, 512> log(trace_max_length);
5400             GLsizei length = 0;
5401             GL_ENTRYPOINT(glGetShaderInfoLog)(replay_handle, trace_max_length, &length, log.get_ptr());
5402
5403             if (length)
5404             {
5405                 process_entrypoint_message("%s: Info log for trace object %u, replay object %u:\n%s\n", VOGL_METHOD_NAME, trace_handle, replay_handle, log.get_ptr());
5406             }
5407
5408             break;
5409         }
5410         case VOGL_ENTRYPOINT_glGetBooleanv:
5411         {
5412             if (!benchmark_mode())
5413             {
5414                 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5415                 const GLboolean *pParams = trace_packet.get_param_client_memory<GLboolean>(1);
5416
5417                 int n = g_gl_enums.get_pname_count(pname);
5418                 if (n <= 0)
5419                 {
5420                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X (%s)\n", VOGL_METHOD_NAME, pname, g_gl_enums.find_gl_name(pname));
5421                     return cStatusSoftFailure;
5422                 }
5423                 else
5424                 {
5425                     vogl::growable_array<GLboolean, 16> params(n + 1);
5426                     params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_BYTE_MAGIC;
5427
5428                     GL_ENTRYPOINT(glGetBooleanv)(pname, params.get_ptr());
5429
5430                     VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_BYTE_MAGIC);
5431
5432                     if (memcmp(pParams, params.get_ptr(), n * sizeof(GLboolean)) != 0)
5433                     {
5434                         process_entrypoint_warning("%s: Replay's returned GLboolean data for pname 0x%08X (%s) differed from trace's\n", VOGL_METHOD_NAME, pname, g_gl_enums.find_gl_name(pname));
5435                     }
5436                 }
5437             }
5438
5439             break;
5440         }
5441         case VOGL_ENTRYPOINT_glGetDoublev:
5442         {
5443             if (!benchmark_mode())
5444             {
5445                 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5446                 const GLdouble *pParams = trace_packet.get_param_client_memory<GLdouble>(1);
5447
5448                 int n = g_gl_enums.get_pname_count(pname);
5449                 if (n <= 0)
5450                 {
5451                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5452                     return cStatusSoftFailure;
5453                 }
5454                 else
5455                 {
5456                     vogl::growable_array<GLdouble, 17> params(n + 1);
5457                     params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
5458
5459                     GL_ENTRYPOINT(glGetDoublev)(pname, params.get_ptr());
5460
5461                     VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
5462
5463                     if (memcmp(pParams, params.get_ptr(), n * sizeof(GLdouble)) != 0)
5464                     {
5465                         process_entrypoint_warning("%s: Replay's returned GLdouble data differed from trace's\n", VOGL_METHOD_NAME);
5466                     }
5467                 }
5468             }
5469
5470             break;
5471         }
5472         case VOGL_ENTRYPOINT_glGetFloatv:
5473         {
5474             if (!benchmark_mode())
5475             {
5476                 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5477                 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<GLfloat>(1);
5478                 uint trace_params_count = trace_packet.get_param_client_memory_data_size(1) / sizeof(GLfloat);
5479
5480                 int n = g_gl_enums.get_pname_count(pname);
5481                 if (n <= 0)
5482                 {
5483                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5484                     return cStatusSoftFailure;
5485                 }
5486
5487                 vogl::growable_array<GLfloat, 17> params(n + 1);
5488                 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
5489
5490                 GL_ENTRYPOINT(glGetFloatv)(pname, params.get_ptr());
5491
5492                 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
5493
5494                 if (static_cast<int>(trace_params_count) < n)
5495                     process_entrypoint_warning("%s: Replay param array size (%u) does not match the expected size (%u)\n", VOGL_METHOD_NAME, trace_params_count, n);
5496                 else if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLfloat)) != 0)
5497                 {
5498                     process_entrypoint_warning("%s: Replay's returned GLfloat data differed from trace's\n", VOGL_METHOD_NAME);
5499                 }
5500             }
5501
5502             break;
5503         }
5504         case VOGL_ENTRYPOINT_glGetIntegerv:
5505         {
5506             if (!benchmark_mode())
5507             {
5508                 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5509                 const GLint *pTrace_params = trace_packet.get_param_client_memory<GLint>(1);
5510                 uint trace_params_count = trace_packet.get_param_client_memory_data_size(1) / sizeof(GLint);
5511
5512                 int n = g_gl_enums.get_pname_count(pname);
5513                 if (n <= 0)
5514                 {
5515                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5516                     return cStatusSoftFailure;
5517                 }
5518
5519                 vogl::growable_array<GLint, 16> params(n + 1);
5520                 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5521
5522                 GL_ENTRYPOINT(glGetIntegerv)(pname, params.get_ptr());
5523
5524                 VOGL_VERIFY(params[n] == (GLint)VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5525
5526                 bool is_binding = false;
5527                 switch (pname)
5528                 {
5529                     case GL_ARRAY_BUFFER_BINDING:
5530                     case GL_COLOR_ARRAY_BUFFER_BINDING:
5531                     case GL_DISPATCH_INDIRECT_BUFFER_BINDING:
5532                     case GL_DRAW_FRAMEBUFFER_BINDING:
5533                     case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING:
5534                     case GL_ELEMENT_ARRAY_BUFFER_BINDING:
5535                     case GL_FOG_COORD_ARRAY_BUFFER_BINDING:
5536                     case GL_INDEX_ARRAY_BUFFER_BINDING:
5537                     case GL_NORMAL_ARRAY_BUFFER_BINDING:
5538                     case GL_PIXEL_PACK_BUFFER_BINDING:
5539                     case GL_PIXEL_UNPACK_BUFFER_BINDING:
5540                     case GL_PROGRAM_PIPELINE_BINDING:
5541                     case GL_READ_FRAMEBUFFER_BINDING:
5542                     case GL_RENDERBUFFER_BINDING:
5543                     case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING:
5544                     case GL_SHADER_STORAGE_BUFFER_BINDING:
5545                     case GL_TEXTURE_BINDING_1D:
5546                     case GL_TEXTURE_BINDING_1D_ARRAY:
5547                     case GL_TEXTURE_BINDING_2D:
5548                     case GL_TEXTURE_BINDING_2D_ARRAY:
5549                     case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
5550                     case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
5551                     case GL_TEXTURE_BINDING_3D:
5552                     case GL_TEXTURE_BINDING_BUFFER:
5553                     case GL_TEXTURE_BINDING_CUBE_MAP:
5554                     case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
5555                     case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
5556                     case GL_TRANSFORM_FEEDBACK_BUFFER_START:
5557                     case GL_UNIFORM_BUFFER_BINDING:
5558                     case GL_VERTEX_ARRAY_BINDING:
5559                     case GL_VERTEX_ARRAY_BUFFER_BINDING:
5560                     case GL_CURRENT_PROGRAM:
5561                     {
5562                         is_binding = true;
5563                         break;
5564                     }
5565                     default:
5566                         break;
5567                 }
5568
5569                 // Don't bother diffing bindings, the trace's are in the trace domain while the glGet's results are in the replay domain.
5570                 if (!is_binding)
5571                 {
5572                     if (static_cast<int>(trace_params_count) < n)
5573                     {
5574                         process_entrypoint_warning("%s: Replay param array size (%u) does not match the expected size (%u)\n", VOGL_METHOD_NAME, trace_params_count, n);
5575                     }
5576                     else if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLint)) != 0)
5577                     {
5578                         process_entrypoint_warning("%s: Replay's returned GLint data differed from trace's, pname %s\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(pname));
5579                         for (int i = 0; i < n; i++)
5580                             vogl_printf("GLint %u: Trace: %i, Replay: %i\n", i, pTrace_params[i], params[i]);
5581                     }
5582                 }
5583             }
5584
5585             break;
5586         }
5587         // glProgramUniform's
5588         case VOGL_ENTRYPOINT_glProgramUniform1f:
5589         {
5590             set_program_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glProgramUniform1f));
5591             break;
5592         }
5593         case VOGL_ENTRYPOINT_glProgramUniform1i:
5594         {
5595             set_program_uniform_helper1<GLint>(GL_ENTRYPOINT(glProgramUniform1i));
5596             break;
5597         }
5598         case VOGL_ENTRYPOINT_glProgramUniform1ui:
5599         {
5600             set_program_uniform_helper1<GLuint>(GL_ENTRYPOINT(glProgramUniform1ui));
5601             break;
5602         }
5603         case VOGL_ENTRYPOINT_glProgramUniform2f:
5604         {
5605             set_program_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glProgramUniform2f));
5606             break;
5607         }
5608         case VOGL_ENTRYPOINT_glProgramUniform2i:
5609         {
5610             set_program_uniform_helper2<GLint>(GL_ENTRYPOINT(glProgramUniform2i));
5611             break;
5612         }
5613         case VOGL_ENTRYPOINT_glProgramUniform2ui:
5614         {
5615             set_program_uniform_helper2<GLuint>(GL_ENTRYPOINT(glProgramUniform2ui));
5616             break;
5617         }
5618         case VOGL_ENTRYPOINT_glProgramUniform3f:
5619         {
5620             set_program_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glProgramUniform3f));
5621             break;
5622         }
5623         case VOGL_ENTRYPOINT_glProgramUniform3i:
5624         {
5625             set_program_uniform_helper3<GLint>(GL_ENTRYPOINT(glProgramUniform3i));
5626             break;
5627         }
5628         case VOGL_ENTRYPOINT_glProgramUniform3ui:
5629         {
5630             set_program_uniform_helper3<GLuint>(GL_ENTRYPOINT(glProgramUniform3ui));
5631             break;
5632         }
5633         case VOGL_ENTRYPOINT_glProgramUniform4f:
5634         {
5635             set_program_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glProgramUniform4f));
5636             break;
5637         }
5638         case VOGL_ENTRYPOINT_glProgramUniform4i:
5639         {
5640             set_program_uniform_helper4<GLint>(GL_ENTRYPOINT(glProgramUniform4i));
5641             break;
5642         }
5643         case VOGL_ENTRYPOINT_glProgramUniform4ui:
5644         {
5645             set_program_uniform_helper4<GLuint>(GL_ENTRYPOINT(glProgramUniform4ui));
5646             break;
5647         }
5648         case VOGL_ENTRYPOINT_glProgramUniform1fv:
5649         {
5650             set_program_uniformv_helper<1, float>(GL_ENTRYPOINT(glProgramUniform1fv));
5651             break;
5652         }
5653         case VOGL_ENTRYPOINT_glProgramUniform2fv:
5654         {
5655             set_program_uniformv_helper<2, float>(GL_ENTRYPOINT(glProgramUniform2fv));
5656             break;
5657         }
5658         case VOGL_ENTRYPOINT_glProgramUniform3fv:
5659         {
5660             set_program_uniformv_helper<3, float>(GL_ENTRYPOINT(glProgramUniform3fv));
5661             break;
5662         }
5663         case VOGL_ENTRYPOINT_glProgramUniform4fv:
5664         {
5665             set_program_uniformv_helper<4, float>(GL_ENTRYPOINT(glProgramUniform4fv));
5666             break;
5667         }
5668         case VOGL_ENTRYPOINT_glProgramUniform1iv:
5669         {
5670             set_program_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glProgramUniform1iv));
5671             break;
5672         }
5673         case VOGL_ENTRYPOINT_glProgramUniform2iv:
5674         {
5675             set_program_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glProgramUniform2iv));
5676             break;
5677         }
5678         case VOGL_ENTRYPOINT_glProgramUniform3iv:
5679         {
5680             set_program_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glProgramUniform3iv));
5681             break;
5682         }
5683         case VOGL_ENTRYPOINT_glProgramUniform4iv:
5684         {
5685             set_program_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glProgramUniform4iv));
5686             break;
5687         }
5688         case VOGL_ENTRYPOINT_glProgramUniform1uiv:
5689         {
5690             set_program_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glProgramUniform1uiv));
5691             break;
5692         }
5693         case VOGL_ENTRYPOINT_glProgramUniform2uiv:
5694         {
5695             set_program_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glProgramUniform2uiv));
5696             break;
5697         }
5698         case VOGL_ENTRYPOINT_glProgramUniform3uiv:
5699         {
5700             set_program_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glProgramUniform3uiv));
5701             break;
5702         }
5703         case VOGL_ENTRYPOINT_glProgramUniform4uiv:
5704         {
5705             set_program_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glProgramUniform4uiv));
5706             break;
5707         }
5708         case VOGL_ENTRYPOINT_glProgramUniformMatrix2fv:
5709         {
5710             set_program_uniform_matrixv_helper<2, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix2fv));
5711             break;
5712         }
5713         case VOGL_ENTRYPOINT_glProgramUniformMatrix3fv:
5714         {
5715             set_program_uniform_matrixv_helper<3, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix3fv));
5716             break;
5717         }
5718         case VOGL_ENTRYPOINT_glProgramUniformMatrix4fv:
5719         {
5720             set_program_uniform_matrixv_helper<4, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix4fv));
5721             break;
5722         }
5723         case VOGL_ENTRYPOINT_glProgramUniformMatrix2x3fv:
5724         {
5725             set_program_uniform_matrixv_helper<2, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix2x3fv));
5726             break;
5727         }
5728         case VOGL_ENTRYPOINT_glProgramUniformMatrix3x2fv:
5729         {
5730             set_program_uniform_matrixv_helper<3, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix3x2fv));
5731             break;
5732         }
5733         case VOGL_ENTRYPOINT_glProgramUniformMatrix2x4fv:
5734         {
5735             set_program_uniform_matrixv_helper<2, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix2x4fv));
5736             break;
5737         }
5738         case VOGL_ENTRYPOINT_glProgramUniformMatrix4x2fv:
5739         {
5740             set_program_uniform_matrixv_helper<4, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix4x2fv));
5741             break;
5742         }
5743         case VOGL_ENTRYPOINT_glProgramUniformMatrix3x4fv:
5744         {
5745             set_program_uniform_matrixv_helper<3, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix3x4fv));
5746             break;
5747         }
5748         case VOGL_ENTRYPOINT_glProgramUniformMatrix4x3fv:
5749         {
5750             set_program_uniform_matrixv_helper<4, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix4x3fv));
5751             break;
5752         }
5753         // glUniform's
5754         case VOGL_ENTRYPOINT_glUniform1f:
5755         {
5756             set_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glUniform1f));
5757             break;
5758         }
5759         case VOGL_ENTRYPOINT_glUniform1fARB:
5760         {
5761             set_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glUniform1fARB));
5762             break;
5763         }
5764         case VOGL_ENTRYPOINT_glUniform2f:
5765         {
5766             set_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glUniform2f));
5767             break;
5768         }
5769         case VOGL_ENTRYPOINT_glUniform2fARB:
5770         {
5771             set_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glUniform2fARB));
5772             break;
5773         }
5774         case VOGL_ENTRYPOINT_glUniform3f:
5775         {
5776             set_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glUniform3f));
5777             break;
5778         }
5779         case VOGL_ENTRYPOINT_glUniform3fARB:
5780         {
5781             set_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glUniform3fARB));
5782             break;
5783         }
5784         case VOGL_ENTRYPOINT_glUniform4f:
5785         {
5786             set_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glUniform4f));
5787             break;
5788         }
5789         case VOGL_ENTRYPOINT_glUniform4fARB:
5790         {
5791             set_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glUniform4fARB));
5792             break;
5793         }
5794         case VOGL_ENTRYPOINT_glUniform1i:
5795         {
5796             set_uniform_helper1<GLint>(GL_ENTRYPOINT(glUniform1i));
5797             break;
5798         }
5799         case VOGL_ENTRYPOINT_glUniform1iARB:
5800         {
5801             set_uniform_helper1<GLint>(GL_ENTRYPOINT(glUniform1iARB));
5802             break;
5803         }
5804         case VOGL_ENTRYPOINT_glUniform2i:
5805         {
5806             set_uniform_helper2<GLint>(GL_ENTRYPOINT(glUniform2i));
5807             break;
5808         }
5809         case VOGL_ENTRYPOINT_glUniform2iARB:
5810         {
5811             set_uniform_helper2<GLint>(GL_ENTRYPOINT(glUniform2iARB));
5812             break;
5813         }
5814         case VOGL_ENTRYPOINT_glUniform3i:
5815         {
5816             set_uniform_helper3<GLint>(GL_ENTRYPOINT(glUniform3i));
5817             break;
5818         }
5819         case VOGL_ENTRYPOINT_glUniform3iARB:
5820         {
5821             set_uniform_helper3<GLint>(GL_ENTRYPOINT(glUniform3iARB));
5822             break;
5823         }
5824         case VOGL_ENTRYPOINT_glUniform4i:
5825         {
5826             set_uniform_helper4<GLint>(GL_ENTRYPOINT(glUniform4i));
5827             break;
5828         }
5829         case VOGL_ENTRYPOINT_glUniform4iARB:
5830         {
5831             set_uniform_helper4<GLint>(GL_ENTRYPOINT(glUniform4iARB));
5832             break;
5833         }
5834         case VOGL_ENTRYPOINT_glUniform1ui:
5835         {
5836             set_uniform_helper1<GLuint>(GL_ENTRYPOINT(glUniform1ui));
5837             break;
5838         }
5839         case VOGL_ENTRYPOINT_glUniform1uiEXT:
5840         {
5841             set_uniform_helper1<GLuint>(GL_ENTRYPOINT(glUniform1uiEXT));
5842             break;
5843         }
5844         case VOGL_ENTRYPOINT_glUniform2ui:
5845         {
5846             set_uniform_helper2<GLuint>(GL_ENTRYPOINT(glUniform2ui));
5847             break;
5848         }
5849         case VOGL_ENTRYPOINT_glUniform2uiEXT:
5850         {
5851             set_uniform_helper2<GLuint>(GL_ENTRYPOINT(glUniform2uiEXT));
5852             break;
5853         }
5854         case VOGL_ENTRYPOINT_glUniform3ui:
5855         {
5856             set_uniform_helper3<GLuint>(GL_ENTRYPOINT(glUniform3ui));
5857             break;
5858         }
5859         case VOGL_ENTRYPOINT_glUniform3uiEXT:
5860         {
5861             set_uniform_helper3<GLuint>(GL_ENTRYPOINT(glUniform3uiEXT));
5862             break;
5863         }
5864         case VOGL_ENTRYPOINT_glUniform4ui:
5865         {
5866             set_uniform_helper4<GLuint>(GL_ENTRYPOINT(glUniform4ui));
5867             break;
5868         }
5869         case VOGL_ENTRYPOINT_glUniform4uiEXT:
5870         {
5871             set_uniform_helper4<GLuint>(GL_ENTRYPOINT(glUniform4uiEXT));
5872             break;
5873         }
5874         case VOGL_ENTRYPOINT_glUniform1uiv:
5875         {
5876             set_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glUniform1uiv));
5877             break;
5878         }
5879         case VOGL_ENTRYPOINT_glUniform1uivEXT:
5880         {
5881             set_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glUniform1uivEXT));
5882             break;
5883         }
5884         case VOGL_ENTRYPOINT_glUniform2uiv:
5885         {
5886             set_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glUniform2uiv));
5887             break;
5888         }
5889         case VOGL_ENTRYPOINT_glUniform2uivEXT:
5890         {
5891             set_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glUniform2uivEXT));
5892             break;
5893         }
5894         case VOGL_ENTRYPOINT_glUniform3uiv:
5895         {
5896             set_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glUniform3uiv));
5897             break;
5898         }
5899         case VOGL_ENTRYPOINT_glUniform3uivEXT:
5900         {
5901             set_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glUniform3uivEXT));
5902             break;
5903         }
5904         case VOGL_ENTRYPOINT_glUniform4uiv:
5905         {
5906             set_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glUniform4uiv));
5907             break;
5908         }
5909         case VOGL_ENTRYPOINT_glUniform4uivEXT:
5910         {
5911             set_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glUniform4uivEXT));
5912             break;
5913         }
5914         case VOGL_ENTRYPOINT_glUniform1iv:
5915         {
5916             set_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glUniform1iv));
5917             break;
5918         }
5919         case VOGL_ENTRYPOINT_glUniform1ivARB:
5920         {
5921             set_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glUniform1ivARB));
5922             break;
5923         }
5924         case VOGL_ENTRYPOINT_glUniform2iv:
5925         {
5926             set_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glUniform2iv));
5927             break;
5928         }
5929         case VOGL_ENTRYPOINT_glUniform2ivARB:
5930         {
5931             set_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glUniform2ivARB));
5932             break;
5933         }
5934         case VOGL_ENTRYPOINT_glUniform3iv:
5935         {
5936             set_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glUniform3iv));
5937             break;
5938         }
5939         case VOGL_ENTRYPOINT_glUniform3ivARB:
5940         {
5941             set_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glUniform3ivARB));
5942             break;
5943         }
5944         case VOGL_ENTRYPOINT_glUniform4iv:
5945         {
5946             set_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glUniform4iv));
5947             break;
5948         }
5949         case VOGL_ENTRYPOINT_glUniform4ivARB:
5950         {
5951             set_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glUniform4ivARB));
5952             break;
5953         }
5954         case VOGL_ENTRYPOINT_glUniform1fv:
5955         {
5956             set_uniformv_helper<1, GLfloat>(GL_ENTRYPOINT(glUniform1fv));
5957             break;
5958         }
5959         case VOGL_ENTRYPOINT_glUniform1fvARB:
5960         {
5961             set_uniformv_helper<1, GLfloat>(GL_ENTRYPOINT(glUniform1fvARB));
5962             break;
5963         }
5964         case VOGL_ENTRYPOINT_glUniform2fv:
5965         {
5966             set_uniformv_helper<2, GLfloat>(GL_ENTRYPOINT(glUniform2fv));
5967             break;
5968         }
5969         case VOGL_ENTRYPOINT_glUniform2fvARB:
5970         {
5971             set_uniformv_helper<2, GLfloat>(GL_ENTRYPOINT(glUniform2fvARB));
5972             break;
5973         }
5974         case VOGL_ENTRYPOINT_glUniform3fv:
5975         {
5976             set_uniformv_helper<3, GLfloat>(GL_ENTRYPOINT(glUniform3fv));
5977             break;
5978         }
5979         case VOGL_ENTRYPOINT_glUniform3fvARB:
5980         {
5981             set_uniformv_helper<3, GLfloat>(GL_ENTRYPOINT(glUniform3fvARB));
5982             break;
5983         }
5984         case VOGL_ENTRYPOINT_glUniform4fv:
5985         {
5986             set_uniformv_helper<4, GLfloat>(GL_ENTRYPOINT(glUniform4fv));
5987             break;
5988         }
5989         case VOGL_ENTRYPOINT_glUniform4fvARB:
5990         {
5991             set_uniformv_helper<4, GLfloat>(GL_ENTRYPOINT(glUniform4fvARB));
5992             break;
5993         }
5994         case VOGL_ENTRYPOINT_glUniformMatrix2fvARB:
5995         {
5996             set_uniform_matrixv_helper<2, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2fvARB));
5997             break;
5998         }
5999         case VOGL_ENTRYPOINT_glUniformMatrix2fv:
6000         {
6001             set_uniform_matrixv_helper<2, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2fv));
6002             break;
6003         }
6004         case VOGL_ENTRYPOINT_glUniformMatrix3fvARB:
6005         {
6006             set_uniform_matrixv_helper<3, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3fvARB));
6007             break;
6008         }
6009         case VOGL_ENTRYPOINT_glUniformMatrix3fv:
6010         {
6011             set_uniform_matrixv_helper<3, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3fv));
6012             break;
6013         }
6014         case VOGL_ENTRYPOINT_glUniformMatrix4fvARB:
6015         {
6016             set_uniform_matrixv_helper<4, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4fvARB));
6017             break;
6018         }
6019         case VOGL_ENTRYPOINT_glUniformMatrix4fv:
6020         {
6021             set_uniform_matrixv_helper<4, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4fv));
6022             break;
6023         }
6024         case VOGL_ENTRYPOINT_glUniformMatrix2x3fv:
6025         {
6026             set_uniform_matrixv_helper<2, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2x3fv));
6027             break;
6028         }
6029         case VOGL_ENTRYPOINT_glUniformMatrix3x2fv:
6030         {
6031             set_uniform_matrixv_helper<3, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3x2fv));
6032             break;
6033         }
6034         case VOGL_ENTRYPOINT_glUniformMatrix2x4fv:
6035         {
6036             set_uniform_matrixv_helper<2, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2x4fv));
6037             break;
6038         }
6039         case VOGL_ENTRYPOINT_glUniformMatrix4x2fv:
6040         {
6041             set_uniform_matrixv_helper<4, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4x2fv));
6042             break;
6043         }
6044         case VOGL_ENTRYPOINT_glUniformMatrix3x4fv:
6045         {
6046             set_uniform_matrixv_helper<3, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3x4fv));
6047             break;
6048         }
6049         case VOGL_ENTRYPOINT_glUniformMatrix4x3fv:
6050         {
6051             set_uniform_matrixv_helper<4, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4x3fv));
6052             break;
6053         }
6054         case VOGL_ENTRYPOINT_glBeginQuery:
6055         case VOGL_ENTRYPOINT_glBeginQueryARB:
6056         {
6057             GLenum target = trace_packet.get_param_value<GLenum>(0);
6058             GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
6059             GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6060
6061             if (!m_pCur_context_state->m_inside_gl_begin)
6062                 check_gl_error();
6063
6064             if (entrypoint_id == VOGL_ENTRYPOINT_glBeginQuery)
6065                 GL_ENTRYPOINT(glBeginQuery)(target, replay_handle);
6066             else
6067                 GL_ENTRYPOINT(glBeginQueryARB)(target, replay_handle);
6068
6069             if ((replay_handle) && (!m_pCur_context_state->m_inside_gl_begin) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6070             {
6071                 if (check_gl_error())
6072                     return cStatusGLError;
6073
6074                 get_shared_state()->m_query_targets[replay_handle] = target;
6075             }
6076
6077             break;
6078         }
6079         case VOGL_ENTRYPOINT_glEndQuery:
6080         {
6081             GL_ENTRYPOINT(glEndQuery)(trace_packet.get_param_value<GLenum>(0));
6082             break;
6083         }
6084         case VOGL_ENTRYPOINT_glEndQueryARB:
6085         {
6086             GL_ENTRYPOINT(glEndQueryARB)(trace_packet.get_param_value<GLenum>(0));
6087             break;
6088         }
6089         case VOGL_ENTRYPOINT_glGetQueryObjectiv:
6090         {
6091             GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6092             GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6093
6094             GLenum pname = trace_packet.get_param_value<GLenum>(1);
6095
6096             int n = g_gl_enums.get_pname_count(pname);
6097             if (n <= 0)
6098             {
6099                 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6100                 return cStatusSoftFailure;
6101             }
6102             else
6103             {
6104                 vogl::growable_array<GLint, 16> params(n + 1);
6105                 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6106
6107                 GL_ENTRYPOINT(glGetQueryObjectiv)(replay_handle, pname, params.get_ptr());
6108
6109                 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6110             }
6111
6112             break;
6113         }
6114         case VOGL_ENTRYPOINT_glGetQueryObjectivARB:
6115         {
6116             GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6117             GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6118
6119             GLenum pname = trace_packet.get_param_value<GLenum>(1);
6120
6121             int n = g_gl_enums.get_pname_count(pname);
6122             if (n <= 0)
6123             {
6124                 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6125                 return cStatusSoftFailure;
6126             }
6127             else
6128             {
6129                 vogl::growable_array<GLint, 16> params(n + 1);
6130                 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6131
6132                 GL_ENTRYPOINT(glGetQueryObjectivARB)(replay_handle, pname, params.get_ptr());
6133
6134                 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6135             }
6136
6137             break;
6138         }
6139         case VOGL_ENTRYPOINT_glGetQueryObjectuiv:
6140         {
6141             GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6142             GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6143
6144             GLenum pname = trace_packet.get_param_value<GLenum>(1);
6145
6146             int n = g_gl_enums.get_pname_count(pname);
6147             if (n <= 0)
6148             {
6149                 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6150                 return cStatusSoftFailure;
6151             }
6152             else
6153             {
6154                 vogl::growable_array<GLuint, 16> params(n + 1);
6155                 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6156
6157                 GL_ENTRYPOINT(glGetQueryObjectuiv)(replay_handle, pname, params.get_ptr());
6158
6159                 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6160             }
6161
6162             break;
6163         }
6164         case VOGL_ENTRYPOINT_glGetQueryObjectuivARB:
6165         {
6166             GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6167             GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6168
6169             GLenum pname = trace_packet.get_param_value<GLenum>(1);
6170
6171             int n = g_gl_enums.get_pname_count(pname);
6172             if (n <= 0)
6173             {
6174                 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6175                 return cStatusSoftFailure;
6176             }
6177             else
6178             {
6179                 vogl::growable_array<GLuint, 16> params(n + 1);
6180                 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6181
6182                 GL_ENTRYPOINT(glGetQueryObjectuivARB)(replay_handle, pname, params.get_ptr());
6183
6184                 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6185             }
6186
6187             break;
6188         }
6189         case VOGL_ENTRYPOINT_glQueryCounter:
6190         {
6191             VOGL_REPLAY_LOAD_PARAMS_HELPER_glQueryCounter;
6192
6193             id = map_handle(get_shared_state()->m_queries, id);
6194
6195             VOGL_REPLAY_CALL_GL_HELPER_glQueryCounter;
6196
6197             break;
6198         }
6199         case VOGL_ENTRYPOINT_glGetQueryObjecti64v:
6200         {
6201             VOGL_REPLAY_LOAD_PARAMS_HELPER_glGetQueryObjecti64v;
6202             VOGL_NOTE_UNUSED(pTrace_params);
6203
6204             id = map_handle(get_shared_state()->m_queries, id);
6205
6206             int n = g_gl_enums.get_pname_count(pname);
6207             if (n <= 0)
6208             {
6209                 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6210                 return cStatusSoftFailure;
6211             }
6212
6213             vogl::growable_array<GLint64, 16> temp_params(n + 1);
6214             temp_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6215
6216             GLint64 *pReplay_params = temp_params.get_ptr();
6217
6218             VOGL_REPLAY_CALL_GL_HELPER_glGetQueryObjecti64v;
6219
6220             VOGL_VERIFY(temp_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6221
6222             break;
6223         }
6224         case VOGL_ENTRYPOINT_glGetQueryObjectui64v:
6225         {
6226             VOGL_REPLAY_LOAD_PARAMS_HELPER_glGetQueryObjectui64v;
6227             VOGL_NOTE_UNUSED(pTrace_params);
6228
6229             id = map_handle(get_shared_state()->m_queries, id);
6230
6231             int n = g_gl_enums.get_pname_count(pname);
6232             if (n <= 0)
6233             {
6234                 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6235                 return cStatusSoftFailure;
6236             }
6237
6238             vogl::growable_array<GLuint64, 16> temp_params(n + 1);
6239             temp_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6240
6241             GLuint64 *pReplay_params = temp_params.get_ptr();
6242
6243             VOGL_REPLAY_CALL_GL_HELPER_glGetQueryObjectui64v;
6244
6245             VOGL_VERIFY(temp_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6246
6247             break;
6248         }
6249         case VOGL_ENTRYPOINT_glBindBuffer:
6250         case VOGL_ENTRYPOINT_glBindBufferARB:
6251         {
6252             GLenum target = trace_packet.get_param_value<GLenum>(0);
6253             GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
6254             GLuint replay_handle = map_handle(get_shared_state()->m_buffers, trace_handle);
6255
6256             check_gl_error();
6257
6258             SWITCH_GL_ENTRYPOINT2_VOID(glBindBuffer, glBindBufferARB, target, replay_handle);
6259
6260             if (check_gl_error())
6261                 return cStatusGLError;
6262
6263             if ((trace_handle) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6264             {
6265                 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_handle);
6266                 if (!pBinding)
6267                     process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_handle);
6268                 else if (*pBinding == GL_NONE)
6269                     *pBinding = target;
6270             }
6271
6272             break;
6273         }
6274         case VOGL_ENTRYPOINT_glBindBufferBase:
6275         case VOGL_ENTRYPOINT_glBindBufferBaseEXT:
6276         case VOGL_ENTRYPOINT_glBindBufferBaseNV:
6277         {
6278             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindBufferBase;
6279
6280             GLuint trace_buffer = buffer;
6281             buffer = map_handle(get_shared_state()->m_buffers, buffer);
6282
6283             check_gl_error();
6284
6285             if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferBaseNV)
6286                 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBaseNV;
6287             else if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferBaseEXT)
6288                 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBaseEXT;
6289             else
6290                 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBase;
6291
6292             if (check_gl_error())
6293                 return cStatusGLError;
6294
6295             if ((trace_buffer) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6296             {
6297                 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_buffer);
6298                 if (!pBinding)
6299                     process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_buffer);
6300                 else if (*pBinding == GL_NONE)
6301                     *pBinding = target;
6302             }
6303
6304             break;
6305         }
6306         case VOGL_ENTRYPOINT_glBindBufferRange:
6307         case VOGL_ENTRYPOINT_glBindBufferRangeEXT:
6308         case VOGL_ENTRYPOINT_glBindBufferRangeNV:
6309         {
6310             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindBufferRange;
6311
6312             GLuint trace_buffer = buffer;
6313             buffer = map_handle(get_shared_state()->m_buffers, buffer);
6314
6315             check_gl_error();
6316
6317             if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferRangeNV)
6318                 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRangeNV;
6319             else if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferRangeEXT)
6320                 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRangeEXT;
6321             else
6322                 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRange;
6323
6324             if (check_gl_error())
6325                 return cStatusGLError;
6326
6327             if ((trace_buffer) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6328             {
6329                 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_buffer);
6330                 if (!pBinding)
6331                     process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_buffer);
6332                 else if (*pBinding == GL_NONE)
6333                     *pBinding = target;
6334             }
6335
6336             break;
6337         }
6338         case VOGL_ENTRYPOINT_glFenceSync:
6339         {
6340             vogl_sync_ptr_value trace_handle = trace_packet.get_return_ptr_value();
6341             if (trace_handle)
6342             {
6343                 GLsync replay_handle = GL_ENTRYPOINT(glFenceSync)(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLbitfield>(1));
6344                 if (!replay_handle)
6345                 {
6346                     process_entrypoint_error("%s: glFenceSync on trace handle 0x%" PRIX64 " succeeded in the trace, but failed during replay!\n", VOGL_METHOD_NAME, trace_handle);
6347                     return cStatusHardFailure;
6348                 }
6349                 else
6350                 {
6351                     get_shared_state()->m_syncs.insert(trace_handle, replay_handle);
6352                 }
6353             }
6354
6355             break;
6356         }
6357         case VOGL_ENTRYPOINT_glWaitSync:
6358         case VOGL_ENTRYPOINT_glClientWaitSync:
6359         {
6360             vogl_sync_ptr_value trace_sync = trace_packet.get_param_ptr_value(0);
6361             GLsync replay_sync = NULL;
6362
6363             gl_sync_hash_map::const_iterator it = get_shared_state()->m_syncs.find(trace_sync);
6364             if (it == get_shared_state()->m_syncs.end())
6365             {
6366                 if (trace_sync)
6367                 {
6368                     process_entrypoint_error("%s: Unable to map trace sync handle 0x%" PRIX64 " to GL handle\n", VOGL_METHOD_NAME, trace_sync);
6369                     return cStatusHardFailure;
6370                 }
6371             }
6372             else
6373             {
6374                 replay_sync = it->second;
6375             }
6376
6377             if (entrypoint_id == VOGL_ENTRYPOINT_glWaitSync)
6378                 GL_ENTRYPOINT(glWaitSync)(replay_sync, trace_packet.get_param_value<GLbitfield>(1), trace_packet.get_param_value<GLuint64>(2));
6379             else
6380                 GL_ENTRYPOINT(glClientWaitSync)(replay_sync, trace_packet.get_param_value<GLbitfield>(1), trace_packet.get_param_value<GLuint64>(2));
6381
6382             break;
6383         }
6384         case VOGL_ENTRYPOINT_glDeleteSync:
6385         {
6386             vogl_sync_ptr_value trace_sync = trace_packet.get_param_ptr_value(0);
6387             GLsync replay_sync = NULL;
6388
6389             gl_sync_hash_map::const_iterator it = get_shared_state()->m_syncs.find(trace_sync);
6390             if (it == get_shared_state()->m_syncs.end())
6391             {
6392                 if (trace_sync)
6393                 {
6394                     process_entrypoint_error("%s: Unable to map trace sync handle 0x%" PRIX64 " to GL handle\n", VOGL_METHOD_NAME, trace_sync);
6395                     return cStatusHardFailure;
6396                 }
6397             }
6398             else
6399             {
6400                 replay_sync = it->second;
6401             }
6402
6403             GL_ENTRYPOINT(glDeleteSync)(replay_sync);
6404
6405             if (trace_sync)
6406             {
6407                 get_shared_state()->m_syncs.erase(trace_sync);
6408             }
6409
6410             break;
6411         }
6412         case VOGL_ENTRYPOINT_glVertexPointer:
6413         {
6414             vertex_array_helper(trace_packet.get_param_value<GLint>(0), trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLsizei>(2), trace_packet.get_param_ptr_value(3),
6415                                 vogl_vertex_pointer_array_id, GL_ENTRYPOINT(glVertexPointer), m_client_side_array_data[vogl_vertex_pointer_array_id]);
6416             break;
6417         }
6418         case VOGL_ENTRYPOINT_glVertexPointerEXT:
6419         {
6420             VOGL_REPLAY_LOAD_PARAMS_HELPER_glVertexPointerEXT;
6421             VOGL_NOTE_UNUSED(pTrace_pointer);
6422
6423             vertex_array_helper_count(size, type, stride, count, trace_packet.get_param_ptr_value(4), vogl_vertex_pointer_array_id, GL_ENTRYPOINT(glVertexPointerEXT), m_client_side_array_data[vogl_vertex_pointer_array_id]);
6424             break;
6425         }
6426         case VOGL_ENTRYPOINT_glColorPointer:
6427         {
6428             vertex_array_helper(trace_packet.get_param_value<GLint>(0), trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLsizei>(2), trace_packet.get_param_ptr_value(3),
6429                                 vogl_color_pointer_array_id, GL_ENTRYPOINT(glColorPointer), m_client_side_array_data[vogl_color_pointer_array_id]);
6430             break;
6431         }
6432         case VOGL_ENTRYPOINT_glColorPointerEXT:
6433         {
6434             VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorPointerEXT;
6435             VOGL_NOTE_UNUSED(pTrace_pointer);
6436
6437             vertex_array_helper_count(size, type, stride, count, trace_packet.get_param_ptr_value(4), vogl_color_pointer_array_id, GL_ENTRYPOINT(glColorPointerEXT), m_client_side_array_data[vogl_color_pointer_array_id]);
6438             break;
6439         }
6440         case VOGL_ENTRYPOINT_glSecondaryColorPointer:
6441         {
6442             vertex_array_helper(trace_packet.get_param_value<GLint>(0), trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLsizei>(2), trace_packet.get_param_ptr_value(3),
6443                                 vogl_secondary_color_pointer_array_id, GL_ENTRYPOINT(glSecondaryColorPointer), m_client_side_array_data[vogl_secondary_color_pointer_array_id]);
6444             break;
6445         }
6446         case VOGL_ENTRYPOINT_glSecondaryColorPointerEXT:
6447         {
6448             vertex_array_helper(trace_packet.get_param_value<GLint>(0), trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLsizei>(2), trace_packet.get_param_ptr_value(3),
6449                                 vogl_secondary_color_pointer_array_id, GL_ENTRYPOINT(glSecondaryColorPointerEXT), m_client_side_array_data[vogl_secondary_color_pointer_array_id]);
6450             break;
6451         }
6452         case VOGL_ENTRYPOINT_glTexCoordPointer:
6453         {
6454             GLint cur_client_active_texture = 0;
6455             GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6456
6457             int tex_index = cur_client_active_texture - GL_TEXTURE0;
6458             if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6459             {
6460                 process_entrypoint_error("%s: glTexCoordPointer/glTexCoordPointerEXT called with an invalid or unsupported client active texture (0x%08X)\n", VOGL_METHOD_NAME, cur_client_active_texture);
6461                 return cStatusSoftFailure;
6462             }
6463
6464             vertex_array_helper(trace_packet.get_param_value<GLint>(0), trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLsizei>(2), trace_packet.get_param_ptr_value(3),
6465                                 vogl_texcoord_pointer_array_id, GL_ENTRYPOINT(glTexCoordPointer), m_client_side_texcoord_data[tex_index]);
6466             break;
6467         }
6468         case VOGL_ENTRYPOINT_glTexCoordPointerEXT:
6469         {
6470             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexCoordPointerEXT;
6471             VOGL_NOTE_UNUSED(pTrace_pointer);
6472
6473             GLint cur_client_active_texture = 0;
6474             GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6475
6476             int tex_index = cur_client_active_texture - GL_TEXTURE0;
6477             if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6478             {
6479                 process_entrypoint_error("%s: glTexCoordPointer/glTexCoordPointerEXT called with an invalid or unsupported client active texture (0x%08X)\n", VOGL_METHOD_NAME, cur_client_active_texture);
6480                 return cStatusSoftFailure;
6481             }
6482
6483             vertex_array_helper_count(size, type, stride, count, trace_packet.get_param_ptr_value(4), vogl_texcoord_pointer_array_id, GL_ENTRYPOINT(glTexCoordPointerEXT), m_client_side_texcoord_data[tex_index]);
6484             break;
6485         }
6486         case VOGL_ENTRYPOINT_glFogCoordPointer:
6487         {
6488             vertex_array_helper_no_size(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLsizei>(1), trace_packet.get_param_ptr_value(2),
6489                                         vogl_fog_coord_pointer_array_id, GL_ENTRYPOINT(glFogCoordPointer));
6490             break;
6491         }
6492         case VOGL_ENTRYPOINT_glFogCoordPointerEXT:
6493         {
6494             vertex_array_helper_no_size(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLsizei>(1), trace_packet.get_param_ptr_value(2),
6495                                         vogl_fog_coord_pointer_array_id, GL_ENTRYPOINT(glFogCoordPointerEXT));
6496             break;
6497         }
6498         case VOGL_ENTRYPOINT_glIndexPointer:
6499         {
6500             vertex_array_helper_no_size(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLsizei>(1), trace_packet.get_param_ptr_value(2),
6501                                         vogl_index_pointer_array_id, GL_ENTRYPOINT(glIndexPointer));
6502             break;
6503         }
6504         case VOGL_ENTRYPOINT_glIndexPointerEXT:
6505         {
6506             VOGL_REPLAY_LOAD_PARAMS_HELPER_glIndexPointerEXT;
6507             VOGL_NOTE_UNUSED(pTrace_pointer);
6508
6509             vertex_array_helper_no_size_count(type, stride, count, trace_packet.get_param_ptr_value(3), vogl_index_pointer_array_id, GL_ENTRYPOINT(glIndexPointerEXT));
6510             break;
6511         }
6512         case VOGL_ENTRYPOINT_glNormalPointer:
6513         {
6514             vertex_array_helper_no_size(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLsizei>(1), trace_packet.get_param_ptr_value(2),
6515                                         vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointer));
6516             break;
6517         }
6518         case VOGL_ENTRYPOINT_glNormalPointerEXT:
6519         {
6520             VOGL_REPLAY_LOAD_PARAMS_HELPER_glNormalPointerEXT;
6521             VOGL_NOTE_UNUSED(pTrace_pointer);
6522
6523             vertex_array_helper_no_size_count(type, stride, count, trace_packet.get_param_ptr_value(3), vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointerEXT));
6524             break;
6525         }
6526         case VOGL_ENTRYPOINT_glEdgeFlagPointer:
6527         {
6528             vertex_array_helper_no_type_no_size(trace_packet.get_param_value<GLsizei>(0), trace_packet.get_param_ptr_value(1),
6529                                                 vogl_edge_flag_pointer_array_id, GL_ENTRYPOINT(glEdgeFlagPointer));
6530             break;
6531         }
6532         case VOGL_ENTRYPOINT_glEdgeFlagPointerEXT:
6533         {
6534             VOGL_REPLAY_LOAD_PARAMS_HELPER_glEdgeFlagPointerEXT;
6535             VOGL_NOTE_UNUSED(pTrace_pointer);
6536
6537             vertex_array_helper_no_type_no_size_count(stride, count, trace_packet.get_param_ptr_value(2), vogl_edge_flag_pointer_array_id, GL_ENTRYPOINT(glEdgeFlagPointerEXT));
6538             break;
6539         }
6540         case VOGL_ENTRYPOINT_glInterleavedArrays:
6541         {
6542             // TODO: Test this more!
6543             GLenum format = trace_packet.get_param_value<GLenum>(0);
6544             GLsizei stride = trace_packet.get_param_value<GLsizei>(1);
6545             const vogl_trace_ptr_value trace_pointer_value = trace_packet.get_param_ptr_value(2);
6546
6547             uint fmt_index;
6548             for (fmt_index = 0; fmt_index < VOGL_INTERLEAVED_ARRAY_SIZE; fmt_index++)
6549                 if (format == vogl_g_interleaved_array_descs[fmt_index].fmt)
6550                     break;
6551             if (fmt_index == VOGL_INTERLEAVED_ARRAY_SIZE)
6552             {
6553                 process_entrypoint_error("%s: Invalid interleaved vertex format: 0x%X \n", VOGL_METHOD_NAME, format);
6554                 return cStatusSoftFailure;
6555             }
6556
6557             if (stride < 0)
6558             {
6559                 process_entrypoint_error("%s: Invalid interleaved vertex stride: %i\n", VOGL_METHOD_NAME, static_cast<int>(stride));
6560                 return cStatusSoftFailure;
6561             }
6562
6563             const interleaved_array_desc_entry_t &fmt = vogl_g_interleaved_array_descs[fmt_index];
6564
6565             if (!stride)
6566             {
6567                 stride = fmt.s;
6568                 VOGL_ASSERT(stride > 0);
6569             }
6570
6571             GL_ENTRYPOINT(glDisableClientState)(GL_EDGE_FLAG_ARRAY);
6572             GL_ENTRYPOINT(glDisableClientState)(GL_INDEX_ARRAY);
6573             GL_ENTRYPOINT(glDisableClientState)(GL_SECONDARY_COLOR_ARRAY);
6574             GL_ENTRYPOINT(glDisableClientState)(GL_FOG_COORD_ARRAY);
6575
6576             check_gl_error();
6577
6578             if (fmt.et)
6579             {
6580                 GLint cur_client_active_texture = 0;
6581                 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6582
6583                 int tex_index = cur_client_active_texture - GL_TEXTURE0;
6584                 if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6585                 {
6586                     process_entrypoint_error("%s: glInterleavedArrays called with an invalid or unsupported client active texture (0x%08X)\n", VOGL_METHOD_NAME, cur_client_active_texture);
6587                     return cStatusSoftFailure;
6588                 }
6589
6590                 GL_ENTRYPOINT(glEnableClientState)(GL_TEXTURE_COORD_ARRAY);
6591                 vertex_array_helper(fmt.st, GL_FLOAT, stride, trace_pointer_value,
6592                                     vogl_texcoord_pointer_array_id, GL_ENTRYPOINT(glTexCoordPointer), m_client_side_texcoord_data[tex_index]);
6593             }
6594             else
6595             {
6596                 GL_ENTRYPOINT(glDisableClientState)(GL_TEXTURE_COORD_ARRAY);
6597             }
6598
6599             check_gl_error();
6600
6601             if (fmt.ec)
6602             {
6603                 GL_ENTRYPOINT(glEnableClientState)(GL_COLOR_ARRAY);
6604                 vertex_array_helper(fmt.sc, fmt.tc, stride, trace_pointer_value + fmt.pc,
6605                                     vogl_color_pointer_array_id, GL_ENTRYPOINT(glColorPointer), m_client_side_array_data[vogl_color_pointer_array_id]);
6606             }
6607             else
6608             {
6609                 GL_ENTRYPOINT(glDisableClientState)(GL_COLOR_ARRAY);
6610             }
6611
6612             check_gl_error();
6613
6614             if (fmt.en)
6615             {
6616                 GL_ENTRYPOINT(glEnableClientState)(GL_NORMAL_ARRAY);
6617                 vertex_array_helper_no_size(GL_FLOAT, stride, trace_pointer_value + fmt.pn,
6618                                             vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointer));
6619             }
6620             else
6621             {
6622                 GL_ENTRYPOINT(glDisableClientState)(GL_NORMAL_ARRAY);
6623             }
6624
6625             check_gl_error();
6626
6627             GL_ENTRYPOINT(glEnableClientState)(GL_VERTEX_ARRAY);
6628             vertex_array_helper(fmt.sv, GL_FLOAT, stride, trace_pointer_value + fmt.pv,
6629                                 vogl_vertex_pointer_array_id, GL_ENTRYPOINT(glVertexPointer), m_client_side_array_data[vogl_vertex_pointer_array_id]);
6630
6631             break;
6632         }
6633         case VOGL_ENTRYPOINT_glVertexAttribIPointer:
6634         case VOGL_ENTRYPOINT_glVertexAttribIPointerEXT:
6635         {
6636             GLuint index = trace_packet.get_param_value<GLuint>(0);
6637             GLint size = trace_packet.get_param_value<GLint>(1);
6638             GLenum type = trace_packet.get_param_value<GLenum>(2);
6639             GLsizei stride = trace_packet.get_param_value<GLsizei>(3);
6640             vogl_trace_ptr_value trace_pointer = trace_packet.get_param_ptr_value(4);
6641
6642             if (index >= m_pCur_context_state->m_context_info.get_max_vertex_attribs())
6643             {
6644                 process_entrypoint_error("%s: Generic vertex attribute index is too large\n", VOGL_METHOD_NAME);
6645                 return cStatusSoftFailure;
6646             }
6647
6648             GLuint buffer = vogl_get_bound_gl_buffer(GL_ARRAY_BUFFER);
6649             void *pPtr = reinterpret_cast<void *>(trace_pointer);
6650             if ((!buffer) && (trace_pointer))
6651             {
6652                 // We've got a trace pointer to client side memory, but we don't have it until the actual draw.
6653                 // So point this guy into one of our client size memory buffers that's hopefully large enough.
6654                 if (!m_client_side_vertex_attrib_data[index].size())
6655                 {
6656                     m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
6657                 }
6658                 pPtr = m_client_side_vertex_attrib_data[index].get_ptr();
6659             }
6660
6661             if (entrypoint_id == VOGL_ENTRYPOINT_glVertexAttribIPointer)
6662                 GL_ENTRYPOINT(glVertexAttribIPointer)(index, size, type, stride, pPtr);
6663             else
6664                 GL_ENTRYPOINT(glVertexAttribIPointerEXT)(index, size, type, stride, pPtr);
6665
6666             break;
6667         }
6668         case VOGL_ENTRYPOINT_glVertexAttribPointerARB:
6669         case VOGL_ENTRYPOINT_glVertexAttribPointer:
6670         {
6671             GLuint index = trace_packet.get_param_value<GLuint>(0);
6672             GLint size = trace_packet.get_param_value<GLint>(1);
6673             GLenum type = trace_packet.get_param_value<GLenum>(2);
6674             GLboolean normalized = trace_packet.get_param_value<GLboolean>(3);
6675             GLsizei stride = trace_packet.get_param_value<GLsizei>(4);
6676             vogl_trace_ptr_value trace_pointer = trace_packet.get_param_ptr_value(5);
6677
6678             if (index >= m_pCur_context_state->m_context_info.get_max_vertex_attribs())
6679             {
6680                 process_entrypoint_error("%s: Generic vertex attribute index is too large\n", VOGL_METHOD_NAME);
6681                 return cStatusSoftFailure;
6682             }
6683
6684             GLuint buffer = vogl_get_bound_gl_buffer(GL_ARRAY_BUFFER);
6685             void *pPtr = reinterpret_cast<void *>(trace_pointer);
6686             if ((!buffer) && (trace_pointer))
6687             {
6688                 // We've got a trace pointer to client side memory, but we don't have it until the actual draw.
6689                 // So point this guy into one of our client size memory buffers that's hopefully large enough.
6690                 if (!m_client_side_vertex_attrib_data[index].size())
6691                 {
6692                     m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
6693                 }
6694                 pPtr = m_client_side_vertex_attrib_data[index].get_ptr();
6695             }
6696
6697             if (entrypoint_id == VOGL_ENTRYPOINT_glVertexAttribPointer)
6698                 GL_ENTRYPOINT(glVertexAttribPointer)(index, size, type, normalized, stride, pPtr);
6699             else
6700                 GL_ENTRYPOINT(glVertexAttribPointerARB)(index, size, type, normalized, stride, pPtr);
6701
6702             break;
6703         }
6704         case VOGL_ENTRYPOINT_glDrawRangeElements:
6705         case VOGL_ENTRYPOINT_glDrawRangeElementsEXT:
6706         {
6707             GLenum mode = trace_packet.get_param_value<GLenum>(0);
6708             GLuint start = trace_packet.get_param_value<GLuint>(1);
6709             GLuint end = trace_packet.get_param_value<GLuint>(2);
6710             GLsizei count = trace_packet.get_param_value<GLsizei>(3);
6711             GLenum type = trace_packet.get_param_value<GLenum>(4);
6712             vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(5);
6713
6714             const GLvoid *pIndices;
6715             if (!draw_elements_client_side_array_setup(mode, start, end, count, type, trace_indices_ptr_value, pIndices, 0, true, true))
6716                 return cStatusSoftFailure;
6717
6718             if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6719             {
6720                 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawRangeElements)
6721                     GL_ENTRYPOINT(glDrawRangeElements)(mode, start, end, count, type, pIndices);
6722                 else
6723                     GL_ENTRYPOINT(glDrawRangeElementsEXT)(mode, start, end, count, type, pIndices);
6724             }
6725
6726             break;
6727         }
6728         case VOGL_ENTRYPOINT_glDrawRangeElementsBaseVertex:
6729         {
6730             GLenum mode = trace_packet.get_param_value<GLenum>(0);
6731             GLuint start = trace_packet.get_param_value<GLuint>(1);
6732             GLuint end = trace_packet.get_param_value<GLuint>(2);
6733             GLsizei count = trace_packet.get_param_value<GLsizei>(3);
6734             GLenum type = trace_packet.get_param_value<GLenum>(4);
6735             vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(5);
6736             GLint basevertex = trace_packet.get_param_value<GLint>(6);
6737
6738             const GLvoid *pIndices;
6739             if (!draw_elements_client_side_array_setup(mode, start, end, count, type, trace_indices_ptr_value, pIndices, basevertex, true, true))
6740                 return cStatusSoftFailure;
6741
6742             if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6743             {
6744                 GL_ENTRYPOINT(glDrawRangeElementsBaseVertex)(mode, start, end, count, type, pIndices, basevertex);
6745             }
6746
6747             break;
6748         }
6749         case VOGL_ENTRYPOINT_glDrawElements:
6750         {
6751             GLenum mode = trace_packet.get_param_value<GLenum>(0);
6752             GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6753             GLenum type = trace_packet.get_param_value<GLenum>(2);
6754             vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6755
6756             const GLvoid *pIndices;
6757             if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, 0, false, true))
6758                 return cStatusSoftFailure;
6759
6760             if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6761             {
6762                 GL_ENTRYPOINT(glDrawElements)(mode, count, type, pIndices);
6763             }
6764
6765             break;
6766         }
6767         case VOGL_ENTRYPOINT_glDrawArraysInstanced:
6768         case VOGL_ENTRYPOINT_glDrawArraysInstancedEXT:
6769         {
6770             VOGL_REPLAY_LOAD_PARAMS_HELPER_glDrawArraysInstanced;
6771
6772             const GLvoid *pIndices = NULL;
6773             if (!draw_elements_client_side_array_setup(mode, first, first + count - 1, count, GL_UNSIGNED_BYTE, 0, pIndices, 0, true, false))
6774                 return cStatusSoftFailure;
6775
6776             if (entrypoint_id == VOGL_ENTRYPOINT_glDrawArraysInstancedEXT)
6777             {
6778                 GLsizei start = first, primcount = instancecount;
6779                 VOGL_REPLAY_CALL_GL_HELPER_glDrawArraysInstancedEXT;
6780             }
6781             else
6782                 VOGL_REPLAY_CALL_GL_HELPER_glDrawArraysInstanced;
6783
6784             break;
6785         }
6786         case VOGL_ENTRYPOINT_glDrawArrays:
6787         case VOGL_ENTRYPOINT_glDrawArraysEXT:
6788         {
6789             GLenum mode = trace_packet.get_param_value<GLenum>(0);
6790             GLint first = trace_packet.get_param_value<GLint>(1);
6791             GLsizei count = trace_packet.get_param_value<GLsizei>(2);
6792
6793             const GLvoid *pIndices = NULL;
6794             if (!draw_elements_client_side_array_setup(mode, first, first + count - 1, count, GL_UNSIGNED_BYTE, 0, pIndices, 0, true, false))
6795                 return cStatusSoftFailure;
6796
6797             if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6798             {
6799                 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawArraysEXT)
6800                     GL_ENTRYPOINT(glDrawArraysEXT)(mode, first, count);
6801                 else
6802                     GL_ENTRYPOINT(glDrawArrays)(mode, first, count);
6803             }
6804
6805             break;
6806         }
6807         case VOGL_ENTRYPOINT_glDrawElementsInstanced:
6808         case VOGL_ENTRYPOINT_glDrawElementsInstancedARB:
6809         case VOGL_ENTRYPOINT_glDrawElementsInstancedEXT:
6810         {
6811             GLenum mode = trace_packet.get_param_value<GLenum>(0);
6812             GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6813             GLenum type = trace_packet.get_param_value<GLenum>(2);
6814             vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6815             GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6816
6817             const GLvoid *pIndices;
6818             if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, 0, false, true))
6819                 return cStatusSoftFailure;
6820
6821             if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6822             {
6823                 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawElementsInstanced)
6824                     GL_ENTRYPOINT(glDrawElementsInstanced)(mode, count, type, pIndices, primcount);
6825                 else if (entrypoint_id == VOGL_ENTRYPOINT_glDrawElementsInstancedEXT)
6826                     GL_ENTRYPOINT(glDrawElementsInstancedEXT)(mode, count, type, pIndices, primcount);
6827                 else
6828                     GL_ENTRYPOINT(glDrawElementsInstancedARB)(mode, count, type, pIndices, primcount);
6829             }
6830
6831             break;
6832         }
6833         case VOGL_ENTRYPOINT_glDrawElementsInstancedBaseVertex:
6834         {
6835             GLenum mode = trace_packet.get_param_value<GLenum>(0);
6836             GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6837             GLenum type = trace_packet.get_param_value<GLenum>(2);
6838             vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6839             GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6840             GLint basevertex = trace_packet.get_param_value<GLint>(5);
6841
6842             const GLvoid *pIndices;
6843             if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, basevertex, false, true))
6844                 return cStatusSoftFailure;
6845
6846             if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6847             {
6848                 GL_ENTRYPOINT(glDrawElementsInstancedBaseVertex)(mode, count, type, pIndices, primcount, basevertex);
6849             }
6850
6851             break;
6852         }
6853         case VOGL_ENTRYPOINT_glMultiDrawArrays:
6854         case VOGL_ENTRYPOINT_glMultiDrawArraysEXT:
6855         {
6856             GLenum mode = trace_packet.get_param_value<GLenum>(0);
6857
6858             const GLint *pFirst = trace_packet.get_param_client_memory<const GLint>(1);
6859             uint first_size = trace_packet.get_param_client_memory_data_size(1);
6860
6861             const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(2);
6862             uint count_size = trace_packet.get_param_client_memory_data_size(2);
6863
6864             GLsizei primcount = trace_packet.get_param_value<GLsizei>(3);
6865
6866             if ((first_size != primcount * sizeof(GLint)) || (count_size != primcount * sizeof(GLsizei)))
6867             {
6868                 process_entrypoint_error("%s: first and/or count params do not point to arrays of the expected size\n", VOGL_METHOD_NAME);
6869                 return cStatusSoftFailure;
6870             }
6871
6872             if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6873             {
6874                 //  Multi-draws with client side arrays are not supported for replay.
6875                 if (entrypoint_id == VOGL_ENTRYPOINT_glMultiDrawElements)
6876                     GL_ENTRYPOINT(glMultiDrawArrays)(mode, pFirst, pCount, primcount);
6877                 else
6878                     GL_ENTRYPOINT(glMultiDrawArraysEXT)(mode, pFirst, pCount, primcount);
6879             }
6880
6881             break;
6882         }
6883         case VOGL_ENTRYPOINT_glMultiDrawElements:
6884         case VOGL_ENTRYPOINT_glMultiDrawElementsEXT:
6885         {
6886             GLenum mode = trace_packet.get_param_value<GLenum>(0);
6887
6888             const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(1);
6889             uint count_size = trace_packet.get_param_client_memory_data_size(1);
6890
6891             GLenum type = trace_packet.get_param_value<GLenum>(2);
6892
6893             const vogl_client_memory_array trace_indices_void_ptr_array = trace_packet.get_param_client_memory_array(3); // const GLvoid *
6894
6895             GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6896
6897             if ((count_size != static_cast<uint>(primcount * sizeof(GLsizei))) || (trace_indices_void_ptr_array.size() != static_cast<uint>(primcount)))
6898             {
6899                 process_entrypoint_error("%s: count and/or indices params do not point to arrays of the expected size\n", VOGL_METHOD_NAME);
6900                 return cStatusSoftFailure;
6901             }
6902
6903             vogl::growable_array<GLvoid *, 256> replay_indices(trace_indices_void_ptr_array.size());
6904             for (uint i = 0; i < trace_indices_void_ptr_array.size(); i++)
6905                 replay_indices[i] = reinterpret_cast<GLvoid *>(trace_indices_void_ptr_array.get_element<vogl_trace_ptr_value>(i));
6906
6907             if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6908             {
6909                 //  Multi-draws with client side arrays are not supported for replay.
6910                 if (entrypoint_id == VOGL_ENTRYPOINT_glMultiDrawElements)
6911                     GL_ENTRYPOINT(glMultiDrawElements)(mode, pCount, type, replay_indices.get_ptr(), primcount);
6912                 else
6913                     GL_ENTRYPOINT(glMultiDrawElementsEXT)(mode, pCount, type, (const GLvoid **)replay_indices.get_ptr(), primcount);
6914             }
6915
6916             break;
6917         }
6918         case VOGL_ENTRYPOINT_glMultiDrawElementsBaseVertex:
6919         {
6920             GLenum mode = trace_packet.get_param_value<GLenum>(0);
6921
6922             const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(1);
6923             uint count_size = trace_packet.get_param_client_memory_data_size(1);
6924
6925             GLenum type = trace_packet.get_param_value<GLenum>(2);
6926
6927             const vogl_client_memory_array trace_indices_void_ptr_array = trace_packet.get_param_client_memory_array(3); // const GLvoid *
6928             //GLvoid * const *ppIndices = trace_packet.get_param_client_memory<GLvoid *>(3);
6929             //uint index_size = trace_packet.get_param_client_memory_data_size(3);
6930
6931             GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6932
6933             const GLint *pBase_vertex = trace_packet.get_param_client_memory<const GLint>(5);
6934             uint base_vertex_size = trace_packet.get_param_client_memory_data_size(5);
6935
6936             if ((count_size != primcount * sizeof(GLsizei)) ||
6937                 (trace_indices_void_ptr_array.size() != static_cast<uint>(primcount)) ||
6938                 (base_vertex_size != primcount * sizeof(GLint)))
6939             {
6940                 process_entrypoint_error("%s: count, indices, and/or base_vertex_size params do not point to arrays of the expected size\n", VOGL_METHOD_NAME);
6941                 return cStatusSoftFailure;
6942             }
6943
6944             vogl::growable_array<GLvoid *, 256> replay_indices(trace_indices_void_ptr_array.size());
6945             for (uint i = 0; i < trace_indices_void_ptr_array.size(); i++)
6946                 replay_indices[i] = reinterpret_cast<GLvoid *>(trace_indices_void_ptr_array.get_element<vogl_trace_ptr_value>(i));
6947
6948             if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6949             {
6950                 //  Multi-draws with client side arrays are not supported for replay.
6951                 GL_ENTRYPOINT(glMultiDrawElementsBaseVertex)(mode, pCount, type, replay_indices.get_ptr(), primcount, pBase_vertex);
6952             }
6953
6954             break;
6955         }
6956         case VOGL_ENTRYPOINT_glDrawElementsBaseVertex:
6957         {
6958             GLenum mode = trace_packet.get_param_value<GLenum>(0);
6959             GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6960             GLenum type = trace_packet.get_param_value<GLenum>(2);
6961             vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6962             GLint base_vertex = trace_packet.get_param_value<GLint>(4);
6963
6964             const GLvoid *pIndices;
6965             if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, base_vertex, false, true))
6966                 return cStatusSoftFailure;
6967
6968             if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6969             {
6970                 GL_ENTRYPOINT(glDrawElementsBaseVertex)(mode, count, type, pIndices, base_vertex);
6971             }
6972
6973             break;
6974         }
6975         case VOGL_ENTRYPOINT_glGetBufferSubData:
6976         {
6977             if (!benchmark_mode())
6978             {
6979                 GLenum target = trace_packet.get_param_value<GLenum>(0);
6980                 vogl_trace_ptr_value offset = trace_packet.get_param_ptr_value(1);
6981                 vogl_trace_ptr_value size = trace_packet.get_param_ptr_value(2);
6982                 GLvoid *pTrace_ptr = trace_packet.get_param_client_memory<GLvoid>(3);
6983
6984                 if (offset != static_cast<uintptr_t>(offset))
6985                 {
6986                     process_entrypoint_error("%s: offset parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, (uint64_t)offset);
6987                     return cStatusHardFailure;
6988                 }
6989
6990                 if ((size > cUINT32_MAX) || (size != static_cast<uintptr_t>(size)))
6991                 {
6992                     process_entrypoint_error("%s: size parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, (uint64_t)size);
6993                     return cStatusHardFailure;
6994                 }
6995
6996                 vogl::growable_array<uint8, 1024> buf(pTrace_ptr ? static_cast<uint>(size) : 0);
6997
6998                 GL_ENTRYPOINT(glGetBufferSubData)(target, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size), pTrace_ptr ? buf.get_ptr() : NULL);
6999
7000                 if ((buf.size()) && (pTrace_ptr))
7001                 {
7002                     if (memcmp(buf.get_ptr(), pTrace_ptr, static_cast<size_t>(size)) != 0)
7003                     {
7004                         process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
7005                     }
7006                 }
7007             }
7008
7009             break;
7010         }
7011         case VOGL_ENTRYPOINT_glGetClipPlane:
7012         {
7013             if (!benchmark_mode())
7014             {
7015                 GLenum plane = trace_packet.get_param_value<GLenum>(0);
7016                 const GLdouble *pTrace_equation = trace_packet.get_param_client_memory<GLdouble>(1);
7017
7018                 GLdouble equation[4];
7019                 GL_ENTRYPOINT(glGetClipPlane)(plane, pTrace_equation ? equation : NULL);
7020
7021                 if (pTrace_equation)
7022                 {
7023                     if (memcmp(equation, pTrace_equation, sizeof(GLdouble) * 4) != 0)
7024                     {
7025                         process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
7026                     }
7027                 }
7028             }
7029
7030             break;
7031         }
7032         case VOGL_ENTRYPOINT_glBufferData:
7033         case VOGL_ENTRYPOINT_glBufferDataARB:
7034         {
7035             GLenum target = trace_packet.get_param_value<GLenum>(0);
7036             vogl_trace_ptr_value size = trace_packet.get_param_value<vogl_trace_ptr_value>(1); // GLsizeiptrARB
7037             const GLvoid *data = trace_packet.get_param_client_memory_ptr(2);
7038             uint data_size = trace_packet.get_param_client_memory_data_size(2);
7039             GLenum usage = trace_packet.get_param_value<GLenum>(3);
7040
7041             if ((data) && (static_cast<vogl_trace_ptr_value>(data_size) < size))
7042             {
7043                 process_entrypoint_error("%s: trace's data array is too small\n", VOGL_METHOD_NAME);
7044                 return cStatusHardFailure;
7045             }
7046
7047             if (size != static_cast<uintptr_t>(size))
7048             {
7049                 process_entrypoint_error("%s: size parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(size));
7050                 return cStatusHardFailure;
7051             }
7052
7053             if (entrypoint_id == VOGL_ENTRYPOINT_glBufferData)
7054                 g_vogl_actual_gl_entrypoints.m_glBufferData(target, static_cast<GLsizeiptr>(size), data, usage);
7055             else
7056                 g_vogl_actual_gl_entrypoints.m_glBufferDataARB(target, static_cast<GLsizeiptrARB>(size), data, usage);
7057
7058             GLuint buffer = vogl_get_bound_gl_buffer(target);
7059             if (buffer)
7060             {
7061                 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7062
7063                 uint i;
7064                 for (i = 0; i < mapped_bufs.size(); i++)
7065                 {
7066                     if (mapped_bufs[i].m_buffer == buffer)
7067                     {
7068                         process_entrypoint_warning("%s: glBufferData() called on already mapped GL buffer %u, assuming GL will be unmapping it\n", VOGL_METHOD_NAME, buffer);
7069
7070                         mapped_bufs.erase_unordered(i);
7071                         break;
7072                     }
7073                 }
7074             }
7075
7076             break;
7077         }
7078         case VOGL_ENTRYPOINT_glMapBufferARB:
7079         case VOGL_ENTRYPOINT_glMapBuffer:
7080         {
7081             GLenum target = trace_packet.get_param_value<GLenum>(0);
7082             GLenum access = trace_packet.get_param_value<GLenum>(1);
7083             vogl_trace_ptr_value trace_result_ptr_value = trace_packet.get_return_ptr_value();
7084
7085             // FIXME - must call GL even if !pTrace_result
7086             if (trace_result_ptr_value)
7087             {
7088                 void *pMap;
7089                 if (entrypoint_id == VOGL_ENTRYPOINT_glMapBuffer)
7090                     pMap = GL_ENTRYPOINT(glMapBuffer)(target, access);
7091                 else
7092                     pMap = GL_ENTRYPOINT(glMapBufferARB)(target, access);
7093
7094                 if (!pMap)
7095                 {
7096                     process_entrypoint_error("%s: glMapBuffer succeeded during trace, but failed during replay!\n", VOGL_METHOD_NAME);
7097                     return cStatusHardFailure;
7098                 }
7099
7100                 GLuint buffer = vogl_get_bound_gl_buffer(target);
7101
7102                 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7103
7104                 uint i;
7105                 for (i = 0; i < mapped_bufs.size(); i++)
7106                 {
7107                     if (mapped_bufs[i].m_buffer == buffer)
7108                     {
7109                         process_entrypoint_error("%s: Buffer %u is already mapped\n", VOGL_METHOD_NAME, buffer);
7110                         return cStatusHardFailure;
7111                     }
7112                 }
7113
7114                 if (i == mapped_bufs.size())
7115                 {
7116                     GLint length = 0;
7117                     GL_ENTRYPOINT(glGetBufferParameteriv)(target, GL_BUFFER_SIZE, &length);
7118
7119                     vogl_mapped_buffer_desc m;
7120                     m.m_buffer = buffer;
7121                     m.m_target = target;
7122                     m.m_offset = 0;
7123                     m.m_length = length;
7124                     m.m_access = access;
7125                     m.m_range = false;
7126                     m.m_pPtr = pMap;
7127                     mapped_bufs.push_back(m);
7128                 }
7129             }
7130
7131             break;
7132         }
7133         case VOGL_ENTRYPOINT_glMapBufferRange:
7134         {
7135             GLenum target = trace_packet.get_param_value<GLenum>(0);
7136             vogl_trace_ptr_value offset = trace_packet.get_param_value<vogl_trace_ptr_value>(1); // GLintptr
7137             vogl_trace_ptr_value length = trace_packet.get_param_value<vogl_trace_ptr_value>(2); // GLsizeiptr
7138             GLbitfield access = trace_packet.get_param_value<GLbitfield>(3);
7139             vogl_trace_ptr_value trace_result_ptr_value = trace_packet.get_return_ptr_value();
7140
7141             if (offset != static_cast<uintptr_t>(offset))
7142             {
7143                 process_entrypoint_error("%s: offset parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(offset));
7144                 return cStatusHardFailure;
7145             }
7146             if (length != static_cast<uintptr_t>(length))
7147             {
7148                 process_entrypoint_error("%s: length parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(length));
7149                 return cStatusHardFailure;
7150             }
7151
7152             // FIXME - must call GL even if !pTrace_result
7153             if (trace_result_ptr_value)
7154             {
7155                 void *pMap = GL_ENTRYPOINT(glMapBufferRange)(target, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(length), access);
7156                 if (!pMap)
7157                 {
7158                     process_entrypoint_error("%s: glMapBufferRange succeeded during trace, but failed during replay!\n", VOGL_METHOD_NAME);
7159                     return cStatusHardFailure;
7160                 }
7161
7162                 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7163
7164                 GLuint buffer = vogl_get_bound_gl_buffer(target);
7165                 uint i;
7166                 for (i = 0; i < mapped_bufs.size(); i++)
7167                 {
7168                     if (mapped_bufs[i].m_buffer == buffer)
7169                     {
7170                         process_entrypoint_error("%s: Buffer %u is already mapped\n", VOGL_METHOD_NAME, buffer);
7171                         return cStatusHardFailure;
7172                     }
7173                 }
7174
7175                 if (i == mapped_bufs.size())
7176                 {
7177                     vogl_mapped_buffer_desc m;
7178                     m.m_buffer = buffer;
7179                     m.m_target = target;
7180                     m.m_offset = offset;
7181                     m.m_length = length;
7182                     m.m_access = access;
7183                     m.m_range = true;
7184                     m.m_pPtr = pMap;
7185                     mapped_bufs.push_back(m);
7186                 }
7187             }
7188
7189             break;
7190         }
7191         case VOGL_ENTRYPOINT_glFlushMappedBufferRange:
7192         {
7193             // vogltrace queues up the flushes, will process them while handling the glUnmapBuffer() call
7194             break;
7195         }
7196         case VOGL_ENTRYPOINT_glUnmapBufferARB:
7197         case VOGL_ENTRYPOINT_glUnmapBuffer:
7198         {
7199             GLenum target = trace_packet.get_param_value<GLenum>(0);
7200             GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7201
7202             GLuint buffer = vogl_get_bound_gl_buffer(target);
7203
7204             // FIXME - must call GL even if !buffer
7205             if (buffer)
7206             {
7207                 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7208
7209                 uint mapped_buffers_index;
7210                 for (mapped_buffers_index = 0; mapped_buffers_index < mapped_bufs.size(); mapped_buffers_index++)
7211                     if (mapped_bufs[mapped_buffers_index].m_buffer == buffer)
7212                         break;
7213                 if (mapped_buffers_index == mapped_bufs.size())
7214                 {
7215                     process_entrypoint_error("%s: Unable to find mapped buffer during unmap\n", VOGL_METHOD_NAME);
7216                     return cStatusHardFailure;
7217                 }
7218
7219                 vogl_mapped_buffer_desc &map_desc = mapped_bufs[mapped_buffers_index];
7220
7221                 bool writable_map = false;
7222                 bool explicit_bit = false;
7223                 if (map_desc.m_range)
7224                 {
7225                     writable_map = ((map_desc.m_access & GL_MAP_WRITE_BIT) != 0);
7226                     explicit_bit = (map_desc.m_access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0;
7227                 }
7228                 else
7229                 {
7230                     writable_map = (map_desc.m_access != GL_READ_ONLY);
7231                 }
7232
7233                 if (writable_map)
7234                 {
7235                     const key_value_map &unmap_data = trace_packet.get_key_value_map();
7236
7237                     if (explicit_bit)
7238                     {
7239                         int num_flushed_ranges = unmap_data.get_int(string_hash("flushed_ranges"));
7240
7241                         for (int i = 0; i < num_flushed_ranges; i++)
7242                         {
7243                             int64_t ofs = unmap_data.get_int64(i * 4 + 0);
7244                             int64_t size = unmap_data.get_int64(i * 4 + 1);
7245                             VOGL_NOTE_UNUSED(size);
7246                             const uint8_vec *pData = unmap_data.get_blob(i * 4 + 2);
7247                             if (!pData)
7248                             {
7249                                 process_entrypoint_error("%s: Failed finding flushed range data in key value map\n", VOGL_METHOD_NAME);
7250                                 return cStatusHardFailure;
7251                             }
7252
7253                             if (ofs != static_cast<GLintptr>(ofs))
7254                             {
7255                                 process_entrypoint_error("%s: Flush offset is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(ofs));
7256                                 return cStatusHardFailure;
7257                             }
7258
7259                             VOGL_ASSERT(size == pData->size());
7260
7261                             memcpy(static_cast<uint8 *>(map_desc.m_pPtr) + ofs, pData->get_ptr(), pData->size());
7262
7263                             GL_ENTRYPOINT(glFlushMappedBufferRange)(target, static_cast<GLintptr>(ofs), pData->size());
7264                         }
7265                     }
7266                     else
7267                     {
7268                         int64_t ofs = unmap_data.get_int64(0);
7269                         VOGL_NOTE_UNUSED(ofs);
7270                         int64_t size = unmap_data.get_int64(1);
7271                         VOGL_NOTE_UNUSED(size);
7272                         const uint8_vec *pData = unmap_data.get_blob(2);
7273                         if (!pData)
7274                         {
7275                             process_entrypoint_error("%s: Failed finding mapped data in key value map\n", VOGL_METHOD_NAME);
7276                             return cStatusHardFailure;
7277                         }
7278                         else
7279                         {
7280                             memcpy(map_desc.m_pPtr, pData->get_ptr(), pData->size());
7281                         }
7282                     }
7283                 }
7284
7285                 get_shared_state()->m_shadow_state.m_mapped_buffers.erase_unordered(mapped_buffers_index);
7286             }
7287
7288             GLboolean replay_result;
7289             if (entrypoint_id == VOGL_ENTRYPOINT_glUnmapBuffer)
7290                 replay_result = GL_ENTRYPOINT(glUnmapBuffer)(target);
7291             else
7292                 replay_result = GL_ENTRYPOINT(glUnmapBufferARB)(target);
7293
7294             if (trace_result != replay_result)
7295                 process_entrypoint_warning("%s: Replay glUnmapBuffer's return value differs from trace's (replay: %u vs. trace: %u)\n", VOGL_METHOD_NAME, replay_result, trace_result);
7296
7297             break;
7298         }
7299         case VOGL_ENTRYPOINT_glGenVertexArrays:
7300         {
7301             if (!gen_handles(get_context_state()->m_vertex_array_objects, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glGenVertexArrays), NULL))
7302                 return cStatusHardFailure;
7303             break;
7304         }
7305         case VOGL_ENTRYPOINT_glBindVertexArray:
7306         {
7307             GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7308             GLuint replay_handle = map_handle(get_context_state()->m_vertex_array_objects, trace_handle);
7309
7310             GL_ENTRYPOINT(glBindVertexArray)(replay_handle);
7311             break;
7312         }
7313         case VOGL_ENTRYPOINT_glDeleteVertexArrays:
7314         {
7315             delete_handles(get_context_state()->m_vertex_array_objects, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteVertexArrays));
7316             break;
7317         }
7318         case VOGL_ENTRYPOINT_glIsFramebuffer:
7319         case VOGL_ENTRYPOINT_glIsFramebufferEXT:
7320         {
7321             if (!benchmark_mode())
7322             {
7323                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7324                 GLuint replay_handle = map_handle(get_context_state()->m_framebuffers, trace_handle);
7325                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7326
7327                 GLboolean replay_result;
7328                 if (entrypoint_id == VOGL_ENTRYPOINT_glIsFramebuffer)
7329                     replay_result = GL_ENTRYPOINT(glIsFramebuffer)(replay_handle);
7330                 else
7331                     replay_result = GL_ENTRYPOINT(glIsFramebufferEXT)(replay_handle);
7332
7333                 if (trace_result != replay_result)
7334                     process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7335             }
7336
7337             break;
7338         }
7339         case VOGL_ENTRYPOINT_glIsBuffer:
7340         {
7341             if (!benchmark_mode())
7342             {
7343                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7344                 GLuint replay_handle = map_handle(get_shared_state()->m_buffers, trace_handle);
7345                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7346
7347                 GLboolean replay_result = GL_ENTRYPOINT(glIsBuffer)(replay_handle);
7348                 if (trace_result != replay_result)
7349                     process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7350             }
7351             break;
7352         }
7353         case VOGL_ENTRYPOINT_glIsEnabledi:
7354         {
7355             if (!benchmark_mode())
7356             {
7357                 GLenum cap = trace_packet.get_param_value<GLenum>(0);
7358                 GLuint index = trace_packet.get_param_value<GLuint>(1);
7359                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7360
7361                 GLboolean replay_result = GL_ENTRYPOINT(glIsEnabledi)(cap, index);
7362                 if (trace_result != replay_result)
7363                     process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7364             }
7365             break;
7366         }
7367         case VOGL_ENTRYPOINT_glIsEnabled:
7368         {
7369             if (!benchmark_mode())
7370             {
7371                 GLenum cap = trace_packet.get_param_value<GLenum>(0);
7372                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7373
7374                 GLboolean replay_result = GL_ENTRYPOINT(glIsEnabled)(cap);
7375                 if (trace_result != replay_result)
7376                     process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7377             }
7378             break;
7379         }
7380         case VOGL_ENTRYPOINT_glIsProgram:
7381         {
7382             if (!benchmark_mode())
7383             {
7384                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7385                 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
7386                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7387
7388                 GLboolean replay_result = GL_ENTRYPOINT(glIsProgram)(replay_handle);
7389
7390                 if (trace_result != replay_result)
7391                     process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7392             }
7393             break;
7394         }
7395         case VOGL_ENTRYPOINT_glIsQuery:
7396         {
7397             if (!benchmark_mode())
7398             {
7399                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7400                 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
7401                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7402
7403                 GLboolean replay_result = GL_ENTRYPOINT(glIsQuery)(replay_handle);
7404                 if (trace_result != replay_result)
7405                     process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7406             }
7407             break;
7408         }
7409         case VOGL_ENTRYPOINT_glIsShader:
7410         {
7411             if (!benchmark_mode())
7412             {
7413                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7414                 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
7415                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7416
7417                 GLboolean replay_result = GL_ENTRYPOINT(glIsShader)(replay_handle);
7418                 if (trace_result != replay_result)
7419                     process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7420             }
7421             break;
7422         }
7423         case VOGL_ENTRYPOINT_glIsTexture:
7424         case VOGL_ENTRYPOINT_glIsTextureEXT:
7425         {
7426             if (!benchmark_mode())
7427             {
7428                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7429                 GLuint replay_handle = trace_handle;
7430                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7431
7432                 map_handle(get_shared_state()->m_shadow_state.m_textures, trace_handle, replay_handle);
7433
7434                 GLboolean replay_result;
7435                 if (entrypoint_id == VOGL_ENTRYPOINT_glIsTexture)
7436                     replay_result = GL_ENTRYPOINT(glIsTexture)(replay_handle);
7437                 else
7438                     replay_result = GL_ENTRYPOINT(glIsTextureEXT)(replay_handle);
7439
7440                 if (trace_result != replay_result)
7441                     process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7442             }
7443
7444             break;
7445         }
7446         case VOGL_ENTRYPOINT_glIsVertexArray:
7447         {
7448             if (!benchmark_mode())
7449             {
7450                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7451                 GLuint replay_handle = map_handle(get_context_state()->m_vertex_array_objects, trace_handle);
7452                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7453
7454                 GLboolean replay_result = GL_ENTRYPOINT(glIsVertexArray)(replay_handle);
7455                 if (trace_result != replay_result)
7456                     process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7457             }
7458
7459             break;
7460         }
7461         case VOGL_ENTRYPOINT_glReadPixels:
7462         {
7463 // TODO: This is causing huge stalls when replaying metro, not sure why. Also, the # of traced bytes is zero in metro.
7464 #if 0
7465                 if (!benchmark_mode())
7466                 {
7467             GLint x = trace_packet.get_param_value<GLint>(0);
7468             GLint y = trace_packet.get_param_value<GLint>(1);
7469             GLsizei width = trace_packet.get_param_value<GLsizei>(2);
7470             GLsizei height = trace_packet.get_param_value<GLsizei>(3);
7471             GLenum format = trace_packet.get_param_value<GLenum>(4);
7472             GLenum type = trace_packet.get_param_value<GLenum>(5);
7473             const GLvoid *trace_data = trace_packet.get_param_client_memory<const GLvoid>(6);
7474             uint trace_data_size = trace_packet.get_param_client_memory_data_size(6);
7475
7476                         size_t replay_data_size = vogl_get_image_size(format, type, width, height, 1);
7477                         if (replay_data_size != trace_data_size)
7478                         {
7479                                 process_entrypoint_warning("%s: Unexpected trace data size, got %u expected %" PRIu64 "\n", VOGL_METHOD_NAME, trace_data_size, (uint64_t)replay_data_size);
7480                         }
7481                         else if (!trace_data)
7482                         {
7483                                 process_entrypoint_warning("%s: Trace data is missing from packet\n", VOGL_METHOD_NAME);
7484                         }
7485
7486                         if (replay_data_size > cUINT32_MAX)
7487                         {
7488                                 process_entrypoint_error("%s: Replay data size is too large (%" PRIu64 ")!\n", VOGL_METHOD_NAME, (uint64_t)replay_data_size);
7489                                 return cStatusHardFailure;
7490                         }
7491
7492                         vogl::vector<uint8> data(static_cast<uint>(replay_data_size));
7493                         GL_ENTRYPOINT(glReadPixels)(x, y, width, height, format, type, data.get_ptr());
7494
7495                         if ((trace_data_size == replay_data_size) && (trace_data_size) && (trace_data))
7496                         {
7497                                 if (memcmp(data.get_ptr(), trace_data, trace_data_size) != 0)
7498                                 {
7499                                         process_entrypoint_error("%s: Replay's returned pixel data differed from trace's!\n", VOGL_METHOD_NAME);
7500                                 }
7501                         }
7502                 }
7503 #endif
7504             break;
7505         }
7506         case VOGL_ENTRYPOINT_glGetTexLevelParameterfv:
7507         {
7508             if (!benchmark_mode())
7509             {
7510                 GLenum target = trace_packet.get_param_value<GLenum>(0);
7511                 GLint level = trace_packet.get_param_value<GLint>(1);
7512                 GLenum pname = trace_packet.get_param_value<GLenum>(2);
7513                 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<const GLfloat>(3);
7514                 uint trace_params_size = trace_packet.get_param_client_memory_data_size(3);
7515
7516                 int n = g_gl_enums.get_pname_count(pname);
7517                 if (n <= 0)
7518                 {
7519                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7520                     return cStatusSoftFailure;
7521                 }
7522
7523                 vogl::growable_array<GLfloat, 17> replay_params(n + 1);
7524                 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
7525
7526                 GL_ENTRYPOINT(glGetTexLevelParameterfv)(target, level, pname, replay_params.get_ptr());
7527
7528                 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
7529
7530                 if (!pTrace_params)
7531                     process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7532                 else if (trace_params_size != sizeof(GLfloat) * n)
7533                     process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7534                 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLfloat) * n) != 0)
7535                     process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7536             }
7537
7538             break;
7539         }
7540         case VOGL_ENTRYPOINT_glGetTexLevelParameteriv:
7541         {
7542             if (!benchmark_mode())
7543             {
7544                 GLenum target = trace_packet.get_param_value<GLenum>(0);
7545                 GLint level = trace_packet.get_param_value<GLint>(1);
7546                 GLenum pname = trace_packet.get_param_value<GLenum>(2);
7547                 const GLint *pTrace_params = trace_packet.get_param_client_memory<const GLint>(3);
7548                 uint trace_params_size = trace_packet.get_param_client_memory_data_size(3);
7549
7550                 int n = g_gl_enums.get_pname_count(pname);
7551                 if (n <= 0)
7552                 {
7553                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7554                     return cStatusSoftFailure;
7555                 }
7556
7557                 vogl::growable_array<GLint, 16> replay_params(n + 1);
7558                 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7559
7560                 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, pname, replay_params.get_ptr());
7561
7562                 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7563
7564                 if (!pTrace_params)
7565                     process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7566                 else if (trace_params_size != sizeof(GLint) * n)
7567                     process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7568                 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLint) * n) != 0)
7569                     process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7570             }
7571
7572             break;
7573         }
7574         case VOGL_ENTRYPOINT_glGetTexParameterIiv:
7575         case VOGL_ENTRYPOINT_glGetTexParameteriv:
7576         {
7577             if (!benchmark_mode())
7578             {
7579                 GLenum target = trace_packet.get_param_value<GLenum>(0);
7580                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7581                 const GLint *pTrace_params = trace_packet.get_param_client_memory<const GLint>(2);
7582                 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7583
7584                 int n = g_gl_enums.get_pname_count(pname);
7585                 if (n <= 0)
7586                 {
7587                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7588                     return cStatusSoftFailure;
7589                 }
7590
7591                 vogl::growable_array<GLint, 16> replay_params(n + 1);
7592                 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7593
7594                 if (entrypoint_id == VOGL_ENTRYPOINT_glGetTexParameterIiv)
7595                     GL_ENTRYPOINT(glGetTexParameterIiv)(target, pname, replay_params.get_ptr());
7596                 else
7597                     GL_ENTRYPOINT(glGetTexParameteriv)(target, pname, replay_params.get_ptr());
7598
7599                 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7600
7601                 if (!pTrace_params)
7602                     process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7603                 else if (trace_params_size != sizeof(GLint) * n)
7604                     process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7605                 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLint) * n) != 0)
7606                     process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7607             }
7608
7609             break;
7610         }
7611         case VOGL_ENTRYPOINT_glGetTexParameterIuiv:
7612         {
7613             if (!benchmark_mode())
7614             {
7615                 GLenum target = trace_packet.get_param_value<GLenum>(0);
7616                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7617                 const GLuint *pTrace_params = trace_packet.get_param_client_memory<const GLuint>(2);
7618                 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7619
7620                 int n = g_gl_enums.get_pname_count(pname);
7621                 if (n <= 0)
7622                 {
7623                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7624                     return cStatusSoftFailure;
7625                 }
7626
7627                 vogl::growable_array<GLuint, 16> replay_params(n + 1);
7628                 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7629
7630                 GL_ENTRYPOINT(glGetTexParameterIuiv)(target, pname, replay_params.get_ptr());
7631
7632                 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7633
7634                 if (!pTrace_params)
7635                     process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7636                 else if (trace_params_size != sizeof(GLuint) * n)
7637                     process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7638                 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLuint) * n) != 0)
7639                     process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7640             }
7641
7642             break;
7643         }
7644         case VOGL_ENTRYPOINT_glGetTexParameterfv:
7645         {
7646             if (!benchmark_mode())
7647             {
7648                 GLenum target = trace_packet.get_param_value<GLenum>(0);
7649                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7650                 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<const GLfloat>(2);
7651                 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7652
7653                 int n = g_gl_enums.get_pname_count(pname);
7654                 if (n <= 0)
7655                 {
7656                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7657                     return cStatusSoftFailure;
7658                 }
7659
7660                 vogl::growable_array<GLfloat, 17> replay_params(n + 1);
7661                 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
7662
7663                 GL_ENTRYPOINT(glGetTexParameterfv)(target, pname, replay_params.get_ptr());
7664
7665                 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
7666
7667                 if (!pTrace_params)
7668                     process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7669                 else if (trace_params_size != sizeof(GLfloat) * n)
7670                     process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7671                 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLfloat) * n) != 0)
7672                     process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7673             }
7674
7675             break;
7676         }
7677
7678         case VOGL_ENTRYPOINT_glGetVertexAttribdv:
7679         {
7680             status = get_vertex_attrib_helper<GLdouble>(GL_ENTRYPOINT(glGetVertexAttribdv));
7681             if (status != cStatusOK)
7682                 return status;
7683             break;
7684         }
7685         case VOGL_ENTRYPOINT_glGetVertexAttribfv:
7686         {
7687             status = get_vertex_attrib_helper<GLfloat>(GL_ENTRYPOINT(glGetVertexAttribfv));
7688             if (status != cStatusOK)
7689                 return status;
7690             break;
7691         }
7692         case VOGL_ENTRYPOINT_glGetVertexAttribiv:
7693         {
7694             status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribiv));
7695             if (status != cStatusOK)
7696                 return status;
7697             break;
7698         }
7699         case VOGL_ENTRYPOINT_glGetVertexAttribIiv:
7700         {
7701             status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribIiv));
7702             if (status != cStatusOK)
7703                 return status;
7704             break;
7705         }
7706         case VOGL_ENTRYPOINT_glGetVertexAttribIivEXT:
7707         {
7708             status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribIivEXT));
7709             if (status != cStatusOK)
7710                 return status;
7711             break;
7712         }
7713         case VOGL_ENTRYPOINT_glGetVertexAttribIuiv:
7714         {
7715             status = get_vertex_attrib_helper<GLuint>(GL_ENTRYPOINT(glGetVertexAttribIuiv));
7716             if (status != cStatusOK)
7717                 return status;
7718             break;
7719         }
7720         case VOGL_ENTRYPOINT_glGetVertexAttribIuivEXT:
7721         {
7722             status = get_vertex_attrib_helper<GLuint>(GL_ENTRYPOINT(glGetVertexAttribIuivEXT));
7723             if (status != cStatusOK)
7724                 return status;
7725             break;
7726         }
7727         case VOGL_ENTRYPOINT_glGenLists:
7728         {
7729             GLsizei range = trace_packet.get_param_value<GLsizei>(0);
7730             GLuint trace_base_handle = trace_packet.get_return_value<GLuint>();
7731
7732             if (trace_base_handle)
7733             {
7734                 check_gl_error();
7735
7736                 GLuint replay_base_handle = GL_ENTRYPOINT(glGenLists)(range);
7737
7738                 if ((check_gl_error()) || (!replay_base_handle))
7739                 {
7740                     process_entrypoint_error("%s: glGenLists() succeeded in the trace, but failed during replay!\n", VOGL_METHOD_NAME);
7741                     return cStatusHardFailure;
7742                 }
7743
7744                 for (GLsizei i = 0; i < range; i++)
7745                 {
7746                     GLuint trace_handle = trace_base_handle + i;
7747                     GLuint replay_handle = replay_base_handle + i;
7748
7749                     if (!gen_handle(get_shared_state()->m_lists, trace_handle, replay_handle))
7750                         return cStatusHardFailure;
7751
7752                     if (!get_shared_state()->m_shadow_state.m_display_lists.gen_lists(trace_handle, 1, &replay_handle))
7753                     {
7754                         process_entrypoint_warning("%s: Failed genning list into display list shadow, trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
7755                     }
7756                 }
7757             }
7758             else
7759             {
7760                 GLuint replay_base_handle = GL_ENTRYPOINT(glGenLists)(range);
7761                 if (replay_base_handle)
7762                 {
7763                     process_entrypoint_warning("%s: glGenLists() failed in the trace, but succeeded during replay!\n", VOGL_METHOD_NAME);
7764
7765                     GL_ENTRYPOINT(glDeleteLists)(replay_base_handle, range);
7766                 }
7767             }
7768
7769             break;
7770         }
7771         case VOGL_ENTRYPOINT_glCallList:
7772         {
7773             GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7774             GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7775
7776             GL_ENTRYPOINT(glCallList)(replay_handle);
7777
7778             if (!get_shared_state()->m_shadow_state.m_display_lists.parse_list_and_update_shadows(trace_handle, display_list_bind_callback, this))
7779             {
7780                 process_entrypoint_warning("%s: Failed processing display list shadow for trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
7781             }
7782
7783             if ((status = post_draw_call()) != cStatusOK)
7784                 return status;
7785
7786             break;
7787         }
7788         case VOGL_ENTRYPOINT_glCallLists:
7789         {
7790             GLsizei n = trace_packet.get_param_value<GLsizei>(0);
7791             GLenum type = trace_packet.get_param_value<GLenum>(1);
7792             const GLvoid *pTrace_lists = trace_packet.get_param_client_memory<const GLvoid>(2);
7793             uint trace_lists_size = trace_packet.get_param_client_memory_data_size(2);
7794
7795             uint type_size = vogl_get_gl_type_size(type);
7796             if (!type_size)
7797             {
7798                 process_entrypoint_error("%s: Unable to execute glCallLists, type is invalid\n", VOGL_METHOD_NAME);
7799                 return cStatusSoftFailure;
7800             }
7801
7802             if ((n) && (!pTrace_lists))
7803             {
7804                 process_entrypoint_error("%s: Unable to execute glCallLists, lists param is NULL\n", VOGL_METHOD_NAME);
7805                 return cStatusSoftFailure;
7806             }
7807
7808             if (trace_lists_size < (type_size * n))
7809             {
7810                 process_entrypoint_error("%s: Unable to execute glCallLists, lists param data size is too small in trace\n", VOGL_METHOD_NAME);
7811                 return cStatusSoftFailure;
7812             }
7813
7814             GLuint list_base = 0;
7815             GL_ENTRYPOINT(glGetIntegerv)(GL_LIST_BASE, reinterpret_cast<GLint *>(&list_base));
7816
7817             const uint8 *pTrace_lists_ptr = static_cast<const uint8 *>(pTrace_lists);
7818             for (GLsizei i = 0; i < n; i++)
7819             {
7820                 GLint trace_handle = list_base;
7821                 switch (type)
7822                 {
7823                     case GL_BYTE:
7824                     {
7825                         trace_handle += *reinterpret_cast<const signed char *>(pTrace_lists_ptr);
7826                         pTrace_lists_ptr++;
7827                         break;
7828                     }
7829                     case GL_UNSIGNED_BYTE:
7830                     {
7831                         trace_handle += *pTrace_lists_ptr;
7832                         pTrace_lists_ptr++;
7833                         break;
7834                     }
7835                     case GL_SHORT:
7836                     {
7837                         trace_handle += *reinterpret_cast<const int16 *>(pTrace_lists_ptr);
7838                         pTrace_lists_ptr += sizeof(int16);
7839                         break;
7840                     }
7841                     case GL_UNSIGNED_SHORT:
7842                     {
7843                         trace_handle += *reinterpret_cast<const uint16 *>(pTrace_lists_ptr);
7844                         pTrace_lists_ptr += sizeof(uint16);
7845                         break;
7846                     }
7847                     case GL_INT:
7848                     {
7849                         trace_handle += *reinterpret_cast<const int32 *>(pTrace_lists_ptr);
7850                         pTrace_lists_ptr += sizeof(int32);
7851                         break;
7852                     }
7853                     case GL_UNSIGNED_INT:
7854                     {
7855                         trace_handle += *reinterpret_cast<const uint32 *>(pTrace_lists_ptr);
7856                         pTrace_lists_ptr += sizeof(uint32);
7857                         break;
7858                     }
7859                     case GL_FLOAT:
7860                     {
7861                         trace_handle += static_cast<GLint>(*reinterpret_cast<const float *>(pTrace_lists_ptr));
7862                         pTrace_lists_ptr += sizeof(float);
7863                         break;
7864                     }
7865                     case GL_2_BYTES:
7866                     {
7867                         trace_handle += ((pTrace_lists_ptr[0] << 8U) + pTrace_lists_ptr[1]);
7868                         pTrace_lists_ptr += 2;
7869                         break;
7870                     }
7871                     case GL_3_BYTES:
7872                     {
7873                         trace_handle += ((pTrace_lists_ptr[0] << 16U) + (pTrace_lists_ptr[1] << 8U) + pTrace_lists_ptr[2]);
7874                         pTrace_lists_ptr += 3;
7875                         break;
7876                     }
7877                     case GL_4_BYTES:
7878                     {
7879                         trace_handle += ((pTrace_lists_ptr[0] << 24U) + (pTrace_lists_ptr[1] << 16U) + (pTrace_lists_ptr[2] << 8U) + pTrace_lists_ptr[3]);
7880                         pTrace_lists_ptr += 4;
7881                         break;
7882                     }
7883                     default:
7884                     {
7885                         process_entrypoint_error("%s: Invalid type parameter (0x%08X)\n", VOGL_METHOD_NAME, type);
7886                         return cStatusSoftFailure;
7887                     }
7888                 }
7889
7890                 if (trace_handle <= 0)
7891                 {
7892                     process_entrypoint_error("%s: Trace handle after adding list base is negative (%i), skipping this list index\n", VOGL_METHOD_NAME, trace_handle);
7893                 }
7894                 else
7895                 {
7896                     GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7897                     GL_ENTRYPOINT(glCallList)(replay_handle);
7898
7899                     if (!get_shared_state()->m_shadow_state.m_display_lists.parse_list_and_update_shadows(trace_handle, display_list_bind_callback, this))
7900                     {
7901                         process_entrypoint_warning("%s: Failed processing display list shadow for trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
7902                     }
7903                 }
7904             }
7905
7906             if ((status = post_draw_call()) != cStatusOK)
7907                 return status;
7908
7909             break;
7910         }
7911         case VOGL_ENTRYPOINT_glDeleteLists:
7912         {
7913             GLuint trace_list = trace_packet.get_param_value<GLuint>(0);
7914             GLsizei range = trace_packet.get_param_value<GLsizei>(1);
7915
7916             for (GLsizei i = 0; i < range; i++)
7917             {
7918                 GLuint trace_handle = trace_list + i;
7919                 delete_handles(get_shared_state()->m_lists, 1, &trace_handle, delete_list_helper);
7920
7921                 if (!get_shared_state()->m_shadow_state.m_display_lists.del_lists(trace_handle, 1))
7922                 {
7923                     process_entrypoint_warning("%s: Unable to delete list in display list shadow, trace handle %u\n", VOGL_METHOD_NAME, trace_handle);
7924                 }
7925             }
7926
7927             break;
7928         }
7929         case VOGL_ENTRYPOINT_glIsList:
7930         {
7931             if (!benchmark_mode())
7932             {
7933                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7934                 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7935                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7936
7937                 GLboolean replay_result = GL_ENTRYPOINT(glIsList)(replay_handle);
7938                 if (trace_result != replay_result)
7939                     process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7940             }
7941
7942             break;
7943         }
7944         case VOGL_ENTRYPOINT_glNewList:
7945         {
7946             GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7947             GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7948             GLenum mode = trace_packet.get_param_value<GLenum>(1);
7949
7950             check_gl_error();
7951
7952             GL_ENTRYPOINT(glNewList)(replay_handle, mode);
7953
7954             if (!check_gl_error())
7955             {
7956                 get_shared_state()->m_shadow_state.m_display_lists.new_list(trace_handle, replay_handle);
7957
7958                 get_context_state()->m_current_display_list_mode = mode;
7959                 get_context_state()->m_current_display_list_handle = trace_handle;
7960             }
7961
7962             // TODO: Check if glNewList() failed vs the replay.
7963             // This is important, because if the new failed during tracing but succeeded during replay then we've seriously diverged.
7964             // This is a bigger topic, we really should have the option of calling glGetError() during tracing after each GL call and recording the results to check for divergence.
7965             break;
7966         }
7967         case VOGL_ENTRYPOINT_glListBase:
7968         {
7969             GLuint base = trace_packet.get_param_value<GLuint>(0);
7970             GL_ENTRYPOINT(glListBase)(base);
7971             break;
7972         }
7973         case VOGL_ENTRYPOINT_glEndList:
7974         {
7975             GL_ENTRYPOINT(glEndList)();
7976
7977             if (!get_context_state()->is_composing_display_list())
7978             {
7979                 process_entrypoint_warning("%s: glEndList() called without calling glNewList()!\n", VOGL_METHOD_NAME);
7980             }
7981             else
7982             {
7983                 if (!get_shared_state()->m_shadow_state.m_display_lists.end_list(get_context_state()->m_current_display_list_handle))
7984                     process_entrypoint_warning("%s: Failed ending display list, trace handle %u\n", VOGL_METHOD_NAME, get_context_state()->m_current_display_list_handle);
7985
7986                 get_context_state()->m_current_display_list_mode = GL_NONE;
7987                 get_context_state()->m_current_display_list_handle = -1;
7988             }
7989
7990             break;
7991         }
7992         case VOGL_ENTRYPOINT_glFeedbackBuffer:
7993         {
7994             GLsizei size = trace_packet.get_param_value<GLsizei>(0);
7995             GLenum type = trace_packet.get_param_value<GLenum>(1);
7996
7997             if (static_cast<GLsizei>(m_pCur_context_state->m_feedback_buffer.size()) < size)
7998                 m_pCur_context_state->m_feedback_buffer.resize(size);
7999
8000             GL_ENTRYPOINT(glFeedbackBuffer)(size, type, m_pCur_context_state->m_feedback_buffer.get_ptr());
8001
8002             break;
8003         }
8004         case VOGL_ENTRYPOINT_glSeparableFilter2D:
8005         {
8006             GLenum target = trace_packet.get_param_value<GLenum>(0);
8007             GLenum internalformat = trace_packet.get_param_value<GLenum>(1);
8008             GLsizei width = trace_packet.get_param_value<GLsizei>(2);
8009             GLsizei height = trace_packet.get_param_value<GLsizei>(3);
8010             GLenum format = trace_packet.get_param_value<GLenum>(4);
8011             GLenum type = trace_packet.get_param_value<GLenum>(5);
8012
8013             const GLvoid *row = trace_packet.get_param_client_memory<const GLvoid>(6);
8014             uint row_size = trace_packet.get_param_client_memory_data_size(6);
8015             if (row_size < vogl_get_image_size(format, type, width, 1, 1))
8016             {
8017                 process_entrypoint_error("%s: row trace array is too small\n", VOGL_METHOD_NAME);
8018                 return cStatusSoftFailure;
8019             }
8020
8021             const GLvoid *column = trace_packet.get_param_client_memory<const GLvoid>(7);
8022             uint col_size = trace_packet.get_param_client_memory_data_size(7);
8023             if (col_size < vogl_get_image_size(format, type, width, 1, 1))
8024             {
8025                 process_entrypoint_error("%s: column trace array is too small\n", VOGL_METHOD_NAME);
8026                 return cStatusSoftFailure;
8027             }
8028
8029             GL_ENTRYPOINT(glSeparableFilter2D)(target, internalformat, width, height, format, type, row, column);
8030             break;
8031         }
8032
8033         case VOGL_ENTRYPOINT_glNamedProgramLocalParameters4fvEXT:
8034         {
8035             GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8036             GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8037
8038             GL_ENTRYPOINT(glNamedProgramLocalParameters4fvEXT)(replay_program, trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLuint>(2), trace_packet.get_param_value<GLsizei>(3), trace_packet.get_param_client_memory<const GLfloat>(4));
8039             break;
8040         }
8041
8042         case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4iEXT:
8043         {
8044             GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8045             GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8046
8047             GL_ENTRYPOINT(glNamedProgramLocalParameterI4iEXT)(replay_program, trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLuint>(2), trace_packet.get_param_value<GLint>(3), trace_packet.get_param_value<GLint>(4), trace_packet.get_param_value<GLint>(5), trace_packet.get_param_value<GLint>(6));
8048             break;
8049         }
8050         case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4ivEXT:
8051         {
8052             GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8053             GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8054
8055             GL_ENTRYPOINT(glNamedProgramLocalParameterI4ivEXT)(replay_program, trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLuint>(2), trace_packet.get_param_client_memory<GLint>(3));
8056             break;
8057         }
8058
8059         case VOGL_ENTRYPOINT_glNamedProgramLocalParametersI4ivEXT:
8060         {
8061             GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8062             GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8063
8064             GL_ENTRYPOINT(glNamedProgramLocalParametersI4ivEXT)(replay_program, trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLuint>(2), trace_packet.get_param_value<GLsizei>(3), trace_packet.get_param_client_memory<GLint>(4));
8065             break;
8066         }
8067         case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4uiEXT:
8068         {
8069             GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8070             GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8071
8072             GL_ENTRYPOINT(glNamedProgramLocalParameterI4uiEXT)(replay_program, trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLuint>(2),
8073                                                                trace_packet.get_param_value<GLuint>(3), trace_packet.get_param_value<GLuint>(4),
8074                                                                trace_packet.get_param_value<GLuint>(5), trace_packet.get_param_value<GLuint>(6));
8075             break;
8076         }
8077         case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4uivEXT:
8078         {
8079             GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8080             GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8081
8082             GL_ENTRYPOINT(glNamedProgramLocalParameterI4uivEXT)(replay_program, trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLuint>(2), trace_packet.get_param_client_memory<GLuint>(3));
8083             break;
8084         }
8085         case VOGL_ENTRYPOINT_glNamedProgramLocalParametersI4uivEXT:
8086         {
8087             GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8088             GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8089
8090             GL_ENTRYPOINT(glNamedProgramLocalParametersI4uivEXT)(replay_program, trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLuint>(2), trace_packet.get_param_value<GLsizei>(3), trace_packet.get_param_client_memory<GLuint>(4));
8091             break;
8092         }
8093         case VOGL_ENTRYPOINT_glNamedProgramLocalParameter4fvEXT:
8094         {
8095             GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8096             GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8097
8098             GL_ENTRYPOINT(glNamedProgramLocalParameter4fvEXT)(replay_program, trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLuint>(2), trace_packet.get_param_client_memory<const GLfloat>(3));
8099             break;
8100         }
8101         case VOGL_ENTRYPOINT_glGetTexEnvfv:
8102         {
8103             if (!benchmark_mode())
8104             {
8105                 GLenum target = trace_packet.get_param_value<GLenum>(0);
8106                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8107                 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8108
8109                 GLfloat vals[4] = { 0, 0, 0, 0 };
8110
8111                 int n = g_gl_enums.get_pname_count(pname);
8112                 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8113
8114                 GL_ENTRYPOINT(glGetTexEnvfv)(target, pname, vals);
8115
8116                 if (n < 0)
8117                 {
8118                     process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8119                 }
8120                 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8121                 {
8122                     process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8123                 }
8124             }
8125
8126             break;
8127         }
8128         case VOGL_ENTRYPOINT_glGetTexEnviv:
8129         {
8130             if (!benchmark_mode())
8131             {
8132                 GLenum target = trace_packet.get_param_value<GLenum>(0);
8133                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8134                 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8135
8136                 GLint vals[4] = { 0, 0, 0, 0 };
8137
8138                 int n = g_gl_enums.get_pname_count(pname);
8139                 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8140
8141                 GL_ENTRYPOINT(glGetTexEnviv)(target, pname, vals);
8142
8143                 if (n < 0)
8144                 {
8145                     process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8146                 }
8147                 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8148                 {
8149                     process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8150                 }
8151             }
8152
8153             break;
8154         }
8155         case VOGL_ENTRYPOINT_glGetTexGendv:
8156         {
8157             if (!benchmark_mode())
8158             {
8159                 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8160                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8161                 const GLdouble *pParams = trace_packet.get_param_client_memory<GLdouble>(2);
8162
8163                 GLdouble vals[4] = { 0, 0, 0, 0 };
8164
8165                 int n = g_gl_enums.get_pname_count(pname);
8166                 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8167
8168                 GL_ENTRYPOINT(glGetTexGendv)(coord, pname, vals);
8169
8170                 if (n < 0)
8171                 {
8172                     process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8173                 }
8174                 else if (memcmp(pParams, vals, n * sizeof(GLdouble)) != 0)
8175                 {
8176                     process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8177                 }
8178             }
8179
8180             break;
8181         }
8182         case VOGL_ENTRYPOINT_glGetTexGenfv:
8183         {
8184             if (!benchmark_mode())
8185             {
8186                 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8187                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8188                 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8189
8190                 GLfloat vals[4] = { 0, 0, 0, 0 };
8191
8192                 int n = g_gl_enums.get_pname_count(pname);
8193                 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8194
8195                 GL_ENTRYPOINT(glGetTexGenfv)(coord, pname, vals);
8196
8197                 if (n < 0)
8198                 {
8199                     process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8200                 }
8201                 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8202                 {
8203                     process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8204                 }
8205             }
8206
8207             break;
8208         }
8209         case VOGL_ENTRYPOINT_glGetTexGeniv:
8210         {
8211             if (!benchmark_mode())
8212             {
8213                 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8214                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8215                 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8216
8217                 GLint vals[4] = { 0, 0, 0, 0 };
8218
8219                 int n = g_gl_enums.get_pname_count(pname);
8220                 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8221
8222                 GL_ENTRYPOINT(glGetTexGeniv)(coord, pname, vals);
8223
8224                 if (n < 0)
8225                 {
8226                     process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8227                 }
8228                 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8229                 {
8230                     process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8231                 }
8232             }
8233
8234             break;
8235         }
8236         case VOGL_ENTRYPOINT_glGetLightfv:
8237         {
8238             if (!benchmark_mode())
8239             {
8240                 GLenum light = trace_packet.get_param_value<GLenum>(0);
8241                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8242                 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8243
8244                 GLfloat vals[4] = { 0, 0, 0, 0 };
8245
8246                 int n = g_gl_enums.get_pname_count(pname);
8247                 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8248
8249                 GL_ENTRYPOINT(glGetLightfv)(light, pname, vals);
8250
8251                 if (n < 0)
8252                 {
8253                     process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8254                 }
8255                 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8256                 {
8257                     process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8258                 }
8259             }
8260
8261             break;
8262         }
8263         case VOGL_ENTRYPOINT_glGetLightiv:
8264         {
8265             if (!benchmark_mode())
8266             {
8267                 GLenum light = trace_packet.get_param_value<GLenum>(0);
8268                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8269                 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8270
8271                 GLint vals[4] = { 0, 0, 0, 0 };
8272
8273                 int n = g_gl_enums.get_pname_count(pname);
8274                 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8275
8276                 GL_ENTRYPOINT(glGetLightiv)(light, pname, vals);
8277
8278                 if (n < 0)
8279                 {
8280                     process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8281                 }
8282                 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8283                 {
8284                     process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8285                 }
8286             }
8287
8288             break;
8289         }
8290         case VOGL_ENTRYPOINT_glSelectBuffer:
8291         {
8292             GLsizei size = trace_packet.get_param_value<GLsizei>(0);
8293
8294             if (m_pCur_context_state->m_select_buffer.try_resize(size))
8295             {
8296                 GL_ENTRYPOINT(glSelectBuffer)(size, m_pCur_context_state->m_select_buffer.get_ptr());
8297             }
8298             else
8299             {
8300                 process_entrypoint_error("%s: Failed resizing context's select buffer\n", VOGL_METHOD_NAME);
8301             }
8302
8303             break;
8304         }
8305         case VOGL_ENTRYPOINT_glClearBufferfv:
8306         {
8307             VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferfv;
8308
8309             // TODO: Check params
8310
8311             VOGL_REPLAY_CALL_GL_HELPER_glClearBufferfv;
8312
8313             break;
8314         }
8315         case VOGL_ENTRYPOINT_glClearBufferiv:
8316         {
8317             VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferiv;
8318
8319             // TODO: Check params
8320
8321             VOGL_REPLAY_CALL_GL_HELPER_glClearBufferiv;
8322
8323             break;
8324         }
8325         case VOGL_ENTRYPOINT_glClearBufferuiv:
8326         {
8327             VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferuiv;
8328
8329             // TODO: Check params
8330
8331             VOGL_REPLAY_CALL_GL_HELPER_glClearBufferuiv;
8332
8333             break;
8334         }
8335         case VOGL_ENTRYPOINT_glTexBuffer:
8336         case VOGL_ENTRYPOINT_glTexBufferARB:
8337         case VOGL_ENTRYPOINT_glTexBufferEXT:
8338         {
8339             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexBuffer;
8340
8341             buffer = map_handle(get_shared_state()->m_buffers, buffer);
8342
8343             SWITCH_GL_ENTRYPOINT3_VOID(glTexBuffer, glTexBufferARB, glTexBufferEXT, target, internalformat, buffer);
8344             break;
8345         }
8346         case VOGL_ENTRYPOINT_glBeginConditionalRender:
8347         {
8348             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBeginConditionalRender;
8349
8350             id = map_handle(get_shared_state()->m_queries, id);
8351
8352             VOGL_REPLAY_CALL_GL_HELPER_glBeginConditionalRender;
8353             break;
8354         }
8355         case VOGL_ENTRYPOINT_glEndConditionalRender:
8356         {
8357             VOGL_REPLAY_LOAD_PARAMS_HELPER_glEndConditionalRender;
8358
8359             VOGL_REPLAY_CALL_GL_HELPER_glEndConditionalRender;
8360             break;
8361         }
8362         case VOGL_ENTRYPOINT_glBeginTransformFeedback:
8363         {
8364             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBeginTransformFeedback;
8365
8366             VOGL_REPLAY_CALL_GL_HELPER_glBeginTransformFeedback;
8367             break;
8368         }
8369         case VOGL_ENTRYPOINT_glEndTransformFeedback:
8370         {
8371             VOGL_REPLAY_LOAD_PARAMS_HELPER_glEndTransformFeedback;
8372
8373             VOGL_REPLAY_CALL_GL_HELPER_glEndTransformFeedback;
8374
8375             break;
8376         }
8377         case VOGL_ENTRYPOINT_glTransformFeedbackVaryings:
8378         {
8379             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTransformFeedbackVaryings;
8380             VOGL_NOTE_UNUSED(pTrace_varyings);
8381
8382             program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8383
8384             dynamic_string_array replay_varyings(count);
8385
8386             const key_value_map &key_value_map = trace_packet.get_key_value_map();
8387             const value_to_value_hash_map &hash_map = key_value_map.get_map();
8388
8389             for (value_to_value_hash_map::const_iterator it = hash_map.begin(); it != hash_map.end(); ++it)
8390             {
8391                 int key_index = it->first.get_int();
8392
8393                 if ((key_index >= 0) && (key_index < count))
8394                 {
8395                     const dynamic_string *pName = it->second.get_string_ptr();
8396                     VOGL_ASSERT(pName);
8397
8398                     replay_varyings[key_index] = pName ? *pName : "";
8399                 }
8400                 else
8401                 {
8402                     VOGL_ASSERT_ALWAYS;
8403                 }
8404             }
8405
8406             vogl::vector<const GLchar *> str_ptrs(count);
8407             for (int i = 0; i < count; i++)
8408                 str_ptrs[i] = reinterpret_cast<const GLchar *>(replay_varyings[i].get_ptr());
8409
8410             GLchar *const *pReplay_varyings = (GLchar *const *)(str_ptrs.get_ptr());
8411
8412             VOGL_REPLAY_CALL_GL_HELPER_glTransformFeedbackVaryings;
8413
8414             break;
8415         }
8416         case VOGL_ENTRYPOINT_glUniformBufferEXT:
8417         {
8418             VOGL_REPLAY_LOAD_PARAMS_HELPER_glUniformBufferEXT;
8419
8420             GLuint trace_program = program;
8421
8422             program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8423             location = determine_uniform_replay_location(trace_program, location);
8424             buffer = map_handle(get_shared_state()->m_buffers, buffer);
8425
8426             VOGL_REPLAY_CALL_GL_HELPER_glUniformBufferEXT;
8427             break;
8428         }
8429         case VOGL_ENTRYPOINT_glUniformBlockBinding:
8430         {
8431             // TODO: Does any of this other stuff need to be remapped?
8432             VOGL_REPLAY_LOAD_PARAMS_HELPER_glUniformBlockBinding;
8433
8434             program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8435
8436             VOGL_REPLAY_CALL_GL_HELPER_glUniformBlockBinding;
8437             break;
8438         }
8439         case VOGL_ENTRYPOINT_glFrameTerminatorGREMEDY:
8440         {
8441             // TODO - we need to hook up this extension to the tracer
8442             break;
8443         }
8444         case VOGL_ENTRYPOINT_glStringMarkerGREMEDY:
8445         {
8446             // TODO - we need to hook up this extension to the tracer
8447             break;
8448         }
8449         case VOGL_ENTRYPOINT_glDebugMessageCallbackARB:
8450         case VOGL_ENTRYPOINT_glGetDebugMessageLogARB:
8451         case VOGL_ENTRYPOINT_glDebugMessageControlARB:
8452         case VOGL_ENTRYPOINT_glDebugMessageInsertARB:
8453         {
8454             // TODO
8455             break;
8456         }
8457         case VOGL_ENTRYPOINT_glBitmap:
8458         {
8459             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBitmap;
8460
8461             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8462             {
8463                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8464                 pTrace_bitmap = (const GLubyte *)ptr_val;
8465             }
8466
8467             VOGL_REPLAY_CALL_GL_HELPER_glBitmap;
8468
8469             break;
8470         }
8471         case VOGL_ENTRYPOINT_glColorSubTable:
8472         {
8473             VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorSubTable;
8474
8475             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8476             {
8477                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8478                 pTrace_data = (const GLvoid *)ptr_val;
8479             }
8480
8481             VOGL_REPLAY_CALL_GL_HELPER_glColorSubTable;
8482
8483             break;
8484         }
8485         case VOGL_ENTRYPOINT_glColorSubTableEXT:
8486         {
8487             VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorSubTableEXT;
8488
8489             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8490             {
8491                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8492                 pTrace_data = (const GLvoid *)ptr_val;
8493             }
8494
8495             VOGL_REPLAY_CALL_GL_HELPER_glColorSubTableEXT;
8496
8497             break;
8498         }
8499         case VOGL_ENTRYPOINT_glColorTable:
8500         {
8501             VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorTable;
8502
8503             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8504             {
8505                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8506                 pTrace_table = (const GLvoid *)ptr_val;
8507             }
8508
8509             VOGL_REPLAY_CALL_GL_HELPER_glColorTable;
8510
8511             break;
8512         }
8513         case VOGL_ENTRYPOINT_glColorTableEXT:
8514         {
8515             VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorTableEXT;
8516
8517             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8518             {
8519                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8520                 pTrace_table = (const GLvoid *)ptr_val;
8521             }
8522
8523             VOGL_REPLAY_CALL_GL_HELPER_glColorTableEXT;
8524
8525             break;
8526         }
8527         case VOGL_ENTRYPOINT_glConvolutionFilter1D:
8528         {
8529             VOGL_REPLAY_LOAD_PARAMS_HELPER_glConvolutionFilter1D;
8530
8531             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8532             {
8533                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8534                 pTrace_image = (const GLvoid *)ptr_val;
8535             }
8536
8537             VOGL_REPLAY_CALL_GL_HELPER_glConvolutionFilter1D;
8538
8539             break;
8540         }
8541         case VOGL_ENTRYPOINT_glConvolutionFilter2D:
8542         {
8543             VOGL_REPLAY_LOAD_PARAMS_HELPER_glConvolutionFilter2D;
8544
8545             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8546             {
8547                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8548                 pTrace_image = (const GLvoid *)ptr_val;
8549             }
8550
8551             VOGL_REPLAY_CALL_GL_HELPER_glConvolutionFilter2D;
8552
8553             break;
8554         }
8555         case VOGL_ENTRYPOINT_glDrawPixels:
8556         {
8557             VOGL_REPLAY_LOAD_PARAMS_HELPER_glDrawPixels;
8558
8559             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8560             {
8561                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(4);
8562                 pTrace_pixels = (const GLvoid *)ptr_val;
8563             }
8564
8565             VOGL_REPLAY_CALL_GL_HELPER_glDrawPixels;
8566
8567             break;
8568         }
8569         case VOGL_ENTRYPOINT_glPolygonStipple:
8570         {
8571             VOGL_REPLAY_LOAD_PARAMS_HELPER_glPolygonStipple;
8572
8573             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8574             {
8575                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(0);
8576                 pTrace_mask = (const GLubyte *)ptr_val;
8577             }
8578
8579             VOGL_REPLAY_CALL_GL_HELPER_glPolygonStipple;
8580
8581             break;
8582         }
8583         case VOGL_ENTRYPOINT_glTexImage1D:
8584         {
8585             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage1D;
8586
8587             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8588             {
8589                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(7);
8590                 pTrace_pixels = (const GLvoid *)ptr_val;
8591             }
8592
8593             VOGL_REPLAY_CALL_GL_HELPER_glTexImage1D;
8594
8595             break;
8596         }
8597         case VOGL_ENTRYPOINT_glTexImage2D:
8598         {
8599             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage2D;
8600
8601             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8602             {
8603                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(8);
8604                 pTrace_pixels = (const GLvoid *)ptr_val;
8605             }
8606
8607             VOGL_REPLAY_CALL_GL_HELPER_glTexImage2D;
8608
8609             break;
8610         }
8611         case VOGL_ENTRYPOINT_glTexImage3D:
8612         {
8613             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage3D;
8614
8615             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8616             {
8617                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(9);
8618                 pTrace_pixels = (const GLvoid *)ptr_val;
8619             }
8620
8621             VOGL_REPLAY_CALL_GL_HELPER_glTexImage3D;
8622
8623             break;
8624         }
8625         case VOGL_ENTRYPOINT_glTexImage3DEXT:
8626         {
8627             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage3DEXT;
8628
8629             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8630             {
8631                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(9);
8632                 pTrace_pixels = (const GLvoid *)ptr_val;
8633             }
8634
8635             VOGL_REPLAY_CALL_GL_HELPER_glTexImage3DEXT;
8636
8637             break;
8638         }
8639         case VOGL_ENTRYPOINT_glTexSubImage1D:
8640         {
8641             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage1D;
8642
8643             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8644             {
8645                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8646                 pTrace_pixels = (const GLvoid *)ptr_val;
8647             }
8648
8649             VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage1D;
8650
8651             break;
8652         }
8653         case VOGL_ENTRYPOINT_glTexSubImage1DEXT:
8654         {
8655             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage1DEXT;
8656
8657             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8658             {
8659                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8660                 pTrace_pixels = (const GLvoid *)ptr_val;
8661             }
8662
8663             VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage1DEXT;
8664
8665             break;
8666         }
8667         case VOGL_ENTRYPOINT_glTexSubImage2D:
8668         {
8669             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage2D;
8670
8671             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8672             {
8673                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(8);
8674                 pTrace_pixels = (const GLvoid *)ptr_val;
8675             }
8676
8677             VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage2D;
8678
8679             break;
8680         }
8681         case VOGL_ENTRYPOINT_glTexSubImage2DEXT:
8682         {
8683             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage2DEXT;
8684
8685             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8686             {
8687                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(8);
8688                 pTrace_pixels = (const GLvoid *)ptr_val;
8689             }
8690
8691             VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage2DEXT;
8692
8693             break;
8694         }
8695         case VOGL_ENTRYPOINT_glTexSubImage3D:
8696         {
8697             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage3D;
8698
8699             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8700             {
8701                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(10);
8702                 pTrace_pixels = (const GLvoid *)ptr_val;
8703             }
8704
8705             VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage3D;
8706
8707             break;
8708         }
8709         case VOGL_ENTRYPOINT_glTexSubImage3DEXT:
8710         {
8711             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage3DEXT;
8712
8713             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8714             {
8715                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(10);
8716                 pTrace_pixels = (const GLvoid *)ptr_val;
8717             }
8718
8719             VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage3DEXT;
8720
8721             break;
8722         }
8723         case VOGL_ENTRYPOINT_glAreTexturesResident:
8724         case VOGL_ENTRYPOINT_glAreTexturesResidentEXT:
8725         case VOGL_ENTRYPOINT_glGetActiveAtomicCounterBufferiv:
8726         case VOGL_ENTRYPOINT_glGetActiveAttribARB:
8727         case VOGL_ENTRYPOINT_glGetActiveSubroutineName:
8728         case VOGL_ENTRYPOINT_glGetActiveSubroutineUniformName:
8729         case VOGL_ENTRYPOINT_glGetActiveSubroutineUniformiv:
8730         case VOGL_ENTRYPOINT_glGetActiveUniformARB:
8731         case VOGL_ENTRYPOINT_glGetActiveUniformBlockName:
8732         case VOGL_ENTRYPOINT_glGetActiveUniformBlockiv:
8733         case VOGL_ENTRYPOINT_glGetActiveUniformName:
8734         case VOGL_ENTRYPOINT_glGetActiveUniformsiv:
8735         case VOGL_ENTRYPOINT_glGetActiveVaryingNV:
8736         case VOGL_ENTRYPOINT_glGetArrayObjectfvATI:
8737         case VOGL_ENTRYPOINT_glGetArrayObjectivATI:
8738         case VOGL_ENTRYPOINT_glGetAttachedObjectsARB:
8739         case VOGL_ENTRYPOINT_glGetAttribLocationARB:
8740         case VOGL_ENTRYPOINT_glGetBooleanIndexedvEXT:
8741         case VOGL_ENTRYPOINT_glGetBooleani_v:
8742         case VOGL_ENTRYPOINT_glGetBufferParameteri64v:
8743         case VOGL_ENTRYPOINT_glGetBufferParameterivARB:
8744         case VOGL_ENTRYPOINT_glGetBufferParameterui64vNV:
8745         case VOGL_ENTRYPOINT_glGetBufferPointervARB:
8746         case VOGL_ENTRYPOINT_glGetBufferSubDataARB:
8747         case VOGL_ENTRYPOINT_glGetClipPlanefOES:
8748         case VOGL_ENTRYPOINT_glGetClipPlanexOES:
8749         case VOGL_ENTRYPOINT_glGetColorTable:
8750         case VOGL_ENTRYPOINT_glGetColorTableEXT:
8751         case VOGL_ENTRYPOINT_glGetColorTableParameterfv:
8752         case VOGL_ENTRYPOINT_glGetColorTableParameterfvEXT:
8753         case VOGL_ENTRYPOINT_glGetColorTableParameterfvSGI:
8754         case VOGL_ENTRYPOINT_glGetColorTableParameteriv:
8755         case VOGL_ENTRYPOINT_glGetColorTableParameterivEXT:
8756         case VOGL_ENTRYPOINT_glGetColorTableParameterivSGI:
8757         case VOGL_ENTRYPOINT_glGetColorTableSGI:
8758         case VOGL_ENTRYPOINT_glGetCombinerInputParameterfvNV:
8759         case VOGL_ENTRYPOINT_glGetCombinerInputParameterivNV:
8760         case VOGL_ENTRYPOINT_glGetCombinerOutputParameterfvNV:
8761         case VOGL_ENTRYPOINT_glGetCombinerOutputParameterivNV:
8762         case VOGL_ENTRYPOINT_glGetCombinerStageParameterfvNV:
8763         case VOGL_ENTRYPOINT_glGetCompressedMultiTexImageEXT:
8764         case VOGL_ENTRYPOINT_glGetCompressedTexImage:
8765         case VOGL_ENTRYPOINT_glGetCompressedTexImageARB:
8766         case VOGL_ENTRYPOINT_glGetCompressedTextureImageEXT:
8767         case VOGL_ENTRYPOINT_glGetConvolutionFilter:
8768         case VOGL_ENTRYPOINT_glGetConvolutionFilterEXT:
8769         case VOGL_ENTRYPOINT_glGetConvolutionParameterfv:
8770         case VOGL_ENTRYPOINT_glGetConvolutionParameterfvEXT:
8771         case VOGL_ENTRYPOINT_glGetConvolutionParameteriv:
8772         case VOGL_ENTRYPOINT_glGetConvolutionParameterivEXT:
8773         case VOGL_ENTRYPOINT_glGetConvolutionParameterxvOES:
8774         case VOGL_ENTRYPOINT_glGetDebugMessageLog:
8775         case VOGL_ENTRYPOINT_glGetDebugMessageLogAMD:
8776         case VOGL_ENTRYPOINT_glGetDetailTexFuncSGIS:
8777         case VOGL_ENTRYPOINT_glGetDoubleIndexedvEXT:
8778         case VOGL_ENTRYPOINT_glGetDoublei_v:
8779         case VOGL_ENTRYPOINT_glGetFenceivNV:
8780         case VOGL_ENTRYPOINT_glGetFinalCombinerInputParameterfvNV:
8781         case VOGL_ENTRYPOINT_glGetFinalCombinerInputParameterivNV:
8782         case VOGL_ENTRYPOINT_glGetFixedvOES:
8783         case VOGL_ENTRYPOINT_glGetFloatIndexedvEXT:
8784         case VOGL_ENTRYPOINT_glGetFloati_v:
8785         case VOGL_ENTRYPOINT_glGetFogFuncSGIS:
8786         case VOGL_ENTRYPOINT_glGetFragDataIndex:
8787         case VOGL_ENTRYPOINT_glGetFragDataLocation:
8788         case VOGL_ENTRYPOINT_glGetFragDataLocationEXT:
8789         case VOGL_ENTRYPOINT_glGetFragmentLightfvSGIX:
8790         case VOGL_ENTRYPOINT_glGetFragmentLightivSGIX:
8791         case VOGL_ENTRYPOINT_glGetFragmentMaterialfvSGIX:
8792         case VOGL_ENTRYPOINT_glGetFragmentMaterialivSGIX:
8793         case VOGL_ENTRYPOINT_glGetFramebufferAttachmentParameteriv:
8794         case VOGL_ENTRYPOINT_glGetFramebufferAttachmentParameterivEXT:
8795         case VOGL_ENTRYPOINT_glGetFramebufferParameteriv:
8796         case VOGL_ENTRYPOINT_glGetFramebufferParameterivEXT:
8797         case VOGL_ENTRYPOINT_glGetGraphicsResetStatusARB:
8798         case VOGL_ENTRYPOINT_glGetHandleARB:
8799         case VOGL_ENTRYPOINT_glGetHistogram:
8800         case VOGL_ENTRYPOINT_glGetHistogramEXT:
8801         case VOGL_ENTRYPOINT_glGetHistogramParameterfv:
8802         case VOGL_ENTRYPOINT_glGetHistogramParameterfvEXT:
8803         case VOGL_ENTRYPOINT_glGetHistogramParameteriv:
8804         case VOGL_ENTRYPOINT_glGetHistogramParameterivEXT:
8805         case VOGL_ENTRYPOINT_glGetHistogramParameterxvOES:
8806         case VOGL_ENTRYPOINT_glGetImageHandleNV:
8807         case VOGL_ENTRYPOINT_glGetImageTransformParameterfvHP:
8808         case VOGL_ENTRYPOINT_glGetImageTransformParameterivHP:
8809         case VOGL_ENTRYPOINT_glGetInstrumentsSGIX:
8810         case VOGL_ENTRYPOINT_glGetInteger64i_v:
8811         case VOGL_ENTRYPOINT_glGetInteger64v:
8812         case VOGL_ENTRYPOINT_glGetIntegerIndexedvEXT:
8813         case VOGL_ENTRYPOINT_glGetIntegeri_v:
8814         case VOGL_ENTRYPOINT_glGetIntegerui64i_vNV:
8815         case VOGL_ENTRYPOINT_glGetIntegerui64vNV:
8816         case VOGL_ENTRYPOINT_glGetInternalformati64v:
8817         case VOGL_ENTRYPOINT_glGetInternalformativ:
8818         case VOGL_ENTRYPOINT_glGetInvariantBooleanvEXT:
8819         case VOGL_ENTRYPOINT_glGetInvariantFloatvEXT:
8820         case VOGL_ENTRYPOINT_glGetInvariantIntegervEXT:
8821         case VOGL_ENTRYPOINT_glGetLightxOES:
8822         case VOGL_ENTRYPOINT_glGetListParameterfvSGIX:
8823         case VOGL_ENTRYPOINT_glGetListParameterivSGIX:
8824         case VOGL_ENTRYPOINT_glGetLocalConstantBooleanvEXT:
8825         case VOGL_ENTRYPOINT_glGetLocalConstantFloatvEXT:
8826         case VOGL_ENTRYPOINT_glGetLocalConstantIntegervEXT:
8827         case VOGL_ENTRYPOINT_glGetMapAttribParameterfvNV:
8828         case VOGL_ENTRYPOINT_glGetMapAttribParameterivNV:
8829         case VOGL_ENTRYPOINT_glGetMapControlPointsNV:
8830         case VOGL_ENTRYPOINT_glGetMapParameterfvNV:
8831         case VOGL_ENTRYPOINT_glGetMapParameterivNV:
8832         case VOGL_ENTRYPOINT_glGetMapdv:
8833         case VOGL_ENTRYPOINT_glGetMapfv:
8834         case VOGL_ENTRYPOINT_glGetMapiv:
8835         case VOGL_ENTRYPOINT_glGetMapxvOES:
8836         case VOGL_ENTRYPOINT_glGetMaterialfv:
8837         case VOGL_ENTRYPOINT_glGetMaterialiv:
8838         case VOGL_ENTRYPOINT_glGetMaterialxOES:
8839         case VOGL_ENTRYPOINT_glGetMinmax:
8840         case VOGL_ENTRYPOINT_glGetMinmaxEXT:
8841         case VOGL_ENTRYPOINT_glGetMinmaxParameterfv:
8842         case VOGL_ENTRYPOINT_glGetMinmaxParameterfvEXT:
8843         case VOGL_ENTRYPOINT_glGetMinmaxParameteriv:
8844         case VOGL_ENTRYPOINT_glGetMinmaxParameterivEXT:
8845         case VOGL_ENTRYPOINT_glGetMultiTexEnvfvEXT:
8846         case VOGL_ENTRYPOINT_glGetMultiTexEnvivEXT:
8847         case VOGL_ENTRYPOINT_glGetMultiTexGendvEXT:
8848         case VOGL_ENTRYPOINT_glGetMultiTexGenfvEXT:
8849         case VOGL_ENTRYPOINT_glGetMultiTexGenivEXT:
8850         case VOGL_ENTRYPOINT_glGetMultiTexImageEXT:
8851         case VOGL_ENTRYPOINT_glGetMultiTexLevelParameterfvEXT:
8852         case VOGL_ENTRYPOINT_glGetMultiTexLevelParameterivEXT:
8853         case VOGL_ENTRYPOINT_glGetMultiTexParameterIivEXT:
8854         case VOGL_ENTRYPOINT_glGetMultiTexParameterIuivEXT:
8855         case VOGL_ENTRYPOINT_glGetMultiTexParameterfvEXT:
8856         case VOGL_ENTRYPOINT_glGetMultiTexParameterivEXT:
8857         case VOGL_ENTRYPOINT_glGetMultisamplefv:
8858         case VOGL_ENTRYPOINT_glGetMultisamplefvNV:
8859         case VOGL_ENTRYPOINT_glGetNamedBufferParameterivEXT:
8860         case VOGL_ENTRYPOINT_glGetNamedBufferParameterui64vNV:
8861         case VOGL_ENTRYPOINT_glGetNamedBufferPointervEXT:
8862         case VOGL_ENTRYPOINT_glGetNamedBufferSubDataEXT:
8863         case VOGL_ENTRYPOINT_glGetNamedFramebufferAttachmentParameterivEXT:
8864         case VOGL_ENTRYPOINT_glGetNamedFramebufferParameterivEXT:
8865         case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterIivEXT:
8866         case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterIuivEXT:
8867         case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterdvEXT:
8868         case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterfvEXT:
8869         case VOGL_ENTRYPOINT_glGetNamedProgramStringEXT:
8870         case VOGL_ENTRYPOINT_glGetNamedProgramivEXT:
8871         case VOGL_ENTRYPOINT_glGetNamedRenderbufferParameterivEXT:
8872         case VOGL_ENTRYPOINT_glGetNamedStringARB:
8873         case VOGL_ENTRYPOINT_glGetNamedStringivARB:
8874         case VOGL_ENTRYPOINT_glGetObjectBufferfvATI:
8875         case VOGL_ENTRYPOINT_glGetObjectBufferivATI:
8876         case VOGL_ENTRYPOINT_glGetObjectLabel:
8877         case VOGL_ENTRYPOINT_glGetObjectParameterfvARB:
8878         case VOGL_ENTRYPOINT_glGetObjectParameterivAPPLE:
8879         case VOGL_ENTRYPOINT_glGetObjectPtrLabel:
8880         case VOGL_ENTRYPOINT_glGetOcclusionQueryivNV:
8881         case VOGL_ENTRYPOINT_glGetOcclusionQueryuivNV:
8882         case VOGL_ENTRYPOINT_glGetPathColorGenfvNV:
8883         case VOGL_ENTRYPOINT_glGetPathColorGenivNV:
8884         case VOGL_ENTRYPOINT_glGetPathCommandsNV:
8885         case VOGL_ENTRYPOINT_glGetPathCoordsNV:
8886         case VOGL_ENTRYPOINT_glGetPathDashArrayNV:
8887         case VOGL_ENTRYPOINT_glGetPathLengthNV:
8888         case VOGL_ENTRYPOINT_glGetPathMetricRangeNV:
8889         case VOGL_ENTRYPOINT_glGetPathMetricsNV:
8890         case VOGL_ENTRYPOINT_glGetPathParameterfvNV:
8891         case VOGL_ENTRYPOINT_glGetPathParameterivNV:
8892         case VOGL_ENTRYPOINT_glGetPathSpacingNV:
8893         case VOGL_ENTRYPOINT_glGetPathTexGenfvNV:
8894         case VOGL_ENTRYPOINT_glGetPathTexGenivNV:
8895         case VOGL_ENTRYPOINT_glGetPerfMonitorCounterDataAMD:
8896         case VOGL_ENTRYPOINT_glGetPerfMonitorCounterInfoAMD:
8897         case VOGL_ENTRYPOINT_glGetPerfMonitorCounterStringAMD:
8898         case VOGL_ENTRYPOINT_glGetPerfMonitorCountersAMD:
8899         case VOGL_ENTRYPOINT_glGetPerfMonitorGroupStringAMD:
8900         case VOGL_ENTRYPOINT_glGetPerfMonitorGroupsAMD:
8901         case VOGL_ENTRYPOINT_glGetPixelMapfv:
8902         case VOGL_ENTRYPOINT_glGetPixelMapuiv:
8903         case VOGL_ENTRYPOINT_glGetPixelMapusv:
8904         case VOGL_ENTRYPOINT_glGetPixelMapxv:
8905         case VOGL_ENTRYPOINT_glGetPixelTexGenParameterfvSGIS:
8906         case VOGL_ENTRYPOINT_glGetPixelTexGenParameterivSGIS:
8907         case VOGL_ENTRYPOINT_glGetPixelTransformParameterfvEXT:
8908         case VOGL_ENTRYPOINT_glGetPixelTransformParameterivEXT:
8909         case VOGL_ENTRYPOINT_glGetPointerIndexedvEXT:
8910         case VOGL_ENTRYPOINT_glGetPointervEXT:
8911         case VOGL_ENTRYPOINT_glGetPolygonStipple:
8912         case VOGL_ENTRYPOINT_glGetProgramBinary:
8913         case VOGL_ENTRYPOINT_glGetProgramEnvParameterIivNV:
8914         case VOGL_ENTRYPOINT_glGetProgramEnvParameterIuivNV:
8915         case VOGL_ENTRYPOINT_glGetProgramEnvParameterdvARB:
8916         case VOGL_ENTRYPOINT_glGetProgramEnvParameterfvARB:
8917         case VOGL_ENTRYPOINT_glGetProgramInterfaceiv:
8918         case VOGL_ENTRYPOINT_glGetProgramLocalParameterIivNV:
8919         case VOGL_ENTRYPOINT_glGetProgramLocalParameterIuivNV:
8920         case VOGL_ENTRYPOINT_glGetProgramLocalParameterdvARB:
8921         case VOGL_ENTRYPOINT_glGetProgramLocalParameterfvARB:
8922         case VOGL_ENTRYPOINT_glGetProgramNamedParameterdvNV:
8923         case VOGL_ENTRYPOINT_glGetProgramNamedParameterfvNV:
8924         case VOGL_ENTRYPOINT_glGetProgramParameterdvNV:
8925         case VOGL_ENTRYPOINT_glGetProgramParameterfvNV:
8926         case VOGL_ENTRYPOINT_glGetProgramPipelineInfoLog:
8927         case VOGL_ENTRYPOINT_glGetProgramPipelineiv:
8928         case VOGL_ENTRYPOINT_glGetProgramResourceIndex:
8929         case VOGL_ENTRYPOINT_glGetProgramResourceLocation:
8930         case VOGL_ENTRYPOINT_glGetProgramResourceLocationIndex:
8931         case VOGL_ENTRYPOINT_glGetProgramResourceName:
8932         case VOGL_ENTRYPOINT_glGetProgramResourceiv:
8933         case VOGL_ENTRYPOINT_glGetProgramStageiv:
8934         case VOGL_ENTRYPOINT_glGetProgramStringARB:
8935         case VOGL_ENTRYPOINT_glGetProgramStringNV:
8936         case VOGL_ENTRYPOINT_glGetProgramSubroutineParameteruivNV:
8937         case VOGL_ENTRYPOINT_glGetProgramivNV:
8938         case VOGL_ENTRYPOINT_glGetQueryIndexediv:
8939         case VOGL_ENTRYPOINT_glGetQueryObjecti64vEXT:
8940         case VOGL_ENTRYPOINT_glGetQueryObjectui64vEXT:
8941         case VOGL_ENTRYPOINT_glGetQueryiv:
8942         case VOGL_ENTRYPOINT_glGetQueryivARB:
8943         case VOGL_ENTRYPOINT_glGetSamplerParameterIiv:
8944         case VOGL_ENTRYPOINT_glGetSamplerParameterIuiv:
8945         case VOGL_ENTRYPOINT_glGetSamplerParameterfv:
8946         case VOGL_ENTRYPOINT_glGetSamplerParameteriv:
8947         case VOGL_ENTRYPOINT_glGetSeparableFilter:
8948         case VOGL_ENTRYPOINT_glGetSeparableFilterEXT:
8949         case VOGL_ENTRYPOINT_glGetShaderPrecisionFormat:
8950         case VOGL_ENTRYPOINT_glGetShaderSource:
8951         case VOGL_ENTRYPOINT_glGetShaderSourceARB:
8952         case VOGL_ENTRYPOINT_glGetSharpenTexFuncSGIS:
8953         case VOGL_ENTRYPOINT_glGetSubroutineIndex:
8954         case VOGL_ENTRYPOINT_glGetSubroutineUniformLocation:
8955         case VOGL_ENTRYPOINT_glGetSynciv:
8956         case VOGL_ENTRYPOINT_glGetTexBumpParameterfvATI:
8957         case VOGL_ENTRYPOINT_glGetTexBumpParameterivATI:
8958         case VOGL_ENTRYPOINT_glGetTexEnvxvOES:
8959         case VOGL_ENTRYPOINT_glGetTexFilterFuncSGIS:
8960         case VOGL_ENTRYPOINT_glGetTexGenxvOES:
8961         case VOGL_ENTRYPOINT_glGetTexImage:
8962         case VOGL_ENTRYPOINT_glGetTexLevelParameterxvOES:
8963         case VOGL_ENTRYPOINT_glGetTexParameterIivEXT:
8964         case VOGL_ENTRYPOINT_glGetTexParameterIuivEXT:
8965         case VOGL_ENTRYPOINT_glGetTexParameterPointervAPPLE:
8966         case VOGL_ENTRYPOINT_glGetTexParameterxvOES:
8967         case VOGL_ENTRYPOINT_glGetTextureHandleNV:
8968         case VOGL_ENTRYPOINT_glGetTextureImageEXT:
8969         case VOGL_ENTRYPOINT_glGetTextureLevelParameterfvEXT:
8970         case VOGL_ENTRYPOINT_glGetTextureLevelParameterivEXT:
8971         case VOGL_ENTRYPOINT_glGetTextureParameterIivEXT:
8972         case VOGL_ENTRYPOINT_glGetTextureParameterIuivEXT:
8973         case VOGL_ENTRYPOINT_glGetTextureParameterfvEXT:
8974         case VOGL_ENTRYPOINT_glGetTextureParameterivEXT:
8975         case VOGL_ENTRYPOINT_glGetTextureSamplerHandleNV:
8976         case VOGL_ENTRYPOINT_glGetTrackMatrixivNV:
8977         case VOGL_ENTRYPOINT_glGetTransformFeedbackVarying:
8978         case VOGL_ENTRYPOINT_glGetTransformFeedbackVaryingEXT:
8979         case VOGL_ENTRYPOINT_glGetTransformFeedbackVaryingNV:
8980         case VOGL_ENTRYPOINT_glGetUniformBlockIndex:
8981         case VOGL_ENTRYPOINT_glGetUniformBufferSizeEXT:
8982         case VOGL_ENTRYPOINT_glGetUniformIndices:
8983         case VOGL_ENTRYPOINT_glGetUniformOffsetEXT:
8984         case VOGL_ENTRYPOINT_glGetUniformSubroutineuiv:
8985         case VOGL_ENTRYPOINT_glGetUniformdv:
8986         case VOGL_ENTRYPOINT_glGetUniformfv:
8987         case VOGL_ENTRYPOINT_glGetUniformfvARB:
8988         case VOGL_ENTRYPOINT_glGetUniformi64vNV:
8989         case VOGL_ENTRYPOINT_glGetUniformiv:
8990         case VOGL_ENTRYPOINT_glGetUniformivARB:
8991         case VOGL_ENTRYPOINT_glGetUniformui64vNV:
8992         case VOGL_ENTRYPOINT_glGetUniformuiv:
8993         case VOGL_ENTRYPOINT_glGetUniformuivEXT:
8994         case VOGL_ENTRYPOINT_glGetVariantArrayObjectfvATI:
8995         case VOGL_ENTRYPOINT_glGetVariantArrayObjectivATI:
8996         case VOGL_ENTRYPOINT_glGetVariantBooleanvEXT:
8997         case VOGL_ENTRYPOINT_glGetVariantFloatvEXT:
8998         case VOGL_ENTRYPOINT_glGetVariantIntegervEXT:
8999         case VOGL_ENTRYPOINT_glGetVariantPointervEXT:
9000         case VOGL_ENTRYPOINT_glGetVaryingLocationNV:
9001         case VOGL_ENTRYPOINT_glGetVertexAttribArrayObjectfvATI:
9002         case VOGL_ENTRYPOINT_glGetVertexAttribArrayObjectivATI:
9003         case VOGL_ENTRYPOINT_glGetVertexAttribLdv:
9004         case VOGL_ENTRYPOINT_glGetVertexAttribLdvEXT:
9005         case VOGL_ENTRYPOINT_glGetVertexAttribLi64vNV:
9006         case VOGL_ENTRYPOINT_glGetVertexAttribLui64vNV:
9007         case VOGL_ENTRYPOINT_glGetVertexAttribPointerv:
9008         case VOGL_ENTRYPOINT_glGetVertexAttribPointervARB:
9009         case VOGL_ENTRYPOINT_glGetVertexAttribPointervNV:
9010         case VOGL_ENTRYPOINT_glGetVertexAttribdvARB:
9011         case VOGL_ENTRYPOINT_glGetVertexAttribdvNV:
9012         case VOGL_ENTRYPOINT_glGetVertexAttribfvARB:
9013         case VOGL_ENTRYPOINT_glGetVertexAttribfvNV:
9014         case VOGL_ENTRYPOINT_glGetVertexAttribivARB:
9015         case VOGL_ENTRYPOINT_glGetVertexAttribivNV:
9016         case VOGL_ENTRYPOINT_glGetVideoCaptureStreamdvNV:
9017         case VOGL_ENTRYPOINT_glGetVideoCaptureStreamfvNV:
9018         case VOGL_ENTRYPOINT_glGetVideoCaptureStreamivNV:
9019         case VOGL_ENTRYPOINT_glGetVideoCaptureivNV:
9020         case VOGL_ENTRYPOINT_glGetVideoi64vNV:
9021         case VOGL_ENTRYPOINT_glGetVideoivNV:
9022         case VOGL_ENTRYPOINT_glGetVideoui64vNV:
9023         case VOGL_ENTRYPOINT_glGetVideouivNV:
9024         case VOGL_ENTRYPOINT_glGetnColorTableARB:
9025         case VOGL_ENTRYPOINT_glGetnCompressedTexImageARB:
9026         case VOGL_ENTRYPOINT_glGetnConvolutionFilterARB:
9027         case VOGL_ENTRYPOINT_glGetnHistogramARB:
9028         case VOGL_ENTRYPOINT_glGetnMapdvARB:
9029         case VOGL_ENTRYPOINT_glGetnMapfvARB:
9030         case VOGL_ENTRYPOINT_glGetnMapivARB:
9031         case VOGL_ENTRYPOINT_glGetnMinmaxARB:
9032         case VOGL_ENTRYPOINT_glGetnPixelMapfvARB:
9033         case VOGL_ENTRYPOINT_glGetnPixelMapuivARB:
9034         case VOGL_ENTRYPOINT_glGetnPixelMapusvARB:
9035         case VOGL_ENTRYPOINT_glGetnPolygonStippleARB:
9036         case VOGL_ENTRYPOINT_glGetnSeparableFilterARB:
9037         case VOGL_ENTRYPOINT_glGetnTexImageARB:
9038         case VOGL_ENTRYPOINT_glGetnUniformdvARB:
9039         case VOGL_ENTRYPOINT_glGetnUniformfvARB:
9040         case VOGL_ENTRYPOINT_glGetnUniformivARB:
9041         case VOGL_ENTRYPOINT_glGetnUniformuivARB:
9042         case VOGL_ENTRYPOINT_glIsBufferARB:
9043         case VOGL_ENTRYPOINT_glIsEnabledIndexedEXT:
9044         case VOGL_ENTRYPOINT_glIsQueryARB:
9045         case VOGL_ENTRYPOINT_glIsSync:
9046         case VOGL_ENTRYPOINT_glPrioritizeTextures:
9047         case VOGL_ENTRYPOINT_glPrioritizeTexturesEXT:
9048         {
9049             if (!(g_vogl_entrypoint_descs[entrypoint_id].m_flags & cGLEFPrintedUnimplementedWarning))
9050             {
9051                 process_entrypoint_warning("%s: TODO: Implement glGet() function %s\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[entrypoint_id].m_pName);
9052
9053                 g_vogl_entrypoint_descs[entrypoint_id].m_flags |= cGLEFPrintedUnimplementedWarning;
9054             }
9055             break;
9056         }
9057         default:
9058         {
9059             if (g_vogl_entrypoint_descs[entrypoint_id].m_is_whitelisted)
9060                 process_entrypoint_error("%s: Unhandled GL function %s. This function is marked as whitelisted but was not handled!\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[entrypoint_id].m_pName);
9061             else
9062                 process_entrypoint_error("%s: Unhandled GL function %s. This function needs to be added to the whitelist!\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[entrypoint_id].m_pName);
9063             return cStatusSoftFailure;
9064         }
9065     }
9066
9067     m_last_processed_call_counter = trace_packet.get_call_counter();
9068
9069     if (!m_pCur_context_state->m_inside_gl_begin)
9070     {
9071         if (check_gl_error())
9072             return cStatusGLError;
9073     }
9074
9075     if (vogl_is_draw_entrypoint(entrypoint_id) || vogl_is_clear_entrypoint(entrypoint_id) || (entrypoint_id == VOGL_ENTRYPOINT_glBitmap))
9076     {
9077         if ((status = post_draw_call()) != cStatusOK)
9078             return status;
9079     }
9080
9081     return cStatusOK;
9082 }
9083
9084 //----------------------------------------------------------------------------------------------------------------------
9085 // vogl_gl_replayer::snapshot_backbuffer
9086 //----------------------------------------------------------------------------------------------------------------------
9087 void vogl_gl_replayer::snapshot_backbuffer()
9088 {
9089     VOGL_FUNC_TRACER
9090
9091     if (!m_pCur_context_state)
9092     {
9093         vogl_warning_printf("%s: Can't take snapshot without an active context\n", VOGL_METHOD_NAME);
9094         return;
9095     }
9096
9097     uint recorded_width = m_pWindow->get_width();
9098     uint recorded_height = m_pWindow->get_height();
9099
9100     uint width = 0, height = 0;
9101     m_pWindow->get_actual_dimensions(width, height);
9102
9103     VOGL_ASSERT((recorded_width == width) && (recorded_height == height));
9104     VOGL_NOTE_UNUSED(recorded_width);
9105     VOGL_NOTE_UNUSED(recorded_height);
9106
9107     m_screenshot_buffer.resize(width * height * 3);
9108
9109     bool success = vogl_copy_buffer_to_image(m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size(), width, height, GL_RGB, GL_UNSIGNED_BYTE, false, 0, GL_BACK);
9110     if (!success)
9111     {
9112         process_entrypoint_error("%s: Failed calling glReadPixels() to take screenshot\n", VOGL_METHOD_NAME);
9113     }
9114
9115     if (m_flags & cGLReplayerDumpScreenshots)
9116     {
9117         size_t png_size = 0;
9118         void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(m_screenshot_buffer.get_ptr(), width, height, 3, &png_size, 1, true);
9119
9120         dynamic_string screenshot_filename(cVarArg, "%s_%07u.png", m_screenshot_prefix.get_ptr(), m_total_swaps);
9121         if (!file_utils::write_buf_to_file(screenshot_filename.get_ptr(), pPNG_data, png_size))
9122         {
9123             process_entrypoint_error("Failed writing PNG screenshot to file %s\n", screenshot_filename.get_ptr());
9124         }
9125         else
9126         {
9127             vogl_message_printf("Wrote screenshot to file %s\n", screenshot_filename.get_ptr());
9128         }
9129
9130         mz_free(pPNG_data);
9131     }
9132
9133     if ((m_flags & cGLReplayerDumpBackbufferHashes) || (m_flags & cGLReplayerHashBackbuffer))
9134     {
9135         uint64_t backbuffer_crc64;
9136
9137         if (m_flags & cGLReplayerSumHashing)
9138         {
9139             backbuffer_crc64 = calc_sum64(m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size());
9140         }
9141         else
9142         {
9143             backbuffer_crc64 = calc_crc64(CRC64_INIT, m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size());
9144         }
9145
9146         vogl_printf("Frame %u hash: 0x%016" PRIX64 "\n", m_frame_index, backbuffer_crc64);
9147
9148         if (m_backbuffer_hash_filename.has_content())
9149         {
9150             FILE *pFile = vogl_fopen(m_backbuffer_hash_filename.get_ptr(), "a");
9151             if (!pFile)
9152                 vogl_error_printf("Failed writing to backbuffer hash file %s\n", m_backbuffer_hash_filename.get_ptr());
9153             else
9154             {
9155                 vogl_fprintf(pFile, "0x%016" PRIX64 "\n", cast_val_to_uint64(backbuffer_crc64));
9156                 vogl_fclose(pFile);
9157             }
9158         }
9159     }
9160 }
9161
9162 //----------------------------------------------------------------------------------------------------------------------
9163 // vogl_gl_replayer::is_valid_handle
9164 //----------------------------------------------------------------------------------------------------------------------
9165 bool vogl_gl_replayer::replay_to_trace_handle_remapper::is_valid_handle(vogl_namespace_t handle_namespace, uint64_t replay_handle)
9166 {
9167     VOGL_FUNC_TRACER
9168
9169     if (!replay_handle)
9170         return 0;
9171
9172     uint32 replay_handle32 = static_cast<uint32>(replay_handle);
9173
9174     switch (handle_namespace)
9175     {
9176         case VOGL_NAMESPACE_VERTEX_ARRAYS:
9177         {
9178             VOGL_ASSERT(replay_handle32 == replay_handle);
9179             return (m_replayer.get_context_state()->m_vertex_array_objects.search_table_for_value_get_count(replay_handle32) != 0);
9180         }
9181         case VOGL_NAMESPACE_FRAMEBUFFERS:
9182         {
9183             VOGL_ASSERT(replay_handle32 == replay_handle);
9184             return (m_replayer.get_context_state()->m_framebuffers.search_table_for_value_get_count(replay_handle32) != 0);
9185         }
9186         case VOGL_NAMESPACE_TEXTURES:
9187         {
9188             VOGL_ASSERT(replay_handle32 == replay_handle);
9189             return (m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(replay_handle32) != 0);
9190         }
9191         case VOGL_NAMESPACE_RENDER_BUFFERS:
9192         {
9193             VOGL_ASSERT(replay_handle32 == replay_handle);
9194             return (m_replayer.get_shared_state()->m_shadow_state.m_rbos.contains_inv(replay_handle32) != 0);
9195         }
9196         case VOGL_NAMESPACE_QUERIES:
9197         {
9198             VOGL_ASSERT(replay_handle32 == replay_handle);
9199             return (m_replayer.get_shared_state()->m_queries.search_table_for_value_get_count(replay_handle32) != 0);
9200         }
9201         case VOGL_NAMESPACE_SAMPLERS:
9202         {
9203             VOGL_ASSERT(replay_handle32 == replay_handle);
9204             return (m_replayer.get_shared_state()->m_sampler_objects.search_table_for_value_get_count(replay_handle32) != 0);
9205         }
9206         case VOGL_NAMESPACE_PROGRAMS:
9207         {
9208             VOGL_ASSERT(replay_handle32 == replay_handle);
9209             return m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_PROGRAM_OBJECT;
9210         }
9211         case VOGL_NAMESPACE_SHADERS:
9212         {
9213             VOGL_ASSERT(replay_handle32 == replay_handle);
9214             return m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_SHADER_OBJECT;
9215         }
9216         case VOGL_NAMESPACE_BUFFERS:
9217         {
9218             VOGL_ASSERT(replay_handle32 == replay_handle);
9219             return m_replayer.get_shared_state()->m_buffers.search_table_for_value_get_count(replay_handle32);
9220         }
9221         case VOGL_NAMESPACE_SYNCS:
9222         {
9223             GLsync replay_sync = vogl_handle_to_sync(replay_handle);
9224             return m_replayer.get_shared_state()->m_syncs.search_table_for_value_get_count(replay_sync) != 0;
9225         }
9226         case VOGL_NAMESPACE_PROGRAM_ARB:
9227         {
9228             VOGL_ASSERT(replay_handle32 == replay_handle);
9229             return m_replayer.get_shared_state()->m_arb_programs.search_table_for_value_get_count(replay_handle32) != 0;
9230         }
9231         default:
9232             break;
9233     }
9234
9235     VOGL_VERIFY(0);
9236
9237     return false;
9238 }
9239
9240 //----------------------------------------------------------------------------------------------------------------------
9241 // vogl_gl_replayer::remap_handle
9242 //----------------------------------------------------------------------------------------------------------------------
9243 uint64_t vogl_gl_replayer::replay_to_trace_handle_remapper::remap_handle(vogl_namespace_t handle_namespace, uint64_t replay_handle)
9244 {
9245     VOGL_FUNC_TRACER
9246
9247     if (!replay_handle)
9248         return 0;
9249
9250     uint32 replay_handle32 = static_cast<uint32>(replay_handle);
9251
9252     switch (handle_namespace)
9253     {
9254         case VOGL_NAMESPACE_VERTEX_ARRAYS:
9255         {
9256             VOGL_ASSERT(replay_handle32 == replay_handle);
9257             if (remap_replay_to_trace_handle(m_replayer.get_context_state()->m_vertex_array_objects, replay_handle32))
9258                 return replay_handle32;
9259             break;
9260         }
9261         case VOGL_NAMESPACE_FRAMEBUFFERS:
9262         {
9263             VOGL_ASSERT(replay_handle32 == replay_handle);
9264             if (remap_replay_to_trace_handle(m_replayer.get_context_state()->m_framebuffers, replay_handle32))
9265                 return replay_handle32;
9266             break;
9267         }
9268         case VOGL_NAMESPACE_TEXTURES:
9269         {
9270             VOGL_ASSERT(replay_handle32 == replay_handle);
9271
9272             uint32 trace_handle = replay_handle32;
9273             if (m_replayer.get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_handle32, trace_handle))
9274                 return trace_handle;
9275
9276             break;
9277         }
9278         case VOGL_NAMESPACE_RENDER_BUFFERS:
9279         {
9280             VOGL_ASSERT(replay_handle32 == replay_handle);
9281             GLuint trace_handle = replay_handle32;
9282             if (m_replayer.get_shared_state()->m_shadow_state.m_rbos.map_inv_handle_to_handle(replay_handle32, trace_handle))
9283                 return trace_handle;
9284
9285             break;
9286         }
9287         case VOGL_NAMESPACE_QUERIES:
9288         {
9289             VOGL_ASSERT(replay_handle32 == replay_handle);
9290             if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_queries, replay_handle32))
9291                 return replay_handle32;
9292             break;
9293         }
9294         case VOGL_NAMESPACE_SAMPLERS:
9295         {
9296             VOGL_ASSERT(replay_handle32 == replay_handle);
9297             if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_sampler_objects, replay_handle32))
9298                 return replay_handle32;
9299             break;
9300         }
9301         case VOGL_NAMESPACE_PROGRAMS:
9302         {
9303             VOGL_ASSERT(replay_handle32 == replay_handle);
9304             VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_PROGRAM_OBJECT);
9305             GLuint trace_handle = replay_handle32;
9306             if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle32, trace_handle))
9307                 return trace_handle;
9308             break;
9309         }
9310         case VOGL_NAMESPACE_SHADERS:
9311         {
9312             VOGL_ASSERT(replay_handle32 == replay_handle);
9313             VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_SHADER_OBJECT);
9314             GLuint trace_handle = replay_handle32;
9315             if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle32, trace_handle))
9316                 return trace_handle;
9317             break;
9318         }
9319         case VOGL_NAMESPACE_BUFFERS:
9320         {
9321             VOGL_ASSERT(replay_handle32 == replay_handle);
9322             if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_buffers, replay_handle32))
9323                 return replay_handle32;
9324             break;
9325         }
9326         case VOGL_NAMESPACE_SYNCS:
9327         {
9328             GLsync replay_sync = vogl_handle_to_sync(replay_handle);
9329
9330             gl_sync_hash_map::const_iterator it(m_replayer.get_shared_state()->m_syncs.search_table_for_value(replay_sync));
9331             if (it != m_replayer.get_shared_state()->m_syncs.end())
9332             {
9333                 VOGL_ASSERT(it->second == replay_sync);
9334                 return it->first;
9335             }
9336
9337             break;
9338         }
9339         case VOGL_NAMESPACE_PROGRAM_ARB:
9340         {
9341             VOGL_ASSERT(replay_handle32 == replay_handle);
9342             if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_arb_programs, replay_handle32))
9343                 return replay_handle32;
9344             break;
9345         }
9346         default:
9347         {
9348             break;
9349         }
9350     }
9351
9352     // This is BAD.
9353     vogl_error_printf("%s: Failed remapping handle %" PRIu64 " in namespace %s. This is either a handle shadowing bug, or this object was deleted while it was still bound on another context or attached to an object.\n", VOGL_METHOD_NAME, replay_handle, vogl_get_namespace_name(handle_namespace));
9354
9355     VOGL_ASSERT_ALWAYS;
9356
9357     return replay_handle;
9358 }
9359
9360 //----------------------------------------------------------------------------------------------------------------------
9361 // vogl_gl_replayer::replay_to_trace_handle_remapper::remap_location
9362 //----------------------------------------------------------------------------------------------------------------------
9363 int32 vogl_gl_replayer::replay_to_trace_handle_remapper::remap_location(uint32 replay_program, int32 replay_location)
9364 {
9365     VOGL_FUNC_TRACER
9366
9367     if ((!replay_program) || (replay_location < 0))
9368         return replay_location;
9369
9370     GLuint trace_program = static_cast<GLuint>(remap_handle(VOGL_NAMESPACE_PROGRAMS, replay_program));
9371
9372     glsl_program_hash_map::const_iterator it(m_replayer.get_shared_state()->m_glsl_program_hash_map.find(trace_program));
9373     if (it != m_replayer.get_shared_state()->m_glsl_program_hash_map.end())
9374     {
9375         const glsl_program_state &state = it->second;
9376
9377         uniform_location_hash_map::const_iterator loc_it(state.m_uniform_locations.search_table_for_value(replay_location));
9378         if (loc_it != state.m_uniform_locations.end())
9379             return loc_it->first;
9380     }
9381
9382     vogl_warning_printf("%s: Failed remapping location %i of program %u\n", VOGL_METHOD_NAME, replay_location, replay_program);
9383
9384     return replay_location;
9385 }
9386
9387 //----------------------------------------------------------------------------------------------------------------------
9388 // vogl_gl_replayer::replay_to_trace_handle_remapper::determine_from_object_target
9389 //----------------------------------------------------------------------------------------------------------------------
9390 bool vogl_gl_replayer::replay_to_trace_handle_remapper::determine_from_object_target(vogl_namespace_t handle_namespace, uint64_t replay_handle, GLenum &target)
9391 {
9392     VOGL_FUNC_TRACER
9393
9394     target = GL_NONE;
9395
9396     uint32 handle32 = static_cast<uint32>(replay_handle);
9397
9398     switch (handle_namespace)
9399     {
9400         case VOGL_NAMESPACE_TEXTURES:
9401         {
9402             VOGL_ASSERT(handle32 == replay_handle);
9403             if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(handle32))
9404                 return false;
9405
9406             target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target_inv(handle32);
9407             return true;
9408         }
9409         default:
9410             break;
9411     }
9412
9413     VOGL_VERIFY(0);
9414     return false;
9415 }
9416
9417 //----------------------------------------------------------------------------------------------------------------------
9418 // vogl_gl_replayer::replay_to_trace_handle_remapper::determine_to_object_target
9419 //----------------------------------------------------------------------------------------------------------------------
9420 bool vogl_gl_replayer::replay_to_trace_handle_remapper::determine_to_object_target(vogl_namespace_t handle_namespace, uint64_t trace_handle, GLenum &target)
9421 {
9422     VOGL_FUNC_TRACER
9423
9424     target = GL_NONE;
9425
9426     uint32 handle32 = static_cast<uint32>(trace_handle);
9427
9428     switch (handle_namespace)
9429     {
9430         case VOGL_NAMESPACE_TEXTURES:
9431         {
9432             VOGL_ASSERT(handle32 == trace_handle);
9433             if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(handle32))
9434                 return false;
9435
9436             target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target(handle32);
9437             return true;
9438         }
9439         default:
9440             break;
9441     }
9442
9443     VOGL_VERIFY(0);
9444     return false;
9445 }
9446
9447 //----------------------------------------------------------------------------------------------------------------------
9448 // vogl_replayer::determine_used_program_handles
9449 //----------------------------------------------------------------------------------------------------------------------
9450 bool vogl_gl_replayer::determine_used_program_handles(const vogl_trace_packet_array &trim_packets, vogl_handle_hash_set &replay_program_handles)
9451 {
9452     VOGL_FUNC_TRACER
9453
9454     trace_to_replay_handle_remapper trace_to_replay_remapper(*this);
9455
9456 #if 0
9457         GLint cur_program_handle = 0;
9458         GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &cur_program_handle);
9459         check_gl_error();
9460
9461         if (cur_program_handle)
9462                 replay_program_handles.insert(cur_program_handle);
9463 #endif
9464
9465     // Scan for bound programs on all contexts in this sharegroup
9466     context_state *pContext_shareroot = m_pCur_context_state->m_pShared_state;
9467     for (context_hash_map::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
9468     {
9469         context_state *pContext = it->second;
9470         if (pContext->m_pShared_state == pContext_shareroot)
9471         {
9472             if (pContext->m_cur_replay_program)
9473                 replay_program_handles.insert(pContext->m_cur_replay_program);
9474         }
9475     }
9476
9477     for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
9478     {
9479         if (trim_packets.get_packet_type(packet_index) != cTSPTGLEntrypoint)
9480             continue;
9481
9482         const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
9483
9484         // Important note: This purposesly doesn't process ctype packets, because they don't really do anything and I'm going to be redesigning the ctype/entrypoint stuff anyway so they are always processed after SOF.
9485         if (!m_temp2_gl_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
9486             return false;
9487
9488         GLuint trace_handle = 0;
9489         bool refers_to_program = vogl_does_packet_refer_to_program(m_temp2_gl_packet, trace_handle);
9490         if (!refers_to_program)
9491             continue;
9492         if (!trace_handle)
9493             continue;
9494
9495         // trace_handle is conservative, and it's fine if it can't be actually mapped into the replay space because as we process packets it's possible for the trace to create/delete program handles
9496         // All that matters is that we're conservative (i.e. we can't filter out any programs that are actually referenced in this trace packet array).
9497         if (!trace_to_replay_remapper.is_valid_handle(VOGL_NAMESPACE_PROGRAMS, trace_handle))
9498             continue;
9499
9500         uint64_t replay_handle = trace_to_replay_remapper.remap_handle(VOGL_NAMESPACE_PROGRAMS, trace_handle);
9501         if (!replay_handle)
9502             continue;
9503
9504         VOGL_ASSERT(utils::is_32bit(replay_handle));
9505
9506         replay_program_handles.insert(static_cast<uint32>(replay_handle));
9507     }
9508
9509     vogl_message_printf("%s: Found %u actually referenced program handles\n", VOGL_METHOD_NAME, replay_program_handles.size());
9510
9511     return true;
9512 }
9513
9514 //----------------------------------------------------------------------------------------------------------------------
9515 // vogl_replayer::fill_replay_handle_hash_set
9516 //----------------------------------------------------------------------------------------------------------------------
9517 void vogl_gl_replayer::fill_replay_handle_hash_set(vogl_handle_hash_set &replay_handle_hash, const gl_handle_hash_map &trace_to_replay_hash)
9518 {
9519     VOGL_FUNC_TRACER
9520
9521     replay_handle_hash.reset();
9522     replay_handle_hash.reserve(trace_to_replay_hash.size());
9523     for (gl_handle_hash_map::const_iterator it = trace_to_replay_hash.begin(); it != trace_to_replay_hash.end(); ++it)
9524     {
9525         // Insert replay handles into destination hash table
9526         bool success = replay_handle_hash.insert(it->second).second;
9527         VOGL_ASSERT(success);
9528         VOGL_NOTE_UNUSED(success);
9529     }
9530 }
9531
9532 //----------------------------------------------------------------------------------------------------------------------
9533 // vogl_replayer::snapshot_state
9534 //----------------------------------------------------------------------------------------------------------------------
9535 vogl_gl_state_snapshot *vogl_gl_replayer::snapshot_state(const vogl_trace_packet_array *pTrim_packets, bool optimize_snapshot)
9536 {
9537     VOGL_FUNC_TRACER
9538
9539     timed_scope ts(VOGL_METHOD_NAME);
9540
9541     vogl_gl_state_snapshot *pSnapshot = vogl_new(vogl_gl_state_snapshot);
9542
9543     vogl_message_printf("%s: Beginning capture: width %u, height %u, trace context 0x%" PRIx64 ", frame index %u, last call counter %" PRIu64 ", at frame boundary: %u\n", VOGL_METHOD_NAME,
9544                        m_pWindow->get_width(), m_pWindow->get_height(), m_cur_trace_context, m_frame_index, m_last_parsed_call_counter, m_at_frame_boundary);
9545
9546     if (!pSnapshot->begin_capture(m_pWindow->get_width(), m_pWindow->get_height(), m_cur_trace_context, m_frame_index, m_last_parsed_call_counter, m_at_frame_boundary))
9547     {
9548         vogl_error_printf("%s: Failed beginning capture\n", VOGL_METHOD_NAME);
9549
9550         vogl_delete(pSnapshot);
9551         pSnapshot = NULL;
9552
9553         return NULL;
9554     }
9555
9556     vogl_client_side_array_desc_vec client_side_vertex_attrib_ptrs;
9557     for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_vertex_attrib_data); i++)
9558         client_side_vertex_attrib_ptrs.push_back(vogl_client_side_array_desc(reinterpret_cast<vogl_trace_ptr_value>(m_client_side_vertex_attrib_data[i].get_ptr()), m_client_side_vertex_attrib_data[i].size()));
9559
9560     vogl_client_side_array_desc_vec client_side_array_ptrs;
9561     for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_array_data); i++)
9562         client_side_array_ptrs.push_back(vogl_client_side_array_desc(reinterpret_cast<vogl_trace_ptr_value>(m_client_side_array_data[i].get_ptr()), m_client_side_array_data[i].size()));
9563
9564     vogl_client_side_array_desc_vec client_side_texcoord_ptrs;
9565     for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_texcoord_data); i++)
9566         client_side_texcoord_ptrs.push_back(vogl_client_side_array_desc(reinterpret_cast<vogl_trace_ptr_value>(m_client_side_texcoord_data[i].get_ptr()), m_client_side_texcoord_data[i].size()));
9567
9568     pSnapshot->add_client_side_array_ptrs(client_side_vertex_attrib_ptrs, client_side_array_ptrs, client_side_texcoord_ptrs);
9569
9570     vogl_printf("%s: Capturing %u context(s)\n", VOGL_METHOD_NAME, m_contexts.size());
9571
9572     context_hash_map::iterator it;
9573     for (it = m_contexts.begin(); it != m_contexts.end(); ++it)
9574     {
9575         context_state *pContext_state = it->second;
9576
9577         if (pContext_state->m_deleted)
9578         {
9579             vogl_error_printf("%s: Sharelist root context 0x%" PRIx64 " was destroyed - this scenario is not yet supported for state snapshotting.\n", VOGL_METHOD_NAME, cast_val_to_uint64(it->first));
9580             break;
9581         }
9582
9583         vogl_capture_context_params temp_shadow_state;
9584         vogl_capture_context_params *pShadow_state = &temp_shadow_state;
9585
9586         if (pContext_state->m_has_been_made_current)
9587         {
9588             status_t status = switch_contexts(it->first);
9589             if (status != cStatusOK)
9590             {
9591                 vogl_error_printf("%s: Failed switching to trace context 0x%" PRIX64 ", capture failed\n", VOGL_METHOD_NAME, cast_val_to_uint64(it->first));
9592                 break;
9593             }
9594
9595             VOGL_ASSERT(m_pCur_context_state == pContext_state);
9596
9597             if (m_pCur_context_state->m_inside_gl_begin)
9598             {
9599                 vogl_warning_printf("%s: Trace context 0x%" PRIX64 " is inside a glBegin, which is not fully supported for state capturing. Capture will continue but will not be replayable.\n", VOGL_METHOD_NAME, cast_val_to_uint64(it->first));
9600                 pSnapshot->set_is_restorable(false);
9601             }
9602
9603
9604             // Init the shadow state needed by the snapshot code.
9605             if (!m_pCur_context_state->is_root_context())
9606             {
9607                 // Only fill in non-shared state.
9608                 fill_replay_handle_hash_set(pShadow_state->m_framebuffers, get_context_state()->m_framebuffers);
9609                 fill_replay_handle_hash_set(pShadow_state->m_vaos, get_context_state()->m_vertex_array_objects);
9610             }
9611             else
9612             {
9613                 pShadow_state = &m_pCur_context_state->m_shadow_state;
9614
9615                 pShadow_state->m_query_targets = get_shared_state()->m_query_targets;
9616
9617                 fill_replay_handle_hash_set(pShadow_state->m_samplers, get_shared_state()->m_sampler_objects);
9618                 fill_replay_handle_hash_set(pShadow_state->m_framebuffers, get_context_state()->m_framebuffers);
9619                 fill_replay_handle_hash_set(pShadow_state->m_vaos, get_context_state()->m_vertex_array_objects);
9620
9621                 // Buffer targets
9622                 pShadow_state->m_buffer_targets.reset();
9623                 for (gl_handle_hash_map::const_iterator buf_it = get_shared_state()->m_buffers.begin(); buf_it != get_shared_state()->m_buffers.end(); ++buf_it)
9624                 {
9625                     GLuint trace_handle = buf_it->first;
9626                     GLuint replay_handle = buf_it->second;
9627
9628                     gl_handle_hash_map::const_iterator target_it = get_shared_state()->m_buffer_targets.find(trace_handle);
9629                     if (target_it == get_shared_state()->m_buffer_targets.end())
9630                     {
9631                         vogl_error_printf("%s: Unable to find buffer trace handle 0x%X GL handle 0x%X in buffer target map! This should not happen!\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
9632                         continue;
9633                     }
9634                     GLenum target = target_it->second;
9635
9636                     pShadow_state->m_buffer_targets.insert(replay_handle, target);
9637                 }
9638
9639                 // Syncs
9640                 pShadow_state->m_syncs.reset();
9641                 pShadow_state->m_syncs.reserve(get_shared_state()->m_syncs.size());
9642                 for (gl_sync_hash_map::const_iterator sync_it = get_shared_state()->m_syncs.begin(); sync_it != get_shared_state()->m_syncs.end(); ++sync_it)
9643                 {
9644                     bool success = pShadow_state->m_syncs.insert(vogl_sync_to_handle(sync_it->second)).second;
9645                     VOGL_ASSERT(success);
9646                     VOGL_NOTE_UNUSED(success);
9647                 }
9648
9649                 // Program handles filter
9650                 pShadow_state->m_filter_program_handles = false;
9651                 pShadow_state->m_program_handles_filter.reset();
9652
9653 #if 0
9654                                 // TODO: The program optimization code works, but we also need to delete any unused shaders (or shaders that have been marked as deleted but are referred to by optimized out programs).
9655                                 // This is an optimization issue, and we're concentrating on correctness right now so let's figure this out later.
9656                                 if ((pTrim_packets) && (optimize_snapshot))
9657                                 {
9658                     if (!determine_used_program_handles(*pTrim_packets, pShadow_state->m_program_handles_filter))
9659                                         {
9660                                                 vogl_warning_printf("%s: Failed determining used program handles\n", VOGL_METHOD_NAME);
9661                                                 pShadow_state->m_program_handles_filter.clear();
9662                                         }
9663                                         else
9664                                         {
9665                                                 pShadow_state->m_filter_program_handles = true;
9666                                         }
9667                                 }
9668 #else
9669                 VOGL_NOTE_UNUSED(optimize_snapshot);
9670                 VOGL_NOTE_UNUSED(pTrim_packets);
9671 #endif
9672
9673                 // ARB program targets
9674                 pShadow_state->m_arb_program_targets.reset();
9675                 for (gl_handle_hash_map::const_iterator arb_prog_it = get_shared_state()->m_arb_program_targets.begin(); arb_prog_it != get_shared_state()->m_arb_program_targets.end(); ++arb_prog_it)
9676                 {
9677                     GLuint trace_handle = arb_prog_it->first;
9678                     GLuint replay_handle = get_shared_state()->m_arb_programs.value(trace_handle);
9679                     if ((!trace_handle) || (!replay_handle))
9680                     {
9681                         VOGL_ASSERT_ALWAYS;
9682                         continue;
9683                     }
9684
9685                     GLenum target = arb_prog_it->second;
9686                     pShadow_state->m_arb_program_targets.insert(replay_handle, target);
9687                 }
9688
9689                 // Deal with any currently mapped buffers.
9690                 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
9691
9692                 pShadow_state->m_mapped_buffers = mapped_bufs;
9693
9694                 if (mapped_bufs.size())
9695                 {
9696                     vogl_warning_printf("%s: %u buffer(s) are currently mapped, these will be temporarily unmapped in order to snapshot them and then remapped\n", VOGL_METHOD_NAME, m_pCur_context_state->m_shadow_state.m_mapped_buffers.size());
9697
9698                     for (uint i = 0; i < mapped_bufs.size(); i++)
9699                     {
9700                         vogl_mapped_buffer_desc &desc = mapped_bufs[i];
9701
9702                         GLuint prev_handle = vogl_get_bound_gl_buffer(desc.m_target);
9703
9704                         GL_ENTRYPOINT(glBindBuffer)(desc.m_target, desc.m_buffer);
9705                         VOGL_CHECK_GL_ERROR;
9706
9707                         GL_ENTRYPOINT(glUnmapBuffer)(desc.m_target);
9708                         VOGL_CHECK_GL_ERROR;
9709
9710                         desc.m_pPtr = NULL;
9711
9712                         GL_ENTRYPOINT(glBindBuffer)(desc.m_target, prev_handle);
9713                         VOGL_CHECK_GL_ERROR;
9714                     }
9715                 }
9716
9717             } // if (!m_pCur_context_state->is_root_context())
9718
9719         } // if (pContext_state->m_has_been_made_current)
9720
9721         if (!pSnapshot->capture_context(pContext_state->m_context_desc, pContext_state->m_context_info, m_replay_to_trace_remapper, *pShadow_state))
9722         {
9723             vogl_error_printf("%s: Failed capturing trace context 0x%" PRIX64 ", capture failed\n", VOGL_METHOD_NAME, static_cast<uint64_t>(it->first));
9724             break;
9725         }
9726
9727         if ((pContext_state->m_has_been_made_current) && (m_pCur_context_state->is_root_context()))
9728         {
9729             vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
9730
9731             // Now remap any mapped buffers
9732             for (uint i = 0; i < mapped_bufs.size(); i++)
9733             {
9734                 vogl_mapped_buffer_desc &desc = mapped_bufs[i];
9735
9736                 GLuint prev_handle = vogl_get_bound_gl_buffer(desc.m_target);
9737
9738                 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, desc.m_buffer);
9739                 VOGL_CHECK_GL_ERROR;
9740
9741                 if (desc.m_range)
9742                 {
9743                     desc.m_pPtr = GL_ENTRYPOINT(glMapBufferRange)(desc.m_target, static_cast<GLintptr>(desc.m_offset), static_cast<GLsizeiptr>(desc.m_length), desc.m_access);
9744                     VOGL_CHECK_GL_ERROR;
9745                 }
9746                 else
9747                 {
9748                     desc.m_pPtr = GL_ENTRYPOINT(glMapBuffer)(desc.m_target, desc.m_access);
9749                     VOGL_CHECK_GL_ERROR;
9750                 }
9751
9752                 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, prev_handle);
9753                 VOGL_CHECK_GL_ERROR;
9754
9755             }
9756         }
9757     }
9758
9759     if ((it == m_contexts.end()) && (pSnapshot->end_capture()))
9760     {
9761         vogl_printf("%s: Capture succeeded\n", VOGL_METHOD_NAME);
9762     }
9763     else
9764     {
9765         vogl_printf("%s: Capture failed\n", VOGL_METHOD_NAME);
9766
9767         vogl_delete(pSnapshot);
9768         pSnapshot = NULL;
9769     }
9770
9771     return pSnapshot;
9772 }
9773
9774 //----------------------------------------------------------------------------------------------------------------------
9775 // vogl_replayer::reset_state
9776 //----------------------------------------------------------------------------------------------------------------------
9777 void vogl_gl_replayer::reset_state()
9778 {
9779     VOGL_FUNC_TRACER
9780
9781     // Purposely does NOT destroy the cached snapshots
9782
9783     destroy_pending_snapshot();
9784     destroy_contexts();
9785
9786     m_pending_make_current_packet.clear();
9787     m_pending_window_resize_width = 0;
9788     m_pending_window_resize_height = 0;
9789     m_pending_window_resize_attempt_counter = 0;
9790
9791     m_frame_index = 0;
9792     m_last_parsed_call_counter = -1;
9793     m_last_processed_call_counter = -1;
9794     m_at_frame_boundary = true;
9795
9796     m_cur_trace_context = 0;
9797     m_cur_replay_context = 0;
9798     m_pCur_context_state = NULL;
9799
9800     // Testing
9801     //if (m_pWindow->is_opened())
9802     //   m_pWindow->clear_window();
9803 }
9804
9805 //----------------------------------------------------------------------------------------------------------------------
9806 // trace_to_replay_handle_remapper::is_valid_handle
9807 //----------------------------------------------------------------------------------------------------------------------
9808 bool vogl_gl_replayer::trace_to_replay_handle_remapper::is_valid_handle(vogl_namespace_t handle_namespace, uint64_t from_handle)
9809 {
9810     VOGL_FUNC_TRACER
9811
9812     if (!from_handle)
9813         return false;
9814
9815     uint32 from_handle32 = static_cast<uint32>(from_handle);
9816
9817     switch (handle_namespace)
9818     {
9819         case VOGL_NAMESPACE_VERTEX_ARRAYS:
9820         {
9821             VOGL_ASSERT(from_handle32 == from_handle);
9822             return m_replayer.get_context_state()->m_vertex_array_objects.contains(from_handle32);
9823         }
9824         case VOGL_NAMESPACE_TEXTURES:
9825         {
9826             VOGL_ASSERT(from_handle32 == from_handle);
9827             return m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(from_handle32);
9828         }
9829         case VOGL_NAMESPACE_SAMPLERS:
9830         {
9831             VOGL_ASSERT(from_handle32 == from_handle);
9832             return m_replayer.get_shared_state()->m_sampler_objects.contains(from_handle32);
9833         }
9834         case VOGL_NAMESPACE_BUFFERS:
9835         {
9836             VOGL_ASSERT(from_handle32 == from_handle);
9837             return m_replayer.get_shared_state()->m_buffers.contains(from_handle32);
9838         }
9839         case VOGL_NAMESPACE_SHADERS:
9840         case VOGL_NAMESPACE_PROGRAMS:
9841         {
9842             VOGL_ASSERT(from_handle32 == from_handle);
9843             return m_replayer.get_shared_state()->m_shadow_state.m_objs.contains(from_handle32);
9844         }
9845         case VOGL_NAMESPACE_FRAMEBUFFERS:
9846         {
9847             VOGL_ASSERT(from_handle32 == from_handle);
9848             return m_replayer.get_context_state()->m_framebuffers.contains(from_handle32);
9849         }
9850         case VOGL_NAMESPACE_RENDER_BUFFERS:
9851         {
9852             VOGL_ASSERT(from_handle32 == from_handle);
9853             return m_replayer.get_shared_state()->m_shadow_state.m_rbos.contains(from_handle32);
9854         }
9855         case VOGL_NAMESPACE_QUERIES:
9856         {
9857             VOGL_ASSERT(from_handle32 == from_handle);
9858             return m_replayer.get_shared_state()->m_queries.contains(from_handle32);
9859         }
9860         case VOGL_NAMESPACE_SYNCS:
9861         {
9862             return m_replayer.get_shared_state()->m_syncs.contains(from_handle);
9863         }
9864         case VOGL_NAMESPACE_PROGRAM_ARB:
9865         {
9866             return m_replayer.get_shared_state()->m_arb_programs.contains(from_handle32);
9867         }
9868         default:
9869             break;
9870     }
9871
9872     VOGL_VERIFY(0);
9873
9874     return false;
9875 }
9876
9877 //----------------------------------------------------------------------------------------------------------------------
9878 // trace_to_replay_handle_remapper::remap_handle
9879 //----------------------------------------------------------------------------------------------------------------------
9880 uint64_t vogl_gl_replayer::trace_to_replay_handle_remapper::remap_handle(vogl_namespace_t handle_namespace, uint64_t from_handle)
9881 {
9882     VOGL_FUNC_TRACER
9883
9884     if (!from_handle)
9885         return from_handle;
9886
9887     uint32 from_handle32 = static_cast<uint32>(from_handle);
9888
9889     switch (handle_namespace)
9890     {
9891         case VOGL_NAMESPACE_VERTEX_ARRAYS:
9892         {
9893             VOGL_ASSERT(from_handle32 == from_handle);
9894             return m_replayer.get_context_state()->m_vertex_array_objects.value(from_handle32, from_handle32);
9895         }
9896         case VOGL_NAMESPACE_TEXTURES:
9897         {
9898             VOGL_ASSERT(from_handle32 == from_handle);
9899
9900             uint32 replay_handle = from_handle32;
9901             if (m_replayer.get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(from_handle32, replay_handle))
9902                 return replay_handle;
9903             break;
9904         }
9905         case VOGL_NAMESPACE_SAMPLERS:
9906         {
9907             VOGL_ASSERT(from_handle32 == from_handle);
9908             return m_replayer.get_shared_state()->m_sampler_objects.value(from_handle32, from_handle32);
9909         }
9910         case VOGL_NAMESPACE_BUFFERS:
9911         {
9912             VOGL_ASSERT(from_handle32 == from_handle);
9913             return m_replayer.get_shared_state()->m_buffers.value(from_handle32, from_handle32);
9914         }
9915         case VOGL_NAMESPACE_SHADERS:
9916         case VOGL_NAMESPACE_PROGRAMS:
9917         {
9918             VOGL_ASSERT(from_handle32 == from_handle);
9919
9920             GLuint replay_handle = from_handle32;
9921             if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_handle_to_inv_handle(from_handle32, replay_handle))
9922                 return replay_handle;
9923             break;
9924         }
9925         case VOGL_NAMESPACE_FRAMEBUFFERS:
9926         {
9927             VOGL_ASSERT(from_handle32 == from_handle);
9928             return m_replayer.get_context_state()->m_framebuffers.value(from_handle32, from_handle32);
9929         }
9930         case VOGL_NAMESPACE_RENDER_BUFFERS:
9931         {
9932             VOGL_ASSERT(from_handle32 == from_handle);
9933
9934             GLuint replay_handle = from_handle32;
9935             if (m_replayer.get_shared_state()->m_shadow_state.m_rbos.map_handle_to_inv_handle(from_handle32, replay_handle))
9936                 return replay_handle;
9937
9938             break;
9939         }
9940         case VOGL_NAMESPACE_QUERIES:
9941         {
9942             VOGL_ASSERT(from_handle32 == from_handle);
9943             return m_replayer.get_shared_state()->m_queries.value(from_handle32, from_handle32);
9944         }
9945         case VOGL_NAMESPACE_SYNCS:
9946         {
9947             return vogl_sync_to_handle(m_replayer.get_shared_state()->m_syncs.value(from_handle, vogl_handle_to_sync(from_handle)));
9948         }
9949         case VOGL_NAMESPACE_PROGRAM_ARB:
9950         {
9951             return m_replayer.get_shared_state()->m_arb_programs.value(from_handle32, from_handle32);
9952         }
9953         default:
9954         {
9955             break;
9956         }
9957     }
9958
9959     VOGL_ASSERT_ALWAYS;
9960
9961     vogl_error_printf("%s: Failed remapping handle %" PRIu64 " in namespace %s.\n", VOGL_METHOD_NAME, from_handle, vogl_get_namespace_name(handle_namespace));
9962
9963     return from_handle;
9964 }
9965
9966 //----------------------------------------------------------------------------------------------------------------------
9967 // trace_to_replay_handle_remapper::remap_location
9968 //----------------------------------------------------------------------------------------------------------------------
9969 int32 vogl_gl_replayer::trace_to_replay_handle_remapper::remap_location(uint32 trace_program, int32 from_location)
9970 {
9971     VOGL_FUNC_TRACER
9972
9973     VOGL_NOTE_UNUSED(trace_program);
9974
9975     // restoring declares, but doesn't need to remap
9976     VOGL_ASSERT_ALWAYS;
9977
9978     return from_location;
9979 }
9980
9981 //----------------------------------------------------------------------------------------------------------------------
9982 // trace_to_replay_handle_remapper::remap_vertex_attrib_ptr
9983 //----------------------------------------------------------------------------------------------------------------------
9984 vogl_trace_ptr_value vogl_gl_replayer::trace_to_replay_handle_remapper::remap_vertex_attrib_ptr(uint index, vogl_trace_ptr_value ptr_val)
9985 {
9986     VOGL_FUNC_TRACER
9987
9988     if (!ptr_val)
9989         return ptr_val;
9990
9991     VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_vertex_attrib_data));
9992     if (!m_replayer.m_client_side_vertex_attrib_data[index].size())
9993     {
9994         m_replayer.m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
9995     }
9996
9997     return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_vertex_attrib_data[index].get_ptr());
9998 }
9999
10000 //----------------------------------------------------------------------------------------------------------------------
10001 // trace_to_replay_handle_remapper::remap_vertex_array_ptr
10002 //----------------------------------------------------------------------------------------------------------------------
10003 vogl_trace_ptr_value vogl_gl_replayer::trace_to_replay_handle_remapper::remap_vertex_array_ptr(vogl_client_side_array_desc_id_t id, uint index, vogl_trace_ptr_value ptr_val)
10004 {
10005     VOGL_FUNC_TRACER
10006
10007     VOGL_ASSERT(id < VOGL_NUM_CLIENT_SIDE_ARRAY_DESCS);
10008
10009     if (!ptr_val)
10010         return ptr_val;
10011
10012     if (id == vogl_texcoord_pointer_array_id)
10013     {
10014         VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_texcoord_data));
10015
10016         if (!m_replayer.m_client_side_texcoord_data[index].size())
10017         {
10018             m_replayer.m_client_side_texcoord_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
10019         }
10020
10021         return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_texcoord_data[index].get_ptr());
10022     }
10023     else
10024     {
10025         VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_array_data));
10026
10027         if (!m_replayer.m_client_side_array_data[id].size())
10028         {
10029             m_replayer.m_client_side_array_data[id].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
10030         }
10031
10032         return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_array_data[id].get_ptr());
10033     }
10034 }
10035
10036 //----------------------------------------------------------------------------------------------------------------------
10037 // trace_to_replay_handle_remapper::declare_handle
10038 //----------------------------------------------------------------------------------------------------------------------
10039 void vogl_gl_replayer::trace_to_replay_handle_remapper::declare_handle(vogl_namespace_t handle_namespace, uint64_t from_handle, uint64_t to_handle, GLenum target)
10040 {
10041     VOGL_FUNC_TRACER
10042
10043     if ((!from_handle) || (!to_handle))
10044     {
10045         VOGL_ASSERT_ALWAYS;
10046         return;
10047     }
10048
10049     uint32 from_handle32 = static_cast<uint32>(from_handle);
10050     uint32 to_handle32 = static_cast<uint32>(to_handle);
10051
10052     switch (handle_namespace)
10053     {
10054         case VOGL_NAMESPACE_VERTEX_ARRAYS:
10055         {
10056             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10057             m_replayer.get_context_state()->m_vertex_array_objects.insert(from_handle32, to_handle32);
10058             break;
10059         }
10060         case VOGL_NAMESPACE_TEXTURES:
10061         {
10062             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10063             if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.update(from_handle32, to_handle32, target))
10064                 vogl_warning_printf("%s: Failed inserting trace texture %u GL texture %u handle into texture handle tracker!\n", VOGL_METHOD_NAME, from_handle32, to_handle32);
10065             break;
10066         }
10067         case VOGL_NAMESPACE_SAMPLERS:
10068         {
10069             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10070             m_replayer.get_shared_state()->m_sampler_objects.insert(from_handle32, to_handle32);
10071             break;
10072         }
10073         case VOGL_NAMESPACE_BUFFERS:
10074         {
10075             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10076             m_replayer.get_shared_state()->m_buffers.insert(from_handle32, to_handle32);
10077             m_replayer.get_shared_state()->m_buffer_targets.insert(from_handle32, target);
10078             break;
10079         }
10080         case VOGL_NAMESPACE_SHADERS:
10081         {
10082             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10083             if (!m_replayer.get_shared_state()->m_shadow_state.m_objs.insert(from_handle32, to_handle32, VOGL_SHADER_OBJECT))
10084                 vogl_warning_printf("%s: Failed inserting trace shader handle %u GL handle %u into object handle tracker!\n", VOGL_METHOD_NAME, from_handle32, to_handle32);
10085             break;
10086         }
10087         case VOGL_NAMESPACE_PROGRAMS:
10088         {
10089             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10090             if (!m_replayer.get_shared_state()->m_shadow_state.m_objs.insert(from_handle32, to_handle32, VOGL_PROGRAM_OBJECT))
10091                 vogl_warning_printf("%s: Failed inserting trace program handle %u GL handle %u into object handle tracker!\n", VOGL_METHOD_NAME, from_handle32, to_handle32);
10092             break;
10093         }
10094         case VOGL_NAMESPACE_FRAMEBUFFERS:
10095         {
10096             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10097             m_replayer.get_context_state()->m_framebuffers.insert(from_handle32, to_handle32);
10098             break;
10099         }
10100         case VOGL_NAMESPACE_RENDER_BUFFERS:
10101         {
10102             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10103             if (!m_replayer.get_shared_state()->m_shadow_state.m_rbos.insert(from_handle32, to_handle32, GL_NONE))
10104                 vogl_warning_printf("%s: Failed inserting trace RBO handle %u GL handle %u into RBO handle tracker!\n", VOGL_METHOD_NAME, from_handle32, to_handle32);
10105             break;
10106         }
10107         case VOGL_NAMESPACE_QUERIES:
10108         {
10109             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10110             m_replayer.get_shared_state()->m_queries.insert(from_handle32, to_handle32);
10111             m_replayer.get_shared_state()->m_query_targets[to_handle32] = target;
10112             break;
10113         }
10114         case VOGL_NAMESPACE_SYNCS:
10115         {
10116             m_replayer.get_shared_state()->m_syncs.insert(from_handle, vogl_handle_to_sync(to_handle));
10117             break;
10118         }
10119         case VOGL_NAMESPACE_PROGRAM_ARB:
10120         {
10121             m_replayer.get_shared_state()->m_arb_programs.insert(from_handle32, to_handle32);
10122             m_replayer.get_shared_state()->m_arb_program_targets.insert(from_handle32, target);
10123             break;
10124         }
10125         default:
10126         {
10127             VOGL_VERIFY(0);
10128             break;
10129         }
10130     }
10131 }
10132
10133 //----------------------------------------------------------------------------------------------------------------------
10134 // trace_to_replay_handle_remapper::delete_handle_and_object
10135 //----------------------------------------------------------------------------------------------------------------------
10136 void vogl_gl_replayer::trace_to_replay_handle_remapper::delete_handle_and_object(vogl_namespace_t handle_namespace, uint64_t from_handle, uint64_t to_handle)
10137 {
10138     VOGL_FUNC_TRACER
10139
10140     if ((!from_handle) || (!to_handle))
10141     {
10142         VOGL_ASSERT_ALWAYS;
10143         return;
10144     }
10145
10146     uint32 from_handle32 = static_cast<uint32>(from_handle);
10147     uint32 to_handle32 = static_cast<uint32>(to_handle);
10148     VOGL_NOTE_UNUSED(to_handle32);
10149
10150     switch (handle_namespace)
10151     {
10152         case VOGL_NAMESPACE_VERTEX_ARRAYS:
10153         {
10154             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10155             m_replayer.get_context_state()->m_vertex_array_objects.erase(from_handle32);
10156             vogl_destroy_gl_object(handle_namespace, to_handle);
10157             break;
10158         }
10159         case VOGL_NAMESPACE_TEXTURES:
10160         {
10161             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10162             if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.erase(from_handle32))
10163                 vogl_warning_printf("%s: Failed deleting trace texture handle %u GL handle %u from texture handle tracker!\n", VOGL_METHOD_NAME, from_handle32, to_handle32);
10164
10165             vogl_destroy_gl_object(handle_namespace, to_handle);
10166             break;
10167         }
10168         case VOGL_NAMESPACE_SAMPLERS:
10169         {
10170             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10171             m_replayer.get_shared_state()->m_sampler_objects.erase(from_handle32);
10172             vogl_destroy_gl_object(handle_namespace, to_handle);
10173             break;
10174         }
10175         case VOGL_NAMESPACE_BUFFERS:
10176         {
10177             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10178             m_replayer.get_shared_state()->m_buffers.erase(from_handle32);
10179             m_replayer.get_shared_state()->m_buffer_targets.erase(from_handle32);
10180             vogl_destroy_gl_object(handle_namespace, to_handle);
10181             break;
10182         }
10183         case VOGL_NAMESPACE_SHADERS:
10184         {
10185             m_replayer.handle_delete_shader(from_handle32);
10186             break;
10187         }
10188         case VOGL_NAMESPACE_PROGRAMS:
10189         {
10190             m_replayer.handle_delete_program(from_handle32);
10191             break;
10192         }
10193         case VOGL_NAMESPACE_FRAMEBUFFERS:
10194         {
10195             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10196             m_replayer.get_context_state()->m_framebuffers.erase(from_handle32);
10197             vogl_destroy_gl_object(handle_namespace, to_handle);
10198             break;
10199         }
10200         case VOGL_NAMESPACE_RENDER_BUFFERS:
10201         {
10202             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10203
10204             if (!m_replayer.get_shared_state()->m_shadow_state.m_rbos.erase(from_handle32))
10205                 vogl_warning_printf("%s: Failed deleting trace texture handle %u GL handle %u from RBO handle tracker!\n", VOGL_METHOD_NAME, from_handle32, to_handle32);
10206
10207             vogl_destroy_gl_object(handle_namespace, to_handle);
10208             break;
10209         }
10210         case VOGL_NAMESPACE_QUERIES:
10211         {
10212             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10213             m_replayer.get_shared_state()->m_queries.erase(from_handle32);
10214             vogl_destroy_gl_object(handle_namespace, to_handle);
10215             break;
10216         }
10217         case VOGL_NAMESPACE_SYNCS:
10218         {
10219             m_replayer.get_shared_state()->m_syncs.erase(from_handle);
10220             vogl_destroy_gl_object(handle_namespace, to_handle);
10221             break;
10222         }
10223         case VOGL_NAMESPACE_PROGRAM_ARB:
10224         {
10225             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10226             m_replayer.get_shared_state()->m_arb_programs.erase(from_handle32);
10227             m_replayer.get_shared_state()->m_arb_program_targets.erase(from_handle32);
10228             vogl_destroy_gl_object(handle_namespace, to_handle);
10229             break;
10230         }
10231         default:
10232         {
10233             VOGL_VERIFY(0);
10234             break;
10235         }
10236     }
10237 }
10238
10239 //----------------------------------------------------------------------------------------------------------------------
10240 // vogl_replayer::trace_to_replay_handle_remapper::declare_location
10241 //----------------------------------------------------------------------------------------------------------------------
10242 void vogl_gl_replayer::trace_to_replay_handle_remapper::declare_location(uint32 from_program_handle, uint32 to_program_handle, int32 from_location, int32 to_location)
10243 {
10244     VOGL_FUNC_TRACER
10245
10246     GLuint check_replay_handle = 0;
10247     VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.map_handle_to_inv_handle(from_program_handle, check_replay_handle));
10248     VOGL_ASSERT(check_replay_handle == to_program_handle);
10249     VOGL_NOTE_UNUSED(check_replay_handle);
10250
10251     VOGL_NOTE_UNUSED(to_program_handle);
10252
10253     glsl_program_hash_map::iterator it(m_replayer.get_shared_state()->m_glsl_program_hash_map.insert(from_program_handle).first);
10254
10255     glsl_program_state &prog_state = it->second;
10256
10257     VOGL_ASSERT(!prog_state.m_uniform_locations.contains(from_location));
10258
10259     prog_state.m_uniform_locations.insert(from_location, to_location);
10260 }
10261
10262 //----------------------------------------------------------------------------------------------------------------------
10263 // vogl_gl_replayer::trace_to_replay_handle_remapper::determine_from_object_target
10264 //----------------------------------------------------------------------------------------------------------------------
10265 bool vogl_gl_replayer::trace_to_replay_handle_remapper::determine_from_object_target(vogl_namespace_t handle_namespace, uint64_t trace_handle, GLenum &target)
10266 {
10267     VOGL_FUNC_TRACER
10268
10269     target = GL_NONE;
10270
10271     uint32 handle32 = static_cast<uint32>(trace_handle);
10272
10273     switch (handle_namespace)
10274     {
10275         case VOGL_NAMESPACE_TEXTURES:
10276         {
10277             VOGL_ASSERT(handle32 == trace_handle);
10278             if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(handle32))
10279                 return false;
10280
10281             target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target(handle32);
10282             return true;
10283         }
10284         default:
10285             break;
10286     }
10287
10288     VOGL_VERIFY(0);
10289     return false;
10290 }
10291
10292 //----------------------------------------------------------------------------------------------------------------------
10293 // vogl_gl_replayer::trace_to_replay_handle_remapper::determine_to_object_target
10294 //----------------------------------------------------------------------------------------------------------------------
10295 bool vogl_gl_replayer::trace_to_replay_handle_remapper::determine_to_object_target(vogl_namespace_t handle_namespace, uint64_t replay_handle, GLenum &target)
10296 {
10297     VOGL_FUNC_TRACER
10298
10299     target = GL_NONE;
10300
10301     uint32 handle32 = static_cast<uint32>(replay_handle);
10302
10303     switch (handle_namespace)
10304     {
10305         case VOGL_NAMESPACE_TEXTURES:
10306         {
10307             VOGL_ASSERT(handle32 == replay_handle);
10308             if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(handle32))
10309                 return false;
10310
10311             target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target_inv(handle32);
10312             return true;
10313         }
10314         default:
10315             break;
10316     }
10317
10318     VOGL_VERIFY(0);
10319     return false;
10320 }
10321
10322 //----------------------------------------------------------------------------------------------------------------------
10323 // vogl_replayer::restore_objects
10324 //----------------------------------------------------------------------------------------------------------------------
10325 vogl_gl_replayer::status_t vogl_gl_replayer::restore_objects(
10326     vogl_handle_remapper &trace_to_replay_remapper, const vogl_gl_state_snapshot &snapshot, const vogl_context_snapshot &context_state, vogl_gl_object_state_type state_type,
10327     vogl_const_gl_object_state_ptr_vec &objects_to_delete)
10328 {
10329     VOGL_FUNC_TRACER
10330
10331     VOGL_NOTE_UNUSED(snapshot);
10332
10333     if (m_flags & cGLReplayerVerboseMode)
10334         vogl_printf("%s: Restoring %s objects\n", VOGL_METHOD_NAME, get_gl_object_state_type_str(state_type));
10335
10336     vogl::timer tm;
10337     if (m_flags & cGLReplayerVerboseMode)
10338         tm.start();
10339
10340     const vogl_gl_object_state_ptr_vec &object_ptrs = context_state.get_objects();
10341
10342     uint n = 0;
10343
10344     for (uint i = 0; i < object_ptrs.size(); i++)
10345     {
10346         const vogl_gl_object_state *pState_obj = object_ptrs[i];
10347
10348         if (pState_obj->get_type() != state_type)
10349             continue;
10350
10351         GLuint64 restore_handle = 0;
10352         if (!pState_obj->restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper, restore_handle))
10353         {
10354             vogl_error_printf("%s: Failed restoring object type %s object index %u trace handle 0x%" PRIX64 " restore handle 0x%" PRIX64 "\n", VOGL_METHOD_NAME, get_gl_object_state_type_str(state_type), i, (uint64_t)pState_obj->get_snapshot_handle(), (uint64_t)restore_handle);
10355             return cStatusHardFailure;
10356         }
10357         n++;
10358
10359         if (pState_obj->get_marked_for_deletion())
10360         {
10361             objects_to_delete.push_back(pState_obj);
10362         }
10363
10364         VOGL_ASSERT(trace_to_replay_remapper.remap_handle(pState_obj->get_handle_namespace(), pState_obj->get_snapshot_handle()) == restore_handle);
10365
10366         switch (pState_obj->get_type())
10367         {
10368             case cGLSTQuery:
10369             {
10370                 const vogl_query_state *pQuery = static_cast<const vogl_query_state *>(pState_obj);
10371
10372                 VOGL_ASSERT(restore_handle <= cUINT32_MAX);
10373                 get_shared_state()->m_query_targets[static_cast<GLuint>(restore_handle)] = pQuery->get_target();
10374
10375                 break;
10376             }
10377             case cGLSTProgram:
10378             {
10379                 const vogl_program_state *pProg = static_cast<const vogl_program_state *>(pState_obj);
10380
10381                 if (pProg->has_link_time_snapshot())
10382                 {
10383                     vogl_program_state link_snapshot(*pProg->get_link_time_snapshot());
10384                     if (!link_snapshot.remap_handles(trace_to_replay_remapper))
10385                     {
10386                         vogl_error_printf("%s: Failed remapping handles in program link time snapshot, object index %u trace handle 0x%" PRIX64 " restore handle 0x%" PRIX64 "\n", VOGL_METHOD_NAME, i, (uint64_t)pState_obj->get_snapshot_handle(), (uint64_t)restore_handle);
10387                     }
10388                     else
10389                     {
10390                         get_shared_state()->m_shadow_state.m_linked_programs.add_snapshot(static_cast<uint32>(restore_handle), link_snapshot);
10391                     }
10392                 }
10393
10394                 if (m_flags & cGLReplayerVerboseMode)
10395                 {
10396                     if ((n & 255) == 255)
10397                         vogl_printf("%s: Restored %u programs\n", VOGL_METHOD_NAME, n);
10398                 }
10399
10400                 break;
10401             }
10402             case cGLSTBuffer:
10403             {
10404                 const vogl_buffer_state *pBuf = static_cast<const vogl_buffer_state *>(pState_obj);
10405
10406                 // Check if the buffer was mapped during the snapshot, if so remap it and record the ptr in the replayer's context shadow.
10407                 if (pBuf->get_is_mapped())
10408                 {
10409                     vogl_mapped_buffer_desc map_desc;
10410                     map_desc.m_buffer = static_cast<GLuint>(restore_handle);
10411                     map_desc.m_target = pBuf->get_target();
10412                     map_desc.m_offset = pBuf->get_map_ofs();
10413                     map_desc.m_length = pBuf->get_map_size();
10414                     map_desc.m_access = pBuf->get_map_access();
10415                     map_desc.m_range = pBuf->get_is_map_range();
10416
10417                     GLuint prev_handle = vogl_get_bound_gl_buffer(map_desc.m_target);
10418
10419                     GL_ENTRYPOINT(glBindBuffer)(map_desc.m_target, map_desc.m_buffer);
10420                     VOGL_CHECK_GL_ERROR;
10421
10422                     if (map_desc.m_range)
10423                     {
10424                         map_desc.m_pPtr = GL_ENTRYPOINT(glMapBufferRange)(map_desc.m_target, static_cast<GLintptr>(map_desc.m_offset), static_cast<GLintptr>(map_desc.m_length), map_desc.m_access);
10425                         VOGL_CHECK_GL_ERROR;
10426                     }
10427                     else
10428                     {
10429                         map_desc.m_pPtr = GL_ENTRYPOINT(glMapBuffer)(map_desc.m_target, map_desc.m_access);
10430                         VOGL_CHECK_GL_ERROR;
10431                     }
10432
10433                     GL_ENTRYPOINT(glBindBuffer)(map_desc.m_target, prev_handle);
10434                     VOGL_CHECK_GL_ERROR;
10435
10436                     vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
10437                     mapped_bufs.push_back(map_desc);
10438                 }
10439
10440                 break;
10441             }
10442             default:
10443                 break;
10444         }
10445     }
10446
10447     if (m_flags & cGLReplayerVerboseMode)
10448     {
10449         tm.stop();
10450         vogl_printf("%s: Restore took %f secs\n", VOGL_METHOD_NAME, tm.get_elapsed_secs());
10451
10452         vogl_printf("%s: Finished restoring %u %s objects\n", VOGL_METHOD_NAME, n, get_gl_object_state_type_str(state_type));
10453     }
10454
10455     return cStatusOK;
10456 }
10457
10458 //----------------------------------------------------------------------------------------------------------------------
10459 // vogl_xfont_cache
10460 //----------------------------------------------------------------------------------------------------------------------
10461 class vogl_xfont_cache
10462 {
10463     VOGL_NO_COPY_OR_ASSIGNMENT_OP(vogl_xfont_cache);
10464
10465 public:
10466     vogl_xfont_cache(Display *dpy)
10467         : m_dpy(dpy)
10468     {
10469         VOGL_FUNC_TRACER
10470     }
10471
10472     ~vogl_xfont_cache()
10473     {
10474         VOGL_FUNC_TRACER
10475
10476         clear();
10477     }
10478
10479     void clear()
10480     {
10481         VOGL_FUNC_TRACER
10482
10483         for (xfont_map::iterator it = m_xfonts.begin(); it != m_xfonts.end(); ++it)
10484             XFreeFont(m_dpy, it->second);
10485         m_xfonts.clear();
10486     }
10487
10488     XFontStruct *get_or_create(const char *pName)
10489     {
10490         VOGL_FUNC_TRACER
10491
10492         XFontStruct **ppXFont = m_xfonts.find_value(pName);
10493         if (ppXFont)
10494             return *ppXFont;
10495
10496         XFontStruct *pXFont = XLoadQueryFont(m_dpy, pName);
10497         if (pXFont)
10498             m_xfonts.insert(pName, pXFont);
10499
10500         return pXFont;
10501     }
10502
10503 private:
10504     Display *m_dpy;
10505
10506     typedef vogl::map<dynamic_string, XFontStruct *> xfont_map;
10507     xfont_map m_xfonts;
10508 };
10509
10510 //----------------------------------------------------------------------------------------------------------------------
10511 // vogl_replayer::restore_display_lists
10512 //----------------------------------------------------------------------------------------------------------------------
10513 vogl_gl_replayer::status_t vogl_gl_replayer::restore_display_lists(vogl_handle_remapper &trace_to_replay_remapper, const vogl_gl_state_snapshot &snapshot, const vogl_context_snapshot &context_snapshot)
10514 {
10515     VOGL_FUNC_TRACER
10516
10517     VOGL_NOTE_UNUSED(trace_to_replay_remapper);
10518     VOGL_NOTE_UNUSED(snapshot);
10519
10520     VOGL_ASSERT(m_cur_trace_context);
10521
10522     check_gl_error();
10523
10524     const vogl_display_list_state &disp_lists = context_snapshot.get_display_list_state();
10525
10526     if (!disp_lists.size())
10527         return cStatusOK;
10528
10529     vogl_message_printf("%s: Recreating %u display lists\n", VOGL_METHOD_NAME, disp_lists.get_display_list_map().size());
10530
10531     vogl_xfont_cache xfont_cache(m_pWindow->get_display());
10532
10533     const vogl_display_list_map &disp_list_map = disp_lists.get_display_list_map();
10534
10535     for (vogl_display_list_map::const_iterator it = disp_list_map.begin(); it != disp_list_map.end(); ++it)
10536     {
10537         GLuint trace_handle = it->first;
10538         const vogl_display_list &disp_list = it->second;
10539
10540         if (!trace_handle)
10541         {
10542             VOGL_ASSERT_ALWAYS;
10543             continue;
10544         }
10545
10546         GLuint replay_handle = GL_ENTRYPOINT(glGenLists)(1);
10547         if (check_gl_error() || !replay_handle)
10548             goto handle_failure;
10549
10550         if (disp_list.is_valid())
10551         {
10552             if (disp_list.is_xfont())
10553             {
10554                 XFontStruct *pXFont = xfont_cache.get_or_create(disp_list.get_xfont_name().get_ptr());
10555                 if (!pXFont)
10556                 {
10557                     vogl_error_printf("%s: Unable to load XFont \"%s\", can't recreate trace display list %u!\n", VOGL_METHOD_NAME, disp_list.get_xfont_name().get_ptr(), trace_handle);
10558                 }
10559                 else
10560                 {
10561                     GL_ENTRYPOINT(glXUseXFont)(pXFont->fid, disp_list.get_xfont_glyph(), 1, replay_handle);
10562                 }
10563             }
10564             else
10565             {
10566                 GL_ENTRYPOINT(glNewList)(replay_handle, GL_COMPILE);
10567
10568                 if (check_gl_error() || !replay_handle)
10569                 {
10570                     GL_ENTRYPOINT(glDeleteLists)(replay_handle, 1);
10571                     check_gl_error();
10572
10573                     goto handle_failure;
10574                 }
10575
10576                 const vogl_trace_packet_array &packets = disp_list.get_packets();
10577
10578                 for (uint packet_index = 0; packet_index < packets.size(); packet_index++)
10579                 {
10580                     if (packets.get_packet_type(packet_index) != cTSPTGLEntrypoint)
10581                     {
10582                         vogl_error_printf("%s: Unexpected display list packet type %u, packet index %u, can't fully recreate trace display list %u!\n", VOGL_METHOD_NAME, packets.get_packet_type(packet_index), packet_index, trace_handle);
10583                         continue;
10584                     }
10585
10586                     const uint8_vec &packet_buf = packets.get_packet_buf(packet_index);
10587
10588                     if (!m_temp2_gl_packet.deserialize(packet_buf, true))
10589                     {
10590                         vogl_error_printf("%s: Failed deserializing display list at packet index %u, can't fully recreate trace display list %u!\n", VOGL_METHOD_NAME, packet_index, trace_handle);
10591                         continue;
10592                     }
10593
10594                     vogl_trace_gl_entrypoint_packet &gl_entrypoint_packet = m_temp2_gl_packet.get_entrypoint_packet();
10595
10596                     gl_entrypoint_packet.m_context_handle = m_cur_trace_context;
10597
10598                     if (m_flags & cGLReplayerDebugMode)
10599                         dump_trace_gl_packet_debug_info(gl_entrypoint_packet);
10600
10601                     int64_t prev_parsed_call_counter = m_last_parsed_call_counter;
10602                     int64_t prev_processed_call_counter = m_last_processed_call_counter;
10603                     m_last_parsed_call_counter = gl_entrypoint_packet.m_call_counter;
10604                     m_last_processed_call_counter = gl_entrypoint_packet.m_call_counter;
10605                     bool prev_at_frame_boundary = m_at_frame_boundary;
10606
10607                     const vogl_trace_packet *pPrev_gl_packet = m_pCur_gl_packet;
10608
10609                     m_pCur_gl_packet = &m_temp2_gl_packet;
10610
10611                     vogl_gl_replayer::status_t status = process_gl_entrypoint_packet_internal(m_temp2_gl_packet);
10612
10613                     m_pCur_gl_packet = pPrev_gl_packet;
10614
10615                     m_last_parsed_call_counter = prev_parsed_call_counter;
10616                     m_last_processed_call_counter = prev_processed_call_counter;
10617                     m_at_frame_boundary = prev_at_frame_boundary;
10618
10619                     if (status != cStatusOK)
10620                     {
10621                         vogl_error_printf("%s: Failed recreating display list at packet index %u, can't fully recreate trace display list %u!\n", VOGL_METHOD_NAME, packet_index, trace_handle);
10622                         continue;
10623                     }
10624                 }
10625
10626                 // TODO: Set context state because we're currently generating a display list!
10627                 if (disp_list.is_generating())
10628                 {
10629                     VOGL_ASSERT_ALWAYS;
10630                 }
10631
10632                 GL_ENTRYPOINT(glEndList)();
10633                 check_gl_error();
10634             }
10635         }
10636
10637         get_shared_state()->m_lists.insert(trace_handle, replay_handle);
10638
10639         if (!get_shared_state()->m_shadow_state.m_display_lists.define_list(trace_handle, replay_handle, disp_list))
10640         {
10641             vogl_error_printf("%s: Failed adding display list trace handle %u GL handle %u into display list shadow!\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
10642         }
10643     }
10644
10645     check_gl_error();
10646
10647     vogl_message_printf("%s: Done recreating display lists\n", VOGL_METHOD_NAME);
10648
10649     return cStatusOK;
10650
10651 handle_failure:
10652     return cStatusHardFailure;
10653 }
10654
10655 //----------------------------------------------------------------------------------------------------------------------
10656 // vogl_replayer::restore_general_state
10657 //----------------------------------------------------------------------------------------------------------------------
10658 vogl_gl_replayer::status_t vogl_gl_replayer::restore_general_state(vogl_handle_remapper &trace_to_replay_remapper, const vogl_gl_state_snapshot &snapshot, const vogl_context_snapshot &context_snapshot)
10659 {
10660     VOGL_FUNC_TRACER
10661
10662     VOGL_NOTE_UNUSED(snapshot);
10663
10664     vogl_general_context_state::vogl_persistent_restore_state persistent_restore_state;
10665     persistent_restore_state.m_pSelect_buffer = &m_pCur_context_state->m_select_buffer;
10666
10667     if (!context_snapshot.get_general_state().restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper, persistent_restore_state))
10668         return cStatusHardFailure;
10669
10670     if (!m_pCur_context_state->m_context_info.is_core_profile())
10671     {
10672         if (context_snapshot.get_texenv_state().is_valid())
10673         {
10674             if (!context_snapshot.get_texenv_state().restore(m_pCur_context_state->m_context_info))
10675                 return cStatusHardFailure;
10676         }
10677
10678         if (context_snapshot.get_material_state().is_valid())
10679         {
10680             if (!context_snapshot.get_material_state().restore(m_pCur_context_state->m_context_info))
10681                 return cStatusHardFailure;
10682         }
10683
10684         if (context_snapshot.get_light_state().is_valid())
10685         {
10686             if (!context_snapshot.get_light_state().restore(m_pCur_context_state->m_context_info))
10687                 return cStatusHardFailure;
10688         }
10689
10690         if (context_snapshot.get_matrix_state().is_valid())
10691         {
10692             if (!context_snapshot.get_matrix_state().restore(m_pCur_context_state->m_context_info))
10693                 return cStatusHardFailure;
10694         }
10695
10696         if (context_snapshot.get_polygon_stipple_state().is_valid())
10697         {
10698             if (!context_snapshot.get_polygon_stipple_state().restore(m_pCur_context_state->m_context_info))
10699                 return cStatusHardFailure;
10700         }
10701
10702         if (context_snapshot.get_arb_program_environment_state().is_valid())
10703         {
10704             if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_vertex_program"))
10705             {
10706                 if (!context_snapshot.get_arb_program_environment_state().restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper))
10707                     return cStatusHardFailure;
10708             }
10709             else
10710             {
10711                 vogl_error_printf("%s: Unable to restore ARB program environment state to context because it does not support the \"GL_ARB_vertex_program\" extension\n", VOGL_METHOD_NAME);
10712             }
10713         }
10714     }
10715
10716     if (context_snapshot.get_current_vertex_attrib_state().is_valid())
10717     {
10718         if (!context_snapshot.get_current_vertex_attrib_state().restore(m_pCur_context_state->m_context_info))
10719             return cStatusHardFailure;
10720     }
10721
10722     return cStatusOK;
10723 }
10724
10725 //----------------------------------------------------------------------------------------------------------------------
10726 // vogl_replayer::validate_program_and_shader_handle_tables
10727 //----------------------------------------------------------------------------------------------------------------------
10728 bool vogl_gl_replayer::validate_program_and_shader_handle_tables()
10729 {
10730     VOGL_FUNC_TRACER
10731
10732     if (!m_pCur_context_state)
10733         return true;
10734
10735     if (!get_shared_state()->m_shadow_state.m_objs.check())
10736         vogl_error_printf("%s: Object handle tracker failed validation!\n", VOGL_METHOD_NAME);
10737
10738     uint_vec replay_handles;
10739     get_shared_state()->m_shadow_state.m_objs.get_inv_handles(replay_handles);
10740
10741     for (uint i = 0; i < replay_handles.size(); i++)
10742     {
10743         GLuint replay_handle = replay_handles[i];
10744         GLuint trace_handle = replay_handle;
10745         bool map_succeeded = get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle, trace_handle);
10746         VOGL_ASSERT(map_succeeded);
10747         VOGL_NOTE_UNUSED(map_succeeded);
10748
10749         GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle);
10750         VOGL_ASSERT(target == get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle));
10751
10752         if (target == VOGL_PROGRAM_OBJECT)
10753         {
10754             if (!GL_ENTRYPOINT(glIsProgram)(replay_handle))
10755             {
10756                 vogl_error_printf("%s: GL handle %u is being tracked, but glIsProgram() reports the handle is not a program\n", VOGL_METHOD_NAME, replay_handle);
10757             }
10758
10759             if (!get_shared_state()->m_glsl_program_hash_map.contains(trace_handle))
10760             {
10761                 vogl_error_printf("%s: Found program at trace handle %u GL handle %u, but the GLSL program hash map doesn't contain an entry for this object!\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
10762             }
10763         }
10764         else if (target == VOGL_SHADER_OBJECT)
10765         {
10766             if (!GL_ENTRYPOINT(glIsShader)(replay_handle))
10767             {
10768                 vogl_error_printf("%s: GL handle %u is being tracked, but glIsShader() reports the handle is not a program\n", VOGL_METHOD_NAME, replay_handle);
10769             }
10770         }
10771         else
10772         {
10773             VOGL_ASSERT_ALWAYS;
10774         }
10775     }
10776
10777     return true;
10778 }
10779
10780 //----------------------------------------------------------------------------------------------------------------------
10781 // vogl_replayer::validate_textures
10782 //----------------------------------------------------------------------------------------------------------------------
10783 bool vogl_gl_replayer::validate_textures()
10784 {
10785     VOGL_FUNC_TRACER
10786
10787     if (!m_pCur_context_state)
10788         return true;
10789
10790     if (!get_shared_state()->m_shadow_state.m_textures.check())
10791         vogl_error_printf("%s: Texture handle tracker failed validation!\n", VOGL_METHOD_NAME);
10792
10793     for (uint replay_handle = 1; replay_handle <= 0xFFFFU; replay_handle++)
10794     {
10795         bool is_tex = GL_ENTRYPOINT(glIsTexture)(replay_handle) != 0;
10796
10797         bool found_in_shadow = get_shared_state()->m_shadow_state.m_textures.contains_inv(replay_handle);
10798
10799         if (!is_tex)
10800         {
10801             if (found_in_shadow)
10802             {
10803                 GLuint trace_handle = 0;
10804                 get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_handle, trace_handle);
10805                 vogl_debug_printf("%s: Texture %u is not a name, but it has a valid mapping to trace handle %u\n", VOGL_METHOD_NAME, replay_handle, trace_handle);
10806             }
10807         }
10808         else
10809         {
10810             if (!found_in_shadow)
10811             {
10812                 vogl_debug_printf("%s: Texture %u is a valid name, but it does have a mapping to a trace handle!\n", VOGL_METHOD_NAME, replay_handle);
10813             }
10814         }
10815     }
10816
10817     return true;
10818 }
10819
10820 //----------------------------------------------------------------------------------------------------------------------
10821 // vogl_replayer::update_context_shadows
10822 //----------------------------------------------------------------------------------------------------------------------
10823 vogl_gl_replayer::status_t vogl_gl_replayer::update_context_shadows(vogl_handle_remapper &trace_to_replay_remapper, const vogl_gl_state_snapshot &snapshot, const vogl_context_snapshot &context_snapshot)
10824 {
10825     VOGL_FUNC_TRACER
10826
10827     VOGL_NOTE_UNUSED(snapshot);
10828     VOGL_NOTE_UNUSED(context_snapshot);
10829     VOGL_NOTE_UNUSED(trace_to_replay_remapper);
10830
10831     check_gl_error();
10832
10833     // Make sure shadow is good
10834     GLint actual_current_replay_program = 0;
10835     GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &actual_current_replay_program);
10836     check_gl_error();
10837
10838     m_pCur_context_state->m_cur_replay_program = actual_current_replay_program;
10839     if (!actual_current_replay_program)
10840         m_pCur_context_state->m_cur_trace_program = 0;
10841     else
10842     {
10843         GLuint trace_handle = actual_current_replay_program;
10844         if (!get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(actual_current_replay_program, trace_handle))
10845         {
10846             process_entrypoint_error("%s: Failed finding restored GL shader %u in program/shader object handle hashmap\n", VOGL_METHOD_NAME, actual_current_replay_program);
10847
10848             m_pCur_context_state->m_cur_replay_program = 0;
10849             m_pCur_context_state->m_cur_trace_program = 0;
10850         }
10851         else
10852         {
10853             m_pCur_context_state->m_cur_trace_program = trace_handle;
10854         }
10855     }
10856
10857     check_program_binding_shadow();
10858
10859     return cStatusOK;
10860 }
10861
10862 //----------------------------------------------------------------------------------------------------------------------
10863 // vogl_replayer::handle_marked_for_deleted_objects
10864 //----------------------------------------------------------------------------------------------------------------------
10865 void vogl_gl_replayer::handle_marked_for_deleted_objects(vogl_const_gl_object_state_ptr_vec &objects_to_delete, trace_to_replay_handle_remapper &trace_to_replay_remapper)
10866 {
10867     VOGL_FUNC_TRACER
10868
10869     if (m_flags & cGLReplayerVerboseMode)
10870     {
10871         vogl_debug_printf("%s: %u program/shader objects where marked as deleted\n", VOGL_METHOD_NAME, objects_to_delete.size());
10872     }
10873
10874     for (uint i = 0; i < objects_to_delete.size(); i++)
10875     {
10876         const vogl_gl_object_state *pState_obj = objects_to_delete[i];
10877
10878         GLuint64 trace_handle = pState_obj->get_snapshot_handle();
10879         GLuint64 restore_handle = trace_to_replay_remapper.remap_handle(pState_obj->get_handle_namespace(), pState_obj->get_snapshot_handle());
10880
10881         if (m_flags & cGLReplayerVerboseMode)
10882         {
10883             // This should be a rare/exception case so let's try to be a little paranoid.
10884             vogl_debug_printf("%s: Snapshot object type %s trace handle 0x%" PRIX64 " restore handle 0x%" PRIX64 ", was marked as deleted, deleting object after restoring (object should still be referenced by state in the GL context)\n", VOGL_METHOD_NAME,
10885                              get_gl_object_state_type_str(pState_obj->get_type()), (uint64_t)trace_handle, (uint64_t)restore_handle);
10886         }
10887
10888         GLboolean object_is_still_a_name = true;
10889
10890         switch (pState_obj->get_type())
10891         {
10892             case cGLSTProgram:
10893             {
10894                 handle_delete_program(static_cast<GLuint>(trace_handle));
10895
10896                 object_is_still_a_name = GL_ENTRYPOINT(glIsProgram)(static_cast<GLuint>(restore_handle));
10897
10898                 break;
10899             }
10900             case cGLSTShader:
10901             {
10902                 handle_delete_shader(static_cast<GLuint>(trace_handle));
10903
10904                 object_is_still_a_name = GL_ENTRYPOINT(glIsShader)(static_cast<GLuint>(restore_handle));
10905
10906                 break;
10907             }
10908             default:
10909             {
10910                 VOGL_ASSERT_ALWAYS;
10911                 break;
10912             }
10913         }
10914
10915         // "A program object marked for deletion with glDeleteProgram but still in use as part of current rendering state is still considered a program object and glIsProgram will return GL_TRUE."
10916         // Same for shaders.
10917         if (!object_is_still_a_name)
10918         {
10919             vogl_debug_printf("%s: Snapshot object type %s trace handle 0x%" PRIX64 " restore handle 0x%" PRIX64 ", was marked as deleted, then deleted after a full state restore, but the object which should still be referenced by state in the GL context fails the glIsProgram()/glIsShader()/etc. test\n", VOGL_METHOD_NAME,
10920                              get_gl_object_state_type_str(pState_obj->get_type()), (uint64_t)trace_handle, (uint64_t)restore_handle);
10921         }
10922     }
10923 }
10924
10925 //----------------------------------------------------------------------------------------------------------------------
10926 // vogl_replayer::begin_applying_snapshot
10927 // Takes ownership (even on errors) when delete_snapshot_after_applying is true.
10928 //----------------------------------------------------------------------------------------------------------------------
10929 vogl_gl_replayer::status_t vogl_gl_replayer::begin_applying_snapshot(const vogl_gl_state_snapshot *pSnapshot, bool delete_snapshot_after_applying)
10930 {
10931     VOGL_FUNC_TRACER
10932
10933     if (!pSnapshot->is_valid())
10934     {
10935         if (delete_snapshot_after_applying)
10936             vogl_delete(const_cast<vogl_gl_state_snapshot *>(pSnapshot));
10937
10938         return cStatusHardFailure;
10939     }
10940
10941     reset_state();
10942
10943     m_pPending_snapshot = pSnapshot;
10944     m_delete_pending_snapshot_after_applying = delete_snapshot_after_applying;
10945
10946     m_frame_index = pSnapshot->get_frame_index();
10947     m_last_parsed_call_counter = pSnapshot->get_gl_call_counter();
10948     m_last_processed_call_counter = pSnapshot->get_gl_call_counter();
10949     m_at_frame_boundary = false;
10950
10951     if (!(m_flags & cGLReplayerLockWindowDimensions))
10952     {
10953         return trigger_pending_window_resize(pSnapshot->get_window_width(), pSnapshot->get_window_height());
10954     }
10955
10956     return process_applying_pending_snapshot();
10957 }
10958
10959 //----------------------------------------------------------------------------------------------------------------------
10960 // vogl_replayer::restore_context
10961 //----------------------------------------------------------------------------------------------------------------------
10962 vogl_gl_replayer::status_t vogl_gl_replayer::restore_context(vogl_handle_remapper &trace_to_replay_remapper, const vogl_gl_state_snapshot &snapshot, const vogl_context_snapshot &context_snapshot)
10963 {
10964     VOGL_FUNC_TRACER
10965
10966     VOGL_NOTE_UNUSED(trace_to_replay_remapper);
10967     VOGL_NOTE_UNUSED(snapshot);
10968
10969     // TODO: This always creates with attribs, also need to support plain glXCreateContext()
10970
10971     Display *dpy = m_pWindow->get_display();
10972     GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
10973
10974     vogl_trace_context_ptr_value trace_share_context = context_snapshot.get_context_desc().get_trace_share_context();
10975
10976     GLXContext replay_share_context = remap_context(trace_share_context);
10977     if ((trace_share_context) && (!replay_share_context))
10978     {
10979         vogl_error_printf("%s: Failed remapping trace share context handle 0x%" PRIx64 " to replay context!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
10980         return cStatusHardFailure;
10981     }
10982
10983     GLboolean direct = context_snapshot.get_context_desc().get_direct();
10984
10985     vogl_trace_context_ptr_value trace_context = context_snapshot.get_context_desc().get_trace_context();
10986
10987     status_t status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct,
10988                                              context_snapshot.get_context_desc().get_attribs().get_vec().get_ptr(),
10989                                              context_snapshot.get_context_desc().get_attribs().get_vec().size(), true);
10990     if (status != cStatusOK)
10991     {
10992         vogl_error_printf("%s: Failed creating new context\n", VOGL_METHOD_NAME);
10993         return status;
10994     }
10995
10996     // Has this context ever been made current?
10997     if (context_snapshot.get_context_info().is_valid())
10998     {
10999         context_state *pContext_state = get_trace_context_state(trace_context);
11000         if (!pContext_state)
11001         {
11002             vogl_error_printf("%s: Failed finding replay context current\n", VOGL_METHOD_NAME);
11003             return cStatusHardFailure;
11004         }
11005
11006         GLXContext replay_context = pContext_state->m_replay_context;
11007         if (!replay_context)
11008         {
11009             vogl_error_printf("%s: Failed finding replay context current\n", VOGL_METHOD_NAME);
11010             return cStatusHardFailure;
11011         }
11012
11013         GLXDrawable drawable = m_pWindow->get_xwindow();
11014
11015         Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
11016         if (!result)
11017         {
11018             vogl_error_printf("%s: Failed making context current\n", VOGL_METHOD_NAME);
11019             return cStatusHardFailure;
11020         }
11021
11022         m_cur_trace_context = trace_context;
11023         m_cur_replay_context = replay_context;
11024         m_pCur_context_state = pContext_state;
11025
11026         if (!handle_context_made_current())
11027             return cStatusHardFailure;
11028     }
11029
11030     return cStatusOK;
11031 }
11032
11033 //----------------------------------------------------------------------------------------------------------------------
11034 // vogl_replayer::process_applying_pending_snapshot
11035 //----------------------------------------------------------------------------------------------------------------------
11036 vogl_gl_replayer::status_t vogl_gl_replayer::process_applying_pending_snapshot()
11037 {
11038     VOGL_FUNC_TRACER
11039
11040     if (!m_pPending_snapshot)
11041         return cStatusOK;
11042
11043     timed_scope ts(VOGL_METHOD_NAME);
11044
11045     const vogl_gl_state_snapshot &snapshot = *m_pPending_snapshot;
11046
11047     trace_to_replay_handle_remapper trace_to_replay_remapper(*this);
11048
11049     m_frame_index = snapshot.get_frame_index();
11050     m_last_parsed_call_counter = snapshot.get_gl_call_counter();
11051     m_last_processed_call_counter = snapshot.get_gl_call_counter();
11052     m_at_frame_boundary = snapshot.get_at_frame_boundary();
11053
11054     // Ensure the client side array bufs are large enough (we don't care about the actual ptr values).
11055     for (uint i = 0; i < snapshot.get_client_side_vertex_attrib_ptrs().size(); i++)
11056         m_client_side_vertex_attrib_data[i].resize(snapshot.get_client_side_vertex_attrib_ptrs()[i].m_size);
11057
11058     for (uint i = 0; i < snapshot.get_client_side_array_ptrs().size(); i++)
11059         m_client_side_array_data[i].resize(snapshot.get_client_side_array_ptrs()[i].m_size);
11060
11061     for (uint i = 0; i < snapshot.get_client_side_texcoord_ptrs().size(); i++)
11062         m_client_side_texcoord_data[i].resize(snapshot.get_client_side_texcoord_ptrs()[i].m_size);
11063
11064     const vogl_context_snapshot_ptr_vec &context_ptrs = snapshot.get_contexts();
11065
11066     vogl_context_snapshot_ptr_vec restore_context_ptrs(snapshot.get_contexts());
11067     vogl::vector<vogl_const_gl_object_state_ptr_vec> objects_to_delete_vec(context_ptrs.size());
11068
11069     status_t status = cStatusOK;
11070     uint total_contexts_restored = 0;
11071     bool restored_default_framebuffer = false;
11072
11073     for (;;)
11074     {
11075         uint num_contexts_restored_in_this_pass = 0;
11076
11077         for (uint context_index = 0; context_index < restore_context_ptrs.size(); context_index++)
11078         {
11079             if (!restore_context_ptrs[context_index])
11080                 continue;
11081
11082             const vogl_context_snapshot &context_state = *restore_context_ptrs[context_index];
11083
11084             if (context_state.get_context_desc().get_trace_share_context())
11085             {
11086                 // Don't restore this context if its sharelist context hasn't been restored yet
11087                 if (!remap_context(context_state.get_context_desc().get_trace_share_context()))
11088                     continue;
11089             }
11090
11091             status = restore_context(trace_to_replay_remapper, snapshot, context_state);
11092             if (status != cStatusOK)
11093                 goto handle_error;
11094
11095             // Has this context ever been made current?
11096             if (context_state.get_context_info().is_valid())
11097             {
11098                 // Keep this in sync with vogl_gl_object_state_type (the order doesn't need to match the enum, but be sure to restore leaf GL objects first!)
11099                 const vogl_gl_object_state_type s_object_type_restore_order[] = { cGLSTBuffer, cGLSTSampler, cGLSTQuery, cGLSTRenderbuffer, cGLSTTexture, cGLSTFramebuffer, cGLSTVertexArray, cGLSTShader, cGLSTProgram, cGLSTSync, cGLSTARBProgram };
11100                 VOGL_ASSUME(VOGL_ARRAY_SIZE(s_object_type_restore_order) == (cGLSTTotalTypes - 1));
11101
11102                 if (m_flags & cGLReplayerLowLevelDebugMode)
11103                 {
11104                     if (!validate_textures())
11105                         vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11106                 }
11107
11108                 vogl_const_gl_object_state_ptr_vec &objects_to_delete = objects_to_delete_vec[context_index];
11109
11110                 for (uint i = 0; i < VOGL_ARRAY_SIZE(s_object_type_restore_order); i++)
11111                 {
11112                     status = restore_objects(trace_to_replay_remapper, snapshot, context_state, s_object_type_restore_order[i], objects_to_delete);
11113                     if (status != cStatusOK)
11114                         goto handle_error;
11115
11116                     if (m_flags & cGLReplayerLowLevelDebugMode)
11117                     {
11118                         if (!validate_program_and_shader_handle_tables())
11119                             vogl_error_printf("%s: Program/shader handle table validation failed!\n", VOGL_METHOD_NAME);
11120
11121                         if (!validate_textures())
11122                             vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11123                     }
11124                 }
11125
11126                 if (m_flags & cGLReplayerLowLevelDebugMode)
11127                 {
11128                     if (!validate_textures())
11129                         vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11130                 }
11131
11132                 status = restore_display_lists(trace_to_replay_remapper, snapshot, context_state);
11133                 if (status != cStatusOK)
11134                     goto handle_error;
11135
11136                 // Restore default framebuffer
11137                 if ((!restored_default_framebuffer) && (snapshot.get_default_framebuffer().is_valid()))
11138                 {
11139                     restored_default_framebuffer = true;
11140
11141                     if (!snapshot.get_default_framebuffer().restore(m_pCur_context_state->m_context_info))
11142                     {
11143                         vogl_warning_printf("%s: Failed restoring default framebuffer!\n", VOGL_METHOD_NAME);
11144                     }
11145                 }
11146
11147                 // Beware: restore_general_state() will bind a bunch of stuff from the trace!
11148                 status = restore_general_state(trace_to_replay_remapper, snapshot, context_state);
11149                 if (status != cStatusOK)
11150                     goto handle_error;
11151
11152                 status = update_context_shadows(trace_to_replay_remapper, snapshot, context_state);
11153                 if (status != cStatusOK)
11154                     goto handle_error;
11155
11156                 if (m_flags & cGLReplayerLowLevelDebugMode)
11157                 {
11158                     if (!validate_program_and_shader_handle_tables())
11159                         vogl_error_printf("%s: Program/shader handle table validation failed!\n", VOGL_METHOD_NAME);
11160
11161                     if (!validate_textures())
11162                         vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11163                 }
11164             }
11165
11166             num_contexts_restored_in_this_pass++;
11167
11168             total_contexts_restored++;
11169
11170             restore_context_ptrs[context_index] = NULL;
11171         }
11172
11173         if (!num_contexts_restored_in_this_pass)
11174             break;
11175     }
11176
11177     if (total_contexts_restored != snapshot.get_contexts().size())
11178     {
11179         vogl_error_printf("%s: Failed satisfying sharelist dependency during context restoration\n", VOGL_METHOD_NAME);
11180         goto handle_error;
11181     }
11182
11183     for (uint context_index = 0; context_index < context_ptrs.size(); context_index++)
11184     {
11185         const vogl_context_snapshot &context_state = *context_ptrs[context_index];
11186
11187         if (!context_state.get_context_info().is_valid())
11188             continue;
11189
11190         status_t status = switch_contexts(context_state.get_context_desc().get_trace_context());
11191         if (status != cStatusOK)
11192         {
11193             vogl_error_printf("%s: Failed switching to trace context 0x%" PRIX64 ", capture failed\n", VOGL_METHOD_NAME, cast_val_to_uint64(context_state.get_context_desc().get_trace_context()));
11194             goto handle_error;
11195         }
11196
11197         vogl_const_gl_object_state_ptr_vec &objects_to_delete = objects_to_delete_vec[context_index];
11198
11199         handle_marked_for_deleted_objects(objects_to_delete, trace_to_replay_remapper);
11200     }
11201
11202     destroy_pending_snapshot();
11203
11204     return cStatusOK;
11205
11206 handle_error:
11207
11208     reset_state();
11209
11210     return status;
11211 }
11212
11213 //----------------------------------------------------------------------------------------------------------------------
11214 // vogl_gl_replayer::write_trim_file_internal
11215 //----------------------------------------------------------------------------------------------------------------------
11216 bool vogl_gl_replayer::write_trim_file_internal(vogl_trace_packet_array &trim_packets, const dynamic_string &trim_filename, vogl_trace_file_reader &trace_reader, bool optimize_snapshot, dynamic_string *pSnapshot_id)
11217 {
11218     // Open the output trace
11219     // TODO: This pretty much ignores the ctypes packet, and uses the one based off the ptr size in the header. The ctypes stuff needs to be refactored, storing it in an explicit packet is bad.
11220     const vogl_ctypes &trace_gl_ctypes = get_trace_gl_ctypes();
11221
11222     vogl_trace_packet trace_packet(&trace_gl_ctypes);
11223
11224     // TODO: This seems like WAY too much work! Move the snapshot to the beginning of the trace, in the header!
11225     bool found_state_snapshot = false;
11226     dynamic_string binary_snapshot_id, text_snapshot_id;
11227
11228     bool is_at_start_of_trace = false;
11229     VOGL_NOTE_UNUSED(is_at_start_of_trace);
11230
11231     int demarcation_packet_index = -1;
11232     for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11233     {
11234         const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11235         if (packet_type != cTSPTGLEntrypoint)
11236             continue;
11237
11238         const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11239
11240         const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(packet_index);
11241         if (pGL_packet->m_entrypoint_id != VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
11242             continue;
11243
11244         if (!trace_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
11245         {
11246             console::error("%s: Failed parsing glInternalTraceCommandRAD packet\n", VOGL_FUNCTION_NAME);
11247             return false;
11248         }
11249
11250         GLuint cmd = trace_packet.get_param_value<GLuint>(0);
11251         if (cmd == cITCRDemarcation)
11252         {
11253             is_at_start_of_trace = true;
11254             demarcation_packet_index = packet_index;
11255         }
11256         else if (cmd == cITCRKeyValueMap)
11257         {
11258             key_value_map &kvm = trace_packet.get_key_value_map();
11259
11260             dynamic_string cmd_type(kvm.get_string("command_type"));
11261
11262             if (cmd_type == "state_snapshot")
11263             {
11264                 found_state_snapshot = true;
11265
11266                 text_snapshot_id = kvm.get_string("id");
11267                 binary_snapshot_id = kvm.get_string("binary_id");
11268             }
11269         }
11270     }
11271
11272     vogl_trace_file_writer trace_writer(&trace_gl_ctypes);
11273     if (!trace_writer.open(trim_filename.get_ptr(), NULL, true, false, m_trace_pointer_size_in_bytes))
11274     {
11275         console::error("%s: Failed creating trimmed trace file \"%s\"!\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11276         return false;
11277     }
11278
11279     if (found_state_snapshot)
11280     {
11281         // Copy over the source trace's archive (it contains the snapshot, along with any files it refers to).
11282         if (trace_reader.get_archive_blob_manager().is_initialized())
11283         {
11284             dynamic_string_array blob_files(trace_reader.get_archive_blob_manager().enumerate());
11285             for (uint i = 0; i < blob_files.size(); i++)
11286             {
11287                 if ((blob_files[i].is_empty()) || (blob_files[i] == VOGL_TRACE_ARCHIVE_FRAME_FILE_OFFSETS_FILENAME))
11288                     continue;
11289
11290                 vogl_message_printf("Adding blob file %s to output trace archive\n", blob_files[i].get_ptr());
11291
11292                 if (!trace_writer.get_trace_archive()->copy_file(trace_reader.get_archive_blob_manager(), blob_files[i], blob_files[i]).has_content())
11293                 {
11294                     vogl_error_printf("%s: Failed copying blob data for file \"%s\" to output trace archive!\n", VOGL_FUNCTION_NAME, blob_files[i].get_ptr());
11295                     return false;
11296                 }
11297             }
11298         }
11299     }
11300     else
11301     {
11302         // Copy over the source trace's backtrace map, machine info, etc. files.
11303         if (trace_reader.get_archive_blob_manager().is_initialized())
11304         {
11305             // compiler_info.json
11306             trace_writer.get_trace_archive()->copy_file(trace_reader.get_archive_blob_manager(), VOGL_TRACE_ARCHIVE_COMPILER_INFO_FILENAME, VOGL_TRACE_ARCHIVE_COMPILER_INFO_FILENAME);
11307             // machine_info.json
11308             trace_writer.get_trace_archive()->copy_file(trace_reader.get_archive_blob_manager(), VOGL_TRACE_ARCHIVE_MACHINE_INFO_FILENAME, VOGL_TRACE_ARCHIVE_MACHINE_INFO_FILENAME);
11309             // backtrace_map_syms.json
11310             trace_writer.get_trace_archive()->copy_file(trace_reader.get_archive_blob_manager(), VOGL_TRACE_ARCHIVE_BACKTRACE_MAP_SYMS_FILENAME, VOGL_TRACE_ARCHIVE_BACKTRACE_MAP_SYMS_FILENAME);
11311             // backtrace_map_addrs.json
11312             trace_writer.get_trace_archive()->copy_file(trace_reader.get_archive_blob_manager(), VOGL_TRACE_ARCHIVE_BACKTRACE_MAP_ADDRS_FILENAME, VOGL_TRACE_ARCHIVE_BACKTRACE_MAP_ADDRS_FILENAME);
11313         }
11314
11315         vogl_unique_ptr<vogl_gl_state_snapshot> pTrim_snapshot(snapshot_state(&trim_packets, optimize_snapshot));
11316
11317         if (!pTrim_snapshot.get())
11318         {
11319             console::error("%s: Failed creating replayer GL snapshot!\n", VOGL_FUNCTION_NAME);
11320             return false;
11321         }
11322
11323         pTrim_snapshot->set_frame_index(0);
11324
11325         json_document doc;
11326         if (!pTrim_snapshot->serialize(*doc.get_root(), *trace_writer.get_trace_archive(), &trace_gl_ctypes))
11327         {
11328             console::error("%s: Failed serializing GL state snapshot!\n", VOGL_FUNCTION_NAME);
11329             trace_writer.close();
11330             file_utils::delete_file(trim_filename.get_ptr());
11331             return false;
11332         }
11333
11334         vogl::vector<char> snapshot_data;
11335         doc.serialize(snapshot_data, true, 0, false);
11336
11337         uint8_vec binary_snapshot_data;
11338         doc.binary_serialize(binary_snapshot_data);
11339
11340         pTrim_snapshot.reset();
11341
11342         // Write the state_snapshot file to the trace archive
11343         dynamic_string snapshot_id(trace_writer.get_trace_archive()->add_buf_compute_unique_id(snapshot_data.get_ptr(), snapshot_data.size(), "state_snapshot", VOGL_TEXT_JSON_EXTENSION));
11344         if (snapshot_id.is_empty())
11345         {
11346             console::error("%s: Failed adding GL snapshot file to output blob manager!\n", VOGL_FUNCTION_NAME);
11347             trace_writer.close();
11348             file_utils::delete_file(trim_filename.get_ptr());
11349             return false;
11350         }
11351
11352         if (pSnapshot_id)
11353             *pSnapshot_id = snapshot_id;
11354
11355         snapshot_data.clear();
11356
11357         // Write the binary_state_snapshot file to the trace archive
11358         dynamic_string binary_snapshot_id(trace_writer.get_trace_archive()->add_buf_compute_unique_id(binary_snapshot_data.get_ptr(), binary_snapshot_data.size(), "binary_state_snapshot", VOGL_BINARY_JSON_EXTENSION));
11359         if (binary_snapshot_id.is_empty())
11360         {
11361             console::error("%s: Failed adding binary GL snapshot file to output blob manager!\n", VOGL_FUNCTION_NAME);
11362             trace_writer.close();
11363             file_utils::delete_file(trim_filename.get_ptr());
11364             return false;
11365         }
11366
11367         binary_snapshot_data.clear();
11368
11369         key_value_map snapshot_key_value_map;
11370         snapshot_key_value_map.insert("command_type", "state_snapshot");
11371         snapshot_key_value_map.insert("id", snapshot_id);
11372         snapshot_key_value_map.insert("binary_id", binary_snapshot_id);
11373
11374         dynamic_stream snapshot_stream(0);
11375         if (!vogl_write_glInternalTraceCommandRAD(snapshot_stream, &trace_gl_ctypes, cITCRKeyValueMap, sizeof(snapshot_key_value_map), reinterpret_cast<const GLubyte *>(&snapshot_key_value_map)))
11376         {
11377             console::error("%s: Failed serializing snapshot packet!\n", VOGL_FUNCTION_NAME);
11378             trace_writer.close();
11379             file_utils::delete_file(trim_filename.get_ptr());
11380             return false;
11381         }
11382
11383         if (demarcation_packet_index >= 0)
11384         {
11385             trim_packets.insert(demarcation_packet_index, snapshot_stream.get_buf());
11386             demarcation_packet_index++;
11387         }
11388         else
11389         {
11390             dynamic_stream demarcation_stream(0);
11391             vogl_write_glInternalTraceCommandRAD(demarcation_stream, &trace_gl_ctypes, cITCRDemarcation, 0, NULL);
11392
11393             // Screw the ctypes packet, it's only used for debugging right now anyway.
11394             trim_packets.insert(0, snapshot_stream.get_buf());
11395             trim_packets.insert(1, demarcation_stream.get_buf());
11396         }
11397     }
11398
11399     for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11400     {
11401         const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11402
11403         const bool is_swap = trim_packets.is_swap_buffers_packet(packet_index);
11404
11405         const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11406         if (packet_type == cTSPTEOF)
11407             break;
11408         else if (packet_type != cTSPTGLEntrypoint)
11409         {
11410             VOGL_ASSERT_ALWAYS;
11411         }
11412
11413         if (!trace_writer.write_packet(packet_buf.get_ptr(), packet_buf.size(), is_swap))
11414         {
11415             console::error("%s: Failed writing trace packet to output trace file \"%s\"!\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11416             trace_writer.close();
11417             file_utils::delete_file(trim_filename.get_ptr());
11418             return false;
11419         }
11420     }
11421
11422     bool success = trace_writer.close();
11423     if (!success)
11424         console::error("%s: Failed closing wrote trim trace file \"%s\"\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11425     else
11426         console::message("%s: Successfully wrote trim trace file \"%s\"\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11427
11428     return success;
11429 }
11430
11431 //----------------------------------------------------------------------------------------------------------------------
11432 // vogl_gl_replayer::write_trim_file
11433 //----------------------------------------------------------------------------------------------------------------------
11434 bool vogl_gl_replayer::write_trim_file(uint flags, const dynamic_string &trim_filename, uint trim_len, vogl_trace_file_reader &trace_reader, dynamic_string *pSnapshot_id)
11435 {
11436     VOGL_FUNC_TRACER
11437
11438     if (!m_is_valid)
11439     {
11440         console::error("%s: Trace is not open\n", VOGL_METHOD_NAME);
11441         return false;
11442     }
11443
11444     bool from_start_of_frame = (flags & cWriteTrimFileFromStartOfFrame) != 0;
11445
11446     if ((!from_start_of_frame) || (!trim_len))
11447         flags &= ~cWriteTrimFileOptimizeSnapshot;
11448
11449     const uint trim_frame = static_cast<uint>(get_frame_index());
11450     const int64_t trim_call_counter = get_last_parsed_call_counter();
11451
11452     // Read the desired packets from the source trace file
11453     vogl_trace_packet_array trim_packets;
11454
11455     if ((trim_len) || (!trim_frame))
11456     {
11457         console::message("%s: Reading trim packets from source trace file\n", VOGL_FUNCTION_NAME);
11458
11459         uint frames_to_read = trim_len;
11460         if ((from_start_of_frame) && (!trim_frame) && (!trim_len))
11461             frames_to_read = 1;
11462
11463         uint actual_trim_len = 0;
11464         vogl_trace_file_reader::trace_file_reader_status_t read_packets_status = trace_reader.read_frame_packets(trim_frame, frames_to_read, trim_packets, actual_trim_len);
11465         if (read_packets_status == vogl_trace_file_reader::cFailed)
11466         {
11467             console::error("%s: Failed reading source trace file packets beginning at frame %u!\n", VOGL_FUNCTION_NAME, trim_frame);
11468             return false;
11469         }
11470
11471         if (actual_trim_len != frames_to_read)
11472         {
11473             console::warning("%s: Only able to read %u frames from trim file beginning at frame %u, not the requested %u\n", VOGL_FUNCTION_NAME, actual_trim_len, trim_frame, frames_to_read);
11474         }
11475
11476         if (from_start_of_frame)
11477         {
11478             console::message("%s: Read %u trim packets beginning at frame %u actual len %u from source trace file\n", VOGL_FUNCTION_NAME, trim_packets.size(), trim_frame, actual_trim_len);
11479
11480             if ((!trim_frame) && (!trim_len))
11481             {
11482                 // Special case: They want frame 0 with no packets, so be sure to copy any internal trace commands at the very beginning of the trace.
11483                 // TODO: Most of this will go away once we move the state snapshot into the trace archive.
11484
11485                 vogl_trace_packet_array new_trim_packets;
11486
11487                 vogl_trace_packet trace_packet(&get_trace_gl_ctypes());
11488
11489                 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11490                 {
11491                     const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11492                     if (packet_type != cTSPTGLEntrypoint)
11493                         break;
11494
11495                     const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11496
11497                     const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(packet_index);
11498                     if (pGL_packet->m_entrypoint_id != VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
11499                         break;
11500
11501                     if (!trace_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
11502                     {
11503                         console::error("%s: Failed parsing glInternalTraceCommandRAD packet\n", VOGL_FUNCTION_NAME);
11504                         return false;
11505                     }
11506
11507                     GLuint cmd = trace_packet.get_param_value<GLuint>(0);
11508
11509                     new_trim_packets.push_back(packet_buf);
11510
11511                     if (cmd == cITCRDemarcation)
11512                         break;
11513                 }
11514
11515                 trim_packets.swap(new_trim_packets);
11516             }
11517         }
11518         else if (trim_call_counter >= 0)
11519         {
11520             uint orig_num_packets = trim_packets.size();
11521             uint total_erased_packets = 0;
11522
11523             // Remove any calls before the current one.
11524             for (int64_t packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11525             {
11526                 if (trim_packets.get_packet_type(static_cast<uint>(packet_index)) != cTSPTGLEntrypoint)
11527                     continue;
11528
11529                 const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(static_cast<uint>(packet_index));
11530
11531                 if (static_cast<int64_t>(pGL_packet->m_call_counter) <= trim_call_counter)
11532                 {
11533                     trim_packets.erase(static_cast<uint>(packet_index));
11534                     packet_index--;
11535
11536                     total_erased_packets++;
11537                 }
11538             }
11539
11540             console::message("%s: Read %u packets from frame %u, erased %u packets before call counter %" PRIu64 ", storing %u trim packets from source trace file\n", VOGL_FUNCTION_NAME, orig_num_packets, trim_frame, total_erased_packets, trim_call_counter, trim_packets.size());
11541         }
11542     }
11543
11544     if (!write_trim_file_internal(trim_packets, trim_filename, trace_reader, (flags & cWriteTrimFileOptimizeSnapshot) != 0, pSnapshot_id))
11545     {
11546         console::warning("%s: Trim file write failed, deleting invalid trim trace file %s\n", VOGL_METHOD_NAME, trim_filename.get_ptr());
11547
11548         file_utils::delete_file(trim_filename.get_ptr());
11549         return false;
11550     }
11551
11552     return true;
11553 }