diff options
| author | Stenzek <stenzek@gmail.com> | 2017-04-16 19:30:11 +1000 |
|---|---|---|
| committer | Stenzek <stenzek@gmail.com> | 2017-04-29 00:14:23 +1000 |
| commit | bc8a96d713eb0a1fb565f121a5d939b99c2295fa (patch) | |
| tree | 8b449d66cb2b61d4b72922276dcdfb735d0aaf49 /Source/Core/VideoCommon/HiresTextures.cpp | |
| parent | 68ee4fc932ddff320f535b6054ceff0c58348b64 (diff) | |
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.
Diffstat (limited to 'Source/Core/VideoCommon/HiresTextures.cpp')
| -rw-r--r-- | Source/Core/VideoCommon/HiresTextures.cpp | 50 |
1 files changed, 40 insertions, 10 deletions
diff --git a/Source/Core/VideoCommon/HiresTextures.cpp b/Source/Core/VideoCommon/HiresTextures.cpp index f4ad7448a5..d087ee8575 100644 --- a/Source/Core/VideoCommon/HiresTextures.cpp +++ b/Source/Core/VideoCommon/HiresTextures.cpp @@ -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; +} |
