2017-04-23 04:44:34 +00:00
|
|
|
// Copyright 2017 Dolphin Emulator Project
|
|
|
|
// Licensed under GPLv2+
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
2017-05-31 04:44:03 +00:00
|
|
|
#include "Common/Assert.h"
|
|
|
|
|
2017-04-23 04:44:34 +00:00
|
|
|
#include "VideoCommon/AbstractTexture.h"
|
2017-05-31 04:44:03 +00:00
|
|
|
#include "VideoCommon/ImageWrite.h"
|
2017-04-23 04:44:34 +00:00
|
|
|
|
2017-11-19 06:23:19 +00:00
|
|
|
AbstractTexture::AbstractTexture(const TextureConfig& c) : m_config(c)
|
2017-04-23 04:44:34 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
AbstractTexture::~AbstractTexture() = default;
|
|
|
|
|
|
|
|
bool AbstractTexture::Save(const std::string& filename, unsigned int level)
|
|
|
|
{
|
2017-05-31 04:44:03 +00: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.
|
|
|
|
_assert_(m_config.format == AbstractTextureFormat::RGBA8);
|
|
|
|
|
|
|
|
auto result = level == 0 ? Map() : Map(level);
|
|
|
|
|
|
|
|
if (!result.has_value())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto raw_data = result.value();
|
|
|
|
return TextureToPng(raw_data.data, raw_data.stride, filename, raw_data.width, raw_data.height);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<AbstractTexture::RawTextureInfo> AbstractTexture::Map()
|
|
|
|
{
|
|
|
|
if (m_currently_mapped)
|
|
|
|
{
|
|
|
|
Unmap();
|
|
|
|
m_currently_mapped = false;
|
|
|
|
}
|
|
|
|
auto result = MapFullImpl();
|
|
|
|
|
|
|
|
if (!result.has_value())
|
|
|
|
{
|
|
|
|
m_currently_mapped = false;
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
m_currently_mapped = true;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<AbstractTexture::RawTextureInfo> AbstractTexture::Map(u32 level, u32 x, u32 y,
|
|
|
|
u32 width, u32 height)
|
|
|
|
{
|
|
|
|
_assert_(level < m_config.levels);
|
|
|
|
|
|
|
|
u32 max_level_width = std::max(m_config.width >> level, 1u);
|
|
|
|
u32 max_level_height = std::max(m_config.height >> level, 1u);
|
|
|
|
|
|
|
|
_assert_(width < max_level_width);
|
|
|
|
_assert_(height < max_level_height);
|
|
|
|
|
|
|
|
auto result = MapRegionImpl(level, x, y, width, height);
|
|
|
|
|
|
|
|
if (!result.has_value())
|
|
|
|
{
|
|
|
|
m_currently_mapped = false;
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
m_currently_mapped = true;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<AbstractTexture::RawTextureInfo> AbstractTexture::Map(u32 level)
|
|
|
|
{
|
|
|
|
_assert_(level < m_config.levels);
|
|
|
|
|
|
|
|
u32 level_width = std::max(m_config.width >> level, 1u);
|
|
|
|
u32 level_height = std::max(m_config.height >> level, 1u);
|
|
|
|
|
|
|
|
return Map(level, 0, 0, level_width, level_height);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AbstractTexture::Unmap()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<AbstractTexture::RawTextureInfo> AbstractTexture::MapFullImpl()
|
|
|
|
{
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<AbstractTexture::RawTextureInfo>
|
|
|
|
AbstractTexture::MapRegionImpl(u32 level, u32 x, u32 y, u32 width, u32 height)
|
|
|
|
{
|
|
|
|
return {};
|
2017-04-23 04:44:34 +00:00
|
|
|
}
|
|
|
|
|
2017-06-12 17:37:28 +00:00
|
|
|
bool AbstractTexture::IsCompressedHostTextureFormat(AbstractTextureFormat format)
|
2017-04-23 04:44:34 +00:00
|
|
|
{
|
|
|
|
// This will need to be changed if we add any other uncompressed formats.
|
2017-06-12 17:37:28 +00:00
|
|
|
return format != AbstractTextureFormat::RGBA8;
|
2017-04-23 04:44:34 +00:00
|
|
|
}
|
|
|
|
|
2017-06-12 17:37:28 +00:00
|
|
|
size_t AbstractTexture::CalculateHostTextureLevelPitch(AbstractTextureFormat format, u32 row_length)
|
2017-04-23 04:44:34 +00:00
|
|
|
{
|
|
|
|
switch (format)
|
|
|
|
{
|
2017-06-12 17:37:28 +00:00
|
|
|
case AbstractTextureFormat::DXT1:
|
2017-04-23 04:44:34 +00:00
|
|
|
return static_cast<size_t>(std::max(1u, row_length / 4)) * 8;
|
2017-06-12 17:37:28 +00:00
|
|
|
case AbstractTextureFormat::DXT3:
|
|
|
|
case AbstractTextureFormat::DXT5:
|
2017-07-27 12:00:04 +00:00
|
|
|
case AbstractTextureFormat::BPTC:
|
2017-04-23 04:44:34 +00:00
|
|
|
return static_cast<size_t>(std::max(1u, row_length / 4)) * 16;
|
2017-06-12 17:37:28 +00:00
|
|
|
case AbstractTextureFormat::RGBA8:
|
2017-04-23 04:44:34 +00:00
|
|
|
default:
|
|
|
|
return static_cast<size_t>(row_length) * 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-19 03:33:15 +00:00
|
|
|
const TextureConfig& AbstractTexture::GetConfig() const
|
2017-04-23 04:44:34 +00:00
|
|
|
{
|
|
|
|
return m_config;
|
|
|
|
}
|