GPU: Saving/loading of VRAM

This commit is contained in:
Connor McLaughlin 2019-09-14 20:45:26 +10:00
parent 2560efbebd
commit f6ef3f7ba6
4 changed files with 63 additions and 0 deletions

View file

@ -66,6 +66,22 @@ bool GPU::DoState(StateWrapper& sw)
UpdateGPUSTAT(); UpdateGPUSTAT();
} }
if (!sw.DoMarker("GPU-VRAM"))
return false;
if (sw.IsReading())
{
std::vector<u16> vram;
sw.Do(&vram);
UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, vram.data());
}
else
{
std::vector<u16> vram(VRAM_WIDTH * VRAM_HEIGHT);
ReadVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, vram.data());
sw.Do(&vram);
}
return !sw.HasError(); return !sw.HasError();
} }
@ -476,6 +492,8 @@ void GPU::UpdateDisplay()
m_system->IncrementFrameNumber(); m_system->IncrementFrameNumber();
} }
void GPU::ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer) {}
void GPU::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) {} void GPU::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) {}
void GPU::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data) {} void GPU::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data) {}

View file

@ -122,6 +122,7 @@ protected:
// Rendering in the backend // Rendering in the backend
virtual void UpdateDisplay(); virtual void UpdateDisplay();
virtual void ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer);
virtual void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color); virtual void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color);
virtual void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data); virtual void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data);
virtual void DispatchRenderCommand(RenderCommand rc, u32 num_vertices); virtual void DispatchRenderCommand(RenderCommand rc, u32 num_vertices);

View file

@ -193,12 +193,55 @@ inline u32 ConvertRGBA5551ToRGBA8888(u16 color)
return ZeroExtend32(r) | (ZeroExtend32(g) << 8) | (ZeroExtend32(b) << 16) | (ZeroExtend32(a) << 24); return ZeroExtend32(r) | (ZeroExtend32(g) << 8) | (ZeroExtend32(b) << 16) | (ZeroExtend32(a) << 24);
} }
inline u16 ConvertRGBA8888ToRGBA5551(u32 color)
{
const u16 r = Truncate16((color >> 3) & 0x1Fu);
const u16 g = Truncate16((color >> 11) & 0x1Fu);
const u16 b = Truncate16((color >> 19) & 0x1Fu);
const u16 a = Truncate16((color >> 31) & 0x01u);
return r | (g << 5) | (b << 10) | (a << 15);
}
void GPU_HW_OpenGL::UpdateDisplay() void GPU_HW_OpenGL::UpdateDisplay()
{ {
GPU_HW::UpdateDisplay(); GPU_HW::UpdateDisplay();
m_system->GetHostInterface()->SetDisplayTexture(m_framebuffer_texture.get(), 0, 0, VRAM_WIDTH, VRAM_HEIGHT); m_system->GetHostInterface()->SetDisplayTexture(m_framebuffer_texture.get(), 0, 0, VRAM_WIDTH, VRAM_HEIGHT);
} }
void GPU_HW_OpenGL::ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer)
{
// we need to convert RGBA8 -> RGBA5551
std::vector<u32> temp_buffer(width * height);
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_framebuffer_fbo_id);
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, temp_buffer.data());
// reverse copy because of lower-left origin
const u32 source_stride = width * sizeof(u32);
const u8* source_ptr = reinterpret_cast<const u8*>(temp_buffer.data()) + (source_stride * (height - 1));
const u32 dst_stride = width * sizeof(u16);
u8* dst_ptr = static_cast<u8*>(buffer);
for (u32 row = 0; row < height; row++)
{
const u8* source_row_ptr = source_ptr;
u8* dst_row_ptr = dst_ptr;
for (u32 col = 0; col < width; col++)
{
u32 src_col;
std::memcpy(&src_col, source_row_ptr, sizeof(src_col));
source_row_ptr += sizeof(src_col);
const u16 dst_col = ConvertRGBA8888ToRGBA5551(src_col);
std::memcpy(dst_row_ptr, &dst_col, sizeof(dst_col));
dst_row_ptr += sizeof(dst_col);
}
source_ptr -= source_stride;
dst_ptr += dst_stride;
}
}
void GPU_HW_OpenGL::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) void GPU_HW_OpenGL::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
{ {
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer_fbo_id); glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer_fbo_id);

View file

@ -18,6 +18,7 @@ public:
protected: protected:
void UpdateDisplay() override; void UpdateDisplay() override;
void ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer) override;
void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) override; void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) override;
void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data) override; void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data) override;
void UpdateTexturePageTexture() override; void UpdateTexturePageTexture() override;