* When loading a trace that contains over 200 frames, the user will be prompted whether they'd like to trim the file. The trimmed file can then optionally be loaded instead of the originally selected trace.
* The new vogleditor_QTrimDialog allows the user to specify the frame index to start the trim at, the number of frames to trim, and the output file name.
* Invalid frame index or lengths will make the textbox turn red to indicate the error. Entries are also validated against the number of frames in the trace file, and the trim lengths are currently limited to 200 frames (so that they can be loaded back into the editor without the trim prompt being shown).
* voglreplay32/64 is launched in a separate process to generate the trim file. Failed replays display an error; successful replays are saved and can be reloaded into the editor.
* Enabled the Trim Trace button to allow trimming of an already open trace.
* Completely removed the Stop and Pause buttons
vogleditor_qtextureexplorer.cpp
vogleditor_qtextureviewer.cpp
vogleditor_qtimelineview.cpp
+ vogleditor_qtrimdialog.cpp
vogleditor_statetreearbprogramitem.cpp
vogleditor_statetreearbprogramenvitem.cpp
vogleditor_statetreebufferitem.cpp
vogleditor_qtextureviewer.h
vogleditor_qtextureexplorer.h
vogleditor_qtimelineview.h
+ vogleditor_qtrimdialog.h
)
# these are for non-QOBJECT headers
vogleditor_qprogramexplorer.ui
vogleditor_qshaderexplorer.ui
vogleditor_qtextureexplorer.ui
+ vogleditor_qtrimdialog.ui
)
set(RESOURCE_LIST
#include <QHBoxLayout>
#include <QItemSelection>
#include <QPalette>
+#include <QProcess>
#include <QSortFilterProxyModel>
#include <QSpacerItem>
#include <QToolButton>
#include "vogleditor_statetreeshaderitem.h"
#include "vogleditor_statetreeframebufferitem.h"
#include "vogleditor_qtextureexplorer.h"
+#include "vogleditor_qtrimdialog.h"
#define VOGLEDITOR_DISABLE_TAB(tab) ui->tabWidget->setTabEnabled(ui->tabWidget->indexOf(tab), false);
#define VOGLEDITOR_ENABLE_TAB(tab) ui->tabWidget->setTabEnabled(ui->tabWidget->indexOf(tab), true);
m_pShaderTab_layout(NULL),
m_currentSnapshot(NULL),
m_pCurrentCallTreeItem(NULL),
+ m_pVoglReplayProcess(new QProcess()),
m_pPlayButton(NULL),
- m_pPauseButton(NULL),
m_pTrimButton(NULL),
- m_pStopButton(NULL),
m_pTraceReader(NULL),
m_pTimelineModel(NULL),
m_pApiCallTreeModel(NULL),
// add buttons to toolbar
m_pPlayButton = new QToolButton(ui->mainToolBar);
- m_pPlayButton->setText("Play trace");
+ m_pPlayButton->setText("Play Trace");
m_pPlayButton->setEnabled(false);
- m_pPauseButton = new QToolButton(ui->mainToolBar);
- m_pPauseButton->setText("Pause");
- m_pPauseButton->setEnabled(false);
-
m_pTrimButton = new QToolButton(ui->mainToolBar);
- m_pTrimButton->setText("Trim");
+ m_pTrimButton->setText("Trim Trace");
m_pTrimButton->setEnabled(false);
- m_pStopButton = new QToolButton(ui->mainToolBar);
- m_pStopButton->setText("Stop");
- m_pStopButton->setEnabled(false);
-
- // Temporarily hide the other buttons (until asyncronous playback is supported)
- m_pPauseButton->setVisible(false);
- m_pTrimButton->setVisible(false);
- m_pStopButton->setVisible(false);
-
ui->mainToolBar->addWidget(m_pPlayButton);
- ui->mainToolBar->addWidget(m_pPauseButton);
ui->mainToolBar->addWidget(m_pTrimButton);
- ui->mainToolBar->addWidget(m_pStopButton);
connect(m_pPlayButton, SIGNAL(clicked()), this, SLOT(playCurrentTraceFile()));
- connect(m_pPauseButton, SIGNAL(clicked()), this, SLOT(pauseCurrentTraceFile()));
connect(m_pTrimButton, SIGNAL(clicked()), this, SLOT(trimCurrentTraceFile()));
- connect(m_pStopButton, SIGNAL(clicked()), this, SLOT(stopCurrentTraceFile()));
connect(m_pProgramExplorer, SIGNAL(program_edited(vogl_program_state*)), this, SLOT(on_program_edited(vogl_program_state*)));
m_pPlayButton = NULL;
}
- if (m_pPauseButton != NULL)
- {
- delete m_pPauseButton;
- m_pPauseButton = NULL;
- }
-
if (m_pTrimButton != NULL)
{
delete m_pTrimButton;
m_pTrimButton = NULL;
}
- if (m_pStopButton != NULL)
- {
- delete m_pStopButton;
- m_pStopButton = NULL;
- }
-
if (m_pFramebufferTab_layout != NULL)
{
delete m_pFramebufferTab_layout;
delete m_pStateTreeModel;
m_pStateTreeModel = NULL;
}
+
+ if (m_pVoglReplayProcess != NULL)
+ {
+ delete m_pVoglReplayProcess;
+ m_pVoglReplayProcess = NULL;
+ }
}
void VoglEditor::playCurrentTraceFile()
// update UI
m_pPlayButton->setEnabled(false);
- m_pPauseButton->setEnabled(true);
- m_pTrimButton->setEnabled(true);
- m_pStopButton->setEnabled(true);
+ m_pTrimButton->setEnabled(false);
m_pStatusLabel->clear();
if (m_traceReplayer.replay(m_pTraceReader, m_pApiCallTreeModel->root(), NULL, 0, true))
{
// replay was successful
m_pPlayButton->setEnabled(true);
- m_pPauseButton->setEnabled(false);
- m_pTrimButton->setEnabled(false);
- m_pStopButton->setEnabled(false);
+ m_pTrimButton->setEnabled(true);
}
else
{
setCursor(origCursor);
}
-void VoglEditor::pauseCurrentTraceFile()
+void VoglEditor::trimCurrentTraceFile()
+{
+ trim_trace_file(m_openFilename, static_cast<uint>(m_pTraceReader->get_max_frame_index()), 200);
+}
+
+/// \return True if the new trim file is now open in the editor
+/// \return False if there was an error, or the user elected NOT to open the new trim file
+bool VoglEditor::trim_trace_file(QString filename, uint maxFrameIndex, uint maxAllowedTrimLen)
{
- if (m_traceReplayer.pause())
+ // open a dialog to gather parameters for the replayer
+ vogleditor_QTrimDialog trimDialog(filename, maxFrameIndex, maxAllowedTrimLen, this);
+ int code = trimDialog.exec();
+
+ if (code == QDialog::Rejected)
{
- // update UI
- m_pPlayButton->setEnabled(true);
- m_pPauseButton->setEnabled(false);
- m_pTrimButton->setEnabled(true);
- m_pStopButton->setEnabled(true);
- m_pStatusLabel->clear();
+ return false;
}
- else
+
+ QStringList arguments;
+ arguments << "--trim_frame" << trimDialog.trim_frame() << "--trim_len" << trimDialog.trim_len() << "--trim_file" << trimDialog.trim_file() << filename;
+
+#ifdef __i386__
+ int procRetValue = m_pVoglReplayProcess->execute("./voglreplay32", arguments);
+#else
+ int procRetValue = m_pVoglReplayProcess->execute("./voglreplay64", arguments);
+#endif
+
+ bool bCompleted = false;
+ if (procRetValue == -2)
{
- m_pStatusLabel->setText("Failed to pause the trace replay.");
+ // proc failed to starts
+ m_pStatusLabel->setText("Error: voglreplay could not be executed.");
}
-}
-
-void VoglEditor::trimCurrentTraceFile()
-{
- if (m_traceReplayer.trim())
+ else if (procRetValue == -1)
+ {
+ // proc crashed
+ m_pStatusLabel->setText("Error: voglreplay aborted unexpectedly.");
+ }
+ else if (procRetValue == 0)
{
- m_pStatusLabel->clear();
+ // success
+ bCompleted = true;
}
else
{
- m_pStatusLabel->setText("Failed to trim the trace replay.");
+ // some other return value
+ bCompleted = false;
}
-}
-void VoglEditor::stopCurrentTraceFile()
-{
- if (m_traceReplayer.stop())
+ if (bCompleted)
{
- // update UI
- m_pPlayButton->setEnabled(true);
- m_pPauseButton->setEnabled(false);
- m_pTrimButton->setEnabled(false);
- m_pStopButton->setEnabled(false);
- m_pStatusLabel->clear();
+ int ret = QMessageBox::warning(this, tr(g_PROJECT_NAME.toStdString().c_str()), tr("Would you like to load the new trimmed trace file?"),
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+
+ if (ret == QMessageBox::Yes)
+ {
+ close_trace_file();
+ if (open_trace_file(trimDialog.trim_file().toStdString().c_str()))
+ {
+ m_pStatusLabel->clear();
+ return true;
+ }
+ else
+ {
+ QMessageBox::critical(this, tr("Error"), tr("Could not open trace file."));
+ }
+ }
}
else
{
- m_pStatusLabel->setText("Failed to stop the trace replay.");
+ QMessageBox::critical(this, tr("Error"), tr("Failed to trim the trace file."));
}
+ return false;
}
void VoglEditor::on_actionE_xit_triggered()
filename.set(fileName.toStdString().c_str());
if (open_trace_file(filename) == false) {
- QMessageBox::critical(this, tr("Error"), tr("Could not open file"));
+ QMessageBox::critical(this, tr("Error"), tr("Could not open trace file."));
return;
}
}
m_pStatusLabel->clear();
}
+ if (tmpReader->get_max_frame_index() > 200)
+ {
+ int ret = QMessageBox::warning(this, tr(g_PROJECT_NAME.toStdString().c_str()), tr("The loaded trace file has many frames and debugging may be difficult.\nWould you like to trim the trace?"),
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+
+ if (ret == QMessageBox::Yes)
+ {
+ if (trim_trace_file(filename.c_str(), static_cast<uint>(tmpReader->get_max_frame_index()), 200))
+ {
+ // user decided to open the new trim file, and the UI should already be updated
+ // clean up here and return
+ vogl_delete(tmpReader);
+ this->setCursor(origCursor);
+ return true;
+ }
+ else
+ {
+ // either there was an error, or the user decided NOT to open the trim file,
+ // so continue to load the original file
+ }
+ }
+ }
+
// now that we know the new trace file can be opened,
// close the old one, and update the trace reader
close_trace_file();
// update toolbar
m_pPlayButton->setEnabled(true);
- m_pPauseButton->setEnabled(false);
- m_pTrimButton->setEnabled(false);
- m_pStopButton->setEnabled(false);
+ m_pTrimButton->setEnabled(true);
// timeline
m_pTimelineModel = new vogleditor_apiCallTimelineModel(m_pApiCallTreeModel->root());
m_pStatusLabel->clear();
m_pPlayButton->setEnabled(false);
- m_pPauseButton->setEnabled(false);
m_pTrimButton->setEnabled(false);
- m_pStopButton->setEnabled(false);
VOGLEDITOR_DISABLE_TAB(ui->machineInfoTab);
class QItemSelection;
class QModelIndex;
+class QProcess;
class QSortFilterProxyModel;
class QToolButton;
class vogl_context_snapshot;
void on_treeView_clicked(const QModelIndex& index);
void playCurrentTraceFile();
- void pauseCurrentTraceFile();
void trimCurrentTraceFile();
- void stopCurrentTraceFile();
+
+ bool trim_trace_file(QString filename, uint maxFrameIndex, uint maxAllowedTrimLen);
void on_stateTreeView_clicked(const QModelIndex &index);
vogleditor_gl_state_snapshot* m_currentSnapshot;
vogleditor_apiCallTreeItem* m_pCurrentCallTreeItem;
+ QProcess* m_pVoglReplayProcess;
QToolButton* m_pPlayButton;
- QToolButton* m_pPauseButton;
QToolButton* m_pTrimButton;
- QToolButton* m_pStopButton;
vogleditor_traceReplayer m_traceReplayer;
vogl_trace_file_reader* m_pTraceReader;
--- /dev/null
+#include "vogleditor_qtrimdialog.h"
+#include "ui_vogleditor_qtrimdialog.h"
+#include <QFileDialog>
+
+vogleditor_QTrimDialog::vogleditor_QTrimDialog(QString parentTraceFile, uint maxFrameIndex, uint maxTrimLength, QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::vogleditor_QTrimDialog),
+ m_maxFrameIndex(maxFrameIndex),
+ m_maxTrimLength(maxTrimLength),
+ m_trim_frame("0"),
+ m_trim_len("1")
+{
+ ui->setupUi(this);
+ ui->trimFrameLineEdit->setText(m_trim_frame);
+ ui->trimLenLineEdit->setText(m_trim_len);
+
+ QString trimFilename = parentTraceFile;
+ trimFilename.insert(trimFilename.lastIndexOf("."), "-trim");
+ ui->trimFileLineEdit->setText(trimFilename);
+}
+
+vogleditor_QTrimDialog::~vogleditor_QTrimDialog()
+{
+ delete ui;
+}
+
+void vogleditor_QTrimDialog::on_buttonBox_accepted()
+{
+ // verify all input
+ bool bValidFrame = false;
+ uint tmpFrame = ui->trimFrameLineEdit->text().toUInt(&bValidFrame);
+ bValidFrame = bValidFrame && (tmpFrame <= m_maxFrameIndex);
+
+ bool bValidLen = false;
+ uint tmpLen = ui->trimLenLineEdit->text().toUInt(&bValidLen);
+ bValidLen = bValidLen && (tmpLen > 0 && tmpLen < m_maxTrimLength);
+
+ bool bValidFile = (ui->trimFrameLineEdit->text().isEmpty() == false);
+
+ if (bValidFrame && bValidLen && bValidFile)
+ {
+ m_trim_frame = ui->trimFrameLineEdit->text();
+ m_trim_len = ui->trimLenLineEdit->text();
+ m_trim_file = ui->trimFileLineEdit->text();
+ accept();
+ }
+}
+
+void vogleditor_QTrimDialog::on_buttonBox_rejected()
+{
+ reject();
+}
+
+void vogleditor_QTrimDialog::on_pickTrimFileButton_pressed()
+{
+ // open file dialog
+ QString suggestedName = ui->trimFileLineEdit->text();
+ QString selectedName = QFileDialog::getSaveFileName(this, tr("Save Trim File"), suggestedName, tr("Trace file (*.bin)"));
+
+ if (!selectedName.isEmpty())
+ {
+ ui->trimFileLineEdit->setText(selectedName);
+ }
+}
+
+void vogleditor_QTrimDialog::on_trimLenLineEdit_textChanged(const QString &arg1)
+{
+ bool bConverted = false;
+ uint trimLen = arg1.toUInt(&bConverted);
+
+ // make sure the length could be converted to a UINT, and that it isn't more than the allowed length
+ if (bConverted == false || trimLen > m_maxTrimLength)
+ {
+ // turn background red
+ QPalette palette(ui->trimLenLineEdit->palette());
+ palette.setColor(QPalette::Base, Qt::red);
+ ui->trimLenLineEdit->setPalette(palette);
+ }
+ else
+ {
+ // restore background color
+ QPalette palette(ui->trimLenLineEdit->palette());
+ palette.setColor(QPalette::Base, Qt::white);
+ ui->trimLenLineEdit->setPalette(palette);
+ }
+}
+
+void vogleditor_QTrimDialog::on_trimFrameLineEdit_textChanged(const QString &arg1)
+{
+ bool bConverted = false;
+ uint trimFrame = arg1.toUInt(&bConverted);
+
+ // make sure frame could be converted to a UINT, and that it isn't greater than the number of frames in the trace
+ if (bConverted == false || trimFrame > m_maxFrameIndex)
+ {
+ // turn background red
+ QPalette palette(ui->trimFrameLineEdit->palette());
+ palette.setColor(QPalette::Base, Qt::red);
+ ui->trimFrameLineEdit->setPalette(palette);
+ }
+ else
+ {
+ // restore background color
+ QPalette palette(ui->trimFrameLineEdit->palette());
+ palette.setColor(QPalette::Base, Qt::white);
+ ui->trimFrameLineEdit->setPalette(palette);
+ }
+}
--- /dev/null
+#ifndef VOGLEDITOR_QTRIMDIALOG_H
+#define VOGLEDITOR_QTRIMDIALOG_H
+
+#include <QDialog>
+#include <QString>
+
+namespace Ui {
+class vogleditor_QTrimDialog;
+}
+
+class vogleditor_QTrimDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit vogleditor_QTrimDialog(QString parentTraceFile, uint maxFrameIndex, uint maxTrimLength, QWidget *parent = 0);
+ ~vogleditor_QTrimDialog();
+
+ QString trim_frame()
+ {
+ return m_trim_frame;
+ }
+
+ QString trim_len()
+ {
+ return m_trim_len;
+ }
+
+ QString trim_file()
+ {
+ return m_trim_file;
+ }
+
+private slots:
+ void on_buttonBox_accepted();
+
+ void on_buttonBox_rejected();
+
+ void on_pickTrimFileButton_pressed();
+
+ void on_trimLenLineEdit_textChanged(const QString &arg1);
+
+ void on_trimFrameLineEdit_textChanged(const QString &arg1);
+
+private:
+ Ui::vogleditor_QTrimDialog *ui;
+ uint m_maxFrameIndex;
+ uint m_maxTrimLength;
+ QString m_trim_frame;
+ QString m_trim_len;
+ QString m_trim_file;
+};
+
+#endif // VOGLEDITOR_QTRIMDIALOG_H
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>vogleditor_QTrimDialog</class>
+ <widget class="QDialog" name="vogleditor_QTrimDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>430</width>
+ <height>154</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>What range of frames would you like to trim?</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>trim_frame:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="trimFrameLineEdit">
+ <property name="inputMask">
+ <string/>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="placeholderText">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>trim_len:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="trimLenLineEdit">
+ <property name="inputMask">
+ <string/>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="placeholderText">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>trim_file:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="trimFileLineEdit">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pickTrimFileButton">
+ <property name="maximumSize">
+ <size>
+ <width>80</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>vogleditor_QTrimDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>vogleditor_QTrimDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>