Implements dds mipmap loading.

This commit is contained in:
Erik Abair 2022-07-01 11:00:27 -07:00
parent aa9a6e958f
commit 6a737e7b83
4 changed files with 67 additions and 25 deletions

View File

@ -29,6 +29,7 @@ OPTIMIZED_SRCS = \
$(SRCDIR)/shaders/projection_vertex_shader.cpp \
$(SRCDIR)/shaders/vertex_shader_program.cpp \
$(SRCDIR)/test_driver.cpp \
$(SRCDIR)/test_host.cpp \
$(SRCDIR)/texture_format.cpp \
$(SRCDIR)/texture_generator.cpp \
$(SRCDIR)/texture_stage.cpp \
@ -38,7 +39,6 @@ OPTIMIZED_SRCS = \
$(THIRDPARTYDIR)/fpng/src/fpng.cpp
SRCS = \
$(SRCDIR)/test_host.cpp \
$(SRCDIR)/tests/antialiasing_tests.cpp \
$(SRCDIR)/tests/attribute_carryover_tests.cpp \
$(SRCDIR)/tests/attribute_explicit_setter_tests.cpp \

View File

@ -128,7 +128,6 @@ bool DDSImage::LoadFile(const char *filename, bool load_mipmaps) {
ASSERT((pixelformat.dwFourCC != kDX10Magic) && "DX10 format not supported.");
uint32_t block_size = 0;
uint32_t pitch = 0;
SubImage::Format format = SubImage::Format::NONE;
uint32_t bytes_per_pixel = 0;
uint32_t compressed_width = compressed_size(header.dwWidth);
@ -160,29 +159,64 @@ bool DDSImage::LoadFile(const char *filename, bool load_mipmaps) {
return false;
}
pitch = compressed_width * block_size;
uint32_t compressed_bytes = pitch * compressed_height * header.dwDepth;
auto read_image = [block_size, format, &f, bytes_per_pixel](
uint32_t width, uint32_t height, uint32_t depth, uint32_t compressed_width,
uint32_t compressed_height) -> std::shared_ptr<SubImage> {
uint32_t pitch = compressed_width * block_size;
uint32_t compressed_bytes = pitch * compressed_height * depth;
std::shared_ptr<SubImage> primary_image = std::make_shared<SubImage>();
primary_image->level = 0;
primary_image->format = format;
primary_image->width = header.dwWidth;
primary_image->height = header.dwHeight;
primary_image->compressed_width = compressed_width;
primary_image->compressed_height = compressed_height;
primary_image->depth = header.dwDepth;
primary_image->pitch = pitch;
primary_image->bytes_per_pixel = bytes_per_pixel;
primary_image->data.resize(compressed_bytes);
if (fread(primary_image->data.data(), compressed_bytes, 1, f) != 1) {
std::shared_ptr<SubImage> ret = std::make_shared<SubImage>();
ret->level = 0;
ret->format = format;
ret->width = width;
ret->height = height;
ret->compressed_width = compressed_width;
ret->compressed_height = compressed_height;
ret->depth = depth;
ret->pitch = pitch;
ret->bytes_per_pixel = bytes_per_pixel;
ret->data.resize(compressed_bytes);
if (fread(ret->data.data(), compressed_bytes, 1, f) != 1) {
return {};
}
return ret;
};
auto primary_image =
read_image(header.dwWidth, header.dwHeight, header.dwDepth, compressed_width, compressed_height);
if (!primary_image) {
ASSERT(!"Failed to read image data.");
fclose(f);
return false;
}
sub_images_.push_back(primary_image);
ASSERT(!load_mipmaps && "Mipmap loading not implemented.");
if (load_mipmaps) {
uint32_t width = header.dwWidth;
uint32_t height = header.dwHeight;
for (auto i = 1; i < header.dwMipMapCount; ++i) {
width >>= 1;
if (width < 1) {
width = 1;
}
height >>= 1;
if (height < 1) {
height = 1;
}
auto subimage = read_image(width, height, header.dwDepth, compressed_size(width), compressed_size(height));
if (!subimage) {
ASSERT(!"Failed to read mipmap data.");
fclose(f);
return false;
}
sub_images_.push_back(subimage);
}
}
} else {
ASSERT((header.dwFlags & DDSD_PITCH) && (pixelformat.dwFlags & DDPF_RGB) && "Texture not flagged as uncompressed");
// TODO: Implement if necessary.

View File

@ -29,6 +29,9 @@ class DDSImage {
inline std::shared_ptr<SubImage> GetPrimaryImage() const { return GetSubImage(0); }
std::shared_ptr<SubImage> GetSubImage(uint32_t mipmap_level = 0) const;
const std::vector<std::shared_ptr<SubImage>> &GetSubImages() const { return sub_images_; }
uint32_t NumLevels() const { return sub_images_.size(); }
private:
bool loaded_{false};

View File

@ -137,12 +137,12 @@ void TextureFormatDXTTests::TestMipmap(const char *filename,
host_.PrepareDraw(0xFE101010);
DDSImage img;
bool loaded = img.LoadFile(filename);
bool loaded = img.LoadFile(filename, true);
ASSERT(loaded && "Failed to load test image from file.");
auto data = img.GetPrimaryImage();
auto primary_image = img.GetPrimaryImage();
uint32_t nv2a_format = 0;
switch (data->format) {
switch (primary_image->format) {
case DDSImage::SubImage::Format::DXT1:
nv2a_format = NV097_SET_TEXTURE_FORMAT_COLOR_L_DXT1_A1R5G5B5;
break;
@ -161,12 +161,17 @@ void TextureFormatDXTTests::TestMipmap(const char *filename,
auto &texture_stage = host_.GetTextureStage(0);
texture_stage.SetFormat(GetTextureFormatInfo(nv2a_format));
texture_stage.SetTextureDimensions(data->width, data->height);
texture_stage.SetTextureDimensions(primary_image->width, primary_image->height);
texture_stage.SetFilter(0, TextureStage::K_QUINCUNX, TextureStage::MIN_TENT_TENT_LOD);
texture_stage.SetMipMapLevels(10);
host_.SetRawTexture(data->data.data(), data->compressed_width, data->compressed_height, data->depth, data->pitch,
data->bytes_per_pixel, false);
texture_stage.SetMipMapLevels(img.NumLevels());
uint8_t *texture_ram = host_.GetTextureMemoryForStage(0);
for (auto &subimage : img.GetSubImages()) {
uint32_t size = subimage->pitch * subimage->compressed_height * subimage->depth;
memcpy(texture_ram, subimage->data.data(), size);
texture_ram += size;
}
host_.SetupTextureStages();
auto draw = [this](float left, float top, float size) {