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