2017-04-22 23:44:34 -05:00
|
|
|
// Copyright 2017 Dolphin Emulator Project
|
2021-07-05 03:22:19 +02:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2017-04-22 23:44:34 -05:00
|
|
|
|
2021-12-09 18:22:16 -08:00
|
|
|
#include "VideoCommon/AbstractTexture.h"
|
|
|
|
|
2017-04-22 23:44:34 -05:00
|
|
|
#include <algorithm>
|
|
|
|
|
2017-05-30 23:44:03 -05:00
|
|
|
#include "Common/Assert.h"
|
2020-12-16 15:34:50 +01:00
|
|
|
#include "Common/Image.h"
|
2017-09-09 15:24:41 +10:00
|
|
|
#include "Common/MsgHandler.h"
|
2023-01-27 11:34:59 +13:00
|
|
|
#include "VideoCommon/AbstractGfx.h"
|
2017-10-30 22:00:15 +10:00
|
|
|
#include "VideoCommon/AbstractStagingTexture.h"
|
2017-04-22 23:44:34 -05:00
|
|
|
|
2017-11-19 01:23:19 -05:00
|
|
|
AbstractTexture::AbstractTexture(const TextureConfig& c) : m_config(c)
|
2017-04-22 23:44:34 -05:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-02-15 11:59:50 +10:00
|
|
|
void AbstractTexture::FinishedRendering()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-11-16 01:23:59 -06:00
|
|
|
bool AbstractTexture::Save(const std::string& filename, unsigned int level, int compression) const
|
2017-04-22 23:44:34 -05:00
|
|
|
{
|
2017-05-30 23:44:03 -05:00
|
|
|
// 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.
|
2018-03-14 20:34:35 -04:00
|
|
|
ASSERT(!IsCompressedFormat(m_config.format));
|
|
|
|
ASSERT(level < m_config.levels);
|
2023-06-08 03:17:20 +03:00
|
|
|
// We can't copy from float (HDR) textures to RGBA8
|
|
|
|
// (most other formats would probably fail as well)
|
|
|
|
ASSERT(m_config.format != AbstractTextureFormat::RGBA16F);
|
2017-05-30 23:44:03 -05:00
|
|
|
|
2017-10-30 22:00:15 +10:00
|
|
|
// 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..
|
2018-01-21 15:03:06 +10:00
|
|
|
TextureConfig readback_texture_config(level_width, level_height, 1, 1, 1,
|
2023-12-09 19:00:11 -06:00
|
|
|
AbstractTextureFormat::RGBA8, 0,
|
|
|
|
AbstractTextureType::Texture_2DArray);
|
2017-10-30 22:00:15 +10:00
|
|
|
auto readback_texture =
|
2023-01-27 11:34:59 +13:00
|
|
|
g_gfx->CreateStagingTexture(StagingTextureType::Readback, readback_texture_config);
|
2017-10-30 22:00:15 +10:00
|
|
|
if (!readback_texture)
|
|
|
|
return false;
|
2017-05-30 23:44:03 -05:00
|
|
|
|
2017-10-30 22:00:15 +10:00
|
|
|
// 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())
|
2017-05-30 23:44:03 -05:00
|
|
|
return false;
|
|
|
|
|
2020-12-16 15:34:50 +01:00
|
|
|
return Common::SavePNG(filename,
|
|
|
|
reinterpret_cast<const u8*>(readback_texture->GetMappedPointer()),
|
|
|
|
Common::ImageByteFormat::RGBA, level_width, level_height,
|
2023-02-09 09:49:25 -05:00
|
|
|
static_cast<int>(readback_texture->GetMappedStride()), compression);
|
2017-05-30 23:44:03 -05:00
|
|
|
}
|
|
|
|
|
2017-10-22 00:49:40 +10:00
|
|
|
bool AbstractTexture::IsCompressedFormat(AbstractTextureFormat format)
|
2017-04-22 23:44:34 -05:00
|
|
|
{
|
2017-09-09 15:24:41 +10:00
|
|
|
switch (format)
|
|
|
|
{
|
|
|
|
case AbstractTextureFormat::DXT1:
|
|
|
|
case AbstractTextureFormat::DXT3:
|
|
|
|
case AbstractTextureFormat::DXT5:
|
|
|
|
case AbstractTextureFormat::BPTC:
|
|
|
|
return true;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
2017-04-22 23:44:34 -05:00
|
|
|
}
|
|
|
|
|
2018-01-21 23:59:19 +10:00
|
|
|
bool AbstractTexture::IsDepthFormat(AbstractTextureFormat format)
|
|
|
|
{
|
|
|
|
switch (format)
|
|
|
|
{
|
|
|
|
case AbstractTextureFormat::D16:
|
2018-07-17 13:22:48 +10:00
|
|
|
case AbstractTextureFormat::D24_S8:
|
2018-01-21 23:59:19 +10:00
|
|
|
case AbstractTextureFormat::D32F:
|
|
|
|
case AbstractTextureFormat::D32F_S8:
|
|
|
|
return true;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-21 20:22:45 +10:00
|
|
|
bool AbstractTexture::IsStencilFormat(AbstractTextureFormat format)
|
|
|
|
{
|
2018-07-17 13:22:48 +10:00
|
|
|
return format == AbstractTextureFormat::D24_S8 || format == AbstractTextureFormat::D32F_S8;
|
2018-01-21 20:22:45 +10:00
|
|
|
}
|
|
|
|
|
2019-07-31 15:33:27 +10:00
|
|
|
bool AbstractTexture::IsCompatibleDepthAndColorFormats(AbstractTextureFormat depth_format,
|
|
|
|
AbstractTextureFormat color_format)
|
2019-02-15 11:59:50 +10:00
|
|
|
{
|
2019-07-31 15:33:27 +10:00
|
|
|
switch (depth_format)
|
2019-02-15 11:59:50 +10:00
|
|
|
{
|
|
|
|
case AbstractTextureFormat::D16:
|
2019-07-31 15:33:27 +10:00
|
|
|
return color_format == AbstractTextureFormat::R16;
|
2019-02-15 11:59:50 +10:00
|
|
|
|
|
|
|
case AbstractTextureFormat::D32F:
|
2019-07-31 15:33:27 +10:00
|
|
|
return color_format == AbstractTextureFormat::R32F;
|
2019-02-15 11:59:50 +10:00
|
|
|
|
|
|
|
default:
|
2019-07-31 15:33:27 +10:00
|
|
|
return false;
|
2019-02-15 11:59:50 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 AbstractTexture::CalculateStrideForFormat(AbstractTextureFormat format, u32 row_length)
|
2017-04-22 23:44:34 -05:00
|
|
|
{
|
|
|
|
switch (format)
|
|
|
|
{
|
2017-06-12 12:37:28 -05:00
|
|
|
case AbstractTextureFormat::DXT1:
|
2017-04-22 23:44:34 -05:00
|
|
|
return static_cast<size_t>(std::max(1u, row_length / 4)) * 8;
|
2017-06-12 12:37:28 -05:00
|
|
|
case AbstractTextureFormat::DXT3:
|
|
|
|
case AbstractTextureFormat::DXT5:
|
2017-07-27 22:00:04 +10:00
|
|
|
case AbstractTextureFormat::BPTC:
|
2017-04-22 23:44:34 -05:00
|
|
|
return static_cast<size_t>(std::max(1u, row_length / 4)) * 16;
|
2018-01-21 23:59:19 +10:00
|
|
|
case AbstractTextureFormat::R16:
|
|
|
|
case AbstractTextureFormat::D16:
|
|
|
|
return static_cast<size_t>(row_length) * 2;
|
2017-06-12 12:37:28 -05:00
|
|
|
case AbstractTextureFormat::RGBA8:
|
2017-09-09 15:24:41 +10:00
|
|
|
case AbstractTextureFormat::BGRA8:
|
2023-06-08 03:17:20 +03:00
|
|
|
case AbstractTextureFormat::RGB10_A2:
|
2018-01-21 23:59:19 +10:00
|
|
|
case AbstractTextureFormat::R32F:
|
|
|
|
case AbstractTextureFormat::D32F:
|
2018-07-17 13:22:48 +10:00
|
|
|
case AbstractTextureFormat::D24_S8:
|
2017-04-22 23:44:34 -05:00
|
|
|
return static_cast<size_t>(row_length) * 4;
|
2018-01-21 23:59:19 +10:00
|
|
|
case AbstractTextureFormat::D32F_S8:
|
2023-06-08 03:17:20 +03:00
|
|
|
case AbstractTextureFormat::RGBA16F:
|
2018-01-21 23:59:19 +10:00
|
|
|
return static_cast<size_t>(row_length) * 8;
|
2017-09-09 15:24:41 +10:00
|
|
|
default:
|
2020-11-13 22:33:26 -05:00
|
|
|
PanicAlertFmt("Unhandled texture format.");
|
2017-09-09 15:24:41 +10:00
|
|
|
return 0;
|
2017-04-22 23:44:34 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-15 11:59:50 +10:00
|
|
|
u32 AbstractTexture::GetTexelSizeForFormat(AbstractTextureFormat format)
|
2017-10-22 00:49:40 +10:00
|
|
|
{
|
|
|
|
switch (format)
|
|
|
|
{
|
|
|
|
case AbstractTextureFormat::DXT1:
|
|
|
|
return 8;
|
|
|
|
case AbstractTextureFormat::DXT3:
|
|
|
|
case AbstractTextureFormat::DXT5:
|
|
|
|
case AbstractTextureFormat::BPTC:
|
|
|
|
return 16;
|
2018-01-21 23:59:19 +10:00
|
|
|
case AbstractTextureFormat::R16:
|
|
|
|
case AbstractTextureFormat::D16:
|
|
|
|
return 2;
|
2017-10-22 00:49:40 +10:00
|
|
|
case AbstractTextureFormat::RGBA8:
|
|
|
|
case AbstractTextureFormat::BGRA8:
|
2023-06-08 03:17:20 +03:00
|
|
|
case AbstractTextureFormat::RGB10_A2:
|
2018-07-17 13:22:48 +10:00
|
|
|
case AbstractTextureFormat::D24_S8:
|
2018-01-21 23:59:19 +10:00
|
|
|
case AbstractTextureFormat::R32F:
|
|
|
|
case AbstractTextureFormat::D32F:
|
2017-10-22 00:49:40 +10:00
|
|
|
return 4;
|
2018-01-21 23:59:19 +10:00
|
|
|
case AbstractTextureFormat::D32F_S8:
|
2023-06-08 03:17:20 +03:00
|
|
|
case AbstractTextureFormat::RGBA16F:
|
2018-01-21 23:59:19 +10:00
|
|
|
return 8;
|
2017-10-22 00:49:40 +10:00
|
|
|
default:
|
2020-11-13 22:33:26 -05:00
|
|
|
PanicAlertFmt("Unhandled texture format.");
|
2017-10-22 00:49:40 +10:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-15 11:59:50 +10:00
|
|
|
u32 AbstractTexture::GetBlockSizeForFormat(AbstractTextureFormat format)
|
|
|
|
{
|
|
|
|
switch (format)
|
|
|
|
{
|
|
|
|
case AbstractTextureFormat::DXT1:
|
|
|
|
case AbstractTextureFormat::DXT3:
|
|
|
|
case AbstractTextureFormat::DXT5:
|
|
|
|
case AbstractTextureFormat::BPTC:
|
|
|
|
return 4;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-18 23:33:15 -04:00
|
|
|
const TextureConfig& AbstractTexture::GetConfig() const
|
2017-04-22 23:44:34 -05:00
|
|
|
{
|
|
|
|
return m_config;
|
|
|
|
}
|