bool vogleditor_traceReplayer::replay(vogl_trace_file_reader* m_pTraceReader, vogleditor_apiCallTreeItem* pRootItem, vogleditor_gl_state_snapshot** ppNewSnapshot, uint64_t apiCallNumber, bool endlessMode) { // reset to beginnning of trace file. m_pTraceReader->seek_to_frame(0); int initial_window_width = 1280; int initial_window_height = 1024; if (!m_window.open(initial_window_width, initial_window_height)) { vogl_error_printf("%s: Failed opening GL replayer window!\n", VOGL_FUNCTION_NAME); return false; } uint replayer_flags = cGLReplayerForceDebugContexts; if (!m_pTraceReplayer->init(replayer_flags, &m_window, m_pTraceReader->get_sof_packet(), m_pTraceReader->get_multi_blob_manager())) { vogl_error_printf("%s: Failed initializing GL replayer\n", VOGL_FUNCTION_NAME); m_window.close(); return false; } XSelectInput(m_window.get_display(), m_window.get_xwindow(), EnterWindowMask | LeaveWindowMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ExposureMask | FocusChangeMask | KeyPressMask | KeyReleaseMask | PropertyChangeMask | StructureNotifyMask | KeymapStateMask); m_wmDeleteMessage = XInternAtom(m_window.get_display(), "WM_DELETE_WINDOW", False); XSetWMProtocols(m_window.get_display(), m_window.get_xwindow(), &m_wmDeleteMessage, 1); timer tm; tm.start(); bool bStatus = true; for ( ; ; ) { if (process_x_events() == false) { break; } if (pRootItem->childCount() > 0) { vogleditor_apiCallTreeItem* pFirstFrame = pRootItem->child(0); // if the first snapshot has not been edited, then restore it here, otherwise it will get restored in the recursive call below. if (pFirstFrame->has_snapshot() && !pFirstFrame->get_snapshot()->is_edited()) { bStatus = applying_snapshot_and_process_resize(pFirstFrame->get_snapshot()->get_snapshot()); } if (bStatus) { // replay each API call. bStatus = recursive_replay_apicallTreeItem(pRootItem, ppNewSnapshot, apiCallNumber); if (bStatus == false) { vogl_error_printf("%s: Replay ending abruptly at frame index %u, global api call %" PRIu64 "\n", VOGL_FUNCTION_NAME, m_pTraceReplayer->get_frame_index(), m_pTraceReplayer->get_last_processed_call_counter()); break; } else { vogl_message_printf("%s: At trace EOF, frame index %u\n", VOGL_FUNCTION_NAME, m_pTraceReplayer->get_frame_index()); if (!endlessMode) { break; } } } else { break; } } } m_pTraceReplayer->deinit(); m_window.close(); return bStatus; }
vogleditor_tracereplayer_result vogleditor_traceReplayer::replay(vogl_trace_file_reader* m_pTraceReader, vogleditor_apiCallTreeItem* pRootItem, vogleditor_gl_state_snapshot** ppNewSnapshot, uint64_t apiCallNumber, bool endlessMode) { // reset to beginnning of trace file. m_pTraceReader->seek_to_frame(0); int initial_window_width = 1280; int initial_window_height = 1024; if (!m_window.open(initial_window_width, initial_window_height)) { vogleditor_output_error("Failed opening GL replayer window!"); return VOGLEDITOR_TRR_ERROR; } uint replayer_flags = cGLReplayerForceDebugContexts; if (!m_pTraceReplayer->init(replayer_flags, &m_window, m_pTraceReader->get_sof_packet(), m_pTraceReader->get_multi_blob_manager())) { vogleditor_output_error("Failed initializing GL replayer!"); m_window.close(); return VOGLEDITOR_TRR_ERROR; } XSelectInput(m_window.get_display(), m_window.get_xwindow(), EnterWindowMask | LeaveWindowMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ExposureMask | FocusChangeMask | KeyPressMask | KeyReleaseMask | PropertyChangeMask | StructureNotifyMask | KeymapStateMask); m_wmDeleteMessage = XInternAtom(m_window.get_display(), "WM_DELETE_WINDOW", False); XSetWMProtocols(m_window.get_display(), m_window.get_xwindow(), &m_wmDeleteMessage, 1); timer tm; tm.start(); vogleditor_tracereplayer_result result = VOGLEDITOR_TRR_SUCCESS; for ( ; ; ) { if (process_x_events() == false) { result = VOGLEDITOR_TRR_USER_EXIT; break; } if (pRootItem->childCount() > 0) { vogleditor_apiCallTreeItem* pFirstFrame = pRootItem->child(0); bool bStatus = true; // if the first snapshot has not been edited, then restore it here, otherwise it will get restored in the recursive call below. if (pFirstFrame->has_snapshot() && !pFirstFrame->get_snapshot()->is_edited()) { bStatus = applying_snapshot_and_process_resize(pFirstFrame->get_snapshot()->get_snapshot()); } if (bStatus) { // replay each API call. result = recursive_replay_apicallTreeItem(pRootItem, ppNewSnapshot, apiCallNumber); if (result == VOGLEDITOR_TRR_ERROR) { QString msg = QString("Replay ending abruptly at frame index %1, global api call %2").arg(m_pTraceReplayer->get_frame_index()).arg(m_pTraceReplayer->get_last_processed_call_counter()); vogleditor_output_error(msg.toStdString().c_str()); break; } else if (result == VOGLEDITOR_TRR_SNAPSHOT_SUCCESS) { break; } else if (result == VOGLEDITOR_TRR_USER_EXIT) { vogleditor_output_message("Replay stopped"); break; } else { QString msg = QString("At trace EOF, frame index %1").arg(m_pTraceReplayer->get_frame_index()); vogleditor_output_message(msg.toStdString().c_str()); if (!endlessMode) { break; } } } else { break; } } } m_pTraceReplayer->deinit(); m_window.close(); return result; }
bool vogleditor_traceReplayer::recursive_replay_apicallTreeItem(vogleditor_apiCallTreeItem* pItem, vogleditor_gl_state_snapshot** ppNewSnapshot, uint64_t apiCallNumber) { bool bStatus = true; vogleditor_apiCallItem* pApiCall = pItem->apiCallItem(); if (pApiCall != NULL) { vogl_trace_packet* pTrace_packet = pApiCall->getTracePacket(); vogl_gl_replayer::status_t status = vogl_gl_replayer::cStatusOK; // See if a window resize or snapshot is pending. If a window resize is pending we must delay a while and pump X events until the window is resized. while (m_pTraceReplayer->get_has_pending_window_resize() || m_pTraceReplayer->get_pending_apply_snapshot()) { // Pump X events in case the window is resizing bStatus = process_x_events(); if (bStatus) { status = m_pTraceReplayer->process_pending_window_resize(); if (status != vogl_gl_replayer::cStatusResizeWindow) break; } else { // most likely the window wants to close, so let's return return false; } } // replay the trace packet if (status == vogl_gl_replayer::cStatusOK) status = m_pTraceReplayer->process_next_packet(*pTrace_packet); // if that was successful, check to see if a state snapshot is needed if ((status != vogl_gl_replayer::cStatusHardFailure) && (status != vogl_gl_replayer::cStatusAtEOF)) { if (ppNewSnapshot != NULL) { // get the snapshot after the selected api call if ((!*ppNewSnapshot) && (m_pTraceReplayer->get_last_processed_call_counter() == static_cast<int64_t>(apiCallNumber))) { vogl_printf("Taking snapshot on API call # %" PRIu64 "\n", apiCallNumber); vogl_gl_state_snapshot* pNewSnapshot = m_pTraceReplayer->snapshot_state(); if (pNewSnapshot == NULL) { vogl_error_printf("Taking new snapshot failed!\n"); } else { vogl_printf("Taking snapshot succeeded\n"); *ppNewSnapshot = vogl_new(vogleditor_gl_state_snapshot, pNewSnapshot); if (*ppNewSnapshot == NULL) { vogl_error_printf("Allocating memory for snapshot container failed!\n"); vogl_delete(pNewSnapshot); } } bStatus = false; } } } else { // replaying the trace packet failed, set as error vogl_error_printf("%s: unable to replay gl entrypoint at call %" PRIu64 "\n", VOGL_FUNCTION_NAME, pTrace_packet->get_call_counter()); bStatus = false; } } if (bStatus && pItem->has_snapshot() && pItem->get_snapshot()->is_edited() && pItem->get_snapshot()->is_valid()) { bStatus = applying_snapshot_and_process_resize(pItem->get_snapshot()->get_snapshot()); } if (bStatus) { for (int i = 0; i < pItem->childCount(); i++) { bStatus = recursive_replay_apicallTreeItem(pItem->child(i), ppNewSnapshot, apiCallNumber); if (!bStatus) break; } } return bStatus; }
vogleditor_tracereplayer_result vogleditor_traceReplayer::recursive_replay_apicallTreeItem(vogleditor_apiCallTreeItem* pItem, vogleditor_gl_state_snapshot** ppNewSnapshot, uint64_t apiCallNumber) { vogleditor_tracereplayer_result result = VOGLEDITOR_TRR_SUCCESS; vogleditor_apiCallItem* pApiCall = pItem->apiCallItem(); if (pApiCall != NULL) { vogl_trace_packet* pTrace_packet = pApiCall->getTracePacket(); vogl_gl_replayer::status_t status = vogl_gl_replayer::cStatusOK; // See if a window resize or snapshot is pending. If a window resize is pending we must delay a while and pump X events until the window is resized. while (m_pTraceReplayer->get_has_pending_window_resize() || m_pTraceReplayer->get_pending_apply_snapshot()) { // Pump X events in case the window is resizing if (process_x_events()) { status = m_pTraceReplayer->process_pending_window_resize(); if (status != vogl_gl_replayer::cStatusResizeWindow) break; } else { // most likely the window wants to close, so let's return return VOGLEDITOR_TRR_USER_EXIT; } } // replay the trace packet if (status == vogl_gl_replayer::cStatusOK) status = m_pTraceReplayer->process_next_packet(*pTrace_packet); // if that was successful, check to see if a state snapshot is needed if ((status != vogl_gl_replayer::cStatusHardFailure) && (status != vogl_gl_replayer::cStatusAtEOF)) { if (ppNewSnapshot != NULL) { // get the snapshot after the selected api call if ((!*ppNewSnapshot) && (m_pTraceReplayer->get_last_processed_call_counter() == static_cast<int64_t>(apiCallNumber))) { dynamic_string info; vogleditor_output_message(info.format("Taking snapshot on API call # %" PRIu64 "...", apiCallNumber).c_str()); vogl_gl_state_snapshot* pNewSnapshot = m_pTraceReplayer->snapshot_state(); if (pNewSnapshot == NULL) { result = VOGLEDITOR_TRR_ERROR; vogleditor_output_error("... snapshot failed!"); } else { result = VOGLEDITOR_TRR_SNAPSHOT_SUCCESS; vogleditor_output_message("... snapshot succeeded!\n"); *ppNewSnapshot = vogl_new(vogleditor_gl_state_snapshot, pNewSnapshot); if (*ppNewSnapshot == NULL) { result = VOGLEDITOR_TRR_ERROR; vogleditor_output_error("Allocating memory for snapshot container failed!"); vogl_delete(pNewSnapshot); } } } } } else { // replaying the trace packet failed, set as error result = VOGLEDITOR_TRR_ERROR; dynamic_string info; vogleditor_output_error(info.format("Unable to replay gl entrypoint at call %" PRIu64, pTrace_packet->get_call_counter()).c_str()); } } if (result == VOGLEDITOR_TRR_SUCCESS && pItem->has_snapshot() && pItem->get_snapshot()->is_edited() && pItem->get_snapshot()->is_valid()) { if(applying_snapshot_and_process_resize(pItem->get_snapshot()->get_snapshot())) { result = VOGLEDITOR_TRR_SUCCESS; } } if (result == VOGLEDITOR_TRR_SUCCESS) { for (int i = 0; i < pItem->childCount(); i++) { result = recursive_replay_apicallTreeItem(pItem->child(i), ppNewSnapshot, apiCallNumber); if (result != VOGLEDITOR_TRR_SUCCESS) break; // Pump X events in case the window is resizing if (process_x_events() == false) { // most likely the window wants to close, so let's return return VOGLEDITOR_TRR_USER_EXIT; } } } return result; }