mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-10 08:09:26 +01:00
HiresTextures: Move the maximum mip level check from DDS to main loader
This way that the mip count check occurs on .png and uncombined DDS textures as well.
This commit is contained in:
parent
a6a13f51c1
commit
20cbef8e9f
@ -366,6 +366,21 @@ std::string HiresTexture::GenBaseName(const u8* texture, size_t texture_size, co
|
||||
return name;
|
||||
}
|
||||
|
||||
u32 HiresTexture::CalculateMipCount(u32 width, u32 height)
|
||||
{
|
||||
u32 mip_width = width;
|
||||
u32 mip_height = height;
|
||||
u32 mip_count = 1;
|
||||
while (mip_width > 1 || mip_height > 1)
|
||||
{
|
||||
mip_width = std::max(mip_width / 2, 1u);
|
||||
mip_height = std::max(mip_height / 2, 1u);
|
||||
mip_count++;
|
||||
}
|
||||
|
||||
return mip_count;
|
||||
}
|
||||
|
||||
std::shared_ptr<HiresTexture> HiresTexture::Search(const u8* texture, size_t texture_size,
|
||||
const u8* tlut, size_t tlut_size, u32 width,
|
||||
u32 height, int format, bool has_mipmaps)
|
||||
@ -453,39 +468,45 @@ std::unique_ptr<HiresTexture> HiresTexture::Load(const std::string& base_filenam
|
||||
// Same deal if the custom texture isn't a multiple of the native size.
|
||||
if (width != 0 && height != 0 && (first_mip.width % width || first_mip.height % height))
|
||||
{
|
||||
WARN_LOG(VIDEO, "Invalid custom texture size %ux%u for texture %s. Please use an integer "
|
||||
"upscaling factor based on the native size %ux%u.",
|
||||
first_mip.width, first_mip.height, first_mip_filename.c_str(), width, height);
|
||||
ERROR_LOG(VIDEO, "Invalid custom texture size %ux%u for texture %s. Please use an integer "
|
||||
"upscaling factor based on the native size %ux%u.",
|
||||
first_mip.width, first_mip.height, first_mip_filename.c_str(), width, height);
|
||||
}
|
||||
|
||||
// Verify that each mip level is the correct size (divide by 2 each time).
|
||||
u32 current_mip_width = std::max(first_mip.width / 2, 1u);
|
||||
u32 current_mip_height = std::max(first_mip.height / 2, 1u);
|
||||
u32 current_mip_width = first_mip.width;
|
||||
u32 current_mip_height = first_mip.height;
|
||||
for (u32 mip_level = 1; mip_level < static_cast<u32>(ret->m_levels.size()); mip_level++)
|
||||
{
|
||||
const Level& level = ret->m_levels[mip_level];
|
||||
if (current_mip_width == level.width && current_mip_height == level.height)
|
||||
if (current_mip_width != 1 || current_mip_height != 1)
|
||||
{
|
||||
current_mip_width = std::max(current_mip_width / 2, 1u);
|
||||
current_mip_height = std::max(current_mip_height / 2, 1u);
|
||||
continue;
|
||||
}
|
||||
|
||||
ERROR_LOG(VIDEO,
|
||||
"Invalid custom texture size %dx%d for texture %s. Mipmap level %u _must_ be %dx%d.",
|
||||
level.width, level.height, first_mip_filename.c_str(), mip_level, current_mip_width,
|
||||
current_mip_height);
|
||||
const Level& level = ret->m_levels[mip_level];
|
||||
if (current_mip_width == level.width && current_mip_height == level.height)
|
||||
continue;
|
||||
|
||||
ERROR_LOG(VIDEO,
|
||||
"Invalid custom texture size %dx%d for texture %s. Mipmap level %u must be %dx%d.",
|
||||
level.width, level.height, first_mip_filename.c_str(), mip_level, current_mip_width,
|
||||
current_mip_height);
|
||||
}
|
||||
else
|
||||
{
|
||||
// It is invalid to have more than a single 1x1 mipmap.
|
||||
ERROR_LOG(VIDEO, "Custom texture %s has too many 1x1 mipmaps. Skipping extra levels.",
|
||||
first_mip_filename.c_str());
|
||||
}
|
||||
|
||||
// Drop this mip level and any others after it.
|
||||
while (ret->m_levels.size() > mip_level)
|
||||
ret->m_levels.pop_back();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// 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; }))
|
||||
if (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.",
|
||||
first_mip_filename.c_str());
|
||||
|
@ -28,6 +28,8 @@ public:
|
||||
size_t tlut_size, u32 width, u32 height, int format,
|
||||
bool has_mipmaps, bool dump = false);
|
||||
|
||||
static u32 CalculateMipCount(u32 width, u32 height);
|
||||
|
||||
~HiresTexture();
|
||||
|
||||
HostTextureFormat GetFormat() const;
|
||||
|
@ -172,21 +172,6 @@ static u32 GetBlockCount(u32 extent, u32 block_size)
|
||||
return std::max(Common::AlignUp(extent, block_size) / block_size, 1u);
|
||||
}
|
||||
|
||||
static u32 CalculateMipCount(u32 width, u32 height)
|
||||
{
|
||||
u32 mip_width = std::max(width / 2, 1u);
|
||||
u32 mip_height = std::max(height / 2, 1u);
|
||||
u32 mip_count = 1;
|
||||
while (mip_width > 1 || mip_height > 1)
|
||||
{
|
||||
mip_width = std::max(mip_width / 2, 1u);
|
||||
mip_height = std::max(mip_height / 2, 1u);
|
||||
mip_count++;
|
||||
}
|
||||
|
||||
return mip_count;
|
||||
}
|
||||
|
||||
static bool ParseDDSHeader(File::IOFile& file, DDSLoadInfo* info)
|
||||
{
|
||||
// Exit as early as possible for non-DDS textures, since all extensions are currently
|
||||
@ -217,13 +202,11 @@ static bool ParseDDSHeader(File::IOFile& file, DDSLoadInfo* info)
|
||||
// Check for mip levels.
|
||||
if (header.dwFlags & DDS_HEADER_FLAGS_MIPMAP)
|
||||
{
|
||||
// Miplevels = 0 means full mip chain?
|
||||
// Some files may specify a number too large here, which doesn't play well with the backends.
|
||||
info->mip_count = header.dwMipMapCount;
|
||||
if (info->mip_count != 0)
|
||||
info->mip_count = std::min(info->mip_count, CalculateMipCount(info->width, info->height));
|
||||
if (header.dwMipMapCount != 0)
|
||||
info->mip_count = header.dwMipMapCount;
|
||||
else
|
||||
info->mip_count = CalculateMipCount(info->width, info->height);
|
||||
info->mip_count = HiresTexture::CalculateMipCount(info->width, info->height);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -372,10 +355,13 @@ bool HiresTexture::LoadDDSTexture(HiresTexture* tex, const std::string& filename
|
||||
|
||||
// Read in any remaining mip levels in the file.
|
||||
// If the .dds file does not contain a full mip chain, we'll fall back to the old path.
|
||||
u32 mip_width = std::max(info.width / 2, 1u);
|
||||
u32 mip_height = std::max(info.height / 2, 1u);
|
||||
u32 mip_width = info.width;
|
||||
u32 mip_height = info.height;
|
||||
for (u32 i = 1; i < info.mip_count; i++)
|
||||
{
|
||||
mip_width = std::max(mip_width / 2, 1u);
|
||||
mip_height = std::max(mip_height / 2, 1u);
|
||||
|
||||
// Pitch can't be specified with each mip level, so we have to calculate it ourselves.
|
||||
u32 blocks_wide = GetBlockCount(mip_width, info.block_size);
|
||||
u32 blocks_high = GetBlockCount(mip_height, info.block_size);
|
||||
@ -386,8 +372,6 @@ bool HiresTexture::LoadDDSTexture(HiresTexture* tex, const std::string& filename
|
||||
break;
|
||||
|
||||
tex->m_levels.push_back(std::move(level));
|
||||
mip_width = std::max(mip_width / 2, 1u);
|
||||
mip_height = std::max(mip_height / 2, 1u);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user