From c2cc128f1b6be695a4facd3c0fd697a24c3df17a Mon Sep 17 00:00:00 2001 From: Stenzek Date: Mon, 30 Oct 2017 22:00:15 +1000 Subject: AbstractTexture: Implement Save using new common methods --- Source/Core/VideoCommon/AbstractTexture.cpp | 32 ++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) (limited to 'Source/Core/VideoCommon/AbstractTexture.cpp') diff --git a/Source/Core/VideoCommon/AbstractTexture.cpp b/Source/Core/VideoCommon/AbstractTexture.cpp index 7e09be5344..109bb52897 100644 --- a/Source/Core/VideoCommon/AbstractTexture.cpp +++ b/Source/Core/VideoCommon/AbstractTexture.cpp @@ -6,8 +6,10 @@ #include "Common/Assert.h" #include "Common/MsgHandler.h" +#include "VideoCommon/AbstractStagingTexture.h" #include "VideoCommon/AbstractTexture.h" #include "VideoCommon/ImageWrite.h" +#include "VideoCommon/RenderBase.h" AbstractTexture::AbstractTexture(const TextureConfig& c) : m_config(c) { @@ -20,17 +22,33 @@ bool AbstractTexture::Save(const std::string& filename, unsigned int level) // We can't dump compressed textures currently (it would mean drawing them to a RGBA8 // framebuffer, and saving that). TextureCache does not call Save for custom textures // anyway, so this is fine for now. - _assert_(m_config.format == AbstractTextureFormat::RGBA8); + _assert_(!IsCompressedFormat(m_config.format)); + _assert_(level < m_config.levels); - auto result = level == 0 ? Map() : Map(level); + // Determine dimensions of image we want to save. + u32 level_width = std::max(1u, m_config.width >> level); + u32 level_height = std::max(1u, m_config.height >> level); + + // Use a temporary staging texture for the download. Certainly not optimal, + // but this is not a frequently-executed code path.. + TextureConfig readback_texture_config(level_width, level_height, 1, 1, + AbstractTextureFormat::RGBA8, false); + auto readback_texture = + g_renderer->CreateStagingTexture(StagingTextureType::Readback, readback_texture_config); + if (!readback_texture) + return false; - if (!result.has_value()) - { + // Copy to the readback texture's buffer. + readback_texture->CopyFromTexture(this, 0, level); + readback_texture->Flush(); + + // Map it so we can encode it to the file. + if (!readback_texture->Map()) return false; - } - auto raw_data = result.value(); - return TextureToPng(raw_data.data, raw_data.stride, filename, raw_data.width, raw_data.height); + return TextureToPng(reinterpret_cast(readback_texture->GetMappedPointer()), + static_cast(readback_texture->GetMappedStride()), filename, level_width, + level_height); } std::optional AbstractTexture::Map() -- cgit v1.2.3