]> git.cworth.org Git - vogl/blob - src/voglcommon/vogl_gl_replayer.cpp
- Fixing driver crash on AMD's fglrx caused by us passing down possibly bogus handles...
[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     // Seems better to return -1 when we can't find the uniform (which can happen if the driver optimizes the program differently vs. tracing).
1270     // Otherwise, we can pass an invalid handle down to the driver and this will crash AMD's fglrx.
1271     //GLint replay_location = trace_location;
1272     GLint replay_location = -1;
1273
1274     glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_program);
1275     if (it == get_shared_state()->m_glsl_program_hash_map.end())
1276     {
1277         process_entrypoint_warning("%s: Failed looking up current trace program in GLSL program hash map\n", VOGL_METHOD_NAME);
1278     }
1279     else
1280     {
1281         glsl_program_state &state = it->second;
1282
1283         uniform_location_hash_map::const_iterator loc_it = state.m_uniform_locations.find(trace_location);
1284         if (loc_it == state.m_uniform_locations.end())
1285         {
1286             process_entrypoint_warning("%s: Failed looking up uniform location index\n", VOGL_METHOD_NAME);
1287         }
1288         else
1289         {
1290             replay_location = loc_it->second;
1291         }
1292     }
1293     return replay_location;
1294 }
1295
1296 //----------------------------------------------------------------------------------------------------------------------
1297 // vogl_replayer::process_entrypoint_print_summary_context
1298 //----------------------------------------------------------------------------------------------------------------------
1299 void vogl_gl_replayer::process_entrypoint_print_summary_context(eConsoleMessageType msg_type)
1300 {
1301     VOGL_FUNC_TRACER
1302
1303     if (!m_pCur_gl_packet)
1304         return;
1305
1306     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",
1307                     g_vogl_entrypoint_descs[m_pCur_gl_packet->get_entrypoint_id()].m_pName,
1308                     m_frame_index, m_total_swaps,
1309                     m_pCur_gl_packet->get_entrypoint_packet().m_call_counter,
1310                     m_pCur_gl_packet->get_entrypoint_packet().m_context_handle,
1311                     m_cur_trace_context,
1312                     m_pCur_gl_packet->get_entrypoint_packet().m_thread_id);
1313
1314 #if 0
1315         dynamic_string_array backtrace;
1316         if (get_printable_backtrace(backtrace))
1317         {
1318                 console::printf("Backtrace:\n");
1319                 for (uint i = 0; i < backtrace.size(); i++)
1320                         console::printf("%s\n", backtrace[i].get_ptr());
1321         }
1322 #endif
1323 }
1324
1325 //----------------------------------------------------------------------------------------------------------------------
1326 // vogl_replayer::print_detailed_context
1327 //----------------------------------------------------------------------------------------------------------------------
1328 void vogl_gl_replayer::print_detailed_context(eConsoleMessageType msg_type)
1329 {
1330     VOGL_FUNC_TRACER
1331
1332     json_node node;
1333
1334     vogl_loose_file_blob_manager blob_file_manager;
1335     blob_file_manager.init(cBMFWritable);
1336
1337     vogl_trace_packet::json_serialize_params serialize_params;
1338     serialize_params.m_output_basename = "replay_error";
1339     serialize_params.m_cur_frame = m_frame_index;
1340     serialize_params.m_blob_file_size_threshold = 1024;
1341     serialize_params.m_pBlob_manager = (m_flags & cGLReplayerDumpPacketBlobFilesOnError) ? &blob_file_manager : NULL;
1342     m_pCur_gl_packet->json_serialize(node, serialize_params);
1343
1344     dynamic_string node_str;
1345     node.serialize(node_str, true, 0);
1346     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());
1347 }
1348
1349 //----------------------------------------------------------------------------------------------------------------------
1350 // vogl_replayer::process_entrypoint_msg_print_detailed_context
1351 //----------------------------------------------------------------------------------------------------------------------
1352 void vogl_gl_replayer::process_entrypoint_msg_print_detailed_context(eConsoleMessageType msg_type)
1353 {
1354     VOGL_FUNC_TRACER
1355
1356     if (!m_pCur_gl_packet)
1357         return;
1358
1359     dump_packet_as_func_call(*m_pCur_gl_packet);
1360
1361     if (!(m_flags & cGLReplayerDumpPacketsOnError))
1362         return;
1363
1364     print_detailed_context(msg_type);
1365 }
1366
1367 //----------------------------------------------------------------------------------------------------------------------
1368 // vogl_replayer::process_entrypoint_info
1369 //----------------------------------------------------------------------------------------------------------------------
1370 void vogl_gl_replayer::process_entrypoint_info(const char *pFmt, ...)
1371 {
1372     VOGL_FUNC_TRACER
1373
1374     process_entrypoint_print_summary_context(cInfoConsoleMessage);
1375
1376     va_list args;
1377     va_start(args, pFmt);
1378     console::vprintf(cInfoConsoleMessage, pFmt, args);
1379     va_end(args);
1380
1381     process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1382 }
1383
1384 //----------------------------------------------------------------------------------------------------------------------
1385 // vogl_replayer::process_entrypoint_message
1386 //----------------------------------------------------------------------------------------------------------------------
1387 void vogl_gl_replayer::process_entrypoint_message(const char *pFmt, ...)
1388 {
1389     VOGL_FUNC_TRACER
1390
1391     process_entrypoint_print_summary_context(cMessageConsoleMessage);
1392
1393     va_list args;
1394     va_start(args, pFmt);
1395     console::vprintf(cMessageConsoleMessage, pFmt, args);
1396     va_end(args);
1397
1398     process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1399 }
1400
1401 //----------------------------------------------------------------------------------------------------------------------
1402 // vogl_replayer::process_entrypoint_warning
1403 //----------------------------------------------------------------------------------------------------------------------
1404 void vogl_gl_replayer::process_entrypoint_warning(const char *pFmt, ...)
1405 {
1406     VOGL_FUNC_TRACER
1407
1408     process_entrypoint_print_summary_context(cWarningConsoleMessage);
1409
1410     va_list args;
1411     va_start(args, pFmt);
1412     console::vprintf(cWarningConsoleMessage, pFmt, args);
1413     va_end(args);
1414
1415     process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1416 }
1417
1418 //----------------------------------------------------------------------------------------------------------------------
1419 // vogl_replayer::process_entrypoint_error
1420 //----------------------------------------------------------------------------------------------------------------------
1421 void vogl_gl_replayer::process_entrypoint_error(const char *pFmt, ...)
1422 {
1423     VOGL_FUNC_TRACER
1424
1425     process_entrypoint_print_summary_context(cErrorConsoleMessage);
1426
1427     va_list args;
1428     va_start(args, pFmt);
1429     console::vprintf(cErrorConsoleMessage, pFmt, args);
1430     va_end(args);
1431
1432     process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1433 }
1434
1435 //----------------------------------------------------------------------------------------------------------------------
1436 // vogl_replayer::switch_contexts
1437 //----------------------------------------------------------------------------------------------------------------------
1438 vogl_gl_replayer::status_t vogl_gl_replayer::switch_contexts(vogl_trace_context_ptr_value trace_context)
1439 {
1440     VOGL_FUNC_TRACER
1441
1442     // HACK HACK
1443     //if (m_pCur_gl_packet->get_call_counter() == 25583)
1444     //    vogl_debug_break();
1445
1446     //vogl_trace_context_ptr_value trace_context = gl_packet.m_context_handle;
1447     if (trace_context == m_cur_trace_context)
1448         return cStatusOK;
1449
1450     if (m_flags & cGLReplayerDebugMode)
1451     {
1452         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));
1453     }
1454
1455     // pContext_state will be NULL if they are unmapping!
1456     context_state *pContext_state = get_trace_context_state(trace_context);
1457     GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
1458
1459     const Display *dpy = m_pWindow->get_display();
1460     GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
1461
1462     Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
1463     if (!result)
1464     {
1465         process_entrypoint_error("%s: Failed switching current trace context to 0x%" PRIX64 "\n", VOGL_METHOD_NAME, trace_context);
1466         return cStatusHardFailure;
1467     }
1468
1469     m_cur_trace_context = trace_context;
1470     m_cur_replay_context = replay_context;
1471     m_pCur_context_state = pContext_state;
1472
1473     return cStatusOK;
1474 }
1475
1476 //----------------------------------------------------------------------------------------------------------------------
1477 // vogl_replayer::debug_callback_arb
1478 //----------------------------------------------------------------------------------------------------------------------
1479 void vogl_gl_replayer::debug_callback_arb(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *pUser_param)
1480 {
1481     VOGL_FUNC_TRACER
1482
1483     VOGL_NOTE_UNUSED(length);
1484
1485     char final_message[4096];
1486
1487     context_state *pContext_state = (context_state *)(pUser_param);
1488
1489     vogl_format_debug_output_arb(final_message, sizeof(final_message), source, type, id, severity, reinterpret_cast<const char *>(message));
1490
1491     if (pContext_state)
1492     {
1493         vogl_warning_printf("%s: Trace context: 0x%" PRIX64 ", Replay context 0x%" PRIX64 ", Last trace call counter: %" PRIu64 "\n%s\n", VOGL_FUNCTION_NAME,
1494                            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);
1495     }
1496     else
1497     {
1498         vogl_warning_printf("%s: %s\n", VOGL_FUNCTION_NAME, final_message);
1499     }
1500 }
1501
1502 //----------------------------------------------------------------------------------------------------------------------
1503 // vogl_replayer::is_extension_supported
1504 //----------------------------------------------------------------------------------------------------------------------
1505 bool vogl_gl_replayer::is_extension_supported(const char *pExt)
1506 {
1507     VOGL_FUNC_TRACER
1508
1509     if ((m_pCur_context_state) && (m_pCur_context_state->m_context_info.is_valid()))
1510     {
1511         return m_pCur_context_state->m_context_info.supports_extension(pExt);
1512     }
1513
1514     VOGL_ASSERT_ALWAYS;
1515
1516     return true;
1517 }
1518
1519 //----------------------------------------------------------------------------------------------------------------------
1520 // vogl_replayer::context_state::handle_context_made_current
1521 //----------------------------------------------------------------------------------------------------------------------
1522 bool vogl_gl_replayer::context_state::handle_context_made_current()
1523 {
1524     VOGL_FUNC_TRACER
1525
1526     if (m_has_been_made_current)
1527         return true;
1528
1529     VOGL_CHECK_GL_ERROR;
1530
1531     m_has_been_made_current = true;
1532
1533     if (!m_context_info.init(m_context_desc))
1534     {
1535         vogl_error_printf("%s: vogl_context_info::init() failed!\n", VOGL_METHOD_NAME);
1536         return false;
1537     }
1538
1539     if (!m_context_info.get_max_vertex_attribs())
1540     {
1541         vogl_warning_printf("%s: GL_MAX_VERTEX_ATTRIBS is 0\n", VOGL_METHOD_NAME);
1542     }
1543     else if (m_context_info.get_max_vertex_attribs() >= VOGL_MAX_SUPPORTED_GL_VERTEX_ATTRIBUTES)
1544     {
1545         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);
1546         return false;
1547     }
1548
1549     if (m_replayer.m_flags & cGLReplayerLowLevelDebugMode)
1550     {
1551         vogl_debug_printf("%s: Creating dummy handles\n", VOGL_METHOD_NAME);
1552
1553         // HACK HACK
1554         // Generate a bunch of replay handles, so the trace and replay namespaces are totally different to shake out handle or target remapping bugs
1555         // TODO: All more object types
1556         vogl::vector<GLuint> dummy_handles(65536);
1557
1558         GL_ENTRYPOINT(glGenTextures)(4000, dummy_handles.get_ptr());
1559         GL_ENTRYPOINT(glGenBuffers)(6000, dummy_handles.get_ptr());
1560         GL_ENTRYPOINT(glGenLists)(8000);
1561         GL_ENTRYPOINT(glGenQueries)(10000, dummy_handles.get_ptr());
1562
1563         GL_ENTRYPOINT(glGenVertexArrays)(12000, dummy_handles.get_ptr());
1564         GL_ENTRYPOINT(glGenProgramsARB)(14000, dummy_handles.get_ptr());
1565         GL_ENTRYPOINT(glGenFramebuffers)(16000, dummy_handles.get_ptr());
1566         GL_ENTRYPOINT(glGenSamplers)(18000, dummy_handles.get_ptr());
1567         GL_ENTRYPOINT(glGenRenderbuffers)(20000, dummy_handles.get_ptr());
1568
1569         for (uint i = 0; i < 22000; i++)
1570             GL_ENTRYPOINT(glCreateProgram)();
1571
1572         vogl_debug_printf("%s: Finished creating dummy handles\n", VOGL_METHOD_NAME);
1573     }
1574
1575     VOGL_CHECK_GL_ERROR;
1576
1577     return true;
1578 }
1579
1580 //----------------------------------------------------------------------------------------------------------------------
1581 // vogl_replayer::handle_context_made_current
1582 //----------------------------------------------------------------------------------------------------------------------
1583 bool vogl_gl_replayer::handle_context_made_current()
1584 {
1585     VOGL_FUNC_TRACER
1586
1587     if (!m_pCur_context_state->handle_context_made_current())
1588         return false;
1589
1590     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")))
1591     {
1592         GL_ENTRYPOINT(glDebugMessageCallbackARB)(debug_callback_arb, (GLvoid *)m_pCur_context_state);
1593         GL_ENTRYPOINT(glEnable)(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
1594         check_gl_error();
1595     }
1596
1597     if (m_flags & cGLReplayerVerboseMode)
1598     {
1599         vogl_debug_printf("%s: Trace context: 0x%" PRIX64 ", replay context 0x%" PRIX64 ", GL_VERSION: %s\n",
1600                          VOGL_METHOD_NAME,
1601                          (uint64_t)m_cur_trace_context,
1602                          (uint64_t)m_cur_replay_context,
1603                          m_pCur_context_state->m_context_info.get_version_str().get_ptr());
1604     }
1605
1606     return true;
1607 }
1608
1609 //----------------------------------------------------------------------------------------------------------------------
1610 // vogl_replayer::dump_context_attrib_list
1611 //----------------------------------------------------------------------------------------------------------------------
1612 void vogl_gl_replayer::dump_context_attrib_list(const int *pAttrib_list, uint size)
1613 {
1614     VOGL_FUNC_TRACER
1615
1616     if (!pAttrib_list)
1617     {
1618         vogl_debug_printf("Attrib list is NULL\n");
1619         return;
1620     }
1621     vogl_debug_printf("Context attribs:\n");
1622
1623     uint ofs = 0;
1624     for (;;)
1625     {
1626         if (ofs >= size)
1627         {
1628             vogl_error_printf("%s: Attrib list ended prematurely (must end in a 0 key)\n", VOGL_METHOD_NAME);
1629             break;
1630         }
1631
1632         uint key = pAttrib_list[ofs];
1633         if (!key)
1634             break;
1635         ofs++;
1636
1637         if (ofs >= size)
1638         {
1639             vogl_error_printf("%s: Attrib list ended prematurely (must end in a 0 key)\n", VOGL_METHOD_NAME);
1640             break;
1641         }
1642
1643         uint value = pAttrib_list[ofs];
1644         ofs++;
1645
1646         vogl_debug_printf("Key: %s (0x%08X), Value: 0x%08X\n", g_gl_enums.find_name(key, "GLX"), key, value);
1647     }
1648     vogl_debug_printf("End of context attribs\n");
1649 }
1650
1651 //----------------------------------------------------------------------------------------------------------------------
1652 // vogl_replayer::find_attrib_key
1653 //----------------------------------------------------------------------------------------------------------------------
1654 int vogl_gl_replayer::find_attrib_key(const vogl::vector<int> &attrib_list, int key_to_find)
1655 {
1656     VOGL_FUNC_TRACER
1657
1658     uint ofs = 0;
1659     while (ofs < attrib_list.size())
1660     {
1661         int key = attrib_list[ofs];
1662         if (!key)
1663             break;
1664
1665         if (++ofs >= attrib_list.size())
1666         {
1667             process_entrypoint_warning("%s: Failed parsing attrib list, this call is probably going to fail\n", VOGL_METHOD_NAME);
1668             break;
1669         }
1670
1671         if (key == key_to_find)
1672             return ofs;
1673         ofs++;
1674     }
1675
1676     return -1;
1677 }
1678
1679 //----------------------------------------------------------------------------------------------------------------------
1680 // vogl_replayer::create_context_attribs
1681 //----------------------------------------------------------------------------------------------------------------------
1682 vogl_gl_replayer::status_t vogl_gl_replayer::create_context_attribs(
1683     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,
1684     const int *pTrace_attrib_list, int trace_attrib_list_size, bool expecting_attribs)
1685 {
1686     VOGL_FUNC_TRACER
1687
1688     vogl::vector<int> temp_attrib_list;
1689
1690     if ((pTrace_attrib_list) && (trace_attrib_list_size))
1691     {
1692         temp_attrib_list.append(pTrace_attrib_list, trace_attrib_list_size);
1693         if (temp_attrib_list.back() != 0)
1694         {
1695             process_entrypoint_warning("%s: attrib list does not end with 0\n", VOGL_METHOD_NAME);
1696         }
1697     }
1698     else
1699     {
1700         if (expecting_attribs)
1701         {
1702             if (m_flags & cGLReplayerVerboseMode)
1703                 process_entrypoint_message("%s: No attrib list found in trace, assuming an attrib list ending with 0\n", VOGL_METHOD_NAME);
1704         }
1705
1706         temp_attrib_list.push_back(0);
1707     }
1708
1709     if (m_flags & cGLReplayerForceDebugContexts)
1710     {
1711         // See http://www.opengl.org/registry/specs/ARB/glx_create_context.txt
1712         int context_flags_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_FLAGS_ARB);
1713         if (context_flags_ofs < 0)
1714         {
1715             temp_attrib_list.back() = GLX_CONTEXT_FLAGS_ARB;
1716             temp_attrib_list.push_back(GLX_CONTEXT_DEBUG_BIT_ARB);
1717             temp_attrib_list.push_back(0);
1718
1719             if (m_flags & cGLReplayerVerboseMode)
1720                 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);
1721         }
1722         else
1723         {
1724             temp_attrib_list[context_flags_ofs] |= GLX_CONTEXT_DEBUG_BIT_ARB;
1725
1726             if (m_flags & cGLReplayerVerboseMode)
1727                 process_entrypoint_warning("%s: Slamming on GLX_CONTEXT_DEBUG_BIT_ARB bit to enable debug context\n", VOGL_METHOD_NAME);
1728         }
1729
1730         int context_major_version_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_MAJOR_VERSION_ARB);
1731         int context_minor_version_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_MINOR_VERSION_ARB);
1732
1733         bool slammed_up_to_3_0 = false;
1734         if (context_major_version_ofs < 0)
1735         {
1736 // 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).
1737 #if 0
1738                         temp_attrib_list.back() = GLX_CONTEXT_MAJOR_VERSION_ARB;
1739                         temp_attrib_list.push_back(3);
1740                         temp_attrib_list.push_back(0);
1741
1742                         slammed_up_to_3_0 = true;
1743 #endif
1744         }
1745         else if (temp_attrib_list[context_major_version_ofs] < 3)
1746         {
1747             temp_attrib_list[context_major_version_ofs] = 3;
1748
1749             slammed_up_to_3_0 = true;
1750         }
1751
1752         if (slammed_up_to_3_0)
1753         {
1754             if (context_minor_version_ofs < 0)
1755             {
1756                 temp_attrib_list.back() = GLX_CONTEXT_MINOR_VERSION_ARB;
1757                 temp_attrib_list.push_back(0);
1758                 temp_attrib_list.push_back(0);
1759             }
1760             else
1761             {
1762                 temp_attrib_list[context_minor_version_ofs] = 0;
1763             }
1764
1765             process_entrypoint_warning("%s: Forcing GL context version up to 3.0 due to debug context usage\n", VOGL_METHOD_NAME);
1766         }
1767     }
1768
1769     const int *pAttrib_list = temp_attrib_list.get_ptr();
1770     const uint attrib_list_size = temp_attrib_list.size();
1771
1772     if (m_flags & cGLReplayerVerboseMode)
1773         dump_context_attrib_list(pAttrib_list, attrib_list_size);
1774
1775     GLXContext replay_context = GL_ENTRYPOINT(glXCreateContextAttribsARB)(dpy, config, replay_share_context, direct, pAttrib_list);
1776     if (!replay_context)
1777     {
1778         if (trace_context)
1779         {
1780             process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
1781             return cStatusHardFailure;
1782         }
1783         else
1784         {
1785             process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
1786         }
1787     }
1788
1789     if (replay_context)
1790     {
1791         if (trace_context)
1792         {
1793             context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateContextAttribsARB, pAttrib_list, attrib_list_size);
1794             VOGL_NOTE_UNUSED(pContext_state);
1795         }
1796         else
1797         {
1798             GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
1799         }
1800     }
1801
1802     return cStatusOK;
1803 }
1804
1805 //----------------------------------------------------------------------------------------------------------------------
1806 // vogl_replayer::process_pending_make_current
1807 //----------------------------------------------------------------------------------------------------------------------
1808 vogl_gl_replayer::status_t vogl_gl_replayer::process_pending_make_current()
1809 {
1810     VOGL_FUNC_TRACER
1811
1812     if (!m_pending_make_current_packet.is_valid())
1813         return cStatusOK;
1814
1815     vogl_trace_packet &gl_packet = m_pending_make_current_packet;
1816
1817     Bool trace_result = gl_packet.get_return_value<Bool>();
1818
1819     gl_entrypoint_id_t entrypoint_id = gl_packet.get_entrypoint_id();
1820     VOGL_ASSERT((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) || (entrypoint_id == VOGL_ENTRYPOINT_glXMakeContextCurrent));
1821
1822     // pContext_state will be NULL if they are unmapping!
1823     vogl_trace_ptr_value trace_context = gl_packet.get_param_ptr_value((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) ? 2 : 3);
1824     context_state *pContext_state = get_trace_context_state(trace_context);
1825     GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
1826
1827     if ((trace_context) && (!replay_context))
1828     {
1829         process_entrypoint_error("%s, Failed remapping GL context\n", VOGL_METHOD_NAME);
1830         m_pending_make_current_packet.clear();
1831         return cStatusHardFailure;
1832     }
1833
1834     const Display *dpy = m_pWindow->get_display();
1835     GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
1836
1837     Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
1838     if (!result)
1839     {
1840         if (trace_result)
1841         {
1842             process_entrypoint_error("%s: Failed making context current, but in the trace this call succeeded!\n", VOGL_METHOD_NAME);
1843             m_pending_make_current_packet.clear();
1844             return cStatusHardFailure;
1845         }
1846         else
1847         {
1848             process_entrypoint_warning("%s: Failed making context current, in the trace this call also failed\n", VOGL_METHOD_NAME);
1849         }
1850     }
1851     else
1852     {
1853         m_cur_trace_context = trace_context;
1854         m_cur_replay_context = replay_context;
1855         m_pCur_context_state = pContext_state;
1856
1857         if (!trace_result)
1858         {
1859             process_entrypoint_warning("%s: Context was successfuly made current, but this operation failed in the trace\n", VOGL_METHOD_NAME);
1860         }
1861
1862         if (m_cur_replay_context)
1863         {
1864             int viewport_x = gl_packet.get_key_value_map().get_int(string_hash("viewport_x"));
1865             int viewport_y = gl_packet.get_key_value_map().get_int(string_hash("viewport_y"));
1866             int viewport_width = gl_packet.get_key_value_map().get_int(string_hash("viewport_width"));
1867             int viewport_height = gl_packet.get_key_value_map().get_int(string_hash("viewport_height"));
1868             int win_width = gl_packet.get_key_value_map().get_int(string_hash("win_width"));
1869             int win_height = gl_packet.get_key_value_map().get_int(string_hash("win_height"));
1870
1871             if (!m_pCur_context_state->m_has_been_made_current)
1872             {
1873                 vogl_printf("glXMakeCurrent(): Trace Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
1874                            viewport_x, viewport_y,
1875                            viewport_width, viewport_height,
1876                            win_width, win_height);
1877             }
1878
1879             GLint cur_viewport[4];
1880             GL_ENTRYPOINT(glGetIntegerv)(GL_VIEWPORT, cur_viewport);
1881
1882             uint cur_win_width = 0, cur_win_height = 0;
1883             m_pWindow->get_actual_dimensions(cur_win_width, cur_win_height);
1884
1885             if (!m_pCur_context_state->m_has_been_made_current)
1886             {
1887                 vogl_printf("glXMakeCurrent(): Replay Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
1888                            cur_viewport[0], cur_viewport[1],
1889                            cur_viewport[2], cur_viewport[3],
1890                            cur_win_width, cur_win_height);
1891             }
1892
1893             if ((cur_viewport[0] != viewport_x) || (cur_viewport[1] != viewport_y) || (cur_viewport[2] != viewport_width) || (cur_viewport[3] != viewport_height))
1894             {
1895                 process_entrypoint_warning("%s: Replay viewport differs from traces!\n", VOGL_METHOD_NAME);
1896             }
1897
1898             if (!handle_context_made_current())
1899                 return cStatusHardFailure;
1900         }
1901     }
1902
1903     m_last_processed_call_counter = gl_packet.get_call_counter();
1904
1905     m_pending_make_current_packet.clear();
1906
1907     return cStatusOK;
1908 }
1909
1910 //----------------------------------------------------------------------------------------------------------------------
1911 // vogl_process_internal_trace_command_ctypes_packet
1912 //----------------------------------------------------------------------------------------------------------------------
1913 bool vogl_process_internal_trace_command_ctypes_packet(const key_value_map &kvm, const vogl_ctypes &ctypes)
1914 {
1915     VOGL_FUNC_TRACER
1916
1917     // TODO: Implement the code to map trace ctypes to replay ctypes. That's going to be fun.
1918     int num_trace_ctypes = kvm.get_int("num_ctypes");
1919     VOGL_VERIFY(num_trace_ctypes == VOGL_NUM_CTYPES);
1920
1921     // TODO: This just verifies that the replayer's idea of each ctype matches the tracer's.
1922     // This will need to be revisited once we port to other OS's.
1923     // TODO: Move the ctypes crap into the SOF packet or something, it's not easy to deal with this packet on the fly.
1924     for (int ctype_iter = 0; ctype_iter < num_trace_ctypes; ctype_iter++)
1925     {
1926         const vogl_ctype_desc_t &desc = ctypes[static_cast<vogl_ctype_t>(ctype_iter)];
1927
1928         uint base_index = ctype_iter << 8;
1929         dynamic_string name(kvm.get_string(base_index++));
1930         dynamic_string ctype(kvm.get_string(base_index++));
1931         int size = kvm.get_int(base_index++);
1932         uint loki_type_flags = kvm.get_uint(base_index++);
1933         bool is_pointer = kvm.get_bool(base_index++);
1934         bool is_opaque_pointer = kvm.get_bool(base_index++);
1935         bool is_pointer_diff = kvm.get_bool(base_index++);
1936         bool is_opaque_type = kvm.get_bool(base_index++);
1937
1938         VOGL_VERIFY(name.compare(desc.m_pName, true) == 0);
1939         VOGL_VERIFY(ctype.compare(desc.m_pCType, true) == 0);
1940         if (!desc.m_is_opaque_type)
1941         {
1942             VOGL_VERIFY(size == desc.m_size);
1943         }
1944
1945         const uint loki_type_check_mask = ~(LOKI_TYPE_BITMASK(LOKI_IS_SIGNED_LONG) | LOKI_TYPE_BITMASK(LOKI_IS_UNSIGNED_LONG));
1946         VOGL_VERIFY((loki_type_flags & loki_type_check_mask) == (desc.m_loki_type_flags & loki_type_check_mask));
1947
1948         VOGL_VERIFY(is_pointer == desc.m_is_pointer);
1949         VOGL_VERIFY(is_opaque_pointer == desc.m_is_opaque_pointer);
1950         VOGL_VERIFY(is_pointer_diff == desc.m_is_pointer_diff);
1951         VOGL_VERIFY(is_opaque_type == desc.m_is_opaque_type);
1952     }
1953
1954     return true;
1955 }
1956
1957 //----------------------------------------------------------------------------------------------------------------------
1958 // vogl_replayer::process_internal_trace_command
1959 //----------------------------------------------------------------------------------------------------------------------
1960 vogl_gl_replayer::status_t vogl_gl_replayer::process_internal_trace_command(const vogl_trace_gl_entrypoint_packet &gl_packet)
1961 {
1962     VOGL_FUNC_TRACER
1963
1964     VOGL_NOTE_UNUSED(gl_packet);
1965
1966     GLuint cmd = m_pCur_gl_packet->get_param_value<GLuint>(0);
1967     GLuint size = m_pCur_gl_packet->get_param_value<GLuint>(1);
1968     VOGL_NOTE_UNUSED(size);
1969     vogl_trace_ptr_value trace_data_ptr_value = m_pCur_gl_packet->get_param_ptr_value(2);
1970     VOGL_NOTE_UNUSED(trace_data_ptr_value);
1971
1972     vogl_gl_replayer::status_t status = cStatusOK;
1973
1974     switch (cmd)
1975     {
1976         case cITCRDemarcation:
1977         {
1978             break;
1979         }
1980         case cITCRKeyValueMap:
1981         {
1982             const key_value_map &kvm = m_pCur_gl_packet->get_key_value_map();
1983
1984             dynamic_string cmd_type(kvm.get_string("command_type"));
1985             if (cmd_type == "state_snapshot")
1986             {
1987                 dynamic_string text_id(kvm.get_string("id"));
1988                 dynamic_string binary_id(kvm.get_string("binary_id"));
1989                 if (text_id.is_empty() && binary_id.is_empty())
1990                 {
1991                     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());
1992                     return cStatusHardFailure;
1993                 }
1994
1995                 dynamic_string id_to_use(text_id.is_empty() ? binary_id : text_id);
1996
1997                 // TODO: Make a 1st class snapshot cache class
1998                 // TODO: This could fail if the user hand modifies the snapshot in some way - add an option to disable caching.
1999                 vogl_gl_state_snapshot *pSnapshot = NULL;
2000                 if (m_flags & cGLReplayerSnapshotCaching)
2001                 {
2002                     for (uint snapshot_index = 0; snapshot_index < m_snapshots.size(); snapshot_index++)
2003                     {
2004                         if (!m_snapshots[snapshot_index].m_name.compare(id_to_use, false))
2005                         {
2006                             pSnapshot = m_snapshots[snapshot_index].m_pSnapshot;
2007                             if (snapshot_index)
2008                             {
2009                                 snapshot_cache_entry cache_entry(m_snapshots[snapshot_index]);
2010                                 m_snapshots.erase(snapshot_index);
2011                                 m_snapshots.insert(0, cache_entry);
2012                             }
2013                             break;
2014                         }
2015                     }
2016                 }
2017
2018                 if (!pSnapshot)
2019                 {
2020                     timed_scope ts("Deserialize snapshot time");
2021
2022                     if (!m_pBlob_manager)
2023                     {
2024                         process_entrypoint_error("%s: Failed reading snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2025                         return cStatusHardFailure;
2026                     }
2027
2028                     uint8_vec snapshot_data;
2029
2030                     if (!m_pBlob_manager->get(id_to_use, snapshot_data) || (snapshot_data.is_empty()))
2031                     {
2032                         process_entrypoint_error("%s: Failed reading snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2033                         return cStatusHardFailure;
2034                     }
2035
2036                     vogl_message_printf("%s: Deserializing state snapshot \"%s\", %u bytes\n", VOGL_METHOD_NAME, id_to_use.get_ptr(), snapshot_data.size());
2037
2038                     json_document doc;
2039
2040                     bool success;
2041                     if (id_to_use == text_id)
2042                         success = doc.deserialize(reinterpret_cast<const char *>(snapshot_data.get_ptr()), snapshot_data.size());
2043                     else
2044                         success = doc.binary_deserialize(snapshot_data);
2045                     if (!success || (!doc.get_root()))
2046                     {
2047                         process_entrypoint_error("%s: Failed deserializing JSON snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2048                         return cStatusHardFailure;
2049                     }
2050
2051                     pSnapshot = vogl_new(vogl_gl_state_snapshot);
2052                     if (!pSnapshot->deserialize(*doc.get_root(), *m_pBlob_manager, &m_trace_gl_ctypes))
2053                     {
2054                         vogl_delete(pSnapshot);
2055                         pSnapshot = NULL;
2056
2057                         process_entrypoint_error("%s: Failed deserializing snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2058                         return cStatusHardFailure;
2059                     }
2060
2061                     if (m_flags & cGLReplayerSnapshotCaching)
2062                     {
2063                         snapshot_cache_entry new_cache_entry;
2064                         new_cache_entry.m_name = id_to_use;
2065                         new_cache_entry.m_pSnapshot = pSnapshot;
2066                         m_snapshots.insert(0, new_cache_entry);
2067
2068                         // FIXME: Even 3-4 snapshots in memory may be too much in 32-bit mode for some large apps.
2069                         while (m_snapshots.size() > 3)
2070                         {
2071                             vogl_delete(m_snapshots.back().m_pSnapshot);
2072                             m_snapshots.resize(m_snapshots.size() - 1);
2073                         }
2074                     }
2075                 }
2076
2077                 status = begin_applying_snapshot(pSnapshot, (m_flags & cGLReplayerSnapshotCaching) ? false : true);
2078
2079                 if ((status != cStatusOK) && (status != cStatusResizeWindow))
2080                 {
2081                     if (m_flags & cGLReplayerSnapshotCaching)
2082                     {
2083                         VOGL_ASSERT(m_snapshots[0].m_pSnapshot == pSnapshot);
2084
2085                         vogl_delete(m_snapshots[0].m_pSnapshot);
2086                         m_snapshots.erase(0U);
2087                     }
2088
2089                     if (m_flags & cGLReplayerSnapshotCaching)
2090                     {
2091                         vogl_delete(pSnapshot);
2092                         pSnapshot = NULL;
2093                     }
2094
2095                     process_entrypoint_error("%s: Failed applying GL snapshot from blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2096                     return status;
2097                 }
2098
2099                 vogl_message_printf("%s: Successfully applied GL state snapshot from blob \"%s\"\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2100             }
2101             else if (cmd_type == "ctypes")
2102             {
2103                 m_ctypes_packet = *m_pCur_gl_packet;
2104
2105                 if (!vogl_process_internal_trace_command_ctypes_packet(kvm, m_trace_gl_ctypes))
2106                     return cStatusHardFailure;
2107             }
2108             else if (cmd_type == "entrypoints")
2109             {
2110                 // TODO
2111             }
2112             else
2113             {
2114                 process_entrypoint_warning("%s: Unknown glInternalTraceCommandRAD key_value_map command type: \"%s\"\n", VOGL_METHOD_NAME, cmd_type.get_ptr());
2115             }
2116             break;
2117         }
2118         default:
2119         {
2120             process_entrypoint_warning("%s: Unknown glInternalTraceCommandRAD command type: %u\n", VOGL_METHOD_NAME, cmd);
2121             break;
2122         }
2123     }
2124
2125     return status;
2126 }
2127
2128 //----------------------------------------------------------------------------------------------------------------------
2129 // vogl_replayer::check_program_binding_shadow
2130 //----------------------------------------------------------------------------------------------------------------------
2131 bool vogl_gl_replayer::check_program_binding_shadow()
2132 {
2133     VOGL_FUNC_TRACER
2134
2135     if (!m_pCur_context_state)
2136         return true;
2137
2138     // Make sure shadow is good
2139     GLint actual_current_replay_program = 0;
2140     GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &actual_current_replay_program);
2141     check_gl_error();
2142
2143     if (m_pCur_context_state->m_cur_replay_program == static_cast<GLuint>(actual_current_replay_program))
2144         return true;
2145
2146     // OK, on AMD it plays games with GL_CURRENT_PROGRAM when the currently bound program is deleted. Check for this scenario.
2147     bool is_still_program = GL_ENTRYPOINT(glIsProgram)(m_pCur_context_state->m_cur_replay_program) != 0;
2148     if ((!check_gl_error()) && (is_still_program))
2149     {
2150         GLint marked_for_deletion = GL_FALSE;
2151         GL_ENTRYPOINT(glGetProgramiv)(m_pCur_context_state->m_cur_replay_program, GL_DELETE_STATUS, &marked_for_deletion);
2152
2153         if ((!check_gl_error()) && (marked_for_deletion))
2154             return true;
2155     }
2156
2157     VOGL_VERIFY(0);
2158     return false;
2159 }
2160
2161 //----------------------------------------------------------------------------------------------------------------------
2162 // vogl_replayer::handle_use_program
2163 //----------------------------------------------------------------------------------------------------------------------
2164 void vogl_gl_replayer::handle_use_program(GLuint trace_handle, gl_entrypoint_id_t entrypoint_id)
2165 {
2166     VOGL_FUNC_TRACER
2167
2168     // 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.
2169     check_program_binding_shadow();
2170
2171     GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2172     VOGL_ASSERT(!trace_handle || get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_PROGRAM_OBJECT);
2173     VOGL_ASSERT(!trace_handle || get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_PROGRAM_OBJECT);
2174
2175     // For safety, absorb any previous error.
2176     check_gl_error();
2177
2178     GLuint prev_replay_program = m_pCur_context_state->m_cur_replay_program;
2179     GLuint prev_trace_program = m_pCur_context_state->m_cur_trace_program;
2180
2181     bool prev_is_program = false;
2182     GLint prev_link_status = false;
2183     GLint prev_is_marked_for_deletion = false;
2184     vogl::growable_array<GLuint, 8> prev_attached_replay_shaders;
2185
2186     if ((prev_replay_program) && (replay_handle != prev_replay_program))
2187     {
2188         prev_is_program = GL_ENTRYPOINT(glIsProgram)(prev_replay_program);
2189         check_gl_error_quietly();
2190
2191         if (prev_is_program)
2192         {
2193             GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_DELETE_STATUS, &prev_is_marked_for_deletion);
2194             check_gl_error_quietly();
2195
2196             GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_LINK_STATUS, &prev_link_status);
2197             check_gl_error_quietly();
2198
2199             if (prev_is_marked_for_deletion)
2200             {
2201                 // 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.
2202                 GLint num_attached_shaders = 0;
2203                 GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_ATTACHED_SHADERS, &num_attached_shaders);
2204                 check_gl_error_quietly();
2205
2206                 if (num_attached_shaders)
2207                 {
2208                     prev_attached_replay_shaders.resize(num_attached_shaders);
2209
2210                     GLsizei actual_count = 0;
2211                     GL_ENTRYPOINT(glGetAttachedShaders)(prev_replay_program, num_attached_shaders, &actual_count, prev_attached_replay_shaders.get_ptr());
2212                     check_gl_error_quietly();
2213
2214                     VOGL_ASSERT(actual_count == num_attached_shaders);
2215                 }
2216             }
2217         }
2218     }
2219
2220     if (entrypoint_id == VOGL_ENTRYPOINT_glUseProgram)
2221         GL_ENTRYPOINT(glUseProgram)(replay_handle);
2222     else
2223         GL_ENTRYPOINT(glUseProgramObjectARB)(replay_handle);
2224
2225     // Can't shadow if glUseProgram failed.
2226     if (check_gl_error())
2227         return;
2228
2229     if ((prev_replay_program) && (prev_replay_program != replay_handle))
2230     {
2231         bool is_prev_still_program = GL_ENTRYPOINT(glIsProgram)(prev_replay_program);
2232         if (!is_prev_still_program)
2233         {
2234             VOGL_ASSERT(prev_is_program);
2235             VOGL_ASSERT(prev_is_marked_for_deletion);
2236
2237             // The previously bound program is really dead now, kill it from our tables and also check up on any shaders it was attached to.
2238             bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(prev_trace_program);
2239             VOGL_ASSERT(was_deleted);
2240             VOGL_NOTE_UNUSED(was_deleted);
2241
2242             was_deleted = get_shared_state()->m_glsl_program_hash_map.erase(prev_trace_program);
2243             VOGL_ASSERT(was_deleted);
2244
2245             was_deleted = get_shared_state()->m_shadow_state.m_linked_programs.remove_snapshot(prev_replay_program);
2246             if ((prev_link_status) && (!was_deleted))
2247             {
2248                 VOGL_ASSERT_ALWAYS;
2249             }
2250
2251             for (uint i = 0; i < prev_attached_replay_shaders.size(); i++)
2252             {
2253                 GLuint replay_shader_handle = prev_attached_replay_shaders[i];
2254
2255                 bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_shader_handle);
2256                 check_gl_error_quietly();
2257
2258                 if (is_still_shader)
2259                     continue;
2260
2261                 if (!get_shared_state()->m_shadow_state.m_objs.contains_inv(replay_shader_handle))
2262                 {
2263                     // We didn't create this shader handle, the AMD driver did on a program binary link, so ignore it.
2264                     continue;
2265                 }
2266
2267                 // The attached shader is now really dead.
2268                 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_shader_handle) == VOGL_SHADER_OBJECT);
2269                 if (!get_shared_state()->m_shadow_state.m_objs.erase_inv(replay_shader_handle))
2270                 {
2271                     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);
2272                 }
2273             }
2274         }
2275     }
2276
2277     m_pCur_context_state->m_cur_replay_program = replay_handle;
2278     m_pCur_context_state->m_cur_trace_program = trace_handle;
2279 }
2280
2281 //----------------------------------------------------------------------------------------------------------------------
2282 // vogl_replayer::handle_delete_program
2283 //----------------------------------------------------------------------------------------------------------------------
2284 void vogl_gl_replayer::handle_delete_program(GLuint trace_handle)
2285 {
2286     VOGL_FUNC_TRACER
2287
2288     check_program_binding_shadow();
2289
2290     // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2291
2292     GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2293     VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_PROGRAM_OBJECT);
2294     VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_PROGRAM_OBJECT);
2295
2296     context_state *pContext_shareroot = m_pCur_context_state->m_pShared_state;
2297     for (context_hash_map::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
2298     {
2299         if (it->first == m_pCur_context_state->m_context_desc.get_trace_context())
2300             continue;
2301
2302         context_state *pContext = it->second;
2303         if (pContext->m_pShared_state == pContext_shareroot)
2304         {
2305             if (pContext->m_cur_trace_program == trace_handle)
2306             {
2307                 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",
2308                                          VOGL_METHOD_NAME, trace_handle, replay_handle,
2309                                          cast_val_to_uint64(m_pCur_context_state->m_context_desc.get_trace_context()),
2310                                          cast_val_to_uint64(it->first));
2311             }
2312         }
2313     }
2314
2315     bool is_program = GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0;
2316     check_gl_error_quietly();
2317
2318     vogl::growable_array<GLuint, 8> attached_replay_shaders;
2319
2320     if ((is_program) && (replay_handle))
2321     {
2322         GLint num_attached_shaders = 0;
2323         GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_ATTACHED_SHADERS, &num_attached_shaders);
2324         check_gl_error_quietly();
2325
2326         if (num_attached_shaders)
2327         {
2328             attached_replay_shaders.resize(num_attached_shaders);
2329
2330             GLsizei actual_count = 0;
2331             GL_ENTRYPOINT(glGetAttachedShaders)(replay_handle, num_attached_shaders, &actual_count, attached_replay_shaders.get_ptr());
2332             check_gl_error_quietly();
2333
2334             VOGL_ASSERT(actual_count == num_attached_shaders);
2335         }
2336     }
2337
2338     GL_ENTRYPOINT(glDeleteProgram)(replay_handle);
2339
2340     bool deletion_succeeded = !check_gl_error();
2341     if (!deletion_succeeded)
2342     {
2343         VOGL_ASSERT(!is_program);
2344
2345         process_entrypoint_warning("%s: Failed deleting program, trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2346         return;
2347     }
2348
2349     if (!replay_handle)
2350         return;
2351
2352     bool is_still_program = GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0;
2353     check_gl_error_quietly();
2354
2355     GLint marked_for_deletion = 0;
2356     if (is_still_program)
2357     {
2358         // It must still be bound to the context, or referred to in some other way that we don't know about.
2359         GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_DELETE_STATUS, &marked_for_deletion);
2360         bool delete_status_check_succeeded = !check_gl_error_quietly();
2361
2362         VOGL_VERIFY(delete_status_check_succeeded);
2363         VOGL_VERIFY(marked_for_deletion);
2364     }
2365     else if (!is_still_program)
2366     {
2367         VOGL_ASSERT(is_program);
2368
2369         // The program is really gone now.
2370         bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_handle);
2371         VOGL_ASSERT(was_deleted);
2372         VOGL_NOTE_UNUSED(was_deleted);
2373
2374         was_deleted = get_shared_state()->m_glsl_program_hash_map.erase(trace_handle);
2375         VOGL_ASSERT(was_deleted);
2376
2377         get_shared_state()->m_shadow_state.m_linked_programs.remove_snapshot(replay_handle);
2378
2379         if (m_pCur_context_state->m_cur_replay_program == replay_handle)
2380         {
2381             // This shouldn't happen - if the program is still bound to the context then it should still be a program.
2382             VOGL_ASSERT_ALWAYS;
2383             m_pCur_context_state->m_cur_replay_program = 0;
2384             m_pCur_context_state->m_cur_trace_program = 0;
2385         }
2386
2387         for (uint i = 0; i < attached_replay_shaders.size(); i++)
2388         {
2389             GLuint replay_shader_handle = attached_replay_shaders[i];
2390
2391             bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_shader_handle) != 0;
2392             check_gl_error_quietly();
2393
2394             if (is_still_shader)
2395                 continue;
2396
2397             if (!get_shared_state()->m_shadow_state.m_objs.contains_inv(replay_shader_handle))
2398             {
2399                 // We didn't create this shader handle, the AMD driver did on a program binary link, so ignore it.
2400                 continue;
2401             }
2402
2403             // The attached shader is now really dead.
2404             VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_shader_handle) == VOGL_SHADER_OBJECT);
2405             if (!get_shared_state()->m_shadow_state.m_objs.erase_inv(replay_shader_handle))
2406             {
2407                 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);
2408             }
2409         }
2410     }
2411 }
2412
2413 //----------------------------------------------------------------------------------------------------------------------
2414 // vogl_replayer::handle_delete_shader
2415 //----------------------------------------------------------------------------------------------------------------------
2416 void vogl_gl_replayer::handle_delete_shader(GLuint trace_handle)
2417 {
2418     VOGL_FUNC_TRACER
2419
2420     check_program_binding_shadow();
2421
2422     check_gl_error();
2423
2424     // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2425
2426     GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2427     VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_SHADER_OBJECT);
2428     VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_SHADER_OBJECT);
2429
2430     GL_ENTRYPOINT(glDeleteShader)(replay_handle);
2431
2432     bool deletion_succeeded = !check_gl_error();
2433     if (!deletion_succeeded)
2434     {
2435         process_entrypoint_warning("%s: Failed deleting shader, trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2436         return;
2437     }
2438
2439     if (!replay_handle)
2440         return;
2441
2442     bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_handle);
2443     check_gl_error_quietly();
2444
2445     if (!is_still_shader)
2446     {
2447         // The shader is really gone.
2448         bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_handle);
2449         VOGL_ASSERT(was_deleted);
2450         VOGL_NOTE_UNUSED(was_deleted);
2451     }
2452     else
2453     {
2454         GLint marked_for_deletion = 0;
2455         GL_ENTRYPOINT(glGetShaderiv)(replay_handle, GL_DELETE_STATUS, &marked_for_deletion);
2456         check_gl_error_quietly();
2457
2458         VOGL_VERIFY(marked_for_deletion);
2459
2460         // The shader is attached to a live program object (which may or may not be actually in the marked_as_deleted state)
2461         // we'll get around to it when the program object is deleted, or when they remove the program object from the current state.
2462     }
2463 }
2464
2465 //----------------------------------------------------------------------------------------------------------------------
2466 // vogl_replayer::handle_detach_shader
2467 //----------------------------------------------------------------------------------------------------------------------
2468 void vogl_gl_replayer::handle_detach_shader(gl_entrypoint_id_t entrypoint_id)
2469 {
2470     GLuint trace_program = m_pCur_gl_packet->get_param_value<GLuint>(0);
2471     GLuint replay_program = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_program);
2472
2473     GLuint trace_shader = m_pCur_gl_packet->get_param_value<GLuint>(1);
2474     GLuint replay_shader = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_shader);
2475
2476     check_gl_error();
2477
2478     // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2479
2480     GLboolean was_shader = GL_ENTRYPOINT(glIsShader)(replay_shader);
2481     check_gl_error_quietly();
2482
2483     GLint marked_for_deletion = 0;
2484     GL_ENTRYPOINT(glGetShaderiv)(replay_shader, GL_DELETE_STATUS, &marked_for_deletion);
2485     check_gl_error_quietly();
2486
2487     if (entrypoint_id == VOGL_ENTRYPOINT_glDetachObjectARB)
2488         GL_ENTRYPOINT(glDetachObjectARB)(replay_program, replay_shader);
2489     else
2490     {
2491         VOGL_ASSERT(entrypoint_id == VOGL_ENTRYPOINT_glDetachShader);
2492         GL_ENTRYPOINT(glDetachShader)(replay_program, replay_shader);
2493     }
2494
2495     bool detach_failed = check_gl_error();
2496
2497     GLboolean is_shader = GL_ENTRYPOINT(glIsShader)(replay_shader);
2498     check_gl_error_quietly();
2499
2500     if (!detach_failed)
2501     {
2502         if ((marked_for_deletion) && (was_shader) && (!is_shader))
2503         {
2504             // The shader is really gone now.
2505             bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_shader);
2506             VOGL_ASSERT(was_deleted);
2507             VOGL_NOTE_UNUSED(was_deleted);
2508         }
2509     }
2510 }
2511
2512 //----------------------------------------------------------------------------------------------------------------------
2513 // vogl_gl_replayer::handle_link_program
2514 //----------------------------------------------------------------------------------------------------------------------
2515 void vogl_gl_replayer::handle_link_program(gl_entrypoint_id_t entrypoint_id)
2516 {
2517     check_gl_error();
2518
2519     GLuint trace_handle = m_pCur_gl_packet->get_param_value<GLuint>(0);
2520     GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2521
2522     GLboolean is_program = GL_ENTRYPOINT(glIsProgram)(replay_handle);
2523     check_gl_error();
2524     if (!is_program)
2525     {
2526         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);
2527     }
2528
2529     const json_document *pDoc = m_pCur_gl_packet->get_key_value_map().get_json_document("metadata");
2530
2531     if (!pDoc)
2532     {
2533         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);
2534     }
2535     else if ((pDoc) && (!pDoc->is_object()))
2536     {
2537         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);
2538         pDoc = NULL;
2539     }
2540
2541     int trace_active_attributes = 0;
2542     int trace_active_uniforms = 0;
2543     int trace_active_uniform_blocks = 0;
2544     int trace_link_status = 1;
2545
2546     VOGL_NOTE_UNUSED(trace_active_uniforms);
2547     VOGL_NOTE_UNUSED(trace_active_uniform_blocks);
2548
2549     if (pDoc)
2550     {
2551         const json_node &doc_root = *pDoc->get_root();
2552
2553         trace_link_status = doc_root.value_as_int("link_status");
2554         trace_active_attributes = doc_root.value_as_int("total_active_attributes");
2555         trace_active_uniforms = doc_root.value_as_int("total_active_uniforms");
2556         trace_active_uniform_blocks = doc_root.value_as_int("active_uniform_blocks");
2557
2558         const json_node *pAttrib_node = doc_root.find_child_array("active_attribs");
2559         if (pAttrib_node)
2560         {
2561             for (uint i = 0; i < pAttrib_node->size(); i++)
2562             {
2563                 const json_node *pAttrib = pAttrib_node->get_child(i);
2564                 if (!pAttrib)
2565                 {
2566                     VOGL_ASSERT_ALWAYS;
2567                     continue;
2568                 }
2569
2570                 const char *pName = pAttrib->value_as_string_ptr("name");
2571                 int attrib_loc = pAttrib->value_as_int("location", -1);
2572
2573                 if ((pName) && (pName[0]) && (attrib_loc >= 0))
2574                 {
2575                     if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2576                         GL_ENTRYPOINT(glBindAttribLocationARB)(replay_handle, attrib_loc, pName);
2577                     else
2578                         GL_ENTRYPOINT(glBindAttribLocation)(replay_handle, attrib_loc, reinterpret_cast<const GLchar *>(pName));
2579
2580                     check_gl_error();
2581                 }
2582             }
2583         }
2584
2585         const json_node *pOutputs_object = doc_root.find_child_array("active_outputs");
2586         if (pOutputs_object)
2587         {
2588             for (uint i = 0; i < pOutputs_object->size(); i++)
2589             {
2590                 const json_node *pOutput_node = pOutputs_object->get_child(i);
2591                 if (!pOutput_node)
2592                     continue;
2593
2594                 dynamic_string name(pOutput_node->value_as_string("name"));
2595                 if ((name.is_empty()) || (name.begins_with("gl_", true)))
2596                     continue;
2597
2598                 int location = pOutput_node->value_as_int("location");
2599                 int location_index = pOutput_node->value_as_int("location_index");
2600
2601                 if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_blend_func_extended") && GL_ENTRYPOINT(glBindFragDataLocationIndexed))
2602                 {
2603                     GL_ENTRYPOINT(glBindFragDataLocationIndexed)(replay_handle, location, location_index, reinterpret_cast<const GLchar *>(name.get_ptr()));
2604                 }
2605                 else
2606                 {
2607                     if (location_index)
2608                         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);
2609
2610                     GL_ENTRYPOINT(glBindFragDataLocation)(replay_handle, location, reinterpret_cast<const GLchar *>(name.get_ptr()));
2611                 }
2612
2613                 check_gl_error();
2614             }
2615         }
2616
2617         GLenum transform_feedback_mode = vogl_get_json_value_as_enum(doc_root, "transform_feedback_mode");
2618         GLint num_varyings = doc_root.value_as_int("transform_feedback_num_varyings");
2619         if (num_varyings)
2620         {
2621             const json_node *pTransform_feedback_varyings = doc_root.find_child_array("transform_feedback_varyings");
2622             if (pTransform_feedback_varyings)
2623             {
2624                 dynamic_string_array names;
2625
2626                 for (uint i = 0; i < pTransform_feedback_varyings->size(); i++)
2627                 {
2628                     const json_node *pVarying_node = pTransform_feedback_varyings->get_child(i);
2629                     if (!pVarying_node)
2630                         continue;
2631
2632                     GLint index = pVarying_node->value_as_int("index");
2633                     if (index < 0)
2634                         continue;
2635
2636                     dynamic_string name(pVarying_node->value_as_string("name"));
2637
2638                     //GLsizei size(pVarying_node->value_as_int("size"));
2639                     //GLenum type(vogl_get_json_value_as_enum(*pVarying_node, "type"));
2640
2641                     names.ensure_element_is_valid(index);
2642                     names[index] = name;
2643                 }
2644
2645                 vogl::vector<GLchar *> varyings(names.size());
2646                 for (uint i = 0; i < names.size(); i++)
2647                     varyings[i] = (GLchar *)(names[i].get_ptr());
2648
2649                 GL_ENTRYPOINT(glTransformFeedbackVaryings)(replay_handle, varyings.size(), varyings.get_ptr(), transform_feedback_mode);
2650                 check_gl_error();
2651             }
2652         }
2653     }
2654
2655     switch (entrypoint_id)
2656     {
2657         case VOGL_ENTRYPOINT_glLinkProgram:
2658         {
2659             GL_ENTRYPOINT(glLinkProgram)(replay_handle);
2660             break;
2661         }
2662         case VOGL_ENTRYPOINT_glLinkProgramARB:
2663         {
2664             GL_ENTRYPOINT(glLinkProgramARB)(replay_handle);
2665             break;
2666         }
2667         case VOGL_ENTRYPOINT_glProgramBinary:
2668         {
2669             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));
2670             break;
2671         }
2672         default:
2673         {
2674             VOGL_ASSERT_ALWAYS;
2675             return;
2676         }
2677     }
2678
2679     check_gl_error();
2680
2681     GLint replay_link_status = 0;
2682     GLint replay_active_attributes = 0;
2683     if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2684     {
2685         GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_LINK_STATUS_ARB, &replay_link_status);
2686         check_gl_error();
2687
2688         GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &replay_active_attributes);
2689         check_gl_error();
2690     }
2691     else
2692     {
2693         GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_LINK_STATUS, &replay_link_status);
2694         check_gl_error();
2695
2696         GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_ACTIVE_ATTRIBUTES, &replay_active_attributes);
2697         check_gl_error();
2698     }
2699
2700     if ((replay_link_status) || (!get_shared_state()->m_shadow_state.m_linked_programs.find_snapshot(replay_handle)))
2701     {
2702         bool success;
2703         if (entrypoint_id == VOGL_ENTRYPOINT_glProgramBinary)
2704             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));
2705         else
2706             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);
2707
2708         if (!success)
2709             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);
2710     }
2711
2712     if ((pDoc) && (replay_link_status != trace_link_status))
2713     {
2714         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);
2715     }
2716
2717     if (!replay_link_status)
2718     {
2719         vogl::vector<GLchar> log;
2720
2721         if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2722         {
2723             GLsizei length = 0;
2724             GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
2725             check_gl_error();
2726
2727             if (length)
2728             {
2729                 log.resize(length);
2730
2731                 GLint actual_length = 0;
2732                 GL_ENTRYPOINT(glGetInfoLogARB)(replay_handle, log.size(), &actual_length, reinterpret_cast<GLcharARB *>(log.get_ptr()));
2733                 check_gl_error();
2734             }
2735         }
2736         else
2737         {
2738             GLint length = 0;
2739             GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_INFO_LOG_LENGTH, &length);
2740             check_gl_error();
2741
2742             if (length)
2743             {
2744                 log.resize(length);
2745
2746                 GL_ENTRYPOINT(glGetShaderInfoLog)(replay_handle, log.size(), &length, log.get_ptr());
2747                 check_gl_error();
2748             }
2749         }
2750
2751         if ((log.size()) && (log[0]))
2752         {
2753             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());
2754         }
2755     }
2756
2757     if ((pDoc) && (replay_active_attributes != trace_active_attributes))
2758     {
2759         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);
2760     }
2761
2762     const json_node *pUniforms_node = pDoc ? pDoc->get_root()->find_child_array("active_uniforms") : NULL;
2763
2764     if (pUniforms_node)
2765     {
2766         glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
2767         if (it == get_shared_state()->m_glsl_program_hash_map.end())
2768             it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
2769         glsl_program_state &prog_state = it->second;
2770
2771         for (uint i = 0; i < pUniforms_node->size(); i++)
2772         {
2773             const json_node *pUniform = pUniforms_node->get_child(i);
2774             if (!pUniform)
2775             {
2776                 VOGL_ASSERT_ALWAYS;
2777                 continue;
2778             }
2779
2780             const char *pName = pUniform->value_as_string_ptr("name");
2781             if (!pName)
2782             {
2783                 VOGL_ASSERT_ALWAYS;
2784                 continue;
2785             }
2786             int trace_loc = pUniform->value_as_int("location");
2787             int trace_array_size = pUniform->value_as_int("size");
2788             //int trace_type = pUniform->value_as_int("type");
2789
2790             VOGL_ASSERT(trace_array_size >= 1);
2791
2792             if ((trace_loc < 0) || (trace_array_size <= 0))
2793                 continue;
2794
2795             if (trace_array_size > 1)
2796             {
2797                 dynamic_string element_name;
2798                 for (int i = 0; i < trace_array_size; i++)
2799                 {
2800                     element_name = pName;
2801                     int start_bracket_ofs = element_name.find_right('[');
2802                     if (start_bracket_ofs >= 0)
2803                         element_name.left(start_bracket_ofs);
2804                     element_name.format_append("[%u]", i);
2805
2806                     GLint element_trace_loc = trace_loc + i;
2807                     GLint element_replay_loc;
2808                     if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2809                         element_replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, reinterpret_cast<const GLcharARB *>(element_name.get_ptr()));
2810                     else
2811                         element_replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, reinterpret_cast<const GLchar *>(element_name.get_ptr()));
2812                     check_gl_error();
2813
2814                     if (element_replay_loc < 0)
2815                     {
2816                         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);
2817                     }
2818                     else
2819                     {
2820                         prog_state.m_uniform_locations.erase(element_trace_loc);
2821                         prog_state.m_uniform_locations.insert(element_trace_loc, element_replay_loc);
2822                     }
2823                 }
2824             }
2825             else if (trace_array_size == 1)
2826             {
2827                 GLint replay_loc;
2828                 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2829                     replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, reinterpret_cast<const GLcharARB *>(pName));
2830                 else
2831                     replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, reinterpret_cast<const GLchar *>(pName));
2832                 check_gl_error();
2833
2834                 if (replay_loc < 0)
2835                 {
2836                     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);
2837                 }
2838                 else
2839                 {
2840                     prog_state.m_uniform_locations.erase(trace_loc);
2841                     prog_state.m_uniform_locations.insert(trace_loc, replay_loc);
2842                 }
2843             }
2844         } // i
2845     }
2846 }
2847
2848 //----------------------------------------------------------------------------------------------------------------------
2849 // vogl_gl_replayer::post_draw_call
2850 // Called after each draw call or blit.
2851 //----------------------------------------------------------------------------------------------------------------------
2852 vogl_gl_replayer::status_t vogl_gl_replayer::post_draw_call()
2853 {
2854     VOGL_FUNC_TRACER
2855
2856     if (m_pCur_context_state->m_inside_gl_begin)
2857         return cStatusOK;
2858
2859     if (check_gl_error())
2860         return cStatusGLError;
2861
2862     bool is_draw = vogl_is_draw_entrypoint(m_pCur_gl_packet->get_entrypoint_id());
2863
2864     if ((m_flags & cGLReplayerDumpShadersOnDraw) && (is_draw))
2865     {
2866         dump_current_shaders();
2867     }
2868
2869     if (m_flags & cGLReplayerDumpFramebufferOnDraws)
2870     {
2871         bool should_dump = false;
2872
2873         if (m_dump_framebuffer_on_draw_frame_index != -1)
2874         {
2875             if (m_frame_index == m_dump_framebuffer_on_draw_frame_index)
2876                 should_dump = true;
2877         }
2878         else if ((m_dump_framebuffer_on_draw_first_gl_call_index >= 0) && (m_dump_framebuffer_on_draw_last_gl_call_index >= 0))
2879         {
2880             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);
2881         }
2882         else
2883         {
2884             should_dump = true;
2885         }
2886
2887         if (should_dump)
2888         {
2889             dump_current_framebuffer();
2890         }
2891     }
2892
2893     m_frame_draw_counter += is_draw;
2894
2895     return cStatusOK;
2896 }
2897
2898 //----------------------------------------------------------------------------------------------------------------------
2899 // vogl_gl_replayer::dump_framebuffer
2900 //----------------------------------------------------------------------------------------------------------------------
2901 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)
2902 {
2903     VOGL_FUNC_TRACER
2904
2905     uint trace_read_framebuffer = 0;
2906     if (read_framebuffer)
2907     {
2908         gl_handle_hash_map::const_iterator it = get_context_state()->m_framebuffers.search_table_for_value(read_framebuffer);
2909         if (it != get_context_state()->m_framebuffers.end())
2910             trace_read_framebuffer = it->second;
2911     }
2912
2913     uint trace_texture = replay_texture;
2914     if (replay_texture)
2915     {
2916         if (!get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_texture, trace_texture))
2917             vogl_warning_printf("%s: Failed finding GL handle %u in texture handle shadow!\n", VOGL_METHOD_NAME, replay_texture);
2918     }
2919
2920     uint trace_rbo = 0;
2921     if (replay_rbo)
2922     {
2923         if (!get_shared_state()->m_shadow_state.m_rbos.map_inv_handle_to_handle(replay_rbo, trace_rbo))
2924             vogl_error_printf("%s: Failed finding GL handle %u in RBO handle shadow!\n", VOGL_METHOD_NAME, replay_rbo);
2925     }
2926
2927     m_screenshot_buffer.resize(width * height * 3);
2928
2929     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);
2930
2931     if (!success)
2932     {
2933         process_entrypoint_warning("%s: vogl_copy_buffer_to_image() failed!\n", VOGL_METHOD_NAME);
2934         return false;
2935     }
2936
2937     size_t png_size = 0;
2938     void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(m_screenshot_buffer.get_ptr(), width, height, 3, &png_size, 1, true);
2939
2940     dynamic_string screenshot_filename(cVarArg, "%s_GLCTR%08llu_%s_FR%06u_DCTR%05llu_W%04i_H%04i_FBO%04u_%s",
2941                                        m_dump_framebuffer_on_draw_prefix.get_ptr(),
2942                                        (unsigned long long)m_pCur_gl_packet->get_call_counter(),
2943                                        g_vogl_entrypoint_descs[m_pCur_gl_packet->get_entrypoint_id()].m_pName,
2944                                        m_frame_index,
2945                                        (unsigned long long)m_frame_draw_counter,
2946                                        width, height,
2947                                        trace_read_framebuffer,
2948                                        g_gl_enums.find_gl_name(read_buffer));
2949
2950     if (internal_format != GL_NONE)
2951     {
2952         screenshot_filename += "_";
2953         screenshot_filename += g_gl_enums.find_gl_image_format_name(internal_format);
2954     }
2955
2956     if (orig_samples != 0)
2957         screenshot_filename += dynamic_string(cVarArg, "_MSAA%u", orig_samples);
2958     if (replay_texture)
2959         screenshot_filename += dynamic_string(cVarArg, "_TEX%04u", replay_texture);
2960     if (replay_rbo)
2961         screenshot_filename += dynamic_string(cVarArg, "_RBO%04u", replay_rbo);
2962
2963     screenshot_filename += ".png";
2964
2965     file_utils::create_directories(file_utils::get_pathname(screenshot_filename.get_ptr()), false);
2966
2967     if (!file_utils::write_buf_to_file(screenshot_filename.get_ptr(), pPNG_data, png_size))
2968     {
2969         process_entrypoint_error("%s: Failed writing framebuffer screenshot to file \"%s\"\n", VOGL_METHOD_NAME, screenshot_filename.get_ptr());
2970         success = false;
2971     }
2972     else
2973     {
2974         vogl_printf("%s: Wrote framebuffer screenshot to file \"%s\"\n", VOGL_METHOD_NAME, screenshot_filename.get_ptr());
2975     }
2976
2977     mz_free(pPNG_data);
2978
2979     return success;
2980 }
2981
2982 //----------------------------------------------------------------------------------------------------------------------
2983 // vogl_gl_replayer::dump_current_framebuffer
2984 //----------------------------------------------------------------------------------------------------------------------
2985 void vogl_gl_replayer::dump_current_framebuffer()
2986 {
2987     VOGL_FUNC_TRACER
2988
2989     uint draw_framebuffer_binding = vogl_get_gl_integer(GL_DRAW_FRAMEBUFFER_BINDING);
2990
2991     uint max_draw_buffers = vogl_get_gl_integer(GL_MAX_DRAW_BUFFERS);
2992     if (!max_draw_buffers)
2993     {
2994         process_entrypoint_warning("%s: GL_MAX_DRAW_BUFFERS is 0\n", VOGL_METHOD_NAME);
2995         return;
2996     }
2997
2998     //GL_COLOR_ATTACHMENT0-GL_COLOR_ATTACHMENT15, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT
2999
3000     vogl::vector<GLenum> draw_buffers(max_draw_buffers);
3001     for (uint i = 0; i < max_draw_buffers; i++)
3002         draw_buffers[i] = vogl_get_gl_integer(GL_DRAW_BUFFER0 + i);
3003
3004     if (!draw_framebuffer_binding)
3005     {
3006         for (uint i = 0; i < max_draw_buffers; i++)
3007             if (draw_buffers[i] != GL_NONE)
3008                 dump_framebuffer(m_pWindow->get_width(), m_pWindow->get_height(), 0, draw_buffers[i], GL_NONE, 0, 0, 0);
3009         return;
3010     }
3011
3012     // TODO: We should probably keep around a persistent set of per-context (or sharelist) remappers
3013     vogl_framebuffer_state fbo_state;
3014     if (!fbo_state.snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, draw_framebuffer_binding, GL_NONE))
3015     {
3016         process_entrypoint_warning("%s: Unable to snapshot current FBO %u\n", VOGL_METHOD_NAME, draw_framebuffer_binding);
3017         return;
3018     }
3019
3020     for (uint i = 0; i < draw_buffers.size(); i++)
3021     {
3022         if (draw_buffers[i] == GL_NONE)
3023             continue;
3024
3025         const vogl_framebuffer_attachment *pAttachment = fbo_state.get_attachments().find_value(draw_buffers[i]);
3026         if (!pAttachment)
3027         {
3028             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);
3029             continue;
3030         }
3031
3032         if (pAttachment->get_type() == GL_FRAMEBUFFER_DEFAULT)
3033             continue;
3034         else if (pAttachment->get_type() == GL_RENDERBUFFER)
3035         {
3036             GLuint rbo_handle = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
3037             if (!rbo_handle)
3038                 continue;
3039
3040             vogl_renderbuffer_state rbo_state;
3041             if (!rbo_state.snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, rbo_handle, GL_NONE))
3042             {
3043                 process_entrypoint_warning("%s: Failed getting RBO %u's' state!\n", VOGL_METHOD_NAME, rbo_handle);
3044                 continue;
3045             }
3046
3047             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))
3048                 continue;
3049
3050             uint width = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_WIDTH);
3051             uint height = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_HEIGHT);
3052             uint samples = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_SAMPLES);
3053             GLenum internal_format = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_INTERNAL_FORMAT);
3054
3055             if ((!width) || (!height) || (!internal_format))
3056             {
3057                 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);
3058                 continue;
3059             }
3060
3061             if (samples > 1)
3062             {
3063                 vogl_scoped_binding_state orig_framebuffers(GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER, GL_RENDERBUFFER);
3064
3065                 GLuint temp_rbo = 0;
3066                 GL_ENTRYPOINT(glGenRenderbuffers)(1, &temp_rbo);
3067                 check_gl_error();
3068
3069                 if (!temp_rbo)
3070                     continue;
3071
3072                 GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, temp_rbo);
3073                 check_gl_error();
3074
3075                 GL_ENTRYPOINT(glRenderbufferStorage)(GL_RENDERBUFFER, internal_format, width, height);
3076                 check_gl_error();
3077
3078                 GLuint temp_fbo = 0;
3079                 GL_ENTRYPOINT(glGenFramebuffers)(1, &temp_fbo);
3080                 check_gl_error();
3081
3082                 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, temp_fbo);
3083                 check_gl_error();
3084
3085                 GL_ENTRYPOINT(glFramebufferRenderbuffer)(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, temp_rbo);
3086                 check_gl_error();
3087
3088                 GLenum draw_buf = GL_COLOR_ATTACHMENT0;
3089                 GL_ENTRYPOINT(glDrawBuffers)(1, &draw_buf);
3090                 check_gl_error();
3091
3092                 GL_ENTRYPOINT(glReadBuffer)(GL_NONE);
3093                 check_gl_error();
3094
3095                 GLenum cur_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_DRAW_FRAMEBUFFER);
3096                 check_gl_error();
3097
3098                 if (cur_status == GL_FRAMEBUFFER_COMPLETE)
3099                 {
3100                     GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, draw_framebuffer_binding);
3101                     check_gl_error();
3102
3103                     // Save the framebuffer's readbuffer (it's per-framebuffer state, not context state).
3104                     vogl_scoped_state_saver state_saver(cGSTReadBuffer);
3105
3106                     GL_ENTRYPOINT(glReadBuffer)(draw_buffers[i]);
3107                     check_gl_error();
3108
3109                     GL_ENTRYPOINT(glBlitFramebuffer)(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3110
3111                     if (!check_gl_error())
3112                         dump_framebuffer(width, height, temp_fbo, GL_COLOR_ATTACHMENT0, internal_format, samples, 0, rbo_handle);
3113                     else
3114                     {
3115                         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);
3116                     }
3117                 }
3118
3119                 GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, 0);
3120                 check_gl_error();
3121
3122                 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, 0);
3123                 check_gl_error();
3124
3125                 GL_ENTRYPOINT(glDeleteFramebuffers)(1, &temp_fbo);
3126                 check_gl_error();
3127
3128                 GL_ENTRYPOINT(glDeleteRenderbuffers)(1, &temp_rbo);
3129                 check_gl_error();
3130             }
3131             else
3132             {
3133                 dump_framebuffer(width, height, draw_framebuffer_binding, draw_buffers[i], internal_format, 0, 0, rbo_handle);
3134             }
3135         }
3136         else if (pAttachment->get_type() == GL_TEXTURE)
3137         {
3138             GLuint tex_handle = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
3139             if (!tex_handle)
3140             {
3141                 process_entrypoint_warning("%s: Current FBO %u has a invalid object name\n", VOGL_METHOD_NAME, draw_framebuffer_binding);
3142                 continue;
3143             }
3144
3145             GLenum target = get_shared_state()->m_shadow_state.m_textures.get_target_inv(tex_handle);
3146             if (target == GL_NONE)
3147             {
3148                 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);
3149                 continue;
3150             }
3151
3152             if ((target == GL_TEXTURE_CUBE_MAP) || (target == GL_TEXTURE_CUBE_MAP_ARRAY))
3153                 target = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE);
3154
3155             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))
3156             {
3157                 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);
3158                 continue;
3159             }
3160
3161             uint level = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL);
3162             uint layer = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER);
3163             VOGL_NOTE_UNUSED(layer);
3164
3165             GLint width = 0, height = 0, samples = 0;
3166             GLenum internal_format = GL_NONE;
3167
3168             {
3169                 vogl_scoped_binding_state binding_saver;
3170                 binding_saver.save_textures();
3171
3172                 GL_ENTRYPOINT(glBindTexture)(target, tex_handle);
3173                 check_gl_error();
3174
3175                 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_WIDTH, &width);
3176                 check_gl_error();
3177
3178                 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_HEIGHT, &height);
3179                 check_gl_error();
3180
3181                 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_INTERNAL_FORMAT, reinterpret_cast<GLint *>(&internal_format));
3182                 check_gl_error();
3183
3184                 if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_texture_multisample"))
3185                 {
3186                     GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_SAMPLES, &samples);
3187                     check_gl_error();
3188                 }
3189             }
3190
3191             if ((!width) || (!height))
3192             {
3193                 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);
3194                 continue;
3195             }
3196
3197             if (samples > 1)
3198             {
3199                 process_entrypoint_warning("%s: Can't dump multisample texture FBO attachments yet\n", VOGL_METHOD_NAME);
3200                 continue;
3201             }
3202
3203             dump_framebuffer(width, height, draw_framebuffer_binding, draw_buffers[i], internal_format, 0, tex_handle, 0);
3204         }
3205     }
3206 }
3207
3208 //----------------------------------------------------------------------------------------------------------------------
3209 // vogl_gl_replayer::dump_current_shaders
3210 //----------------------------------------------------------------------------------------------------------------------
3211 void vogl_gl_replayer::dump_current_shaders()
3212 {
3213     VOGL_FUNC_TRACER
3214
3215     if (!m_pCur_context_state)
3216         return;
3217
3218     check_gl_error();
3219
3220     const GLuint replay_program = m_pCur_context_state->m_cur_replay_program;
3221
3222     // Get the current program.
3223     GLuint current_program = 0;
3224     GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, (GLint *)(&current_program));
3225     check_gl_error();
3226
3227     VOGL_ASSERT(replay_program == current_program);
3228
3229     if (!current_program)
3230         return;
3231
3232     // Get the attached shaders.
3233     GLsizei attached_shader_count = -1;
3234     GL_ENTRYPOINT(glGetProgramiv)(replay_program, GL_ATTACHED_SHADERS, &attached_shader_count);
3235     check_gl_error();
3236
3237     if (!attached_shader_count)
3238         return;
3239
3240     vogl::vector<GLuint> shaders(attached_shader_count);
3241     GLsizei actual_shader_count = 0;
3242     GL_ENTRYPOINT(glGetAttachedShaders)(replay_program,
3243                                         attached_shader_count,
3244                                         &actual_shader_count,
3245                                         shaders.get_ptr());
3246     check_gl_error();
3247
3248     VOGL_ASSERT(attached_shader_count == actual_shader_count); // Sanity check.
3249
3250     vogl_printf("Trace context 0x%" PRIx64 ", GL draw counter %" PRIu64 ", frame %u, replay program %u trace program %u has %d attached shaders:\n",
3251                cast_val_to_uint64(m_cur_trace_context), m_last_parsed_call_counter, m_frame_index,
3252                replay_program, m_pCur_context_state->m_cur_trace_program,
3253                attached_shader_count);
3254
3255     // Get source from shaders.
3256     vogl::vector<GLchar> source; // Shared buffer for each iteration.
3257     for (GLsizei i = 0; i < attached_shader_count; ++i)
3258     {
3259         const GLuint shader = shaders[i];
3260         GLint shader_type = 0;
3261         GL_ENTRYPOINT(glGetShaderiv)(shader, GL_SHADER_TYPE, &shader_type);
3262         check_gl_error();
3263
3264         vogl_printf("\n%s: %u\n", g_gl_enums.find_gl_name(shader_type), shader);
3265
3266         GLint source_length = -1; // Includes NUL terminator.
3267         GL_ENTRYPOINT(glGetShaderiv)(shader, GL_SHADER_SOURCE_LENGTH, &source_length);
3268         check_gl_error();
3269
3270         VOGL_ASSERT(source_length > 0);
3271
3272         source.resize(source_length);
3273         GLint actual_length = 0; // Excludes NUL terminator!
3274         GL_ENTRYPOINT(glGetShaderSource)(shader, source_length, &actual_length, source.get_ptr());
3275         check_gl_error();
3276
3277         VOGL_ASSERT(source_length == actual_length + 1); // Sanity check.
3278         vogl_printf("%.*s\n", source_length, source.get_const_ptr());
3279     }
3280     vogl_printf("========\n");
3281 }
3282
3283 //----------------------------------------------------------------------------------------------------------------------
3284 // vogl_gl_replayer::handle_ShaderSource
3285 // Handle ShaderSource and ShaderSourceARB.
3286 //----------------------------------------------------------------------------------------------------------------------
3287 vogl_gl_replayer::status_t vogl_gl_replayer::handle_ShaderSource(GLhandleARB trace_object,
3288                                                                GLsizei count,
3289                                                                const vogl_client_memory_array trace_strings_glchar_ptr_array,
3290                                                                const GLint *pTrace_lengths)
3291 {
3292     VOGL_FUNC_TRACER
3293
3294     GLhandleARB replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
3295
3296     // m_pCur_gl_packet->get_param_client_memory_data_size(2) / sizeof(const GLchar *);
3297     const uint trace_strings_count = trace_strings_glchar_ptr_array.size();
3298     const uint trace_lengths_count = m_pCur_gl_packet->get_param_client_memory_data_size(3) / sizeof(const GLint);
3299
3300     if ((trace_strings_glchar_ptr_array.get_ptr()) &&
3301         (trace_strings_count != static_cast<uint>(count)))
3302     {
3303         process_entrypoint_error("%s: Trace strings array has an invalid count (expected %u, got %u)\n",
3304                                  VOGL_METHOD_NAME, count, trace_strings_count);
3305         return cStatusHardFailure;
3306     }
3307
3308     if ((pTrace_lengths) && (trace_lengths_count != static_cast<uint>(count)))
3309     {
3310         process_entrypoint_error("%s: Trace lengths array has an invalid count (expected %u, got %u)\n",
3311                                  VOGL_METHOD_NAME, count, trace_lengths_count);
3312         return cStatusHardFailure;
3313     }
3314
3315     vogl::vector<const GLcharARB *> strings(count);
3316     vogl::vector<GLint> lengths(count);
3317
3318     const key_value_map &map = m_pCur_gl_packet->get_key_value_map();
3319
3320     vogl::vector<uint8_vec> blobs(count);
3321
3322     for (GLsizei i = 0; i < count; i++)
3323     {
3324         strings[i] = NULL;
3325         if ((trace_strings_glchar_ptr_array.get_ptr()) &&
3326             (trace_strings_glchar_ptr_array.get_element<vogl_trace_ptr_value>(i) != 0))
3327         {
3328             strings[i] = "";
3329         }
3330
3331         lengths[i] = pTrace_lengths ? pTrace_lengths[i] : 0;
3332
3333         key_value_map::const_iterator it = map.find(i);
3334         if (it == map.end())
3335         {
3336             if (lengths[i] > 0)
3337             {
3338                 process_entrypoint_error("%s: Failed finding blob for non-empty string %i in packet's key value map\n",
3339                                          VOGL_METHOD_NAME, i);
3340                 return cStatusHardFailure;
3341             }
3342             continue;
3343         }
3344
3345         const uint8_vec *pBlob = it->second.get_blob();
3346         if (!pBlob)
3347         {
3348             process_entrypoint_error("%s: Can't convert string %i to a blob\n", VOGL_METHOD_NAME, i);
3349             return cStatusHardFailure;
3350         }
3351
3352         blobs[i] = *pBlob;
3353         uint8_vec &blob = blobs[i];
3354
3355         if ((pTrace_lengths) && (pTrace_lengths[i] >= 0))
3356         {
3357             if (static_cast<uint>(pTrace_lengths[i]) != blob.size())
3358             {
3359                 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());
3360                 lengths[i] = blob.size();
3361             }
3362         }
3363         else
3364         {
3365             if ((blob.size()) && (blob.back() != '\0'))
3366             {
3367                 process_entrypoint_warning("%s: String %u doesn't end in 0 terminator - appending terminator\n", VOGL_METHOD_NAME, i);
3368
3369                 blob.push_back('\0');
3370             }
3371
3372             VOGL_ASSERT(blob.size() &&
3373                           (blob.back() == '\0') &&
3374                           (blob.size() == (1 + vogl_strlen(reinterpret_cast<const char *>(blob.get_ptr())))));
3375         }
3376
3377         strings[i] = reinterpret_cast<const GLcharARB *>(blob.get_ptr());
3378     }
3379
3380     if (m_pCur_gl_packet->get_entrypoint_id() == VOGL_ENTRYPOINT_glShaderSource)
3381     {
3382         GL_ENTRYPOINT(glShaderSource)(replay_object,
3383                                       count,
3384                                       trace_strings_glchar_ptr_array.get_ptr() ? (GLchar * const *)strings.get_ptr() : NULL,
3385                                       pTrace_lengths ? lengths.get_ptr() : NULL);
3386     }
3387     else
3388     {
3389         GL_ENTRYPOINT(glShaderSourceARB)(replay_object,
3390                                          count,
3391                                          trace_strings_glchar_ptr_array.get_ptr() ? strings.get_ptr() : NULL,
3392                                          pTrace_lengths ? lengths.get_ptr() : NULL);
3393     }
3394     return cStatusOK;
3395 }
3396
3397 //----------------------------------------------------------------------------------------------------------------------
3398 // vogl_gl_replayer::display_list_bind_callback
3399 // handle is in the trace namespace
3400 //----------------------------------------------------------------------------------------------------------------------
3401 void vogl_gl_replayer::display_list_bind_callback(vogl_namespace_t handle_namespace, GLenum target, GLuint handle, void *pOpaque)
3402 {
3403     VOGL_FUNC_TRACER
3404
3405     vogl_gl_replayer *pReplayer = static_cast<vogl_gl_replayer *>(pOpaque);
3406
3407     if (handle_namespace == VOGL_NAMESPACE_TEXTURES)
3408     {
3409         if ((handle) && (target != GL_NONE))
3410         {
3411             // A conditional update because we can't really test to see if the bind inside the display list really succeeded.
3412             pReplayer->get_shared_state()->m_shadow_state.m_textures.conditional_update(handle, GL_NONE, target);
3413         }
3414     }
3415     else
3416     {
3417         // TODO - right now the display list whitelist doens't let anything else get bound.
3418         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);
3419     }
3420 }
3421
3422 //----------------------------------------------------------------------------------------------------------------------
3423 // Helper macros - slightly simplifies hand-generating entrypoints with EXT/ARB/etc. variants
3424 //----------------------------------------------------------------------------------------------------------------------
3425 #define SWITCH_GL_ENTRYPOINT2(e0, e1, ...)                 \
3426     if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3427         result = GL_ENTRYPOINT(e0)(__VA_ARGS__);           \
3428     else                                                   \
3429         result = GL_ENTRYPOINT(e1)(__VA_ARGS__);
3430
3431 #define SWITCH_GL_ENTRYPOINT3(e0, e1, e2, ...)                  \
3432     if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0))      \
3433         result = GL_ENTRYPOINT(e0)(__VA_ARGS__);                \
3434     else if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e1)) \
3435         result = GL_ENTRYPOINT(e1)(__VA_ARGS__);                \
3436     else                                                        \
3437         result = GL_ENTRYPOINT(e2)(__VA_ARGS__);
3438
3439 #define SWITCH_GL_ENTRYPOINT2_VOID(e0, e1, ...)            \
3440     if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3441         GL_ENTRYPOINT(e0)(__VA_ARGS__);                    \
3442     else                                                   \
3443         GL_ENTRYPOINT(e1)(__VA_ARGS__);
3444
3445 #define SWITCH_GL_ENTRYPOINT3_VOID(e0, e1, e2, ...)             \
3446     if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0))      \
3447         GL_ENTRYPOINT(e0)(__VA_ARGS__);                         \
3448     else if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e1)) \
3449         GL_ENTRYPOINT(e1)(__VA_ARGS__);                         \
3450     else                                                        \
3451         GL_ENTRYPOINT(e2)(__VA_ARGS__);
3452
3453 //----------------------------------------------------------------------------------------------------------------------
3454 // vogl_replayer::process_gl_entrypoint_packet
3455 // This will be called during replaying, or when building display lists during state restoring.
3456 //----------------------------------------------------------------------------------------------------------------------
3457 vogl_gl_replayer::status_t vogl_gl_replayer::process_gl_entrypoint_packet(vogl_trace_packet& trace_packet)
3458 {
3459     m_pCur_gl_packet = &trace_packet;
3460
3461     status_t status = cStatusOK;
3462
3463     if (m_pPending_snapshot)
3464     {
3465         status = process_applying_pending_snapshot();
3466         if (status != cStatusOK)
3467             return status;
3468     }
3469
3470     if (m_pending_make_current_packet.is_valid())
3471     {
3472         status = process_pending_make_current();
3473         if (status != cStatusOK)
3474             return status;
3475     }
3476
3477     const vogl_trace_gl_entrypoint_packet &entrypoint_packet = trace_packet.get_entrypoint_packet();
3478
3479     m_last_parsed_call_counter = entrypoint_packet.m_call_counter;
3480
3481     status = process_gl_entrypoint_packet_internal(trace_packet);
3482
3483     if (status != cStatusResizeWindow)
3484         m_last_processed_call_counter = entrypoint_packet.m_call_counter;
3485
3486     m_pCur_gl_packet = NULL;
3487
3488     return status;
3489 }
3490
3491 //----------------------------------------------------------------------------------------------------------------------
3492 // vogl_replayer::process_gl_entrypoint_packet_internal
3493 // This will be called during replaying, or when building display lists during state restoring.
3494 //----------------------------------------------------------------------------------------------------------------------
3495 vogl_gl_replayer::status_t vogl_gl_replayer::process_gl_entrypoint_packet_internal(vogl_trace_packet& trace_packet)
3496 {
3497     VOGL_FUNC_TRACER
3498
3499     m_at_frame_boundary = false;
3500
3501     const vogl_trace_gl_entrypoint_packet &gl_entrypoint_packet = trace_packet.get_entrypoint_packet();
3502     const gl_entrypoint_id_t entrypoint_id = trace_packet.get_entrypoint_id();
3503
3504     if (m_flags & cGLReplayerDebugMode)
3505         dump_trace_gl_packet_debug_info(gl_entrypoint_packet);
3506
3507     if (m_flags & cGLReplayerDebugMode)
3508         dump_packet_as_func_call(trace_packet);
3509
3510     if (m_flags & cGLReplayerDumpAllPackets)
3511         print_detailed_context(cDebugConsoleMessage);
3512
3513     if (entrypoint_id == VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
3514         return process_internal_trace_command(gl_entrypoint_packet);
3515
3516     status_t status = cStatusOK;
3517
3518     if (gl_entrypoint_packet.m_context_handle != m_cur_trace_context)
3519     {
3520         status = switch_contexts(gl_entrypoint_packet.m_context_handle);
3521         if (status != cStatusOK)
3522             return status;
3523     }
3524
3525     bool processed_glx_packet = true;
3526     switch (entrypoint_id)
3527     {
3528         case VOGL_ENTRYPOINT_glXDestroyContext:
3529         {
3530             const Display *dpy = m_pWindow->get_display();
3531
3532             vogl_trace_context_ptr_value trace_context = trace_packet.get_param_ptr_value(1);
3533             GLXContext replay_context = remap_context(trace_context);
3534
3535             if ((trace_context) && (!replay_context))
3536             {
3537                 process_entrypoint_error("%s: Failed remapping GL trace context 0x%" PRIx64 "\n", VOGL_METHOD_NAME, (uint64_t)trace_context);
3538                 return cStatusHardFailure;
3539             }
3540
3541             if (trace_context == m_cur_trace_context)
3542             {
3543                 process_entrypoint_warning("%s: glXDestroyContext() called while trace context 0x%" PRIx64 " is still current, forcing it to not be current\n",
3544                                            VOGL_METHOD_NAME, (uint64_t)trace_context);
3545
3546                 m_cur_trace_context = 0;
3547                 m_cur_replay_context = 0;
3548                 m_pCur_context_state = NULL;
3549             }
3550
3551             GL_ENTRYPOINT(glXDestroyContext)(dpy, replay_context);
3552
3553             destroy_context(trace_context);
3554
3555             break;
3556         }
3557         case VOGL_ENTRYPOINT_glXMakeCurrent:
3558         case VOGL_ENTRYPOINT_glXMakeContextCurrent:
3559         {
3560             Bool trace_result = trace_packet.get_return_value<Bool>();
3561
3562             vogl_trace_context_ptr_value trace_context = trace_packet.get_param_ptr_value((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) ? 2 : 3);
3563
3564             // pContext_state can be NULL!
3565             context_state *pContext_state = get_trace_context_state(trace_context);
3566             GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
3567
3568             if ((trace_context) && (!replay_context))
3569             {
3570                 process_entrypoint_error("%s, Failed remapping GL context\n", VOGL_METHOD_NAME);
3571                 return cStatusHardFailure;
3572             }
3573
3574             int viewport_x = trace_packet.get_key_value_map().get_int(string_hash("viewport_x"));
3575             VOGL_NOTE_UNUSED(viewport_x);
3576             int viewport_y = trace_packet.get_key_value_map().get_int(string_hash("viewport_y"));
3577             VOGL_NOTE_UNUSED(viewport_y);
3578             int viewport_width = trace_packet.get_key_value_map().get_int(string_hash("viewport_width"));
3579             VOGL_NOTE_UNUSED(viewport_width);
3580             int viewport_height = trace_packet.get_key_value_map().get_int(string_hash("viewport_height"));
3581             VOGL_NOTE_UNUSED(viewport_height);
3582             int win_width = trace_packet.get_key_value_map().get_int(string_hash("win_width"));
3583             int win_height = trace_packet.get_key_value_map().get_int(string_hash("win_height"));
3584
3585             // 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.
3586             if ((trace_context) && (trace_result))
3587             {
3588                 if ((win_width) && (win_height))
3589                 {
3590                     if (!(m_flags & cGLReplayerLockWindowDimensions))
3591                     {
3592                         if ((m_pWindow->get_width() != win_width) || (m_pWindow->get_height() != win_height))
3593                         {
3594                             m_pending_make_current_packet = *m_pCur_gl_packet;
3595
3596                             status = trigger_pending_window_resize(win_width, win_height);
3597
3598                             vogl_printf("%s: Deferring glXMakeCurrent() until window resizes to %ux%u\n", VOGL_METHOD_NAME, win_width, win_height);
3599                         }
3600                     }
3601                 }
3602             }
3603
3604             if (status != cStatusResizeWindow)
3605             {
3606                 const Display *dpy = m_pWindow->get_display();
3607                 GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
3608
3609                 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
3610                 if (!result)
3611                 {
3612                     if (trace_result)
3613                     {
3614                         process_entrypoint_error("%s: Failed making context current, but in the trace this call succeeded!\n", VOGL_METHOD_NAME);
3615                         return cStatusHardFailure;
3616                     }
3617                     else
3618                     {
3619                         process_entrypoint_warning("%s: Failed making context current, in the trace this call also failed\n", VOGL_METHOD_NAME);
3620                     }
3621                 }
3622                 else
3623                 {
3624                     m_cur_trace_context = trace_context;
3625                     m_cur_replay_context = replay_context;
3626                     m_pCur_context_state = pContext_state;
3627
3628                     if (!trace_result)
3629                     {
3630                         process_entrypoint_warning("%s: Context was successfuly made current, but this operation failed in the trace\n", VOGL_METHOD_NAME);
3631                     }
3632
3633 #if 0
3634                                 vogl_printf("glXMakeCurrent(): Trace Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
3635                                            viewport_x, viewport_y,
3636                                            viewport_width, viewport_height,
3637                                            win_width, win_height);
3638 #endif
3639
3640                     if (m_cur_replay_context)
3641                     {
3642                         if (!handle_context_made_current())
3643                             return cStatusHardFailure;
3644                     }
3645                 }
3646             }
3647
3648             break;
3649         }
3650         case VOGL_ENTRYPOINT_glXQueryVersion:
3651         {
3652             int major = 0, minor = 0;
3653             Bool status = GL_ENTRYPOINT(glXQueryVersion)(m_pWindow->get_display(), &major, &minor);
3654             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,
3655                                        *trace_packet.get_param_client_memory<int>(1),
3656                                        *trace_packet.get_param_client_memory<int>(2),
3657                                        trace_packet.get_return_value<Bool>());
3658
3659             break;
3660         }
3661         case VOGL_ENTRYPOINT_glXChooseFBConfig:
3662         {
3663             // TODO
3664             break;
3665         }
3666         case VOGL_ENTRYPOINT_glXGetFBConfigAttrib:
3667         {
3668             // TODO
3669             break;
3670         }
3671         case VOGL_ENTRYPOINT_glXGetVisualFromFBConfig:
3672         {
3673             // TODO
3674             break;
3675         }
3676         case VOGL_ENTRYPOINT_glXGetProcAddress:
3677         case VOGL_ENTRYPOINT_glXGetProcAddressARB:
3678         {
3679             const GLubyte *procName = trace_packet.get_param_client_memory<GLubyte>(0);
3680             vogl_trace_ptr_value trace_func_ptr_value = trace_packet.get_return_ptr_value();
3681
3682             void *pFunc = (void *)GL_ENTRYPOINT(glXGetProcAddress)(procName);
3683
3684             if ((pFunc != NULL) != (trace_func_ptr_value != 0))
3685             {
3686                 process_entrypoint_warning("%s: glXGetProcAddress of function %s %s in the replay, but %s in the trace\n", VOGL_METHOD_NAME,
3687                                            (const char *)procName,
3688                                            (pFunc != NULL) ? "succeeded" : "failed",
3689                                            (trace_func_ptr_value != 0) ? "succeeded" : "failed");
3690             }
3691
3692             break;
3693         }
3694         case VOGL_ENTRYPOINT_glXCreateNewContext:
3695         {
3696             Display *dpy = m_pWindow->get_display();
3697             GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3698             int render_type = trace_packet.get_param_value<GLint>(2);
3699
3700             vogl_trace_context_ptr_value trace_share_context = trace_packet.get_param_ptr_value(3);
3701             GLXContext replay_share_context = remap_context(trace_share_context);
3702
3703             if ((trace_share_context) && (!replay_share_context))
3704             {
3705                 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3706             }
3707
3708             Bool direct = trace_packet.get_param_value<Bool>(4);
3709             vogl_trace_context_ptr_value trace_context = trace_packet.get_return_ptr_value();
3710
3711             if (m_flags & cGLReplayerForceDebugContexts)
3712             {
3713                 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);
3714
3715                 status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, NULL, 0, false);
3716                 if (status != cStatusOK)
3717                     return status;
3718             }
3719             else
3720             {
3721                 GLXContext replay_context = GL_ENTRYPOINT(glXCreateNewContext)(dpy, fb_config, render_type, replay_share_context, direct);
3722
3723                 if (!replay_context)
3724                 {
3725                     if (trace_context)
3726                     {
3727                         process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
3728                         return cStatusHardFailure;
3729                     }
3730                     else
3731                     {
3732                         process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
3733                     }
3734                 }
3735
3736                 if (replay_context)
3737                 {
3738                     if (trace_context)
3739                     {
3740                         context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateNewContext, NULL, 0);
3741                         VOGL_NOTE_UNUSED(pContext_state);
3742                     }
3743                     else
3744                     {
3745                         GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
3746                     }
3747                 }
3748             }
3749
3750             break;
3751         }
3752         case VOGL_ENTRYPOINT_glXCreateContext:
3753         {
3754             Display *dpy = m_pWindow->get_display();
3755
3756             vogl_trace_context_ptr_value trace_share_context = trace_packet.get_param_ptr_value(2);
3757             GLXContext replay_share_context = remap_context(trace_share_context);
3758
3759             if ((trace_share_context) && (!replay_share_context))
3760             {
3761                 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3762             }
3763
3764             GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3765             Bool direct = trace_packet.get_param_value<Bool>(3);
3766             vogl_trace_context_ptr_value trace_context = trace_packet.get_return_ptr_value();
3767
3768             if (m_flags & cGLReplayerForceDebugContexts)
3769             {
3770                 status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, NULL, 0, false);
3771                 if (status != cStatusOK)
3772                     return status;
3773             }
3774             else
3775             {
3776                 XVisualInfo *pVisual_info = GL_ENTRYPOINT(glXGetVisualFromFBConfig)(dpy, fb_config);
3777
3778                 GLXContext replay_context = GL_ENTRYPOINT(glXCreateContext)(dpy, pVisual_info, replay_share_context, direct);
3779
3780                 if (!replay_context)
3781                 {
3782                     if (trace_context)
3783                     {
3784                         process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
3785                         return cStatusHardFailure;
3786                     }
3787                     else
3788                     {
3789                         process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
3790                     }
3791                 }
3792
3793                 if (replay_context)
3794                 {
3795                     if (trace_context)
3796                     {
3797                         context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateContext, NULL, 0);
3798                         VOGL_NOTE_UNUSED(pContext_state);
3799                     }
3800                     else
3801                     {
3802                         GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
3803                     }
3804                 }
3805             }
3806
3807             break;
3808         }
3809         case VOGL_ENTRYPOINT_glXCreateContextAttribsARB:
3810         {
3811             Display *dpy = m_pWindow->get_display();
3812             GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3813
3814             vogl_trace_ptr_value trace_share_context = trace_packet.get_param_ptr_value(2);
3815             GLXContext replay_share_context = remap_context(trace_share_context);
3816
3817             if ((trace_share_context) && (!replay_share_context))
3818             {
3819                 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3820             }
3821
3822             Bool direct = trace_packet.get_param_value<Bool>(3);
3823             const int *pTrace_attrib_list = static_cast<const int *>(trace_packet.get_param_client_memory_ptr(4));
3824             const uint trace_attrib_list_size = trace_packet.get_param_client_memory_data_size(4) / sizeof(int);
3825
3826             vogl_trace_ptr_value trace_context = trace_packet.get_return_ptr_value();
3827
3828             status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, pTrace_attrib_list, trace_attrib_list_size, true);
3829             if (status != cStatusOK)
3830                 return status;
3831
3832             break;
3833         }
3834         case VOGL_ENTRYPOINT_glXSwapBuffers:
3835         {
3836             check_program_binding_shadow();
3837
3838             if (m_flags & cGLReplayerLowLevelDebugMode)
3839             {
3840                 if (!validate_program_and_shader_handle_tables())
3841                     vogl_warning_printf("%s: Failed validating program/shaders against handle mapping tables\n", VOGL_METHOD_NAME);
3842                 if (!validate_textures())
3843                     vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
3844             }
3845
3846             const Display *dpy = m_pWindow->get_display();
3847             GLXDrawable drawable = m_pWindow->get_xwindow();
3848
3849             if ((m_flags & cGLReplayerHashBackbuffer) || (m_flags & cGLReplayerDumpScreenshots) || (m_flags & cGLReplayerDumpBackbufferHashes))
3850             {
3851                 snapshot_backbuffer();
3852             }
3853
3854             if (m_dump_frontbuffer_filename.has_content())
3855             {
3856                 dump_frontbuffer_to_file(m_dump_frontbuffer_filename);
3857                 m_dump_frontbuffer_filename.clear();
3858             }
3859
3860             GL_ENTRYPOINT(glXSwapBuffers)(dpy, drawable);
3861
3862             if (m_swap_sleep_time)
3863                 vogl_sleep(m_swap_sleep_time);
3864
3865             status = cStatusNextFrame;
3866
3867             m_at_frame_boundary = true;
3868
3869             if (m_flags & cGLReplayerDebugMode)
3870             {
3871                 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);
3872             }
3873
3874             m_frame_index++;
3875             m_total_swaps++;
3876
3877             m_frame_draw_counter = 0;
3878
3879             int win_width = trace_packet.get_key_value_map().get_int(string_hash("win_width"));
3880             int win_height = trace_packet.get_key_value_map().get_int(string_hash("win_height"));
3881             if ((win_width) && (win_height))
3882             {
3883                 if (!(m_flags & cGLReplayerLockWindowDimensions))
3884                 {
3885                     if ((win_width != m_pWindow->get_width()) || (win_height != m_pWindow->get_height()))
3886                     {
3887                         // TODO: This resize might need to be deferred until the window system actually resizes the window.
3888                         //m_pWindow->resize(win_width, win_height);
3889                         trigger_pending_window_resize(win_width, win_height);
3890
3891                         vogl_printf("%s: Resizing window after swap to %ux%u\n", VOGL_METHOD_NAME, win_width, win_height);
3892                     }
3893                 }
3894             }
3895
3896             break;
3897         }
3898         case VOGL_ENTRYPOINT_glXWaitX:
3899         {
3900             VOGL_REPLAY_LOAD_PARAMS_HELPER_glXWaitX;
3901
3902             VOGL_REPLAY_CALL_GL_HELPER_glXWaitX;
3903
3904             break;
3905         }
3906         case VOGL_ENTRYPOINT_glXWaitGL:
3907         {
3908             VOGL_REPLAY_LOAD_PARAMS_HELPER_glXWaitGL;
3909
3910             VOGL_REPLAY_CALL_GL_HELPER_glXWaitGL;
3911
3912             break;
3913         }
3914         case VOGL_ENTRYPOINT_glXIsDirect:
3915         {
3916             const Display *dpy = m_pWindow->get_display();
3917
3918             vogl_trace_ptr_value trace_context = trace_packet.get_param_ptr_value(1);
3919             GLXContext replay_context = remap_context(trace_context);
3920
3921             Bool replay_is_direct = GL_ENTRYPOINT(glXIsDirect)(dpy, replay_context);
3922             Bool trace_is_direct = trace_packet.get_return_value<Bool>();
3923
3924             if (replay_is_direct != trace_is_direct)
3925             {
3926                 process_entrypoint_warning("%s: glXIsDirect() returned different results while replaying (%u) vs tracing (%u)!\n", VOGL_METHOD_NAME, replay_is_direct, trace_is_direct);
3927             }
3928
3929             break;
3930         }
3931         case VOGL_ENTRYPOINT_glXGetCurrentContext:
3932         {
3933             GLXContext replay_context = GL_ENTRYPOINT(glXGetCurrentContext)();
3934             vogl_trace_ptr_value trace_context = trace_packet.get_return_ptr_value();
3935
3936             if ((replay_context != 0) != (trace_context != 0))
3937             {
3938                 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);
3939             }
3940
3941             break;
3942         }
3943         case VOGL_ENTRYPOINT_glXCreateWindow:
3944         case VOGL_ENTRYPOINT_glXDestroyWindow:
3945         case VOGL_ENTRYPOINT_glXChooseVisual:
3946         case VOGL_ENTRYPOINT_glXGetCurrentDisplay:
3947         case VOGL_ENTRYPOINT_glXQueryDrawable:
3948         case VOGL_ENTRYPOINT_glXQueryExtension:
3949         case VOGL_ENTRYPOINT_glXQueryExtensionsString:
3950         case VOGL_ENTRYPOINT_glXSwapIntervalEXT:
3951         case VOGL_ENTRYPOINT_glXSwapIntervalSGI:
3952         case VOGL_ENTRYPOINT_glXGetCurrentDrawable:
3953         case VOGL_ENTRYPOINT_glXGetCurrentReadDrawable:
3954         case VOGL_ENTRYPOINT_glXQueryContext:
3955         case VOGL_ENTRYPOINT_glXGetClientString:
3956         case VOGL_ENTRYPOINT_glXGetConfig:
3957         case VOGL_ENTRYPOINT_glXGetFBConfigs:
3958         {
3959             // TODO
3960             break;
3961         }
3962         default:
3963         {
3964             processed_glx_packet = false;
3965             break;
3966         }
3967     }
3968
3969     if (processed_glx_packet)
3970     {
3971         // TODO: Check for GLX errors?
3972         return status;
3973     }
3974
3975     if (!m_cur_replay_context)
3976     {
3977         process_entrypoint_error("%s: Trace contains a GL call with no current context! Skipping call.\n", VOGL_METHOD_NAME);
3978         return cStatusSoftFailure;
3979     }
3980
3981     VOGL_ASSERT(m_pCur_context_state);
3982     m_pCur_context_state->m_last_call_counter = m_last_parsed_call_counter;
3983
3984 #ifdef VOGL_BUILD_DEBUG
3985     VOGL_ASSERT(get_trace_context_state(m_cur_trace_context) == m_pCur_context_state);
3986 #endif
3987
3988     // Add call to current display list
3989     if ((get_context_state()->is_composing_display_list()) && (g_vogl_entrypoint_descs[entrypoint_id].m_is_listable))
3990     {
3991         if (!vogl_display_list_state::is_call_listable(entrypoint_id, trace_packet))
3992         {
3993             if (!g_vogl_entrypoint_descs[entrypoint_id].m_whitelisted_for_displaylists)
3994                 process_entrypoint_error("%s: Failed serializing trace packet into display list shadow! Call is not listable.\n", VOGL_FUNCTION_NAME);
3995             else
3996                 process_entrypoint_warning("%s: Failed serializing trace packet into display list shadow! Call with these parameters is not listable.\n", VOGL_FUNCTION_NAME);
3997         }
3998         else
3999         {
4000             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))
4001             {
4002                 process_entrypoint_warning("%s: Failed adding current packet to display list shadow!\n", VOGL_METHOD_NAME);
4003             }
4004         }
4005     }
4006
4007     switch (entrypoint_id)
4008     {
4009 // ----- Create simple auto-generated replay funcs - voglgen creates this inc file from the funcs in gl_glx_simple_replay_funcs.txt
4010 // These simple GL entrypoints only take value params that don't require handle remapping, or simple pointers to client memory
4011 // (typically pointers to fixed size buffers, or params directly controlling the size of buffers).
4012 #define VOGL_SIMPLE_REPLAY_FUNC_BEGIN(name, num_params) \
4013     case VOGL_ENTRYPOINT_##name:                        \
4014     { 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 \
4015     GL_ENTRYPOINT(name)(
4016 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_VALUE(type, index) trace_packet.get_param_value<type>(index)
4017 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_SEPERATOR ,
4018 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_CLIENT_MEMORY(type, index) trace_packet.get_param_client_memory<type>(index)
4019 #define VOGL_SIMPLE_REPLAY_FUNC_END(name) ); \
4020     break;                                  \
4021     }
4022 #include "gl_glx_simple_replay_funcs.inc"
4023 #undef VOGL_SIMPLE_REPLAY_FUNC_BEGIN
4024 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_VALUE
4025 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_SEPERATOR
4026 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_CLIENT_MEMORY
4027 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_END
4028         // -----
4029         case VOGL_ENTRYPOINT_glXUseXFont:
4030         {
4031             const key_value_map &key_value_map = trace_packet.get_key_value_map();
4032
4033             const dynamic_string *pFont_name = key_value_map.get_string_ptr("font_name");
4034             if ((!pFont_name) || (pFont_name->is_empty()))
4035             {
4036                 process_entrypoint_warning("%s: Couldn't find font_name key, or key was empty - unable to call glXUseXFont()!\n", VOGL_METHOD_NAME);
4037             }
4038             else
4039             {
4040                 XFontStruct *pFont = XLoadQueryFont(m_pWindow->get_display(), pFont_name->get_ptr());
4041                 if (!pFont)
4042                 {
4043                     process_entrypoint_warning("%s: Couldn't load X font %s  - unable to call glXUseXFont()!\n", VOGL_METHOD_NAME, pFont_name->get_ptr());
4044                 }
4045                 else
4046                 {
4047                     GLint first = trace_packet.get_param_value<int>(1);
4048                     GLint count = trace_packet.get_param_value<int>(2);
4049                     int trace_list_base = trace_packet.get_param_value<int>(3);
4050                     GLuint replay_list_base = map_handle(get_shared_state()->m_lists, trace_list_base);
4051
4052                     GL_ENTRYPOINT(glXUseXFont)(pFont->fid, first, count, replay_list_base);
4053
4054                     XFreeFont(m_pWindow->get_display(), pFont);
4055
4056                     if (get_context_state()->is_composing_display_list())
4057                     {
4058                         process_entrypoint_warning("%s: glXUseXFont() called while composing a display list!\n", VOGL_METHOD_NAME);
4059                     }
4060                     else
4061                     {
4062                         if (!get_shared_state()->m_shadow_state.m_display_lists.glx_font(pFont_name->get_ptr(), first, count, trace_list_base))
4063                         {
4064                             process_entrypoint_warning("%s: Failed updating display list shadow\n", VOGL_METHOD_NAME);
4065                         }
4066                     }
4067                 }
4068             }
4069
4070             break;
4071         }
4072         case VOGL_ENTRYPOINT_glBlitFramebufferEXT:
4073         {
4074             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBlitFramebufferEXT;
4075
4076             VOGL_REPLAY_CALL_GL_HELPER_glBlitFramebufferEXT;
4077
4078             if ((status = post_draw_call()) != cStatusOK)
4079                 return status;
4080
4081             break;
4082         }
4083         case VOGL_ENTRYPOINT_glBlitFramebuffer:
4084         {
4085             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBlitFramebuffer;
4086
4087             VOGL_REPLAY_CALL_GL_HELPER_glBlitFramebuffer;
4088
4089             if ((status = post_draw_call()) != cStatusOK)
4090                 return status;
4091
4092             break;
4093         }
4094         case VOGL_ENTRYPOINT_glBegin:
4095         {
4096             if (m_pCur_context_state->m_inside_gl_begin)
4097             {
4098                 process_entrypoint_warning("%s: Got a glBegin while already inside a glBegin\n", VOGL_METHOD_NAME);
4099             }
4100             m_pCur_context_state->m_inside_gl_begin = true;
4101
4102             g_vogl_actual_gl_entrypoints.m_glBegin(trace_packet.get_param_value<GLenum>(0));
4103
4104             break;
4105         }
4106         case VOGL_ENTRYPOINT_glEnd:
4107         {
4108             if (!m_pCur_context_state->m_inside_gl_begin)
4109             {
4110                 process_entrypoint_warning("%s: Got glEnd without a matching glBegin\n", VOGL_METHOD_NAME);
4111             }
4112             m_pCur_context_state->m_inside_gl_begin = false;
4113
4114             g_vogl_actual_gl_entrypoints.m_glEnd();
4115
4116             if ((status = post_draw_call()) != cStatusOK)
4117                 return status;
4118
4119             break;
4120         }
4121         case VOGL_ENTRYPOINT_glGetError:
4122         {
4123             // TODO: Compare trace error vs. replay error
4124
4125             break;
4126         }
4127         case VOGL_ENTRYPOINT_glGetStringi:
4128         {
4129             if (!benchmark_mode())
4130             {
4131                 const GLubyte *pStr = GL_ENTRYPOINT(glGetStringi)(
4132                     trace_packet.get_param_value<GLenum>(0),
4133                     trace_packet.get_param_value<GLuint>(1));
4134                 VOGL_NOTE_UNUSED(pStr);
4135
4136                 // TODO: Compare vs. trace's?
4137             }
4138
4139             break;
4140         }
4141         case VOGL_ENTRYPOINT_glGetString:
4142         {
4143             if (!benchmark_mode())
4144             {
4145                 const GLubyte *pStr = GL_ENTRYPOINT(glGetString)(
4146                     trace_packet.get_param_value<GLenum>(0));
4147                 VOGL_NOTE_UNUSED(pStr);
4148
4149                 // TODO: Compare vs. trace's?
4150             }
4151
4152             break;
4153         }
4154         case VOGL_ENTRYPOINT_glGenFramebuffers:
4155         case VOGL_ENTRYPOINT_glGenFramebuffersEXT:
4156         {
4157             if (!gen_handles(get_context_state()->m_framebuffers,
4158                              trace_packet.get_param_value<GLsizei>(0),
4159                              static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)),
4160                              (entrypoint_id == VOGL_ENTRYPOINT_glGenFramebuffers) ? GL_ENTRYPOINT(glGenFramebuffers) : GL_ENTRYPOINT(glGenFramebuffersEXT), NULL))
4161                 return cStatusHardFailure;
4162
4163             break;
4164         }
4165         case VOGL_ENTRYPOINT_glBindFramebuffer:
4166         case VOGL_ENTRYPOINT_glBindFramebufferEXT:
4167         {
4168             GLenum target = trace_packet.get_param_value<GLenum>(0);
4169             GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
4170
4171             GLuint replay_handle = map_handle(get_context_state()->m_framebuffers, trace_handle);
4172
4173             SWITCH_GL_ENTRYPOINT2_VOID(glBindFramebuffer, glBindFramebufferEXT, target, replay_handle);
4174
4175             break;
4176         }
4177         case VOGL_ENTRYPOINT_glGetRenderbufferParameterivEXT:
4178         case VOGL_ENTRYPOINT_glGetRenderbufferParameteriv:
4179         {
4180             if (!benchmark_mode())
4181             {
4182                 GLenum target = trace_packet.get_param_value<GLenum>(0);
4183                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
4184                 GLint *pTrace_params = trace_packet.get_param_client_memory<GLint>(2);
4185                 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
4186                 uint trace_params_count = trace_params_size / sizeof(GLint);
4187
4188                 int n = g_gl_enums.get_pname_count(pname);
4189                 if (n <= 0)
4190                 {
4191                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
4192                     return cStatusSoftFailure;
4193                 }
4194                 else if (n < static_cast<int>(trace_params_count))
4195                 {
4196                     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);
4197                     return cStatusSoftFailure;
4198                 }
4199                 else
4200                 {
4201                     vogl::growable_array<GLint, 16> params(n + 1);
4202                     params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4203
4204                     SWITCH_GL_ENTRYPOINT2_VOID(glGetRenderbufferParameteriv, glGetRenderbufferParameterivEXT, target, pname, params.get_ptr());
4205
4206                     VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
4207
4208                     if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLint)) != 0)
4209                     {
4210                         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));
4211                     }
4212                 }
4213             }
4214
4215             break;
4216         }
4217         case VOGL_ENTRYPOINT_glCheckFramebufferStatus:
4218         case VOGL_ENTRYPOINT_glCheckFramebufferStatusEXT:
4219         {
4220             GLenum result;
4221             SWITCH_GL_ENTRYPOINT2(glCheckFramebufferStatus, glCheckFramebufferStatusEXT, trace_packet.get_param_value<GLenum>(0));
4222
4223             GLenum trace_status = trace_packet.get_return_value<GLenum>();
4224             if (result != trace_status)
4225             {
4226                 process_entrypoint_warning("%s: glCheckFramebufferStatus returned status 0x%08X during trace, but status 0x%08X during replay\n", VOGL_METHOD_NAME, trace_status, result);
4227             }
4228             break;
4229         }
4230         case VOGL_ENTRYPOINT_glDeleteFramebuffers:
4231         {
4232             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));
4233             break;
4234         }
4235         case VOGL_ENTRYPOINT_glDeleteFramebuffersEXT:
4236         {
4237             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));
4238             break;
4239         }
4240         case VOGL_ENTRYPOINT_glFramebufferTexture:
4241         {
4242             GLenum target = trace_packet.get_param_value<GLenum>(0);
4243             GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4244             GLuint trace_texture = trace_packet.get_param_value<GLuint>(2);
4245             GLuint replay_texture = trace_texture;
4246             GLint level = trace_packet.get_param_value<GLint>(3);
4247
4248             if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4249             {
4250                 if (trace_texture)
4251                     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);
4252             }
4253
4254             GL_ENTRYPOINT(glFramebufferTexture)(target, attachment, replay_texture, level);
4255
4256             break;
4257         }
4258         case VOGL_ENTRYPOINT_glFramebufferTextureLayer:
4259         case VOGL_ENTRYPOINT_glFramebufferTextureLayerEXT:
4260         {
4261             GLenum target = trace_packet.get_param_value<GLenum>(0);
4262             GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4263             GLuint trace_texture = trace_packet.get_param_value<GLuint>(2);
4264             GLuint replay_texture = trace_texture;
4265             GLint level = trace_packet.get_param_value<GLint>(3);
4266             GLint layer = trace_packet.get_param_value<GLint>(4);
4267
4268             if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4269             {
4270                 if (trace_texture)
4271                     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);
4272             }
4273
4274             SWITCH_GL_ENTRYPOINT2_VOID(glFramebufferTextureLayer, glFramebufferTextureLayerEXT, target, attachment, replay_texture, level, layer);
4275
4276             break;
4277         }
4278         case VOGL_ENTRYPOINT_glFramebufferTexture1DEXT:
4279         case VOGL_ENTRYPOINT_glFramebufferTexture1D:
4280         case VOGL_ENTRYPOINT_glFramebufferTexture2DEXT:
4281         case VOGL_ENTRYPOINT_glFramebufferTexture2D:
4282         case VOGL_ENTRYPOINT_glFramebufferTexture3DEXT:
4283         case VOGL_ENTRYPOINT_glFramebufferTexture3D:
4284         {
4285             GLenum target = trace_packet.get_param_value<GLenum>(0);
4286             GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4287             GLenum textarget = trace_packet.get_param_value<GLenum>(2);
4288             GLuint trace_texture = trace_packet.get_param_value<GLuint>(3);
4289             GLuint replay_texture = trace_texture;
4290             GLint level = trace_packet.get_param_value<GLint>(4);
4291
4292             if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4293             {
4294                 if (trace_texture)
4295                     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);
4296             }
4297
4298             switch (entrypoint_id)
4299             {
4300                 case VOGL_ENTRYPOINT_glFramebufferTexture1DEXT:
4301                     GL_ENTRYPOINT(glFramebufferTexture1DEXT)(target, attachment, textarget, replay_texture, level);
4302                     break;
4303                 case VOGL_ENTRYPOINT_glFramebufferTexture1D:
4304                     GL_ENTRYPOINT(glFramebufferTexture1D)(target, attachment, textarget, replay_texture, level);
4305                     break;
4306                 case VOGL_ENTRYPOINT_glFramebufferTexture2DEXT:
4307                     GL_ENTRYPOINT(glFramebufferTexture2DEXT)(target, attachment, textarget, replay_texture, level);
4308                     break;
4309                 case VOGL_ENTRYPOINT_glFramebufferTexture2D:
4310                     GL_ENTRYPOINT(glFramebufferTexture2D)(target, attachment, textarget, replay_texture, level);
4311                     break;
4312                 case VOGL_ENTRYPOINT_glFramebufferTexture3DEXT:
4313                     GL_ENTRYPOINT(glFramebufferTexture3DEXT)(target, attachment, textarget, replay_texture, level, trace_packet.get_param_value<GLint>(5));
4314                     break;
4315                 case VOGL_ENTRYPOINT_glFramebufferTexture3D:
4316                     GL_ENTRYPOINT(glFramebufferTexture3D)(target, attachment, textarget, replay_texture, level, trace_packet.get_param_value<GLint>(5));
4317                     break;
4318                 default:
4319                     break;
4320             }
4321
4322             break;
4323         }
4324         case VOGL_ENTRYPOINT_glGenTextures:
4325         {
4326             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))
4327                 return cStatusHardFailure;
4328             break;
4329         }
4330         case VOGL_ENTRYPOINT_glGenTexturesEXT:
4331         {
4332             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))
4333                 return cStatusHardFailure;
4334             break;
4335         }
4336         case VOGL_ENTRYPOINT_glDeleteTextures:
4337         {
4338             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));
4339             break;
4340         }
4341         case VOGL_ENTRYPOINT_glDeleteTexturesEXT:
4342         {
4343             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));
4344             break;
4345         }
4346         case VOGL_ENTRYPOINT_glBindMultiTextureEXT:
4347         {
4348             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindMultiTextureEXT;
4349
4350             GLuint trace_texture = texture;
4351             map_handle(get_shared_state()->m_shadow_state.m_textures, trace_texture, texture);
4352
4353             if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4354                 check_gl_error();
4355
4356             VOGL_REPLAY_CALL_GL_HELPER_glBindMultiTextureEXT;
4357
4358             if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4359             {
4360                 if (!check_gl_error())
4361                     get_shared_state()->m_shadow_state.m_textures.update(trace_texture, texture, target);
4362             }
4363
4364             break;
4365         }
4366         case VOGL_ENTRYPOINT_glBindTexture:
4367         case VOGL_ENTRYPOINT_glBindTextureEXT:
4368         {
4369             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindTexture;
4370
4371             GLuint trace_texture = texture;
4372             map_handle(get_shared_state()->m_shadow_state.m_textures, trace_texture, texture);
4373
4374             if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4375                 check_gl_error();
4376
4377             SWITCH_GL_ENTRYPOINT2_VOID(glBindTexture, glBindTextureEXT, target, texture);
4378
4379             if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4380             {
4381                 if (!check_gl_error())
4382                     get_shared_state()->m_shadow_state.m_textures.update(trace_texture, texture, target);
4383             }
4384
4385             break;
4386         }
4387         case VOGL_ENTRYPOINT_glBindSampler:
4388         {
4389             GLuint replay_handle = map_handle(get_shared_state()->m_sampler_objects, trace_packet.get_param_value<GLuint>(1));
4390             GL_ENTRYPOINT(glBindSampler)(trace_packet.get_param_value<GLuint>(0), replay_handle);
4391             break;
4392         }
4393         case VOGL_ENTRYPOINT_glDeleteSamplers:
4394         {
4395             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));
4396             break;
4397         }
4398         case VOGL_ENTRYPOINT_glGenSamplers:
4399         {
4400             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))
4401                 return cStatusHardFailure;
4402             break;
4403         }
4404
4405         case VOGL_ENTRYPOINT_glSamplerParameterf:
4406         {
4407             VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterf;
4408             sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4409             VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterf;
4410             break;
4411         }
4412         case VOGL_ENTRYPOINT_glSamplerParameteri:
4413         {
4414             VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameteri;
4415             sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4416             VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameteri;
4417             break;
4418         }
4419         case VOGL_ENTRYPOINT_glSamplerParameterfv:
4420         {
4421             VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterfv;
4422             sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4423             VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterfv;
4424             break;
4425         }
4426         case VOGL_ENTRYPOINT_glSamplerParameteriv:
4427         {
4428             VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameteriv;
4429             sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4430             VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameteriv;
4431             break;
4432         }
4433         case VOGL_ENTRYPOINT_glSamplerParameterIiv:
4434         {
4435             VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterIiv;
4436             sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4437             VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterIiv;
4438             break;
4439         }
4440         case VOGL_ENTRYPOINT_glSamplerParameterIuiv:
4441         {
4442             VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterIuiv;
4443             sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4444             VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterIuiv;
4445             break;
4446         }
4447         case VOGL_ENTRYPOINT_glGenBuffers:
4448         case VOGL_ENTRYPOINT_glGenBuffersARB:
4449         {
4450             uint n = trace_packet.get_param_value<GLsizei>(0);
4451             const GLuint *pTrace_handles = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4452
4453             if (entrypoint_id == VOGL_ENTRYPOINT_glGenBuffers)
4454             {
4455                 if (!gen_handles(get_shared_state()->m_buffers, n, pTrace_handles, GL_ENTRYPOINT(glGenBuffers), NULL))
4456                     return cStatusHardFailure;
4457             }
4458             else
4459             {
4460                 if (!gen_handles(get_shared_state()->m_buffers, n, pTrace_handles, GL_ENTRYPOINT(glGenBuffersARB), NULL))
4461                     return cStatusHardFailure;
4462             }
4463
4464             if (pTrace_handles)
4465             {
4466                 for (uint i = 0; i < n; i++)
4467                 {
4468                     if (pTrace_handles[i])
4469                         get_shared_state()->m_buffer_targets.insert(pTrace_handles[i], GL_NONE);
4470                 }
4471             }
4472
4473             break;
4474         }
4475         case VOGL_ENTRYPOINT_glDeleteBuffers:
4476         case VOGL_ENTRYPOINT_glDeleteBuffersARB:
4477         {
4478             GLsizei trace_n = trace_packet.get_param_value<GLsizei>(0);
4479             const GLuint *pTrace_ids = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4480             uint trace_ids_count = trace_packet.get_param_client_memory_data_size(1);
4481
4482             if ((pTrace_ids) && (static_cast<GLsizei>(trace_ids_count) < trace_n))
4483             {
4484                 process_entrypoint_warning("%s: trace_ids trace array is too small\n", VOGL_METHOD_NAME);
4485                 return cStatusHardFailure;
4486             }
4487
4488             for (GLsizei iter = 0; iter < trace_n; iter++)
4489             {
4490                 GLuint trace_id = pTrace_ids[iter];
4491                 if (!trace_id)
4492                     continue;
4493
4494                 if (!get_shared_state()->m_buffer_targets.erase(trace_id))
4495                 {
4496                     process_entrypoint_warning("%s: Couldn't find trace buffer id %u in buffer target map!\n", VOGL_METHOD_NAME, trace_id);
4497                 }
4498
4499                 gl_handle_hash_map::const_iterator it = get_shared_state()->m_buffers.find(trace_id);
4500                 if (it == get_shared_state()->m_buffers.end())
4501                 {
4502                     process_entrypoint_warning("%s: Couldn't map trace buffer id %u to GL buffer id\n", VOGL_METHOD_NAME, trace_id);
4503                     continue;
4504                 }
4505
4506                 GLuint replay_id = it->second;
4507
4508                 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
4509
4510                 for (uint i = 0; i < mapped_bufs.size(); i++)
4511                 {
4512                     if (mapped_bufs[i].m_buffer == replay_id)
4513                     {
4514                         process_entrypoint_warning("%s: glDeleteBuffers() called on mapped trace buffer %u GL buffer %u\n", VOGL_METHOD_NAME, trace_id, replay_id);
4515
4516                         mapped_bufs.erase_unordered(i);
4517                         break;
4518                     }
4519                 }
4520             }
4521
4522             if (entrypoint_id == VOGL_ENTRYPOINT_glDeleteBuffers)
4523                 delete_handles(get_shared_state()->m_buffers, trace_n, pTrace_ids, GL_ENTRYPOINT(glDeleteBuffers));
4524             else
4525                 delete_handles(get_shared_state()->m_buffers, trace_n, pTrace_ids, GL_ENTRYPOINT(glDeleteBuffersARB));
4526
4527             break;
4528         }
4529         case VOGL_ENTRYPOINT_glGenProgramsARB:
4530         {
4531             // arb program objects
4532             VOGL_REPLAY_LOAD_PARAMS_HELPER_glGenProgramsARB;
4533
4534             if (!gen_handles(get_shared_state()->m_arb_programs, n, pTrace_programs, GL_ENTRYPOINT(glGenProgramsARB), NULL))
4535                 return cStatusHardFailure;
4536
4537             for (GLsizei i = 0; (pTrace_programs) && (i < n); i++)
4538                 if (pTrace_programs[i])
4539                     get_shared_state()->m_arb_program_targets.insert(pTrace_programs[i], GL_NONE);
4540
4541             break;
4542         }
4543         case VOGL_ENTRYPOINT_glDeleteProgramsARB:
4544         {
4545             // arb program objects
4546             VOGL_REPLAY_LOAD_PARAMS_HELPER_glDeleteProgramsARB;
4547
4548             for (GLsizei i = 0; (pTrace_programs) && (i < n); i++)
4549                 get_shared_state()->m_arb_program_targets.erase(pTrace_programs[i]);
4550
4551             delete_handles(get_shared_state()->m_arb_programs, n, pTrace_programs, GL_ENTRYPOINT(glDeleteProgramsARB));
4552             break;
4553         }
4554         case VOGL_ENTRYPOINT_glBindProgramARB:
4555         {
4556             // arb program objects
4557             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindProgramARB;
4558
4559             GLuint trace_program = program;
4560             gl_handle_hash_map::const_iterator it;
4561             if (program)
4562             {
4563                 it = get_shared_state()->m_arb_programs.find(program);
4564                 if (it != get_shared_state()->m_arb_programs.end())
4565                     program = it->second;
4566                 else
4567                     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);
4568             }
4569
4570             check_gl_error();
4571
4572             VOGL_REPLAY_CALL_GL_HELPER_glBindProgramARB;
4573
4574             if (!check_gl_error() && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4575             {
4576                 if (trace_program)
4577                 {
4578                     if (it == get_shared_state()->m_arb_programs.end())
4579                         get_shared_state()->m_arb_programs.insert(trace_program, program);
4580
4581                     get_shared_state()->m_arb_program_targets[trace_program] = target;
4582                 }
4583             }
4584             else
4585             {
4586                 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));
4587                 return cStatusGLError;
4588             }
4589
4590             break;
4591         }
4592         case VOGL_ENTRYPOINT_glIsProgramARB:
4593         {
4594             if (!benchmark_mode())
4595             {
4596                 VOGL_REPLAY_LOAD_PARAMS_HELPER_glIsProgramARB;
4597
4598                 GLuint trace_program = program;
4599                 program = map_handle(get_shared_state()->m_arb_programs, program);
4600
4601                 GLboolean replay_result = VOGL_REPLAY_CALL_GL_HELPER_glIsProgramARB;
4602                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4603
4604                 if (trace_result != replay_result)
4605                     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);
4606             }
4607
4608             break;
4609         }
4610         case VOGL_ENTRYPOINT_glGenQueries:
4611         case VOGL_ENTRYPOINT_glGenQueriesARB:
4612         {
4613             GLsizei n = trace_packet.get_param_value<GLsizei>(0);
4614             vogl::growable_array<GLuint, 16> replay_handles(n);
4615
4616             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()))
4617                 return cStatusHardFailure;
4618
4619             for (GLsizei i = 0; i < n; i++)
4620                 get_shared_state()->m_query_targets[replay_handles[i]] = GL_NONE;
4621
4622             break;
4623         }
4624         case VOGL_ENTRYPOINT_glDeleteQueries:
4625         case VOGL_ENTRYPOINT_glDeleteQueriesARB:
4626         {
4627             GLsizei n = trace_packet.get_param_value<GLsizei>(0);
4628             const GLuint *pTrace_ids = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4629
4630             if (pTrace_ids)
4631             {
4632                 for (GLsizei i = 0; i < n; i++)
4633                 {
4634                     GLuint trace_id = pTrace_ids[i];
4635                     if (!trace_id)
4636                         continue;
4637                     gl_handle_hash_map::const_iterator it(get_shared_state()->m_queries.find(trace_id));
4638                     if (it != get_shared_state()->m_queries.end())
4639                         get_shared_state()->m_query_targets.erase(it->second);
4640                 }
4641             }
4642
4643             if (entrypoint_id == VOGL_ENTRYPOINT_glDeleteQueries)
4644                 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));
4645             else
4646                 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));
4647
4648             break;
4649         }
4650         case VOGL_ENTRYPOINT_glGenRenderbuffersEXT:
4651         {
4652             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))
4653                 return cStatusHardFailure;
4654             break;
4655         }
4656         case VOGL_ENTRYPOINT_glGenRenderbuffers:
4657         {
4658             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))
4659                 return cStatusHardFailure;
4660             break;
4661         }
4662         case VOGL_ENTRYPOINT_glDeleteRenderbuffersEXT:
4663         {
4664             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));
4665             break;
4666         }
4667         case VOGL_ENTRYPOINT_glDeleteRenderbuffers:
4668         {
4669             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));
4670             break;
4671         }
4672         case VOGL_ENTRYPOINT_glIsRenderbuffer:
4673         {
4674             if (!benchmark_mode())
4675             {
4676                 GLboolean replay_result = GL_ENTRYPOINT(glIsRenderbuffer)(map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(0)));
4677                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4678                 if (replay_result != trace_result)
4679                 {
4680                     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);
4681                 }
4682             }
4683             break;
4684         }
4685         case VOGL_ENTRYPOINT_glIsRenderbufferEXT:
4686         {
4687             if (!benchmark_mode())
4688             {
4689                 GLboolean replay_result = GL_ENTRYPOINT(glIsRenderbufferEXT)(map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(0)));
4690                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4691                 if (replay_result != trace_result)
4692                 {
4693                     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);
4694                 }
4695             }
4696             break;
4697         }
4698         case VOGL_ENTRYPOINT_glBindRenderbufferEXT:
4699         {
4700             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)));
4701             break;
4702         }
4703         case VOGL_ENTRYPOINT_glBindRenderbuffer:
4704         {
4705             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)));
4706             break;
4707         }
4708         case VOGL_ENTRYPOINT_glFramebufferRenderbufferEXT:
4709         {
4710             GL_ENTRYPOINT(glFramebufferRenderbufferEXT)(
4711                 trace_packet.get_param_value<GLenum>(0),
4712                 trace_packet.get_param_value<GLenum>(1),
4713                 trace_packet.get_param_value<GLenum>(2),
4714                 map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(3)));
4715             break;
4716         }
4717         case VOGL_ENTRYPOINT_glFramebufferRenderbuffer:
4718         {
4719             GL_ENTRYPOINT(glFramebufferRenderbuffer)(
4720                 trace_packet.get_param_value<GLenum>(0),
4721                 trace_packet.get_param_value<GLenum>(1),
4722                 trace_packet.get_param_value<GLenum>(2),
4723                 map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(3)));
4724             break;
4725         }
4726         case VOGL_ENTRYPOINT_glUseProgramObjectARB:
4727         case VOGL_ENTRYPOINT_glUseProgram:
4728         {
4729             GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
4730             handle_use_program(trace_handle, entrypoint_id);
4731             break;
4732         }
4733         case VOGL_ENTRYPOINT_glProgramParameteri:
4734         case VOGL_ENTRYPOINT_glProgramParameteriARB:
4735         case VOGL_ENTRYPOINT_glProgramParameteriEXT:
4736         {
4737             VOGL_REPLAY_LOAD_PARAMS_HELPER_glProgramParameteri;
4738
4739             program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4740
4741             if (entrypoint_id == VOGL_ENTRYPOINT_glProgramParameteriARB)
4742                 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteriARB;
4743             else if (entrypoint_id == VOGL_ENTRYPOINT_glProgramParameteriEXT)
4744                 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteriEXT;
4745             else
4746                 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteri;
4747
4748             break;
4749         }
4750         case VOGL_ENTRYPOINT_glBindFragDataLocation:
4751         case VOGL_ENTRYPOINT_glBindFragDataLocationEXT:
4752         {
4753             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindFragDataLocation;
4754
4755             program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4756
4757             if (entrypoint_id == VOGL_ENTRYPOINT_glBindFragDataLocation)
4758                 VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocation;
4759             else
4760                 VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocationEXT;
4761
4762             break;
4763         }
4764         case VOGL_ENTRYPOINT_glBindFragDataLocationIndexed:
4765         {
4766             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindFragDataLocationIndexed;
4767
4768             program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4769
4770             VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocationIndexed;
4771
4772             break;
4773         }
4774         case VOGL_ENTRYPOINT_glValidateProgramARB:
4775         {
4776             VOGL_REPLAY_LOAD_PARAMS_HELPER_glValidateProgramARB;
4777
4778             programObj = map_handle(get_shared_state()->m_shadow_state.m_objs, programObj);
4779
4780             VOGL_REPLAY_CALL_GL_HELPER_glValidateProgramARB;
4781
4782             break;
4783         }
4784         case VOGL_ENTRYPOINT_glValidateProgram:
4785         {
4786             VOGL_REPLAY_LOAD_PARAMS_HELPER_glValidateProgram;
4787
4788             program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4789
4790             VOGL_REPLAY_CALL_GL_HELPER_glValidateProgram;
4791
4792             break;
4793         }
4794         case VOGL_ENTRYPOINT_glCreateProgram:
4795         case VOGL_ENTRYPOINT_glCreateProgramObjectARB:
4796         {
4797             GLuint trace_handle = trace_packet.get_return_value<GLuint>();
4798             if (trace_handle)
4799             {
4800                 GLuint replay_handle;
4801
4802                 if (entrypoint_id == VOGL_ENTRYPOINT_glCreateProgram)
4803                     replay_handle = GL_ENTRYPOINT(glCreateProgram)();
4804                 else
4805                     replay_handle = GL_ENTRYPOINT(glCreateProgramObjectARB)();
4806
4807                 VOGL_ASSERT(!replay_handle || (GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0));
4808
4809                 if (!gen_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle, replay_handle, VOGL_PROGRAM_OBJECT))
4810                     return cStatusHardFailure;
4811             }
4812             break;
4813         }
4814         case VOGL_ENTRYPOINT_glDeleteProgram:
4815         {
4816             GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
4817             handle_delete_program(trace_handle);
4818
4819             break;
4820         }
4821         case VOGL_ENTRYPOINT_glDeleteObjectARB:
4822         {
4823             GLuint trace_handle = trace_packet.get_param_value<GLenum>(0);
4824             GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle);
4825
4826             if (target == VOGL_SHADER_OBJECT)
4827                 handle_delete_shader(trace_handle);
4828             else if (target == VOGL_PROGRAM_OBJECT)
4829                 handle_delete_program(trace_handle);
4830             else
4831             {
4832                 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
4833
4834                 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);
4835                 return cStatusSoftFailure;
4836             }
4837
4838             break;
4839         }
4840         case VOGL_ENTRYPOINT_glDeleteShader:
4841         {
4842             GLuint trace_shader = trace_packet.get_param_value<GLuint>(0);
4843             handle_delete_shader(trace_shader);
4844
4845             break;
4846         }
4847         case VOGL_ENTRYPOINT_glCreateShader:
4848         case VOGL_ENTRYPOINT_glCreateShaderObjectARB:
4849         {
4850             GLuint trace_handle = trace_packet.get_return_value<GLuint>();
4851             if (trace_handle)
4852             {
4853                 GLuint replay_handle;
4854
4855                 if (entrypoint_id == VOGL_ENTRYPOINT_glCreateShader)
4856                     replay_handle = GL_ENTRYPOINT(glCreateShader)(trace_packet.get_param_value<GLenum>(0));
4857                 else
4858                     replay_handle = GL_ENTRYPOINT(glCreateShaderObjectARB)(trace_packet.get_param_value<GLenum>(0));
4859
4860                 VOGL_ASSERT(!replay_handle || (GL_ENTRYPOINT(glIsShader)(replay_handle) != 0));
4861
4862                 if (!gen_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle, replay_handle, VOGL_SHADER_OBJECT))
4863                     return cStatusHardFailure;
4864             }
4865             break;
4866         }
4867         case VOGL_ENTRYPOINT_glAttachShader:
4868         {
4869             GL_ENTRYPOINT(glAttachShader)(
4870                 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)),
4871                 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(1)));
4872             break;
4873         }
4874         case VOGL_ENTRYPOINT_glAttachObjectARB:
4875         {
4876             GL_ENTRYPOINT(glAttachObjectARB)(
4877                 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4878                 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(1)));
4879             break;
4880         }
4881         case VOGL_ENTRYPOINT_glDetachShader:
4882         {
4883             handle_detach_shader(entrypoint_id);
4884
4885             break;
4886         }
4887         case VOGL_ENTRYPOINT_glDetachObjectARB:
4888         {
4889             GLhandleARB trace_object_handle = trace_packet.get_param_value<GLhandleARB>(1);
4890
4891             GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target(trace_object_handle);
4892
4893             if (target == VOGL_SHADER_OBJECT)
4894                 handle_detach_shader(entrypoint_id);
4895             else
4896             {
4897                 GLuint replay_object_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object_handle);
4898                 GL_ENTRYPOINT(glDetachObjectARB)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)), replay_object_handle);
4899             }
4900
4901             break;
4902         }
4903         case VOGL_ENTRYPOINT_glBindAttribLocation:
4904         {
4905             GL_ENTRYPOINT(glBindAttribLocation)(
4906                 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)),
4907                 trace_packet.get_param_value<GLuint>(1),
4908                 trace_packet.get_param_client_memory<GLchar>(2));
4909             break;
4910         }
4911         case VOGL_ENTRYPOINT_glBindAttribLocationARB:
4912         {
4913             GL_ENTRYPOINT(glBindAttribLocationARB)(
4914                 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4915                 trace_packet.get_param_value<GLuint>(1),
4916                 trace_packet.get_param_client_memory<GLcharARB>(2));
4917             break;
4918         }
4919         case VOGL_ENTRYPOINT_glGetObjectParameterivARB:
4920         {
4921             if (!benchmark_mode())
4922             {
4923                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
4924                 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
4925
4926                 int n = g_gl_enums.get_pname_count(pname);
4927                 if (n <= 0)
4928                 {
4929                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
4930                     return cStatusSoftFailure;
4931                 }
4932                 else
4933                 {
4934                     vogl::growable_array<GLint, 16> params(n + 1);
4935                     params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4936
4937                     GL_ENTRYPOINT(glGetObjectParameterivARB)(
4938                         map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4939                         pname,
4940                         params.get_ptr());
4941
4942                     VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
4943
4944                     if (memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
4945                     {
4946                         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));
4947                     }
4948                 }
4949             }
4950             break;
4951         }
4952         case VOGL_ENTRYPOINT_glGetBufferParameteriv:
4953         {
4954             if (!benchmark_mode())
4955             {
4956                 GLenum target = trace_packet.get_param_value<GLenum>(0);
4957                 GLenum value = trace_packet.get_param_value<GLenum>(1);
4958                 const GLint *pTrace_data = trace_packet.get_param_client_memory<GLint>(2);
4959
4960                 int n = g_gl_enums.get_pname_count(value);
4961                 if (n <= 0)
4962                 {
4963                     process_entrypoint_error("%s: Can't determine count of GL value 0x%08X\n", VOGL_METHOD_NAME, value);
4964                     return cStatusSoftFailure;
4965                 }
4966                 else
4967                 {
4968                     vogl::growable_array<GLint, 16> data(n + 1);
4969                     data[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4970
4971                     GL_ENTRYPOINT(glGetBufferParameteriv)(target, value, data.get_ptr());
4972
4973                     VOGL_VERIFY(data[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
4974
4975                     GLint trace_data = pTrace_data ? pTrace_data[0] : -1;
4976                     if (data[0] != trace_data)
4977                     {
4978                         process_entrypoint_warning("%s: Replay's returned GLint differed from trace's!\n", VOGL_METHOD_NAME);
4979                         vogl_warning_printf("Trace data: %i, Replay data: %i\n", trace_data, data[0]);
4980                     }
4981                 }
4982             }
4983
4984             break;
4985         }
4986
4987         case VOGL_ENTRYPOINT_glGetBufferPointerv:
4988         {
4989             if (!benchmark_mode())
4990             {
4991                 GLvoid *pReplay_ptr = NULL;
4992                 GL_ENTRYPOINT(glGetBufferPointerv)(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLenum>(1), &pReplay_ptr);
4993
4994                 vogl_client_memory_array trace_void_ptr_array = trace_packet.get_param_client_memory_array(2);
4995                 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;
4996
4997                 if ((pReplay_ptr != NULL) != (first_trace_ptr != 0))
4998                 {
4999                     process_entrypoint_warning("%s: First replay's returned GLvoid* differed from trace's!\n", VOGL_METHOD_NAME);
5000                     vogl_warning_printf("Trace: 0x%" PRIx64 ", Replay: 0x%" PRIx64 "\n", first_trace_ptr, reinterpret_cast<uint64_t>(pReplay_ptr));
5001                 }
5002             }
5003
5004             break;
5005         }
5006         case VOGL_ENTRYPOINT_glShaderSource:
5007         case VOGL_ENTRYPOINT_glShaderSourceARB:
5008         {
5009             const status_t status = handle_ShaderSource(trace_packet.get_param_value<GLhandleARB>(0),
5010                                                         trace_packet.get_param_value<GLsizei>(1),
5011                                                         trace_packet.get_param_client_memory_array(2),
5012                                                         trace_packet.get_param_client_memory<const GLint>(3));
5013             if (status != cStatusOK)
5014                 return status;
5015             break;
5016         }
5017         case VOGL_ENTRYPOINT_glGetProgramInfoLog:
5018         {
5019             GLuint trace_object = trace_packet.get_param_value<GLuint>(0);
5020             GLuint replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
5021
5022             GLint length = -1;
5023             GL_ENTRYPOINT(glGetProgramiv)(replay_object, GL_INFO_LOG_LENGTH, &length);
5024             if (length < 0)
5025             {
5026                 process_entrypoint_error("%s: Failed retrieving info log length for trace object %u, reply object %u\n", VOGL_METHOD_NAME, trace_object, replay_object);
5027                 return cStatusSoftFailure;
5028             }
5029             else
5030             {
5031                 vogl::vector<GLchar> log(length);
5032
5033                 GLsizei actual_length = 0;
5034                 GL_ENTRYPOINT(glGetProgramInfoLog)(replay_object, length, &actual_length, log.get_ptr());
5035
5036                 if (actual_length)
5037                 {
5038                     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());
5039                 }
5040             }
5041
5042             break;
5043         }
5044         case VOGL_ENTRYPOINT_glGetPointerv:
5045         {
5046             if (!benchmark_mode())
5047             {
5048                 GLvoid *ptr = NULL;
5049                 GL_ENTRYPOINT(glGetPointerv)(trace_packet.get_param_value<GLenum>(0), &ptr);
5050
5051                 // TODO: Differ vs. trace's in some way?
5052             }
5053
5054             break;
5055         }
5056         case VOGL_ENTRYPOINT_glGetInfoLogARB:
5057         {
5058             GLhandleARB trace_object = trace_packet.get_param_value<GLhandleARB>(0);
5059             GLhandleARB replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
5060
5061             GLsizei length = -1;
5062             GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
5063             if (length < 0)
5064             {
5065                 process_entrypoint_error("%s: Failed retrieving info log length for trace object %u, reply object %u\n", VOGL_METHOD_NAME, trace_object, replay_object);
5066                 return cStatusSoftFailure;
5067             }
5068             else
5069             {
5070                 vogl::vector<GLcharARB> log(length);
5071
5072                 GLsizei actual_length = 0;
5073                 GL_ENTRYPOINT(glGetInfoLogARB)(replay_object, length, &actual_length, log.get_ptr());
5074
5075                 if (actual_length)
5076                 {
5077                     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());
5078                 }
5079             }
5080
5081             break;
5082         }
5083         case VOGL_ENTRYPOINT_glGetUniformLocation:
5084         {
5085             GLhandleARB trace_handle = trace_packet.get_param_value<GLhandleARB>(0);
5086             GLhandleARB replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5087             GLint trace_loc = trace_packet.get_return_value<GLint>();
5088
5089             if (replay_handle)
5090             {
5091                 const GLchar *pName = trace_packet.get_param_client_memory<GLchar>(1);
5092
5093                 GLint replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, pName);
5094                 if (replay_loc < 0)
5095                 {
5096                     if (trace_loc >= 0)
5097                         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);
5098                 }
5099                 else
5100                 {
5101                     if (trace_loc < 0)
5102                         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);
5103                     else
5104                     {
5105                         glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
5106                         if (it == get_shared_state()->m_glsl_program_hash_map.end())
5107                             it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
5108
5109                         glsl_program_state &state = it->second;
5110                         state.m_uniform_locations.erase(trace_loc);
5111                         state.m_uniform_locations.insert(trace_loc, replay_loc);
5112                     }
5113                 }
5114             }
5115
5116             break;
5117         }
5118         case VOGL_ENTRYPOINT_glGetUniformLocationARB:
5119         {
5120             GLhandleARB trace_handle = trace_packet.get_param_value<GLhandleARB>(0);
5121             GLhandleARB replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5122             GLint trace_loc = trace_packet.get_return_value<GLint>();
5123
5124             if (replay_handle)
5125             {
5126                 const GLcharARB *pName = trace_packet.get_param_client_memory<GLcharARB>(1);
5127
5128                 GLint replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, pName);
5129                 if (replay_loc < 0)
5130                 {
5131                     if (trace_loc >= 0)
5132                         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);
5133                 }
5134                 else
5135                 {
5136                     if (trace_loc < 0)
5137                         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);
5138                     else
5139                     {
5140                         glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
5141                         if (it == get_shared_state()->m_glsl_program_hash_map.end())
5142                             it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
5143
5144                         glsl_program_state &state = it->second;
5145                         state.m_uniform_locations.erase(trace_loc);
5146                         state.m_uniform_locations.insert(trace_loc, replay_loc);
5147                     }
5148                 }
5149             }
5150
5151             break;
5152         }
5153         case VOGL_ENTRYPOINT_glGetActiveAttrib:
5154         case VOGL_ENTRYPOINT_glGetActiveUniform:
5155         {
5156             if (!benchmark_mode())
5157             {
5158                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5159                 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5160
5161                 GLuint index = trace_packet.get_param_value<GLuint>(1);
5162                 GLsizei bufSize = trace_packet.get_param_value<GLsizei>(2);
5163
5164                 GLsizei *pTrace_length = trace_packet.get_param_client_memory<GLsizei>(3);
5165                 GLint *pTrace_size = trace_packet.get_param_client_memory<GLint>(4);
5166                 GLenum *pTrace_type = trace_packet.get_param_client_memory<GLenum>(5);
5167                 GLchar *pTrace_name = trace_packet.get_param_client_memory<GLchar>(6);
5168
5169                 vogl::growable_array<GLchar, 1024> name_buf(bufSize + 1); // + 1 guarantees non-empty and null terminated
5170
5171                 GLsizei len = 0;
5172                 GLint size = 0;
5173                 GLenum type = 0;
5174
5175                 if (entrypoint_id == VOGL_ENTRYPOINT_glGetActiveAttrib)
5176                     GL_ENTRYPOINT(glGetActiveAttrib)(replay_handle, index, bufSize, &len, &size, &type, name_buf.get_ptr());
5177                 else
5178                     GL_ENTRYPOINT(glGetActiveUniform)(replay_handle, index, bufSize, &len, &size, &type, name_buf.get_ptr());
5179
5180                 bool mismatch = false;
5181
5182                 GLsizei trace_len = 0;
5183                 if (pTrace_length)
5184                 {
5185                     trace_len = pTrace_length[0];
5186                     if (trace_len != len)
5187                         mismatch = true;
5188                 }
5189
5190                 GLint trace_size = 0;
5191                 if (pTrace_size)
5192                 {
5193                     trace_size = pTrace_size[0];
5194                     if (trace_size != size)
5195                         mismatch = true;
5196                 }
5197
5198                 GLenum trace_type = 0;
5199                 if (pTrace_type)
5200                 {
5201                     trace_type = pTrace_type[0];
5202                     if (trace_type != type)
5203                         mismatch = true;
5204                 }
5205
5206                 if ((bufSize) && (pTrace_name))
5207                 {
5208                     uint n = vogl_strlen((const char *)pTrace_name) + 1;
5209                     if (bufSize < (GLsizei)n)
5210                         mismatch = true;
5211                     else if (memcmp(name_buf.get_ptr(), pTrace_name, n) != 0)
5212                         mismatch = true;
5213                 }
5214
5215                 if (mismatch)
5216                 {
5217                     process_entrypoint_warning("%s: Replay of %s returned data differed from trace's\n", VOGL_METHOD_NAME, trace_packet.get_entrypoint_desc().m_pName);
5218                     vogl_warning_printf("Trace handle: %u, index: %u, bufSize: %u, trace_len: %u, trace_type: %u, name: %s\n",
5219                                        (uint)trace_handle, (uint)index, (uint)bufSize, (uint)trace_len, (uint)trace_type, (pTrace_name != NULL) ? (const char *)pTrace_name : "");
5220                     vogl_warning_printf("GL handle: %u, index: %u, bufSize: %u, trace_len: %u, trace_type: %u, name: %s\n",
5221                                        (uint)replay_handle, (uint)index, (uint)bufSize, (uint)len, (uint)type, name_buf.get_ptr());
5222                 }
5223             }
5224
5225             break;
5226         }
5227         case VOGL_ENTRYPOINT_glGetAttachedShaders:
5228         {
5229             if (!benchmark_mode())
5230             {
5231                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5232                 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5233
5234                 GLsizei max_count = trace_packet.get_param_value<GLsizei>(1);
5235                 GLsizei count = 0;
5236                 vogl::growable_array<GLuint, 16> shaders(max_count);
5237
5238                 GL_ENTRYPOINT(glGetAttachedShaders)(replay_handle, trace_packet.get_param_value<GLsizei>(1), &count, shaders.get_ptr());
5239
5240                 // TODO: Diff results
5241             }
5242
5243             break;
5244         }
5245         case VOGL_ENTRYPOINT_glGetAttribLocation:
5246         {
5247             if (!benchmark_mode())
5248             {
5249                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5250                 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5251
5252                 const GLchar *pName = trace_packet.get_param_client_memory<GLchar>(1);
5253
5254                 GLint replay_result = GL_ENTRYPOINT(glGetAttribLocation)(replay_handle, pName);
5255                 GLint trace_result = trace_packet.get_return_value<GLint>();
5256
5257                 if (replay_result != trace_result)
5258                 {
5259                     process_entrypoint_warning("%s: Replay of %s returned data differed from trace's\n", VOGL_METHOD_NAME, trace_packet.get_entrypoint_desc().m_pName);
5260                     vogl_warning_printf("Trace value: %i, replay: %i\n", trace_result, replay_result);
5261                 }
5262             }
5263
5264             break;
5265         }
5266         case VOGL_ENTRYPOINT_glGetProgramivARB:
5267         {
5268             if (!benchmark_mode())
5269             {
5270                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5271                 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
5272                 uint params_size = trace_packet.get_param_client_memory_data_size(2);
5273                 uint params_count = params_size / sizeof(GLint);
5274
5275                 int n = g_gl_enums.get_pname_count(pname);
5276                 if (n <= 0)
5277                 {
5278                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5279                     return cStatusSoftFailure;
5280                 }
5281                 else
5282                 {
5283                     vogl::growable_array<GLint, 16> params(n + 1);
5284                     params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5285
5286                     GL_ENTRYPOINT(glGetProgramivARB)(
5287                         trace_packet.get_param_value<GLenum>(0),
5288                         pname,
5289                         params.get_ptr());
5290
5291                     VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5292
5293                     if (params_count != static_cast<uint>(n))
5294                     {
5295                         process_entrypoint_warning("%s: Size of replay's params array differs from trace's\n", VOGL_METHOD_NAME);
5296                     }
5297                     else if (pParams && memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
5298                     {
5299                         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));
5300                     }
5301                 }
5302             }
5303
5304             break;
5305         }
5306         case VOGL_ENTRYPOINT_glGetProgramiv:
5307         {
5308             if (!benchmark_mode())
5309             {
5310                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5311                 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5312
5313                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5314
5315                 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
5316                 uint params_size = trace_packet.get_param_client_memory_data_size(2);
5317                 uint params_count = params_size / sizeof(GLint);
5318
5319                 int n = g_gl_enums.get_pname_count(pname);
5320                 if (n <= 0)
5321                 {
5322                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5323                     return cStatusSoftFailure;
5324                 }
5325                 else
5326                 {
5327                     vogl::growable_array<GLint, 16> params(n + 1);
5328                     params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5329
5330                     GL_ENTRYPOINT(glGetProgramiv)(
5331                         replay_handle,
5332                         pname,
5333                         params.get_ptr());
5334
5335                     VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5336
5337                     if (params_count != static_cast<uint>(n))
5338                     {
5339                         process_entrypoint_warning("%s: Size of replay's params array differs from trace's\n", VOGL_METHOD_NAME);
5340                     }
5341                     else if (pParams && memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
5342                     {
5343                         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));
5344                     }
5345                 }
5346             }
5347
5348             break;
5349         }
5350         case VOGL_ENTRYPOINT_glLinkProgram:
5351         case VOGL_ENTRYPOINT_glLinkProgramARB:
5352         case VOGL_ENTRYPOINT_glProgramBinary:
5353         {
5354             handle_link_program(entrypoint_id);
5355
5356             break;
5357         }
5358         case VOGL_ENTRYPOINT_glCompileShader:
5359         {
5360             GL_ENTRYPOINT(glCompileShader)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)));
5361             break;
5362         }
5363         case VOGL_ENTRYPOINT_glCompileShaderARB:
5364         {
5365             GL_ENTRYPOINT(glCompileShaderARB)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)));
5366             break;
5367         }
5368         case VOGL_ENTRYPOINT_glGetShaderiv:
5369         {
5370             if (!benchmark_mode())
5371             {
5372                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5373                 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5374
5375                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5376                 GLint params = 0;
5377
5378                 const GLint *pClient_params = trace_packet.get_param_client_memory<GLint>(2);
5379
5380                 GL_ENTRYPOINT(glGetShaderiv)(replay_handle, pname, &params);
5381
5382                 if ((pClient_params) && (*pClient_params != params))
5383                 {
5384                     process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
5385                     vogl_warning_printf("Trace data: %i, Replay data: %i\n", pClient_params ? *pClient_params : 0, params);
5386                 }
5387             }
5388
5389             break;
5390         }
5391         case VOGL_ENTRYPOINT_glGetShaderInfoLog:
5392         {
5393             GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5394             GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5395
5396             GLsizei trace_max_length = trace_packet.get_param_value<GLsizei>(1);
5397             const GLsizei *pTrace_length = trace_packet.get_param_client_memory<GLsizei>(2);
5398             VOGL_NOTE_UNUSED(pTrace_length);
5399             const GLchar *pTrace_info_log = trace_packet.get_param_client_memory<GLchar>(3);
5400             VOGL_NOTE_UNUSED(pTrace_info_log);
5401
5402             vogl::growable_array<GLchar, 512> log(trace_max_length);
5403             GLsizei length = 0;
5404             GL_ENTRYPOINT(glGetShaderInfoLog)(replay_handle, trace_max_length, &length, log.get_ptr());
5405
5406             if (length)
5407             {
5408                 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());
5409             }
5410
5411             break;
5412         }
5413         case VOGL_ENTRYPOINT_glGetBooleanv:
5414         {
5415             if (!benchmark_mode())
5416             {
5417                 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5418                 const GLboolean *pParams = trace_packet.get_param_client_memory<GLboolean>(1);
5419
5420                 int n = g_gl_enums.get_pname_count(pname);
5421                 if (n <= 0)
5422                 {
5423                     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));
5424                     return cStatusSoftFailure;
5425                 }
5426                 else
5427                 {
5428                     vogl::growable_array<GLboolean, 16> params(n + 1);
5429                     params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_BYTE_MAGIC;
5430
5431                     GL_ENTRYPOINT(glGetBooleanv)(pname, params.get_ptr());
5432
5433                     VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_BYTE_MAGIC);
5434
5435                     if (memcmp(pParams, params.get_ptr(), n * sizeof(GLboolean)) != 0)
5436                     {
5437                         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));
5438                     }
5439                 }
5440             }
5441
5442             break;
5443         }
5444         case VOGL_ENTRYPOINT_glGetDoublev:
5445         {
5446             if (!benchmark_mode())
5447             {
5448                 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5449                 const GLdouble *pParams = trace_packet.get_param_client_memory<GLdouble>(1);
5450
5451                 int n = g_gl_enums.get_pname_count(pname);
5452                 if (n <= 0)
5453                 {
5454                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5455                     return cStatusSoftFailure;
5456                 }
5457                 else
5458                 {
5459                     vogl::growable_array<GLdouble, 17> params(n + 1);
5460                     params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
5461
5462                     GL_ENTRYPOINT(glGetDoublev)(pname, params.get_ptr());
5463
5464                     VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
5465
5466                     if (memcmp(pParams, params.get_ptr(), n * sizeof(GLdouble)) != 0)
5467                     {
5468                         process_entrypoint_warning("%s: Replay's returned GLdouble data differed from trace's\n", VOGL_METHOD_NAME);
5469                     }
5470                 }
5471             }
5472
5473             break;
5474         }
5475         case VOGL_ENTRYPOINT_glGetFloatv:
5476         {
5477             if (!benchmark_mode())
5478             {
5479                 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5480                 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<GLfloat>(1);
5481                 uint trace_params_count = trace_packet.get_param_client_memory_data_size(1) / sizeof(GLfloat);
5482
5483                 int n = g_gl_enums.get_pname_count(pname);
5484                 if (n <= 0)
5485                 {
5486                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5487                     return cStatusSoftFailure;
5488                 }
5489
5490                 vogl::growable_array<GLfloat, 17> params(n + 1);
5491                 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
5492
5493                 GL_ENTRYPOINT(glGetFloatv)(pname, params.get_ptr());
5494
5495                 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
5496
5497                 if (static_cast<int>(trace_params_count) < n)
5498                     process_entrypoint_warning("%s: Replay param array size (%u) does not match the expected size (%u)\n", VOGL_METHOD_NAME, trace_params_count, n);
5499                 else if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLfloat)) != 0)
5500                 {
5501                     process_entrypoint_warning("%s: Replay's returned GLfloat data differed from trace's\n", VOGL_METHOD_NAME);
5502                 }
5503             }
5504
5505             break;
5506         }
5507         case VOGL_ENTRYPOINT_glGetIntegerv:
5508         {
5509             if (!benchmark_mode())
5510             {
5511                 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5512                 const GLint *pTrace_params = trace_packet.get_param_client_memory<GLint>(1);
5513                 uint trace_params_count = trace_packet.get_param_client_memory_data_size(1) / sizeof(GLint);
5514
5515                 int n = g_gl_enums.get_pname_count(pname);
5516                 if (n <= 0)
5517                 {
5518                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5519                     return cStatusSoftFailure;
5520                 }
5521
5522                 vogl::growable_array<GLint, 16> params(n + 1);
5523                 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5524
5525                 GL_ENTRYPOINT(glGetIntegerv)(pname, params.get_ptr());
5526
5527                 VOGL_VERIFY(params[n] == (GLint)VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5528
5529                 bool is_binding = false;
5530                 switch (pname)
5531                 {
5532                     case GL_ARRAY_BUFFER_BINDING:
5533                     case GL_COLOR_ARRAY_BUFFER_BINDING:
5534                     case GL_DISPATCH_INDIRECT_BUFFER_BINDING:
5535                     case GL_DRAW_FRAMEBUFFER_BINDING:
5536                     case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING:
5537                     case GL_ELEMENT_ARRAY_BUFFER_BINDING:
5538                     case GL_FOG_COORD_ARRAY_BUFFER_BINDING:
5539                     case GL_INDEX_ARRAY_BUFFER_BINDING:
5540                     case GL_NORMAL_ARRAY_BUFFER_BINDING:
5541                     case GL_PIXEL_PACK_BUFFER_BINDING:
5542                     case GL_PIXEL_UNPACK_BUFFER_BINDING:
5543                     case GL_PROGRAM_PIPELINE_BINDING:
5544                     case GL_READ_FRAMEBUFFER_BINDING:
5545                     case GL_RENDERBUFFER_BINDING:
5546                     case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING:
5547                     case GL_SHADER_STORAGE_BUFFER_BINDING:
5548                     case GL_TEXTURE_BINDING_1D:
5549                     case GL_TEXTURE_BINDING_1D_ARRAY:
5550                     case GL_TEXTURE_BINDING_2D:
5551                     case GL_TEXTURE_BINDING_2D_ARRAY:
5552                     case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
5553                     case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
5554                     case GL_TEXTURE_BINDING_3D:
5555                     case GL_TEXTURE_BINDING_BUFFER:
5556                     case GL_TEXTURE_BINDING_CUBE_MAP:
5557                     case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
5558                     case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
5559                     case GL_TRANSFORM_FEEDBACK_BUFFER_START:
5560                     case GL_UNIFORM_BUFFER_BINDING:
5561                     case GL_VERTEX_ARRAY_BINDING:
5562                     case GL_VERTEX_ARRAY_BUFFER_BINDING:
5563                     case GL_CURRENT_PROGRAM:
5564                     {
5565                         is_binding = true;
5566                         break;
5567                     }
5568                     default:
5569                         break;
5570                 }
5571
5572                 // Don't bother diffing bindings, the trace's are in the trace domain while the glGet's results are in the replay domain.
5573                 if (!is_binding)
5574                 {
5575                     if (static_cast<int>(trace_params_count) < n)
5576                     {
5577                         process_entrypoint_warning("%s: Replay param array size (%u) does not match the expected size (%u)\n", VOGL_METHOD_NAME, trace_params_count, n);
5578                     }
5579                     else if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLint)) != 0)
5580                     {
5581                         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));
5582                         for (int i = 0; i < n; i++)
5583                             vogl_printf("GLint %u: Trace: %i, Replay: %i\n", i, pTrace_params[i], params[i]);
5584                     }
5585                 }
5586             }
5587
5588             break;
5589         }
5590         // glProgramUniform's
5591         case VOGL_ENTRYPOINT_glProgramUniform1f:
5592         {
5593             set_program_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glProgramUniform1f));
5594             break;
5595         }
5596         case VOGL_ENTRYPOINT_glProgramUniform1i:
5597         {
5598             set_program_uniform_helper1<GLint>(GL_ENTRYPOINT(glProgramUniform1i));
5599             break;
5600         }
5601         case VOGL_ENTRYPOINT_glProgramUniform1ui:
5602         {
5603             set_program_uniform_helper1<GLuint>(GL_ENTRYPOINT(glProgramUniform1ui));
5604             break;
5605         }
5606         case VOGL_ENTRYPOINT_glProgramUniform2f:
5607         {
5608             set_program_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glProgramUniform2f));
5609             break;
5610         }
5611         case VOGL_ENTRYPOINT_glProgramUniform2i:
5612         {
5613             set_program_uniform_helper2<GLint>(GL_ENTRYPOINT(glProgramUniform2i));
5614             break;
5615         }
5616         case VOGL_ENTRYPOINT_glProgramUniform2ui:
5617         {
5618             set_program_uniform_helper2<GLuint>(GL_ENTRYPOINT(glProgramUniform2ui));
5619             break;
5620         }
5621         case VOGL_ENTRYPOINT_glProgramUniform3f:
5622         {
5623             set_program_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glProgramUniform3f));
5624             break;
5625         }
5626         case VOGL_ENTRYPOINT_glProgramUniform3i:
5627         {
5628             set_program_uniform_helper3<GLint>(GL_ENTRYPOINT(glProgramUniform3i));
5629             break;
5630         }
5631         case VOGL_ENTRYPOINT_glProgramUniform3ui:
5632         {
5633             set_program_uniform_helper3<GLuint>(GL_ENTRYPOINT(glProgramUniform3ui));
5634             break;
5635         }
5636         case VOGL_ENTRYPOINT_glProgramUniform4f:
5637         {
5638             set_program_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glProgramUniform4f));
5639             break;
5640         }
5641         case VOGL_ENTRYPOINT_glProgramUniform4i:
5642         {
5643             set_program_uniform_helper4<GLint>(GL_ENTRYPOINT(glProgramUniform4i));
5644             break;
5645         }
5646         case VOGL_ENTRYPOINT_glProgramUniform4ui:
5647         {
5648             set_program_uniform_helper4<GLuint>(GL_ENTRYPOINT(glProgramUniform4ui));
5649             break;
5650         }
5651         case VOGL_ENTRYPOINT_glProgramUniform1fv:
5652         {
5653             set_program_uniformv_helper<1, float>(GL_ENTRYPOINT(glProgramUniform1fv));
5654             break;
5655         }
5656         case VOGL_ENTRYPOINT_glProgramUniform2fv:
5657         {
5658             set_program_uniformv_helper<2, float>(GL_ENTRYPOINT(glProgramUniform2fv));
5659             break;
5660         }
5661         case VOGL_ENTRYPOINT_glProgramUniform3fv:
5662         {
5663             set_program_uniformv_helper<3, float>(GL_ENTRYPOINT(glProgramUniform3fv));
5664             break;
5665         }
5666         case VOGL_ENTRYPOINT_glProgramUniform4fv:
5667         {
5668             set_program_uniformv_helper<4, float>(GL_ENTRYPOINT(glProgramUniform4fv));
5669             break;
5670         }
5671         case VOGL_ENTRYPOINT_glProgramUniform1iv:
5672         {
5673             set_program_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glProgramUniform1iv));
5674             break;
5675         }
5676         case VOGL_ENTRYPOINT_glProgramUniform2iv:
5677         {
5678             set_program_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glProgramUniform2iv));
5679             break;
5680         }
5681         case VOGL_ENTRYPOINT_glProgramUniform3iv:
5682         {
5683             set_program_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glProgramUniform3iv));
5684             break;
5685         }
5686         case VOGL_ENTRYPOINT_glProgramUniform4iv:
5687         {
5688             set_program_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glProgramUniform4iv));
5689             break;
5690         }
5691         case VOGL_ENTRYPOINT_glProgramUniform1uiv:
5692         {
5693             set_program_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glProgramUniform1uiv));
5694             break;
5695         }
5696         case VOGL_ENTRYPOINT_glProgramUniform2uiv:
5697         {
5698             set_program_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glProgramUniform2uiv));
5699             break;
5700         }
5701         case VOGL_ENTRYPOINT_glProgramUniform3uiv:
5702         {
5703             set_program_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glProgramUniform3uiv));
5704             break;
5705         }
5706         case VOGL_ENTRYPOINT_glProgramUniform4uiv:
5707         {
5708             set_program_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glProgramUniform4uiv));
5709             break;
5710         }
5711         case VOGL_ENTRYPOINT_glProgramUniformMatrix2fv:
5712         {
5713             set_program_uniform_matrixv_helper<2, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix2fv));
5714             break;
5715         }
5716         case VOGL_ENTRYPOINT_glProgramUniformMatrix3fv:
5717         {
5718             set_program_uniform_matrixv_helper<3, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix3fv));
5719             break;
5720         }
5721         case VOGL_ENTRYPOINT_glProgramUniformMatrix4fv:
5722         {
5723             set_program_uniform_matrixv_helper<4, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix4fv));
5724             break;
5725         }
5726         case VOGL_ENTRYPOINT_glProgramUniformMatrix2x3fv:
5727         {
5728             set_program_uniform_matrixv_helper<2, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix2x3fv));
5729             break;
5730         }
5731         case VOGL_ENTRYPOINT_glProgramUniformMatrix3x2fv:
5732         {
5733             set_program_uniform_matrixv_helper<3, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix3x2fv));
5734             break;
5735         }
5736         case VOGL_ENTRYPOINT_glProgramUniformMatrix2x4fv:
5737         {
5738             set_program_uniform_matrixv_helper<2, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix2x4fv));
5739             break;
5740         }
5741         case VOGL_ENTRYPOINT_glProgramUniformMatrix4x2fv:
5742         {
5743             set_program_uniform_matrixv_helper<4, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix4x2fv));
5744             break;
5745         }
5746         case VOGL_ENTRYPOINT_glProgramUniformMatrix3x4fv:
5747         {
5748             set_program_uniform_matrixv_helper<3, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix3x4fv));
5749             break;
5750         }
5751         case VOGL_ENTRYPOINT_glProgramUniformMatrix4x3fv:
5752         {
5753             set_program_uniform_matrixv_helper<4, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix4x3fv));
5754             break;
5755         }
5756         // glUniform's
5757         case VOGL_ENTRYPOINT_glUniform1f:
5758         {
5759             set_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glUniform1f));
5760             break;
5761         }
5762         case VOGL_ENTRYPOINT_glUniform1fARB:
5763         {
5764             set_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glUniform1fARB));
5765             break;
5766         }
5767         case VOGL_ENTRYPOINT_glUniform2f:
5768         {
5769             set_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glUniform2f));
5770             break;
5771         }
5772         case VOGL_ENTRYPOINT_glUniform2fARB:
5773         {
5774             set_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glUniform2fARB));
5775             break;
5776         }
5777         case VOGL_ENTRYPOINT_glUniform3f:
5778         {
5779             set_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glUniform3f));
5780             break;
5781         }
5782         case VOGL_ENTRYPOINT_glUniform3fARB:
5783         {
5784             set_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glUniform3fARB));
5785             break;
5786         }
5787         case VOGL_ENTRYPOINT_glUniform4f:
5788         {
5789             set_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glUniform4f));
5790             break;
5791         }
5792         case VOGL_ENTRYPOINT_glUniform4fARB:
5793         {
5794             set_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glUniform4fARB));
5795             break;
5796         }
5797         case VOGL_ENTRYPOINT_glUniform1i:
5798         {
5799             set_uniform_helper1<GLint>(GL_ENTRYPOINT(glUniform1i));
5800             break;
5801         }
5802         case VOGL_ENTRYPOINT_glUniform1iARB:
5803         {
5804             set_uniform_helper1<GLint>(GL_ENTRYPOINT(glUniform1iARB));
5805             break;
5806         }
5807         case VOGL_ENTRYPOINT_glUniform2i:
5808         {
5809             set_uniform_helper2<GLint>(GL_ENTRYPOINT(glUniform2i));
5810             break;
5811         }
5812         case VOGL_ENTRYPOINT_glUniform2iARB:
5813         {
5814             set_uniform_helper2<GLint>(GL_ENTRYPOINT(glUniform2iARB));
5815             break;
5816         }
5817         case VOGL_ENTRYPOINT_glUniform3i:
5818         {
5819             set_uniform_helper3<GLint>(GL_ENTRYPOINT(glUniform3i));
5820             break;
5821         }
5822         case VOGL_ENTRYPOINT_glUniform3iARB:
5823         {
5824             set_uniform_helper3<GLint>(GL_ENTRYPOINT(glUniform3iARB));
5825             break;
5826         }
5827         case VOGL_ENTRYPOINT_glUniform4i:
5828         {
5829             set_uniform_helper4<GLint>(GL_ENTRYPOINT(glUniform4i));
5830             break;
5831         }
5832         case VOGL_ENTRYPOINT_glUniform4iARB:
5833         {
5834             set_uniform_helper4<GLint>(GL_ENTRYPOINT(glUniform4iARB));
5835             break;
5836         }
5837         case VOGL_ENTRYPOINT_glUniform1ui:
5838         {
5839             set_uniform_helper1<GLuint>(GL_ENTRYPOINT(glUniform1ui));
5840             break;
5841         }
5842         case VOGL_ENTRYPOINT_glUniform1uiEXT:
5843         {
5844             set_uniform_helper1<GLuint>(GL_ENTRYPOINT(glUniform1uiEXT));
5845             break;
5846         }
5847         case VOGL_ENTRYPOINT_glUniform2ui:
5848         {
5849             set_uniform_helper2<GLuint>(GL_ENTRYPOINT(glUniform2ui));
5850             break;
5851         }
5852         case VOGL_ENTRYPOINT_glUniform2uiEXT:
5853         {
5854             set_uniform_helper2<GLuint>(GL_ENTRYPOINT(glUniform2uiEXT));
5855             break;
5856         }
5857         case VOGL_ENTRYPOINT_glUniform3ui:
5858         {
5859             set_uniform_helper3<GLuint>(GL_ENTRYPOINT(glUniform3ui));
5860             break;
5861         }
5862         case VOGL_ENTRYPOINT_glUniform3uiEXT:
5863         {
5864             set_uniform_helper3<GLuint>(GL_ENTRYPOINT(glUniform3uiEXT));
5865             break;
5866         }
5867         case VOGL_ENTRYPOINT_glUniform4ui:
5868         {
5869             set_uniform_helper4<GLuint>(GL_ENTRYPOINT(glUniform4ui));
5870             break;
5871         }
5872         case VOGL_ENTRYPOINT_glUniform4uiEXT:
5873         {
5874             set_uniform_helper4<GLuint>(GL_ENTRYPOINT(glUniform4uiEXT));
5875             break;
5876         }
5877         case VOGL_ENTRYPOINT_glUniform1uiv:
5878         {
5879             set_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glUniform1uiv));
5880             break;
5881         }
5882         case VOGL_ENTRYPOINT_glUniform1uivEXT:
5883         {
5884             set_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glUniform1uivEXT));
5885             break;
5886         }
5887         case VOGL_ENTRYPOINT_glUniform2uiv:
5888         {
5889             set_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glUniform2uiv));
5890             break;
5891         }
5892         case VOGL_ENTRYPOINT_glUniform2uivEXT:
5893         {
5894             set_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glUniform2uivEXT));
5895             break;
5896         }
5897         case VOGL_ENTRYPOINT_glUniform3uiv:
5898         {
5899             set_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glUniform3uiv));
5900             break;
5901         }
5902         case VOGL_ENTRYPOINT_glUniform3uivEXT:
5903         {
5904             set_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glUniform3uivEXT));
5905             break;
5906         }
5907         case VOGL_ENTRYPOINT_glUniform4uiv:
5908         {
5909             set_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glUniform4uiv));
5910             break;
5911         }
5912         case VOGL_ENTRYPOINT_glUniform4uivEXT:
5913         {
5914             set_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glUniform4uivEXT));
5915             break;
5916         }
5917         case VOGL_ENTRYPOINT_glUniform1iv:
5918         {
5919             set_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glUniform1iv));
5920             break;
5921         }
5922         case VOGL_ENTRYPOINT_glUniform1ivARB:
5923         {
5924             set_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glUniform1ivARB));
5925             break;
5926         }
5927         case VOGL_ENTRYPOINT_glUniform2iv:
5928         {
5929             set_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glUniform2iv));
5930             break;
5931         }
5932         case VOGL_ENTRYPOINT_glUniform2ivARB:
5933         {
5934             set_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glUniform2ivARB));
5935             break;
5936         }
5937         case VOGL_ENTRYPOINT_glUniform3iv:
5938         {
5939             set_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glUniform3iv));
5940             break;
5941         }
5942         case VOGL_ENTRYPOINT_glUniform3ivARB:
5943         {
5944             set_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glUniform3ivARB));
5945             break;
5946         }
5947         case VOGL_ENTRYPOINT_glUniform4iv:
5948         {
5949             set_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glUniform4iv));
5950             break;
5951         }
5952         case VOGL_ENTRYPOINT_glUniform4ivARB:
5953         {
5954             set_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glUniform4ivARB));
5955             break;
5956         }
5957         case VOGL_ENTRYPOINT_glUniform1fv:
5958         {
5959             set_uniformv_helper<1, GLfloat>(GL_ENTRYPOINT(glUniform1fv));
5960             break;
5961         }
5962         case VOGL_ENTRYPOINT_glUniform1fvARB:
5963         {
5964             set_uniformv_helper<1, GLfloat>(GL_ENTRYPOINT(glUniform1fvARB));
5965             break;
5966         }
5967         case VOGL_ENTRYPOINT_glUniform2fv:
5968         {
5969             set_uniformv_helper<2, GLfloat>(GL_ENTRYPOINT(glUniform2fv));
5970             break;
5971         }
5972         case VOGL_ENTRYPOINT_glUniform2fvARB:
5973         {
5974             set_uniformv_helper<2, GLfloat>(GL_ENTRYPOINT(glUniform2fvARB));
5975             break;
5976         }
5977         case VOGL_ENTRYPOINT_glUniform3fv:
5978         {
5979             set_uniformv_helper<3, GLfloat>(GL_ENTRYPOINT(glUniform3fv));
5980             break;
5981         }
5982         case VOGL_ENTRYPOINT_glUniform3fvARB:
5983         {
5984             set_uniformv_helper<3, GLfloat>(GL_ENTRYPOINT(glUniform3fvARB));
5985             break;
5986         }
5987         case VOGL_ENTRYPOINT_glUniform4fv:
5988         {
5989             set_uniformv_helper<4, GLfloat>(GL_ENTRYPOINT(glUniform4fv));
5990             break;
5991         }
5992         case VOGL_ENTRYPOINT_glUniform4fvARB:
5993         {
5994             set_uniformv_helper<4, GLfloat>(GL_ENTRYPOINT(glUniform4fvARB));
5995             break;
5996         }
5997         case VOGL_ENTRYPOINT_glUniformMatrix2fvARB:
5998         {
5999             set_uniform_matrixv_helper<2, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2fvARB));
6000             break;
6001         }
6002         case VOGL_ENTRYPOINT_glUniformMatrix2fv:
6003         {
6004             set_uniform_matrixv_helper<2, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2fv));
6005             break;
6006         }
6007         case VOGL_ENTRYPOINT_glUniformMatrix3fvARB:
6008         {
6009             set_uniform_matrixv_helper<3, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3fvARB));
6010             break;
6011         }
6012         case VOGL_ENTRYPOINT_glUniformMatrix3fv:
6013         {
6014             set_uniform_matrixv_helper<3, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3fv));
6015             break;
6016         }
6017         case VOGL_ENTRYPOINT_glUniformMatrix4fvARB:
6018         {
6019             set_uniform_matrixv_helper<4, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4fvARB));
6020             break;
6021         }
6022         case VOGL_ENTRYPOINT_glUniformMatrix4fv:
6023         {
6024             set_uniform_matrixv_helper<4, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4fv));
6025             break;
6026         }
6027         case VOGL_ENTRYPOINT_glUniformMatrix2x3fv:
6028         {
6029             set_uniform_matrixv_helper<2, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2x3fv));
6030             break;
6031         }
6032         case VOGL_ENTRYPOINT_glUniformMatrix3x2fv:
6033         {
6034             set_uniform_matrixv_helper<3, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3x2fv));
6035             break;
6036         }
6037         case VOGL_ENTRYPOINT_glUniformMatrix2x4fv:
6038         {
6039             set_uniform_matrixv_helper<2, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2x4fv));
6040             break;
6041         }
6042         case VOGL_ENTRYPOINT_glUniformMatrix4x2fv:
6043         {
6044             set_uniform_matrixv_helper<4, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4x2fv));
6045             break;
6046         }
6047         case VOGL_ENTRYPOINT_glUniformMatrix3x4fv:
6048         {
6049             set_uniform_matrixv_helper<3, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3x4fv));
6050             break;
6051         }
6052         case VOGL_ENTRYPOINT_glUniformMatrix4x3fv:
6053         {
6054             set_uniform_matrixv_helper<4, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4x3fv));
6055             break;
6056         }
6057         case VOGL_ENTRYPOINT_glBeginQuery:
6058         case VOGL_ENTRYPOINT_glBeginQueryARB:
6059         {
6060             GLenum target = trace_packet.get_param_value<GLenum>(0);
6061             GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
6062             GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6063
6064             if (!m_pCur_context_state->m_inside_gl_begin)
6065                 check_gl_error();
6066
6067             if (entrypoint_id == VOGL_ENTRYPOINT_glBeginQuery)
6068                 GL_ENTRYPOINT(glBeginQuery)(target, replay_handle);
6069             else
6070                 GL_ENTRYPOINT(glBeginQueryARB)(target, replay_handle);
6071
6072             if ((replay_handle) && (!m_pCur_context_state->m_inside_gl_begin) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6073             {
6074                 if (check_gl_error())
6075                     return cStatusGLError;
6076
6077                 get_shared_state()->m_query_targets[replay_handle] = target;
6078             }
6079
6080             break;
6081         }
6082         case VOGL_ENTRYPOINT_glEndQuery:
6083         {
6084             GL_ENTRYPOINT(glEndQuery)(trace_packet.get_param_value<GLenum>(0));
6085             break;
6086         }
6087         case VOGL_ENTRYPOINT_glEndQueryARB:
6088         {
6089             GL_ENTRYPOINT(glEndQueryARB)(trace_packet.get_param_value<GLenum>(0));
6090             break;
6091         }
6092         case VOGL_ENTRYPOINT_glGetQueryObjectiv:
6093         {
6094             GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6095             GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6096
6097             GLenum pname = trace_packet.get_param_value<GLenum>(1);
6098
6099             int n = g_gl_enums.get_pname_count(pname);
6100             if (n <= 0)
6101             {
6102                 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6103                 return cStatusSoftFailure;
6104             }
6105             else
6106             {
6107                 vogl::growable_array<GLint, 16> params(n + 1);
6108                 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6109
6110                 GL_ENTRYPOINT(glGetQueryObjectiv)(replay_handle, pname, params.get_ptr());
6111
6112                 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6113             }
6114
6115             break;
6116         }
6117         case VOGL_ENTRYPOINT_glGetQueryObjectivARB:
6118         {
6119             GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6120             GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6121
6122             GLenum pname = trace_packet.get_param_value<GLenum>(1);
6123
6124             int n = g_gl_enums.get_pname_count(pname);
6125             if (n <= 0)
6126             {
6127                 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6128                 return cStatusSoftFailure;
6129             }
6130             else
6131             {
6132                 vogl::growable_array<GLint, 16> params(n + 1);
6133                 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6134
6135                 GL_ENTRYPOINT(glGetQueryObjectivARB)(replay_handle, pname, params.get_ptr());
6136
6137                 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6138             }
6139
6140             break;
6141         }
6142         case VOGL_ENTRYPOINT_glGetQueryObjectuiv:
6143         {
6144             GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6145             GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6146
6147             GLenum pname = trace_packet.get_param_value<GLenum>(1);
6148
6149             int n = g_gl_enums.get_pname_count(pname);
6150             if (n <= 0)
6151             {
6152                 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6153                 return cStatusSoftFailure;
6154             }
6155             else
6156             {
6157                 vogl::growable_array<GLuint, 16> params(n + 1);
6158                 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6159
6160                 GL_ENTRYPOINT(glGetQueryObjectuiv)(replay_handle, pname, params.get_ptr());
6161
6162                 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6163             }
6164
6165             break;
6166         }
6167         case VOGL_ENTRYPOINT_glGetQueryObjectuivARB:
6168         {
6169             GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6170             GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6171
6172             GLenum pname = trace_packet.get_param_value<GLenum>(1);
6173
6174             int n = g_gl_enums.get_pname_count(pname);
6175             if (n <= 0)
6176             {
6177                 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6178                 return cStatusSoftFailure;
6179             }
6180             else
6181             {
6182                 vogl::growable_array<GLuint, 16> params(n + 1);
6183                 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6184
6185                 GL_ENTRYPOINT(glGetQueryObjectuivARB)(replay_handle, pname, params.get_ptr());
6186
6187                 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6188             }
6189
6190             break;
6191         }
6192         case VOGL_ENTRYPOINT_glQueryCounter:
6193         {
6194             VOGL_REPLAY_LOAD_PARAMS_HELPER_glQueryCounter;
6195
6196             id = map_handle(get_shared_state()->m_queries, id);
6197
6198             VOGL_REPLAY_CALL_GL_HELPER_glQueryCounter;
6199
6200             break;
6201         }
6202         case VOGL_ENTRYPOINT_glGetQueryObjecti64v:
6203         {
6204             VOGL_REPLAY_LOAD_PARAMS_HELPER_glGetQueryObjecti64v;
6205             VOGL_NOTE_UNUSED(pTrace_params);
6206
6207             id = map_handle(get_shared_state()->m_queries, id);
6208
6209             int n = g_gl_enums.get_pname_count(pname);
6210             if (n <= 0)
6211             {
6212                 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6213                 return cStatusSoftFailure;
6214             }
6215
6216             vogl::growable_array<GLint64, 16> temp_params(n + 1);
6217             temp_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6218
6219             GLint64 *pReplay_params = temp_params.get_ptr();
6220
6221             VOGL_REPLAY_CALL_GL_HELPER_glGetQueryObjecti64v;
6222
6223             VOGL_VERIFY(temp_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6224
6225             break;
6226         }
6227         case VOGL_ENTRYPOINT_glGetQueryObjectui64v:
6228         {
6229             VOGL_REPLAY_LOAD_PARAMS_HELPER_glGetQueryObjectui64v;
6230             VOGL_NOTE_UNUSED(pTrace_params);
6231
6232             id = map_handle(get_shared_state()->m_queries, id);
6233
6234             int n = g_gl_enums.get_pname_count(pname);
6235             if (n <= 0)
6236             {
6237                 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6238                 return cStatusSoftFailure;
6239             }
6240
6241             vogl::growable_array<GLuint64, 16> temp_params(n + 1);
6242             temp_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6243
6244             GLuint64 *pReplay_params = temp_params.get_ptr();
6245
6246             VOGL_REPLAY_CALL_GL_HELPER_glGetQueryObjectui64v;
6247
6248             VOGL_VERIFY(temp_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6249
6250             break;
6251         }
6252         case VOGL_ENTRYPOINT_glBindBuffer:
6253         case VOGL_ENTRYPOINT_glBindBufferARB:
6254         {
6255             GLenum target = trace_packet.get_param_value<GLenum>(0);
6256             GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
6257             GLuint replay_handle = map_handle(get_shared_state()->m_buffers, trace_handle);
6258
6259             check_gl_error();
6260
6261             SWITCH_GL_ENTRYPOINT2_VOID(glBindBuffer, glBindBufferARB, target, replay_handle);
6262
6263             if (check_gl_error())
6264                 return cStatusGLError;
6265
6266             if ((trace_handle) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6267             {
6268                 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_handle);
6269                 if (!pBinding)
6270                     process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_handle);
6271                 else if (*pBinding == GL_NONE)
6272                     *pBinding = target;
6273             }
6274
6275             break;
6276         }
6277         case VOGL_ENTRYPOINT_glBindBufferBase:
6278         case VOGL_ENTRYPOINT_glBindBufferBaseEXT:
6279         case VOGL_ENTRYPOINT_glBindBufferBaseNV:
6280         {
6281             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindBufferBase;
6282
6283             GLuint trace_buffer = buffer;
6284             buffer = map_handle(get_shared_state()->m_buffers, buffer);
6285
6286             check_gl_error();
6287
6288             if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferBaseNV)
6289                 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBaseNV;
6290             else if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferBaseEXT)
6291                 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBaseEXT;
6292             else
6293                 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBase;
6294
6295             if (check_gl_error())
6296                 return cStatusGLError;
6297
6298             if ((trace_buffer) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6299             {
6300                 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_buffer);
6301                 if (!pBinding)
6302                     process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_buffer);
6303                 else if (*pBinding == GL_NONE)
6304                     *pBinding = target;
6305             }
6306
6307             break;
6308         }
6309         case VOGL_ENTRYPOINT_glBindBufferRange:
6310         case VOGL_ENTRYPOINT_glBindBufferRangeEXT:
6311         case VOGL_ENTRYPOINT_glBindBufferRangeNV:
6312         {
6313             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindBufferRange;
6314
6315             GLuint trace_buffer = buffer;
6316             buffer = map_handle(get_shared_state()->m_buffers, buffer);
6317
6318             check_gl_error();
6319
6320             if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferRangeNV)
6321                 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRangeNV;
6322             else if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferRangeEXT)
6323                 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRangeEXT;
6324             else
6325                 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRange;
6326
6327             if (check_gl_error())
6328                 return cStatusGLError;
6329
6330             if ((trace_buffer) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6331             {
6332                 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_buffer);
6333                 if (!pBinding)
6334                     process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_buffer);
6335                 else if (*pBinding == GL_NONE)
6336                     *pBinding = target;
6337             }
6338
6339             break;
6340         }
6341         case VOGL_ENTRYPOINT_glFenceSync:
6342         {
6343             vogl_sync_ptr_value trace_handle = trace_packet.get_return_ptr_value();
6344             if (trace_handle)
6345             {
6346                 GLsync replay_handle = GL_ENTRYPOINT(glFenceSync)(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLbitfield>(1));
6347                 if (!replay_handle)
6348                 {
6349                     process_entrypoint_error("%s: glFenceSync on trace handle 0x%" PRIX64 " succeeded in the trace, but failed during replay!\n", VOGL_METHOD_NAME, trace_handle);
6350                     return cStatusHardFailure;
6351                 }
6352                 else
6353                 {
6354                     get_shared_state()->m_syncs.insert(trace_handle, replay_handle);
6355                 }
6356             }
6357
6358             break;
6359         }
6360         case VOGL_ENTRYPOINT_glWaitSync:
6361         case VOGL_ENTRYPOINT_glClientWaitSync:
6362         {
6363             vogl_sync_ptr_value trace_sync = trace_packet.get_param_ptr_value(0);
6364             GLsync replay_sync = NULL;
6365
6366             gl_sync_hash_map::const_iterator it = get_shared_state()->m_syncs.find(trace_sync);
6367             if (it == get_shared_state()->m_syncs.end())
6368             {
6369                 if (trace_sync)
6370                 {
6371                     process_entrypoint_error("%s: Unable to map trace sync handle 0x%" PRIX64 " to GL handle\n", VOGL_METHOD_NAME, trace_sync);
6372                     return cStatusHardFailure;
6373                 }
6374             }
6375             else
6376             {
6377                 replay_sync = it->second;
6378             }
6379
6380             if (entrypoint_id == VOGL_ENTRYPOINT_glWaitSync)
6381                 GL_ENTRYPOINT(glWaitSync)(replay_sync, trace_packet.get_param_value<GLbitfield>(1), trace_packet.get_param_value<GLuint64>(2));
6382             else
6383                 GL_ENTRYPOINT(glClientWaitSync)(replay_sync, trace_packet.get_param_value<GLbitfield>(1), trace_packet.get_param_value<GLuint64>(2));
6384
6385             break;
6386         }
6387         case VOGL_ENTRYPOINT_glDeleteSync:
6388         {
6389             vogl_sync_ptr_value trace_sync = trace_packet.get_param_ptr_value(0);
6390             GLsync replay_sync = NULL;
6391
6392             gl_sync_hash_map::const_iterator it = get_shared_state()->m_syncs.find(trace_sync);
6393             if (it == get_shared_state()->m_syncs.end())
6394             {
6395                 if (trace_sync)
6396                 {
6397                     process_entrypoint_error("%s: Unable to map trace sync handle 0x%" PRIX64 " to GL handle\n", VOGL_METHOD_NAME, trace_sync);
6398                     return cStatusHardFailure;
6399                 }
6400             }
6401             else
6402             {
6403                 replay_sync = it->second;
6404             }
6405
6406             GL_ENTRYPOINT(glDeleteSync)(replay_sync);
6407
6408             if (trace_sync)
6409             {
6410                 get_shared_state()->m_syncs.erase(trace_sync);
6411             }
6412
6413             break;
6414         }
6415         case VOGL_ENTRYPOINT_glVertexPointer:
6416         {
6417             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),
6418                                 vogl_vertex_pointer_array_id, GL_ENTRYPOINT(glVertexPointer), m_client_side_array_data[vogl_vertex_pointer_array_id]);
6419             break;
6420         }
6421         case VOGL_ENTRYPOINT_glVertexPointerEXT:
6422         {
6423             VOGL_REPLAY_LOAD_PARAMS_HELPER_glVertexPointerEXT;
6424             VOGL_NOTE_UNUSED(pTrace_pointer);
6425
6426             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]);
6427             break;
6428         }
6429         case VOGL_ENTRYPOINT_glColorPointer:
6430         {
6431             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),
6432                                 vogl_color_pointer_array_id, GL_ENTRYPOINT(glColorPointer), m_client_side_array_data[vogl_color_pointer_array_id]);
6433             break;
6434         }
6435         case VOGL_ENTRYPOINT_glColorPointerEXT:
6436         {
6437             VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorPointerEXT;
6438             VOGL_NOTE_UNUSED(pTrace_pointer);
6439
6440             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]);
6441             break;
6442         }
6443         case VOGL_ENTRYPOINT_glSecondaryColorPointer:
6444         {
6445             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),
6446                                 vogl_secondary_color_pointer_array_id, GL_ENTRYPOINT(glSecondaryColorPointer), m_client_side_array_data[vogl_secondary_color_pointer_array_id]);
6447             break;
6448         }
6449         case VOGL_ENTRYPOINT_glSecondaryColorPointerEXT:
6450         {
6451             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),
6452                                 vogl_secondary_color_pointer_array_id, GL_ENTRYPOINT(glSecondaryColorPointerEXT), m_client_side_array_data[vogl_secondary_color_pointer_array_id]);
6453             break;
6454         }
6455         case VOGL_ENTRYPOINT_glTexCoordPointer:
6456         {
6457             GLint cur_client_active_texture = 0;
6458             GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6459
6460             int tex_index = cur_client_active_texture - GL_TEXTURE0;
6461             if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6462             {
6463                 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);
6464                 return cStatusSoftFailure;
6465             }
6466
6467             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),
6468                                 vogl_texcoord_pointer_array_id, GL_ENTRYPOINT(glTexCoordPointer), m_client_side_texcoord_data[tex_index]);
6469             break;
6470         }
6471         case VOGL_ENTRYPOINT_glTexCoordPointerEXT:
6472         {
6473             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexCoordPointerEXT;
6474             VOGL_NOTE_UNUSED(pTrace_pointer);
6475
6476             GLint cur_client_active_texture = 0;
6477             GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6478
6479             int tex_index = cur_client_active_texture - GL_TEXTURE0;
6480             if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6481             {
6482                 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);
6483                 return cStatusSoftFailure;
6484             }
6485
6486             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]);
6487             break;
6488         }
6489         case VOGL_ENTRYPOINT_glFogCoordPointer:
6490         {
6491             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),
6492                                         vogl_fog_coord_pointer_array_id, GL_ENTRYPOINT(glFogCoordPointer));
6493             break;
6494         }
6495         case VOGL_ENTRYPOINT_glFogCoordPointerEXT:
6496         {
6497             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),
6498                                         vogl_fog_coord_pointer_array_id, GL_ENTRYPOINT(glFogCoordPointerEXT));
6499             break;
6500         }
6501         case VOGL_ENTRYPOINT_glIndexPointer:
6502         {
6503             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),
6504                                         vogl_index_pointer_array_id, GL_ENTRYPOINT(glIndexPointer));
6505             break;
6506         }
6507         case VOGL_ENTRYPOINT_glIndexPointerEXT:
6508         {
6509             VOGL_REPLAY_LOAD_PARAMS_HELPER_glIndexPointerEXT;
6510             VOGL_NOTE_UNUSED(pTrace_pointer);
6511
6512             vertex_array_helper_no_size_count(type, stride, count, trace_packet.get_param_ptr_value(3), vogl_index_pointer_array_id, GL_ENTRYPOINT(glIndexPointerEXT));
6513             break;
6514         }
6515         case VOGL_ENTRYPOINT_glNormalPointer:
6516         {
6517             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),
6518                                         vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointer));
6519             break;
6520         }
6521         case VOGL_ENTRYPOINT_glNormalPointerEXT:
6522         {
6523             VOGL_REPLAY_LOAD_PARAMS_HELPER_glNormalPointerEXT;
6524             VOGL_NOTE_UNUSED(pTrace_pointer);
6525
6526             vertex_array_helper_no_size_count(type, stride, count, trace_packet.get_param_ptr_value(3), vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointerEXT));
6527             break;
6528         }
6529         case VOGL_ENTRYPOINT_glEdgeFlagPointer:
6530         {
6531             vertex_array_helper_no_type_no_size(trace_packet.get_param_value<GLsizei>(0), trace_packet.get_param_ptr_value(1),
6532                                                 vogl_edge_flag_pointer_array_id, GL_ENTRYPOINT(glEdgeFlagPointer));
6533             break;
6534         }
6535         case VOGL_ENTRYPOINT_glEdgeFlagPointerEXT:
6536         {
6537             VOGL_REPLAY_LOAD_PARAMS_HELPER_glEdgeFlagPointerEXT;
6538             VOGL_NOTE_UNUSED(pTrace_pointer);
6539
6540             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));
6541             break;
6542         }
6543         case VOGL_ENTRYPOINT_glInterleavedArrays:
6544         {
6545             // TODO: Test this more!
6546             GLenum format = trace_packet.get_param_value<GLenum>(0);
6547             GLsizei stride = trace_packet.get_param_value<GLsizei>(1);
6548             const vogl_trace_ptr_value trace_pointer_value = trace_packet.get_param_ptr_value(2);
6549
6550             uint fmt_index;
6551             for (fmt_index = 0; fmt_index < VOGL_INTERLEAVED_ARRAY_SIZE; fmt_index++)
6552                 if (format == vogl_g_interleaved_array_descs[fmt_index].fmt)
6553                     break;
6554             if (fmt_index == VOGL_INTERLEAVED_ARRAY_SIZE)
6555             {
6556                 process_entrypoint_error("%s: Invalid interleaved vertex format: 0x%X \n", VOGL_METHOD_NAME, format);
6557                 return cStatusSoftFailure;
6558             }
6559
6560             if (stride < 0)
6561             {
6562                 process_entrypoint_error("%s: Invalid interleaved vertex stride: %i\n", VOGL_METHOD_NAME, static_cast<int>(stride));
6563                 return cStatusSoftFailure;
6564             }
6565
6566             const interleaved_array_desc_entry_t &fmt = vogl_g_interleaved_array_descs[fmt_index];
6567
6568             if (!stride)
6569             {
6570                 stride = fmt.s;
6571                 VOGL_ASSERT(stride > 0);
6572             }
6573
6574             GL_ENTRYPOINT(glDisableClientState)(GL_EDGE_FLAG_ARRAY);
6575             GL_ENTRYPOINT(glDisableClientState)(GL_INDEX_ARRAY);
6576             GL_ENTRYPOINT(glDisableClientState)(GL_SECONDARY_COLOR_ARRAY);
6577             GL_ENTRYPOINT(glDisableClientState)(GL_FOG_COORD_ARRAY);
6578
6579             check_gl_error();
6580
6581             if (fmt.et)
6582             {
6583                 GLint cur_client_active_texture = 0;
6584                 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6585
6586                 int tex_index = cur_client_active_texture - GL_TEXTURE0;
6587                 if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6588                 {
6589                     process_entrypoint_error("%s: glInterleavedArrays called with an invalid or unsupported client active texture (0x%08X)\n", VOGL_METHOD_NAME, cur_client_active_texture);
6590                     return cStatusSoftFailure;
6591                 }
6592
6593                 GL_ENTRYPOINT(glEnableClientState)(GL_TEXTURE_COORD_ARRAY);
6594                 vertex_array_helper(fmt.st, GL_FLOAT, stride, trace_pointer_value,
6595                                     vogl_texcoord_pointer_array_id, GL_ENTRYPOINT(glTexCoordPointer), m_client_side_texcoord_data[tex_index]);
6596             }
6597             else
6598             {
6599                 GL_ENTRYPOINT(glDisableClientState)(GL_TEXTURE_COORD_ARRAY);
6600             }
6601
6602             check_gl_error();
6603
6604             if (fmt.ec)
6605             {
6606                 GL_ENTRYPOINT(glEnableClientState)(GL_COLOR_ARRAY);
6607                 vertex_array_helper(fmt.sc, fmt.tc, stride, trace_pointer_value + fmt.pc,
6608                                     vogl_color_pointer_array_id, GL_ENTRYPOINT(glColorPointer), m_client_side_array_data[vogl_color_pointer_array_id]);
6609             }
6610             else
6611             {
6612                 GL_ENTRYPOINT(glDisableClientState)(GL_COLOR_ARRAY);
6613             }
6614
6615             check_gl_error();
6616
6617             if (fmt.en)
6618             {
6619                 GL_ENTRYPOINT(glEnableClientState)(GL_NORMAL_ARRAY);
6620                 vertex_array_helper_no_size(GL_FLOAT, stride, trace_pointer_value + fmt.pn,
6621                                             vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointer));
6622             }
6623             else
6624             {
6625                 GL_ENTRYPOINT(glDisableClientState)(GL_NORMAL_ARRAY);
6626             }
6627
6628             check_gl_error();
6629
6630             GL_ENTRYPOINT(glEnableClientState)(GL_VERTEX_ARRAY);
6631             vertex_array_helper(fmt.sv, GL_FLOAT, stride, trace_pointer_value + fmt.pv,
6632                                 vogl_vertex_pointer_array_id, GL_ENTRYPOINT(glVertexPointer), m_client_side_array_data[vogl_vertex_pointer_array_id]);
6633
6634             break;
6635         }
6636         case VOGL_ENTRYPOINT_glVertexAttribIPointer:
6637         case VOGL_ENTRYPOINT_glVertexAttribIPointerEXT:
6638         {
6639             GLuint index = trace_packet.get_param_value<GLuint>(0);
6640             GLint size = trace_packet.get_param_value<GLint>(1);
6641             GLenum type = trace_packet.get_param_value<GLenum>(2);
6642             GLsizei stride = trace_packet.get_param_value<GLsizei>(3);
6643             vogl_trace_ptr_value trace_pointer = trace_packet.get_param_ptr_value(4);
6644
6645             if (index >= m_pCur_context_state->m_context_info.get_max_vertex_attribs())
6646             {
6647                 process_entrypoint_error("%s: Generic vertex attribute index is too large\n", VOGL_METHOD_NAME);
6648                 return cStatusSoftFailure;
6649             }
6650
6651             GLuint buffer = vogl_get_bound_gl_buffer(GL_ARRAY_BUFFER);
6652             void *pPtr = reinterpret_cast<void *>(trace_pointer);
6653             if ((!buffer) && (trace_pointer))
6654             {
6655                 // We've got a trace pointer to client side memory, but we don't have it until the actual draw.
6656                 // So point this guy into one of our client size memory buffers that's hopefully large enough.
6657                 if (!m_client_side_vertex_attrib_data[index].size())
6658                 {
6659                     m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
6660                 }
6661                 pPtr = m_client_side_vertex_attrib_data[index].get_ptr();
6662             }
6663
6664             if (entrypoint_id == VOGL_ENTRYPOINT_glVertexAttribIPointer)
6665                 GL_ENTRYPOINT(glVertexAttribIPointer)(index, size, type, stride, pPtr);
6666             else
6667                 GL_ENTRYPOINT(glVertexAttribIPointerEXT)(index, size, type, stride, pPtr);
6668
6669             break;
6670         }
6671         case VOGL_ENTRYPOINT_glVertexAttribPointerARB:
6672         case VOGL_ENTRYPOINT_glVertexAttribPointer:
6673         {
6674             GLuint index = trace_packet.get_param_value<GLuint>(0);
6675             GLint size = trace_packet.get_param_value<GLint>(1);
6676             GLenum type = trace_packet.get_param_value<GLenum>(2);
6677             GLboolean normalized = trace_packet.get_param_value<GLboolean>(3);
6678             GLsizei stride = trace_packet.get_param_value<GLsizei>(4);
6679             vogl_trace_ptr_value trace_pointer = trace_packet.get_param_ptr_value(5);
6680
6681             if (index >= m_pCur_context_state->m_context_info.get_max_vertex_attribs())
6682             {
6683                 process_entrypoint_error("%s: Generic vertex attribute index is too large\n", VOGL_METHOD_NAME);
6684                 return cStatusSoftFailure;
6685             }
6686
6687             GLuint buffer = vogl_get_bound_gl_buffer(GL_ARRAY_BUFFER);
6688             void *pPtr = reinterpret_cast<void *>(trace_pointer);
6689             if ((!buffer) && (trace_pointer))
6690             {
6691                 // We've got a trace pointer to client side memory, but we don't have it until the actual draw.
6692                 // So point this guy into one of our client size memory buffers that's hopefully large enough.
6693                 if (!m_client_side_vertex_attrib_data[index].size())
6694                 {
6695                     m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
6696                 }
6697                 pPtr = m_client_side_vertex_attrib_data[index].get_ptr();
6698             }
6699
6700             if (entrypoint_id == VOGL_ENTRYPOINT_glVertexAttribPointer)
6701                 GL_ENTRYPOINT(glVertexAttribPointer)(index, size, type, normalized, stride, pPtr);
6702             else
6703                 GL_ENTRYPOINT(glVertexAttribPointerARB)(index, size, type, normalized, stride, pPtr);
6704
6705             break;
6706         }
6707         case VOGL_ENTRYPOINT_glDrawRangeElements:
6708         case VOGL_ENTRYPOINT_glDrawRangeElementsEXT:
6709         {
6710             GLenum mode = trace_packet.get_param_value<GLenum>(0);
6711             GLuint start = trace_packet.get_param_value<GLuint>(1);
6712             GLuint end = trace_packet.get_param_value<GLuint>(2);
6713             GLsizei count = trace_packet.get_param_value<GLsizei>(3);
6714             GLenum type = trace_packet.get_param_value<GLenum>(4);
6715             vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(5);
6716
6717             const GLvoid *pIndices;
6718             if (!draw_elements_client_side_array_setup(mode, start, end, count, type, trace_indices_ptr_value, pIndices, 0, true, true))
6719                 return cStatusSoftFailure;
6720
6721             if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6722             {
6723                 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawRangeElements)
6724                     GL_ENTRYPOINT(glDrawRangeElements)(mode, start, end, count, type, pIndices);
6725                 else
6726                     GL_ENTRYPOINT(glDrawRangeElementsEXT)(mode, start, end, count, type, pIndices);
6727             }
6728
6729             break;
6730         }
6731         case VOGL_ENTRYPOINT_glDrawRangeElementsBaseVertex:
6732         {
6733             GLenum mode = trace_packet.get_param_value<GLenum>(0);
6734             GLuint start = trace_packet.get_param_value<GLuint>(1);
6735             GLuint end = trace_packet.get_param_value<GLuint>(2);
6736             GLsizei count = trace_packet.get_param_value<GLsizei>(3);
6737             GLenum type = trace_packet.get_param_value<GLenum>(4);
6738             vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(5);
6739             GLint basevertex = trace_packet.get_param_value<GLint>(6);
6740
6741             const GLvoid *pIndices;
6742             if (!draw_elements_client_side_array_setup(mode, start, end, count, type, trace_indices_ptr_value, pIndices, basevertex, true, true))
6743                 return cStatusSoftFailure;
6744
6745             if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6746             {
6747                 GL_ENTRYPOINT(glDrawRangeElementsBaseVertex)(mode, start, end, count, type, pIndices, basevertex);
6748             }
6749
6750             break;
6751         }
6752         case VOGL_ENTRYPOINT_glDrawElements:
6753         {
6754             GLenum mode = trace_packet.get_param_value<GLenum>(0);
6755             GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6756             GLenum type = trace_packet.get_param_value<GLenum>(2);
6757             vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6758
6759             const GLvoid *pIndices;
6760             if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, 0, false, true))
6761                 return cStatusSoftFailure;
6762
6763             if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6764             {
6765                 GL_ENTRYPOINT(glDrawElements)(mode, count, type, pIndices);
6766             }
6767
6768             break;
6769         }
6770         case VOGL_ENTRYPOINT_glDrawArraysInstanced:
6771         case VOGL_ENTRYPOINT_glDrawArraysInstancedEXT:
6772         {
6773             VOGL_REPLAY_LOAD_PARAMS_HELPER_glDrawArraysInstanced;
6774
6775             const GLvoid *pIndices = NULL;
6776             if (!draw_elements_client_side_array_setup(mode, first, first + count - 1, count, GL_UNSIGNED_BYTE, 0, pIndices, 0, true, false))
6777                 return cStatusSoftFailure;
6778
6779             if (entrypoint_id == VOGL_ENTRYPOINT_glDrawArraysInstancedEXT)
6780             {
6781                 GLsizei start = first, primcount = instancecount;
6782                 VOGL_REPLAY_CALL_GL_HELPER_glDrawArraysInstancedEXT;
6783             }
6784             else
6785                 VOGL_REPLAY_CALL_GL_HELPER_glDrawArraysInstanced;
6786
6787             break;
6788         }
6789         case VOGL_ENTRYPOINT_glDrawArrays:
6790         case VOGL_ENTRYPOINT_glDrawArraysEXT:
6791         {
6792             GLenum mode = trace_packet.get_param_value<GLenum>(0);
6793             GLint first = trace_packet.get_param_value<GLint>(1);
6794             GLsizei count = trace_packet.get_param_value<GLsizei>(2);
6795
6796             const GLvoid *pIndices = NULL;
6797             if (!draw_elements_client_side_array_setup(mode, first, first + count - 1, count, GL_UNSIGNED_BYTE, 0, pIndices, 0, true, false))
6798                 return cStatusSoftFailure;
6799
6800             if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6801             {
6802                 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawArraysEXT)
6803                     GL_ENTRYPOINT(glDrawArraysEXT)(mode, first, count);
6804                 else
6805                     GL_ENTRYPOINT(glDrawArrays)(mode, first, count);
6806             }
6807
6808             break;
6809         }
6810         case VOGL_ENTRYPOINT_glDrawElementsInstanced:
6811         case VOGL_ENTRYPOINT_glDrawElementsInstancedARB:
6812         case VOGL_ENTRYPOINT_glDrawElementsInstancedEXT:
6813         {
6814             GLenum mode = trace_packet.get_param_value<GLenum>(0);
6815             GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6816             GLenum type = trace_packet.get_param_value<GLenum>(2);
6817             vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6818             GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6819
6820             const GLvoid *pIndices;
6821             if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, 0, false, true))
6822                 return cStatusSoftFailure;
6823
6824             if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6825             {
6826                 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawElementsInstanced)
6827                     GL_ENTRYPOINT(glDrawElementsInstanced)(mode, count, type, pIndices, primcount);
6828                 else if (entrypoint_id == VOGL_ENTRYPOINT_glDrawElementsInstancedEXT)
6829                     GL_ENTRYPOINT(glDrawElementsInstancedEXT)(mode, count, type, pIndices, primcount);
6830                 else
6831                     GL_ENTRYPOINT(glDrawElementsInstancedARB)(mode, count, type, pIndices, primcount);
6832             }
6833
6834             break;
6835         }
6836         case VOGL_ENTRYPOINT_glDrawElementsInstancedBaseVertex:
6837         {
6838             GLenum mode = trace_packet.get_param_value<GLenum>(0);
6839             GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6840             GLenum type = trace_packet.get_param_value<GLenum>(2);
6841             vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6842             GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6843             GLint basevertex = trace_packet.get_param_value<GLint>(5);
6844
6845             const GLvoid *pIndices;
6846             if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, basevertex, false, true))
6847                 return cStatusSoftFailure;
6848
6849             if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6850             {
6851                 GL_ENTRYPOINT(glDrawElementsInstancedBaseVertex)(mode, count, type, pIndices, primcount, basevertex);
6852             }
6853
6854             break;
6855         }
6856         case VOGL_ENTRYPOINT_glMultiDrawArrays:
6857         case VOGL_ENTRYPOINT_glMultiDrawArraysEXT:
6858         {
6859             GLenum mode = trace_packet.get_param_value<GLenum>(0);
6860
6861             const GLint *pFirst = trace_packet.get_param_client_memory<const GLint>(1);
6862             uint first_size = trace_packet.get_param_client_memory_data_size(1);
6863
6864             const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(2);
6865             uint count_size = trace_packet.get_param_client_memory_data_size(2);
6866
6867             GLsizei primcount = trace_packet.get_param_value<GLsizei>(3);
6868
6869             if ((first_size != primcount * sizeof(GLint)) || (count_size != primcount * sizeof(GLsizei)))
6870             {
6871                 process_entrypoint_error("%s: first and/or count params do not point to arrays of the expected size\n", VOGL_METHOD_NAME);
6872                 return cStatusSoftFailure;
6873             }
6874
6875             if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6876             {
6877                 //  Multi-draws with client side arrays are not supported for replay.
6878                 if (entrypoint_id == VOGL_ENTRYPOINT_glMultiDrawElements)
6879                     GL_ENTRYPOINT(glMultiDrawArrays)(mode, pFirst, pCount, primcount);
6880                 else
6881                     GL_ENTRYPOINT(glMultiDrawArraysEXT)(mode, pFirst, pCount, primcount);
6882             }
6883
6884             break;
6885         }
6886         case VOGL_ENTRYPOINT_glMultiDrawElements:
6887         case VOGL_ENTRYPOINT_glMultiDrawElementsEXT:
6888         {
6889             GLenum mode = trace_packet.get_param_value<GLenum>(0);
6890
6891             const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(1);
6892             uint count_size = trace_packet.get_param_client_memory_data_size(1);
6893
6894             GLenum type = trace_packet.get_param_value<GLenum>(2);
6895
6896             const vogl_client_memory_array trace_indices_void_ptr_array = trace_packet.get_param_client_memory_array(3); // const GLvoid *
6897
6898             GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6899
6900             if ((count_size != static_cast<uint>(primcount * sizeof(GLsizei))) || (trace_indices_void_ptr_array.size() != static_cast<uint>(primcount)))
6901             {
6902                 process_entrypoint_error("%s: count and/or indices params do not point to arrays of the expected size\n", VOGL_METHOD_NAME);
6903                 return cStatusSoftFailure;
6904             }
6905
6906             vogl::growable_array<GLvoid *, 256> replay_indices(trace_indices_void_ptr_array.size());
6907             for (uint i = 0; i < trace_indices_void_ptr_array.size(); i++)
6908                 replay_indices[i] = reinterpret_cast<GLvoid *>(trace_indices_void_ptr_array.get_element<vogl_trace_ptr_value>(i));
6909
6910             if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6911             {
6912                 //  Multi-draws with client side arrays are not supported for replay.
6913                 if (entrypoint_id == VOGL_ENTRYPOINT_glMultiDrawElements)
6914                     GL_ENTRYPOINT(glMultiDrawElements)(mode, pCount, type, replay_indices.get_ptr(), primcount);
6915                 else
6916                     GL_ENTRYPOINT(glMultiDrawElementsEXT)(mode, pCount, type, (const GLvoid **)replay_indices.get_ptr(), primcount);
6917             }
6918
6919             break;
6920         }
6921         case VOGL_ENTRYPOINT_glMultiDrawElementsBaseVertex:
6922         {
6923             GLenum mode = trace_packet.get_param_value<GLenum>(0);
6924
6925             const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(1);
6926             uint count_size = trace_packet.get_param_client_memory_data_size(1);
6927
6928             GLenum type = trace_packet.get_param_value<GLenum>(2);
6929
6930             const vogl_client_memory_array trace_indices_void_ptr_array = trace_packet.get_param_client_memory_array(3); // const GLvoid *
6931             //GLvoid * const *ppIndices = trace_packet.get_param_client_memory<GLvoid *>(3);
6932             //uint index_size = trace_packet.get_param_client_memory_data_size(3);
6933
6934             GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6935
6936             const GLint *pBase_vertex = trace_packet.get_param_client_memory<const GLint>(5);
6937             uint base_vertex_size = trace_packet.get_param_client_memory_data_size(5);
6938
6939             if ((count_size != primcount * sizeof(GLsizei)) ||
6940                 (trace_indices_void_ptr_array.size() != static_cast<uint>(primcount)) ||
6941                 (base_vertex_size != primcount * sizeof(GLint)))
6942             {
6943                 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);
6944                 return cStatusSoftFailure;
6945             }
6946
6947             vogl::growable_array<GLvoid *, 256> replay_indices(trace_indices_void_ptr_array.size());
6948             for (uint i = 0; i < trace_indices_void_ptr_array.size(); i++)
6949                 replay_indices[i] = reinterpret_cast<GLvoid *>(trace_indices_void_ptr_array.get_element<vogl_trace_ptr_value>(i));
6950
6951             if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6952             {
6953                 //  Multi-draws with client side arrays are not supported for replay.
6954                 GL_ENTRYPOINT(glMultiDrawElementsBaseVertex)(mode, pCount, type, replay_indices.get_ptr(), primcount, pBase_vertex);
6955             }
6956
6957             break;
6958         }
6959         case VOGL_ENTRYPOINT_glDrawElementsBaseVertex:
6960         {
6961             GLenum mode = trace_packet.get_param_value<GLenum>(0);
6962             GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6963             GLenum type = trace_packet.get_param_value<GLenum>(2);
6964             vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6965             GLint base_vertex = trace_packet.get_param_value<GLint>(4);
6966
6967             const GLvoid *pIndices;
6968             if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, base_vertex, false, true))
6969                 return cStatusSoftFailure;
6970
6971             if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6972             {
6973                 GL_ENTRYPOINT(glDrawElementsBaseVertex)(mode, count, type, pIndices, base_vertex);
6974             }
6975
6976             break;
6977         }
6978         case VOGL_ENTRYPOINT_glGetBufferSubData:
6979         {
6980             if (!benchmark_mode())
6981             {
6982                 GLenum target = trace_packet.get_param_value<GLenum>(0);
6983                 vogl_trace_ptr_value offset = trace_packet.get_param_ptr_value(1);
6984                 vogl_trace_ptr_value size = trace_packet.get_param_ptr_value(2);
6985                 GLvoid *pTrace_ptr = trace_packet.get_param_client_memory<GLvoid>(3);
6986
6987                 if (offset != static_cast<uintptr_t>(offset))
6988                 {
6989                     process_entrypoint_error("%s: offset parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, (uint64_t)offset);
6990                     return cStatusHardFailure;
6991                 }
6992
6993                 if ((size > cUINT32_MAX) || (size != static_cast<uintptr_t>(size)))
6994                 {
6995                     process_entrypoint_error("%s: size parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, (uint64_t)size);
6996                     return cStatusHardFailure;
6997                 }
6998
6999                 vogl::growable_array<uint8, 1024> buf(pTrace_ptr ? static_cast<uint>(size) : 0);
7000
7001                 GL_ENTRYPOINT(glGetBufferSubData)(target, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size), pTrace_ptr ? buf.get_ptr() : NULL);
7002
7003                 if ((buf.size()) && (pTrace_ptr))
7004                 {
7005                     if (memcmp(buf.get_ptr(), pTrace_ptr, static_cast<size_t>(size)) != 0)
7006                     {
7007                         process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
7008                     }
7009                 }
7010             }
7011
7012             break;
7013         }
7014         case VOGL_ENTRYPOINT_glGetClipPlane:
7015         {
7016             if (!benchmark_mode())
7017             {
7018                 GLenum plane = trace_packet.get_param_value<GLenum>(0);
7019                 const GLdouble *pTrace_equation = trace_packet.get_param_client_memory<GLdouble>(1);
7020
7021                 GLdouble equation[4];
7022                 GL_ENTRYPOINT(glGetClipPlane)(plane, pTrace_equation ? equation : NULL);
7023
7024                 if (pTrace_equation)
7025                 {
7026                     if (memcmp(equation, pTrace_equation, sizeof(GLdouble) * 4) != 0)
7027                     {
7028                         process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
7029                     }
7030                 }
7031             }
7032
7033             break;
7034         }
7035         case VOGL_ENTRYPOINT_glBufferData:
7036         case VOGL_ENTRYPOINT_glBufferDataARB:
7037         {
7038             GLenum target = trace_packet.get_param_value<GLenum>(0);
7039             vogl_trace_ptr_value size = trace_packet.get_param_value<vogl_trace_ptr_value>(1); // GLsizeiptrARB
7040             const GLvoid *data = trace_packet.get_param_client_memory_ptr(2);
7041             uint data_size = trace_packet.get_param_client_memory_data_size(2);
7042             GLenum usage = trace_packet.get_param_value<GLenum>(3);
7043
7044             if ((data) && (static_cast<vogl_trace_ptr_value>(data_size) < size))
7045             {
7046                 process_entrypoint_error("%s: trace's data array is too small\n", VOGL_METHOD_NAME);
7047                 return cStatusHardFailure;
7048             }
7049
7050             if (size != static_cast<uintptr_t>(size))
7051             {
7052                 process_entrypoint_error("%s: size parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(size));
7053                 return cStatusHardFailure;
7054             }
7055
7056             if (entrypoint_id == VOGL_ENTRYPOINT_glBufferData)
7057                 g_vogl_actual_gl_entrypoints.m_glBufferData(target, static_cast<GLsizeiptr>(size), data, usage);
7058             else
7059                 g_vogl_actual_gl_entrypoints.m_glBufferDataARB(target, static_cast<GLsizeiptrARB>(size), data, usage);
7060
7061             GLuint buffer = vogl_get_bound_gl_buffer(target);
7062             if (buffer)
7063             {
7064                 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7065
7066                 uint i;
7067                 for (i = 0; i < mapped_bufs.size(); i++)
7068                 {
7069                     if (mapped_bufs[i].m_buffer == buffer)
7070                     {
7071                         process_entrypoint_warning("%s: glBufferData() called on already mapped GL buffer %u, assuming GL will be unmapping it\n", VOGL_METHOD_NAME, buffer);
7072
7073                         mapped_bufs.erase_unordered(i);
7074                         break;
7075                     }
7076                 }
7077             }
7078
7079             break;
7080         }
7081         case VOGL_ENTRYPOINT_glMapBufferARB:
7082         case VOGL_ENTRYPOINT_glMapBuffer:
7083         {
7084             GLenum target = trace_packet.get_param_value<GLenum>(0);
7085             GLenum access = trace_packet.get_param_value<GLenum>(1);
7086             vogl_trace_ptr_value trace_result_ptr_value = trace_packet.get_return_ptr_value();
7087
7088             // FIXME - must call GL even if !pTrace_result
7089             if (trace_result_ptr_value)
7090             {
7091                 void *pMap;
7092                 if (entrypoint_id == VOGL_ENTRYPOINT_glMapBuffer)
7093                     pMap = GL_ENTRYPOINT(glMapBuffer)(target, access);
7094                 else
7095                     pMap = GL_ENTRYPOINT(glMapBufferARB)(target, access);
7096
7097                 if (!pMap)
7098                 {
7099                     process_entrypoint_error("%s: glMapBuffer succeeded during trace, but failed during replay!\n", VOGL_METHOD_NAME);
7100                     return cStatusHardFailure;
7101                 }
7102
7103                 GLuint buffer = vogl_get_bound_gl_buffer(target);
7104
7105                 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7106
7107                 uint i;
7108                 for (i = 0; i < mapped_bufs.size(); i++)
7109                 {
7110                     if (mapped_bufs[i].m_buffer == buffer)
7111                     {
7112                         process_entrypoint_error("%s: Buffer %u is already mapped\n", VOGL_METHOD_NAME, buffer);
7113                         return cStatusHardFailure;
7114                     }
7115                 }
7116
7117                 if (i == mapped_bufs.size())
7118                 {
7119                     GLint length = 0;
7120                     GL_ENTRYPOINT(glGetBufferParameteriv)(target, GL_BUFFER_SIZE, &length);
7121
7122                     vogl_mapped_buffer_desc m;
7123                     m.m_buffer = buffer;
7124                     m.m_target = target;
7125                     m.m_offset = 0;
7126                     m.m_length = length;
7127                     m.m_access = access;
7128                     m.m_range = false;
7129                     m.m_pPtr = pMap;
7130                     mapped_bufs.push_back(m);
7131                 }
7132             }
7133
7134             break;
7135         }
7136         case VOGL_ENTRYPOINT_glMapBufferRange:
7137         {
7138             GLenum target = trace_packet.get_param_value<GLenum>(0);
7139             vogl_trace_ptr_value offset = trace_packet.get_param_value<vogl_trace_ptr_value>(1); // GLintptr
7140             vogl_trace_ptr_value length = trace_packet.get_param_value<vogl_trace_ptr_value>(2); // GLsizeiptr
7141             GLbitfield access = trace_packet.get_param_value<GLbitfield>(3);
7142             vogl_trace_ptr_value trace_result_ptr_value = trace_packet.get_return_ptr_value();
7143
7144             if (offset != static_cast<uintptr_t>(offset))
7145             {
7146                 process_entrypoint_error("%s: offset parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(offset));
7147                 return cStatusHardFailure;
7148             }
7149             if (length != static_cast<uintptr_t>(length))
7150             {
7151                 process_entrypoint_error("%s: length parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(length));
7152                 return cStatusHardFailure;
7153             }
7154
7155             // FIXME - must call GL even if !pTrace_result
7156             if (trace_result_ptr_value)
7157             {
7158                 void *pMap = GL_ENTRYPOINT(glMapBufferRange)(target, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(length), access);
7159                 if (!pMap)
7160                 {
7161                     process_entrypoint_error("%s: glMapBufferRange succeeded during trace, but failed during replay!\n", VOGL_METHOD_NAME);
7162                     return cStatusHardFailure;
7163                 }
7164
7165                 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7166
7167                 GLuint buffer = vogl_get_bound_gl_buffer(target);
7168                 uint i;
7169                 for (i = 0; i < mapped_bufs.size(); i++)
7170                 {
7171                     if (mapped_bufs[i].m_buffer == buffer)
7172                     {
7173                         process_entrypoint_error("%s: Buffer %u is already mapped\n", VOGL_METHOD_NAME, buffer);
7174                         return cStatusHardFailure;
7175                     }
7176                 }
7177
7178                 if (i == mapped_bufs.size())
7179                 {
7180                     vogl_mapped_buffer_desc m;
7181                     m.m_buffer = buffer;
7182                     m.m_target = target;
7183                     m.m_offset = offset;
7184                     m.m_length = length;
7185                     m.m_access = access;
7186                     m.m_range = true;
7187                     m.m_pPtr = pMap;
7188                     mapped_bufs.push_back(m);
7189                 }
7190             }
7191
7192             break;
7193         }
7194         case VOGL_ENTRYPOINT_glFlushMappedBufferRange:
7195         {
7196             // vogltrace queues up the flushes, will process them while handling the glUnmapBuffer() call
7197             break;
7198         }
7199         case VOGL_ENTRYPOINT_glUnmapBufferARB:
7200         case VOGL_ENTRYPOINT_glUnmapBuffer:
7201         {
7202             GLenum target = trace_packet.get_param_value<GLenum>(0);
7203             GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7204
7205             GLuint buffer = vogl_get_bound_gl_buffer(target);
7206
7207             // FIXME - must call GL even if !buffer
7208             if (buffer)
7209             {
7210                 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7211
7212                 uint mapped_buffers_index;
7213                 for (mapped_buffers_index = 0; mapped_buffers_index < mapped_bufs.size(); mapped_buffers_index++)
7214                     if (mapped_bufs[mapped_buffers_index].m_buffer == buffer)
7215                         break;
7216                 if (mapped_buffers_index == mapped_bufs.size())
7217                 {
7218                     process_entrypoint_error("%s: Unable to find mapped buffer during unmap\n", VOGL_METHOD_NAME);
7219                     return cStatusHardFailure;
7220                 }
7221
7222                 vogl_mapped_buffer_desc &map_desc = mapped_bufs[mapped_buffers_index];
7223
7224                 bool writable_map = false;
7225                 bool explicit_bit = false;
7226                 if (map_desc.m_range)
7227                 {
7228                     writable_map = ((map_desc.m_access & GL_MAP_WRITE_BIT) != 0);
7229                     explicit_bit = (map_desc.m_access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0;
7230                 }
7231                 else
7232                 {
7233                     writable_map = (map_desc.m_access != GL_READ_ONLY);
7234                 }
7235
7236                 if (writable_map)
7237                 {
7238                     const key_value_map &unmap_data = trace_packet.get_key_value_map();
7239
7240                     if (explicit_bit)
7241                     {
7242                         int num_flushed_ranges = unmap_data.get_int(string_hash("flushed_ranges"));
7243
7244                         for (int i = 0; i < num_flushed_ranges; i++)
7245                         {
7246                             int64_t ofs = unmap_data.get_int64(i * 4 + 0);
7247                             int64_t size = unmap_data.get_int64(i * 4 + 1);
7248                             VOGL_NOTE_UNUSED(size);
7249                             const uint8_vec *pData = unmap_data.get_blob(i * 4 + 2);
7250                             if (!pData)
7251                             {
7252                                 process_entrypoint_error("%s: Failed finding flushed range data in key value map\n", VOGL_METHOD_NAME);
7253                                 return cStatusHardFailure;
7254                             }
7255
7256                             if (ofs != static_cast<GLintptr>(ofs))
7257                             {
7258                                 process_entrypoint_error("%s: Flush offset is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(ofs));
7259                                 return cStatusHardFailure;
7260                             }
7261
7262                             VOGL_ASSERT(size == pData->size());
7263
7264                             memcpy(static_cast<uint8 *>(map_desc.m_pPtr) + ofs, pData->get_ptr(), pData->size());
7265
7266                             GL_ENTRYPOINT(glFlushMappedBufferRange)(target, static_cast<GLintptr>(ofs), pData->size());
7267                         }
7268                     }
7269                     else
7270                     {
7271                         int64_t ofs = unmap_data.get_int64(0);
7272                         VOGL_NOTE_UNUSED(ofs);
7273                         int64_t size = unmap_data.get_int64(1);
7274                         VOGL_NOTE_UNUSED(size);
7275                         const uint8_vec *pData = unmap_data.get_blob(2);
7276                         if (!pData)
7277                         {
7278                             process_entrypoint_error("%s: Failed finding mapped data in key value map\n", VOGL_METHOD_NAME);
7279                             return cStatusHardFailure;
7280                         }
7281                         else
7282                         {
7283                             memcpy(map_desc.m_pPtr, pData->get_ptr(), pData->size());
7284                         }
7285                     }
7286                 }
7287
7288                 get_shared_state()->m_shadow_state.m_mapped_buffers.erase_unordered(mapped_buffers_index);
7289             }
7290
7291             GLboolean replay_result;
7292             if (entrypoint_id == VOGL_ENTRYPOINT_glUnmapBuffer)
7293                 replay_result = GL_ENTRYPOINT(glUnmapBuffer)(target);
7294             else
7295                 replay_result = GL_ENTRYPOINT(glUnmapBufferARB)(target);
7296
7297             if (trace_result != replay_result)
7298                 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);
7299
7300             break;
7301         }
7302         case VOGL_ENTRYPOINT_glGenVertexArrays:
7303         {
7304             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))
7305                 return cStatusHardFailure;
7306             break;
7307         }
7308         case VOGL_ENTRYPOINT_glBindVertexArray:
7309         {
7310             GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7311             GLuint replay_handle = map_handle(get_context_state()->m_vertex_array_objects, trace_handle);
7312
7313             GL_ENTRYPOINT(glBindVertexArray)(replay_handle);
7314             break;
7315         }
7316         case VOGL_ENTRYPOINT_glDeleteVertexArrays:
7317         {
7318             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));
7319             break;
7320         }
7321         case VOGL_ENTRYPOINT_glIsFramebuffer:
7322         case VOGL_ENTRYPOINT_glIsFramebufferEXT:
7323         {
7324             if (!benchmark_mode())
7325             {
7326                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7327                 GLuint replay_handle = map_handle(get_context_state()->m_framebuffers, trace_handle);
7328                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7329
7330                 GLboolean replay_result;
7331                 if (entrypoint_id == VOGL_ENTRYPOINT_glIsFramebuffer)
7332                     replay_result = GL_ENTRYPOINT(glIsFramebuffer)(replay_handle);
7333                 else
7334                     replay_result = GL_ENTRYPOINT(glIsFramebufferEXT)(replay_handle);
7335
7336                 if (trace_result != replay_result)
7337                     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));
7338             }
7339
7340             break;
7341         }
7342         case VOGL_ENTRYPOINT_glIsBuffer:
7343         {
7344             if (!benchmark_mode())
7345             {
7346                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7347                 GLuint replay_handle = map_handle(get_shared_state()->m_buffers, trace_handle);
7348                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7349
7350                 GLboolean replay_result = GL_ENTRYPOINT(glIsBuffer)(replay_handle);
7351                 if (trace_result != replay_result)
7352                     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));
7353             }
7354             break;
7355         }
7356         case VOGL_ENTRYPOINT_glIsEnabledi:
7357         {
7358             if (!benchmark_mode())
7359             {
7360                 GLenum cap = trace_packet.get_param_value<GLenum>(0);
7361                 GLuint index = trace_packet.get_param_value<GLuint>(1);
7362                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7363
7364                 GLboolean replay_result = GL_ENTRYPOINT(glIsEnabledi)(cap, index);
7365                 if (trace_result != replay_result)
7366                     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));
7367             }
7368             break;
7369         }
7370         case VOGL_ENTRYPOINT_glIsEnabled:
7371         {
7372             if (!benchmark_mode())
7373             {
7374                 GLenum cap = trace_packet.get_param_value<GLenum>(0);
7375                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7376
7377                 GLboolean replay_result = GL_ENTRYPOINT(glIsEnabled)(cap);
7378                 if (trace_result != replay_result)
7379                     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));
7380             }
7381             break;
7382         }
7383         case VOGL_ENTRYPOINT_glIsProgram:
7384         {
7385             if (!benchmark_mode())
7386             {
7387                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7388                 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
7389                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7390
7391                 GLboolean replay_result = GL_ENTRYPOINT(glIsProgram)(replay_handle);
7392
7393                 if (trace_result != replay_result)
7394                     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));
7395             }
7396             break;
7397         }
7398         case VOGL_ENTRYPOINT_glIsQuery:
7399         {
7400             if (!benchmark_mode())
7401             {
7402                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7403                 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
7404                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7405
7406                 GLboolean replay_result = GL_ENTRYPOINT(glIsQuery)(replay_handle);
7407                 if (trace_result != replay_result)
7408                     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));
7409             }
7410             break;
7411         }
7412         case VOGL_ENTRYPOINT_glIsShader:
7413         {
7414             if (!benchmark_mode())
7415             {
7416                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7417                 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
7418                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7419
7420                 GLboolean replay_result = GL_ENTRYPOINT(glIsShader)(replay_handle);
7421                 if (trace_result != replay_result)
7422                     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));
7423             }
7424             break;
7425         }
7426         case VOGL_ENTRYPOINT_glIsTexture:
7427         case VOGL_ENTRYPOINT_glIsTextureEXT:
7428         {
7429             if (!benchmark_mode())
7430             {
7431                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7432                 GLuint replay_handle = trace_handle;
7433                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7434
7435                 map_handle(get_shared_state()->m_shadow_state.m_textures, trace_handle, replay_handle);
7436
7437                 GLboolean replay_result;
7438                 if (entrypoint_id == VOGL_ENTRYPOINT_glIsTexture)
7439                     replay_result = GL_ENTRYPOINT(glIsTexture)(replay_handle);
7440                 else
7441                     replay_result = GL_ENTRYPOINT(glIsTextureEXT)(replay_handle);
7442
7443                 if (trace_result != replay_result)
7444                     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));
7445             }
7446
7447             break;
7448         }
7449         case VOGL_ENTRYPOINT_glIsVertexArray:
7450         {
7451             if (!benchmark_mode())
7452             {
7453                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7454                 GLuint replay_handle = map_handle(get_context_state()->m_vertex_array_objects, trace_handle);
7455                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7456
7457                 GLboolean replay_result = GL_ENTRYPOINT(glIsVertexArray)(replay_handle);
7458                 if (trace_result != replay_result)
7459                     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));
7460             }
7461
7462             break;
7463         }
7464         case VOGL_ENTRYPOINT_glReadPixels:
7465         {
7466 // TODO: This is causing huge stalls when replaying metro, not sure why. Also, the # of traced bytes is zero in metro.
7467 #if 0
7468                 if (!benchmark_mode())
7469                 {
7470             GLint x = trace_packet.get_param_value<GLint>(0);
7471             GLint y = trace_packet.get_param_value<GLint>(1);
7472             GLsizei width = trace_packet.get_param_value<GLsizei>(2);
7473             GLsizei height = trace_packet.get_param_value<GLsizei>(3);
7474             GLenum format = trace_packet.get_param_value<GLenum>(4);
7475             GLenum type = trace_packet.get_param_value<GLenum>(5);
7476             const GLvoid *trace_data = trace_packet.get_param_client_memory<const GLvoid>(6);
7477             uint trace_data_size = trace_packet.get_param_client_memory_data_size(6);
7478
7479                         size_t replay_data_size = vogl_get_image_size(format, type, width, height, 1);
7480                         if (replay_data_size != trace_data_size)
7481                         {
7482                                 process_entrypoint_warning("%s: Unexpected trace data size, got %u expected %" PRIu64 "\n", VOGL_METHOD_NAME, trace_data_size, (uint64_t)replay_data_size);
7483                         }
7484                         else if (!trace_data)
7485                         {
7486                                 process_entrypoint_warning("%s: Trace data is missing from packet\n", VOGL_METHOD_NAME);
7487                         }
7488
7489                         if (replay_data_size > cUINT32_MAX)
7490                         {
7491                                 process_entrypoint_error("%s: Replay data size is too large (%" PRIu64 ")!\n", VOGL_METHOD_NAME, (uint64_t)replay_data_size);
7492                                 return cStatusHardFailure;
7493                         }
7494
7495                         vogl::vector<uint8> data(static_cast<uint>(replay_data_size));
7496                         GL_ENTRYPOINT(glReadPixels)(x, y, width, height, format, type, data.get_ptr());
7497
7498                         if ((trace_data_size == replay_data_size) && (trace_data_size) && (trace_data))
7499                         {
7500                                 if (memcmp(data.get_ptr(), trace_data, trace_data_size) != 0)
7501                                 {
7502                                         process_entrypoint_error("%s: Replay's returned pixel data differed from trace's!\n", VOGL_METHOD_NAME);
7503                                 }
7504                         }
7505                 }
7506 #endif
7507             break;
7508         }
7509         case VOGL_ENTRYPOINT_glGetTexLevelParameterfv:
7510         {
7511             if (!benchmark_mode())
7512             {
7513                 GLenum target = trace_packet.get_param_value<GLenum>(0);
7514                 GLint level = trace_packet.get_param_value<GLint>(1);
7515                 GLenum pname = trace_packet.get_param_value<GLenum>(2);
7516                 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<const GLfloat>(3);
7517                 uint trace_params_size = trace_packet.get_param_client_memory_data_size(3);
7518
7519                 int n = g_gl_enums.get_pname_count(pname);
7520                 if (n <= 0)
7521                 {
7522                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7523                     return cStatusSoftFailure;
7524                 }
7525
7526                 vogl::growable_array<GLfloat, 17> replay_params(n + 1);
7527                 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
7528
7529                 GL_ENTRYPOINT(glGetTexLevelParameterfv)(target, level, pname, replay_params.get_ptr());
7530
7531                 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
7532
7533                 if (!pTrace_params)
7534                     process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7535                 else if (trace_params_size != sizeof(GLfloat) * n)
7536                     process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7537                 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLfloat) * n) != 0)
7538                     process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7539             }
7540
7541             break;
7542         }
7543         case VOGL_ENTRYPOINT_glGetTexLevelParameteriv:
7544         {
7545             if (!benchmark_mode())
7546             {
7547                 GLenum target = trace_packet.get_param_value<GLenum>(0);
7548                 GLint level = trace_packet.get_param_value<GLint>(1);
7549                 GLenum pname = trace_packet.get_param_value<GLenum>(2);
7550                 const GLint *pTrace_params = trace_packet.get_param_client_memory<const GLint>(3);
7551                 uint trace_params_size = trace_packet.get_param_client_memory_data_size(3);
7552
7553                 int n = g_gl_enums.get_pname_count(pname);
7554                 if (n <= 0)
7555                 {
7556                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7557                     return cStatusSoftFailure;
7558                 }
7559
7560                 vogl::growable_array<GLint, 16> replay_params(n + 1);
7561                 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7562
7563                 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, pname, replay_params.get_ptr());
7564
7565                 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7566
7567                 if (!pTrace_params)
7568                     process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7569                 else if (trace_params_size != sizeof(GLint) * n)
7570                     process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7571                 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLint) * n) != 0)
7572                     process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7573             }
7574
7575             break;
7576         }
7577         case VOGL_ENTRYPOINT_glGetTexParameterIiv:
7578         case VOGL_ENTRYPOINT_glGetTexParameteriv:
7579         {
7580             if (!benchmark_mode())
7581             {
7582                 GLenum target = trace_packet.get_param_value<GLenum>(0);
7583                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7584                 const GLint *pTrace_params = trace_packet.get_param_client_memory<const GLint>(2);
7585                 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7586
7587                 int n = g_gl_enums.get_pname_count(pname);
7588                 if (n <= 0)
7589                 {
7590                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7591                     return cStatusSoftFailure;
7592                 }
7593
7594                 vogl::growable_array<GLint, 16> replay_params(n + 1);
7595                 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7596
7597                 if (entrypoint_id == VOGL_ENTRYPOINT_glGetTexParameterIiv)
7598                     GL_ENTRYPOINT(glGetTexParameterIiv)(target, pname, replay_params.get_ptr());
7599                 else
7600                     GL_ENTRYPOINT(glGetTexParameteriv)(target, pname, replay_params.get_ptr());
7601
7602                 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7603
7604                 if (!pTrace_params)
7605                     process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7606                 else if (trace_params_size != sizeof(GLint) * n)
7607                     process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7608                 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLint) * n) != 0)
7609                     process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7610             }
7611
7612             break;
7613         }
7614         case VOGL_ENTRYPOINT_glGetTexParameterIuiv:
7615         {
7616             if (!benchmark_mode())
7617             {
7618                 GLenum target = trace_packet.get_param_value<GLenum>(0);
7619                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7620                 const GLuint *pTrace_params = trace_packet.get_param_client_memory<const GLuint>(2);
7621                 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7622
7623                 int n = g_gl_enums.get_pname_count(pname);
7624                 if (n <= 0)
7625                 {
7626                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7627                     return cStatusSoftFailure;
7628                 }
7629
7630                 vogl::growable_array<GLuint, 16> replay_params(n + 1);
7631                 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7632
7633                 GL_ENTRYPOINT(glGetTexParameterIuiv)(target, pname, replay_params.get_ptr());
7634
7635                 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7636
7637                 if (!pTrace_params)
7638                     process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7639                 else if (trace_params_size != sizeof(GLuint) * n)
7640                     process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7641                 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLuint) * n) != 0)
7642                     process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7643             }
7644
7645             break;
7646         }
7647         case VOGL_ENTRYPOINT_glGetTexParameterfv:
7648         {
7649             if (!benchmark_mode())
7650             {
7651                 GLenum target = trace_packet.get_param_value<GLenum>(0);
7652                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7653                 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<const GLfloat>(2);
7654                 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7655
7656                 int n = g_gl_enums.get_pname_count(pname);
7657                 if (n <= 0)
7658                 {
7659                     process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7660                     return cStatusSoftFailure;
7661                 }
7662
7663                 vogl::growable_array<GLfloat, 17> replay_params(n + 1);
7664                 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
7665
7666                 GL_ENTRYPOINT(glGetTexParameterfv)(target, pname, replay_params.get_ptr());
7667
7668                 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
7669
7670                 if (!pTrace_params)
7671                     process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7672                 else if (trace_params_size != sizeof(GLfloat) * n)
7673                     process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7674                 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLfloat) * n) != 0)
7675                     process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7676             }
7677
7678             break;
7679         }
7680
7681         case VOGL_ENTRYPOINT_glGetVertexAttribdv:
7682         {
7683             status = get_vertex_attrib_helper<GLdouble>(GL_ENTRYPOINT(glGetVertexAttribdv));
7684             if (status != cStatusOK)
7685                 return status;
7686             break;
7687         }
7688         case VOGL_ENTRYPOINT_glGetVertexAttribfv:
7689         {
7690             status = get_vertex_attrib_helper<GLfloat>(GL_ENTRYPOINT(glGetVertexAttribfv));
7691             if (status != cStatusOK)
7692                 return status;
7693             break;
7694         }
7695         case VOGL_ENTRYPOINT_glGetVertexAttribiv:
7696         {
7697             status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribiv));
7698             if (status != cStatusOK)
7699                 return status;
7700             break;
7701         }
7702         case VOGL_ENTRYPOINT_glGetVertexAttribIiv:
7703         {
7704             status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribIiv));
7705             if (status != cStatusOK)
7706                 return status;
7707             break;
7708         }
7709         case VOGL_ENTRYPOINT_glGetVertexAttribIivEXT:
7710         {
7711             status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribIivEXT));
7712             if (status != cStatusOK)
7713                 return status;
7714             break;
7715         }
7716         case VOGL_ENTRYPOINT_glGetVertexAttribIuiv:
7717         {
7718             status = get_vertex_attrib_helper<GLuint>(GL_ENTRYPOINT(glGetVertexAttribIuiv));
7719             if (status != cStatusOK)
7720                 return status;
7721             break;
7722         }
7723         case VOGL_ENTRYPOINT_glGetVertexAttribIuivEXT:
7724         {
7725             status = get_vertex_attrib_helper<GLuint>(GL_ENTRYPOINT(glGetVertexAttribIuivEXT));
7726             if (status != cStatusOK)
7727                 return status;
7728             break;
7729         }
7730         case VOGL_ENTRYPOINT_glGenLists:
7731         {
7732             GLsizei range = trace_packet.get_param_value<GLsizei>(0);
7733             GLuint trace_base_handle = trace_packet.get_return_value<GLuint>();
7734
7735             if (trace_base_handle)
7736             {
7737                 check_gl_error();
7738
7739                 GLuint replay_base_handle = GL_ENTRYPOINT(glGenLists)(range);
7740
7741                 if ((check_gl_error()) || (!replay_base_handle))
7742                 {
7743                     process_entrypoint_error("%s: glGenLists() succeeded in the trace, but failed during replay!\n", VOGL_METHOD_NAME);
7744                     return cStatusHardFailure;
7745                 }
7746
7747                 for (GLsizei i = 0; i < range; i++)
7748                 {
7749                     GLuint trace_handle = trace_base_handle + i;
7750                     GLuint replay_handle = replay_base_handle + i;
7751
7752                     if (!gen_handle(get_shared_state()->m_lists, trace_handle, replay_handle))
7753                         return cStatusHardFailure;
7754
7755                     if (!get_shared_state()->m_shadow_state.m_display_lists.gen_lists(trace_handle, 1, &replay_handle))
7756                     {
7757                         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);
7758                     }
7759                 }
7760             }
7761             else
7762             {
7763                 GLuint replay_base_handle = GL_ENTRYPOINT(glGenLists)(range);
7764                 if (replay_base_handle)
7765                 {
7766                     process_entrypoint_warning("%s: glGenLists() failed in the trace, but succeeded during replay!\n", VOGL_METHOD_NAME);
7767
7768                     GL_ENTRYPOINT(glDeleteLists)(replay_base_handle, range);
7769                 }
7770             }
7771
7772             break;
7773         }
7774         case VOGL_ENTRYPOINT_glCallList:
7775         {
7776             GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7777             GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7778
7779             GL_ENTRYPOINT(glCallList)(replay_handle);
7780
7781             if (!get_shared_state()->m_shadow_state.m_display_lists.parse_list_and_update_shadows(trace_handle, display_list_bind_callback, this))
7782             {
7783                 process_entrypoint_warning("%s: Failed processing display list shadow for trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
7784             }
7785
7786             if ((status = post_draw_call()) != cStatusOK)
7787                 return status;
7788
7789             break;
7790         }
7791         case VOGL_ENTRYPOINT_glCallLists:
7792         {
7793             GLsizei n = trace_packet.get_param_value<GLsizei>(0);
7794             GLenum type = trace_packet.get_param_value<GLenum>(1);
7795             const GLvoid *pTrace_lists = trace_packet.get_param_client_memory<const GLvoid>(2);
7796             uint trace_lists_size = trace_packet.get_param_client_memory_data_size(2);
7797
7798             uint type_size = vogl_get_gl_type_size(type);
7799             if (!type_size)
7800             {
7801                 process_entrypoint_error("%s: Unable to execute glCallLists, type is invalid\n", VOGL_METHOD_NAME);
7802                 return cStatusSoftFailure;
7803             }
7804
7805             if ((n) && (!pTrace_lists))
7806             {
7807                 process_entrypoint_error("%s: Unable to execute glCallLists, lists param is NULL\n", VOGL_METHOD_NAME);
7808                 return cStatusSoftFailure;
7809             }
7810
7811             if (trace_lists_size < (type_size * n))
7812             {
7813                 process_entrypoint_error("%s: Unable to execute glCallLists, lists param data size is too small in trace\n", VOGL_METHOD_NAME);
7814                 return cStatusSoftFailure;
7815             }
7816
7817             GLuint list_base = 0;
7818             GL_ENTRYPOINT(glGetIntegerv)(GL_LIST_BASE, reinterpret_cast<GLint *>(&list_base));
7819
7820             const uint8 *pTrace_lists_ptr = static_cast<const uint8 *>(pTrace_lists);
7821             for (GLsizei i = 0; i < n; i++)
7822             {
7823                 GLint trace_handle = list_base;
7824                 switch (type)
7825                 {
7826                     case GL_BYTE:
7827                     {
7828                         trace_handle += *reinterpret_cast<const signed char *>(pTrace_lists_ptr);
7829                         pTrace_lists_ptr++;
7830                         break;
7831                     }
7832                     case GL_UNSIGNED_BYTE:
7833                     {
7834                         trace_handle += *pTrace_lists_ptr;
7835                         pTrace_lists_ptr++;
7836                         break;
7837                     }
7838                     case GL_SHORT:
7839                     {
7840                         trace_handle += *reinterpret_cast<const int16 *>(pTrace_lists_ptr);
7841                         pTrace_lists_ptr += sizeof(int16);
7842                         break;
7843                     }
7844                     case GL_UNSIGNED_SHORT:
7845                     {
7846                         trace_handle += *reinterpret_cast<const uint16 *>(pTrace_lists_ptr);
7847                         pTrace_lists_ptr += sizeof(uint16);
7848                         break;
7849                     }
7850                     case GL_INT:
7851                     {
7852                         trace_handle += *reinterpret_cast<const int32 *>(pTrace_lists_ptr);
7853                         pTrace_lists_ptr += sizeof(int32);
7854                         break;
7855                     }
7856                     case GL_UNSIGNED_INT:
7857                     {
7858                         trace_handle += *reinterpret_cast<const uint32 *>(pTrace_lists_ptr);
7859                         pTrace_lists_ptr += sizeof(uint32);
7860                         break;
7861                     }
7862                     case GL_FLOAT:
7863                     {
7864                         trace_handle += static_cast<GLint>(*reinterpret_cast<const float *>(pTrace_lists_ptr));
7865                         pTrace_lists_ptr += sizeof(float);
7866                         break;
7867                     }
7868                     case GL_2_BYTES:
7869                     {
7870                         trace_handle += ((pTrace_lists_ptr[0] << 8U) + pTrace_lists_ptr[1]);
7871                         pTrace_lists_ptr += 2;
7872                         break;
7873                     }
7874                     case GL_3_BYTES:
7875                     {
7876                         trace_handle += ((pTrace_lists_ptr[0] << 16U) + (pTrace_lists_ptr[1] << 8U) + pTrace_lists_ptr[2]);
7877                         pTrace_lists_ptr += 3;
7878                         break;
7879                     }
7880                     case GL_4_BYTES:
7881                     {
7882                         trace_handle += ((pTrace_lists_ptr[0] << 24U) + (pTrace_lists_ptr[1] << 16U) + (pTrace_lists_ptr[2] << 8U) + pTrace_lists_ptr[3]);
7883                         pTrace_lists_ptr += 4;
7884                         break;
7885                     }
7886                     default:
7887                     {
7888                         process_entrypoint_error("%s: Invalid type parameter (0x%08X)\n", VOGL_METHOD_NAME, type);
7889                         return cStatusSoftFailure;
7890                     }
7891                 }
7892
7893                 if (trace_handle <= 0)
7894                 {
7895                     process_entrypoint_error("%s: Trace handle after adding list base is negative (%i), skipping this list index\n", VOGL_METHOD_NAME, trace_handle);
7896                 }
7897                 else
7898                 {
7899                     GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7900                     GL_ENTRYPOINT(glCallList)(replay_handle);
7901
7902                     if (!get_shared_state()->m_shadow_state.m_display_lists.parse_list_and_update_shadows(trace_handle, display_list_bind_callback, this))
7903                     {
7904                         process_entrypoint_warning("%s: Failed processing display list shadow for trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
7905                     }
7906                 }
7907             }
7908
7909             if ((status = post_draw_call()) != cStatusOK)
7910                 return status;
7911
7912             break;
7913         }
7914         case VOGL_ENTRYPOINT_glDeleteLists:
7915         {
7916             GLuint trace_list = trace_packet.get_param_value<GLuint>(0);
7917             GLsizei range = trace_packet.get_param_value<GLsizei>(1);
7918
7919             for (GLsizei i = 0; i < range; i++)
7920             {
7921                 GLuint trace_handle = trace_list + i;
7922                 delete_handles(get_shared_state()->m_lists, 1, &trace_handle, delete_list_helper);
7923
7924                 if (!get_shared_state()->m_shadow_state.m_display_lists.del_lists(trace_handle, 1))
7925                 {
7926                     process_entrypoint_warning("%s: Unable to delete list in display list shadow, trace handle %u\n", VOGL_METHOD_NAME, trace_handle);
7927                 }
7928             }
7929
7930             break;
7931         }
7932         case VOGL_ENTRYPOINT_glIsList:
7933         {
7934             if (!benchmark_mode())
7935             {
7936                 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7937                 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7938                 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7939
7940                 GLboolean replay_result = GL_ENTRYPOINT(glIsList)(replay_handle);
7941                 if (trace_result != replay_result)
7942                     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));
7943             }
7944
7945             break;
7946         }
7947         case VOGL_ENTRYPOINT_glNewList:
7948         {
7949             GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7950             GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7951             GLenum mode = trace_packet.get_param_value<GLenum>(1);
7952
7953             check_gl_error();
7954
7955             GL_ENTRYPOINT(glNewList)(replay_handle, mode);
7956
7957             if (!check_gl_error())
7958             {
7959                 get_shared_state()->m_shadow_state.m_display_lists.new_list(trace_handle, replay_handle);
7960
7961                 get_context_state()->m_current_display_list_mode = mode;
7962                 get_context_state()->m_current_display_list_handle = trace_handle;
7963             }
7964
7965             // TODO: Check if glNewList() failed vs the replay.
7966             // This is important, because if the new failed during tracing but succeeded during replay then we've seriously diverged.
7967             // 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.
7968             break;
7969         }
7970         case VOGL_ENTRYPOINT_glListBase:
7971         {
7972             GLuint base = trace_packet.get_param_value<GLuint>(0);
7973             GL_ENTRYPOINT(glListBase)(base);
7974             break;
7975         }
7976         case VOGL_ENTRYPOINT_glEndList:
7977         {
7978             GL_ENTRYPOINT(glEndList)();
7979
7980             if (!get_context_state()->is_composing_display_list())
7981             {
7982                 process_entrypoint_warning("%s: glEndList() called without calling glNewList()!\n", VOGL_METHOD_NAME);
7983             }
7984             else
7985             {
7986                 if (!get_shared_state()->m_shadow_state.m_display_lists.end_list(get_context_state()->m_current_display_list_handle))
7987                     process_entrypoint_warning("%s: Failed ending display list, trace handle %u\n", VOGL_METHOD_NAME, get_context_state()->m_current_display_list_handle);
7988
7989                 get_context_state()->m_current_display_list_mode = GL_NONE;
7990                 get_context_state()->m_current_display_list_handle = -1;
7991             }
7992
7993             break;
7994         }
7995         case VOGL_ENTRYPOINT_glFeedbackBuffer:
7996         {
7997             GLsizei size = trace_packet.get_param_value<GLsizei>(0);
7998             GLenum type = trace_packet.get_param_value<GLenum>(1);
7999
8000             if (static_cast<GLsizei>(m_pCur_context_state->m_feedback_buffer.size()) < size)
8001                 m_pCur_context_state->m_feedback_buffer.resize(size);
8002
8003             GL_ENTRYPOINT(glFeedbackBuffer)(size, type, m_pCur_context_state->m_feedback_buffer.get_ptr());
8004
8005             break;
8006         }
8007         case VOGL_ENTRYPOINT_glSeparableFilter2D:
8008         {
8009             GLenum target = trace_packet.get_param_value<GLenum>(0);
8010             GLenum internalformat = trace_packet.get_param_value<GLenum>(1);
8011             GLsizei width = trace_packet.get_param_value<GLsizei>(2);
8012             GLsizei height = trace_packet.get_param_value<GLsizei>(3);
8013             GLenum format = trace_packet.get_param_value<GLenum>(4);
8014             GLenum type = trace_packet.get_param_value<GLenum>(5);
8015
8016             const GLvoid *row = trace_packet.get_param_client_memory<const GLvoid>(6);
8017             uint row_size = trace_packet.get_param_client_memory_data_size(6);
8018             if (row_size < vogl_get_image_size(format, type, width, 1, 1))
8019             {
8020                 process_entrypoint_error("%s: row trace array is too small\n", VOGL_METHOD_NAME);
8021                 return cStatusSoftFailure;
8022             }
8023
8024             const GLvoid *column = trace_packet.get_param_client_memory<const GLvoid>(7);
8025             uint col_size = trace_packet.get_param_client_memory_data_size(7);
8026             if (col_size < vogl_get_image_size(format, type, width, 1, 1))
8027             {
8028                 process_entrypoint_error("%s: column trace array is too small\n", VOGL_METHOD_NAME);
8029                 return cStatusSoftFailure;
8030             }
8031
8032             GL_ENTRYPOINT(glSeparableFilter2D)(target, internalformat, width, height, format, type, row, column);
8033             break;
8034         }
8035
8036         case VOGL_ENTRYPOINT_glNamedProgramLocalParameters4fvEXT:
8037         {
8038             GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8039             GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8040
8041             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));
8042             break;
8043         }
8044
8045         case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4iEXT:
8046         {
8047             GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8048             GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8049
8050             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));
8051             break;
8052         }
8053         case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4ivEXT:
8054         {
8055             GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8056             GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8057
8058             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));
8059             break;
8060         }
8061
8062         case VOGL_ENTRYPOINT_glNamedProgramLocalParametersI4ivEXT:
8063         {
8064             GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8065             GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8066
8067             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));
8068             break;
8069         }
8070         case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4uiEXT:
8071         {
8072             GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8073             GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8074
8075             GL_ENTRYPOINT(glNamedProgramLocalParameterI4uiEXT)(replay_program, trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLuint>(2),
8076                                                                trace_packet.get_param_value<GLuint>(3), trace_packet.get_param_value<GLuint>(4),
8077                                                                trace_packet.get_param_value<GLuint>(5), trace_packet.get_param_value<GLuint>(6));
8078             break;
8079         }
8080         case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4uivEXT:
8081         {
8082             GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8083             GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8084
8085             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));
8086             break;
8087         }
8088         case VOGL_ENTRYPOINT_glNamedProgramLocalParametersI4uivEXT:
8089         {
8090             GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8091             GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8092
8093             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));
8094             break;
8095         }
8096         case VOGL_ENTRYPOINT_glNamedProgramLocalParameter4fvEXT:
8097         {
8098             GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8099             GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8100
8101             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));
8102             break;
8103         }
8104         case VOGL_ENTRYPOINT_glGetTexEnvfv:
8105         {
8106             if (!benchmark_mode())
8107             {
8108                 GLenum target = trace_packet.get_param_value<GLenum>(0);
8109                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8110                 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8111
8112                 GLfloat vals[4] = { 0, 0, 0, 0 };
8113
8114                 int n = g_gl_enums.get_pname_count(pname);
8115                 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8116
8117                 GL_ENTRYPOINT(glGetTexEnvfv)(target, pname, vals);
8118
8119                 if (n < 0)
8120                 {
8121                     process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8122                 }
8123                 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8124                 {
8125                     process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8126                 }
8127             }
8128
8129             break;
8130         }
8131         case VOGL_ENTRYPOINT_glGetTexEnviv:
8132         {
8133             if (!benchmark_mode())
8134             {
8135                 GLenum target = trace_packet.get_param_value<GLenum>(0);
8136                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8137                 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8138
8139                 GLint vals[4] = { 0, 0, 0, 0 };
8140
8141                 int n = g_gl_enums.get_pname_count(pname);
8142                 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8143
8144                 GL_ENTRYPOINT(glGetTexEnviv)(target, pname, vals);
8145
8146                 if (n < 0)
8147                 {
8148                     process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8149                 }
8150                 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8151                 {
8152                     process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8153                 }
8154             }
8155
8156             break;
8157         }
8158         case VOGL_ENTRYPOINT_glGetTexGendv:
8159         {
8160             if (!benchmark_mode())
8161             {
8162                 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8163                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8164                 const GLdouble *pParams = trace_packet.get_param_client_memory<GLdouble>(2);
8165
8166                 GLdouble vals[4] = { 0, 0, 0, 0 };
8167
8168                 int n = g_gl_enums.get_pname_count(pname);
8169                 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8170
8171                 GL_ENTRYPOINT(glGetTexGendv)(coord, pname, vals);
8172
8173                 if (n < 0)
8174                 {
8175                     process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8176                 }
8177                 else if (memcmp(pParams, vals, n * sizeof(GLdouble)) != 0)
8178                 {
8179                     process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8180                 }
8181             }
8182
8183             break;
8184         }
8185         case VOGL_ENTRYPOINT_glGetTexGenfv:
8186         {
8187             if (!benchmark_mode())
8188             {
8189                 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8190                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8191                 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8192
8193                 GLfloat vals[4] = { 0, 0, 0, 0 };
8194
8195                 int n = g_gl_enums.get_pname_count(pname);
8196                 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8197
8198                 GL_ENTRYPOINT(glGetTexGenfv)(coord, pname, vals);
8199
8200                 if (n < 0)
8201                 {
8202                     process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8203                 }
8204                 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8205                 {
8206                     process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8207                 }
8208             }
8209
8210             break;
8211         }
8212         case VOGL_ENTRYPOINT_glGetTexGeniv:
8213         {
8214             if (!benchmark_mode())
8215             {
8216                 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8217                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8218                 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8219
8220                 GLint vals[4] = { 0, 0, 0, 0 };
8221
8222                 int n = g_gl_enums.get_pname_count(pname);
8223                 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8224
8225                 GL_ENTRYPOINT(glGetTexGeniv)(coord, pname, vals);
8226
8227                 if (n < 0)
8228                 {
8229                     process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8230                 }
8231                 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8232                 {
8233                     process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8234                 }
8235             }
8236
8237             break;
8238         }
8239         case VOGL_ENTRYPOINT_glGetLightfv:
8240         {
8241             if (!benchmark_mode())
8242             {
8243                 GLenum light = trace_packet.get_param_value<GLenum>(0);
8244                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8245                 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8246
8247                 GLfloat vals[4] = { 0, 0, 0, 0 };
8248
8249                 int n = g_gl_enums.get_pname_count(pname);
8250                 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8251
8252                 GL_ENTRYPOINT(glGetLightfv)(light, pname, vals);
8253
8254                 if (n < 0)
8255                 {
8256                     process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8257                 }
8258                 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8259                 {
8260                     process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8261                 }
8262             }
8263
8264             break;
8265         }
8266         case VOGL_ENTRYPOINT_glGetLightiv:
8267         {
8268             if (!benchmark_mode())
8269             {
8270                 GLenum light = trace_packet.get_param_value<GLenum>(0);
8271                 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8272                 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8273
8274                 GLint vals[4] = { 0, 0, 0, 0 };
8275
8276                 int n = g_gl_enums.get_pname_count(pname);
8277                 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8278
8279                 GL_ENTRYPOINT(glGetLightiv)(light, pname, vals);
8280
8281                 if (n < 0)
8282                 {
8283                     process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8284                 }
8285                 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8286                 {
8287                     process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8288                 }
8289             }
8290
8291             break;
8292         }
8293         case VOGL_ENTRYPOINT_glSelectBuffer:
8294         {
8295             GLsizei size = trace_packet.get_param_value<GLsizei>(0);
8296
8297             if (m_pCur_context_state->m_select_buffer.try_resize(size))
8298             {
8299                 GL_ENTRYPOINT(glSelectBuffer)(size, m_pCur_context_state->m_select_buffer.get_ptr());
8300             }
8301             else
8302             {
8303                 process_entrypoint_error("%s: Failed resizing context's select buffer\n", VOGL_METHOD_NAME);
8304             }
8305
8306             break;
8307         }
8308         case VOGL_ENTRYPOINT_glClearBufferfv:
8309         {
8310             VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferfv;
8311
8312             // TODO: Check params
8313
8314             VOGL_REPLAY_CALL_GL_HELPER_glClearBufferfv;
8315
8316             break;
8317         }
8318         case VOGL_ENTRYPOINT_glClearBufferiv:
8319         {
8320             VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferiv;
8321
8322             // TODO: Check params
8323
8324             VOGL_REPLAY_CALL_GL_HELPER_glClearBufferiv;
8325
8326             break;
8327         }
8328         case VOGL_ENTRYPOINT_glClearBufferuiv:
8329         {
8330             VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferuiv;
8331
8332             // TODO: Check params
8333
8334             VOGL_REPLAY_CALL_GL_HELPER_glClearBufferuiv;
8335
8336             break;
8337         }
8338         case VOGL_ENTRYPOINT_glTexBuffer:
8339         case VOGL_ENTRYPOINT_glTexBufferARB:
8340         case VOGL_ENTRYPOINT_glTexBufferEXT:
8341         {
8342             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexBuffer;
8343
8344             buffer = map_handle(get_shared_state()->m_buffers, buffer);
8345
8346             SWITCH_GL_ENTRYPOINT3_VOID(glTexBuffer, glTexBufferARB, glTexBufferEXT, target, internalformat, buffer);
8347             break;
8348         }
8349         case VOGL_ENTRYPOINT_glBeginConditionalRender:
8350         {
8351             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBeginConditionalRender;
8352
8353             id = map_handle(get_shared_state()->m_queries, id);
8354
8355             VOGL_REPLAY_CALL_GL_HELPER_glBeginConditionalRender;
8356             break;
8357         }
8358         case VOGL_ENTRYPOINT_glEndConditionalRender:
8359         {
8360             VOGL_REPLAY_LOAD_PARAMS_HELPER_glEndConditionalRender;
8361
8362             VOGL_REPLAY_CALL_GL_HELPER_glEndConditionalRender;
8363             break;
8364         }
8365         case VOGL_ENTRYPOINT_glBeginTransformFeedback:
8366         {
8367             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBeginTransformFeedback;
8368
8369             VOGL_REPLAY_CALL_GL_HELPER_glBeginTransformFeedback;
8370             break;
8371         }
8372         case VOGL_ENTRYPOINT_glEndTransformFeedback:
8373         {
8374             VOGL_REPLAY_LOAD_PARAMS_HELPER_glEndTransformFeedback;
8375
8376             VOGL_REPLAY_CALL_GL_HELPER_glEndTransformFeedback;
8377
8378             break;
8379         }
8380         case VOGL_ENTRYPOINT_glTransformFeedbackVaryings:
8381         {
8382             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTransformFeedbackVaryings;
8383             VOGL_NOTE_UNUSED(pTrace_varyings);
8384
8385             program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8386
8387             dynamic_string_array replay_varyings(count);
8388
8389             const key_value_map &key_value_map = trace_packet.get_key_value_map();
8390             const value_to_value_hash_map &hash_map = key_value_map.get_map();
8391
8392             for (value_to_value_hash_map::const_iterator it = hash_map.begin(); it != hash_map.end(); ++it)
8393             {
8394                 int key_index = it->first.get_int();
8395
8396                 if ((key_index >= 0) && (key_index < count))
8397                 {
8398                     const dynamic_string *pName = it->second.get_string_ptr();
8399                     VOGL_ASSERT(pName);
8400
8401                     replay_varyings[key_index] = pName ? *pName : "";
8402                 }
8403                 else
8404                 {
8405                     VOGL_ASSERT_ALWAYS;
8406                 }
8407             }
8408
8409             vogl::vector<const GLchar *> str_ptrs(count);
8410             for (int i = 0; i < count; i++)
8411                 str_ptrs[i] = reinterpret_cast<const GLchar *>(replay_varyings[i].get_ptr());
8412
8413             GLchar *const *pReplay_varyings = (GLchar *const *)(str_ptrs.get_ptr());
8414
8415             VOGL_REPLAY_CALL_GL_HELPER_glTransformFeedbackVaryings;
8416
8417             break;
8418         }
8419         case VOGL_ENTRYPOINT_glUniformBufferEXT:
8420         {
8421             VOGL_REPLAY_LOAD_PARAMS_HELPER_glUniformBufferEXT;
8422
8423             GLuint trace_program = program;
8424
8425             program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8426             location = determine_uniform_replay_location(trace_program, location);
8427             buffer = map_handle(get_shared_state()->m_buffers, buffer);
8428
8429             VOGL_REPLAY_CALL_GL_HELPER_glUniformBufferEXT;
8430             break;
8431         }
8432         case VOGL_ENTRYPOINT_glUniformBlockBinding:
8433         {
8434             // TODO: Does any of this other stuff need to be remapped?
8435             VOGL_REPLAY_LOAD_PARAMS_HELPER_glUniformBlockBinding;
8436
8437             program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8438
8439             VOGL_REPLAY_CALL_GL_HELPER_glUniformBlockBinding;
8440             break;
8441         }
8442         case VOGL_ENTRYPOINT_glFrameTerminatorGREMEDY:
8443         {
8444             // TODO - we need to hook up this extension to the tracer
8445             break;
8446         }
8447         case VOGL_ENTRYPOINT_glStringMarkerGREMEDY:
8448         {
8449             // TODO - we need to hook up this extension to the tracer
8450             break;
8451         }
8452         case VOGL_ENTRYPOINT_glDebugMessageCallbackARB:
8453         case VOGL_ENTRYPOINT_glGetDebugMessageLogARB:
8454         case VOGL_ENTRYPOINT_glDebugMessageControlARB:
8455         case VOGL_ENTRYPOINT_glDebugMessageInsertARB:
8456         {
8457             // TODO
8458             break;
8459         }
8460         case VOGL_ENTRYPOINT_glBitmap:
8461         {
8462             VOGL_REPLAY_LOAD_PARAMS_HELPER_glBitmap;
8463
8464             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8465             {
8466                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8467                 pTrace_bitmap = (const GLubyte *)ptr_val;
8468             }
8469
8470             VOGL_REPLAY_CALL_GL_HELPER_glBitmap;
8471
8472             break;
8473         }
8474         case VOGL_ENTRYPOINT_glColorSubTable:
8475         {
8476             VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorSubTable;
8477
8478             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8479             {
8480                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8481                 pTrace_data = (const GLvoid *)ptr_val;
8482             }
8483
8484             VOGL_REPLAY_CALL_GL_HELPER_glColorSubTable;
8485
8486             break;
8487         }
8488         case VOGL_ENTRYPOINT_glColorSubTableEXT:
8489         {
8490             VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorSubTableEXT;
8491
8492             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8493             {
8494                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8495                 pTrace_data = (const GLvoid *)ptr_val;
8496             }
8497
8498             VOGL_REPLAY_CALL_GL_HELPER_glColorSubTableEXT;
8499
8500             break;
8501         }
8502         case VOGL_ENTRYPOINT_glColorTable:
8503         {
8504             VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorTable;
8505
8506             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8507             {
8508                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8509                 pTrace_table = (const GLvoid *)ptr_val;
8510             }
8511
8512             VOGL_REPLAY_CALL_GL_HELPER_glColorTable;
8513
8514             break;
8515         }
8516         case VOGL_ENTRYPOINT_glColorTableEXT:
8517         {
8518             VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorTableEXT;
8519
8520             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8521             {
8522                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8523                 pTrace_table = (const GLvoid *)ptr_val;
8524             }
8525
8526             VOGL_REPLAY_CALL_GL_HELPER_glColorTableEXT;
8527
8528             break;
8529         }
8530         case VOGL_ENTRYPOINT_glConvolutionFilter1D:
8531         {
8532             VOGL_REPLAY_LOAD_PARAMS_HELPER_glConvolutionFilter1D;
8533
8534             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8535             {
8536                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8537                 pTrace_image = (const GLvoid *)ptr_val;
8538             }
8539
8540             VOGL_REPLAY_CALL_GL_HELPER_glConvolutionFilter1D;
8541
8542             break;
8543         }
8544         case VOGL_ENTRYPOINT_glConvolutionFilter2D:
8545         {
8546             VOGL_REPLAY_LOAD_PARAMS_HELPER_glConvolutionFilter2D;
8547
8548             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8549             {
8550                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8551                 pTrace_image = (const GLvoid *)ptr_val;
8552             }
8553
8554             VOGL_REPLAY_CALL_GL_HELPER_glConvolutionFilter2D;
8555
8556             break;
8557         }
8558         case VOGL_ENTRYPOINT_glDrawPixels:
8559         {
8560             VOGL_REPLAY_LOAD_PARAMS_HELPER_glDrawPixels;
8561
8562             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8563             {
8564                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(4);
8565                 pTrace_pixels = (const GLvoid *)ptr_val;
8566             }
8567
8568             VOGL_REPLAY_CALL_GL_HELPER_glDrawPixels;
8569
8570             break;
8571         }
8572         case VOGL_ENTRYPOINT_glPolygonStipple:
8573         {
8574             VOGL_REPLAY_LOAD_PARAMS_HELPER_glPolygonStipple;
8575
8576             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8577             {
8578                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(0);
8579                 pTrace_mask = (const GLubyte *)ptr_val;
8580             }
8581
8582             VOGL_REPLAY_CALL_GL_HELPER_glPolygonStipple;
8583
8584             break;
8585         }
8586         case VOGL_ENTRYPOINT_glTexImage1D:
8587         {
8588             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage1D;
8589
8590             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8591             {
8592                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(7);
8593                 pTrace_pixels = (const GLvoid *)ptr_val;
8594             }
8595
8596             VOGL_REPLAY_CALL_GL_HELPER_glTexImage1D;
8597
8598             break;
8599         }
8600         case VOGL_ENTRYPOINT_glTexImage2D:
8601         {
8602             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage2D;
8603
8604             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8605             {
8606                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(8);
8607                 pTrace_pixels = (const GLvoid *)ptr_val;
8608             }
8609
8610             VOGL_REPLAY_CALL_GL_HELPER_glTexImage2D;
8611
8612             break;
8613         }
8614         case VOGL_ENTRYPOINT_glTexImage3D:
8615         {
8616             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage3D;
8617
8618             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8619             {
8620                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(9);
8621                 pTrace_pixels = (const GLvoid *)ptr_val;
8622             }
8623
8624             VOGL_REPLAY_CALL_GL_HELPER_glTexImage3D;
8625
8626             break;
8627         }
8628         case VOGL_ENTRYPOINT_glTexImage3DEXT:
8629         {
8630             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage3DEXT;
8631
8632             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8633             {
8634                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(9);
8635                 pTrace_pixels = (const GLvoid *)ptr_val;
8636             }
8637
8638             VOGL_REPLAY_CALL_GL_HELPER_glTexImage3DEXT;
8639
8640             break;
8641         }
8642         case VOGL_ENTRYPOINT_glTexSubImage1D:
8643         {
8644             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage1D;
8645
8646             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8647             {
8648                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8649                 pTrace_pixels = (const GLvoid *)ptr_val;
8650             }
8651
8652             VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage1D;
8653
8654             break;
8655         }
8656         case VOGL_ENTRYPOINT_glTexSubImage1DEXT:
8657         {
8658             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage1DEXT;
8659
8660             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8661             {
8662                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8663                 pTrace_pixels = (const GLvoid *)ptr_val;
8664             }
8665
8666             VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage1DEXT;
8667
8668             break;
8669         }
8670         case VOGL_ENTRYPOINT_glTexSubImage2D:
8671         {
8672             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage2D;
8673
8674             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8675             {
8676                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(8);
8677                 pTrace_pixels = (const GLvoid *)ptr_val;
8678             }
8679
8680             VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage2D;
8681
8682             break;
8683         }
8684         case VOGL_ENTRYPOINT_glTexSubImage2DEXT:
8685         {
8686             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage2DEXT;
8687
8688             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8689             {
8690                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(8);
8691                 pTrace_pixels = (const GLvoid *)ptr_val;
8692             }
8693
8694             VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage2DEXT;
8695
8696             break;
8697         }
8698         case VOGL_ENTRYPOINT_glTexSubImage3D:
8699         {
8700             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage3D;
8701
8702             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8703             {
8704                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(10);
8705                 pTrace_pixels = (const GLvoid *)ptr_val;
8706             }
8707
8708             VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage3D;
8709
8710             break;
8711         }
8712         case VOGL_ENTRYPOINT_glTexSubImage3DEXT:
8713         {
8714             VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage3DEXT;
8715
8716             if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8717             {
8718                 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(10);
8719                 pTrace_pixels = (const GLvoid *)ptr_val;
8720             }
8721
8722             VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage3DEXT;
8723
8724             break;
8725         }
8726         case VOGL_ENTRYPOINT_glAreTexturesResident:
8727         case VOGL_ENTRYPOINT_glAreTexturesResidentEXT:
8728         case VOGL_ENTRYPOINT_glGetActiveAtomicCounterBufferiv:
8729         case VOGL_ENTRYPOINT_glGetActiveAttribARB:
8730         case VOGL_ENTRYPOINT_glGetActiveSubroutineName:
8731         case VOGL_ENTRYPOINT_glGetActiveSubroutineUniformName:
8732         case VOGL_ENTRYPOINT_glGetActiveSubroutineUniformiv:
8733         case VOGL_ENTRYPOINT_glGetActiveUniformARB:
8734         case VOGL_ENTRYPOINT_glGetActiveUniformBlockName:
8735         case VOGL_ENTRYPOINT_glGetActiveUniformBlockiv:
8736         case VOGL_ENTRYPOINT_glGetActiveUniformName:
8737         case VOGL_ENTRYPOINT_glGetActiveUniformsiv:
8738         case VOGL_ENTRYPOINT_glGetActiveVaryingNV:
8739         case VOGL_ENTRYPOINT_glGetArrayObjectfvATI:
8740         case VOGL_ENTRYPOINT_glGetArrayObjectivATI:
8741         case VOGL_ENTRYPOINT_glGetAttachedObjectsARB:
8742         case VOGL_ENTRYPOINT_glGetAttribLocationARB:
8743         case VOGL_ENTRYPOINT_glGetBooleanIndexedvEXT:
8744         case VOGL_ENTRYPOINT_glGetBooleani_v:
8745         case VOGL_ENTRYPOINT_glGetBufferParameteri64v:
8746         case VOGL_ENTRYPOINT_glGetBufferParameterivARB:
8747         case VOGL_ENTRYPOINT_glGetBufferParameterui64vNV:
8748         case VOGL_ENTRYPOINT_glGetBufferPointervARB:
8749         case VOGL_ENTRYPOINT_glGetBufferSubDataARB:
8750         case VOGL_ENTRYPOINT_glGetClipPlanefOES:
8751         case VOGL_ENTRYPOINT_glGetClipPlanexOES:
8752         case VOGL_ENTRYPOINT_glGetColorTable:
8753         case VOGL_ENTRYPOINT_glGetColorTableEXT:
8754         case VOGL_ENTRYPOINT_glGetColorTableParameterfv:
8755         case VOGL_ENTRYPOINT_glGetColorTableParameterfvEXT:
8756         case VOGL_ENTRYPOINT_glGetColorTableParameterfvSGI:
8757         case VOGL_ENTRYPOINT_glGetColorTableParameteriv:
8758         case VOGL_ENTRYPOINT_glGetColorTableParameterivEXT:
8759         case VOGL_ENTRYPOINT_glGetColorTableParameterivSGI:
8760         case VOGL_ENTRYPOINT_glGetColorTableSGI:
8761         case VOGL_ENTRYPOINT_glGetCombinerInputParameterfvNV:
8762         case VOGL_ENTRYPOINT_glGetCombinerInputParameterivNV:
8763         case VOGL_ENTRYPOINT_glGetCombinerOutputParameterfvNV:
8764         case VOGL_ENTRYPOINT_glGetCombinerOutputParameterivNV:
8765         case VOGL_ENTRYPOINT_glGetCombinerStageParameterfvNV:
8766         case VOGL_ENTRYPOINT_glGetCompressedMultiTexImageEXT:
8767         case VOGL_ENTRYPOINT_glGetCompressedTexImage:
8768         case VOGL_ENTRYPOINT_glGetCompressedTexImageARB:
8769         case VOGL_ENTRYPOINT_glGetCompressedTextureImageEXT:
8770         case VOGL_ENTRYPOINT_glGetConvolutionFilter:
8771         case VOGL_ENTRYPOINT_glGetConvolutionFilterEXT:
8772         case VOGL_ENTRYPOINT_glGetConvolutionParameterfv:
8773         case VOGL_ENTRYPOINT_glGetConvolutionParameterfvEXT:
8774         case VOGL_ENTRYPOINT_glGetConvolutionParameteriv:
8775         case VOGL_ENTRYPOINT_glGetConvolutionParameterivEXT:
8776         case VOGL_ENTRYPOINT_glGetConvolutionParameterxvOES:
8777         case VOGL_ENTRYPOINT_glGetDebugMessageLog:
8778         case VOGL_ENTRYPOINT_glGetDebugMessageLogAMD:
8779         case VOGL_ENTRYPOINT_glGetDetailTexFuncSGIS:
8780         case VOGL_ENTRYPOINT_glGetDoubleIndexedvEXT:
8781         case VOGL_ENTRYPOINT_glGetDoublei_v:
8782         case VOGL_ENTRYPOINT_glGetFenceivNV:
8783         case VOGL_ENTRYPOINT_glGetFinalCombinerInputParameterfvNV:
8784         case VOGL_ENTRYPOINT_glGetFinalCombinerInputParameterivNV:
8785         case VOGL_ENTRYPOINT_glGetFixedvOES:
8786         case VOGL_ENTRYPOINT_glGetFloatIndexedvEXT:
8787         case VOGL_ENTRYPOINT_glGetFloati_v:
8788         case VOGL_ENTRYPOINT_glGetFogFuncSGIS:
8789         case VOGL_ENTRYPOINT_glGetFragDataIndex:
8790         case VOGL_ENTRYPOINT_glGetFragDataLocation:
8791         case VOGL_ENTRYPOINT_glGetFragDataLocationEXT:
8792         case VOGL_ENTRYPOINT_glGetFragmentLightfvSGIX:
8793         case VOGL_ENTRYPOINT_glGetFragmentLightivSGIX:
8794         case VOGL_ENTRYPOINT_glGetFragmentMaterialfvSGIX:
8795         case VOGL_ENTRYPOINT_glGetFragmentMaterialivSGIX:
8796         case VOGL_ENTRYPOINT_glGetFramebufferAttachmentParameteriv:
8797         case VOGL_ENTRYPOINT_glGetFramebufferAttachmentParameterivEXT:
8798         case VOGL_ENTRYPOINT_glGetFramebufferParameteriv:
8799         case VOGL_ENTRYPOINT_glGetFramebufferParameterivEXT:
8800         case VOGL_ENTRYPOINT_glGetGraphicsResetStatusARB:
8801         case VOGL_ENTRYPOINT_glGetHandleARB:
8802         case VOGL_ENTRYPOINT_glGetHistogram:
8803         case VOGL_ENTRYPOINT_glGetHistogramEXT:
8804         case VOGL_ENTRYPOINT_glGetHistogramParameterfv:
8805         case VOGL_ENTRYPOINT_glGetHistogramParameterfvEXT:
8806         case VOGL_ENTRYPOINT_glGetHistogramParameteriv:
8807         case VOGL_ENTRYPOINT_glGetHistogramParameterivEXT:
8808         case VOGL_ENTRYPOINT_glGetHistogramParameterxvOES:
8809         case VOGL_ENTRYPOINT_glGetImageHandleNV:
8810         case VOGL_ENTRYPOINT_glGetImageTransformParameterfvHP:
8811         case VOGL_ENTRYPOINT_glGetImageTransformParameterivHP:
8812         case VOGL_ENTRYPOINT_glGetInstrumentsSGIX:
8813         case VOGL_ENTRYPOINT_glGetInteger64i_v:
8814         case VOGL_ENTRYPOINT_glGetInteger64v:
8815         case VOGL_ENTRYPOINT_glGetIntegerIndexedvEXT:
8816         case VOGL_ENTRYPOINT_glGetIntegeri_v:
8817         case VOGL_ENTRYPOINT_glGetIntegerui64i_vNV:
8818         case VOGL_ENTRYPOINT_glGetIntegerui64vNV:
8819         case VOGL_ENTRYPOINT_glGetInternalformati64v:
8820         case VOGL_ENTRYPOINT_glGetInternalformativ:
8821         case VOGL_ENTRYPOINT_glGetInvariantBooleanvEXT:
8822         case VOGL_ENTRYPOINT_glGetInvariantFloatvEXT:
8823         case VOGL_ENTRYPOINT_glGetInvariantIntegervEXT:
8824         case VOGL_ENTRYPOINT_glGetLightxOES:
8825         case VOGL_ENTRYPOINT_glGetListParameterfvSGIX:
8826         case VOGL_ENTRYPOINT_glGetListParameterivSGIX:
8827         case VOGL_ENTRYPOINT_glGetLocalConstantBooleanvEXT:
8828         case VOGL_ENTRYPOINT_glGetLocalConstantFloatvEXT:
8829         case VOGL_ENTRYPOINT_glGetLocalConstantIntegervEXT:
8830         case VOGL_ENTRYPOINT_glGetMapAttribParameterfvNV:
8831         case VOGL_ENTRYPOINT_glGetMapAttribParameterivNV:
8832         case VOGL_ENTRYPOINT_glGetMapControlPointsNV:
8833         case VOGL_ENTRYPOINT_glGetMapParameterfvNV:
8834         case VOGL_ENTRYPOINT_glGetMapParameterivNV:
8835         case VOGL_ENTRYPOINT_glGetMapdv:
8836         case VOGL_ENTRYPOINT_glGetMapfv:
8837         case VOGL_ENTRYPOINT_glGetMapiv:
8838         case VOGL_ENTRYPOINT_glGetMapxvOES:
8839         case VOGL_ENTRYPOINT_glGetMaterialfv:
8840         case VOGL_ENTRYPOINT_glGetMaterialiv:
8841         case VOGL_ENTRYPOINT_glGetMaterialxOES:
8842         case VOGL_ENTRYPOINT_glGetMinmax:
8843         case VOGL_ENTRYPOINT_glGetMinmaxEXT:
8844         case VOGL_ENTRYPOINT_glGetMinmaxParameterfv:
8845         case VOGL_ENTRYPOINT_glGetMinmaxParameterfvEXT:
8846         case VOGL_ENTRYPOINT_glGetMinmaxParameteriv:
8847         case VOGL_ENTRYPOINT_glGetMinmaxParameterivEXT:
8848         case VOGL_ENTRYPOINT_glGetMultiTexEnvfvEXT:
8849         case VOGL_ENTRYPOINT_glGetMultiTexEnvivEXT:
8850         case VOGL_ENTRYPOINT_glGetMultiTexGendvEXT:
8851         case VOGL_ENTRYPOINT_glGetMultiTexGenfvEXT:
8852         case VOGL_ENTRYPOINT_glGetMultiTexGenivEXT:
8853         case VOGL_ENTRYPOINT_glGetMultiTexImageEXT:
8854         case VOGL_ENTRYPOINT_glGetMultiTexLevelParameterfvEXT:
8855         case VOGL_ENTRYPOINT_glGetMultiTexLevelParameterivEXT:
8856         case VOGL_ENTRYPOINT_glGetMultiTexParameterIivEXT:
8857         case VOGL_ENTRYPOINT_glGetMultiTexParameterIuivEXT:
8858         case VOGL_ENTRYPOINT_glGetMultiTexParameterfvEXT:
8859         case VOGL_ENTRYPOINT_glGetMultiTexParameterivEXT:
8860         case VOGL_ENTRYPOINT_glGetMultisamplefv:
8861         case VOGL_ENTRYPOINT_glGetMultisamplefvNV:
8862         case VOGL_ENTRYPOINT_glGetNamedBufferParameterivEXT:
8863         case VOGL_ENTRYPOINT_glGetNamedBufferParameterui64vNV:
8864         case VOGL_ENTRYPOINT_glGetNamedBufferPointervEXT:
8865         case VOGL_ENTRYPOINT_glGetNamedBufferSubDataEXT:
8866         case VOGL_ENTRYPOINT_glGetNamedFramebufferAttachmentParameterivEXT:
8867         case VOGL_ENTRYPOINT_glGetNamedFramebufferParameterivEXT:
8868         case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterIivEXT:
8869         case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterIuivEXT:
8870         case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterdvEXT:
8871         case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterfvEXT:
8872         case VOGL_ENTRYPOINT_glGetNamedProgramStringEXT:
8873         case VOGL_ENTRYPOINT_glGetNamedProgramivEXT:
8874         case VOGL_ENTRYPOINT_glGetNamedRenderbufferParameterivEXT:
8875         case VOGL_ENTRYPOINT_glGetNamedStringARB:
8876         case VOGL_ENTRYPOINT_glGetNamedStringivARB:
8877         case VOGL_ENTRYPOINT_glGetObjectBufferfvATI:
8878         case VOGL_ENTRYPOINT_glGetObjectBufferivATI:
8879         case VOGL_ENTRYPOINT_glGetObjectLabel:
8880         case VOGL_ENTRYPOINT_glGetObjectParameterfvARB:
8881         case VOGL_ENTRYPOINT_glGetObjectParameterivAPPLE:
8882         case VOGL_ENTRYPOINT_glGetObjectPtrLabel:
8883         case VOGL_ENTRYPOINT_glGetOcclusionQueryivNV:
8884         case VOGL_ENTRYPOINT_glGetOcclusionQueryuivNV:
8885         case VOGL_ENTRYPOINT_glGetPathColorGenfvNV:
8886         case VOGL_ENTRYPOINT_glGetPathColorGenivNV:
8887         case VOGL_ENTRYPOINT_glGetPathCommandsNV:
8888         case VOGL_ENTRYPOINT_glGetPathCoordsNV:
8889         case VOGL_ENTRYPOINT_glGetPathDashArrayNV:
8890         case VOGL_ENTRYPOINT_glGetPathLengthNV:
8891         case VOGL_ENTRYPOINT_glGetPathMetricRangeNV:
8892         case VOGL_ENTRYPOINT_glGetPathMetricsNV:
8893         case VOGL_ENTRYPOINT_glGetPathParameterfvNV:
8894         case VOGL_ENTRYPOINT_glGetPathParameterivNV:
8895         case VOGL_ENTRYPOINT_glGetPathSpacingNV:
8896         case VOGL_ENTRYPOINT_glGetPathTexGenfvNV:
8897         case VOGL_ENTRYPOINT_glGetPathTexGenivNV:
8898         case VOGL_ENTRYPOINT_glGetPerfMonitorCounterDataAMD:
8899         case VOGL_ENTRYPOINT_glGetPerfMonitorCounterInfoAMD:
8900         case VOGL_ENTRYPOINT_glGetPerfMonitorCounterStringAMD:
8901         case VOGL_ENTRYPOINT_glGetPerfMonitorCountersAMD:
8902         case VOGL_ENTRYPOINT_glGetPerfMonitorGroupStringAMD:
8903         case VOGL_ENTRYPOINT_glGetPerfMonitorGroupsAMD:
8904         case VOGL_ENTRYPOINT_glGetPixelMapfv:
8905         case VOGL_ENTRYPOINT_glGetPixelMapuiv:
8906         case VOGL_ENTRYPOINT_glGetPixelMapusv:
8907         case VOGL_ENTRYPOINT_glGetPixelMapxv:
8908         case VOGL_ENTRYPOINT_glGetPixelTexGenParameterfvSGIS:
8909         case VOGL_ENTRYPOINT_glGetPixelTexGenParameterivSGIS:
8910         case VOGL_ENTRYPOINT_glGetPixelTransformParameterfvEXT:
8911         case VOGL_ENTRYPOINT_glGetPixelTransformParameterivEXT:
8912         case VOGL_ENTRYPOINT_glGetPointerIndexedvEXT:
8913         case VOGL_ENTRYPOINT_glGetPointervEXT:
8914         case VOGL_ENTRYPOINT_glGetPolygonStipple:
8915         case VOGL_ENTRYPOINT_glGetProgramBinary:
8916         case VOGL_ENTRYPOINT_glGetProgramEnvParameterIivNV:
8917         case VOGL_ENTRYPOINT_glGetProgramEnvParameterIuivNV:
8918         case VOGL_ENTRYPOINT_glGetProgramEnvParameterdvARB:
8919         case VOGL_ENTRYPOINT_glGetProgramEnvParameterfvARB:
8920         case VOGL_ENTRYPOINT_glGetProgramInterfaceiv:
8921         case VOGL_ENTRYPOINT_glGetProgramLocalParameterIivNV:
8922         case VOGL_ENTRYPOINT_glGetProgramLocalParameterIuivNV:
8923         case VOGL_ENTRYPOINT_glGetProgramLocalParameterdvARB:
8924         case VOGL_ENTRYPOINT_glGetProgramLocalParameterfvARB:
8925         case VOGL_ENTRYPOINT_glGetProgramNamedParameterdvNV:
8926         case VOGL_ENTRYPOINT_glGetProgramNamedParameterfvNV:
8927         case VOGL_ENTRYPOINT_glGetProgramParameterdvNV:
8928         case VOGL_ENTRYPOINT_glGetProgramParameterfvNV:
8929         case VOGL_ENTRYPOINT_glGetProgramPipelineInfoLog:
8930         case VOGL_ENTRYPOINT_glGetProgramPipelineiv:
8931         case VOGL_ENTRYPOINT_glGetProgramResourceIndex:
8932         case VOGL_ENTRYPOINT_glGetProgramResourceLocation:
8933         case VOGL_ENTRYPOINT_glGetProgramResourceLocationIndex:
8934         case VOGL_ENTRYPOINT_glGetProgramResourceName:
8935         case VOGL_ENTRYPOINT_glGetProgramResourceiv:
8936         case VOGL_ENTRYPOINT_glGetProgramStageiv:
8937         case VOGL_ENTRYPOINT_glGetProgramStringARB:
8938         case VOGL_ENTRYPOINT_glGetProgramStringNV:
8939         case VOGL_ENTRYPOINT_glGetProgramSubroutineParameteruivNV:
8940         case VOGL_ENTRYPOINT_glGetProgramivNV:
8941         case VOGL_ENTRYPOINT_glGetQueryIndexediv:
8942         case VOGL_ENTRYPOINT_glGetQueryObjecti64vEXT:
8943         case VOGL_ENTRYPOINT_glGetQueryObjectui64vEXT:
8944         case VOGL_ENTRYPOINT_glGetQueryiv:
8945         case VOGL_ENTRYPOINT_glGetQueryivARB:
8946         case VOGL_ENTRYPOINT_glGetSamplerParameterIiv:
8947         case VOGL_ENTRYPOINT_glGetSamplerParameterIuiv:
8948         case VOGL_ENTRYPOINT_glGetSamplerParameterfv:
8949         case VOGL_ENTRYPOINT_glGetSamplerParameteriv:
8950         case VOGL_ENTRYPOINT_glGetSeparableFilter:
8951         case VOGL_ENTRYPOINT_glGetSeparableFilterEXT:
8952         case VOGL_ENTRYPOINT_glGetShaderPrecisionFormat:
8953         case VOGL_ENTRYPOINT_glGetShaderSource:
8954         case VOGL_ENTRYPOINT_glGetShaderSourceARB:
8955         case VOGL_ENTRYPOINT_glGetSharpenTexFuncSGIS:
8956         case VOGL_ENTRYPOINT_glGetSubroutineIndex:
8957         case VOGL_ENTRYPOINT_glGetSubroutineUniformLocation:
8958         case VOGL_ENTRYPOINT_glGetSynciv:
8959         case VOGL_ENTRYPOINT_glGetTexBumpParameterfvATI:
8960         case VOGL_ENTRYPOINT_glGetTexBumpParameterivATI:
8961         case VOGL_ENTRYPOINT_glGetTexEnvxvOES:
8962         case VOGL_ENTRYPOINT_glGetTexFilterFuncSGIS:
8963         case VOGL_ENTRYPOINT_glGetTexGenxvOES:
8964         case VOGL_ENTRYPOINT_glGetTexImage:
8965         case VOGL_ENTRYPOINT_glGetTexLevelParameterxvOES:
8966         case VOGL_ENTRYPOINT_glGetTexParameterIivEXT:
8967         case VOGL_ENTRYPOINT_glGetTexParameterIuivEXT:
8968         case VOGL_ENTRYPOINT_glGetTexParameterPointervAPPLE:
8969         case VOGL_ENTRYPOINT_glGetTexParameterxvOES:
8970         case VOGL_ENTRYPOINT_glGetTextureHandleNV:
8971         case VOGL_ENTRYPOINT_glGetTextureImageEXT:
8972         case VOGL_ENTRYPOINT_glGetTextureLevelParameterfvEXT:
8973         case VOGL_ENTRYPOINT_glGetTextureLevelParameterivEXT:
8974         case VOGL_ENTRYPOINT_glGetTextureParameterIivEXT:
8975         case VOGL_ENTRYPOINT_glGetTextureParameterIuivEXT:
8976         case VOGL_ENTRYPOINT_glGetTextureParameterfvEXT:
8977         case VOGL_ENTRYPOINT_glGetTextureParameterivEXT:
8978         case VOGL_ENTRYPOINT_glGetTextureSamplerHandleNV:
8979         case VOGL_ENTRYPOINT_glGetTrackMatrixivNV:
8980         case VOGL_ENTRYPOINT_glGetTransformFeedbackVarying:
8981         case VOGL_ENTRYPOINT_glGetTransformFeedbackVaryingEXT:
8982         case VOGL_ENTRYPOINT_glGetTransformFeedbackVaryingNV:
8983         case VOGL_ENTRYPOINT_glGetUniformBlockIndex:
8984         case VOGL_ENTRYPOINT_glGetUniformBufferSizeEXT:
8985         case VOGL_ENTRYPOINT_glGetUniformIndices:
8986         case VOGL_ENTRYPOINT_glGetUniformOffsetEXT:
8987         case VOGL_ENTRYPOINT_glGetUniformSubroutineuiv:
8988         case VOGL_ENTRYPOINT_glGetUniformdv:
8989         case VOGL_ENTRYPOINT_glGetUniformfv:
8990         case VOGL_ENTRYPOINT_glGetUniformfvARB:
8991         case VOGL_ENTRYPOINT_glGetUniformi64vNV:
8992         case VOGL_ENTRYPOINT_glGetUniformiv:
8993         case VOGL_ENTRYPOINT_glGetUniformivARB:
8994         case VOGL_ENTRYPOINT_glGetUniformui64vNV:
8995         case VOGL_ENTRYPOINT_glGetUniformuiv:
8996         case VOGL_ENTRYPOINT_glGetUniformuivEXT:
8997         case VOGL_ENTRYPOINT_glGetVariantArrayObjectfvATI:
8998         case VOGL_ENTRYPOINT_glGetVariantArrayObjectivATI:
8999         case VOGL_ENTRYPOINT_glGetVariantBooleanvEXT:
9000         case VOGL_ENTRYPOINT_glGetVariantFloatvEXT:
9001         case VOGL_ENTRYPOINT_glGetVariantIntegervEXT:
9002         case VOGL_ENTRYPOINT_glGetVariantPointervEXT:
9003         case VOGL_ENTRYPOINT_glGetVaryingLocationNV:
9004         case VOGL_ENTRYPOINT_glGetVertexAttribArrayObjectfvATI:
9005         case VOGL_ENTRYPOINT_glGetVertexAttribArrayObjectivATI:
9006         case VOGL_ENTRYPOINT_glGetVertexAttribLdv:
9007         case VOGL_ENTRYPOINT_glGetVertexAttribLdvEXT:
9008         case VOGL_ENTRYPOINT_glGetVertexAttribLi64vNV:
9009         case VOGL_ENTRYPOINT_glGetVertexAttribLui64vNV:
9010         case VOGL_ENTRYPOINT_glGetVertexAttribPointerv:
9011         case VOGL_ENTRYPOINT_glGetVertexAttribPointervARB:
9012         case VOGL_ENTRYPOINT_glGetVertexAttribPointervNV:
9013         case VOGL_ENTRYPOINT_glGetVertexAttribdvARB:
9014         case VOGL_ENTRYPOINT_glGetVertexAttribdvNV:
9015         case VOGL_ENTRYPOINT_glGetVertexAttribfvARB:
9016         case VOGL_ENTRYPOINT_glGetVertexAttribfvNV:
9017         case VOGL_ENTRYPOINT_glGetVertexAttribivARB:
9018         case VOGL_ENTRYPOINT_glGetVertexAttribivNV:
9019         case VOGL_ENTRYPOINT_glGetVideoCaptureStreamdvNV:
9020         case VOGL_ENTRYPOINT_glGetVideoCaptureStreamfvNV:
9021         case VOGL_ENTRYPOINT_glGetVideoCaptureStreamivNV:
9022         case VOGL_ENTRYPOINT_glGetVideoCaptureivNV:
9023         case VOGL_ENTRYPOINT_glGetVideoi64vNV:
9024         case VOGL_ENTRYPOINT_glGetVideoivNV:
9025         case VOGL_ENTRYPOINT_glGetVideoui64vNV:
9026         case VOGL_ENTRYPOINT_glGetVideouivNV:
9027         case VOGL_ENTRYPOINT_glGetnColorTableARB:
9028         case VOGL_ENTRYPOINT_glGetnCompressedTexImageARB:
9029         case VOGL_ENTRYPOINT_glGetnConvolutionFilterARB:
9030         case VOGL_ENTRYPOINT_glGetnHistogramARB:
9031         case VOGL_ENTRYPOINT_glGetnMapdvARB:
9032         case VOGL_ENTRYPOINT_glGetnMapfvARB:
9033         case VOGL_ENTRYPOINT_glGetnMapivARB:
9034         case VOGL_ENTRYPOINT_glGetnMinmaxARB:
9035         case VOGL_ENTRYPOINT_glGetnPixelMapfvARB:
9036         case VOGL_ENTRYPOINT_glGetnPixelMapuivARB:
9037         case VOGL_ENTRYPOINT_glGetnPixelMapusvARB:
9038         case VOGL_ENTRYPOINT_glGetnPolygonStippleARB:
9039         case VOGL_ENTRYPOINT_glGetnSeparableFilterARB:
9040         case VOGL_ENTRYPOINT_glGetnTexImageARB:
9041         case VOGL_ENTRYPOINT_glGetnUniformdvARB:
9042         case VOGL_ENTRYPOINT_glGetnUniformfvARB:
9043         case VOGL_ENTRYPOINT_glGetnUniformivARB:
9044         case VOGL_ENTRYPOINT_glGetnUniformuivARB:
9045         case VOGL_ENTRYPOINT_glIsBufferARB:
9046         case VOGL_ENTRYPOINT_glIsEnabledIndexedEXT:
9047         case VOGL_ENTRYPOINT_glIsQueryARB:
9048         case VOGL_ENTRYPOINT_glIsSync:
9049         case VOGL_ENTRYPOINT_glPrioritizeTextures:
9050         case VOGL_ENTRYPOINT_glPrioritizeTexturesEXT:
9051         {
9052             if (!(g_vogl_entrypoint_descs[entrypoint_id].m_flags & cGLEFPrintedUnimplementedWarning))
9053             {
9054                 process_entrypoint_warning("%s: TODO: Implement glGet() function %s\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[entrypoint_id].m_pName);
9055
9056                 g_vogl_entrypoint_descs[entrypoint_id].m_flags |= cGLEFPrintedUnimplementedWarning;
9057             }
9058             break;
9059         }
9060         default:
9061         {
9062             if (g_vogl_entrypoint_descs[entrypoint_id].m_is_whitelisted)
9063                 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);
9064             else
9065                 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);
9066             return cStatusSoftFailure;
9067         }
9068     }
9069
9070     m_last_processed_call_counter = trace_packet.get_call_counter();
9071
9072     if (!m_pCur_context_state->m_inside_gl_begin)
9073     {
9074         if (check_gl_error())
9075             return cStatusGLError;
9076     }
9077
9078     if (vogl_is_draw_entrypoint(entrypoint_id) || vogl_is_clear_entrypoint(entrypoint_id) || (entrypoint_id == VOGL_ENTRYPOINT_glBitmap))
9079     {
9080         if ((status = post_draw_call()) != cStatusOK)
9081             return status;
9082     }
9083
9084     return cStatusOK;
9085 }
9086
9087 //----------------------------------------------------------------------------------------------------------------------
9088 // vogl_gl_replayer::snapshot_backbuffer
9089 //----------------------------------------------------------------------------------------------------------------------
9090 void vogl_gl_replayer::snapshot_backbuffer()
9091 {
9092     VOGL_FUNC_TRACER
9093
9094     if (!m_pCur_context_state)
9095     {
9096         vogl_warning_printf("%s: Can't take snapshot without an active context\n", VOGL_METHOD_NAME);
9097         return;
9098     }
9099
9100     uint recorded_width = m_pWindow->get_width();
9101     uint recorded_height = m_pWindow->get_height();
9102
9103     uint width = 0, height = 0;
9104     m_pWindow->get_actual_dimensions(width, height);
9105
9106     VOGL_ASSERT((recorded_width == width) && (recorded_height == height));
9107     VOGL_NOTE_UNUSED(recorded_width);
9108     VOGL_NOTE_UNUSED(recorded_height);
9109
9110     m_screenshot_buffer.resize(width * height * 3);
9111
9112     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);
9113     if (!success)
9114     {
9115         process_entrypoint_error("%s: Failed calling glReadPixels() to take screenshot\n", VOGL_METHOD_NAME);
9116     }
9117
9118     if (m_flags & cGLReplayerDumpScreenshots)
9119     {
9120         size_t png_size = 0;
9121         void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(m_screenshot_buffer.get_ptr(), width, height, 3, &png_size, 1, true);
9122
9123         dynamic_string screenshot_filename(cVarArg, "%s_%07u.png", m_screenshot_prefix.get_ptr(), m_total_swaps);
9124         if (!file_utils::write_buf_to_file(screenshot_filename.get_ptr(), pPNG_data, png_size))
9125         {
9126             process_entrypoint_error("Failed writing PNG screenshot to file %s\n", screenshot_filename.get_ptr());
9127         }
9128         else
9129         {
9130             vogl_message_printf("Wrote screenshot to file %s\n", screenshot_filename.get_ptr());
9131         }
9132
9133         mz_free(pPNG_data);
9134     }
9135
9136     if ((m_flags & cGLReplayerDumpBackbufferHashes) || (m_flags & cGLReplayerHashBackbuffer))
9137     {
9138         uint64_t backbuffer_crc64;
9139
9140         if (m_flags & cGLReplayerSumHashing)
9141         {
9142             backbuffer_crc64 = calc_sum64(m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size());
9143         }
9144         else
9145         {
9146             backbuffer_crc64 = calc_crc64(CRC64_INIT, m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size());
9147         }
9148
9149         vogl_printf("Frame %u hash: 0x%016" PRIX64 "\n", m_frame_index, backbuffer_crc64);
9150
9151         if (m_backbuffer_hash_filename.has_content())
9152         {
9153             FILE *pFile = vogl_fopen(m_backbuffer_hash_filename.get_ptr(), "a");
9154             if (!pFile)
9155                 vogl_error_printf("Failed writing to backbuffer hash file %s\n", m_backbuffer_hash_filename.get_ptr());
9156             else
9157             {
9158                 vogl_fprintf(pFile, "0x%016" PRIX64 "\n", cast_val_to_uint64(backbuffer_crc64));
9159                 vogl_fclose(pFile);
9160             }
9161         }
9162     }
9163 }
9164
9165 //----------------------------------------------------------------------------------------------------------------------
9166 // vogl_gl_replayer::is_valid_handle
9167 //----------------------------------------------------------------------------------------------------------------------
9168 bool vogl_gl_replayer::replay_to_trace_handle_remapper::is_valid_handle(vogl_namespace_t handle_namespace, uint64_t replay_handle)
9169 {
9170     VOGL_FUNC_TRACER
9171
9172     if (!replay_handle)
9173         return 0;
9174
9175     uint32 replay_handle32 = static_cast<uint32>(replay_handle);
9176
9177     switch (handle_namespace)
9178     {
9179         case VOGL_NAMESPACE_VERTEX_ARRAYS:
9180         {
9181             VOGL_ASSERT(replay_handle32 == replay_handle);
9182             return (m_replayer.get_context_state()->m_vertex_array_objects.search_table_for_value_get_count(replay_handle32) != 0);
9183         }
9184         case VOGL_NAMESPACE_FRAMEBUFFERS:
9185         {
9186             VOGL_ASSERT(replay_handle32 == replay_handle);
9187             return (m_replayer.get_context_state()->m_framebuffers.search_table_for_value_get_count(replay_handle32) != 0);
9188         }
9189         case VOGL_NAMESPACE_TEXTURES:
9190         {
9191             VOGL_ASSERT(replay_handle32 == replay_handle);
9192             return (m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(replay_handle32) != 0);
9193         }
9194         case VOGL_NAMESPACE_RENDER_BUFFERS:
9195         {
9196             VOGL_ASSERT(replay_handle32 == replay_handle);
9197             return (m_replayer.get_shared_state()->m_shadow_state.m_rbos.contains_inv(replay_handle32) != 0);
9198         }
9199         case VOGL_NAMESPACE_QUERIES:
9200         {
9201             VOGL_ASSERT(replay_handle32 == replay_handle);
9202             return (m_replayer.get_shared_state()->m_queries.search_table_for_value_get_count(replay_handle32) != 0);
9203         }
9204         case VOGL_NAMESPACE_SAMPLERS:
9205         {
9206             VOGL_ASSERT(replay_handle32 == replay_handle);
9207             return (m_replayer.get_shared_state()->m_sampler_objects.search_table_for_value_get_count(replay_handle32) != 0);
9208         }
9209         case VOGL_NAMESPACE_PROGRAMS:
9210         {
9211             VOGL_ASSERT(replay_handle32 == replay_handle);
9212             return m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_PROGRAM_OBJECT;
9213         }
9214         case VOGL_NAMESPACE_SHADERS:
9215         {
9216             VOGL_ASSERT(replay_handle32 == replay_handle);
9217             return m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_SHADER_OBJECT;
9218         }
9219         case VOGL_NAMESPACE_BUFFERS:
9220         {
9221             VOGL_ASSERT(replay_handle32 == replay_handle);
9222             return m_replayer.get_shared_state()->m_buffers.search_table_for_value_get_count(replay_handle32);
9223         }
9224         case VOGL_NAMESPACE_SYNCS:
9225         {
9226             GLsync replay_sync = vogl_handle_to_sync(replay_handle);
9227             return m_replayer.get_shared_state()->m_syncs.search_table_for_value_get_count(replay_sync) != 0;
9228         }
9229         case VOGL_NAMESPACE_PROGRAM_ARB:
9230         {
9231             VOGL_ASSERT(replay_handle32 == replay_handle);
9232             return m_replayer.get_shared_state()->m_arb_programs.search_table_for_value_get_count(replay_handle32) != 0;
9233         }
9234         default:
9235             break;
9236     }
9237
9238     VOGL_VERIFY(0);
9239
9240     return false;
9241 }
9242
9243 //----------------------------------------------------------------------------------------------------------------------
9244 // vogl_gl_replayer::remap_handle
9245 //----------------------------------------------------------------------------------------------------------------------
9246 uint64_t vogl_gl_replayer::replay_to_trace_handle_remapper::remap_handle(vogl_namespace_t handle_namespace, uint64_t replay_handle)
9247 {
9248     VOGL_FUNC_TRACER
9249
9250     if (!replay_handle)
9251         return 0;
9252
9253     uint32 replay_handle32 = static_cast<uint32>(replay_handle);
9254
9255     switch (handle_namespace)
9256     {
9257         case VOGL_NAMESPACE_VERTEX_ARRAYS:
9258         {
9259             VOGL_ASSERT(replay_handle32 == replay_handle);
9260             if (remap_replay_to_trace_handle(m_replayer.get_context_state()->m_vertex_array_objects, replay_handle32))
9261                 return replay_handle32;
9262             break;
9263         }
9264         case VOGL_NAMESPACE_FRAMEBUFFERS:
9265         {
9266             VOGL_ASSERT(replay_handle32 == replay_handle);
9267             if (remap_replay_to_trace_handle(m_replayer.get_context_state()->m_framebuffers, replay_handle32))
9268                 return replay_handle32;
9269             break;
9270         }
9271         case VOGL_NAMESPACE_TEXTURES:
9272         {
9273             VOGL_ASSERT(replay_handle32 == replay_handle);
9274
9275             uint32 trace_handle = replay_handle32;
9276             if (m_replayer.get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_handle32, trace_handle))
9277                 return trace_handle;
9278
9279             break;
9280         }
9281         case VOGL_NAMESPACE_RENDER_BUFFERS:
9282         {
9283             VOGL_ASSERT(replay_handle32 == replay_handle);
9284             GLuint trace_handle = replay_handle32;
9285             if (m_replayer.get_shared_state()->m_shadow_state.m_rbos.map_inv_handle_to_handle(replay_handle32, trace_handle))
9286                 return trace_handle;
9287
9288             break;
9289         }
9290         case VOGL_NAMESPACE_QUERIES:
9291         {
9292             VOGL_ASSERT(replay_handle32 == replay_handle);
9293             if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_queries, replay_handle32))
9294                 return replay_handle32;
9295             break;
9296         }
9297         case VOGL_NAMESPACE_SAMPLERS:
9298         {
9299             VOGL_ASSERT(replay_handle32 == replay_handle);
9300             if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_sampler_objects, replay_handle32))
9301                 return replay_handle32;
9302             break;
9303         }
9304         case VOGL_NAMESPACE_PROGRAMS:
9305         {
9306             VOGL_ASSERT(replay_handle32 == replay_handle);
9307             VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_PROGRAM_OBJECT);
9308             GLuint trace_handle = replay_handle32;
9309             if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle32, trace_handle))
9310                 return trace_handle;
9311             break;
9312         }
9313         case VOGL_NAMESPACE_SHADERS:
9314         {
9315             VOGL_ASSERT(replay_handle32 == replay_handle);
9316             VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_SHADER_OBJECT);
9317             GLuint trace_handle = replay_handle32;
9318             if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle32, trace_handle))
9319                 return trace_handle;
9320             break;
9321         }
9322         case VOGL_NAMESPACE_BUFFERS:
9323         {
9324             VOGL_ASSERT(replay_handle32 == replay_handle);
9325             if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_buffers, replay_handle32))
9326                 return replay_handle32;
9327             break;
9328         }
9329         case VOGL_NAMESPACE_SYNCS:
9330         {
9331             GLsync replay_sync = vogl_handle_to_sync(replay_handle);
9332
9333             gl_sync_hash_map::const_iterator it(m_replayer.get_shared_state()->m_syncs.search_table_for_value(replay_sync));
9334             if (it != m_replayer.get_shared_state()->m_syncs.end())
9335             {
9336                 VOGL_ASSERT(it->second == replay_sync);
9337                 return it->first;
9338             }
9339
9340             break;
9341         }
9342         case VOGL_NAMESPACE_PROGRAM_ARB:
9343         {
9344             VOGL_ASSERT(replay_handle32 == replay_handle);
9345             if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_arb_programs, replay_handle32))
9346                 return replay_handle32;
9347             break;
9348         }
9349         default:
9350         {
9351             break;
9352         }
9353     }
9354
9355     // This is BAD.
9356     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));
9357
9358     VOGL_ASSERT_ALWAYS;
9359
9360     return replay_handle;
9361 }
9362
9363 //----------------------------------------------------------------------------------------------------------------------
9364 // vogl_gl_replayer::replay_to_trace_handle_remapper::remap_location
9365 //----------------------------------------------------------------------------------------------------------------------
9366 int32 vogl_gl_replayer::replay_to_trace_handle_remapper::remap_location(uint32 replay_program, int32 replay_location)
9367 {
9368     VOGL_FUNC_TRACER
9369
9370     if ((!replay_program) || (replay_location < 0))
9371         return replay_location;
9372
9373     GLuint trace_program = static_cast<GLuint>(remap_handle(VOGL_NAMESPACE_PROGRAMS, replay_program));
9374
9375     glsl_program_hash_map::const_iterator it(m_replayer.get_shared_state()->m_glsl_program_hash_map.find(trace_program));
9376     if (it != m_replayer.get_shared_state()->m_glsl_program_hash_map.end())
9377     {
9378         const glsl_program_state &state = it->second;
9379
9380         uniform_location_hash_map::const_iterator loc_it(state.m_uniform_locations.search_table_for_value(replay_location));
9381         if (loc_it != state.m_uniform_locations.end())
9382             return loc_it->first;
9383     }
9384
9385     vogl_warning_printf("%s: Failed remapping location %i of program %u\n", VOGL_METHOD_NAME, replay_location, replay_program);
9386
9387     return replay_location;
9388 }
9389
9390 //----------------------------------------------------------------------------------------------------------------------
9391 // vogl_gl_replayer::replay_to_trace_handle_remapper::determine_from_object_target
9392 //----------------------------------------------------------------------------------------------------------------------
9393 bool vogl_gl_replayer::replay_to_trace_handle_remapper::determine_from_object_target(vogl_namespace_t handle_namespace, uint64_t replay_handle, GLenum &target)
9394 {
9395     VOGL_FUNC_TRACER
9396
9397     target = GL_NONE;
9398
9399     uint32 handle32 = static_cast<uint32>(replay_handle);
9400
9401     switch (handle_namespace)
9402     {
9403         case VOGL_NAMESPACE_TEXTURES:
9404         {
9405             VOGL_ASSERT(handle32 == replay_handle);
9406             if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(handle32))
9407                 return false;
9408
9409             target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target_inv(handle32);
9410             return true;
9411         }
9412         default:
9413             break;
9414     }
9415
9416     VOGL_VERIFY(0);
9417     return false;
9418 }
9419
9420 //----------------------------------------------------------------------------------------------------------------------
9421 // vogl_gl_replayer::replay_to_trace_handle_remapper::determine_to_object_target
9422 //----------------------------------------------------------------------------------------------------------------------
9423 bool vogl_gl_replayer::replay_to_trace_handle_remapper::determine_to_object_target(vogl_namespace_t handle_namespace, uint64_t trace_handle, GLenum &target)
9424 {
9425     VOGL_FUNC_TRACER
9426
9427     target = GL_NONE;
9428
9429     uint32 handle32 = static_cast<uint32>(trace_handle);
9430
9431     switch (handle_namespace)
9432     {
9433         case VOGL_NAMESPACE_TEXTURES:
9434         {
9435             VOGL_ASSERT(handle32 == trace_handle);
9436             if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(handle32))
9437                 return false;
9438
9439             target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target(handle32);
9440             return true;
9441         }
9442         default:
9443             break;
9444     }
9445
9446     VOGL_VERIFY(0);
9447     return false;
9448 }
9449
9450 //----------------------------------------------------------------------------------------------------------------------
9451 // vogl_replayer::determine_used_program_handles
9452 //----------------------------------------------------------------------------------------------------------------------
9453 bool vogl_gl_replayer::determine_used_program_handles(const vogl_trace_packet_array &trim_packets, vogl_handle_hash_set &replay_program_handles)
9454 {
9455     VOGL_FUNC_TRACER
9456
9457     trace_to_replay_handle_remapper trace_to_replay_remapper(*this);
9458
9459 #if 0
9460         GLint cur_program_handle = 0;
9461         GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &cur_program_handle);
9462         check_gl_error();
9463
9464         if (cur_program_handle)
9465                 replay_program_handles.insert(cur_program_handle);
9466 #endif
9467
9468     // Scan for bound programs on all contexts in this sharegroup
9469     context_state *pContext_shareroot = m_pCur_context_state->m_pShared_state;
9470     for (context_hash_map::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
9471     {
9472         context_state *pContext = it->second;
9473         if (pContext->m_pShared_state == pContext_shareroot)
9474         {
9475             if (pContext->m_cur_replay_program)
9476                 replay_program_handles.insert(pContext->m_cur_replay_program);
9477         }
9478     }
9479
9480     for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
9481     {
9482         if (trim_packets.get_packet_type(packet_index) != cTSPTGLEntrypoint)
9483             continue;
9484
9485         const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
9486
9487         // 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.
9488         if (!m_temp2_gl_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
9489             return false;
9490
9491         GLuint trace_handle = 0;
9492         bool refers_to_program = vogl_does_packet_refer_to_program(m_temp2_gl_packet, trace_handle);
9493         if (!refers_to_program)
9494             continue;
9495         if (!trace_handle)
9496             continue;
9497
9498         // 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
9499         // 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).
9500         if (!trace_to_replay_remapper.is_valid_handle(VOGL_NAMESPACE_PROGRAMS, trace_handle))
9501             continue;
9502
9503         uint64_t replay_handle = trace_to_replay_remapper.remap_handle(VOGL_NAMESPACE_PROGRAMS, trace_handle);
9504         if (!replay_handle)
9505             continue;
9506
9507         VOGL_ASSERT(utils::is_32bit(replay_handle));
9508
9509         replay_program_handles.insert(static_cast<uint32>(replay_handle));
9510     }
9511
9512     vogl_message_printf("%s: Found %u actually referenced program handles\n", VOGL_METHOD_NAME, replay_program_handles.size());
9513
9514     return true;
9515 }
9516
9517 //----------------------------------------------------------------------------------------------------------------------
9518 // vogl_replayer::fill_replay_handle_hash_set
9519 //----------------------------------------------------------------------------------------------------------------------
9520 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)
9521 {
9522     VOGL_FUNC_TRACER
9523
9524     replay_handle_hash.reset();
9525     replay_handle_hash.reserve(trace_to_replay_hash.size());
9526     for (gl_handle_hash_map::const_iterator it = trace_to_replay_hash.begin(); it != trace_to_replay_hash.end(); ++it)
9527     {
9528         // Insert replay handles into destination hash table
9529         bool success = replay_handle_hash.insert(it->second).second;
9530         VOGL_ASSERT(success);
9531         VOGL_NOTE_UNUSED(success);
9532     }
9533 }
9534
9535 //----------------------------------------------------------------------------------------------------------------------
9536 // vogl_replayer::snapshot_state
9537 //----------------------------------------------------------------------------------------------------------------------
9538 vogl_gl_state_snapshot *vogl_gl_replayer::snapshot_state(const vogl_trace_packet_array *pTrim_packets, bool optimize_snapshot)
9539 {
9540     VOGL_FUNC_TRACER
9541
9542     timed_scope ts(VOGL_METHOD_NAME);
9543
9544     vogl_gl_state_snapshot *pSnapshot = vogl_new(vogl_gl_state_snapshot);
9545
9546     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,
9547                        m_pWindow->get_width(), m_pWindow->get_height(), m_cur_trace_context, m_frame_index, m_last_parsed_call_counter, m_at_frame_boundary);
9548
9549     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))
9550     {
9551         vogl_error_printf("%s: Failed beginning capture\n", VOGL_METHOD_NAME);
9552
9553         vogl_delete(pSnapshot);
9554         pSnapshot = NULL;
9555
9556         return NULL;
9557     }
9558
9559     vogl_client_side_array_desc_vec client_side_vertex_attrib_ptrs;
9560     for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_vertex_attrib_data); i++)
9561         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()));
9562
9563     vogl_client_side_array_desc_vec client_side_array_ptrs;
9564     for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_array_data); i++)
9565         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()));
9566
9567     vogl_client_side_array_desc_vec client_side_texcoord_ptrs;
9568     for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_texcoord_data); i++)
9569         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()));
9570
9571     pSnapshot->add_client_side_array_ptrs(client_side_vertex_attrib_ptrs, client_side_array_ptrs, client_side_texcoord_ptrs);
9572
9573     vogl_printf("%s: Capturing %u context(s)\n", VOGL_METHOD_NAME, m_contexts.size());
9574
9575     context_hash_map::iterator it;
9576     for (it = m_contexts.begin(); it != m_contexts.end(); ++it)
9577     {
9578         context_state *pContext_state = it->second;
9579
9580         if (pContext_state->m_deleted)
9581         {
9582             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));
9583             break;
9584         }
9585
9586         vogl_capture_context_params temp_shadow_state;
9587         vogl_capture_context_params *pShadow_state = &temp_shadow_state;
9588
9589         if (pContext_state->m_has_been_made_current)
9590         {
9591             status_t status = switch_contexts(it->first);
9592             if (status != cStatusOK)
9593             {
9594                 vogl_error_printf("%s: Failed switching to trace context 0x%" PRIX64 ", capture failed\n", VOGL_METHOD_NAME, cast_val_to_uint64(it->first));
9595                 break;
9596             }
9597
9598             VOGL_ASSERT(m_pCur_context_state == pContext_state);
9599
9600             if (m_pCur_context_state->m_inside_gl_begin)
9601             {
9602                 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));
9603                 pSnapshot->set_is_restorable(false);
9604             }
9605
9606
9607             // Init the shadow state needed by the snapshot code.
9608             if (!m_pCur_context_state->is_root_context())
9609             {
9610                 // Only fill in non-shared state.
9611                 fill_replay_handle_hash_set(pShadow_state->m_framebuffers, get_context_state()->m_framebuffers);
9612                 fill_replay_handle_hash_set(pShadow_state->m_vaos, get_context_state()->m_vertex_array_objects);
9613             }
9614             else
9615             {
9616                 pShadow_state = &m_pCur_context_state->m_shadow_state;
9617
9618                 pShadow_state->m_query_targets = get_shared_state()->m_query_targets;
9619
9620                 fill_replay_handle_hash_set(pShadow_state->m_samplers, get_shared_state()->m_sampler_objects);
9621                 fill_replay_handle_hash_set(pShadow_state->m_framebuffers, get_context_state()->m_framebuffers);
9622                 fill_replay_handle_hash_set(pShadow_state->m_vaos, get_context_state()->m_vertex_array_objects);
9623
9624                 // Buffer targets
9625                 pShadow_state->m_buffer_targets.reset();
9626                 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)
9627                 {
9628                     GLuint trace_handle = buf_it->first;
9629                     GLuint replay_handle = buf_it->second;
9630
9631                     gl_handle_hash_map::const_iterator target_it = get_shared_state()->m_buffer_targets.find(trace_handle);
9632                     if (target_it == get_shared_state()->m_buffer_targets.end())
9633                     {
9634                         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);
9635                         continue;
9636                     }
9637                     GLenum target = target_it->second;
9638
9639                     pShadow_state->m_buffer_targets.insert(replay_handle, target);
9640                 }
9641
9642                 // Syncs
9643                 pShadow_state->m_syncs.reset();
9644                 pShadow_state->m_syncs.reserve(get_shared_state()->m_syncs.size());
9645                 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)
9646                 {
9647                     bool success = pShadow_state->m_syncs.insert(vogl_sync_to_handle(sync_it->second)).second;
9648                     VOGL_ASSERT(success);
9649                     VOGL_NOTE_UNUSED(success);
9650                 }
9651
9652                 // Program handles filter
9653                 pShadow_state->m_filter_program_handles = false;
9654                 pShadow_state->m_program_handles_filter.reset();
9655
9656 #if 0
9657                                 // 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).
9658                                 // This is an optimization issue, and we're concentrating on correctness right now so let's figure this out later.
9659                                 if ((pTrim_packets) && (optimize_snapshot))
9660                                 {
9661                     if (!determine_used_program_handles(*pTrim_packets, pShadow_state->m_program_handles_filter))
9662                                         {
9663                                                 vogl_warning_printf("%s: Failed determining used program handles\n", VOGL_METHOD_NAME);
9664                                                 pShadow_state->m_program_handles_filter.clear();
9665                                         }
9666                                         else
9667                                         {
9668                                                 pShadow_state->m_filter_program_handles = true;
9669                                         }
9670                                 }
9671 #else
9672                 VOGL_NOTE_UNUSED(optimize_snapshot);
9673                 VOGL_NOTE_UNUSED(pTrim_packets);
9674 #endif
9675
9676                 // ARB program targets
9677                 pShadow_state->m_arb_program_targets.reset();
9678                 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)
9679                 {
9680                     GLuint trace_handle = arb_prog_it->first;
9681                     GLuint replay_handle = get_shared_state()->m_arb_programs.value(trace_handle);
9682                     if ((!trace_handle) || (!replay_handle))
9683                     {
9684                         VOGL_ASSERT_ALWAYS;
9685                         continue;
9686                     }
9687
9688                     GLenum target = arb_prog_it->second;
9689                     pShadow_state->m_arb_program_targets.insert(replay_handle, target);
9690                 }
9691
9692                 // Deal with any currently mapped buffers.
9693                 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
9694
9695                 pShadow_state->m_mapped_buffers = mapped_bufs;
9696
9697                 if (mapped_bufs.size())
9698                 {
9699                     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());
9700
9701                     for (uint i = 0; i < mapped_bufs.size(); i++)
9702                     {
9703                         vogl_mapped_buffer_desc &desc = mapped_bufs[i];
9704
9705                         GLuint prev_handle = vogl_get_bound_gl_buffer(desc.m_target);
9706
9707                         GL_ENTRYPOINT(glBindBuffer)(desc.m_target, desc.m_buffer);
9708                         VOGL_CHECK_GL_ERROR;
9709
9710                         GL_ENTRYPOINT(glUnmapBuffer)(desc.m_target);
9711                         VOGL_CHECK_GL_ERROR;
9712
9713                         desc.m_pPtr = NULL;
9714
9715                         GL_ENTRYPOINT(glBindBuffer)(desc.m_target, prev_handle);
9716                         VOGL_CHECK_GL_ERROR;
9717                     }
9718                 }
9719
9720             } // if (!m_pCur_context_state->is_root_context())
9721
9722         } // if (pContext_state->m_has_been_made_current)
9723
9724         if (!pSnapshot->capture_context(pContext_state->m_context_desc, pContext_state->m_context_info, m_replay_to_trace_remapper, *pShadow_state))
9725         {
9726             vogl_error_printf("%s: Failed capturing trace context 0x%" PRIX64 ", capture failed\n", VOGL_METHOD_NAME, static_cast<uint64_t>(it->first));
9727             break;
9728         }
9729
9730         if ((pContext_state->m_has_been_made_current) && (m_pCur_context_state->is_root_context()))
9731         {
9732             vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
9733
9734             // Now remap any mapped buffers
9735             for (uint i = 0; i < mapped_bufs.size(); i++)
9736             {
9737                 vogl_mapped_buffer_desc &desc = mapped_bufs[i];
9738
9739                 GLuint prev_handle = vogl_get_bound_gl_buffer(desc.m_target);
9740
9741                 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, desc.m_buffer);
9742                 VOGL_CHECK_GL_ERROR;
9743
9744                 if (desc.m_range)
9745                 {
9746                     desc.m_pPtr = GL_ENTRYPOINT(glMapBufferRange)(desc.m_target, static_cast<GLintptr>(desc.m_offset), static_cast<GLsizeiptr>(desc.m_length), desc.m_access);
9747                     VOGL_CHECK_GL_ERROR;
9748                 }
9749                 else
9750                 {
9751                     desc.m_pPtr = GL_ENTRYPOINT(glMapBuffer)(desc.m_target, desc.m_access);
9752                     VOGL_CHECK_GL_ERROR;
9753                 }
9754
9755                 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, prev_handle);
9756                 VOGL_CHECK_GL_ERROR;
9757
9758             }
9759         }
9760     }
9761
9762     if ((it == m_contexts.end()) && (pSnapshot->end_capture()))
9763     {
9764         vogl_printf("%s: Capture succeeded\n", VOGL_METHOD_NAME);
9765     }
9766     else
9767     {
9768         vogl_printf("%s: Capture failed\n", VOGL_METHOD_NAME);
9769
9770         vogl_delete(pSnapshot);
9771         pSnapshot = NULL;
9772     }
9773
9774     return pSnapshot;
9775 }
9776
9777 //----------------------------------------------------------------------------------------------------------------------
9778 // vogl_replayer::reset_state
9779 //----------------------------------------------------------------------------------------------------------------------
9780 void vogl_gl_replayer::reset_state()
9781 {
9782     VOGL_FUNC_TRACER
9783
9784     // Purposely does NOT destroy the cached snapshots
9785
9786     destroy_pending_snapshot();
9787     destroy_contexts();
9788
9789     m_pending_make_current_packet.clear();
9790     m_pending_window_resize_width = 0;
9791     m_pending_window_resize_height = 0;
9792     m_pending_window_resize_attempt_counter = 0;
9793
9794     m_frame_index = 0;
9795     m_last_parsed_call_counter = -1;
9796     m_last_processed_call_counter = -1;
9797     m_at_frame_boundary = true;
9798
9799     m_cur_trace_context = 0;
9800     m_cur_replay_context = 0;
9801     m_pCur_context_state = NULL;
9802
9803     // Testing
9804     //if (m_pWindow->is_opened())
9805     //   m_pWindow->clear_window();
9806 }
9807
9808 //----------------------------------------------------------------------------------------------------------------------
9809 // trace_to_replay_handle_remapper::is_valid_handle
9810 //----------------------------------------------------------------------------------------------------------------------
9811 bool vogl_gl_replayer::trace_to_replay_handle_remapper::is_valid_handle(vogl_namespace_t handle_namespace, uint64_t from_handle)
9812 {
9813     VOGL_FUNC_TRACER
9814
9815     if (!from_handle)
9816         return false;
9817
9818     uint32 from_handle32 = static_cast<uint32>(from_handle);
9819
9820     switch (handle_namespace)
9821     {
9822         case VOGL_NAMESPACE_VERTEX_ARRAYS:
9823         {
9824             VOGL_ASSERT(from_handle32 == from_handle);
9825             return m_replayer.get_context_state()->m_vertex_array_objects.contains(from_handle32);
9826         }
9827         case VOGL_NAMESPACE_TEXTURES:
9828         {
9829             VOGL_ASSERT(from_handle32 == from_handle);
9830             return m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(from_handle32);
9831         }
9832         case VOGL_NAMESPACE_SAMPLERS:
9833         {
9834             VOGL_ASSERT(from_handle32 == from_handle);
9835             return m_replayer.get_shared_state()->m_sampler_objects.contains(from_handle32);
9836         }
9837         case VOGL_NAMESPACE_BUFFERS:
9838         {
9839             VOGL_ASSERT(from_handle32 == from_handle);
9840             return m_replayer.get_shared_state()->m_buffers.contains(from_handle32);
9841         }
9842         case VOGL_NAMESPACE_SHADERS:
9843         case VOGL_NAMESPACE_PROGRAMS:
9844         {
9845             VOGL_ASSERT(from_handle32 == from_handle);
9846             return m_replayer.get_shared_state()->m_shadow_state.m_objs.contains(from_handle32);
9847         }
9848         case VOGL_NAMESPACE_FRAMEBUFFERS:
9849         {
9850             VOGL_ASSERT(from_handle32 == from_handle);
9851             return m_replayer.get_context_state()->m_framebuffers.contains(from_handle32);
9852         }
9853         case VOGL_NAMESPACE_RENDER_BUFFERS:
9854         {
9855             VOGL_ASSERT(from_handle32 == from_handle);
9856             return m_replayer.get_shared_state()->m_shadow_state.m_rbos.contains(from_handle32);
9857         }
9858         case VOGL_NAMESPACE_QUERIES:
9859         {
9860             VOGL_ASSERT(from_handle32 == from_handle);
9861             return m_replayer.get_shared_state()->m_queries.contains(from_handle32);
9862         }
9863         case VOGL_NAMESPACE_SYNCS:
9864         {
9865             return m_replayer.get_shared_state()->m_syncs.contains(from_handle);
9866         }
9867         case VOGL_NAMESPACE_PROGRAM_ARB:
9868         {
9869             return m_replayer.get_shared_state()->m_arb_programs.contains(from_handle32);
9870         }
9871         default:
9872             break;
9873     }
9874
9875     VOGL_VERIFY(0);
9876
9877     return false;
9878 }
9879
9880 //----------------------------------------------------------------------------------------------------------------------
9881 // trace_to_replay_handle_remapper::remap_handle
9882 //----------------------------------------------------------------------------------------------------------------------
9883 uint64_t vogl_gl_replayer::trace_to_replay_handle_remapper::remap_handle(vogl_namespace_t handle_namespace, uint64_t from_handle)
9884 {
9885     VOGL_FUNC_TRACER
9886
9887     if (!from_handle)
9888         return from_handle;
9889
9890     uint32 from_handle32 = static_cast<uint32>(from_handle);
9891
9892     switch (handle_namespace)
9893     {
9894         case VOGL_NAMESPACE_VERTEX_ARRAYS:
9895         {
9896             VOGL_ASSERT(from_handle32 == from_handle);
9897             return m_replayer.get_context_state()->m_vertex_array_objects.value(from_handle32, from_handle32);
9898         }
9899         case VOGL_NAMESPACE_TEXTURES:
9900         {
9901             VOGL_ASSERT(from_handle32 == from_handle);
9902
9903             uint32 replay_handle = from_handle32;
9904             if (m_replayer.get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(from_handle32, replay_handle))
9905                 return replay_handle;
9906             break;
9907         }
9908         case VOGL_NAMESPACE_SAMPLERS:
9909         {
9910             VOGL_ASSERT(from_handle32 == from_handle);
9911             return m_replayer.get_shared_state()->m_sampler_objects.value(from_handle32, from_handle32);
9912         }
9913         case VOGL_NAMESPACE_BUFFERS:
9914         {
9915             VOGL_ASSERT(from_handle32 == from_handle);
9916             return m_replayer.get_shared_state()->m_buffers.value(from_handle32, from_handle32);
9917         }
9918         case VOGL_NAMESPACE_SHADERS:
9919         case VOGL_NAMESPACE_PROGRAMS:
9920         {
9921             VOGL_ASSERT(from_handle32 == from_handle);
9922
9923             GLuint replay_handle = from_handle32;
9924             if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_handle_to_inv_handle(from_handle32, replay_handle))
9925                 return replay_handle;
9926             break;
9927         }
9928         case VOGL_NAMESPACE_FRAMEBUFFERS:
9929         {
9930             VOGL_ASSERT(from_handle32 == from_handle);
9931             return m_replayer.get_context_state()->m_framebuffers.value(from_handle32, from_handle32);
9932         }
9933         case VOGL_NAMESPACE_RENDER_BUFFERS:
9934         {
9935             VOGL_ASSERT(from_handle32 == from_handle);
9936
9937             GLuint replay_handle = from_handle32;
9938             if (m_replayer.get_shared_state()->m_shadow_state.m_rbos.map_handle_to_inv_handle(from_handle32, replay_handle))
9939                 return replay_handle;
9940
9941             break;
9942         }
9943         case VOGL_NAMESPACE_QUERIES:
9944         {
9945             VOGL_ASSERT(from_handle32 == from_handle);
9946             return m_replayer.get_shared_state()->m_queries.value(from_handle32, from_handle32);
9947         }
9948         case VOGL_NAMESPACE_SYNCS:
9949         {
9950             return vogl_sync_to_handle(m_replayer.get_shared_state()->m_syncs.value(from_handle, vogl_handle_to_sync(from_handle)));
9951         }
9952         case VOGL_NAMESPACE_PROGRAM_ARB:
9953         {
9954             return m_replayer.get_shared_state()->m_arb_programs.value(from_handle32, from_handle32);
9955         }
9956         default:
9957         {
9958             break;
9959         }
9960     }
9961
9962     VOGL_ASSERT_ALWAYS;
9963
9964     vogl_error_printf("%s: Failed remapping handle %" PRIu64 " in namespace %s.\n", VOGL_METHOD_NAME, from_handle, vogl_get_namespace_name(handle_namespace));
9965
9966     return from_handle;
9967 }
9968
9969 //----------------------------------------------------------------------------------------------------------------------
9970 // trace_to_replay_handle_remapper::remap_location
9971 //----------------------------------------------------------------------------------------------------------------------
9972 int32 vogl_gl_replayer::trace_to_replay_handle_remapper::remap_location(uint32 trace_program, int32 from_location)
9973 {
9974     VOGL_FUNC_TRACER
9975
9976     VOGL_NOTE_UNUSED(trace_program);
9977
9978     // restoring declares, but doesn't need to remap
9979     VOGL_ASSERT_ALWAYS;
9980
9981     return from_location;
9982 }
9983
9984 //----------------------------------------------------------------------------------------------------------------------
9985 // trace_to_replay_handle_remapper::remap_vertex_attrib_ptr
9986 //----------------------------------------------------------------------------------------------------------------------
9987 vogl_trace_ptr_value vogl_gl_replayer::trace_to_replay_handle_remapper::remap_vertex_attrib_ptr(uint index, vogl_trace_ptr_value ptr_val)
9988 {
9989     VOGL_FUNC_TRACER
9990
9991     if (!ptr_val)
9992         return ptr_val;
9993
9994     VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_vertex_attrib_data));
9995     if (!m_replayer.m_client_side_vertex_attrib_data[index].size())
9996     {
9997         m_replayer.m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
9998     }
9999
10000     return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_vertex_attrib_data[index].get_ptr());
10001 }
10002
10003 //----------------------------------------------------------------------------------------------------------------------
10004 // trace_to_replay_handle_remapper::remap_vertex_array_ptr
10005 //----------------------------------------------------------------------------------------------------------------------
10006 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)
10007 {
10008     VOGL_FUNC_TRACER
10009
10010     VOGL_ASSERT(id < VOGL_NUM_CLIENT_SIDE_ARRAY_DESCS);
10011
10012     if (!ptr_val)
10013         return ptr_val;
10014
10015     if (id == vogl_texcoord_pointer_array_id)
10016     {
10017         VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_texcoord_data));
10018
10019         if (!m_replayer.m_client_side_texcoord_data[index].size())
10020         {
10021             m_replayer.m_client_side_texcoord_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
10022         }
10023
10024         return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_texcoord_data[index].get_ptr());
10025     }
10026     else
10027     {
10028         VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_array_data));
10029
10030         if (!m_replayer.m_client_side_array_data[id].size())
10031         {
10032             m_replayer.m_client_side_array_data[id].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
10033         }
10034
10035         return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_array_data[id].get_ptr());
10036     }
10037 }
10038
10039 //----------------------------------------------------------------------------------------------------------------------
10040 // trace_to_replay_handle_remapper::declare_handle
10041 //----------------------------------------------------------------------------------------------------------------------
10042 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)
10043 {
10044     VOGL_FUNC_TRACER
10045
10046     if ((!from_handle) || (!to_handle))
10047     {
10048         VOGL_ASSERT_ALWAYS;
10049         return;
10050     }
10051
10052     uint32 from_handle32 = static_cast<uint32>(from_handle);
10053     uint32 to_handle32 = static_cast<uint32>(to_handle);
10054
10055     switch (handle_namespace)
10056     {
10057         case VOGL_NAMESPACE_VERTEX_ARRAYS:
10058         {
10059             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10060             m_replayer.get_context_state()->m_vertex_array_objects.insert(from_handle32, to_handle32);
10061             break;
10062         }
10063         case VOGL_NAMESPACE_TEXTURES:
10064         {
10065             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10066             if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.update(from_handle32, to_handle32, target))
10067                 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);
10068             break;
10069         }
10070         case VOGL_NAMESPACE_SAMPLERS:
10071         {
10072             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10073             m_replayer.get_shared_state()->m_sampler_objects.insert(from_handle32, to_handle32);
10074             break;
10075         }
10076         case VOGL_NAMESPACE_BUFFERS:
10077         {
10078             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10079             m_replayer.get_shared_state()->m_buffers.insert(from_handle32, to_handle32);
10080             m_replayer.get_shared_state()->m_buffer_targets.insert(from_handle32, target);
10081             break;
10082         }
10083         case VOGL_NAMESPACE_SHADERS:
10084         {
10085             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10086             if (!m_replayer.get_shared_state()->m_shadow_state.m_objs.insert(from_handle32, to_handle32, VOGL_SHADER_OBJECT))
10087                 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);
10088             break;
10089         }
10090         case VOGL_NAMESPACE_PROGRAMS:
10091         {
10092             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10093             if (!m_replayer.get_shared_state()->m_shadow_state.m_objs.insert(from_handle32, to_handle32, VOGL_PROGRAM_OBJECT))
10094                 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);
10095             break;
10096         }
10097         case VOGL_NAMESPACE_FRAMEBUFFERS:
10098         {
10099             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10100             m_replayer.get_context_state()->m_framebuffers.insert(from_handle32, to_handle32);
10101             break;
10102         }
10103         case VOGL_NAMESPACE_RENDER_BUFFERS:
10104         {
10105             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10106             if (!m_replayer.get_shared_state()->m_shadow_state.m_rbos.insert(from_handle32, to_handle32, GL_NONE))
10107                 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);
10108             break;
10109         }
10110         case VOGL_NAMESPACE_QUERIES:
10111         {
10112             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10113             m_replayer.get_shared_state()->m_queries.insert(from_handle32, to_handle32);
10114             m_replayer.get_shared_state()->m_query_targets[to_handle32] = target;
10115             break;
10116         }
10117         case VOGL_NAMESPACE_SYNCS:
10118         {
10119             m_replayer.get_shared_state()->m_syncs.insert(from_handle, vogl_handle_to_sync(to_handle));
10120             break;
10121         }
10122         case VOGL_NAMESPACE_PROGRAM_ARB:
10123         {
10124             m_replayer.get_shared_state()->m_arb_programs.insert(from_handle32, to_handle32);
10125             m_replayer.get_shared_state()->m_arb_program_targets.insert(from_handle32, target);
10126             break;
10127         }
10128         default:
10129         {
10130             VOGL_VERIFY(0);
10131             break;
10132         }
10133     }
10134 }
10135
10136 //----------------------------------------------------------------------------------------------------------------------
10137 // trace_to_replay_handle_remapper::delete_handle_and_object
10138 //----------------------------------------------------------------------------------------------------------------------
10139 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)
10140 {
10141     VOGL_FUNC_TRACER
10142
10143     if ((!from_handle) || (!to_handle))
10144     {
10145         VOGL_ASSERT_ALWAYS;
10146         return;
10147     }
10148
10149     uint32 from_handle32 = static_cast<uint32>(from_handle);
10150     uint32 to_handle32 = static_cast<uint32>(to_handle);
10151     VOGL_NOTE_UNUSED(to_handle32);
10152
10153     switch (handle_namespace)
10154     {
10155         case VOGL_NAMESPACE_VERTEX_ARRAYS:
10156         {
10157             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10158             m_replayer.get_context_state()->m_vertex_array_objects.erase(from_handle32);
10159             vogl_destroy_gl_object(handle_namespace, to_handle);
10160             break;
10161         }
10162         case VOGL_NAMESPACE_TEXTURES:
10163         {
10164             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10165             if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.erase(from_handle32))
10166                 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);
10167
10168             vogl_destroy_gl_object(handle_namespace, to_handle);
10169             break;
10170         }
10171         case VOGL_NAMESPACE_SAMPLERS:
10172         {
10173             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10174             m_replayer.get_shared_state()->m_sampler_objects.erase(from_handle32);
10175             vogl_destroy_gl_object(handle_namespace, to_handle);
10176             break;
10177         }
10178         case VOGL_NAMESPACE_BUFFERS:
10179         {
10180             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10181             m_replayer.get_shared_state()->m_buffers.erase(from_handle32);
10182             m_replayer.get_shared_state()->m_buffer_targets.erase(from_handle32);
10183             vogl_destroy_gl_object(handle_namespace, to_handle);
10184             break;
10185         }
10186         case VOGL_NAMESPACE_SHADERS:
10187         {
10188             m_replayer.handle_delete_shader(from_handle32);
10189             break;
10190         }
10191         case VOGL_NAMESPACE_PROGRAMS:
10192         {
10193             m_replayer.handle_delete_program(from_handle32);
10194             break;
10195         }
10196         case VOGL_NAMESPACE_FRAMEBUFFERS:
10197         {
10198             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10199             m_replayer.get_context_state()->m_framebuffers.erase(from_handle32);
10200             vogl_destroy_gl_object(handle_namespace, to_handle);
10201             break;
10202         }
10203         case VOGL_NAMESPACE_RENDER_BUFFERS:
10204         {
10205             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10206
10207             if (!m_replayer.get_shared_state()->m_shadow_state.m_rbos.erase(from_handle32))
10208                 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);
10209
10210             vogl_destroy_gl_object(handle_namespace, to_handle);
10211             break;
10212         }
10213         case VOGL_NAMESPACE_QUERIES:
10214         {
10215             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10216             m_replayer.get_shared_state()->m_queries.erase(from_handle32);
10217             vogl_destroy_gl_object(handle_namespace, to_handle);
10218             break;
10219         }
10220         case VOGL_NAMESPACE_SYNCS:
10221         {
10222             m_replayer.get_shared_state()->m_syncs.erase(from_handle);
10223             vogl_destroy_gl_object(handle_namespace, to_handle);
10224             break;
10225         }
10226         case VOGL_NAMESPACE_PROGRAM_ARB:
10227         {
10228             VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10229             m_replayer.get_shared_state()->m_arb_programs.erase(from_handle32);
10230             m_replayer.get_shared_state()->m_arb_program_targets.erase(from_handle32);
10231             vogl_destroy_gl_object(handle_namespace, to_handle);
10232             break;
10233         }
10234         default:
10235         {
10236             VOGL_VERIFY(0);
10237             break;
10238         }
10239     }
10240 }
10241
10242 //----------------------------------------------------------------------------------------------------------------------
10243 // vogl_replayer::trace_to_replay_handle_remapper::declare_location
10244 //----------------------------------------------------------------------------------------------------------------------
10245 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)
10246 {
10247     VOGL_FUNC_TRACER
10248
10249     GLuint check_replay_handle = 0;
10250     VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.map_handle_to_inv_handle(from_program_handle, check_replay_handle));
10251     VOGL_ASSERT(check_replay_handle == to_program_handle);
10252     VOGL_NOTE_UNUSED(check_replay_handle);
10253
10254     VOGL_NOTE_UNUSED(to_program_handle);
10255
10256     glsl_program_hash_map::iterator it(m_replayer.get_shared_state()->m_glsl_program_hash_map.insert(from_program_handle).first);
10257
10258     glsl_program_state &prog_state = it->second;
10259
10260     VOGL_ASSERT(!prog_state.m_uniform_locations.contains(from_location));
10261
10262     prog_state.m_uniform_locations.insert(from_location, to_location);
10263 }
10264
10265 //----------------------------------------------------------------------------------------------------------------------
10266 // vogl_gl_replayer::trace_to_replay_handle_remapper::determine_from_object_target
10267 //----------------------------------------------------------------------------------------------------------------------
10268 bool vogl_gl_replayer::trace_to_replay_handle_remapper::determine_from_object_target(vogl_namespace_t handle_namespace, uint64_t trace_handle, GLenum &target)
10269 {
10270     VOGL_FUNC_TRACER
10271
10272     target = GL_NONE;
10273
10274     uint32 handle32 = static_cast<uint32>(trace_handle);
10275
10276     switch (handle_namespace)
10277     {
10278         case VOGL_NAMESPACE_TEXTURES:
10279         {
10280             VOGL_ASSERT(handle32 == trace_handle);
10281             if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(handle32))
10282                 return false;
10283
10284             target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target(handle32);
10285             return true;
10286         }
10287         default:
10288             break;
10289     }
10290
10291     VOGL_VERIFY(0);
10292     return false;
10293 }
10294
10295 //----------------------------------------------------------------------------------------------------------------------
10296 // vogl_gl_replayer::trace_to_replay_handle_remapper::determine_to_object_target
10297 //----------------------------------------------------------------------------------------------------------------------
10298 bool vogl_gl_replayer::trace_to_replay_handle_remapper::determine_to_object_target(vogl_namespace_t handle_namespace, uint64_t replay_handle, GLenum &target)
10299 {
10300     VOGL_FUNC_TRACER
10301
10302     target = GL_NONE;
10303
10304     uint32 handle32 = static_cast<uint32>(replay_handle);
10305
10306     switch (handle_namespace)
10307     {
10308         case VOGL_NAMESPACE_TEXTURES:
10309         {
10310             VOGL_ASSERT(handle32 == replay_handle);
10311             if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(handle32))
10312                 return false;
10313
10314             target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target_inv(handle32);
10315             return true;
10316         }
10317         default:
10318             break;
10319     }
10320
10321     VOGL_VERIFY(0);
10322     return false;
10323 }
10324
10325 //----------------------------------------------------------------------------------------------------------------------
10326 // vogl_replayer::restore_objects
10327 //----------------------------------------------------------------------------------------------------------------------
10328 vogl_gl_replayer::status_t vogl_gl_replayer::restore_objects(
10329     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,
10330     vogl_const_gl_object_state_ptr_vec &objects_to_delete)
10331 {
10332     VOGL_FUNC_TRACER
10333
10334     VOGL_NOTE_UNUSED(snapshot);
10335
10336     if (m_flags & cGLReplayerVerboseMode)
10337         vogl_printf("%s: Restoring %s objects\n", VOGL_METHOD_NAME, get_gl_object_state_type_str(state_type));
10338
10339     vogl::timer tm;
10340     if (m_flags & cGLReplayerVerboseMode)
10341         tm.start();
10342
10343     const vogl_gl_object_state_ptr_vec &object_ptrs = context_state.get_objects();
10344
10345     uint n = 0;
10346
10347     for (uint i = 0; i < object_ptrs.size(); i++)
10348     {
10349         const vogl_gl_object_state *pState_obj = object_ptrs[i];
10350
10351         if (pState_obj->get_type() != state_type)
10352             continue;
10353
10354         GLuint64 restore_handle = 0;
10355         if (!pState_obj->restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper, restore_handle))
10356         {
10357             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);
10358             return cStatusHardFailure;
10359         }
10360         n++;
10361
10362         if (pState_obj->get_marked_for_deletion())
10363         {
10364             objects_to_delete.push_back(pState_obj);
10365         }
10366
10367         VOGL_ASSERT(trace_to_replay_remapper.remap_handle(pState_obj->get_handle_namespace(), pState_obj->get_snapshot_handle()) == restore_handle);
10368
10369         switch (pState_obj->get_type())
10370         {
10371             case cGLSTQuery:
10372             {
10373                 const vogl_query_state *pQuery = static_cast<const vogl_query_state *>(pState_obj);
10374
10375                 VOGL_ASSERT(restore_handle <= cUINT32_MAX);
10376                 get_shared_state()->m_query_targets[static_cast<GLuint>(restore_handle)] = pQuery->get_target();
10377
10378                 break;
10379             }
10380             case cGLSTProgram:
10381             {
10382                 const vogl_program_state *pProg = static_cast<const vogl_program_state *>(pState_obj);
10383
10384                 if (pProg->has_link_time_snapshot())
10385                 {
10386                     vogl_program_state link_snapshot(*pProg->get_link_time_snapshot());
10387                     if (!link_snapshot.remap_handles(trace_to_replay_remapper))
10388                     {
10389                         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);
10390                     }
10391                     else
10392                     {
10393                         get_shared_state()->m_shadow_state.m_linked_programs.add_snapshot(static_cast<uint32>(restore_handle), link_snapshot);
10394                     }
10395                 }
10396
10397                 if (m_flags & cGLReplayerVerboseMode)
10398                 {
10399                     if ((n & 255) == 255)
10400                         vogl_printf("%s: Restored %u programs\n", VOGL_METHOD_NAME, n);
10401                 }
10402
10403                 break;
10404             }
10405             case cGLSTBuffer:
10406             {
10407                 const vogl_buffer_state *pBuf = static_cast<const vogl_buffer_state *>(pState_obj);
10408
10409                 // Check if the buffer was mapped during the snapshot, if so remap it and record the ptr in the replayer's context shadow.
10410                 if (pBuf->get_is_mapped())
10411                 {
10412                     vogl_mapped_buffer_desc map_desc;
10413                     map_desc.m_buffer = static_cast<GLuint>(restore_handle);
10414                     map_desc.m_target = pBuf->get_target();
10415                     map_desc.m_offset = pBuf->get_map_ofs();
10416                     map_desc.m_length = pBuf->get_map_size();
10417                     map_desc.m_access = pBuf->get_map_access();
10418                     map_desc.m_range = pBuf->get_is_map_range();
10419
10420                     GLuint prev_handle = vogl_get_bound_gl_buffer(map_desc.m_target);
10421
10422                     GL_ENTRYPOINT(glBindBuffer)(map_desc.m_target, map_desc.m_buffer);
10423                     VOGL_CHECK_GL_ERROR;
10424
10425                     if (map_desc.m_range)
10426                     {
10427                         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);
10428                         VOGL_CHECK_GL_ERROR;
10429                     }
10430                     else
10431                     {
10432                         map_desc.m_pPtr = GL_ENTRYPOINT(glMapBuffer)(map_desc.m_target, map_desc.m_access);
10433                         VOGL_CHECK_GL_ERROR;
10434                     }
10435
10436                     GL_ENTRYPOINT(glBindBuffer)(map_desc.m_target, prev_handle);
10437                     VOGL_CHECK_GL_ERROR;
10438
10439                     vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
10440                     mapped_bufs.push_back(map_desc);
10441                 }
10442
10443                 break;
10444             }
10445             default:
10446                 break;
10447         }
10448     }
10449
10450     if (m_flags & cGLReplayerVerboseMode)
10451     {
10452         tm.stop();
10453         vogl_printf("%s: Restore took %f secs\n", VOGL_METHOD_NAME, tm.get_elapsed_secs());
10454
10455         vogl_printf("%s: Finished restoring %u %s objects\n", VOGL_METHOD_NAME, n, get_gl_object_state_type_str(state_type));
10456     }
10457
10458     return cStatusOK;
10459 }
10460
10461 //----------------------------------------------------------------------------------------------------------------------
10462 // vogl_xfont_cache
10463 //----------------------------------------------------------------------------------------------------------------------
10464 class vogl_xfont_cache
10465 {
10466     VOGL_NO_COPY_OR_ASSIGNMENT_OP(vogl_xfont_cache);
10467
10468 public:
10469     vogl_xfont_cache(Display *dpy)
10470         : m_dpy(dpy)
10471     {
10472         VOGL_FUNC_TRACER
10473     }
10474
10475     ~vogl_xfont_cache()
10476     {
10477         VOGL_FUNC_TRACER
10478
10479         clear();
10480     }
10481
10482     void clear()
10483     {
10484         VOGL_FUNC_TRACER
10485
10486         for (xfont_map::iterator it = m_xfonts.begin(); it != m_xfonts.end(); ++it)
10487             XFreeFont(m_dpy, it->second);
10488         m_xfonts.clear();
10489     }
10490
10491     XFontStruct *get_or_create(const char *pName)
10492     {
10493         VOGL_FUNC_TRACER
10494
10495         XFontStruct **ppXFont = m_xfonts.find_value(pName);
10496         if (ppXFont)
10497             return *ppXFont;
10498
10499         XFontStruct *pXFont = XLoadQueryFont(m_dpy, pName);
10500         if (pXFont)
10501             m_xfonts.insert(pName, pXFont);
10502
10503         return pXFont;
10504     }
10505
10506 private:
10507     Display *m_dpy;
10508
10509     typedef vogl::map<dynamic_string, XFontStruct *> xfont_map;
10510     xfont_map m_xfonts;
10511 };
10512
10513 //----------------------------------------------------------------------------------------------------------------------
10514 // vogl_replayer::restore_display_lists
10515 //----------------------------------------------------------------------------------------------------------------------
10516 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)
10517 {
10518     VOGL_FUNC_TRACER
10519
10520     VOGL_NOTE_UNUSED(trace_to_replay_remapper);
10521     VOGL_NOTE_UNUSED(snapshot);
10522
10523     VOGL_ASSERT(m_cur_trace_context);
10524
10525     check_gl_error();
10526
10527     const vogl_display_list_state &disp_lists = context_snapshot.get_display_list_state();
10528
10529     if (!disp_lists.size())
10530         return cStatusOK;
10531
10532     vogl_message_printf("%s: Recreating %u display lists\n", VOGL_METHOD_NAME, disp_lists.get_display_list_map().size());
10533
10534     vogl_xfont_cache xfont_cache(m_pWindow->get_display());
10535
10536     const vogl_display_list_map &disp_list_map = disp_lists.get_display_list_map();
10537
10538     for (vogl_display_list_map::const_iterator it = disp_list_map.begin(); it != disp_list_map.end(); ++it)
10539     {
10540         GLuint trace_handle = it->first;
10541         const vogl_display_list &disp_list = it->second;
10542
10543         if (!trace_handle)
10544         {
10545             VOGL_ASSERT_ALWAYS;
10546             continue;
10547         }
10548
10549         GLuint replay_handle = GL_ENTRYPOINT(glGenLists)(1);
10550         if (check_gl_error() || !replay_handle)
10551             goto handle_failure;
10552
10553         if (disp_list.is_valid())
10554         {
10555             if (disp_list.is_xfont())
10556             {
10557                 XFontStruct *pXFont = xfont_cache.get_or_create(disp_list.get_xfont_name().get_ptr());
10558                 if (!pXFont)
10559                 {
10560                     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);
10561                 }
10562                 else
10563                 {
10564                     GL_ENTRYPOINT(glXUseXFont)(pXFont->fid, disp_list.get_xfont_glyph(), 1, replay_handle);
10565                 }
10566             }
10567             else
10568             {
10569                 GL_ENTRYPOINT(glNewList)(replay_handle, GL_COMPILE);
10570
10571                 if (check_gl_error() || !replay_handle)
10572                 {
10573                     GL_ENTRYPOINT(glDeleteLists)(replay_handle, 1);
10574                     check_gl_error();
10575
10576                     goto handle_failure;
10577                 }
10578
10579                 const vogl_trace_packet_array &packets = disp_list.get_packets();
10580
10581                 for (uint packet_index = 0; packet_index < packets.size(); packet_index++)
10582                 {
10583                     if (packets.get_packet_type(packet_index) != cTSPTGLEntrypoint)
10584                     {
10585                         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);
10586                         continue;
10587                     }
10588
10589                     const uint8_vec &packet_buf = packets.get_packet_buf(packet_index);
10590
10591                     if (!m_temp2_gl_packet.deserialize(packet_buf, true))
10592                     {
10593                         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);
10594                         continue;
10595                     }
10596
10597                     vogl_trace_gl_entrypoint_packet &gl_entrypoint_packet = m_temp2_gl_packet.get_entrypoint_packet();
10598
10599                     gl_entrypoint_packet.m_context_handle = m_cur_trace_context;
10600
10601                     if (m_flags & cGLReplayerDebugMode)
10602                         dump_trace_gl_packet_debug_info(gl_entrypoint_packet);
10603
10604                     int64_t prev_parsed_call_counter = m_last_parsed_call_counter;
10605                     int64_t prev_processed_call_counter = m_last_processed_call_counter;
10606                     m_last_parsed_call_counter = gl_entrypoint_packet.m_call_counter;
10607                     m_last_processed_call_counter = gl_entrypoint_packet.m_call_counter;
10608                     bool prev_at_frame_boundary = m_at_frame_boundary;
10609
10610                     const vogl_trace_packet *pPrev_gl_packet = m_pCur_gl_packet;
10611
10612                     m_pCur_gl_packet = &m_temp2_gl_packet;
10613
10614                     vogl_gl_replayer::status_t status = process_gl_entrypoint_packet_internal(m_temp2_gl_packet);
10615
10616                     m_pCur_gl_packet = pPrev_gl_packet;
10617
10618                     m_last_parsed_call_counter = prev_parsed_call_counter;
10619                     m_last_processed_call_counter = prev_processed_call_counter;
10620                     m_at_frame_boundary = prev_at_frame_boundary;
10621
10622                     if (status != cStatusOK)
10623                     {
10624                         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);
10625                         continue;
10626                     }
10627                 }
10628
10629                 // TODO: Set context state because we're currently generating a display list!
10630                 if (disp_list.is_generating())
10631                 {
10632                     VOGL_ASSERT_ALWAYS;
10633                 }
10634
10635                 GL_ENTRYPOINT(glEndList)();
10636                 check_gl_error();
10637             }
10638         }
10639
10640         get_shared_state()->m_lists.insert(trace_handle, replay_handle);
10641
10642         if (!get_shared_state()->m_shadow_state.m_display_lists.define_list(trace_handle, replay_handle, disp_list))
10643         {
10644             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);
10645         }
10646     }
10647
10648     check_gl_error();
10649
10650     vogl_message_printf("%s: Done recreating display lists\n", VOGL_METHOD_NAME);
10651
10652     return cStatusOK;
10653
10654 handle_failure:
10655     return cStatusHardFailure;
10656 }
10657
10658 //----------------------------------------------------------------------------------------------------------------------
10659 // vogl_replayer::restore_general_state
10660 //----------------------------------------------------------------------------------------------------------------------
10661 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)
10662 {
10663     VOGL_FUNC_TRACER
10664
10665     VOGL_NOTE_UNUSED(snapshot);
10666
10667     vogl_general_context_state::vogl_persistent_restore_state persistent_restore_state;
10668     persistent_restore_state.m_pSelect_buffer = &m_pCur_context_state->m_select_buffer;
10669
10670     if (!context_snapshot.get_general_state().restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper, persistent_restore_state))
10671         return cStatusHardFailure;
10672
10673     if (!m_pCur_context_state->m_context_info.is_core_profile())
10674     {
10675         if (context_snapshot.get_texenv_state().is_valid())
10676         {
10677             if (!context_snapshot.get_texenv_state().restore(m_pCur_context_state->m_context_info))
10678                 return cStatusHardFailure;
10679         }
10680
10681         if (context_snapshot.get_material_state().is_valid())
10682         {
10683             if (!context_snapshot.get_material_state().restore(m_pCur_context_state->m_context_info))
10684                 return cStatusHardFailure;
10685         }
10686
10687         if (context_snapshot.get_light_state().is_valid())
10688         {
10689             if (!context_snapshot.get_light_state().restore(m_pCur_context_state->m_context_info))
10690                 return cStatusHardFailure;
10691         }
10692
10693         if (context_snapshot.get_matrix_state().is_valid())
10694         {
10695             if (!context_snapshot.get_matrix_state().restore(m_pCur_context_state->m_context_info))
10696                 return cStatusHardFailure;
10697         }
10698
10699         if (context_snapshot.get_polygon_stipple_state().is_valid())
10700         {
10701             if (!context_snapshot.get_polygon_stipple_state().restore(m_pCur_context_state->m_context_info))
10702                 return cStatusHardFailure;
10703         }
10704
10705         if (context_snapshot.get_arb_program_environment_state().is_valid())
10706         {
10707             if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_vertex_program"))
10708             {
10709                 if (!context_snapshot.get_arb_program_environment_state().restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper))
10710                     return cStatusHardFailure;
10711             }
10712             else
10713             {
10714                 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);
10715             }
10716         }
10717     }
10718
10719     if (context_snapshot.get_current_vertex_attrib_state().is_valid())
10720     {
10721         if (!context_snapshot.get_current_vertex_attrib_state().restore(m_pCur_context_state->m_context_info))
10722             return cStatusHardFailure;
10723     }
10724
10725     return cStatusOK;
10726 }
10727
10728 //----------------------------------------------------------------------------------------------------------------------
10729 // vogl_replayer::validate_program_and_shader_handle_tables
10730 //----------------------------------------------------------------------------------------------------------------------
10731 bool vogl_gl_replayer::validate_program_and_shader_handle_tables()
10732 {
10733     VOGL_FUNC_TRACER
10734
10735     if (!m_pCur_context_state)
10736         return true;
10737
10738     if (!get_shared_state()->m_shadow_state.m_objs.check())
10739         vogl_error_printf("%s: Object handle tracker failed validation!\n", VOGL_METHOD_NAME);
10740
10741     uint_vec replay_handles;
10742     get_shared_state()->m_shadow_state.m_objs.get_inv_handles(replay_handles);
10743
10744     for (uint i = 0; i < replay_handles.size(); i++)
10745     {
10746         GLuint replay_handle = replay_handles[i];
10747         GLuint trace_handle = replay_handle;
10748         bool map_succeeded = get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle, trace_handle);
10749         VOGL_ASSERT(map_succeeded);
10750         VOGL_NOTE_UNUSED(map_succeeded);
10751
10752         GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle);
10753         VOGL_ASSERT(target == get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle));
10754
10755         if (target == VOGL_PROGRAM_OBJECT)
10756         {
10757             if (!GL_ENTRYPOINT(glIsProgram)(replay_handle))
10758             {
10759                 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);
10760             }
10761
10762             if (!get_shared_state()->m_glsl_program_hash_map.contains(trace_handle))
10763             {
10764                 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);
10765             }
10766         }
10767         else if (target == VOGL_SHADER_OBJECT)
10768         {
10769             if (!GL_ENTRYPOINT(glIsShader)(replay_handle))
10770             {
10771                 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);
10772             }
10773         }
10774         else
10775         {
10776             VOGL_ASSERT_ALWAYS;
10777         }
10778     }
10779
10780     return true;
10781 }
10782
10783 //----------------------------------------------------------------------------------------------------------------------
10784 // vogl_replayer::validate_textures
10785 //----------------------------------------------------------------------------------------------------------------------
10786 bool vogl_gl_replayer::validate_textures()
10787 {
10788     VOGL_FUNC_TRACER
10789
10790     if (!m_pCur_context_state)
10791         return true;
10792
10793     if (!get_shared_state()->m_shadow_state.m_textures.check())
10794         vogl_error_printf("%s: Texture handle tracker failed validation!\n", VOGL_METHOD_NAME);
10795
10796     for (uint replay_handle = 1; replay_handle <= 0xFFFFU; replay_handle++)
10797     {
10798         bool is_tex = GL_ENTRYPOINT(glIsTexture)(replay_handle) != 0;
10799
10800         bool found_in_shadow = get_shared_state()->m_shadow_state.m_textures.contains_inv(replay_handle);
10801
10802         if (!is_tex)
10803         {
10804             if (found_in_shadow)
10805             {
10806                 GLuint trace_handle = 0;
10807                 get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_handle, trace_handle);
10808                 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);
10809             }
10810         }
10811         else
10812         {
10813             if (!found_in_shadow)
10814             {
10815                 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);
10816             }
10817         }
10818     }
10819
10820     return true;
10821 }
10822
10823 //----------------------------------------------------------------------------------------------------------------------
10824 // vogl_replayer::update_context_shadows
10825 //----------------------------------------------------------------------------------------------------------------------
10826 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)
10827 {
10828     VOGL_FUNC_TRACER
10829
10830     VOGL_NOTE_UNUSED(snapshot);
10831     VOGL_NOTE_UNUSED(context_snapshot);
10832     VOGL_NOTE_UNUSED(trace_to_replay_remapper);
10833
10834     check_gl_error();
10835
10836     // Make sure shadow is good
10837     GLint actual_current_replay_program = 0;
10838     GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &actual_current_replay_program);
10839     check_gl_error();
10840
10841     m_pCur_context_state->m_cur_replay_program = actual_current_replay_program;
10842     if (!actual_current_replay_program)
10843         m_pCur_context_state->m_cur_trace_program = 0;
10844     else
10845     {
10846         GLuint trace_handle = actual_current_replay_program;
10847         if (!get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(actual_current_replay_program, trace_handle))
10848         {
10849             process_entrypoint_error("%s: Failed finding restored GL shader %u in program/shader object handle hashmap\n", VOGL_METHOD_NAME, actual_current_replay_program);
10850
10851             m_pCur_context_state->m_cur_replay_program = 0;
10852             m_pCur_context_state->m_cur_trace_program = 0;
10853         }
10854         else
10855         {
10856             m_pCur_context_state->m_cur_trace_program = trace_handle;
10857         }
10858     }
10859
10860     check_program_binding_shadow();
10861
10862     return cStatusOK;
10863 }
10864
10865 //----------------------------------------------------------------------------------------------------------------------
10866 // vogl_replayer::handle_marked_for_deleted_objects
10867 //----------------------------------------------------------------------------------------------------------------------
10868 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)
10869 {
10870     VOGL_FUNC_TRACER
10871
10872     if (m_flags & cGLReplayerVerboseMode)
10873     {
10874         vogl_debug_printf("%s: %u program/shader objects where marked as deleted\n", VOGL_METHOD_NAME, objects_to_delete.size());
10875     }
10876
10877     for (uint i = 0; i < objects_to_delete.size(); i++)
10878     {
10879         const vogl_gl_object_state *pState_obj = objects_to_delete[i];
10880
10881         GLuint64 trace_handle = pState_obj->get_snapshot_handle();
10882         GLuint64 restore_handle = trace_to_replay_remapper.remap_handle(pState_obj->get_handle_namespace(), pState_obj->get_snapshot_handle());
10883
10884         if (m_flags & cGLReplayerVerboseMode)
10885         {
10886             // This should be a rare/exception case so let's try to be a little paranoid.
10887             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,
10888                              get_gl_object_state_type_str(pState_obj->get_type()), (uint64_t)trace_handle, (uint64_t)restore_handle);
10889         }
10890
10891         GLboolean object_is_still_a_name = true;
10892
10893         switch (pState_obj->get_type())
10894         {
10895             case cGLSTProgram:
10896             {
10897                 handle_delete_program(static_cast<GLuint>(trace_handle));
10898
10899                 object_is_still_a_name = GL_ENTRYPOINT(glIsProgram)(static_cast<GLuint>(restore_handle));
10900
10901                 break;
10902             }
10903             case cGLSTShader:
10904             {
10905                 handle_delete_shader(static_cast<GLuint>(trace_handle));
10906
10907                 object_is_still_a_name = GL_ENTRYPOINT(glIsShader)(static_cast<GLuint>(restore_handle));
10908
10909                 break;
10910             }
10911             default:
10912             {
10913                 VOGL_ASSERT_ALWAYS;
10914                 break;
10915             }
10916         }
10917
10918         // "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."
10919         // Same for shaders.
10920         if (!object_is_still_a_name)
10921         {
10922             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,
10923                              get_gl_object_state_type_str(pState_obj->get_type()), (uint64_t)trace_handle, (uint64_t)restore_handle);
10924         }
10925     }
10926 }
10927
10928 //----------------------------------------------------------------------------------------------------------------------
10929 // vogl_replayer::begin_applying_snapshot
10930 // Takes ownership (even on errors) when delete_snapshot_after_applying is true.
10931 //----------------------------------------------------------------------------------------------------------------------
10932 vogl_gl_replayer::status_t vogl_gl_replayer::begin_applying_snapshot(const vogl_gl_state_snapshot *pSnapshot, bool delete_snapshot_after_applying)
10933 {
10934     VOGL_FUNC_TRACER
10935
10936     if (!pSnapshot->is_valid())
10937     {
10938         if (delete_snapshot_after_applying)
10939             vogl_delete(const_cast<vogl_gl_state_snapshot *>(pSnapshot));
10940
10941         return cStatusHardFailure;
10942     }
10943
10944     reset_state();
10945
10946     m_pPending_snapshot = pSnapshot;
10947     m_delete_pending_snapshot_after_applying = delete_snapshot_after_applying;
10948
10949     m_frame_index = pSnapshot->get_frame_index();
10950     m_last_parsed_call_counter = pSnapshot->get_gl_call_counter();
10951     m_last_processed_call_counter = pSnapshot->get_gl_call_counter();
10952     m_at_frame_boundary = false;
10953
10954     if (!(m_flags & cGLReplayerLockWindowDimensions))
10955     {
10956         return trigger_pending_window_resize(pSnapshot->get_window_width(), pSnapshot->get_window_height());
10957     }
10958
10959     return process_applying_pending_snapshot();
10960 }
10961
10962 //----------------------------------------------------------------------------------------------------------------------
10963 // vogl_replayer::restore_context
10964 //----------------------------------------------------------------------------------------------------------------------
10965 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)
10966 {
10967     VOGL_FUNC_TRACER
10968
10969     VOGL_NOTE_UNUSED(trace_to_replay_remapper);
10970     VOGL_NOTE_UNUSED(snapshot);
10971
10972     // TODO: This always creates with attribs, also need to support plain glXCreateContext()
10973
10974     Display *dpy = m_pWindow->get_display();
10975     GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
10976
10977     vogl_trace_context_ptr_value trace_share_context = context_snapshot.get_context_desc().get_trace_share_context();
10978
10979     GLXContext replay_share_context = remap_context(trace_share_context);
10980     if ((trace_share_context) && (!replay_share_context))
10981     {
10982         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));
10983         return cStatusHardFailure;
10984     }
10985
10986     GLboolean direct = context_snapshot.get_context_desc().get_direct();
10987
10988     vogl_trace_context_ptr_value trace_context = context_snapshot.get_context_desc().get_trace_context();
10989
10990     status_t status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct,
10991                                              context_snapshot.get_context_desc().get_attribs().get_vec().get_ptr(),
10992                                              context_snapshot.get_context_desc().get_attribs().get_vec().size(), true);
10993     if (status != cStatusOK)
10994     {
10995         vogl_error_printf("%s: Failed creating new context\n", VOGL_METHOD_NAME);
10996         return status;
10997     }
10998
10999     // Has this context ever been made current?
11000     if (context_snapshot.get_context_info().is_valid())
11001     {
11002         context_state *pContext_state = get_trace_context_state(trace_context);
11003         if (!pContext_state)
11004         {
11005             vogl_error_printf("%s: Failed finding replay context current\n", VOGL_METHOD_NAME);
11006             return cStatusHardFailure;
11007         }
11008
11009         GLXContext replay_context = pContext_state->m_replay_context;
11010         if (!replay_context)
11011         {
11012             vogl_error_printf("%s: Failed finding replay context current\n", VOGL_METHOD_NAME);
11013             return cStatusHardFailure;
11014         }
11015
11016         GLXDrawable drawable = m_pWindow->get_xwindow();
11017
11018         Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
11019         if (!result)
11020         {
11021             vogl_error_printf("%s: Failed making context current\n", VOGL_METHOD_NAME);
11022             return cStatusHardFailure;
11023         }
11024
11025         m_cur_trace_context = trace_context;
11026         m_cur_replay_context = replay_context;
11027         m_pCur_context_state = pContext_state;
11028
11029         if (!handle_context_made_current())
11030             return cStatusHardFailure;
11031     }
11032
11033     return cStatusOK;
11034 }
11035
11036 //----------------------------------------------------------------------------------------------------------------------
11037 // vogl_replayer::process_applying_pending_snapshot
11038 //----------------------------------------------------------------------------------------------------------------------
11039 vogl_gl_replayer::status_t vogl_gl_replayer::process_applying_pending_snapshot()
11040 {
11041     VOGL_FUNC_TRACER
11042
11043     if (!m_pPending_snapshot)
11044         return cStatusOK;
11045
11046     timed_scope ts(VOGL_METHOD_NAME);
11047
11048     const vogl_gl_state_snapshot &snapshot = *m_pPending_snapshot;
11049
11050     trace_to_replay_handle_remapper trace_to_replay_remapper(*this);
11051
11052     m_frame_index = snapshot.get_frame_index();
11053     m_last_parsed_call_counter = snapshot.get_gl_call_counter();
11054     m_last_processed_call_counter = snapshot.get_gl_call_counter();
11055     m_at_frame_boundary = snapshot.get_at_frame_boundary();
11056
11057     // Ensure the client side array bufs are large enough (we don't care about the actual ptr values).
11058     for (uint i = 0; i < snapshot.get_client_side_vertex_attrib_ptrs().size(); i++)
11059         m_client_side_vertex_attrib_data[i].resize(snapshot.get_client_side_vertex_attrib_ptrs()[i].m_size);
11060
11061     for (uint i = 0; i < snapshot.get_client_side_array_ptrs().size(); i++)
11062         m_client_side_array_data[i].resize(snapshot.get_client_side_array_ptrs()[i].m_size);
11063
11064     for (uint i = 0; i < snapshot.get_client_side_texcoord_ptrs().size(); i++)
11065         m_client_side_texcoord_data[i].resize(snapshot.get_client_side_texcoord_ptrs()[i].m_size);
11066
11067     const vogl_context_snapshot_ptr_vec &context_ptrs = snapshot.get_contexts();
11068
11069     vogl_context_snapshot_ptr_vec restore_context_ptrs(snapshot.get_contexts());
11070     vogl::vector<vogl_const_gl_object_state_ptr_vec> objects_to_delete_vec(context_ptrs.size());
11071
11072     status_t status = cStatusOK;
11073     uint total_contexts_restored = 0;
11074     bool restored_default_framebuffer = false;
11075
11076     for (;;)
11077     {
11078         uint num_contexts_restored_in_this_pass = 0;
11079
11080         for (uint context_index = 0; context_index < restore_context_ptrs.size(); context_index++)
11081         {
11082             if (!restore_context_ptrs[context_index])
11083                 continue;
11084
11085             const vogl_context_snapshot &context_state = *restore_context_ptrs[context_index];
11086
11087             if (context_state.get_context_desc().get_trace_share_context())
11088             {
11089                 // Don't restore this context if its sharelist context hasn't been restored yet
11090                 if (!remap_context(context_state.get_context_desc().get_trace_share_context()))
11091                     continue;
11092             }
11093
11094             status = restore_context(trace_to_replay_remapper, snapshot, context_state);
11095             if (status != cStatusOK)
11096                 goto handle_error;
11097
11098             // Has this context ever been made current?
11099             if (context_state.get_context_info().is_valid())
11100             {
11101                 // 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!)
11102                 const vogl_gl_object_state_type s_object_type_restore_order[] = { cGLSTBuffer, cGLSTSampler, cGLSTQuery, cGLSTRenderbuffer, cGLSTTexture, cGLSTFramebuffer, cGLSTVertexArray, cGLSTShader, cGLSTProgram, cGLSTSync, cGLSTARBProgram };
11103                 VOGL_ASSUME(VOGL_ARRAY_SIZE(s_object_type_restore_order) == (cGLSTTotalTypes - 1));
11104
11105                 if (m_flags & cGLReplayerLowLevelDebugMode)
11106                 {
11107                     if (!validate_textures())
11108                         vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11109                 }
11110
11111                 vogl_const_gl_object_state_ptr_vec &objects_to_delete = objects_to_delete_vec[context_index];
11112
11113                 for (uint i = 0; i < VOGL_ARRAY_SIZE(s_object_type_restore_order); i++)
11114                 {
11115                     status = restore_objects(trace_to_replay_remapper, snapshot, context_state, s_object_type_restore_order[i], objects_to_delete);
11116                     if (status != cStatusOK)
11117                         goto handle_error;
11118
11119                     if (m_flags & cGLReplayerLowLevelDebugMode)
11120                     {
11121                         if (!validate_program_and_shader_handle_tables())
11122                             vogl_error_printf("%s: Program/shader handle table validation failed!\n", VOGL_METHOD_NAME);
11123
11124                         if (!validate_textures())
11125                             vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11126                     }
11127                 }
11128
11129                 if (m_flags & cGLReplayerLowLevelDebugMode)
11130                 {
11131                     if (!validate_textures())
11132                         vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11133                 }
11134
11135                 status = restore_display_lists(trace_to_replay_remapper, snapshot, context_state);
11136                 if (status != cStatusOK)
11137                     goto handle_error;
11138
11139                 // Restore default framebuffer
11140                 if ((!restored_default_framebuffer) && (snapshot.get_default_framebuffer().is_valid()))
11141                 {
11142                     restored_default_framebuffer = true;
11143
11144                     if (!snapshot.get_default_framebuffer().restore(m_pCur_context_state->m_context_info))
11145                     {
11146                         vogl_warning_printf("%s: Failed restoring default framebuffer!\n", VOGL_METHOD_NAME);
11147                     }
11148                 }
11149
11150                 // Beware: restore_general_state() will bind a bunch of stuff from the trace!
11151                 status = restore_general_state(trace_to_replay_remapper, snapshot, context_state);
11152                 if (status != cStatusOK)
11153                     goto handle_error;
11154
11155                 status = update_context_shadows(trace_to_replay_remapper, snapshot, context_state);
11156                 if (status != cStatusOK)
11157                     goto handle_error;
11158
11159                 if (m_flags & cGLReplayerLowLevelDebugMode)
11160                 {
11161                     if (!validate_program_and_shader_handle_tables())
11162                         vogl_error_printf("%s: Program/shader handle table validation failed!\n", VOGL_METHOD_NAME);
11163
11164                     if (!validate_textures())
11165                         vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11166                 }
11167             }
11168
11169             num_contexts_restored_in_this_pass++;
11170
11171             total_contexts_restored++;
11172
11173             restore_context_ptrs[context_index] = NULL;
11174         }
11175
11176         if (!num_contexts_restored_in_this_pass)
11177             break;
11178     }
11179
11180     if (total_contexts_restored != snapshot.get_contexts().size())
11181     {
11182         vogl_error_printf("%s: Failed satisfying sharelist dependency during context restoration\n", VOGL_METHOD_NAME);
11183         goto handle_error;
11184     }
11185
11186     for (uint context_index = 0; context_index < context_ptrs.size(); context_index++)
11187     {
11188         const vogl_context_snapshot &context_state = *context_ptrs[context_index];
11189
11190         if (!context_state.get_context_info().is_valid())
11191             continue;
11192
11193         status_t status = switch_contexts(context_state.get_context_desc().get_trace_context());
11194         if (status != cStatusOK)
11195         {
11196             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()));
11197             goto handle_error;
11198         }
11199
11200         vogl_const_gl_object_state_ptr_vec &objects_to_delete = objects_to_delete_vec[context_index];
11201
11202         handle_marked_for_deleted_objects(objects_to_delete, trace_to_replay_remapper);
11203     }
11204
11205     destroy_pending_snapshot();
11206
11207     return cStatusOK;
11208
11209 handle_error:
11210
11211     reset_state();
11212
11213     return status;
11214 }
11215
11216 //----------------------------------------------------------------------------------------------------------------------
11217 // vogl_gl_replayer::write_trim_file_internal
11218 //----------------------------------------------------------------------------------------------------------------------
11219 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)
11220 {
11221     // Open the output trace
11222     // 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.
11223     const vogl_ctypes &trace_gl_ctypes = get_trace_gl_ctypes();
11224
11225     vogl_trace_packet trace_packet(&trace_gl_ctypes);
11226
11227     // TODO: This seems like WAY too much work! Move the snapshot to the beginning of the trace, in the header!
11228     bool found_state_snapshot = false;
11229     dynamic_string binary_snapshot_id, text_snapshot_id;
11230
11231     bool is_at_start_of_trace = false;
11232     VOGL_NOTE_UNUSED(is_at_start_of_trace);
11233
11234     int demarcation_packet_index = -1;
11235     for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11236     {
11237         const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11238         if (packet_type != cTSPTGLEntrypoint)
11239             continue;
11240
11241         const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11242
11243         const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(packet_index);
11244         if (pGL_packet->m_entrypoint_id != VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
11245             continue;
11246
11247         if (!trace_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
11248         {
11249             console::error("%s: Failed parsing glInternalTraceCommandRAD packet\n", VOGL_FUNCTION_NAME);
11250             return false;
11251         }
11252
11253         GLuint cmd = trace_packet.get_param_value<GLuint>(0);
11254         if (cmd == cITCRDemarcation)
11255         {
11256             is_at_start_of_trace = true;
11257             demarcation_packet_index = packet_index;
11258         }
11259         else if (cmd == cITCRKeyValueMap)
11260         {
11261             key_value_map &kvm = trace_packet.get_key_value_map();
11262
11263             dynamic_string cmd_type(kvm.get_string("command_type"));
11264
11265             if (cmd_type == "state_snapshot")
11266             {
11267                 found_state_snapshot = true;
11268
11269                 text_snapshot_id = kvm.get_string("id");
11270                 binary_snapshot_id = kvm.get_string("binary_id");
11271             }
11272         }
11273     }
11274
11275     vogl_trace_file_writer trace_writer(&trace_gl_ctypes);
11276     if (!trace_writer.open(trim_filename.get_ptr(), NULL, true, false, m_trace_pointer_size_in_bytes))
11277     {
11278         console::error("%s: Failed creating trimmed trace file \"%s\"!\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11279         return false;
11280     }
11281
11282     if (found_state_snapshot)
11283     {
11284         // Copy over the source trace's archive (it contains the snapshot, along with any files it refers to).
11285         if (trace_reader.get_archive_blob_manager().is_initialized())
11286         {
11287             dynamic_string_array blob_files(trace_reader.get_archive_blob_manager().enumerate());
11288             for (uint i = 0; i < blob_files.size(); i++)
11289             {
11290                 if ((blob_files[i].is_empty()) || (blob_files[i] == VOGL_TRACE_ARCHIVE_FRAME_FILE_OFFSETS_FILENAME))
11291                     continue;
11292
11293                 vogl_message_printf("Adding blob file %s to output trace archive\n", blob_files[i].get_ptr());
11294
11295                 if (!trace_writer.get_trace_archive()->copy_file(trace_reader.get_archive_blob_manager(), blob_files[i], blob_files[i]).has_content())
11296                 {
11297                     vogl_error_printf("%s: Failed copying blob data for file \"%s\" to output trace archive!\n", VOGL_FUNCTION_NAME, blob_files[i].get_ptr());
11298                     return false;
11299                 }
11300             }
11301         }
11302     }
11303     else
11304     {
11305         // Copy over the source trace's backtrace map, machine info, etc. files.
11306         if (trace_reader.get_archive_blob_manager().is_initialized())
11307         {
11308             // compiler_info.json
11309             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);
11310             // machine_info.json
11311             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);
11312             // backtrace_map_syms.json
11313             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);
11314             // backtrace_map_addrs.json
11315             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);
11316         }
11317
11318         vogl_unique_ptr<vogl_gl_state_snapshot> pTrim_snapshot(snapshot_state(&trim_packets, optimize_snapshot));
11319
11320         if (!pTrim_snapshot.get())
11321         {
11322             console::error("%s: Failed creating replayer GL snapshot!\n", VOGL_FUNCTION_NAME);
11323             return false;
11324         }
11325
11326         pTrim_snapshot->set_frame_index(0);
11327
11328         json_document doc;
11329         if (!pTrim_snapshot->serialize(*doc.get_root(), *trace_writer.get_trace_archive(), &trace_gl_ctypes))
11330         {
11331             console::error("%s: Failed serializing GL state snapshot!\n", VOGL_FUNCTION_NAME);
11332             trace_writer.close();
11333             file_utils::delete_file(trim_filename.get_ptr());
11334             return false;
11335         }
11336
11337         vogl::vector<char> snapshot_data;
11338         doc.serialize(snapshot_data, true, 0, false);
11339
11340         uint8_vec binary_snapshot_data;
11341         doc.binary_serialize(binary_snapshot_data);
11342
11343         pTrim_snapshot.reset();
11344
11345         // Write the state_snapshot file to the trace archive
11346         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));
11347         if (snapshot_id.is_empty())
11348         {
11349             console::error("%s: Failed adding GL snapshot file to output blob manager!\n", VOGL_FUNCTION_NAME);
11350             trace_writer.close();
11351             file_utils::delete_file(trim_filename.get_ptr());
11352             return false;
11353         }
11354
11355         if (pSnapshot_id)
11356             *pSnapshot_id = snapshot_id;
11357
11358         snapshot_data.clear();
11359
11360         // Write the binary_state_snapshot file to the trace archive
11361         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));
11362         if (binary_snapshot_id.is_empty())
11363         {
11364             console::error("%s: Failed adding binary GL snapshot file to output blob manager!\n", VOGL_FUNCTION_NAME);
11365             trace_writer.close();
11366             file_utils::delete_file(trim_filename.get_ptr());
11367             return false;
11368         }
11369
11370         binary_snapshot_data.clear();
11371
11372         key_value_map snapshot_key_value_map;
11373         snapshot_key_value_map.insert("command_type", "state_snapshot");
11374         snapshot_key_value_map.insert("id", snapshot_id);
11375         snapshot_key_value_map.insert("binary_id", binary_snapshot_id);
11376
11377         dynamic_stream snapshot_stream(0);
11378         if (!vogl_write_glInternalTraceCommandRAD(snapshot_stream, &trace_gl_ctypes, cITCRKeyValueMap, sizeof(snapshot_key_value_map), reinterpret_cast<const GLubyte *>(&snapshot_key_value_map)))
11379         {
11380             console::error("%s: Failed serializing snapshot packet!\n", VOGL_FUNCTION_NAME);
11381             trace_writer.close();
11382             file_utils::delete_file(trim_filename.get_ptr());
11383             return false;
11384         }
11385
11386         if (demarcation_packet_index >= 0)
11387         {
11388             trim_packets.insert(demarcation_packet_index, snapshot_stream.get_buf());
11389             demarcation_packet_index++;
11390         }
11391         else
11392         {
11393             dynamic_stream demarcation_stream(0);
11394             vogl_write_glInternalTraceCommandRAD(demarcation_stream, &trace_gl_ctypes, cITCRDemarcation, 0, NULL);
11395
11396             // Screw the ctypes packet, it's only used for debugging right now anyway.
11397             trim_packets.insert(0, snapshot_stream.get_buf());
11398             trim_packets.insert(1, demarcation_stream.get_buf());
11399         }
11400     }
11401
11402     for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11403     {
11404         const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11405
11406         const bool is_swap = trim_packets.is_swap_buffers_packet(packet_index);
11407
11408         const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11409         if (packet_type == cTSPTEOF)
11410             break;
11411         else if (packet_type != cTSPTGLEntrypoint)
11412         {
11413             VOGL_ASSERT_ALWAYS;
11414         }
11415
11416         if (!trace_writer.write_packet(packet_buf.get_ptr(), packet_buf.size(), is_swap))
11417         {
11418             console::error("%s: Failed writing trace packet to output trace file \"%s\"!\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11419             trace_writer.close();
11420             file_utils::delete_file(trim_filename.get_ptr());
11421             return false;
11422         }
11423     }
11424
11425     bool success = trace_writer.close();
11426     if (!success)
11427         console::error("%s: Failed closing wrote trim trace file \"%s\"\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11428     else
11429         console::message("%s: Successfully wrote trim trace file \"%s\"\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11430
11431     return success;
11432 }
11433
11434 //----------------------------------------------------------------------------------------------------------------------
11435 // vogl_gl_replayer::write_trim_file
11436 //----------------------------------------------------------------------------------------------------------------------
11437 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)
11438 {
11439     VOGL_FUNC_TRACER
11440
11441     if (!m_is_valid)
11442     {
11443         console::error("%s: Trace is not open\n", VOGL_METHOD_NAME);
11444         return false;
11445     }
11446
11447     bool from_start_of_frame = (flags & cWriteTrimFileFromStartOfFrame) != 0;
11448
11449     if ((!from_start_of_frame) || (!trim_len))
11450         flags &= ~cWriteTrimFileOptimizeSnapshot;
11451
11452     const uint trim_frame = static_cast<uint>(get_frame_index());
11453     const int64_t trim_call_counter = get_last_parsed_call_counter();
11454
11455     // Read the desired packets from the source trace file
11456     vogl_trace_packet_array trim_packets;
11457
11458     if ((trim_len) || (!trim_frame))
11459     {
11460         console::message("%s: Reading trim packets from source trace file\n", VOGL_FUNCTION_NAME);
11461
11462         uint frames_to_read = trim_len;
11463         if ((from_start_of_frame) && (!trim_frame) && (!trim_len))
11464             frames_to_read = 1;
11465
11466         uint actual_trim_len = 0;
11467         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);
11468         if (read_packets_status == vogl_trace_file_reader::cFailed)
11469         {
11470             console::error("%s: Failed reading source trace file packets beginning at frame %u!\n", VOGL_FUNCTION_NAME, trim_frame);
11471             return false;
11472         }
11473
11474         if (actual_trim_len != frames_to_read)
11475         {
11476             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);
11477         }
11478
11479         if (from_start_of_frame)
11480         {
11481             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);
11482
11483             if ((!trim_frame) && (!trim_len))
11484             {
11485                 // 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.
11486                 // TODO: Most of this will go away once we move the state snapshot into the trace archive.
11487
11488                 vogl_trace_packet_array new_trim_packets;
11489
11490                 vogl_trace_packet trace_packet(&get_trace_gl_ctypes());
11491
11492                 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11493                 {
11494                     const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11495                     if (packet_type != cTSPTGLEntrypoint)
11496                         break;
11497
11498                     const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11499
11500                     const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(packet_index);
11501                     if (pGL_packet->m_entrypoint_id != VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
11502                         break;
11503
11504                     if (!trace_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
11505                     {
11506                         console::error("%s: Failed parsing glInternalTraceCommandRAD packet\n", VOGL_FUNCTION_NAME);
11507                         return false;
11508                     }
11509
11510                     GLuint cmd = trace_packet.get_param_value<GLuint>(0);
11511
11512                     new_trim_packets.push_back(packet_buf);
11513
11514                     if (cmd == cITCRDemarcation)
11515                         break;
11516                 }
11517
11518                 trim_packets.swap(new_trim_packets);
11519             }
11520         }
11521         else if (trim_call_counter >= 0)
11522         {
11523             uint orig_num_packets = trim_packets.size();
11524             uint total_erased_packets = 0;
11525
11526             // Remove any calls before the current one.
11527             for (int64_t packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11528             {
11529                 if (trim_packets.get_packet_type(static_cast<uint>(packet_index)) != cTSPTGLEntrypoint)
11530                     continue;
11531
11532                 const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(static_cast<uint>(packet_index));
11533
11534                 if (static_cast<int64_t>(pGL_packet->m_call_counter) <= trim_call_counter)
11535                 {
11536                     trim_packets.erase(static_cast<uint>(packet_index));
11537                     packet_index--;
11538
11539                     total_erased_packets++;
11540                 }
11541             }
11542
11543             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());
11544         }
11545     }
11546
11547     if (!write_trim_file_internal(trim_packets, trim_filename, trace_reader, (flags & cWriteTrimFileOptimizeSnapshot) != 0, pSnapshot_id))
11548     {
11549         console::warning("%s: Trim file write failed, deleting invalid trim trace file %s\n", VOGL_METHOD_NAME, trim_filename.get_ptr());
11550
11551         file_utils::delete_file(trim_filename.get_ptr());
11552         return false;
11553     }
11554
11555     return true;
11556 }