diff options
Diffstat (limited to 'src/citra_qt/debugger/graphics_framebuffer.cpp')
| -rw-r--r-- | src/citra_qt/debugger/graphics_framebuffer.cpp | 65 |
1 files changed, 60 insertions, 5 deletions
diff --git a/src/citra_qt/debugger/graphics_framebuffer.cpp b/src/citra_qt/debugger/graphics_framebuffer.cpp index 5bd6c0235..d621d7204 100644 --- a/src/citra_qt/debugger/graphics_framebuffer.cpp +++ b/src/citra_qt/debugger/graphics_framebuffer.cpp | |||
| @@ -27,6 +27,7 @@ GraphicsFramebufferWidget::GraphicsFramebufferWidget(std::shared_ptr<Pica::Debug | |||
| 27 | 27 | ||
| 28 | framebuffer_source_list = new QComboBox; | 28 | framebuffer_source_list = new QComboBox; |
| 29 | framebuffer_source_list->addItem(tr("Active Render Target")); | 29 | framebuffer_source_list->addItem(tr("Active Render Target")); |
| 30 | framebuffer_source_list->addItem(tr("Active Depth Buffer")); | ||
| 30 | framebuffer_source_list->addItem(tr("Custom")); | 31 | framebuffer_source_list->addItem(tr("Custom")); |
| 31 | framebuffer_source_list->setCurrentIndex(static_cast<int>(framebuffer_source)); | 32 | framebuffer_source_list->setCurrentIndex(static_cast<int>(framebuffer_source)); |
| 32 | 33 | ||
| @@ -49,6 +50,9 @@ GraphicsFramebufferWidget::GraphicsFramebufferWidget(std::shared_ptr<Pica::Debug | |||
| 49 | framebuffer_format_control->addItem(tr("RGB5A1")); | 50 | framebuffer_format_control->addItem(tr("RGB5A1")); |
| 50 | framebuffer_format_control->addItem(tr("RGB565")); | 51 | framebuffer_format_control->addItem(tr("RGB565")); |
| 51 | framebuffer_format_control->addItem(tr("RGBA4")); | 52 | framebuffer_format_control->addItem(tr("RGBA4")); |
| 53 | framebuffer_format_control->addItem(tr("D16")); | ||
| 54 | framebuffer_format_control->addItem(tr("D24")); | ||
| 55 | framebuffer_format_control->addItem(tr("D24S8")); | ||
| 52 | 56 | ||
| 53 | // TODO: This QLabel should shrink the image to the available space rather than just expanding... | 57 | // TODO: This QLabel should shrink the image to the available space rather than just expanding... |
| 54 | framebuffer_picture_label = new QLabel; | 58 | framebuffer_picture_label = new QLabel; |
| @@ -172,8 +176,7 @@ void GraphicsFramebufferWidget::OnUpdate() | |||
| 172 | { | 176 | { |
| 173 | // TODO: Store a reference to the registers in the debug context instead of accessing them directly... | 177 | // TODO: Store a reference to the registers in the debug context instead of accessing them directly... |
| 174 | 178 | ||
| 175 | auto framebuffer = Pica::registers.framebuffer; | 179 | const auto& framebuffer = Pica::registers.framebuffer; |
| 176 | using Framebuffer = decltype(framebuffer); | ||
| 177 | 180 | ||
| 178 | framebuffer_address = framebuffer.GetColorBufferPhysicalAddress(); | 181 | framebuffer_address = framebuffer.GetColorBufferPhysicalAddress(); |
| 179 | framebuffer_width = framebuffer.GetWidth(); | 182 | framebuffer_width = framebuffer.GetWidth(); |
| @@ -184,6 +187,18 @@ void GraphicsFramebufferWidget::OnUpdate() | |||
| 184 | break; | 187 | break; |
| 185 | } | 188 | } |
| 186 | 189 | ||
| 190 | case Source::DepthBuffer: | ||
| 191 | { | ||
| 192 | const auto& framebuffer = Pica::registers.framebuffer; | ||
| 193 | |||
| 194 | framebuffer_address = framebuffer.GetDepthBufferPhysicalAddress(); | ||
| 195 | framebuffer_width = framebuffer.GetWidth(); | ||
| 196 | framebuffer_height = framebuffer.GetHeight(); | ||
| 197 | framebuffer_format = Format::D16; | ||
| 198 | |||
| 199 | break; | ||
| 200 | } | ||
| 201 | |||
| 187 | case Source::Custom: | 202 | case Source::Custom: |
| 188 | { | 203 | { |
| 189 | // Keep user-specified values | 204 | // Keep user-specified values |
| @@ -197,15 +212,16 @@ void GraphicsFramebufferWidget::OnUpdate() | |||
| 197 | 212 | ||
| 198 | // TODO: Implement a good way to visualize alpha components! | 213 | // TODO: Implement a good way to visualize alpha components! |
| 199 | // TODO: Unify this decoding code with the texture decoder | 214 | // TODO: Unify this decoding code with the texture decoder |
| 200 | u32 bytes_per_pixel = GPU::Regs::BytesPerPixel(GPU::Regs::PixelFormat(framebuffer_format)); | 215 | u32 bytes_per_pixel = GraphicsFramebufferWidget::BytesPerPixel(framebuffer_format); |
| 201 | 216 | ||
| 202 | QImage decoded_image(framebuffer_width, framebuffer_height, QImage::Format_ARGB32); | 217 | QImage decoded_image(framebuffer_width, framebuffer_height, QImage::Format_ARGB32); |
| 203 | u8* color_buffer = Memory::GetPointer(Pica::PAddrToVAddr(framebuffer_address)); | 218 | u8* buffer = Memory::GetPointer(Pica::PAddrToVAddr(framebuffer_address)); |
| 219 | |||
| 204 | for (unsigned int y = 0; y < framebuffer_height; ++y) { | 220 | for (unsigned int y = 0; y < framebuffer_height; ++y) { |
| 205 | for (unsigned int x = 0; x < framebuffer_width; ++x) { | 221 | for (unsigned int x = 0; x < framebuffer_width; ++x) { |
| 206 | const u32 coarse_y = y & ~7; | 222 | const u32 coarse_y = y & ~7; |
| 207 | u32 offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * framebuffer_width * bytes_per_pixel; | 223 | u32 offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * framebuffer_width * bytes_per_pixel; |
| 208 | const u8* pixel = color_buffer + offset; | 224 | const u8* pixel = buffer + offset; |
| 209 | Math::Vec4<u8> color = { 0, 0, 0, 0 }; | 225 | Math::Vec4<u8> color = { 0, 0, 0, 0 }; |
| 210 | 226 | ||
| 211 | switch (framebuffer_format) { | 227 | switch (framebuffer_format) { |
| @@ -224,6 +240,29 @@ void GraphicsFramebufferWidget::OnUpdate() | |||
| 224 | case Format::RGBA4: | 240 | case Format::RGBA4: |
| 225 | color = Color::DecodeRGBA4(pixel); | 241 | color = Color::DecodeRGBA4(pixel); |
| 226 | break; | 242 | break; |
| 243 | case Format::D16: | ||
| 244 | { | ||
| 245 | u32 data = Color::DecodeD16(pixel); | ||
| 246 | color.r() = data & 0xFF; | ||
| 247 | color.g() = (data >> 8) & 0xFF; | ||
| 248 | break; | ||
| 249 | } | ||
| 250 | case Format::D24: | ||
| 251 | { | ||
| 252 | u32 data = Color::DecodeD24(pixel); | ||
| 253 | color.r() = data & 0xFF; | ||
| 254 | color.g() = (data >> 8) & 0xFF; | ||
| 255 | color.b() = (data >> 16) & 0xFF; | ||
| 256 | break; | ||
| 257 | } | ||
| 258 | case Format::D24S8: | ||
| 259 | { | ||
| 260 | Math::Vec2<u32> data = Color::DecodeD24S8(pixel); | ||
| 261 | color.r() = data.x & 0xFF; | ||
| 262 | color.g() = (data.x >> 8) & 0xFF; | ||
| 263 | color.b() = (data.x >> 16) & 0xFF; | ||
| 264 | break; | ||
| 265 | } | ||
| 227 | default: | 266 | default: |
| 228 | qDebug() << "Unknown fb color format " << static_cast<int>(framebuffer_format); | 267 | qDebug() << "Unknown fb color format " << static_cast<int>(framebuffer_format); |
| 229 | break; | 268 | break; |
| @@ -240,3 +279,19 @@ void GraphicsFramebufferWidget::OnUpdate() | |||
| 240 | framebuffer_format_control->setCurrentIndex(static_cast<int>(framebuffer_format)); | 279 | framebuffer_format_control->setCurrentIndex(static_cast<int>(framebuffer_format)); |
| 241 | framebuffer_picture_label->setPixmap(pixmap); | 280 | framebuffer_picture_label->setPixmap(pixmap); |
| 242 | } | 281 | } |
| 282 | |||
| 283 | u32 GraphicsFramebufferWidget::BytesPerPixel(GraphicsFramebufferWidget::Format format) { | ||
| 284 | switch (format) { | ||
| 285 | case Format::RGBA8: | ||
| 286 | case Format::D24S8: | ||
| 287 | return 4; | ||
| 288 | case Format::RGB8: | ||
| 289 | case Format::D24: | ||
| 290 | return 3; | ||
| 291 | case Format::RGB5A1: | ||
| 292 | case Format::RGB565: | ||
| 293 | case Format::RGBA4: | ||
| 294 | case Format::D16: | ||
| 295 | return 2; | ||
| 296 | } | ||
| 297 | } | ||