diff options
Diffstat (limited to 'src/citra_qt')
-rw-r--r-- | src/citra_qt/CMakeLists.txt | 29 | ||||
-rw-r--r-- | src/citra_qt/bootmanager.cpp | 34 | ||||
-rw-r--r-- | src/citra_qt/citra_qt.vcxproj | 8 | ||||
-rw-r--r-- | src/citra_qt/citra_qt.vcxproj.filters | 22 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics.cpp | 83 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics.hxx | 43 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics_cmdlists.cpp | 139 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics_cmdlists.hxx | 64 | ||||
-rw-r--r-- | src/citra_qt/main.cpp | 12 | ||||
-rw-r--r-- | src/citra_qt/main.hxx | 4 |
10 files changed, 414 insertions, 24 deletions
diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt index 594460a71..7f880df8b 100644 --- a/src/citra_qt/CMakeLists.txt +++ b/src/citra_qt/CMakeLists.txt @@ -2,12 +2,31 @@ set(SRCS bootmanager.cpp debugger/callstack.cpp debugger/disassembler.cpp + debugger/graphics.cpp + debugger/graphics_cmdlists.cpp debugger/ramview.cpp debugger/registers.cpp hotkeys.cpp main.cpp config/controller_config.cpp config/controller_config_util.cpp) +set (HEADERS + bootmanager.hxx + debugger/callstack.hxx + debugger/disassembler.hxx + debugger/ramview.hxx + debugger/registers.hxx + hotkeys.hxx + main.hxx + ui_callstack.h + ui_controller_config.h + ui_disassembler.h + ui_hotkeys.h + ui_main.h + ui_registers.h + version.h + config/controller_config.hxx + config/controller_config_util.hxx) qt4_wrap_ui(UI_HDRS debugger/callstack.ui @@ -21,6 +40,8 @@ qt4_wrap_cpp(MOC_SRCS bootmanager.hxx debugger/callstack.hxx debugger/disassembler.hxx + debugger/graphics.hxx + debugger/graphics_cmdlists.hxx debugger/registers.hxx debugger/ramview.hxx hotkeys.hxx @@ -32,7 +53,11 @@ qt4_wrap_cpp(MOC_SRCS include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(./) -add_executable(citra-qt ${SRCS} ${MOC_SRCS} ${UI_HDRS}) -target_link_libraries(citra-qt core common video_core qhexedit ${QT_LIBRARIES} ${OPENGL_LIBRARIES} ${SDL2_LIBRARY} rt GLEW ${GLFW_LIBRARIES}) +add_executable(citra-qt ${SRCS} ${HEADERS} ${MOC_SRCS} ${UI_HDRS}) +if (APPLE) + target_link_libraries(citra-qt core common video_core qhexedit iconv ${COREFOUNDATION_LIBRARY} ${QT_LIBRARIES} ${GLEW_LIBRARY} ${OPENGL_LIBRARIES}) +else() + target_link_libraries(citra-qt core common video_core qhexedit ${QT_LIBRARIES} ${OPENGL_LIBRARIES} ${SDL2_LIBRARY} rt GLEW ${GLFW_LIBRARIES}) +endif() #install(TARGETS citra-qt RUNTIME DESTINATION ${bindir}) diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp index cf9e1bffc..f85116419 100644 --- a/src/citra_qt/bootmanager.cpp +++ b/src/citra_qt/bootmanager.cpp @@ -50,7 +50,7 @@ void EmuThread::run() void EmuThread::Stop() { - if (!isRunning()) + if (!isRunning()) { INFO_LOG(MASTER_LOG, "EmuThread::Stop called while emu thread wasn't running, returning..."); return; @@ -65,7 +65,7 @@ void EmuThread::Stop() terminate(); wait(1000); if (isRunning()) - WARN_LOG(MASTER_LOG, "EmuThread STILL running, something is wrong here..."); + WARN_LOG(MASTER_LOG, "EmuThread STILL running, something is wrong here..."); } INFO_LOG(MASTER_LOG, "EmuThread stopped"); } @@ -76,9 +76,8 @@ void EmuThread::Stop() class GGLWidgetInternal : public QGLWidget { public: - GGLWidgetInternal(GRenderWindow* parent) : QGLWidget(parent) + GGLWidgetInternal(QGLFormat fmt, GRenderWindow* parent) : QGLWidget(parent) { - setAutoBufferSwap(false); doneCurrent(); parent_ = parent; } @@ -106,8 +105,13 @@ EmuThread& GRenderWindow::GetEmuThread() GRenderWindow::GRenderWindow(QWidget* parent) : QWidget(parent), emu_thread(this) { // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground, WA_DontShowOnScreen, WA_DeleteOnClose - - child = new GGLWidgetInternal(this); + QGLFormat fmt; + fmt.setProfile(QGLFormat::CoreProfile); + fmt.setVersion(3,2); + fmt.setSampleBuffers(true); + fmt.setSamples(4); + + child = new GGLWidgetInternal(fmt, this); QBoxLayout* layout = new QHBoxLayout(this); resize(VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight); layout->addWidget(child); @@ -147,12 +151,12 @@ void GRenderWindow::DoneCurrent() void GRenderWindow::PollEvents() { // TODO(ShizZy): Does this belong here? This is a reasonable place to update the window title // from the main thread, but this should probably be in an event handler... - /* - static char title[128]; + /* + static char title[128]; sprintf(title, "%s (FPS: %02.02f)", window_title_.c_str(), video_core::g_renderer->current_fps()); setWindowTitle(title); - */ + */ } void GRenderWindow::BackupGeometry() @@ -185,26 +189,26 @@ QByteArray GRenderWindow::saveGeometry() void GRenderWindow::keyPressEvent(QKeyEvent* event) { - /* - bool key_processed = false; + /* + bool key_processed = false; for (unsigned int channel = 0; channel < 4 && controller_interface(); ++channel) if (controller_interface()->SetControllerStatus(channel, event->key(), input_common::GCController::PRESSED)) key_processed = true; if (!key_processed) QWidget::keyPressEvent(event); - */ + */ } void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { - /* - bool key_processed = false; + /* + bool key_processed = false; for (unsigned int channel = 0; channel < 4 && controller_interface(); ++channel) if (controller_interface()->SetControllerStatus(channel, event->key(), input_common::GCController::RELEASED)) key_processed = true; if (!key_processed) QWidget::keyPressEvent(event); - */ + */ }
\ No newline at end of file diff --git a/src/citra_qt/citra_qt.vcxproj b/src/citra_qt/citra_qt.vcxproj index 3f24bbfbf..c99c8eeee 100644 --- a/src/citra_qt/citra_qt.vcxproj +++ b/src/citra_qt/citra_qt.vcxproj @@ -130,6 +130,8 @@ <ClCompile Include="config\controller_config.cpp" /> <ClCompile Include="config\controller_config_util.cpp" /> <ClCompile Include="debugger\callstack.cpp" /> + <ClCompile Include="debugger\graphics.cpp" /> + <ClCompile Include="debugger\graphics_cmdlists.cpp" /> <ClCompile Include="debugger\registers.cpp" /> <ClCompile Include="debugger\disassembler.cpp" /> <ClCompile Include="debugger\ramview.cpp" /> @@ -143,9 +145,11 @@ <MOC Include="..\..\externals\qhexedit\qhexedit_p.h" /> <MOC Include="..\..\externals\qhexedit\xbytearray.h" /> <MOC Include="debugger\callstack.hxx" /> - <MOC Include="debugger\registers.hxx" /> <MOC Include="debugger\disassembler.hxx" /> + <MOC Include="debugger\graphics.hxx" /> + <MOC Include="debugger\graphics_cmdlists.hxx" /> <MOC Include="debugger\ramview.hxx" /> + <MOC Include="debugger\registers.hxx" /> <MOC Include="bootmanager.hxx" /> <MOC Include="hotkeys.hxx" /> <MOC Include="main.hxx" /> @@ -182,4 +186,4 @@ <ImportGroup Label="ExtensionTargets"> <Import Project="qt-build.targets" /> </ImportGroup> -</Project>
\ No newline at end of file +</Project> diff --git a/src/citra_qt/citra_qt.vcxproj.filters b/src/citra_qt/citra_qt.vcxproj.filters index 2b3838e29..903082c3c 100644 --- a/src/citra_qt/citra_qt.vcxproj.filters +++ b/src/citra_qt/citra_qt.vcxproj.filters @@ -36,10 +36,16 @@ <ClCompile Include="debugger\callstack.cpp"> <Filter>debugger</Filter> </ClCompile> - <ClCompile Include="debugger\ramview.cpp"> + <ClCompile Include="debugger\disassembler.cpp"> <Filter>debugger</Filter> </ClCompile> - <ClCompile Include="debugger\disassembler.cpp"> + <ClCompile Include="debugger\graphics.cpp"> + <Filter>debugger</Filter> + </ClCompile> + <ClCompile Include="debugger\graphics_cmdlists.cpp"> + <Filter>debugger</Filter> + </ClCompile> + <ClCompile Include="debugger\ramview.cpp"> <Filter>debugger</Filter> </ClCompile> <ClCompile Include="debugger\registers.cpp"> @@ -65,10 +71,16 @@ <MOC Include="debugger\callstack.hxx"> <Filter>debugger</Filter> </MOC> - <MOC Include="debugger\ramview.hxx"> + <MOC Include="debugger\disassembler.hxx"> <Filter>debugger</Filter> </MOC> - <MOC Include="debugger\disassembler.hxx"> + <MOC Include="debugger\graphics.hxx"> + <Filter>debugger</Filter> + </MOC> + <MOC Include="debugger\graphics_cmdlists.hxx"> + <Filter>debugger</Filter> + </MOC> + <MOC Include="debugger\ramview.hxx"> <Filter>debugger</Filter> </MOC> <MOC Include="debugger\registers.hxx"> @@ -106,4 +118,4 @@ <ItemGroup> <Text Include="CMakeLists.txt" /> </ItemGroup> -</Project>
\ No newline at end of file +</Project> diff --git a/src/citra_qt/debugger/graphics.cpp b/src/citra_qt/debugger/graphics.cpp new file mode 100644 index 000000000..9aaade8f9 --- /dev/null +++ b/src/citra_qt/debugger/graphics.cpp @@ -0,0 +1,83 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include "graphics.hxx" +#include <QListView> +#include <QVBoxLayout> +#include <QDebug> + +extern GraphicsDebugger g_debugger; + +GPUCommandStreamItemModel::GPUCommandStreamItemModel(QObject* parent) : QAbstractListModel(parent), command_count(0) +{ + connect(this, SIGNAL(GXCommandFinished(int)), this, SLOT(OnGXCommandFinishedInternal(int))); +} + +int GPUCommandStreamItemModel::rowCount(const QModelIndex& parent) const +{ + return command_count; +} + +QVariant GPUCommandStreamItemModel::data(const QModelIndex& index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + int command_index = index.row(); + const GSP_GPU::GXCommand& command = GetDebugger()->ReadGXCommandHistory(command_index); + if (role == Qt::DisplayRole) + { + std::map<GSP_GPU::GXCommandId, const char*> command_names; + command_names[GSP_GPU::GXCommandId::REQUEST_DMA] = "REQUEST_DMA"; + command_names[GSP_GPU::GXCommandId::SET_COMMAND_LIST_FIRST] = "SET_COMMAND_LIST_FIRST"; + command_names[GSP_GPU::GXCommandId::SET_MEMORY_FILL] = "SET_MEMORY_FILL"; + command_names[GSP_GPU::GXCommandId::SET_DISPLAY_TRANSFER] = "SET_DISPLAY_TRANSFER"; + command_names[GSP_GPU::GXCommandId::SET_TEXTURE_COPY] = "SET_TEXTURE_COPY"; + command_names[GSP_GPU::GXCommandId::SET_COMMAND_LIST_LAST] = "SET_COMMAND_LIST_LAST"; + QString str = QString("%1 %2 %3 %4 %5 %6 %7 %8 %9").arg(command_names[static_cast<GSP_GPU::GXCommandId>(command.id)]) + .arg(command.data[0], 8, 16, QLatin1Char('0')) + .arg(command.data[1], 8, 16, QLatin1Char('0')) + .arg(command.data[2], 8, 16, QLatin1Char('0')) + .arg(command.data[3], 8, 16, QLatin1Char('0')) + .arg(command.data[4], 8, 16, QLatin1Char('0')) + .arg(command.data[5], 8, 16, QLatin1Char('0')) + .arg(command.data[6], 8, 16, QLatin1Char('0')) + .arg(command.data[7], 8, 16, QLatin1Char('0')); + return QVariant(str); + } + else + { + return QVariant(); + } +} + +void GPUCommandStreamItemModel::GXCommandProcessed(int total_command_count) +{ + emit GXCommandFinished(total_command_count); +} + +void GPUCommandStreamItemModel::OnGXCommandFinishedInternal(int total_command_count) +{ + if (total_command_count == 0) + return; + + int prev_command_count = command_count; + command_count = total_command_count; + emit dataChanged(index(prev_command_count,0), index(total_command_count-1,0)); +} + + +GPUCommandStreamWidget::GPUCommandStreamWidget(QWidget* parent) : QDockWidget(tr("Graphics Debugger"), parent) +{ + // TODO: set objectName! + + GPUCommandStreamItemModel* command_model = new GPUCommandStreamItemModel(this); + g_debugger.RegisterObserver(command_model); + + QListView* command_list = new QListView; + command_list->setModel(command_model); + command_list->setFont(QFont("monospace")); + + setWidget(command_list); +} diff --git a/src/citra_qt/debugger/graphics.hxx b/src/citra_qt/debugger/graphics.hxx new file mode 100644 index 000000000..72656f93c --- /dev/null +++ b/src/citra_qt/debugger/graphics.hxx @@ -0,0 +1,43 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include <QAbstractListModel> +#include <QDockWidget> + +#include "video_core/gpu_debugger.h" + +class GPUCommandStreamItemModel : public QAbstractListModel, public GraphicsDebugger::DebuggerObserver +{ + Q_OBJECT + +public: + GPUCommandStreamItemModel(QObject* parent); + + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + +public: + void GXCommandProcessed(int total_command_count) override; + +public slots: + void OnGXCommandFinishedInternal(int total_command_count); + +signals: + void GXCommandFinished(int total_command_count); + +private: + int command_count; +}; + +class GPUCommandStreamWidget : public QDockWidget +{ + Q_OBJECT + +public: + GPUCommandStreamWidget(QWidget* parent = 0); + +private: +}; diff --git a/src/citra_qt/debugger/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics_cmdlists.cpp new file mode 100644 index 000000000..195197ef5 --- /dev/null +++ b/src/citra_qt/debugger/graphics_cmdlists.cpp @@ -0,0 +1,139 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include "graphics_cmdlists.hxx" +#include <QTreeView> + +extern GraphicsDebugger g_debugger; + +GPUCommandListModel::GPUCommandListModel(QObject* parent) : QAbstractItemModel(parent) +{ + root_item = new TreeItem(TreeItem::ROOT, 0, NULL, this); + + connect(this, SIGNAL(CommandListCalled()), this, SLOT(OnCommandListCalledInternal()), Qt::UniqueConnection); +} + +QModelIndex GPUCommandListModel::index(int row, int column, const QModelIndex& parent) const +{ + TreeItem* item; + + if (!parent.isValid()) { + item = root_item; + } else { + item = (TreeItem*)parent.internalPointer(); + } + + return createIndex(row, column, item->children[row]); +} + +QModelIndex GPUCommandListModel::parent(const QModelIndex& child) const +{ + if (!child.isValid()) + return QModelIndex(); + + TreeItem* item = (TreeItem*)child.internalPointer(); + + if (item->parent == NULL) + return QModelIndex(); + + return createIndex(item->parent->index, 0, item->parent); +} + +int GPUCommandListModel::rowCount(const QModelIndex& parent) const +{ + TreeItem* item; + if (!parent.isValid()) { + item = root_item; + } else { + item = (TreeItem*)parent.internalPointer(); + } + return item->children.size(); +} + +int GPUCommandListModel::columnCount(const QModelIndex& parent) const +{ + return 2; +} + +QVariant GPUCommandListModel::data(const QModelIndex& index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + const TreeItem* item = (const TreeItem*)index.internalPointer(); + + if (item->type == TreeItem::COMMAND_LIST) + { + const GraphicsDebugger::PicaCommandList& cmdlist = command_lists[item->index].second; + u32 address = command_lists[item->index].first; + + if (role == Qt::DisplayRole && index.column() == 0) + { + return QVariant(QString("0x%1 bytes at 0x%2").arg(cmdlist.size(), 0, 16).arg(address, 8, 16, QLatin1Char('0'))); + } + } + else + { + // index refers to a specific command + const GraphicsDebugger::PicaCommandList& cmdlist = command_lists[item->parent->index].second; + const GraphicsDebugger::PicaCommand& cmd = cmdlist[item->index]; + const Pica::CommandHeader& header = cmd.GetHeader(); + + if (role == Qt::DisplayRole) { + QString content; + if (index.column() == 0) { + content = Pica::command_names[header.cmd_id]; + content.append(" "); + } else if (index.column() == 1) { + for (int j = 0; j < cmd.size(); ++j) + content.append(QString("%1 ").arg(cmd[j], 8, 16, QLatin1Char('0'))); + } + + return QVariant(content); + } + } + + return QVariant(); +} + +void GPUCommandListModel::OnCommandListCalled(const GraphicsDebugger::PicaCommandList& lst, bool is_new) +{ + emit CommandListCalled(); +} + + +void GPUCommandListModel::OnCommandListCalledInternal() +{ + beginResetModel(); + + command_lists = GetDebugger()->GetCommandLists(); + + // delete root item and rebuild tree + delete root_item; + root_item = new TreeItem(TreeItem::ROOT, 0, NULL, this); + + for (int command_list_idx = 0; command_list_idx < command_lists.size(); ++command_list_idx) { + TreeItem* command_list_item = new TreeItem(TreeItem::COMMAND_LIST, command_list_idx, root_item, root_item); + root_item->children.push_back(command_list_item); + + const GraphicsDebugger::PicaCommandList& command_list = command_lists[command_list_idx].second; + for (int command_idx = 0; command_idx < command_list.size(); ++command_idx) { + TreeItem* command_item = new TreeItem(TreeItem::COMMAND, command_idx, command_list_item, command_list_item); + command_list_item->children.push_back(command_item); + } + } + + endResetModel(); +} + +GPUCommandListWidget::GPUCommandListWidget(QWidget* parent) : QDockWidget(tr("Pica Command List"), parent) +{ + GPUCommandListModel* model = new GPUCommandListModel(this); + g_debugger.RegisterObserver(model); + + QTreeView* tree_widget = new QTreeView; + tree_widget->setModel(model); + tree_widget->setFont(QFont("monospace")); + setWidget(tree_widget); +} diff --git a/src/citra_qt/debugger/graphics_cmdlists.hxx b/src/citra_qt/debugger/graphics_cmdlists.hxx new file mode 100644 index 000000000..b4e6e3c8a --- /dev/null +++ b/src/citra_qt/debugger/graphics_cmdlists.hxx @@ -0,0 +1,64 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include <QAbstractItemModel> +#include <QDockWidget> + +#include "video_core/gpu_debugger.h" + +// TODO: Rename class, since it's not actually a list model anymore... +class GPUCommandListModel : public QAbstractItemModel, public GraphicsDebugger::DebuggerObserver +{ + Q_OBJECT + +public: + GPUCommandListModel(QObject* parent); + + QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex& child) const; + int columnCount(const QModelIndex& parent = QModelIndex()) const; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + +public: + void OnCommandListCalled(const GraphicsDebugger::PicaCommandList& lst, bool is_new) override; + +public slots: + void OnCommandListCalledInternal(); + +signals: + void CommandListCalled(); + +private: + struct TreeItem : public QObject + { + enum Type { + ROOT, + COMMAND_LIST, + COMMAND + }; + + TreeItem(Type type, int index, TreeItem* item_parent, QObject* parent) : QObject(parent), type(type), index(index), parent(item_parent) {} + + Type type; + int index; + std::vector<TreeItem*> children; + TreeItem* parent; + }; + + std::vector<std::pair<u32,GraphicsDebugger::PicaCommandList>> command_lists; + TreeItem* root_item; +}; + +class GPUCommandListWidget : public QDockWidget +{ + Q_OBJECT + +public: + GPUCommandListWidget(QWidget* parent = 0); + +private: +}; diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 9be982909..087716c01 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -19,6 +19,8 @@ #include "debugger/registers.hxx" #include "debugger/callstack.hxx" #include "debugger/ramview.hxx" +#include "debugger/graphics.hxx" +#include "debugger/graphics_cmdlists.hxx" #include "core/system.h" #include "core/loader.h" @@ -47,10 +49,20 @@ GMainWindow::GMainWindow() addDockWidget(Qt::RightDockWidgetArea, callstackWidget); callstackWidget->hide(); + graphicsWidget = new GPUCommandStreamWidget(this); + addDockWidget(Qt::RightDockWidgetArea, graphicsWidget); + callstackWidget->hide(); + + graphicsCommandsWidget = new GPUCommandListWidget(this); + addDockWidget(Qt::RightDockWidgetArea, graphicsCommandsWidget); + callstackWidget->hide(); + QMenu* debug_menu = ui.menu_View->addMenu(tr("Debugging")); debug_menu->addAction(disasmWidget->toggleViewAction()); debug_menu->addAction(registersWidget->toggleViewAction()); debug_menu->addAction(callstackWidget->toggleViewAction()); + debug_menu->addAction(graphicsWidget->toggleViewAction()); + debug_menu->addAction(graphicsCommandsWidget->toggleViewAction()); // Set default UI state // geometry: 55% of the window contents are in the upper screen half, 45% in the lower half diff --git a/src/citra_qt/main.hxx b/src/citra_qt/main.hxx index fa122f76e..6bcb37a30 100644 --- a/src/citra_qt/main.hxx +++ b/src/citra_qt/main.hxx @@ -10,6 +10,8 @@ class GRenderWindow; class DisassemblerWidget; class RegistersWidget; class CallstackWidget; +class GPUCommandStreamWidget; +class GPUCommandListWidget; class GMainWindow : public QMainWindow { @@ -50,6 +52,8 @@ private: DisassemblerWidget* disasmWidget; RegistersWidget* registersWidget; CallstackWidget* callstackWidget; + GPUCommandStreamWidget* graphicsWidget; + GPUCommandListWidget* graphicsCommandsWidget; }; #endif // _CITRA_QT_MAIN_HXX_ |