HiresTextures: Support DXT10 extended header in DDS loader

This commit is contained in:
Stenzek 2017-04-21 19:33:05 +10:00
parent 8761c8244d
commit a6a13f51c1
1 changed files with 51 additions and 26 deletions

View File

@ -196,7 +196,8 @@ static bool ParseDDSHeader(File::IOFile& file, DDSLoadInfo* info)
return false; return false;
DDS_HEADER header; DDS_HEADER header;
if (!file.ReadBytes(&header, sizeof(header)) || header.dwSize < sizeof(header)) size_t header_size = sizeof(header);
if (!file.ReadBytes(&header, header_size) || header.dwSize < header_size)
return false; return false;
// Required fields. // Required fields.
@ -229,35 +230,59 @@ static bool ParseDDSHeader(File::IOFile& file, DDSLoadInfo* info)
info->mip_count = 1; info->mip_count = 1;
} }
// Currently, we only handle compressed textures here, and leave the rest to the SOIL loader. // Handle fourcc formats vs uncompressed formats.
// In the future, this could be extended, but these isn't much benefit in doing so currently. bool has_fourcc = (header.ddspf.dwFlags & DDS_FOURCC) != 0;
// TODO: DX10 extension header handling.
// TODO: Support RGBA8 and friends.
bool needs_s3tc = false; bool needs_s3tc = false;
if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '1')) if (has_fourcc)
{ {
info->format = HostTextureFormat::DXT1; // Handle DX10 extension header.
info->block_size = 4; u32 dxt10_format = 0;
info->bytes_per_block = 8; if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', '1', '0'))
needs_s3tc = true; {
} DDS_HEADER_DXT10 dxt10_header;
else if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '3')) if (!file.ReadBytes(&dxt10_header, sizeof(dxt10_header)))
{ return false;
info->format = HostTextureFormat::DXT3;
info->block_size = 4; // Can't handle array textures here. Doesn't make sense to use them, anyway.
info->bytes_per_block = 16; if (dxt10_header.resourceDimension != DDS_DIMENSION_TEXTURE2D || dxt10_header.arraySize != 1)
needs_s3tc = true; return false;
}
else if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '5')) header_size += sizeof(dxt10_header);
{ dxt10_format = dxt10_header.dxgiFormat;
info->format = HostTextureFormat::DXT5; }
info->block_size = 4;
info->bytes_per_block = 16; // Currently, we only handle compressed textures here, and leave the rest to the SOIL loader.
needs_s3tc = true; // In the future, this could be extended, but these isn't much benefit in doing so currently.
if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '1') || dxt10_format == 71)
{
info->format = HostTextureFormat::DXT1;
info->block_size = 4;
info->bytes_per_block = 8;
needs_s3tc = true;
}
else if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '3') || dxt10_format == 74)
{
info->format = HostTextureFormat::DXT3;
info->block_size = 4;
info->bytes_per_block = 16;
needs_s3tc = true;
}
else if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '5') || dxt10_format == 77)
{
info->format = HostTextureFormat::DXT5;
info->block_size = 4;
info->bytes_per_block = 16;
needs_s3tc = true;
}
else
{
// Leave all remaining formats to SOIL.
return false;
}
} }
else else
{ {
// Leave all remaining formats to SOIL. // TODO: Support RGBA8 and friends.
return false; return false;
} }
@ -295,7 +320,7 @@ static bool ParseDDSHeader(File::IOFile& file, DDSLoadInfo* info)
} }
// Check for truncated or corrupted files. // Check for truncated or corrupted files.
info->first_mip_offset = sizeof(magic) + sizeof(DDS_HEADER); info->first_mip_offset = sizeof(magic) + header_size;
if (info->first_mip_offset >= file.GetSize()) if (info->first_mip_offset >= file.GetSize())
return false; return false;