You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
114 lines
3.8 KiB
114 lines
3.8 KiB
#include <cstdio> |
|
#include <glm/gtc/round.hpp> |
|
#include "../load_ktx.hpp" |
|
#include "file.hpp" |
|
|
|
namespace gli{ |
|
namespace detail |
|
{ |
|
inline texture::size_type compute_ktx_storage_size(texture const & Texture) |
|
{ |
|
texture::size_type const BlockSize = block_size(Texture.format()); |
|
texture::size_type TotalSize = sizeof(detail::FOURCC_KTX10) + sizeof(detail::ktx_header10); |
|
|
|
for(texture::size_type Level = 0, Levels = Texture.levels(); Level < Levels; ++Level) |
|
{ |
|
TotalSize += sizeof(std::uint32_t); |
|
|
|
for(texture::size_type Layer = 0, Layers = Texture.layers(); Layer < Layers; ++Layer) |
|
for(texture::size_type Face = 0, Faces = Texture.faces(); Face < Faces; ++Face) |
|
{ |
|
texture::size_type const FaceSize = Texture.size(Level); |
|
texture::size_type const PaddedSize = std::max(BlockSize, glm::ceilMultiple(FaceSize, static_cast<texture::size_type>(4))); |
|
|
|
TotalSize += PaddedSize; |
|
} |
|
} |
|
|
|
return TotalSize; |
|
} |
|
}//namespace detail |
|
|
|
inline bool save_ktx(texture const& Texture, std::vector<char>& Memory) |
|
{ |
|
if(Texture.empty()) |
|
return false; |
|
|
|
gl GL(gl::PROFILE_KTX); |
|
gl::format const& Format = GL.translate(Texture.format(), Texture.swizzles()); |
|
target const Target = Texture.target(); |
|
|
|
detail::formatInfo const& Desc = detail::get_format_info(Texture.format()); |
|
|
|
Memory.resize(detail::compute_ktx_storage_size(Texture)); |
|
|
|
std::memcpy(&Memory[0], detail::FOURCC_KTX10, sizeof(detail::FOURCC_KTX10)); |
|
|
|
std::size_t Offset = sizeof(detail::FOURCC_KTX10); |
|
|
|
detail::ktx_header10& Header = *reinterpret_cast<detail::ktx_header10*>(&Memory[0] + Offset); |
|
Header.Endianness = 0x04030201; |
|
Header.GLType = Format.Type; |
|
Header.GLTypeSize = Format.Type == gl::TYPE_NONE ? 1 : Desc.BlockSize; |
|
Header.GLFormat = Format.External; |
|
Header.GLInternalFormat = Format.Internal; |
|
Header.GLBaseInternalFormat = Format.External; |
|
Header.PixelWidth = static_cast<std::uint32_t>(Texture.extent().x); |
|
Header.PixelHeight = !is_target_1d(Target) ? static_cast<std::uint32_t>(Texture.extent().y) : 0; |
|
Header.PixelDepth = Target == TARGET_3D ? static_cast<std::uint32_t>(Texture.extent().z) : 0; |
|
Header.NumberOfArrayElements = is_target_array(Target) ? static_cast<std::uint32_t>(Texture.layers()) : 0; |
|
Header.NumberOfFaces = is_target_cube(Target) ? static_cast<std::uint32_t>(Texture.faces()) : 1; |
|
Header.NumberOfMipmapLevels = static_cast<std::uint32_t>(Texture.levels()); |
|
Header.BytesOfKeyValueData = 0; |
|
|
|
Offset += sizeof(detail::ktx_header10); |
|
|
|
for(texture::size_type Level = 0, Levels = Texture.levels(); Level < Levels; ++Level) |
|
{ |
|
std::uint32_t& ImageSize = *reinterpret_cast<std::uint32_t*>(&Memory[0] + Offset); |
|
Offset += sizeof(std::uint32_t); |
|
|
|
for(texture::size_type Layer = 0, Layers = Texture.layers(); Layer < Layers; ++Layer) |
|
for(texture::size_type Face = 0, Faces = Texture.faces(); Face < Faces; ++Face) |
|
{ |
|
texture::size_type const FaceSize = Texture.size(Level); |
|
|
|
std::memcpy(&Memory[0] + Offset, Texture.data(Layer, Face, Level), FaceSize); |
|
|
|
texture::size_type const PaddedSize = glm::ceilMultiple(FaceSize, static_cast<texture::size_type>(4)); |
|
|
|
ImageSize += static_cast<std::uint32_t>(PaddedSize); |
|
Offset += PaddedSize; |
|
|
|
GLI_ASSERT(Offset <= Memory.size()); |
|
} |
|
|
|
ImageSize = glm::ceilMultiple(ImageSize, static_cast<std::uint32_t>(4)); |
|
} |
|
|
|
return true; |
|
} |
|
|
|
inline bool save_ktx(texture const& Texture, char const* Filename) |
|
{ |
|
if(Texture.empty()) |
|
return false; |
|
|
|
FILE* File = detail::open_file(Filename, "wb"); |
|
if(!File) |
|
return false; |
|
|
|
std::vector<char> Memory; |
|
bool const Result = save_ktx(Texture, Memory); |
|
|
|
std::fwrite(&Memory[0], 1, Memory.size(), File); |
|
std::fclose(File); |
|
|
|
return Result; |
|
} |
|
|
|
inline bool save_ktx(texture const& Texture, std::string const& Filename) |
|
{ |
|
return save_ktx(Texture, Filename.c_str()); |
|
} |
|
}//namespace gli
|
|
|