mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 14:19:46 -06:00
VideoCommon: Replace SOIL with libpng for hires textures
This commit is contained in:

committed by
JosJuice

parent
0706add584
commit
17e65a7167
@ -4,7 +4,6 @@
|
||||
|
||||
#include "VideoCommon/HiresTextures.h"
|
||||
|
||||
#include <SOIL/SOIL.h>
|
||||
#include <algorithm>
|
||||
#include <cinttypes>
|
||||
#include <cstring>
|
||||
@ -22,6 +21,7 @@
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/Flag.h"
|
||||
#include "Common/Hash.h"
|
||||
#include "Common/Image.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/MemoryUtil.h"
|
||||
#include "Common/StringUtil.h"
|
||||
@ -49,10 +49,6 @@ static std::thread s_prefetcher;
|
||||
|
||||
static const std::string s_format_prefix = "tex1_";
|
||||
|
||||
HiresTexture::Level::Level() : data(nullptr, SOIL_free_image_data)
|
||||
{
|
||||
}
|
||||
|
||||
void HiresTexture::Init()
|
||||
{
|
||||
Update();
|
||||
@ -92,10 +88,7 @@ void HiresTexture::Update()
|
||||
|
||||
const std::string& game_id = SConfig::GetInstance().GetGameID();
|
||||
const std::string texture_directory = GetTextureDirectory(game_id);
|
||||
std::vector<std::string> extensions{
|
||||
".png", ".bmp", ".tga", ".dds",
|
||||
".jpg" // Why not? Could be useful for large photo-like textures
|
||||
};
|
||||
const std::vector<std::string> extensions{".png", ".dds"};
|
||||
|
||||
const std::vector<std::string> texture_paths =
|
||||
Common::DoFileSearch({texture_directory}, extensions, /*recursive*/ true);
|
||||
@ -183,9 +176,7 @@ void HiresTexture::Prefetch()
|
||||
if (iter != s_textureCache.end())
|
||||
{
|
||||
for (const Level& l : iter->second->m_levels)
|
||||
{
|
||||
size_sum += l.data_size;
|
||||
}
|
||||
size_sum += l.data.size();
|
||||
}
|
||||
}
|
||||
|
||||
@ -361,6 +352,7 @@ std::unique_ptr<HiresTexture> HiresTexture::Load(const std::string& base_filenam
|
||||
file.Open(filename_iter->second.path, "rb");
|
||||
std::vector<u8> buffer(file.GetSize());
|
||||
file.ReadBytes(buffer.data(), file.GetSize());
|
||||
|
||||
if (!LoadTexture(level, buffer))
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Custom texture %s failed to load", filename.c_str());
|
||||
@ -440,22 +432,15 @@ std::unique_ptr<HiresTexture> HiresTexture::Load(const std::string& base_filenam
|
||||
|
||||
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)
|
||||
if (!Common::LoadPNG(buffer, &level.data, &level.width, &level.height))
|
||||
return false;
|
||||
|
||||
// Images loaded by SOIL are converted to RGBA.
|
||||
level.width = static_cast<u32>(width);
|
||||
level.height = static_cast<u32>(height);
|
||||
if (level.data.empty())
|
||||
return false;
|
||||
|
||||
// Loaded PNG images are converted to RGBA.
|
||||
level.format = AbstractTextureFormat::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;
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,6 @@ enum class TextureFormat;
|
||||
class HiresTexture
|
||||
{
|
||||
public:
|
||||
using ImageDataPointer = std::unique_ptr<u8, void (*)(unsigned char*)>;
|
||||
|
||||
static void Init();
|
||||
static void Update();
|
||||
static void Shutdown();
|
||||
@ -39,14 +37,11 @@ public:
|
||||
|
||||
struct Level
|
||||
{
|
||||
Level();
|
||||
|
||||
ImageDataPointer data;
|
||||
std::vector<u8> data;
|
||||
AbstractTextureFormat format = AbstractTextureFormat::RGBA8;
|
||||
u32 width = 0;
|
||||
u32 height = 0;
|
||||
u32 row_length = 0;
|
||||
size_t data_size = 0;
|
||||
};
|
||||
std::vector<Level> m_levels;
|
||||
|
||||
|
@ -155,14 +155,9 @@ u32 GetBlockCount(u32 extent, u32 block_size)
|
||||
return std::max(Common::AlignUp(extent, block_size) / block_size, 1u);
|
||||
}
|
||||
|
||||
HiresTexture::ImageDataPointer AllocateLevelData(size_t size)
|
||||
{
|
||||
return HiresTexture::ImageDataPointer(new u8[size], [](u8* data) { delete[] data; });
|
||||
}
|
||||
|
||||
void ConvertTexture_X8B8G8R8(HiresTexture::Level* level)
|
||||
{
|
||||
u8* data_ptr = level->data.get();
|
||||
u8* data_ptr = level->data.data();
|
||||
for (u32 row = 0; row < level->height; row++)
|
||||
{
|
||||
for (u32 x = 0; x < level->row_length; x++)
|
||||
@ -176,7 +171,7 @@ void ConvertTexture_X8B8G8R8(HiresTexture::Level* level)
|
||||
|
||||
void ConvertTexture_A8R8G8B8(HiresTexture::Level* level)
|
||||
{
|
||||
u8* data_ptr = level->data.get();
|
||||
u8* data_ptr = level->data.data();
|
||||
for (u32 row = 0; row < level->height; row++)
|
||||
{
|
||||
for (u32 x = 0; x < level->row_length; x++)
|
||||
@ -193,7 +188,7 @@ void ConvertTexture_A8R8G8B8(HiresTexture::Level* level)
|
||||
|
||||
void ConvertTexture_X8R8G8B8(HiresTexture::Level* level)
|
||||
{
|
||||
u8* data_ptr = level->data.get();
|
||||
u8* data_ptr = level->data.data();
|
||||
for (u32 row = 0; row < level->height; row++)
|
||||
{
|
||||
for (u32 x = 0; x < level->row_length; x++)
|
||||
@ -210,14 +205,10 @@ void ConvertTexture_X8R8G8B8(HiresTexture::Level* level)
|
||||
|
||||
void ConvertTexture_R8G8B8(HiresTexture::Level* level)
|
||||
{
|
||||
// Have to reallocate the buffer for this one, since the data in the file
|
||||
// does not have an alpha byte.
|
||||
level->data_size = level->row_length * level->height * sizeof(u32);
|
||||
HiresTexture::ImageDataPointer rgb_data = AllocateLevelData(level->data_size);
|
||||
std::swap(level->data, rgb_data);
|
||||
std::vector<u8> new_data(level->row_length * level->height * sizeof(u32));
|
||||
|
||||
const u8* rgb_data_ptr = rgb_data.get();
|
||||
u8* data_ptr = level->data.get();
|
||||
const u8* rgb_data_ptr = level->data.data();
|
||||
u8* data_ptr = new_data.data();
|
||||
|
||||
for (u32 row = 0; row < level->height; row++)
|
||||
{
|
||||
@ -232,6 +223,8 @@ void ConvertTexture_R8G8B8(HiresTexture::Level* level)
|
||||
rgb_data_ptr += 3;
|
||||
}
|
||||
}
|
||||
|
||||
level->data = std::move(new_data);
|
||||
}
|
||||
|
||||
bool ParseDDSHeader(File::IOFile& file, DDSLoadInfo* info)
|
||||
@ -410,19 +403,14 @@ bool ParseDDSHeader(File::IOFile& file, DDSLoadInfo* info)
|
||||
bool ReadMipLevel(HiresTexture::Level* level, File::IOFile& file, const DDSLoadInfo& info,
|
||||
u32 width, u32 height, u32 row_length, size_t size)
|
||||
{
|
||||
// Copy to the final storage location. The deallocator here is simple, nothing extra is
|
||||
// needed, compared to the SOIL-based loader.
|
||||
// Copy to the final storage location.
|
||||
level->width = width;
|
||||
level->height = height;
|
||||
level->format = info.format;
|
||||
level->row_length = row_length;
|
||||
level->data_size = size;
|
||||
level->data = AllocateLevelData(level->data_size);
|
||||
if (!file.ReadBytes(level->data.get(), level->data_size))
|
||||
{
|
||||
level->data.reset();
|
||||
level->data.resize(size);
|
||||
if (!file.ReadBytes(level->data.data(), level->data.size()))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Apply conversion function for uncompressed textures.
|
||||
if (info.conversion_function)
|
||||
|
@ -957,8 +957,8 @@ TextureCacheBase::GetTexture(u32 address, u32 width, u32 height, const TextureFo
|
||||
if (hires_tex)
|
||||
{
|
||||
const auto& level = hires_tex->m_levels[0];
|
||||
entry->texture->Load(0, level.width, level.height, level.row_length, level.data.get(),
|
||||
level.data_size);
|
||||
entry->texture->Load(0, level.width, level.height, level.row_length, level.data.data(),
|
||||
level.data.size());
|
||||
}
|
||||
|
||||
// Initialized to null because only software loading uses this buffer
|
||||
@ -1042,7 +1042,7 @@ TextureCacheBase::GetTexture(u32 address, u32 width, u32 height, const TextureFo
|
||||
{
|
||||
const auto& level = hires_tex->m_levels[level_index];
|
||||
entry->texture->Load(level_index, level.width, level.height, level.row_length,
|
||||
level.data.get(), level.data_size);
|
||||
level.data.data(), level.data.size());
|
||||
}
|
||||
}
|
||||
else
|
||||
|
Reference in New Issue
Block a user