From 9d296f8a358dd6e033fc779d452a7440b4c48514 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 5 Apr 2019 19:09:53 -0400 Subject: [PATCH 1/4] yuzu/debugger/graphics_surface: Fill in missing surface format listings Fills in the missing surface types that were marked as unknown. The order corresponds with the TextureFormat enum within video_core/texture.h. We also don't need to all of these strings as translatable (only the first string, as it's an English word). --- .../debugger/graphics/graphics_surface.cpp | 127 ++++++++++++------ 1 file changed, 84 insertions(+), 43 deletions(-) diff --git a/src/yuzu/debugger/graphics/graphics_surface.cpp b/src/yuzu/debugger/graphics/graphics_surface.cpp index 11023ed63..946a17dd8 100644 --- a/src/yuzu/debugger/graphics/graphics_surface.cpp +++ b/src/yuzu/debugger/graphics/graphics_surface.cpp @@ -95,50 +95,91 @@ GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptrsetRange(0, max_dimension - 1); - surface_format_control = new QComboBox; - + // clang-format off // Color formats sorted by Maxwell texture format index - surface_format_control->addItem(tr("None")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("A8R8G8B8")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("Unknown")); - surface_format_control->addItem(tr("DXT1")); - surface_format_control->addItem(tr("DXT23")); - surface_format_control->addItem(tr("DXT45")); - surface_format_control->addItem(tr("DXN1")); - surface_format_control->addItem(tr("DXN2")); + const QStringList surface_formats{ + tr("None"), + QStringLiteral("R32_G32_B32_A32"), + QStringLiteral("R32_G32_B32"), + QStringLiteral("R16_G16_B16_A16"), + QStringLiteral("R32_G32"), + QStringLiteral("R32_B24G8"), + QStringLiteral("ETC2_RGB"), + QStringLiteral("X8B8G8R8"), + QStringLiteral("A8R8G8B8"), + QStringLiteral("A2B10G10R10"), + QStringLiteral("ETC2_RGB_PTA"), + QStringLiteral("ETC2_RGBA"), + QStringLiteral("R16_G16"), + QStringLiteral("G8R24"), + QStringLiteral("G24R8"), + QStringLiteral("R32"), + QStringLiteral("BC6H_SF16"), + QStringLiteral("BC6H_UF16"), + QStringLiteral("A4B4G4R4"), + QStringLiteral("A5B5G5R1"), + QStringLiteral("A1B5G5R5"), + QStringLiteral("B5G6R5"), + QStringLiteral("B6G5R5"), + QStringLiteral("BC7U"), + QStringLiteral("G8R8"), + QStringLiteral("EAC"), + QStringLiteral("EACX2"), + QStringLiteral("R16"), + QStringLiteral("Y8_VIDEO"), + QStringLiteral("R8"), + QStringLiteral("G4R4"), + QStringLiteral("R1"), + QStringLiteral("E5B9G9R9_SHAREDEXP"), + QStringLiteral("BF10GF11RF11"), + QStringLiteral("G8B8G8R8"), + QStringLiteral("B8G8R8G8"), + QStringLiteral("DXT1"), + QStringLiteral("DXT23"), + QStringLiteral("DXT45"), + QStringLiteral("DXN1"), + QStringLiteral("DXN2"), + QStringLiteral("Z24S8"), + QStringLiteral("X8Z24"), + QStringLiteral("S8Z24"), + QStringLiteral("X4V4Z24__COV4R4V"), + QStringLiteral("X4V4Z24__COV8R8V"), + QStringLiteral("V8Z24__COV4R12V"), + QStringLiteral("ZF32"), + QStringLiteral("ZF32_X24S8"), + QStringLiteral("X8Z24_X20V4S8__COV4R4V"), + QStringLiteral("X8Z24_X20V4S8__COV8R8V"), + QStringLiteral("ZF32_X20V4X8__COV4R4V"), + QStringLiteral("ZF32_X20V4X8__COV8R8V"), + QStringLiteral("ZF32_X20V4S8__COV4R4V"), + QStringLiteral("ZF32_X20V4S8__COV8R8V"), + QStringLiteral("X8Z24_X16V8S8__COV4R12V"), + QStringLiteral("ZF32_X16V8X8__COV4R12V"), + QStringLiteral("ZF32_X16V8S8__COV4R12V"), + QStringLiteral("Z16"), + QStringLiteral("V8Z24__COV8R24V"), + QStringLiteral("X8Z24_X16V8S8__COV8R24V"), + QStringLiteral("ZF32_X16V8X8__COV8R24V"), + QStringLiteral("ZF32_X16V8S8__COV8R24V"), + QStringLiteral("ASTC_2D_4X4"), + QStringLiteral("ASTC_2D_5X5"), + QStringLiteral("ASTC_2D_6X6"), + QStringLiteral("ASTC_2D_8X8"), + QStringLiteral("ASTC_2D_10X10"), + QStringLiteral("ASTC_2D_12X12"), + QStringLiteral("ASTC_2D_5X4"), + QStringLiteral("ASTC_2D_6X5"), + QStringLiteral("ASTC_2D_8X6"), + QStringLiteral("ASTC_2D_10X8"), + QStringLiteral("ASTC_2D_12X10"), + QStringLiteral("ASTC_2D_8X5"), + QStringLiteral("ASTC_2D_10X5"), + QStringLiteral("ASTC_2D_10X6"), + }; + // clang-format on + + surface_format_control = new QComboBox; + surface_format_control->addItems(surface_formats); surface_info_label = new QLabel(); surface_info_label->setWordWrap(true); From bbeb859122e322e062ee271a0dba5b46cca87ef7 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 5 Apr 2019 19:26:39 -0400 Subject: [PATCH 2/4] yuzu/debugger/graphics_surface: Clean up connection overload deduction We can utilize qOverload with the signal connections to make the function deducing a little less ugly. --- .../debugger/graphics/graphics_surface.cpp | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/yuzu/debugger/graphics/graphics_surface.cpp b/src/yuzu/debugger/graphics/graphics_surface.cpp index 946a17dd8..886da9587 100644 --- a/src/yuzu/debugger/graphics/graphics_surface.cpp +++ b/src/yuzu/debugger/graphics/graphics_surface.cpp @@ -198,22 +198,20 @@ GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr(&QComboBox::currentIndexChanged), this, + connect(surface_source_list, qOverload(&QComboBox::currentIndexChanged), this, &GraphicsSurfaceWidget::OnSurfaceSourceChanged); connect(surface_address_control, &CSpinBox::ValueChanged, this, &GraphicsSurfaceWidget::OnSurfaceAddressChanged); - connect(surface_width_control, static_cast(&QSpinBox::valueChanged), - this, &GraphicsSurfaceWidget::OnSurfaceWidthChanged); - connect(surface_height_control, static_cast(&QSpinBox::valueChanged), - this, &GraphicsSurfaceWidget::OnSurfaceHeightChanged); - connect(surface_format_control, - static_cast(&QComboBox::currentIndexChanged), this, + connect(surface_width_control, qOverload(&QSpinBox::valueChanged), this, + &GraphicsSurfaceWidget::OnSurfaceWidthChanged); + connect(surface_height_control, qOverload(&QSpinBox::valueChanged), this, + &GraphicsSurfaceWidget::OnSurfaceHeightChanged); + connect(surface_format_control, qOverload(&QComboBox::currentIndexChanged), this, &GraphicsSurfaceWidget::OnSurfaceFormatChanged); - connect(surface_picker_x_control, static_cast(&QSpinBox::valueChanged), - this, &GraphicsSurfaceWidget::OnSurfacePickerXChanged); - connect(surface_picker_y_control, static_cast(&QSpinBox::valueChanged), - this, &GraphicsSurfaceWidget::OnSurfacePickerYChanged); + connect(surface_picker_x_control, qOverload(&QSpinBox::valueChanged), this, + &GraphicsSurfaceWidget::OnSurfacePickerXChanged); + connect(surface_picker_y_control, qOverload(&QSpinBox::valueChanged), this, + &GraphicsSurfaceWidget::OnSurfacePickerYChanged); connect(save_surface, &QPushButton::clicked, this, &GraphicsSurfaceWidget::SaveSurface); auto main_widget = new QWidget; From 845607481c3b4a25125df2052c4416fcc2badbb7 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 5 Apr 2019 19:32:58 -0400 Subject: [PATCH 3/4] yuzu/debugger/graphics_surface: Tidy up SaveSurface - Use QStringLiteral where applicable. - Use const where applicable - Remove unnecessary precondition check (we already assert the pixbuf being non null) --- .../debugger/graphics/graphics_surface.cpp | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/yuzu/debugger/graphics/graphics_surface.cpp b/src/yuzu/debugger/graphics/graphics_surface.cpp index 886da9587..31d412ff5 100644 --- a/src/yuzu/debugger/graphics/graphics_surface.cpp +++ b/src/yuzu/debugger/graphics/graphics_surface.cpp @@ -459,39 +459,38 @@ void GraphicsSurfaceWidget::OnUpdate() { } void GraphicsSurfaceWidget::SaveSurface() { - QString png_filter = tr("Portable Network Graphic (*.png)"); - QString bin_filter = tr("Binary data (*.bin)"); + const QString png_filter = tr("Portable Network Graphic (*.png)"); + const QString bin_filter = tr("Binary data (*.bin)"); - QString selectedFilter; - QString filename = QFileDialog::getSaveFileName( + QString selected_filter; + const QString filename = QFileDialog::getSaveFileName( this, tr("Save Surface"), - QString("texture-0x%1.png").arg(QString::number(surface_address, 16)), - QString("%1;;%2").arg(png_filter, bin_filter), &selectedFilter); + QStringLiteral("texture-0x%1.png").arg(QString::number(surface_address, 16)), + QStringLiteral("%1;;%2").arg(png_filter, bin_filter), &selected_filter); if (filename.isEmpty()) { // If the user canceled the dialog, don't save anything. return; } - if (selectedFilter == png_filter) { - const QPixmap* pixmap = surface_picture_label->pixmap(); + if (selected_filter == png_filter) { + const QPixmap* const pixmap = surface_picture_label->pixmap(); ASSERT_MSG(pixmap != nullptr, "No pixmap set"); QFile file(filename); file.open(QIODevice::WriteOnly); - if (pixmap) - pixmap->save(&file, "PNG"); - } else if (selectedFilter == bin_filter) { + pixmap->save(&file, "PNG"); + } else if (selected_filter == bin_filter) { auto& gpu = Core::System::GetInstance().GPU(); - std::optional address = gpu.MemoryManager().GpuToCpuAddress(surface_address); + const std::optional address = gpu.MemoryManager().GpuToCpuAddress(surface_address); - const u8* buffer = Memory::GetPointer(*address); + const u8* const buffer = Memory::GetPointer(*address); ASSERT_MSG(buffer != nullptr, "Memory not accessible"); QFile file(filename); file.open(QIODevice::WriteOnly); - int size = surface_width * surface_height * Tegra::Texture::BytesPerPixel(surface_format); - QByteArray data(reinterpret_cast(buffer), size); + const int size = surface_width * surface_height * Tegra::Texture::BytesPerPixel(surface_format); + const QByteArray data(reinterpret_cast(buffer), size); file.write(data); } else { UNREACHABLE_MSG("Unhandled filter selected"); From c0e320ad0da51b5245a071cecbfcdae7a461522f Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 5 Apr 2019 19:45:10 -0400 Subject: [PATCH 4/4] yuzu/debugger/graphics_surface: Display error messages for file I/O errors --- .../debugger/graphics/graphics_surface.cpp | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/yuzu/debugger/graphics/graphics_surface.cpp b/src/yuzu/debugger/graphics/graphics_surface.cpp index 31d412ff5..f2d14becf 100644 --- a/src/yuzu/debugger/graphics/graphics_surface.cpp +++ b/src/yuzu/debugger/graphics/graphics_surface.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -477,9 +478,16 @@ void GraphicsSurfaceWidget::SaveSurface() { const QPixmap* const pixmap = surface_picture_label->pixmap(); ASSERT_MSG(pixmap != nullptr, "No pixmap set"); - QFile file(filename); - file.open(QIODevice::WriteOnly); - pixmap->save(&file, "PNG"); + QFile file{filename}; + if (!file.open(QIODevice::WriteOnly)) { + QMessageBox::warning(this, tr("Error"), tr("Failed to open file '%1'").arg(filename)); + return; + } + + if (!pixmap->save(&file, "PNG")) { + QMessageBox::warning(this, tr("Error"), + tr("Failed to save surface data to file '%1'").arg(filename)); + } } else if (selected_filter == bin_filter) { auto& gpu = Core::System::GetInstance().GPU(); const std::optional address = gpu.MemoryManager().GpuToCpuAddress(surface_address); @@ -487,11 +495,21 @@ void GraphicsSurfaceWidget::SaveSurface() { const u8* const buffer = Memory::GetPointer(*address); ASSERT_MSG(buffer != nullptr, "Memory not accessible"); - QFile file(filename); - file.open(QIODevice::WriteOnly); - const int size = surface_width * surface_height * Tegra::Texture::BytesPerPixel(surface_format); + QFile file{filename}; + if (!file.open(QIODevice::WriteOnly)) { + QMessageBox::warning(this, tr("Error"), tr("Failed to open file '%1'").arg(filename)); + return; + } + + const int size = + surface_width * surface_height * Tegra::Texture::BytesPerPixel(surface_format); const QByteArray data(reinterpret_cast(buffer), size); - file.write(data); + if (file.write(data) != data.size()) { + QMessageBox::warning( + this, tr("Error"), + tr("Failed to completely write surface data to file. The saved data will " + "likely be corrupt.")); + } } else { UNREACHABLE_MSG("Unhandled filter selected"); }