glvdebug: Move QReplayWorker into a separate thread.
authorPeter Lohrmann <peterl@valvesoftware.com>
Thu, 26 Feb 2015 18:51:36 +0000 (10:51 -0800)
committerPeter Lohrmann <peterl@valvesoftware.com>
Fri, 27 Feb 2015 01:06:58 +0000 (17:06 -0800)
* In order to achieve this correctly, the QController could not inherit from the QReplayWorker; instead the controller now has a worker object. The QReplayWidget puts the worker on a separate thread.
* Any interaction between the QReplayWorker and the rest of the UI must be done through Qt's signals and slots, which knows how to pass data between threads.
* Performance of replaying within the UI is now on-par with replaying using glvreplay64 from the command line, based on the cube demo. Increasing the validation level will slow down the replay preformance (as expected), and printing of validation messages will also slow down replay performance (as expected).

13 files changed:
glave-generate.py
tools/glave/src/glv_extensions/glvdebug_xgl/CMakeLists.txt
tools/glave/src/glv_extensions/glvdebug_xgl/glvdebug_xgl_qcontroller.cpp
tools/glave/src/glv_extensions/glvdebug_xgl/glvdebug_xgl_qcontroller.h
tools/glave/src/glvdebug/CMakeLists.txt
tools/glave/src/glvdebug/glvdebug.cpp
tools/glave/src/glvdebug/glvdebug.h
tools/glave/src/glvdebug/glvdebug_QReplayWidget.h
tools/glave/src/glvdebug/glvdebug_QReplayWorker.cpp [new file with mode: 0644]
tools/glave/src/glvdebug/glvdebug_QReplayWorker.h
tools/glave/src/glvdebug/glvdebug_output.cpp
tools/glave/src/glvdebug/glvdebug_output.h
tools/glave/src/glvdebug/glvdebug_view.h

index bb99ea0..94de7d1 100755 (executable)
@@ -2328,6 +2328,7 @@ class Subcommand(object):
         rs_body.append('{')
         rs_body.append('    g_pReplaySettings = pReplaySettings;')
         rs_body.append('    m_display = new xglDisplay();')
+        rs_body.append('    m_pDSDump = NULL;')
         rs_body.append('    if (g_pReplaySettings && g_pReplaySettings->screenshotList) {')
         rs_body.append('        process_screenshot_list(g_pReplaySettings->screenshotList);')
         rs_body.append('    }')
index df2919a..30d6be1 100644 (file)
@@ -46,6 +46,7 @@ set(SRC_LIST
     glvdebug_xgl_settings.cpp
     glvdebug_xgl_qcontroller.cpp
     glvdebug_xgl_qfile_model.cpp
+    ${SRC_DIR}/glvdebug/glvdebug_QReplayWorker.cpp
     ${SRC_DIR}/glvreplay/glvreplay_factory.cpp
 )
 
index 9f3f373..c47df14 100644 (file)
@@ -40,7 +40,9 @@ extern "C" {
 #include "glvreplay_seq.h"
 
 glvdebug_xgl_QController::glvdebug_xgl_QController()
-    : m_pSvgDiagram(NULL),
+    : m_pView(NULL),
+      m_pTraceFileInfo(NULL),
+      m_pSvgDiagram(NULL),
       m_pReplayWidget(NULL),
       m_pTraceFileModel(NULL)
 {
@@ -71,11 +73,11 @@ bool glvdebug_xgl_QController::LoadTraceFile(glvdebug_trace_file_info* pTraceFil
     setView(pView);
     m_pTraceFileInfo = pTraceFileInfo;
 
-    m_pReplayWidget = new glvdebug_QReplayWidget(this);
+    m_pReplayWidget = new glvdebug_QReplayWidget(&m_replayWorker);
     if (m_pReplayWidget != NULL)
     {
         // load available replayers
-        if (!load_replayers(pTraceFileInfo, m_pReplayWidget->GetReplayWindow(),
+        if (!m_replayWorker.load_replayers(pTraceFileInfo, m_pReplayWidget->GetReplayWindow(),
             g_xglDebugSettings.replay_window_width,
             g_xglDebugSettings.replay_window_height,
             g_xglDebugSettings.separate_replay_window))
@@ -88,11 +90,15 @@ bool glvdebug_xgl_QController::LoadTraceFile(glvdebug_trace_file_info* pTraceFil
         {
             m_pView->add_custom_state_viewer(m_pReplayWidget, "Replayer", true);
             m_pReplayWidget->setEnabled(true);
-            connect(m_pReplayWidget, SIGNAL(ReplayStarted()), this, SLOT(onReplayStarted()));
-            connect(m_pReplayWidget, SIGNAL(ReplayPaused(uint64_t)), this, SLOT(onReplayPaused(uint64_t)));
-            connect(m_pReplayWidget, SIGNAL(ReplayContinued()), this, SLOT(onReplayContinued()));
-            connect(m_pReplayWidget, SIGNAL(ReplayStopped(uint64_t)), this, SLOT(onReplayStopped(uint64_t)));
-            connect(m_pReplayWidget, SIGNAL(ReplayFinished()), this, SLOT(onReplayFinished()));
+            connect(m_pReplayWidget, SIGNAL(ReplayStarted()), this, SLOT(onReplayStarted()), Qt::QueuedConnection);
+            connect(m_pReplayWidget, SIGNAL(ReplayPaused(uint64_t)), this, SLOT(onReplayPaused(uint64_t)), Qt::QueuedConnection);
+            connect(m_pReplayWidget, SIGNAL(ReplayContinued()), this, SLOT(onReplayContinued()), Qt::QueuedConnection);
+            connect(m_pReplayWidget, SIGNAL(ReplayStopped(uint64_t)), this, SLOT(onReplayStopped(uint64_t)), Qt::QueuedConnection);
+            connect(m_pReplayWidget, SIGNAL(ReplayFinished(uint64_t)), this, SLOT(onReplayFinished(uint64_t)), Qt::QueuedConnection);
+
+            connect(m_pReplayWidget, SIGNAL(OutputMessage(const QString&)), this, SLOT(OnOutputMessage(const QString&)), Qt::QueuedConnection);
+            connect(m_pReplayWidget, SIGNAL(OutputError(const QString&)), this, SLOT(OnOutputError(const QString&)), Qt::QueuedConnection);
+            connect(m_pReplayWidget, SIGNAL(OutputWarning(const QString&)), this, SLOT(OnOutputWarning(const QString&)), Qt::QueuedConnection);
         }
     }
 
@@ -143,12 +149,20 @@ void glvdebug_xgl_QController::setStateWidgetsEnabled(bool bEnabled)
 
 void glvdebug_xgl_QController::onReplayStarted()
 {
+    m_pView->output_message(QString("Replay Started"));
     deleteStateDumps();
     setStateWidgetsEnabled(false);
 }
 
 void glvdebug_xgl_QController::onReplayPaused(uint64_t packetIndex)
 {
+    m_pView->output_message(QString("Replay Paused at packet index %1").arg(packetIndex));
+    m_pView->on_replay_state_changed(false);
+
+    // When paused, the replay will 'continue' from the last packet,
+    // so select that call to indicate to the user where the pause occured.
+    m_pView->select_call_at_packet_index(packetIndex);
+
     if(m_pSvgDiagram == NULL)
     {
         m_pSvgDiagram = new glvdebug_qsvgviewer;
@@ -161,10 +175,13 @@ void glvdebug_xgl_QController::onReplayPaused(uint64_t packetIndex)
 
     if(m_pSvgDiagram != NULL)
     {
-        if (m_pReplayers[GLV_TID_XGL] != NULL) {
+        glv_replay::glv_trace_packet_replay_library* pXglReplayer = m_replayWorker.getReplayer(GLV_TID_XGL);
+        if (pXglReplayer != NULL)
+        {
             int err;
-            err = m_pReplayers[GLV_TID_XGL]->Dump();
-            if (err) {
+            err = pXglReplayer->Dump();
+            if (err)
+            {
                 glv_LogWarn("Couldn't Dump SVG data\n");
             }
         }
@@ -199,56 +216,56 @@ void glvdebug_xgl_QController::onReplayPaused(uint64_t packetIndex)
 
 void glvdebug_xgl_QController::onReplayContinued()
 {
+    m_pView->output_message(QString("Replay Continued"));
     deleteStateDumps();
     setStateWidgetsEnabled(false);
 }
 
 void glvdebug_xgl_QController::onReplayStopped(uint64_t packetIndex)
 {
-}
+    m_pView->output_message(QString("Replay Stopped at packet index %1").arg(packetIndex));
+    m_pView->on_replay_state_changed(false);
 
-void glvdebug_xgl_QController::onReplayFinished()
-{
+    // Stopping the replay means that it will 'play' or 'step' from the beginning,
+    // so select the first packet index to indicate to the user what stopping replay does.
+    m_pView->select_call_at_packet_index(0);
 }
 
-BOOL glvdebug_xgl_QController::PrintReplayInfoMsgs()
+void glvdebug_xgl_QController::onReplayFinished(uint64_t packetIndex)
 {
-    return g_xglDebugSettings.printReplayInfoMsgs;
-}
+    m_pView->output_message(QString("Replay Finished"));
+    m_pView->on_replay_state_changed(false);
 
-BOOL glvdebug_xgl_QController::PrintReplayWarningMsgs()
-{
-    return g_xglDebugSettings.printReplayWarningMsgs;
-}
-
-BOOL glvdebug_xgl_QController::PrintReplayErrorMsgs()
-{
-    return g_xglDebugSettings.printReplayErrorMsgs;
+    // The replay has completed, so highlight the final packet index.
+    m_pView->select_call_at_packet_index(packetIndex);
 }
 
-BOOL glvdebug_xgl_QController::PauseOnReplayInfoMsg()
+void glvdebug_xgl_QController::OnOutputMessage(const QString& msg)
 {
-    return g_xglDebugSettings.pauseOnReplayInfo;
+    m_pView->output_message(msg);
 }
 
-BOOL glvdebug_xgl_QController::PauseOnReplayWarningMsg()
+void glvdebug_xgl_QController::OnOutputError(const QString& msg)
 {
-    return g_xglDebugSettings.pauseOnReplayWarning;
+    m_pView->output_error(msg);
 }
 
-BOOL glvdebug_xgl_QController::PauseOnReplayErrorMsg()
+void glvdebug_xgl_QController::OnOutputWarning(const QString& msg)
 {
-    return g_xglDebugSettings.pauseOnReplayError;
+    m_pView->output_warning(msg);
 }
 
 void glvdebug_xgl_QController::onSettingsUpdated(glv_SettingGroup *pGroups, unsigned int numGroups)
 {
     glv_SettingGroup_Apply_Overrides(&g_xglDebugSettingGroup, pGroups, numGroups);
 
-    if (m_pReplayWidget != NULL)
-    {
-        m_pReplayWidget->OnSettingsUpdated(pGroups, numGroups);
-    }
+    m_replayWorker.setPrintReplayMessages(g_xglDebugSettings.printReplayInfoMsgs,
+                                          g_xglDebugSettings.printReplayWarningMsgs,
+                                          g_xglDebugSettings.printReplayErrorMsgs);
+
+    m_replayWorker.setPauseOnReplayMessages(g_xglDebugSettings.pauseOnReplayInfo,
+                                            g_xglDebugSettings.pauseOnReplayWarning,
+                                            g_xglDebugSettings.pauseOnReplayError);
 
     updateCallTreeBasedOnSettings();
 }
@@ -279,17 +296,6 @@ void glvdebug_xgl_QController::UnloadTraceFile(void)
         m_pSvgDiagram = NULL;
     }
 
-    // Clean up replayers
-    if (m_pReplayers != NULL)
-    {
-        for (int i = 0; i < GLV_MAX_TRACER_ID_ARRAY_SIZE; i++)
-        {
-            if (m_pReplayers[i] != NULL)
-            {
-                m_pReplayers[i]->Deinitialize();
-                m_replayerFactory.Destroy(&m_pReplayers[i]);
-            }
-        }
-    }
+    m_replayWorker.unloadReplayers();
 }
 
index 703247b..31aa9be 100644 (file)
@@ -35,7 +35,7 @@
 #include <QLabel>
 #include <QScrollArea>
 
-class glvdebug_xgl_QController : public glvdebug_QReplayWorker
+class glvdebug_xgl_QController : public QObject
 {
     Q_OBJECT
 public:
@@ -46,12 +46,11 @@ public:
     bool LoadTraceFile(glvdebug_trace_file_info* pTraceFileInfo, glvdebug_view* pView);
     void UnloadTraceFile(void);
 
-    virtual BOOL PrintReplayInfoMsgs();
-    virtual BOOL PrintReplayWarningMsgs();
-    virtual BOOL PrintReplayErrorMsgs();
-    virtual BOOL PauseOnReplayInfoMsg();
-    virtual BOOL PauseOnReplayWarningMsg();
-    virtual BOOL PauseOnReplayErrorMsg();
+    void setView(glvdebug_view* pView)
+    {
+        m_pView = pView;
+        m_replayWorker.setView(pView);
+    }
 
     void onSettingsUpdated(glv_SettingGroup *pGroups, unsigned int numGroups);
 
@@ -62,9 +61,16 @@ protected slots:
     void onReplayPaused(uint64_t packetIndex);
     void onReplayContinued();
     void onReplayStopped(uint64_t packetIndex);
-    void onReplayFinished();
+    void onReplayFinished(uint64_t packetIndex);
+
+    void OnOutputMessage(const QString& msg);
+    void OnOutputError(const QString& msg);
+    void OnOutputWarning(const QString &msg);
 
 private:
+    glvdebug_view* m_pView;
+    glvdebug_trace_file_info* m_pTraceFileInfo;
+    glvdebug_QReplayWorker m_replayWorker;
     glvdebug_qsvgviewer* m_pSvgDiagram;
     glvdebug_QReplayWidget* m_pReplayWidget;
     glvdebug_xgl_QFileModel* m_pTraceFileModel;
index e5fe034..f98df81 100755 (executable)
@@ -41,6 +41,7 @@ set(SRC_LIST
     glvdebug_qgeneratetracedialog.cpp\r
     glvdebug_qsettingsdialog.cpp\r
     glvdebug_qtimelineview.cpp\r
+    glvdebug_QReplayWorker.cpp\r
     glvdebug_controller_factory.cpp\r
     ${SRC_DIR}/glvreplay/glvreplay_seq.cpp\r
     ${SRC_DIR}/glvreplay/glvreplay_factory.cpp\r
index be6f14a..865e27d 100755 (executable)
@@ -306,25 +306,27 @@ unsigned long long glvdebug::get_current_packet_index()
 \r
 void glvdebug::reset_view()\r
 {\r
-    while (ui->stateTabWidget->count() > 0)\r
+    int count = ui->stateTabWidget->count();\r
+    while (count > 0)\r
     {\r
         delete ui->stateTabWidget->widget(0);\r
+        count = ui->stateTabWidget->count();\r
     }\r
 }\r
 \r
-void glvdebug::output_message(QString message, bool bRefresh)\r
+void glvdebug::output_message(QString message)\r
 {\r
-    glvdebug_output_message(message.toStdString().c_str(), bRefresh);\r
+    gs_OUTPUT.message(message);\r
 }\r
 \r
-void glvdebug::output_warning(QString message, bool bRefresh)\r
+void glvdebug::output_warning(QString message)\r
 {\r
-    glvdebug_output_warning(message.toStdString().c_str(), bRefresh);\r
+    gs_OUTPUT.warning(message);\r
 }\r
 \r
-void glvdebug::output_error(QString message, bool bRefresh)\r
+void glvdebug::output_error(QString message)\r
 {\r
-    glvdebug_output_error(message.toStdString().c_str(), bRefresh);\r
+    gs_OUTPUT.error(message);\r
 }\r
 \r
 void glvdebug::add_setting_group(glv_SettingGroup* pGroup)\r
index 8c21bc4..0dda86d 100755 (executable)
@@ -75,9 +75,9 @@ public:
 \r
     // Implementation of glvdebug_view\r
     virtual void reset_view();\r
-    virtual void output_message(QString message, bool bRefresh = true);\r
-    virtual void output_warning(QString message, bool bRefresh = true);\r
-    virtual void output_error(QString message, bool bRefresh = true);\r
+    virtual void output_message(QString message);\r
+    virtual void output_warning(QString message);\r
+    virtual void output_error(QString message);\r
     virtual void add_setting_group(glv_SettingGroup* pGroup);\r
     virtual unsigned int get_global_settings(glv_SettingGroup** ppGroups);\r
     virtual int add_custom_state_viewer(QWidget* pWidget, const QString& title, bool bBringToFront = false);\r
index 613f051..da532f0 100755 (executable)
@@ -30,7 +30,7 @@
 #include <QToolBar>\r
 #include <QToolButton>\r
 #include <QVBoxLayout>\r
-\r
+#include <QDebug>\r
 #include "glvdebug_QReplayWorker.h"\r
 \r
 class glvdebug_QReplayWidget : public QWidget\r
@@ -80,36 +80,33 @@ public:
         m_pReplayWindow = new QWidget(this);\r
         pLayout->addWidget(m_pReplayWindow);\r
 \r
-        connect(this, SIGNAL(PlayButtonClicked()), m_pWorker, SLOT(StartReplay()));\r
-        connect(this, SIGNAL(StepButtonClicked()), m_pWorker, SLOT(StepReplay()));\r
-        connect(this, SIGNAL(PauseButtonClicked()), m_pWorker, SLOT(PauseReplay()));\r
-        connect(this, SIGNAL(ContinueButtonClicked()), m_pWorker, SLOT(ContinueReplay()));\r
-        connect(this, SIGNAL(StopButtonClicked()), m_pWorker, SLOT(StopReplay()));\r
-\r
-//        qRegisterMetaType<uint64_t>("uint64_t");\r
+        connect(this, SIGNAL(PlayButtonClicked()), m_pWorker, SLOT(StartReplay()), Qt::QueuedConnection);\r
+        connect(this, SIGNAL(StepButtonClicked()), m_pWorker, SLOT(StepReplay()), Qt::DirectConnection);\r
+        connect(this, SIGNAL(PauseButtonClicked()), m_pWorker, SLOT(PauseReplay()), Qt::DirectConnection);\r
+        connect(this, SIGNAL(ContinueButtonClicked()), m_pWorker, SLOT(ContinueReplay()), Qt::QueuedConnection);\r
+        connect(this, SIGNAL(StopButtonClicked()), m_pWorker, SLOT(StopReplay()), Qt::DirectConnection);\r
 \r
         // connect worker signals to widget actions\r
-        connect(m_pWorker, SIGNAL(ReplayStarted()), this, SLOT(slotReplayStarted()));\r
-        connect(m_pWorker, SIGNAL(ReplayPaused(uint64_t)), this, SLOT(slotReplayPaused(uint64_t)));\r
-        connect(m_pWorker, SIGNAL(ReplayContinued()), this, SLOT(slotReplayContinued()));\r
-        connect(m_pWorker, SIGNAL(ReplayStopped(uint64_t)), this, SLOT(slotReplayStopped(uint64_t)));\r
-        connect(m_pWorker, SIGNAL(ReplayFinished()), this, SLOT(slotReplayFinished()));\r
-\r
-        connect(m_pWorker, SIGNAL(ReplayStarted()), this, SIGNAL(ReplayStarted()));\r
-        connect(m_pWorker, SIGNAL(ReplayPaused(uint64_t)), this, SIGNAL(ReplayPaused(uint64_t)));\r
-        connect(m_pWorker, SIGNAL(ReplayContinued()), this, SIGNAL(ReplayContinued()));\r
-        connect(m_pWorker, SIGNAL(ReplayStopped(uint64_t)), this, SIGNAL(ReplayStopped(uint64_t)));\r
-        connect(m_pWorker, SIGNAL(ReplayFinished()), this, SIGNAL(ReplayFinished()));\r
-\r
-//        m_replayThread.setObjectName("ReplayThread");\r
-//        m_pWorker->moveToThread(&m_replayThread);\r
-//        m_replayThread.start();\r
+        qRegisterMetaType<uint64_t>("uint64_t");\r
+        m_replayThread.setObjectName("ReplayThread");\r
+        m_pWorker->moveToThread(&m_replayThread);\r
+        m_replayThread.start();\r
+\r
+        connect(m_pWorker, SIGNAL(ReplayStarted()), this, SLOT(slotReplayStarted()), Qt::QueuedConnection);\r
+        connect(m_pWorker, SIGNAL(ReplayPaused(uint64_t)), this, SLOT(slotReplayPaused(uint64_t)), Qt::QueuedConnection);\r
+        connect(m_pWorker, SIGNAL(ReplayContinued()), this, SLOT(slotReplayContinued()), Qt::QueuedConnection);\r
+        connect(m_pWorker, SIGNAL(ReplayStopped(uint64_t)), this, SLOT(slotReplayStopped(uint64_t)), Qt::QueuedConnection);\r
+        connect(m_pWorker, SIGNAL(ReplayFinished(uint64_t)), this, SLOT(slotReplayFinished(uint64_t)), Qt::QueuedConnection);\r
+\r
+        connect(m_pWorker, SIGNAL(OutputMessage(const QString&)), this, SLOT(OnOutputMessage(const QString&)), Qt::BlockingQueuedConnection);\r
+        connect(m_pWorker, SIGNAL(OutputError(const QString&)), this, SLOT(OnOutputError(const QString&)), Qt::BlockingQueuedConnection);\r
+        connect(m_pWorker, SIGNAL(OutputWarning(const QString&)), this, SLOT(OnOutputWarning(const QString&)), Qt::BlockingQueuedConnection);\r
     }\r
 \r
     virtual ~glvdebug_QReplayWidget()\r
     {\r
-//        m_replayThread.exit();\r
-//        m_replayThread.wait();\r
+        m_replayThread.quit();\r
+        m_replayThread.wait();\r
     }\r
 \r
     virtual QPaintEngine* paintEngine() const\r
@@ -133,7 +130,11 @@ signals:
     void ReplayPaused(uint64_t packetIndex);\r
     void ReplayContinued();\r
     void ReplayStopped(uint64_t packetIndex);\r
-    void ReplayFinished();\r
+    void ReplayFinished(uint64_t packetIndex);\r
+\r
+    void OutputMessage(const QString& msg);\r
+    void OutputError(const QString& msg);\r
+    void OutputWarning(const QString& msg);\r
 \r
 private slots:\r
 \r
@@ -144,15 +145,19 @@ private slots:
         m_pPauseButton->setEnabled(true);\r
         m_pContinueButton->setEnabled(false);\r
         m_pStopButton->setEnabled(true);\r
+\r
+        emit ReplayStarted();\r
     }\r
 \r
-    void slotReplayPaused(uint64_t)\r
+    void slotReplayPaused(uint64_t packetIndex)\r
     {\r
         m_pPlayButton->setEnabled(false);\r
         m_pStepButton->setEnabled(true);\r
         m_pPauseButton->setEnabled(false);\r
         m_pContinueButton->setEnabled(true);\r
         m_pStopButton->setEnabled(false);\r
+\r
+        emit ReplayPaused(packetIndex);\r
     }\r
 \r
     void slotReplayContinued()\r
@@ -162,24 +167,45 @@ private slots:
         m_pPauseButton->setEnabled(true);\r
         m_pContinueButton->setEnabled(false);\r
         m_pStopButton->setEnabled(true);\r
+\r
+        emit ReplayContinued();\r
     }\r
 \r
-    void slotReplayStopped(uint64_t)\r
+    void slotReplayStopped(uint64_t packetIndex)\r
     {\r
         m_pPlayButton->setEnabled(true);\r
         m_pStepButton->setEnabled(true);\r
         m_pPauseButton->setEnabled(false);\r
         m_pContinueButton->setEnabled(false);\r
         m_pStopButton->setEnabled(false);\r
+\r
+        emit ReplayStopped(packetIndex);\r
     }\r
 \r
-    void slotReplayFinished()\r
+    void slotReplayFinished(uint64_t packetIndex)\r
     {\r
         m_pPlayButton->setEnabled(true);\r
         m_pStepButton->setEnabled(true);\r
         m_pPauseButton->setEnabled(false);\r
         m_pContinueButton->setEnabled(false);\r
         m_pStopButton->setEnabled(false);\r
+\r
+        emit ReplayFinished(packetIndex);\r
+    }\r
+\r
+    void OnOutputMessage(const QString& msg)\r
+    {\r
+        emit OutputMessage(msg);\r
+    }\r
+\r
+    void OnOutputError(const QString& msg)\r
+    {\r
+        emit OutputError(msg);\r
+    }\r
+\r
+    void OnOutputWarning(const QString& msg)\r
+    {\r
+        emit OutputWarning(msg);\r
     }\r
 \r
 public slots:\r
@@ -213,14 +239,6 @@ public slots:
         emit StopButtonClicked();\r
     }\r
 \r
-    void OnSettingsUpdated(glv_SettingGroup* pGroups, unsigned int numGroups)\r
-    {\r
-        if (m_pWorker != NULL)\r
-        {\r
-            m_pWorker->onSettingsUpdated(pGroups, numGroups);\r
-        }\r
-    }\r
-\r
 private:\r
     glvdebug_QReplayWorker* m_pWorker;\r
     QWidget* m_pReplayWindow;\r
diff --git a/tools/glave/src/glvdebug/glvdebug_QReplayWorker.cpp b/tools/glave/src/glvdebug/glvdebug_QReplayWorker.cpp
new file mode 100644 (file)
index 0000000..56f7e24
--- /dev/null
@@ -0,0 +1,486 @@
+/**************************************************************************
+ *
+ * Copyright 2014 Valve Software
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "glvdebug_QReplayWorker.h"
+#include <QAction>
+#include <QCoreApplication>
+#include "glvdebug_trace_file_utils.h"
+
+glvdebug_QReplayWorker* g_pWorker;
+
+static void dbg_msg_callback(glv_replay::GLV_DBG_MSG_TYPE msgType, const char* pMsg);
+
+glvdebug_QReplayWorker::glvdebug_QReplayWorker()
+    : QObject(NULL),
+      m_bPauseReplay(false),
+      m_bStopReplay(false),
+      m_pView(NULL),
+      m_pTraceFileInfo(NULL),
+      m_currentReplayPacketIndex(0),
+      m_pActionRunToHere(NULL),
+      m_pauseAtPacketIndex((uint64_t)-1),
+      m_bPrintReplayInfoMessages(TRUE),
+      m_bPrintReplayWarningMessages(TRUE),
+      m_bPrintReplayErrorMessages(TRUE),
+      m_bPauseOnReplayInfoMessages(FALSE),
+      m_bPauseOnReplayWarningMessages(FALSE),
+      m_bPauseOnReplayErrorMessages(FALSE)
+{
+    memset(m_pReplayers, 0, sizeof(glv_replay::glv_trace_packet_replay_library*) * GLV_MAX_TRACER_ID_ARRAY_SIZE);
+    g_pWorker = this;
+}
+
+glvdebug_QReplayWorker::~glvdebug_QReplayWorker()
+{
+    setView(NULL);
+    g_pWorker = NULL;
+
+    if (m_pActionRunToHere != NULL)
+    {
+        disconnect(m_pActionRunToHere, SIGNAL(triggered()), this, SLOT(onPlayToHere()));
+        delete m_pActionRunToHere;
+        m_pActionRunToHere = NULL;
+    }
+}
+
+void glvdebug_QReplayWorker::setPrintReplayMessages(BOOL bPrintInfo, BOOL bPrintWarning, BOOL bPrintError)
+{
+    m_bPrintReplayInfoMessages = bPrintInfo;
+    m_bPrintReplayWarningMessages = bPrintWarning;
+    m_bPrintReplayErrorMessages = bPrintError;
+}
+
+void glvdebug_QReplayWorker::setPauseOnReplayMessages(BOOL bPauseOnInfo, BOOL bPauseOnWarning, BOOL bPauseOnError)
+{
+    m_bPauseOnReplayInfoMessages = bPauseOnInfo;
+    m_bPauseOnReplayWarningMessages = bPauseOnWarning;
+    m_bPauseOnReplayErrorMessages = bPauseOnError;
+}
+
+BOOL glvdebug_QReplayWorker::PrintReplayInfoMsgs()
+{
+    return m_bPrintReplayInfoMessages;
+}
+
+BOOL glvdebug_QReplayWorker::PrintReplayWarningMsgs()
+{
+    return m_bPrintReplayWarningMessages;
+}
+
+BOOL glvdebug_QReplayWorker::PrintReplayErrorMsgs()
+{
+    return m_bPrintReplayErrorMessages;
+}
+
+BOOL glvdebug_QReplayWorker::PauseOnReplayInfoMsg()
+{
+    return m_bPauseOnReplayInfoMessages;
+}
+
+BOOL glvdebug_QReplayWorker::PauseOnReplayWarningMsg()
+{
+    return m_bPauseOnReplayWarningMessages;
+}
+
+BOOL glvdebug_QReplayWorker::PauseOnReplayErrorMsg()
+{
+    return m_bPauseOnReplayErrorMessages;
+}
+
+void glvdebug_QReplayWorker::setView(glvdebug_view* pView)
+{
+    m_pView = pView;
+}
+
+bool glvdebug_QReplayWorker::load_replayers(glvdebug_trace_file_info* pTraceFileInfo,
+    QWidget* pReplayWindow, int const replayWindowWidth,
+    int const replayWindowHeight, bool const separateReplayWindow)
+{
+    // Get window handle of the widget to replay into.
+    assert(pReplayWindow != NULL);
+    assert(replayWindowWidth > 0);
+    assert(replayWindowHeight > 0);
+
+    m_pTraceFileInfo = pTraceFileInfo;
+
+    // TODO: Get the width and height from the replayer. We can't do this yet
+    // because the replayer doesn't know the render target's size.
+
+    WId hWindow = pReplayWindow->winId();
+
+    // load any API specific driver libraries and init replayer objects
+    uint8_t tidApi = GLV_TID_RESERVED;
+    bool bReplayerLoaded = false;
+
+    glv_replay::Display disp;
+    if(separateReplayWindow)
+    {
+        disp = glv_replay::Display(replayWindowWidth, replayWindowHeight, 0, false);
+    }
+    else
+    {
+        disp = glv_replay::Display((glv_window_handle)hWindow, replayWindowWidth, replayWindowHeight);
+    }
+
+    for (int i = 0; i < GLV_MAX_TRACER_ID_ARRAY_SIZE; i++)
+    {
+        m_pReplayers[i] = NULL;
+    }
+
+    for (int i = 0; i < pTraceFileInfo->header.tracer_count; i++)
+    {
+        uint8_t tracerId = pTraceFileInfo->header.tracer_id_array[i].id;
+        tidApi = tracerId;
+
+        const GLV_TRACER_REPLAYER_INFO* pReplayerInfo = &(gs_tracerReplayerInfo[tracerId]);
+
+        if (pReplayerInfo->tracerId != tracerId)
+        {
+            emit OutputError(QString("Replayer info for TracerId (%1) failed consistency check.").arg(tracerId));
+            assert(!"TracerId in GLV_TRACER_REPLAYER_INFO does not match the requested tracerId. The array needs to be corrected.");
+        }
+        else if (pReplayerInfo->needsReplayer == TRUE)
+        {
+            // Have our factory create the necessary replayer
+            m_pReplayers[tracerId] = m_replayerFactory.Create(tracerId);
+
+            if (m_pReplayers[tracerId] == NULL)
+            {
+                // replayer failed to be created
+                emit OutputError(QString("Couldn't create replayer for TracerId %1.").arg(tracerId));
+            }
+            else
+            {
+                m_pReplayers[tracerId]->RegisterDbgMsgCallback((glv_replay::GLV_DBG_MSG_CALLBACK_FUNCTION)&dbg_msg_callback);
+
+                // get settings from the replayer
+                m_pView->add_setting_group(m_pReplayers[tracerId]->GetSettings());
+
+                // update replayer with updated state
+                glv_SettingGroup* pGlobalSettings = NULL;
+                unsigned int numGlobalSettings = m_pView->get_global_settings(&pGlobalSettings);
+                m_pReplayers[tracerId]->UpdateFromSettings(pGlobalSettings, numGlobalSettings);
+
+                // Initialize the replayer
+                int err = m_pReplayers[tracerId]->Initialize(&disp, NULL);
+                if (err) {
+                    emit OutputError(QString("Couldn't Initialize replayer for TracerId %1.").arg(tracerId));
+                    return false;
+                }
+
+                bReplayerLoaded = true;
+            }
+        }
+    }
+
+    if (tidApi == GLV_TID_RESERVED)
+    {
+        emit OutputError(QString("No API specified in tracefile for replaying."));
+        return false;
+    }
+
+    if (bReplayerLoaded)
+    {
+        m_pActionRunToHere = new QAction("Play to here", NULL);
+        connect(m_pActionRunToHere, SIGNAL(triggered()), this, SLOT(onPlayToHere()));
+        m_pView->add_calltree_contextmenu_item(m_pActionRunToHere);
+    }
+
+    return true;
+}
+
+void glvdebug_QReplayWorker::unloadReplayers()
+{
+    m_pTraceFileInfo = NULL;
+
+    // Clean up replayers
+    if (m_pReplayers != NULL)
+    {
+        for (int i = 0; i < GLV_MAX_TRACER_ID_ARRAY_SIZE; i++)
+        {
+            if (m_pReplayers[i] != NULL)
+            {
+                m_pReplayers[i]->Deinitialize();
+                m_replayerFactory.Destroy(&m_pReplayers[i]);
+            }
+        }
+    }
+}
+
+void glvdebug_QReplayWorker::playCurrentTraceFile(uint64_t startPacketIndex)
+{
+    glvdebug_trace_file_info* pTraceFileInfo = m_pTraceFileInfo;
+    glvdebug_trace_file_packet_offsets* pCurPacket;
+    unsigned int res;
+    glv_replay::glv_trace_packet_replay_library *replayer;
+
+    for (uint64_t i = startPacketIndex; i < pTraceFileInfo->packetCount; i++)
+    {
+        m_currentReplayPacketIndex = i;
+
+        pCurPacket = &pTraceFileInfo->pPacketOffsets[i];
+        switch (pCurPacket->pHeader->packet_id) {
+            case GLV_TPI_MESSAGE:
+            {
+//                glv_trace_packet_message* msgPacket;
+//                msgPacket = (glv_trace_packet_message*)pCurPacket->pHeader;
+//                if(msgPacket->type == TLLWarn) {
+//                    emit OutputWarning(QString(msgPacket->message));
+//                } else if(msgPacket->type == TLLError) {
+//                    emit OutputError(QString(msgPacket->message));
+//                } else {
+//                    emit OutputMessage(QString(msgPacket->message));
+//                }
+            }
+                break;
+            case GLV_TPI_MARKER_CHECKPOINT:
+                break;
+            case GLV_TPI_MARKER_API_BOUNDARY:
+                break;
+            case GLV_TPI_MARKER_API_GROUP_BEGIN:
+                break;
+            case GLV_TPI_MARKER_API_GROUP_END:
+                break;
+            case GLV_TPI_MARKER_TERMINATE_PROCESS:
+                break;
+            //TODO processing code for all the above cases
+            default:
+            {
+                if (pCurPacket->pHeader->tracer_id >= GLV_MAX_TRACER_ID_ARRAY_SIZE  || pCurPacket->pHeader->tracer_id == GLV_TID_RESERVED)
+                {
+                    emit OutputWarning(QString("Tracer_id from packet num packet %1 invalid.\n").arg(pCurPacket->pHeader->packet_id));
+                    continue;
+                }
+                replayer = m_pReplayers[pCurPacket->pHeader->tracer_id];
+                if (replayer == NULL) {
+                    emit OutputWarning(QString("Tracer_id %1 has no valid replayer.\n").arg(pCurPacket->pHeader->tracer_id));
+                    continue;
+                }
+                if (pCurPacket->pHeader->packet_id >= GLV_TPI_BEGIN_API_HERE)
+                {
+                    // replay the API packet
+                    res = replayer->Replay(pCurPacket->pHeader);
+
+                    if (res == glv_replay::GLV_REPLAY_ERROR ||
+                        res == glv_replay::GLV_REPLAY_INVALID_ID ||
+                        res == glv_replay::GLV_REPLAY_CALL_ERROR)
+                    {
+                        emit OutputError(QString("Failed to replay packet_id %1.\n").arg(pCurPacket->pHeader->packet_id));
+                    }
+                    else if (res == glv_replay::GLV_REPLAY_BAD_RETURN)
+                    {
+                        emit OutputWarning(QString("Replay of packet_id %1 has diverged from trace due to a different return value.\n").arg(pCurPacket->pHeader->packet_id));
+                    }
+                    else if (res == glv_replay::GLV_REPLAY_INVALID_PARAMS ||
+                             res == glv_replay::GLV_REPLAY_VALIDATION_ERROR)
+                    {
+                        // validation layer should have reported these if the user wanted them, so don't print any additional warnings here.
+                    }
+                    else if (res != glv_replay::GLV_REPLAY_SUCCESS)
+                    {
+                        emit OutputError(QString("Unknown error caused by packet_id %1.\n").arg(pCurPacket->pHeader->packet_id));
+                    }
+                } else {
+                    emit OutputError(QString("Bad packet type id=%1, index=%2.\n").arg(pCurPacket->pHeader->packet_id).arg(pCurPacket->pHeader->global_packet_index));
+                }
+            }
+        }
+
+        // Process events and pause or stop if needed
+        QCoreApplication::sendPostedEvents();
+        if (m_bPauseReplay || m_pauseAtPacketIndex == m_currentReplayPacketIndex)
+        {
+            if (m_pauseAtPacketIndex == m_currentReplayPacketIndex)
+            {
+                // reset
+                m_pauseAtPacketIndex = -1;
+            }
+
+            doReplayPaused(m_currentReplayPacketIndex);
+            return;
+        }
+
+        if (m_bStopReplay)
+        {
+            doReplayStopped(m_currentReplayPacketIndex);
+            m_currentReplayPacketIndex = 0;
+            return;
+        }
+    }
+
+    doReplayFinished(m_currentReplayPacketIndex);
+}
+
+void glvdebug_QReplayWorker::onPlayToHere()
+{
+    m_pauseAtPacketIndex = m_pView->get_current_packet_index();
+    if (m_pauseAtPacketIndex <= m_currentReplayPacketIndex || m_currentReplayPacketIndex == 0)
+    {
+        // pause location is behind the current replay position, so restart the replay.
+        StartReplay();
+    }
+    else
+    {
+        // pause location is ahead of current replay position, so continue the replay.
+        ContinueReplay();
+    }
+}
+
+
+void glvdebug_QReplayWorker::StartReplay()
+{
+    // Starting the replay can happen immediately.
+    emit ReplayStarted();
+
+    // Reset some flags and play the replay from the beginning
+    m_bPauseReplay = false;
+    m_bStopReplay = false;
+    playCurrentTraceFile(0);
+}
+
+void glvdebug_QReplayWorker::StepReplay()
+{
+    // Stepping the replay can happen immediately.
+    emit ReplayContinued();
+
+    // Set the pause flag so that the replay will stop after replaying the next packet.
+    m_bPauseReplay = true;
+    m_bStopReplay = false;
+    playCurrentTraceFile(m_currentReplayPacketIndex+1);
+}
+
+void glvdebug_QReplayWorker::PauseReplay()
+{
+    // Pausing the replay happens asyncronously.
+    // So set the pause flag and the replay will
+    // react to it as soon as it can. It will call
+    // doReplayPaused() when it has paused.
+    m_bPauseReplay = true;
+}
+
+void glvdebug_QReplayWorker::ContinueReplay()
+{
+    // Continuing the replay can happen immediately.
+    emit ReplayContinued();
+
+    // clear the pause and stop flags and continue the replay from the next packet
+    m_bPauseReplay = false;
+    m_bStopReplay = false;
+    playCurrentTraceFile(m_currentReplayPacketIndex+1);
+}
+
+void glvdebug_QReplayWorker::StopReplay()
+{
+    // Stopping the replay happens asycnronously.
+    // Set the stop flag and the replay will
+    // react to it as soon as it can. It will call
+    // doReplayStopped() when it has stopped.
+    m_bStopReplay = true;
+}
+
+void glvdebug_QReplayWorker::onSettingsUpdated(glv_SettingGroup* pGroups, unsigned int numGroups)
+{
+    if (m_pReplayers != NULL)
+    {
+        for (unsigned int tracerId = 0; tracerId < GLV_MAX_TRACER_ID_ARRAY_SIZE; tracerId++)
+        {
+            if (m_pReplayers[tracerId] != NULL)
+            {
+                // now update the replayer with the loaded settings
+                m_pReplayers[tracerId]->UpdateFromSettings(pGroups, numGroups);
+            }
+        }
+    }
+}
+
+glv_replay::glv_trace_packet_replay_library* glvdebug_QReplayWorker::getReplayer(GLV_TRACER_ID tracerId)
+{
+    if (tracerId < 0 || tracerId >= GLV_MAX_TRACER_ID_ARRAY_SIZE)
+    {
+        return NULL;
+    }
+
+    return m_pReplayers[tracerId];
+}
+
+void glvdebug_QReplayWorker::doReplayPaused(uint64_t packetIndex)
+{
+    emit ReplayPaused(packetIndex);
+}
+
+void glvdebug_QReplayWorker::doReplayStopped(uint64_t packetIndex)
+{
+    emit ReplayStopped(packetIndex);
+}
+
+void glvdebug_QReplayWorker::doReplayFinished(uint64_t packetIndex)
+{
+    // Indicate that the replay finished at the particular packet.
+    emit ReplayFinished(packetIndex);
+
+    // Replay will start again from the beginning, so setup for that now.
+    m_currentReplayPacketIndex = 0;
+}
+
+//=============================================================================
+void dbg_msg_callback(glv_replay::GLV_DBG_MSG_TYPE msgType, const char* pMsg)
+{
+    if (g_pWorker != NULL)
+    {
+        if (msgType == glv_replay::GLV_DBG_MSG_ERROR)
+        {
+            if (g_pWorker->PrintReplayErrorMsgs())
+            {
+                g_pWorker->OutputError(QString(pMsg));
+            }
+            if (g_pWorker->PauseOnReplayErrorMsg())
+            {
+                g_pWorker->PauseReplay();
+            }
+        }
+        else if (msgType == glv_replay::GLV_DBG_MSG_WARNING)
+        {
+            if (g_pWorker->PrintReplayWarningMsgs())
+            {
+                g_pWorker->OutputWarning(QString(pMsg));
+            }
+            if (g_pWorker->PauseOnReplayWarningMsg())
+            {
+                g_pWorker->PauseReplay();
+            }
+        }
+        else
+        {
+            if (g_pWorker->PrintReplayInfoMsgs())
+            {
+                g_pWorker->OutputMessage(QString(pMsg));
+            }
+            if (g_pWorker->PauseOnReplayInfoMsg())
+            {
+                g_pWorker->PauseReplay();
+            }
+        }
+    }
+}
index 89062bc..bf96a7a 100644 (file)
 #ifndef GLVDEBUG_QREPLAYWORKER_H
 #define GLVDEBUG_QREPLAYWORKER_H
 
-#include <QAction>
 #include <QObject>
-#include <QWidget>
-#include <QCoreApplication>
 #include "glvdebug_view.h"
-#include "glvdebug_trace_file_utils.h"
 #include "glvreplay_factory.h"
 
-class glvdebug_QReplayWorker;
-static void dbg_msg_callback(glv_replay::GLV_DBG_MSG_TYPE msgType, const char* pMsg);
-
-static glvdebug_view* s_pView = NULL;
-static glvdebug_QReplayWorker* s_pWorker = NULL;
-
 class glvdebug_QReplayWorker : public QObject
 {
     Q_OBJECT
 public:
-    glvdebug_QReplayWorker()
-        : m_bPauseReplay(false),
-          m_bStopReplay(false),
-          m_pView(NULL),
-          m_pTraceFileInfo(NULL),
-          m_currentReplayPacketIndex(0),
-          m_pActionRunToHere(NULL),
-          m_pauseAtPacketIndex((uint64_t)-1)
-    {
-        memset(m_pReplayers, 0, sizeof(glv_replay::glv_trace_packet_replay_library*) * GLV_MAX_TRACER_ID_ARRAY_SIZE);
-        s_pWorker = this;
-    }
-
-    virtual ~glvdebug_QReplayWorker()
-    {
-        setView(NULL);
-        s_pWorker = NULL;
-
-        if (m_pActionRunToHere != NULL)
-        {
-            disconnect(m_pActionRunToHere, SIGNAL(triggered()), this, SLOT(onPlayToHere()));
-            delete m_pActionRunToHere;
-            m_pActionRunToHere = NULL;
-        }
-    }
+    glvdebug_QReplayWorker();
+    virtual ~glvdebug_QReplayWorker();
 
-    virtual BOOL PrintReplayInfoMsgs()
-    {
-        return FALSE;
-    }
+    void setPrintReplayMessages(BOOL bPrintInfo, BOOL bPrintWarning, BOOL bPrintError);
+    void setPauseOnReplayMessages(BOOL bPauseOnInfo, BOOL bPauseOnWarning, BOOL bPauseOnError);
 
-    virtual BOOL PrintReplayWarningMsgs()
-    {
-        return TRUE;
-    }
+    BOOL PrintReplayInfoMsgs();
+    BOOL PrintReplayWarningMsgs();
+    BOOL PrintReplayErrorMsgs();
 
-    virtual BOOL PrintReplayErrorMsgs()
-    {
-        return TRUE;
-    }
+    BOOL PauseOnReplayInfoMsg();
+    BOOL PauseOnReplayWarningMsg();
+    BOOL PauseOnReplayErrorMsg();
 
-    virtual BOOL PauseOnReplayInfoMsg()
-    {
-        return FALSE;
-    }
+    void setView(glvdebug_view* pView);
 
-    virtual BOOL PauseOnReplayWarningMsg()
-    {
-        return TRUE;
-    }
+    bool load_replayers(glvdebug_trace_file_info* pTraceFileInfo,
+        QWidget* pReplayWindow, int const replayWindowWidth,
+        int const replayWindowHeight, bool const separateReplayWindow);
 
-    virtual BOOL PauseOnReplayErrorMsg()
-    {
-        return TRUE;
-    }
+    void unloadReplayers();
 
 protected slots:
-    void playCurrentTraceFile(uint64_t startPacketIndex)
-    {
-        glvdebug_trace_file_info* pTraceFileInfo = m_pTraceFileInfo;
-        glvdebug_trace_file_packet_offsets* pCurPacket;
-        unsigned int res;
-        glv_replay::glv_trace_packet_replay_library *replayer;
-
-        for (uint64_t i = startPacketIndex; i < pTraceFileInfo->packetCount; i++)
-        {
-            m_currentReplayPacketIndex = i;
-
-            pCurPacket = &pTraceFileInfo->pPacketOffsets[i];
-            switch (pCurPacket->pHeader->packet_id) {
-                case GLV_TPI_MESSAGE:
-                {
-    //                glv_trace_packet_message* msgPacket;
-    //                msgPacket = (glv_trace_packet_message*)pCurPacket->pHeader;
-    //                if(msgPacket->type == TLLWarn) {
-    //                    s_pView->output_warning(msgPacket->message);
-    //                } else if(msgPacket->type == TLLError) {
-    //                    s_pView->output_error(msgPacket->message);
-    //                } else {
-    //                    s_pView->output_message(msgPacket->message);
-    //                }
-                }
-                    break;
-                case GLV_TPI_MARKER_CHECKPOINT:
-                    break;
-                case GLV_TPI_MARKER_API_BOUNDARY:
-                    break;
-                case GLV_TPI_MARKER_API_GROUP_BEGIN:
-                    break;
-                case GLV_TPI_MARKER_API_GROUP_END:
-                    break;
-                case GLV_TPI_MARKER_TERMINATE_PROCESS:
-                    break;
-                //TODO processing code for all the above cases
-                default:
-                {
-                    if (pCurPacket->pHeader->tracer_id >= GLV_MAX_TRACER_ID_ARRAY_SIZE  || pCurPacket->pHeader->tracer_id == GLV_TID_RESERVED) {
-                        m_pView->output_warning(QString("Tracer_id from packet num packet %1 invalid.\n").arg(pCurPacket->pHeader->packet_id));
-                        continue;
-                    }
-                    replayer = m_pReplayers[pCurPacket->pHeader->tracer_id];
-                    if (replayer == NULL) {
-                        m_pView->output_warning(QString("Tracer_id %1 has no valid replayer.\n").arg(pCurPacket->pHeader->tracer_id));
-                        continue;
-                    }
-                    if (pCurPacket->pHeader->packet_id >= GLV_TPI_BEGIN_API_HERE)
-                    {
-                        // replay the API packet
-                        res = replayer->Replay(pCurPacket->pHeader);
-
-                        if (res == glv_replay::GLV_REPLAY_ERROR ||
-                            res == glv_replay::GLV_REPLAY_INVALID_ID ||
-                            res == glv_replay::GLV_REPLAY_CALL_ERROR)
-                        {
-                            m_pView->output_error(QString("Failed to replay packet_id %1.\n").arg(pCurPacket->pHeader->packet_id));
-                        }
-                        else if (res == glv_replay::GLV_REPLAY_BAD_RETURN)
-                        {
-                            m_pView->output_warning(QString("Replay of packet_id %1 has diverged from trace due to a different return value.\n").arg(pCurPacket->pHeader->packet_id));
-                        }
-                        else if (res == glv_replay::GLV_REPLAY_INVALID_PARAMS ||
-                                 res == glv_replay::GLV_REPLAY_VALIDATION_ERROR)
-                        {
-                            // validation layer should have reported these if the user wanted them, so don't print any additional warnings here.
-                        }
-                        else if (res != glv_replay::GLV_REPLAY_SUCCESS)
-                        {
-                            m_pView->output_error(QString("Unknown error caused by packet_id %1.\n").arg(pCurPacket->pHeader->packet_id));
-                        }
-                    } else {
-                        m_pView->output_error(QString("Bad packet type id=%1, index=%2.\n").arg(pCurPacket->pHeader->packet_id).arg(pCurPacket->pHeader->global_packet_index));
-                    }
-                }
-            }
-
-            // Process events and pause or stop if needed
-            QCoreApplication::processEvents();
-            if (m_bPauseReplay || m_pauseAtPacketIndex == m_currentReplayPacketIndex)
-            {
-                if (m_pauseAtPacketIndex == m_currentReplayPacketIndex)
-                {
-                    // reset
-                    m_pauseAtPacketIndex = -1;
-                }
-
-                doReplayPaused(m_currentReplayPacketIndex);
-                return;
-            }
-
-            if (m_bStopReplay)
-            {
-                doReplayStopped(m_currentReplayPacketIndex);
-                m_currentReplayPacketIndex = 0;
-                return;
-            }
-        }
-
-        doReplayFinished();
-    }
-
-    virtual void onPlayToHere()
-    {
-        m_pauseAtPacketIndex = m_pView->get_current_packet_index();
-        if (m_pauseAtPacketIndex <= m_currentReplayPacketIndex || m_currentReplayPacketIndex == 0)
-        {
-            // pause location is behind the current replay position, so restart the replay.
-            StartReplay();
-        }
-        else
-        {
-            // pause location is ahead of current replay position, so continue the replay.
-            ContinueReplay();
-        }
-    }
+    virtual void playCurrentTraceFile(uint64_t startPacketIndex);
+    virtual void onPlayToHere();
 
 public slots:
+    void StartReplay();
+    void StepReplay();
+    void PauseReplay();
+    void ContinueReplay();
+    void StopReplay();
 
-    void StartReplay()
-    {
-        // Starting the replay can happen immediately.
-        // Update the UI to reflect that the replay is started
-        m_pView->output_message(QString("Replay Started"));
-        m_pView->on_replay_state_changed(true);
-        emit ReplayStarted();
-
-        // Reset some flags and play the replay from the beginning
-        m_bPauseReplay = false;
-        m_bStopReplay = false;
-        playCurrentTraceFile(0);
-    }
-
-    void StepReplay()
-    {
-        // Stepping the replay can happen immediately.
-        // Update the UI to repflect that it has been stepped
-        m_pView->output_message(QString("Replay Stepped"));
-        m_pView->on_replay_state_changed(true);
-        emit ReplayContinued();
-
-        // Set the pause flag so that the replay will stop after replaying the next packet.
-        m_bPauseReplay = true;
-        playCurrentTraceFile(m_currentReplayPacketIndex+1);
-    }
-
-    void PauseReplay()
-    {
-        // Pausing the replay happens asyncronously.
-        // So set the pause flag and the replay will
-        // react to it as soon as it can. It will call
-        // doReplayPaused() when it has paused.
-        m_bPauseReplay = true;
-    }
-
-    void ContinueReplay()
-    {
-        // Continuing the replay can happen immediately.
-        // Update the UI to reflect being continued.
-        m_pView->output_message(QString("Replay Continued"));
-        m_pView->on_replay_state_changed(true);
-        emit ReplayContinued();
-
-        // clear the pause flag and continue the replay from the next packet
-        m_bPauseReplay = false;
-        playCurrentTraceFile(m_currentReplayPacketIndex+1);
-    }
+    void onSettingsUpdated(glv_SettingGroup* pGroups, unsigned int numGroups);
 
-    void StopReplay()
-    {
-        // Stopping the replay happens asycnronously.
-        // Set the stop flag and the replay will
-        // react to it as soon as it can. It will call
-        // doReplayStopped() when it has stopped.
-        m_bStopReplay = true;
-    }
-
-    void onSettingsUpdated(glv_SettingGroup* pGroups, unsigned int numGroups)
-    {
-        if (m_pReplayers != NULL)
-        {
-            for (unsigned int tracerId = 0; tracerId < GLV_MAX_TRACER_ID_ARRAY_SIZE; tracerId++)
-            {
-                if (m_pReplayers[tracerId] != NULL)
-                {
-                    // now update the replayer with the loaded settings
-                    m_pReplayers[tracerId]->UpdateFromSettings(pGroups, numGroups);
-                }
-            }
-        }
-    }
+    glv_replay::glv_trace_packet_replay_library* getReplayer(GLV_TRACER_ID tracerId);
 
 signals:
     void ReplayStarted();
     void ReplayPaused(uint64_t packetIndex);
     void ReplayContinued();
     void ReplayStopped(uint64_t packetIndex);
-    void ReplayFinished();
+    void ReplayFinished(uint64_t packetIndex);
+
+    void OutputMessage(const QString& msg);
+    void OutputError(const QString& msg);
+    void OutputWarning(const QString& msg);
 
-protected:
+private:
     bool m_bPauseReplay;
     bool m_bStopReplay;
     glvdebug_view* m_pView;
@@ -309,186 +90,20 @@ protected:
     QAction* m_pActionRunToHere;
     uint64_t m_pauseAtPacketIndex;
 
-    void setView(glvdebug_view* pView)
-    {
-        m_pView = pView;
-        s_pView = pView;
-    }
-
-    void doReplayPaused(uint64_t packetIndex)
-    {
-        m_pView->output_message(QString("Replay Paused at packet index %1").arg(packetIndex));
-        m_pView->on_replay_state_changed(false);
-
-        // When paused, the replay will 'continue' from the last packet,
-        // so select that call to indicate to the user where the pause occured.
-        m_pView->select_call_at_packet_index(packetIndex);
-
-        emit ReplayPaused(packetIndex);
-    }
-
-    void doReplayStopped(uint64_t packetIndex)
-    {
-        m_pView->output_message(QString("Replay Stopped at packet index %1").arg(packetIndex));
-        m_pView->on_replay_state_changed(false);
+    BOOL m_bPrintReplayInfoMessages;
+    BOOL m_bPrintReplayWarningMessages;
+    BOOL m_bPrintReplayErrorMessages;
 
-        // Stopping the replay means that it will 'play' or 'step' from the beginning,
-        // so select the first packet index to indicate to the user what stopping replay does.
-        m_pView->select_call_at_packet_index(0);
-
-        emit ReplayStopped(packetIndex);
-    }
-
-    void doReplayFinished()
-    {
-        m_pView->output_message(QString("Replay Finished"));
-        m_pView->on_replay_state_changed(false);
-
-        // The replay has completed, so highlight the final packet index.
-        m_pView->select_call_at_packet_index(m_currentReplayPacketIndex);
-        m_currentReplayPacketIndex = 0;
-
-        emit ReplayFinished();
-    }
-
-    bool load_replayers(glvdebug_trace_file_info* pTraceFileInfo,
-        QWidget* pReplayWindow, int const replayWindowWidth,
-        int const replayWindowHeight, bool const separateReplayWindow)
-    {
-        // Get window handle of the widget to replay into.
-        assert(pReplayWindow != NULL);
-        assert(replayWindowWidth > 0);
-        assert(replayWindowHeight > 0);
-
-        // TODO: Get the width and height from the replayer. We can't do this yet
-        // because the replayer doesn't know the render target's size.
-
-        WId hWindow = pReplayWindow->winId();
-
-        // load any API specific driver libraries and init replayer objects
-        uint8_t tidApi = GLV_TID_RESERVED;
-        bool bReplayerLoaded = false;
-
-        glv_replay::Display disp;
-        if(separateReplayWindow)
-        {
-            disp = glv_replay::Display(replayWindowWidth, replayWindowHeight, 0, false);
-        }
-        else
-        {
-            disp = glv_replay::Display((glv_window_handle)hWindow, replayWindowWidth, replayWindowHeight);
-        }
-
-        for (int i = 0; i < GLV_MAX_TRACER_ID_ARRAY_SIZE; i++)
-        {
-            m_pReplayers[i] = NULL;
-        }
-
-        for (int i = 0; i < pTraceFileInfo->header.tracer_count; i++)
-        {
-            uint8_t tracerId = pTraceFileInfo->header.tracer_id_array[i].id;
-            tidApi = tracerId;
-
-            const GLV_TRACER_REPLAYER_INFO* pReplayerInfo = &(gs_tracerReplayerInfo[tracerId]);
-
-            if (pReplayerInfo->tracerId != tracerId)
-            {
-                glv_LogError("Replayer info for TracerId (%d) failed consistency check.\n", tracerId);
-                assert(!"TracerId in GLV_TRACER_REPLAYER_INFO does not match the requested tracerId. The array needs to be corrected.");
-            }
-            else if (pReplayerInfo->needsReplayer == TRUE)
-            {
-                // Have our factory create the necessary replayer
-                m_pReplayers[tracerId] = m_replayerFactory.Create(tracerId);
-
-                if (m_pReplayers[tracerId] == NULL)
-                {
-                    // replayer failed to be created
-                    glv_LogError("Couldn't create replayer for TracerId %d.\n", tracerId);
-                }
-                else
-                {
-                    m_pReplayers[tracerId]->RegisterDbgMsgCallback((glv_replay::GLV_DBG_MSG_CALLBACK_FUNCTION)&dbg_msg_callback);
-
-                    // get settings from the replayer
-                    m_pView->add_setting_group(m_pReplayers[tracerId]->GetSettings());
-
-                    // update replayer with updated state
-                    glv_SettingGroup* pGlobalSettings = NULL;
-                    unsigned int numGlobalSettings = m_pView->get_global_settings(&pGlobalSettings);
-                    m_pReplayers[tracerId]->UpdateFromSettings(pGlobalSettings, numGlobalSettings);
-
-                    // Initialize the replayer
-                    int err = m_pReplayers[tracerId]->Initialize(&disp, NULL);
-                    if (err) {
-                        glv_LogError("Couldn't Initialize replayer for TracerId %d.\n", tracerId);
-                        return false;
-                    }
-
-                    bReplayerLoaded = true;
-                }
-            }
-        }
-
-        if (tidApi == GLV_TID_RESERVED)
-        {
-            glv_LogError("No API specified in tracefile for replaying.\n");
-            return false;
-        }
-
-        if (bReplayerLoaded)
-        {
-            m_pActionRunToHere = new QAction("Play to here", NULL);
-            connect(m_pActionRunToHere, SIGNAL(triggered()), this, SLOT(onPlayToHere()));
-            m_pView->add_calltree_contextmenu_item(m_pActionRunToHere);
-        }
-
-        return true;
-    }
+    BOOL m_bPauseOnReplayInfoMessages;
+    BOOL m_bPauseOnReplayWarningMessages;
+    BOOL m_bPauseOnReplayErrorMessages;
 
     glv_replay::ReplayFactory m_replayerFactory;
     glv_replay::glv_trace_packet_replay_library* m_pReplayers[GLV_MAX_TRACER_ID_ARRAY_SIZE];
 
+    void doReplayPaused(uint64_t packetIndex);
+    void doReplayStopped(uint64_t packetIndex);
+    void doReplayFinished(uint64_t packetIndex);
 };
 
-static void dbg_msg_callback(glv_replay::GLV_DBG_MSG_TYPE msgType, const char* pMsg)
-{
-    if (s_pView != NULL && s_pWorker != NULL)
-    {
-        if (msgType == glv_replay::GLV_DBG_MSG_ERROR)
-        {
-            if (s_pWorker->PrintReplayErrorMsgs())
-            {
-                s_pView->output_error(pMsg);
-            }
-            if (s_pWorker->PauseOnReplayErrorMsg())
-            {
-                s_pWorker->PauseReplay();
-            }
-        }
-        else if (msgType == glv_replay::GLV_DBG_MSG_WARNING)
-        {
-            if (s_pWorker->PrintReplayWarningMsgs())
-            {
-                s_pView->output_warning(pMsg);
-            }
-            if (s_pWorker->PauseOnReplayWarningMsg())
-            {
-                s_pWorker->PauseReplay();
-            }
-        }
-        else
-        {
-            if (s_pWorker->PrintReplayInfoMsgs())
-            {
-                s_pView->output_message(pMsg);
-            }
-            if (s_pWorker->PauseOnReplayInfoMsg())
-            {
-                s_pWorker->PauseReplay();
-            }
-        }
-    }
-}
-
 #endif // GLVDEBUG_QREPLAYWORKER_H
index a1ba8b1..7c37e2c 100755 (executable)
@@ -11,40 +11,33 @@ glvdebug_output::~glvdebug_output()
 {\r
 }\r
 \r
-void glvdebug_output::message(const char* pMessage, bool bRefresh)\r
+void glvdebug_output::init(QTextEdit* pTextEdit)\r
+{\r
+    m_pTextEdit = pTextEdit;\r
+}\r
+\r
+void glvdebug_output::message(const QString& message)\r
 {\r
     if (m_pTextEdit != NULL)\r
     {\r
-        m_pTextEdit->append(pMessage);\r
-        if (bRefresh)\r
-        {\r
-            m_pTextEdit->repaint();\r
-        }\r
+        m_pTextEdit->append(message);\r
     }\r
 }\r
 \r
-void glvdebug_output::warning(const char* pWarning, bool bRefresh)\r
+void glvdebug_output::warning(const QString& warning)\r
 {\r
     if (m_pTextEdit != NULL)\r
     {\r
-        QString msg = QString("Warning: %1").arg(pWarning);\r
+        QString msg = QString("Warning: %1").arg(warning);\r
         m_pTextEdit->append(msg);\r
-        if (bRefresh)\r
-        {\r
-            m_pTextEdit->repaint();\r
-        }\r
     }\r
 }\r
 \r
-void glvdebug_output::error(const char* pError, bool bRefresh)\r
+void glvdebug_output::error(const QString& error)\r
 {\r
     if (m_pTextEdit != NULL)\r
     {\r
-        QString msg = QString("ERROR: %1").arg(pError);\r
+        QString msg = QString("ERROR: %1").arg(error);\r
         m_pTextEdit->append(msg);\r
-        if (bRefresh)\r
-        {\r
-            m_pTextEdit->repaint();\r
-        }\r
     }\r
 }\r
index 914f4f9..3344a02 100755 (executable)
@@ -1,6 +1,8 @@
 #ifndef GLVDEBUG_OUTPUT_H\r
 #define GLVDEBUG_OUTPUT_H\r
 \r
+#include <QString>\r
+\r
 class QTextEdit;\r
 \r
 class glvdebug_output\r
@@ -9,11 +11,11 @@ public:
     glvdebug_output();\r
     ~glvdebug_output();\r
 \r
-    void init(QTextEdit* pTextEdit) { m_pTextEdit = pTextEdit; }\r
+    void init(QTextEdit* pTextEdit);\r
 \r
-    void message(const char* pMessage, bool bRefresh);\r
-    void warning(const char* pWarning, bool bRefresh);\r
-    void error(const char* pError, bool bRefresh);\r
+    void message(const QString& message);\r
+    void warning(const QString& warning);\r
+    void error(const QString& error);\r
 \r
 private:\r
     QTextEdit* m_pTextEdit;\r
@@ -22,9 +24,9 @@ private:
 extern glvdebug_output gs_OUTPUT;\r
 \r
 inline void glvdebug_output_init(QTextEdit* pTextEdit) { gs_OUTPUT.init(pTextEdit); }\r
-inline void glvdebug_output_message(const char* pMessage, bool bRefresh = true) { gs_OUTPUT.message(pMessage, bRefresh); }\r
-inline void glvdebug_output_warning(const char* pWarning, bool bRefresh = true) { gs_OUTPUT.warning(pWarning, bRefresh); }\r
-inline void glvdebug_output_error(const char* pError, bool bRefresh = true) { gs_OUTPUT.error(pError, bRefresh); }\r
+inline void glvdebug_output_message(const QString& message) { gs_OUTPUT.message(message); }\r
+inline void glvdebug_output_warning(const QString& warning) { gs_OUTPUT.warning(warning); }\r
+inline void glvdebug_output_error(const QString& error) { gs_OUTPUT.error(error); }\r
 inline void glvdebug_output_deinit() { gs_OUTPUT.init(0); }\r
 \r
 #endif // GLVDEBUG_OUTPUT_H\r
index 3956d16..698885a 100755 (executable)
@@ -37,9 +37,9 @@ class glvdebug_view
 public:\r
     virtual void reset_view() = 0;\r
 \r
-    virtual void output_message(QString message, bool bRefresh = true) = 0;\r
-    virtual void output_warning(QString message, bool bRefresh = true) = 0;\r
-    virtual void output_error(QString message, bool bRefresh = true) = 0;\r
+    virtual void output_message(QString message) = 0;\r
+    virtual void output_warning(QString message) = 0;\r
+    virtual void output_error(QString message) = 0;\r
 \r
     virtual void add_setting_group(glv_SettingGroup* pGroup) = 0;\r
     virtual unsigned int get_global_settings(glv_SettingGroup** ppGroups) = 0;\r