From 39e60cfeb10ef317521ff1685df3d265d2c9d5ef Mon Sep 17 00:00:00 2001
From: Subv <subv2112@gmail.com>
Date: Thu, 22 Mar 2018 16:40:11 -0500
Subject: [PATCH] Frontend: Updated the surface view debug widget to work with
 Maxwell surfaces.

---
 src/video_core/gpu.h                          |  4 ++
 src/video_core/textures/decoders.cpp          | 11 +++++
 .../debugger/graphics/graphics_surface.cpp    | 42 ++++++++++---------
 3 files changed, 38 insertions(+), 19 deletions(-)

diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index 778b63218a..8183b12e91 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -13,6 +13,10 @@
 
 namespace Tegra {
 
+enum class RenderTargetFormat {
+    RGBA8_UNORM = 0xD5,
+};
+
 class DebugContext;
 
 /**
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index 300267209d..2e87281ebc 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -48,6 +48,8 @@ u32 BytesPerPixel(TextureFormat format) {
     case TextureFormat::DXT1:
         // In this case a 'pixel' actually refers to a 4x4 tile.
         return 8;
+    case TextureFormat::A8R8G8B8:
+        return 4;
     default:
         UNIMPLEMENTED_MSG("Format not implemented");
         break;
@@ -68,6 +70,10 @@ std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width,
         CopySwizzledData(width / 4, height / 4, bytes_per_pixel, bytes_per_pixel, data,
                          unswizzled_data.data(), true, DefaultBlockHeight);
         break;
+    case TextureFormat::A8R8G8B8:
+        CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data,
+                         unswizzled_data.data(), true, DefaultBlockHeight);
+        break;
     default:
         UNIMPLEMENTED_MSG("Format not implemented");
         break;
@@ -82,6 +88,11 @@ std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat
 
     // TODO(Subv): Implement.
     switch (format) {
+    case TextureFormat::DXT1:
+    case TextureFormat::A8R8G8B8:
+        // TODO(Subv): For the time being just forward the same data without any decoding.
+        rgba_data = texture_data;
+        break;
     default:
         UNIMPLEMENTED_MSG("Format not implemented");
         break;
diff --git a/src/yuzu/debugger/graphics/graphics_surface.cpp b/src/yuzu/debugger/graphics/graphics_surface.cpp
index 54b816054b..d061013da6 100644
--- a/src/yuzu/debugger/graphics/graphics_surface.cpp
+++ b/src/yuzu/debugger/graphics/graphics_surface.cpp
@@ -13,12 +13,23 @@
 #include <QSpinBox>
 #include "core/core.h"
 #include "video_core/engines/maxwell_3d.h"
+#include "video_core/gpu.h"
 #include "video_core/textures/decoders.h"
 #include "video_core/textures/texture.h"
 #include "video_core/utils.h"
 #include "yuzu/debugger/graphics/graphics_surface.h"
 #include "yuzu/util/spinbox.h"
 
+static Tegra::Texture::TextureFormat ConvertToTextureFormat(
+    Tegra::RenderTargetFormat render_target_format) {
+    switch (render_target_format) {
+    case Tegra::RenderTargetFormat::RGBA8_UNORM:
+        return Tegra::Texture::TextureFormat::A8R8G8B8;
+    default:
+        UNIMPLEMENTED_MSG("Unimplemented RT format");
+    }
+}
+
 SurfacePicture::SurfacePicture(QWidget* parent, GraphicsSurfaceWidget* surface_widget_)
     : QLabel(parent), surface_widget(surface_widget_) {}
 SurfacePicture::~SurfacePicture() {}
@@ -62,7 +73,7 @@ GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr<Tegra::DebugContext
 
     surface_address_control = new CSpinBox;
     surface_address_control->SetBase(16);
-    surface_address_control->SetRange(0, 0xFFFFFFFF);
+    surface_address_control->SetRange(0, 0x7FFFFFFFFFFFFFFF);
     surface_address_control->SetPrefix("0x");
 
     unsigned max_dimension = 16384; // TODO: Find actual maximum
@@ -243,7 +254,7 @@ void GraphicsSurfaceWidget::OnSurfaceSourceChanged(int new_value) {
 
 void GraphicsSurfaceWidget::OnSurfaceAddressChanged(qint64 new_value) {
     if (surface_address != new_value) {
-        surface_address = static_cast<unsigned>(new_value);
+        surface_address = static_cast<Tegra::GPUVAddr>(new_value);
 
         surface_source_list->setCurrentIndex(static_cast<int>(Source::Custom));
         emit Update();
@@ -302,13 +313,6 @@ void GraphicsSurfaceWidget::Pick(int x, int y) {
         return;
     }
 
-    u8* buffer = Memory::GetPhysicalPointer(surface_address);
-    if (buffer == nullptr) {
-        surface_info_label->setText(tr("(unable to access pixel data)"));
-        surface_info_label->setAlignment(Qt::AlignCenter);
-        return;
-    }
-
     surface_info_label->setText(QString("Raw: <Unimplemented>\n(%1)").arg("<Unimplemented>"));
     surface_info_label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
 }
@@ -318,8 +322,6 @@ void GraphicsSurfaceWidget::OnUpdate() {
 
     QPixmap pixmap;
 
-    Tegra::GPUVAddr surface_address = 0;
-
     switch (surface_source) {
     case Source::RenderTarget0:
     case Source::RenderTarget1:
@@ -333,11 +335,13 @@ void GraphicsSurfaceWidget::OnUpdate() {
         // directly...
 
         auto& registers = gpu.Get3DEngine().regs;
+        auto& rt = registers.rt[static_cast<size_t>(surface_source) -
+                                static_cast<size_t>(Source::RenderTarget0)];
 
-        surface_address = 0;
-        surface_width = 0;
-        surface_height = 0;
-        surface_format = Tegra::Texture::TextureFormat::DXT1;
+        surface_address = rt.Address();
+        surface_width = rt.horiz;
+        surface_height = rt.vert;
+        surface_format = ConvertToTextureFormat(static_cast<Tegra::RenderTargetFormat>(rt.format));
 
         break;
     }
@@ -378,9 +382,6 @@ void GraphicsSurfaceWidget::OnUpdate() {
     auto texture_data = Tegra::Texture::DecodeTexture(unswizzled_data, surface_format,
                                                       surface_width, surface_height);
 
-    ASSERT(texture_data.size() ==
-           surface_width * surface_height *
-               Tegra::Texture::BytesPerPixel(Tegra::Texture::TextureFormat::A8R8G8B8));
     surface_picture_label->show();
 
     for (unsigned int y = 0; y < surface_height; ++y) {
@@ -431,7 +432,10 @@ void GraphicsSurfaceWidget::SaveSurface() {
         if (pixmap)
             pixmap->save(&file, "PNG");
     } else if (selectedFilter == bin_filter) {
-        const u8* buffer = Memory::GetPhysicalPointer(surface_address);
+        auto& gpu = Core::System::GetInstance().GPU();
+        VAddr address = gpu.memory_manager->PhysicalToVirtualAddress(surface_address);
+
+        const u8* buffer = Memory::GetPointer(address);
         ASSERT_MSG(buffer != nullptr, "Memory not accessible");
 
         QFile file(filename);
-- 
GitLab