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