GPU: Rotate screenshot framebuffer per display.

This commit is contained in:
Unknown W. Brackets 2021-02-19 22:51:33 -08:00
parent 1197795945
commit 28a4057115
3 changed files with 77 additions and 6 deletions

View File

@ -24,6 +24,7 @@
#include "Common/ColorConv.h"
#include "Common/File/FileUtil.h"
#include "Common/Log.h"
#include "Common/System/Display.h"
#include "Core/Config.h"
#include "Core/Screenshot.h"
#include "Core/Core.h"
@ -295,6 +296,36 @@ const u8 *ConvertBufferToScreenshot(const GPUDebugBuffer &buf, bool alpha, u8 *&
return temp ? temp : buffer;
}
static GPUDebugBuffer ApplyRotation(const GPUDebugBuffer &buf, DisplayRotation rotation) {
GPUDebugBuffer rotated;
// This is a simple but not terribly efficient rotation.
if (rotation == DisplayRotation::ROTATE_90) {
rotated.Allocate(buf.GetHeight(), buf.GetStride(), buf.GetFormat(), false);
for (u32 y = 0; y < buf.GetStride(); ++y) {
for (u32 x = 0; x < buf.GetHeight(); ++x) {
rotated.SetRawPixel(x, y, buf.GetRawPixel(buf.GetStride() - y - 1, x));
}
}
} else if (rotation == DisplayRotation::ROTATE_180) {
rotated.Allocate(buf.GetStride(), buf.GetHeight(), buf.GetFormat(), false);
for (u32 y = 0; y < buf.GetHeight(); ++y) {
for (u32 x = 0; x < buf.GetStride(); ++x) {
rotated.SetRawPixel(x, y, buf.GetRawPixel(buf.GetStride() - x - 1, buf.GetHeight() - y - 1));
}
}
} else {
rotated.Allocate(buf.GetHeight(), buf.GetStride(), buf.GetFormat(), false);
for (u32 y = 0; y < buf.GetStride(); ++y) {
for (u32 x = 0; x < buf.GetHeight(); ++x) {
rotated.SetRawPixel(x, y, buf.GetRawPixel(y, buf.GetHeight() - x - 1));
}
}
}
return rotated;
}
bool TakeGameScreenshot(const char *filename, ScreenshotFormat fmt, ScreenshotType type, int *width, int *height, int maxRes) {
if (!gpuDebug) {
ERROR_LOG(SYSTEM, "Can't take screenshots when GPU not running");
@ -311,6 +342,12 @@ bool TakeGameScreenshot(const char *filename, ScreenshotFormat fmt, ScreenshotTy
// Only crop to the top left when using a render screenshot.
w = maxRes > 0 ? 480 * maxRes : PSP_CoreParameter().renderWidth;
h = maxRes > 0 ? 272 * maxRes : PSP_CoreParameter().renderHeight;
} else if (g_display_rotation != DisplayRotation::ROTATE_0) {
GPUDebugBuffer temp;
success = gpuDebug->GetOutputFramebuffer(temp);
if (success) {
buf = ApplyRotation(temp, g_display_rotation);
}
} else {
success = gpuDebug->GetOutputFramebuffer(buf);
}

View File

@ -39,7 +39,7 @@ void GPUDebugBuffer::Allocate(u32 stride, u32 height, GPUDebugBufferFormat fmt,
fmt_ = fmt;
flipped_ = flipped;
u32 pixelSize = PixelSize(fmt);
u32 pixelSize = PixelSize();
data_ = new u8[pixelSize * stride * height];
}
@ -50,8 +50,8 @@ void GPUDebugBuffer::Free() {
data_ = NULL;
}
u32 GPUDebugBuffer::PixelSize(GPUDebugBufferFormat fmt) const {
switch (fmt) {
u32 GPUDebugBuffer::PixelSize() const {
switch (fmt_) {
case GPU_DBG_FORMAT_8888:
case GPU_DBG_FORMAT_8888_BGRA:
case GPU_DBG_FORMAT_FLOAT:
@ -81,7 +81,7 @@ u32 GPUDebugBuffer::GetRawPixel(int x, int y) const {
y = height_ - y - 1;
}
u32 pixelSize = PixelSize(fmt_);
u32 pixelSize = PixelSize();
u32 byteOffset = pixelSize * (stride_ * y + x);
const u8 *ptr = &data_[byteOffset];
@ -98,3 +98,36 @@ u32 GPUDebugBuffer::GetRawPixel(int x, int y) const {
return 0;
}
}
void GPUDebugBuffer::SetRawPixel(int x, int y, u32 c) {
if (data_ == nullptr) {
return;
}
if (flipped_) {
y = height_ - y - 1;
}
u32 pixelSize = PixelSize();
u32 byteOffset = pixelSize * (stride_ * y + x);
u8 *ptr = &data_[byteOffset];
switch (pixelSize) {
case 4:
*(u32 *)ptr = c;
break;
case 3:
ptr[0] = (c >> 0) & 0xFF;
ptr[1] = (c >> 8) & 0xFF;
ptr[2] = (c >> 16) & 0xFF;
break;
case 2:
*(u16 *)ptr = (u16)c;
break;
case 1:
*ptr = (u8)c;
break;
default:
break;
}
}

View File

@ -140,6 +140,7 @@ struct GPUDebugBuffer {
}
u32 GetRawPixel(int x, int y) const;
void SetRawPixel(int x, int y, u32 c);
const u8 *GetData() const {
return data_;
@ -161,9 +162,9 @@ struct GPUDebugBuffer {
return fmt_;
}
private:
u32 PixelSize(GPUDebugBufferFormat fmt) const;
u32 PixelSize() const;
private:
bool alloc_ = false;
u8 *data_ = nullptr;
u32 stride_ = 0;