HiresTextures: Support parsing DDS files directly

This leaves DDS textures using DXT1/3/5 compressed in-memory, which can
be passed directly to the backend.
This commit is contained in:
Stenzek
2017-04-16 19:30:11 +10:00
parent 68ee4fc932
commit bc8a96d713
14 changed files with 329 additions and 18 deletions

View File

@ -404,23 +404,18 @@ std::unique_ptr<HiresTexture> HiresTexture::Load(const std::string& base_filenam
filename += StringFromFormat("_mip%u", level);
}
if (s_textureMap.find(filename) != s_textureMap.end())
auto filename_iter = s_textureMap.find(filename);
if (filename_iter != s_textureMap.end())
{
Level l;
File::IOFile file;
file.Open(s_textureMap[filename], "rb");
file.Open(filename_iter->second, "rb");
std::vector<u8> buffer(file.GetSize());
file.ReadBytes(buffer.data(), file.GetSize());
int channels;
l.data =
SOILPointer(SOIL_load_image_from_memory(buffer.data(), (int)buffer.size(), (int*)&l.width,
(int*)&l.height, &channels, SOIL_LOAD_RGBA),
SOIL_free_image_data);
l.data_size = (size_t)l.width * l.height * 4;
if (l.data == nullptr)
// Try loading DDS textures first, that way we maintain compression of DXT formats.
if (!LoadDDSTexture(l, buffer) && !LoadTexture(l, buffer))
{
ERROR_LOG(VIDEO, "Custom texture %s failed to load", filename.c_str());
break;
@ -467,9 +462,39 @@ std::unique_ptr<HiresTexture> HiresTexture::Load(const std::string& base_filenam
}
}
// All levels have to have the same format.
if (ret && std::any_of(ret->m_levels.begin(), ret->m_levels.end(),
[&ret](const Level& l) { return l.format != ret->m_levels[0].format; }))
{
ERROR_LOG(VIDEO, "Custom texture %s has inconsistent formats across mip levels.",
base_filename.c_str());
ret.reset();
}
return ret;
}
bool HiresTexture::LoadTexture(Level& level, const std::vector<u8>& buffer)
{
int channels;
int width;
int height;
u8* data = SOIL_load_image_from_memory(buffer.data(), static_cast<int>(buffer.size()), &width,
&height, &channels, SOIL_LOAD_RGBA);
if (!data)
return false;
// Images loaded by SOIL are converted to RGBA.
level.width = static_cast<u32>(width);
level.height = static_cast<u32>(height);
level.format = HostTextureFormat::RGBA8;
level.data = ImageDataPointer(data, SOIL_free_image_data);
level.row_length = level.width;
level.data_size = static_cast<size_t>(level.row_length) * 4 * level.height;
return true;
}
std::string HiresTexture::GetTextureDirectory(const std::string& game_id)
{
const std::string texture_directory = File::GetUserPath(D_HIRESTEXTURES_IDX) + game_id;
@ -484,3 +509,8 @@ std::string HiresTexture::GetTextureDirectory(const std::string& game_id)
HiresTexture::~HiresTexture()
{
}
HostTextureFormat HiresTexture::GetFormat() const
{
return m_levels.at(0).format;
}