diff options
Diffstat (limited to 'src/yuzu/debugger/graphics')
| -rw-r--r-- | src/yuzu/debugger/graphics/graphics_surface.cpp | 206 | 
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 @@  #include <QDebug>  #include <QFileDialog>  #include <QLabel> +#include <QMessageBox>  #include <QMouseEvent>  #include <QPushButton>  #include <QScrollArea> @@ -95,50 +96,91 @@ GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr<Tegra::DebugContext      surface_picker_y_control = new QSpinBox;      surface_picker_y_control->setRange(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); @@ -157,22 +199,20 @@ GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr<Tegra::DebugContext      // Connections      connect(this, &GraphicsSurfaceWidget::Update, this, &GraphicsSurfaceWidget::OnUpdate); -    connect(surface_source_list, -            static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, +    connect(surface_source_list, qOverload<int>(&QComboBox::currentIndexChanged), this,              &GraphicsSurfaceWidget::OnSurfaceSourceChanged);      connect(surface_address_control, &CSpinBox::ValueChanged, this,              &GraphicsSurfaceWidget::OnSurfaceAddressChanged); -    connect(surface_width_control, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), -            this, &GraphicsSurfaceWidget::OnSurfaceWidthChanged); -    connect(surface_height_control, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), -            this, &GraphicsSurfaceWidget::OnSurfaceHeightChanged); -    connect(surface_format_control, -            static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, +    connect(surface_width_control, qOverload<int>(&QSpinBox::valueChanged), this, +            &GraphicsSurfaceWidget::OnSurfaceWidthChanged); +    connect(surface_height_control, qOverload<int>(&QSpinBox::valueChanged), this, +            &GraphicsSurfaceWidget::OnSurfaceHeightChanged); +    connect(surface_format_control, qOverload<int>(&QComboBox::currentIndexChanged), this,              &GraphicsSurfaceWidget::OnSurfaceFormatChanged); -    connect(surface_picker_x_control, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), -            this, &GraphicsSurfaceWidget::OnSurfacePickerXChanged); -    connect(surface_picker_y_control, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), -            this, &GraphicsSurfaceWidget::OnSurfacePickerYChanged); +    connect(surface_picker_x_control, qOverload<int>(&QSpinBox::valueChanged), this, +            &GraphicsSurfaceWidget::OnSurfacePickerXChanged); +    connect(surface_picker_y_control, qOverload<int>(&QSpinBox::valueChanged), this, +            &GraphicsSurfaceWidget::OnSurfacePickerYChanged);      connect(save_surface, &QPushButton::clicked, this, &GraphicsSurfaceWidget::SaveSurface);      auto main_widget = new QWidget; @@ -420,40 +460,56 @@ 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) { +        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(); -        std::optional<VAddr> address = gpu.MemoryManager().GpuToCpuAddress(surface_address); +        const std::optional<VAddr> 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<const char*>(buffer), size); -        file.write(data); +        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<const char*>(buffer), size); +        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");      } | 
