summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/yuzu/debugger/graphics/graphics_surface.cpp206
1 files changed, 131 insertions, 75 deletions
diff --git a/src/yuzu/debugger/graphics/graphics_surface.cpp b/src/yuzu/debugger/graphics/graphics_surface.cpp
index 11023ed63..f2d14becf 100644
--- a/src/yuzu/debugger/graphics/graphics_surface.cpp
+++ b/src/yuzu/debugger/graphics/graphics_surface.cpp
@@ -7,6 +7,7 @@
7#include <QDebug> 7#include <QDebug>
8#include <QFileDialog> 8#include <QFileDialog>
9#include <QLabel> 9#include <QLabel>
10#include <QMessageBox>
10#include <QMouseEvent> 11#include <QMouseEvent>
11#include <QPushButton> 12#include <QPushButton>
12#include <QScrollArea> 13#include <QScrollArea>
@@ -95,50 +96,91 @@ GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr<Tegra::DebugContext
95 surface_picker_y_control = new QSpinBox; 96 surface_picker_y_control = new QSpinBox;
96 surface_picker_y_control->setRange(0, max_dimension - 1); 97 surface_picker_y_control->setRange(0, max_dimension - 1);
97 98
98 surface_format_control = new QComboBox; 99 // clang-format off
99
100 // Color formats sorted by Maxwell texture format index 100 // Color formats sorted by Maxwell texture format index
101 surface_format_control->addItem(tr("None")); 101 const QStringList surface_formats{
102 surface_format_control->addItem(tr("Unknown")); 102 tr("None"),
103 surface_format_control->addItem(tr("Unknown")); 103 QStringLiteral("R32_G32_B32_A32"),
104 surface_format_control->addItem(tr("Unknown")); 104 QStringLiteral("R32_G32_B32"),
105 surface_format_control->addItem(tr("Unknown")); 105 QStringLiteral("R16_G16_B16_A16"),
106 surface_format_control->addItem(tr("Unknown")); 106 QStringLiteral("R32_G32"),
107 surface_format_control->addItem(tr("Unknown")); 107 QStringLiteral("R32_B24G8"),
108 surface_format_control->addItem(tr("Unknown")); 108 QStringLiteral("ETC2_RGB"),
109 surface_format_control->addItem(tr("A8R8G8B8")); 109 QStringLiteral("X8B8G8R8"),
110 surface_format_control->addItem(tr("Unknown")); 110 QStringLiteral("A8R8G8B8"),
111 surface_format_control->addItem(tr("Unknown")); 111 QStringLiteral("A2B10G10R10"),
112 surface_format_control->addItem(tr("Unknown")); 112 QStringLiteral("ETC2_RGB_PTA"),
113 surface_format_control->addItem(tr("Unknown")); 113 QStringLiteral("ETC2_RGBA"),
114 surface_format_control->addItem(tr("Unknown")); 114 QStringLiteral("R16_G16"),
115 surface_format_control->addItem(tr("Unknown")); 115 QStringLiteral("G8R24"),
116 surface_format_control->addItem(tr("Unknown")); 116 QStringLiteral("G24R8"),
117 surface_format_control->addItem(tr("Unknown")); 117 QStringLiteral("R32"),
118 surface_format_control->addItem(tr("Unknown")); 118 QStringLiteral("BC6H_SF16"),
119 surface_format_control->addItem(tr("Unknown")); 119 QStringLiteral("BC6H_UF16"),
120 surface_format_control->addItem(tr("Unknown")); 120 QStringLiteral("A4B4G4R4"),
121 surface_format_control->addItem(tr("Unknown")); 121 QStringLiteral("A5B5G5R1"),
122 surface_format_control->addItem(tr("Unknown")); 122 QStringLiteral("A1B5G5R5"),
123 surface_format_control->addItem(tr("Unknown")); 123 QStringLiteral("B5G6R5"),
124 surface_format_control->addItem(tr("Unknown")); 124 QStringLiteral("B6G5R5"),
125 surface_format_control->addItem(tr("Unknown")); 125 QStringLiteral("BC7U"),
126 surface_format_control->addItem(tr("Unknown")); 126 QStringLiteral("G8R8"),
127 surface_format_control->addItem(tr("Unknown")); 127 QStringLiteral("EAC"),
128 surface_format_control->addItem(tr("Unknown")); 128 QStringLiteral("EACX2"),
129 surface_format_control->addItem(tr("Unknown")); 129 QStringLiteral("R16"),
130 surface_format_control->addItem(tr("Unknown")); 130 QStringLiteral("Y8_VIDEO"),
131 surface_format_control->addItem(tr("Unknown")); 131 QStringLiteral("R8"),
132 surface_format_control->addItem(tr("Unknown")); 132 QStringLiteral("G4R4"),
133 surface_format_control->addItem(tr("Unknown")); 133 QStringLiteral("R1"),
134 surface_format_control->addItem(tr("Unknown")); 134 QStringLiteral("E5B9G9R9_SHAREDEXP"),
135 surface_format_control->addItem(tr("Unknown")); 135 QStringLiteral("BF10GF11RF11"),
136 surface_format_control->addItem(tr("Unknown")); 136 QStringLiteral("G8B8G8R8"),
137 surface_format_control->addItem(tr("DXT1")); 137 QStringLiteral("B8G8R8G8"),
138 surface_format_control->addItem(tr("DXT23")); 138 QStringLiteral("DXT1"),
139 surface_format_control->addItem(tr("DXT45")); 139 QStringLiteral("DXT23"),
140 surface_format_control->addItem(tr("DXN1")); 140 QStringLiteral("DXT45"),
141 surface_format_control->addItem(tr("DXN2")); 141 QStringLiteral("DXN1"),
142 QStringLiteral("DXN2"),
143 QStringLiteral("Z24S8"),
144 QStringLiteral("X8Z24"),
145 QStringLiteral("S8Z24"),
146 QStringLiteral("X4V4Z24__COV4R4V"),
147 QStringLiteral("X4V4Z24__COV8R8V"),
148 QStringLiteral("V8Z24__COV4R12V"),
149 QStringLiteral("ZF32"),
150 QStringLiteral("ZF32_X24S8"),
151 QStringLiteral("X8Z24_X20V4S8__COV4R4V"),
152 QStringLiteral("X8Z24_X20V4S8__COV8R8V"),
153 QStringLiteral("ZF32_X20V4X8__COV4R4V"),
154 QStringLiteral("ZF32_X20V4X8__COV8R8V"),
155 QStringLiteral("ZF32_X20V4S8__COV4R4V"),
156 QStringLiteral("ZF32_X20V4S8__COV8R8V"),
157 QStringLiteral("X8Z24_X16V8S8__COV4R12V"),
158 QStringLiteral("ZF32_X16V8X8__COV4R12V"),
159 QStringLiteral("ZF32_X16V8S8__COV4R12V"),
160 QStringLiteral("Z16"),
161 QStringLiteral("V8Z24__COV8R24V"),
162 QStringLiteral("X8Z24_X16V8S8__COV8R24V"),
163 QStringLiteral("ZF32_X16V8X8__COV8R24V"),
164 QStringLiteral("ZF32_X16V8S8__COV8R24V"),
165 QStringLiteral("ASTC_2D_4X4"),
166 QStringLiteral("ASTC_2D_5X5"),
167 QStringLiteral("ASTC_2D_6X6"),
168 QStringLiteral("ASTC_2D_8X8"),
169 QStringLiteral("ASTC_2D_10X10"),
170 QStringLiteral("ASTC_2D_12X12"),
171 QStringLiteral("ASTC_2D_5X4"),
172 QStringLiteral("ASTC_2D_6X5"),
173 QStringLiteral("ASTC_2D_8X6"),
174 QStringLiteral("ASTC_2D_10X8"),
175 QStringLiteral("ASTC_2D_12X10"),
176 QStringLiteral("ASTC_2D_8X5"),
177 QStringLiteral("ASTC_2D_10X5"),
178 QStringLiteral("ASTC_2D_10X6"),
179 };
180 // clang-format on
181
182 surface_format_control = new QComboBox;
183 surface_format_control->addItems(surface_formats);
142 184
143 surface_info_label = new QLabel(); 185 surface_info_label = new QLabel();
144 surface_info_label->setWordWrap(true); 186 surface_info_label->setWordWrap(true);
@@ -157,22 +199,20 @@ GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr<Tegra::DebugContext
157 199
158 // Connections 200 // Connections
159 connect(this, &GraphicsSurfaceWidget::Update, this, &GraphicsSurfaceWidget::OnUpdate); 201 connect(this, &GraphicsSurfaceWidget::Update, this, &GraphicsSurfaceWidget::OnUpdate);
160 connect(surface_source_list, 202 connect(surface_source_list, qOverload<int>(&QComboBox::currentIndexChanged), this,
161 static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
162 &GraphicsSurfaceWidget::OnSurfaceSourceChanged); 203 &GraphicsSurfaceWidget::OnSurfaceSourceChanged);
163 connect(surface_address_control, &CSpinBox::ValueChanged, this, 204 connect(surface_address_control, &CSpinBox::ValueChanged, this,
164 &GraphicsSurfaceWidget::OnSurfaceAddressChanged); 205 &GraphicsSurfaceWidget::OnSurfaceAddressChanged);
165 connect(surface_width_control, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), 206 connect(surface_width_control, qOverload<int>(&QSpinBox::valueChanged), this,
166 this, &GraphicsSurfaceWidget::OnSurfaceWidthChanged); 207 &GraphicsSurfaceWidget::OnSurfaceWidthChanged);
167 connect(surface_height_control, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), 208 connect(surface_height_control, qOverload<int>(&QSpinBox::valueChanged), this,
168 this, &GraphicsSurfaceWidget::OnSurfaceHeightChanged); 209 &GraphicsSurfaceWidget::OnSurfaceHeightChanged);
169 connect(surface_format_control, 210 connect(surface_format_control, qOverload<int>(&QComboBox::currentIndexChanged), this,
170 static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
171 &GraphicsSurfaceWidget::OnSurfaceFormatChanged); 211 &GraphicsSurfaceWidget::OnSurfaceFormatChanged);
172 connect(surface_picker_x_control, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), 212 connect(surface_picker_x_control, qOverload<int>(&QSpinBox::valueChanged), this,
173 this, &GraphicsSurfaceWidget::OnSurfacePickerXChanged); 213 &GraphicsSurfaceWidget::OnSurfacePickerXChanged);
174 connect(surface_picker_y_control, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), 214 connect(surface_picker_y_control, qOverload<int>(&QSpinBox::valueChanged), this,
175 this, &GraphicsSurfaceWidget::OnSurfacePickerYChanged); 215 &GraphicsSurfaceWidget::OnSurfacePickerYChanged);
176 connect(save_surface, &QPushButton::clicked, this, &GraphicsSurfaceWidget::SaveSurface); 216 connect(save_surface, &QPushButton::clicked, this, &GraphicsSurfaceWidget::SaveSurface);
177 217
178 auto main_widget = new QWidget; 218 auto main_widget = new QWidget;
@@ -420,40 +460,56 @@ void GraphicsSurfaceWidget::OnUpdate() {
420} 460}
421 461
422void GraphicsSurfaceWidget::SaveSurface() { 462void GraphicsSurfaceWidget::SaveSurface() {
423 QString png_filter = tr("Portable Network Graphic (*.png)"); 463 const QString png_filter = tr("Portable Network Graphic (*.png)");
424 QString bin_filter = tr("Binary data (*.bin)"); 464 const QString bin_filter = tr("Binary data (*.bin)");
425 465
426 QString selectedFilter; 466 QString selected_filter;
427 QString filename = QFileDialog::getSaveFileName( 467 const QString filename = QFileDialog::getSaveFileName(
428 this, tr("Save Surface"), 468 this, tr("Save Surface"),
429 QString("texture-0x%1.png").arg(QString::number(surface_address, 16)), 469 QStringLiteral("texture-0x%1.png").arg(QString::number(surface_address, 16)),
430 QString("%1;;%2").arg(png_filter, bin_filter), &selectedFilter); 470 QStringLiteral("%1;;%2").arg(png_filter, bin_filter), &selected_filter);
431 471
432 if (filename.isEmpty()) { 472 if (filename.isEmpty()) {
433 // If the user canceled the dialog, don't save anything. 473 // If the user canceled the dialog, don't save anything.
434 return; 474 return;
435 } 475 }
436 476
437 if (selectedFilter == png_filter) { 477 if (selected_filter == png_filter) {
438 const QPixmap* pixmap = surface_picture_label->pixmap(); 478 const QPixmap* const pixmap = surface_picture_label->pixmap();
439 ASSERT_MSG(pixmap != nullptr, "No pixmap set"); 479 ASSERT_MSG(pixmap != nullptr, "No pixmap set");
440 480
441 QFile file(filename); 481 QFile file{filename};
442 file.open(QIODevice::WriteOnly); 482 if (!file.open(QIODevice::WriteOnly)) {
443 if (pixmap) 483 QMessageBox::warning(this, tr("Error"), tr("Failed to open file '%1'").arg(filename));
444 pixmap->save(&file, "PNG"); 484 return;
445 } else if (selectedFilter == bin_filter) { 485 }
486
487 if (!pixmap->save(&file, "PNG")) {
488 QMessageBox::warning(this, tr("Error"),
489 tr("Failed to save surface data to file '%1'").arg(filename));
490 }
491 } else if (selected_filter == bin_filter) {
446 auto& gpu = Core::System::GetInstance().GPU(); 492 auto& gpu = Core::System::GetInstance().GPU();
447 std::optional<VAddr> address = gpu.MemoryManager().GpuToCpuAddress(surface_address); 493 const std::optional<VAddr> address = gpu.MemoryManager().GpuToCpuAddress(surface_address);
448 494
449 const u8* buffer = Memory::GetPointer(*address); 495 const u8* const buffer = Memory::GetPointer(*address);
450 ASSERT_MSG(buffer != nullptr, "Memory not accessible"); 496 ASSERT_MSG(buffer != nullptr, "Memory not accessible");
451 497
452 QFile file(filename); 498 QFile file{filename};
453 file.open(QIODevice::WriteOnly); 499 if (!file.open(QIODevice::WriteOnly)) {
454 int size = surface_width * surface_height * Tegra::Texture::BytesPerPixel(surface_format); 500 QMessageBox::warning(this, tr("Error"), tr("Failed to open file '%1'").arg(filename));
455 QByteArray data(reinterpret_cast<const char*>(buffer), size); 501 return;
456 file.write(data); 502 }
503
504 const int size =
505 surface_width * surface_height * Tegra::Texture::BytesPerPixel(surface_format);
506 const QByteArray data(reinterpret_cast<const char*>(buffer), size);
507 if (file.write(data) != data.size()) {
508 QMessageBox::warning(
509 this, tr("Error"),
510 tr("Failed to completely write surface data to file. The saved data will "
511 "likely be corrupt."));
512 }
457 } else { 513 } else {
458 UNREACHABLE_MSG("Unhandled filter selected"); 514 UNREACHABLE_MSG("Unhandled filter selected");
459 } 515 }