little finalization

This commit is contained in:
2019-06-28 12:52:35 +07:00
parent dd2dc510bc
commit 1b8cfbf902
5 changed files with 48 additions and 99 deletions

View File

@@ -696,28 +696,4 @@ namespace e2d::math
E2D_ASSERT(!approximately(l, r, T(0)));
return (v - l) / (r - l);
}
//
// align_floor/align_ceil
//
template < typename T, typename U >
std::enable_if_t<
std::is_integral_v<T> &&
std::is_convertible_v<U,T>,
T>
align_ceil (T v, U alignment) {
T result = ((v + alignment - 1) / alignment) * alignment;
E2D_ASSERT(result >= v);
return result;
}
template < typename T, typename U >
std::enable_if_t<
std::is_integral_v<T> &&
std::is_convertible_v<U,T>,
T>
align_floor (T v, U alignment) {
return (v / alignment) * alignment;
}
}

View File

@@ -12,7 +12,7 @@ namespace
// https://docs.microsoft.com/en-us/windows/desktop/direct3ddds/dx-graphics-dds-pguide
using namespace e2d;
// pixel format flags
const u32 ddsf_alphapixels = 0x00000001;
const u32 ddsf_fourcc = 0x00000004;
@@ -24,33 +24,11 @@ namespace
const u32 ddsf_volume = 0x00200000;
// compressed texture types
const u32 fourcc_dxt1 = 0x31545844; //(MAKEFOURCC('D','X','T','1'))
const u32 fourcc_dxt3 = 0x33545844; //(MAKEFOURCC('D','X','T','3'))
const u32 fourcc_dxt5 = 0x35545844; //(MAKEFOURCC('D','X','T','5'))
const u32 fourcc_dxt1 = 0x31545844; // 'DXT1'
const u32 fourcc_dxt3 = 0x33545844; // 'DXT3'
const u32 fourcc_dxt5 = 0x35545844; // 'DXT5'
struct DXTColBlock
{
u16 col0;
u16 col1;
u8 row[4];
};
struct DXT3AlphaBlock
{
u16 row[4];
};
struct DXT5AlphaBlock
{
u8 alpha0;
u8 alpha1;
u8 row[6];
};
struct dds_pixelformat
{
struct dds_pixel_format {
u32 dwSize;
u32 dwFlags;
u32 dwFourCC;
@@ -61,8 +39,8 @@ namespace
u32 dwABitMask;
};
struct dds_header
{
struct dds_header {
u32 dwMagic;
u32 dwSize;
u32 dwFlags;
u32 dwHeight;
@@ -71,39 +49,34 @@ namespace
u32 dwDepth;
u32 dwMipMapCount;
u32 dwReserved1[11];
dds_pixelformat ddspf;
dds_pixel_format ddspf;
u32 dwCaps1;
u32 dwCaps2;
u32 dwReserved2[3];
};
struct dds_header_with_magic
{
u32 dwMagicFourCC;
dds_header header;
};
static_assert(sizeof(dds_pixel_format) == 32, "invalid dds_pixel_format structure size");
static_assert(sizeof(dds_header) == 128, "invalid dds_header structure size");
static_assert(sizeof(dds_pixelformat) == 32, "invalid DDSS pixelformat structure size");
static_assert(sizeof(dds_header) == 124, "invalid DDS header size");
bool is_dds(const void* data, std::size_t byte_size) {
if ( byte_size > sizeof(dds_header_with_magic) ) {
const auto* hdr = reinterpret_cast<const dds_header_with_magic*>(data);
return hdr->dwMagicFourCC == 0x20534444; // DDS
bool is_dds(const void* data, std::size_t byte_size) noexcept {
if ( byte_size > sizeof(dds_header) ) {
const auto* hdr = reinterpret_cast<const dds_header*>(data);
return hdr->dwMagic == 0x20534444; // 'DDS '
}
return false;
}
bool get_dds_format(const dds_header& hdr, image_data_format& out_format, u32& out_bytes_per_block) {
out_format = image_data_format(-1);
out_bytes_per_block = 0;
bool get_dds_format(
const dds_header& hdr,
image_data_format& out_format,
u32& out_bytes_per_block) noexcept
{
if ( math::check_all_flags(hdr.ddspf.dwFlags, ddsf_fourcc) ) {
switch (hdr.ddspf.dwFourCC)
{
switch ( hdr.ddspf.dwFourCC ) {
case fourcc_dxt1:
out_format = math::check_all_flags(hdr.ddspf.dwFlags, ddsf_alphapixels)
? image_data_format::rgba_dxt1
: image_data_format::rgb_dxt1;
? image_data_format::rgba_dxt1
: image_data_format::rgb_dxt1;
out_bytes_per_block = 8;
break;
case fourcc_dxt3:
@@ -115,17 +88,17 @@ namespace
out_bytes_per_block = 16;
break;
default:
return false; // unsupported compressed format
return false;
}
} else if ( math::check_all_flags(hdr.ddspf.dwFlags, ddsf_rgba|ddsf_rgb) && (hdr.ddspf.dwRGBBitCount == 32) ) {
out_bytes_per_block = 4;
} else if ( math::check_all_flags(hdr.ddspf.dwFlags, ddsf_rgba) && (hdr.ddspf.dwRGBBitCount == 32) ) {
out_format = image_data_format::rgba8;
out_bytes_per_block = 4;
if ( hdr.ddspf.dwRBitMask == 0x00FF0000 ) {
return false; // BGRA format is not supported
}
} else if ( math::check_all_flags(hdr.ddspf.dwFlags, ddsf_rgb) && (hdr.ddspf.dwRGBBitCount == 24) ) {
out_bytes_per_block = 3;
out_format = image_data_format::rgb8;
out_bytes_per_block = 3;
if (hdr.ddspf.dwRBitMask == 0x00FF0000) {
return false; // BGRA format is not supported
}
@@ -134,6 +107,8 @@ namespace
} else if ( hdr.ddspf.dwRGBBitCount == 8 ) {
out_format = image_data_format::g8;
out_bytes_per_block = 1;
} else {
return false;
}
return true;
}
@@ -145,23 +120,26 @@ namespace e2d::images::impl
if ( !is_dds(src.data(), src.size()) ) {
return false;
}
const dds_header& hdr = reinterpret_cast<const dds_header_with_magic*>(src.data())->header;
const u8* content = src.data() + sizeof(dds_header_with_magic);
const dds_header& hdr = *reinterpret_cast<const dds_header*>(src.data());
const u8* content = src.data() + sizeof(dds_header);
if ( math::check_all_flags(hdr.dwCaps2, ddsf_cubemap) ||
math::check_all_flags(hdr.dwCaps2, ddsf_volume) ||
(hdr.dwDepth > 0) ) {
return false; // cubemap and volume textures are not supported
(hdr.dwDepth > 0) )
{
return false;
}
image_data_format format = image_data_format(-1);
u32 bytes_per_block = 0;
if ( !get_dds_format(hdr, format, bytes_per_block) ) {
return false; // unsupported format
return false;
}
//u32 num_mipmaps = (hdr.dwMipMapCount == 0) ? 1 : hdr.dwMipMapCount;
v2u dimension = v2u(hdr.dwWidth, hdr.dwHeight);
const v2u dimension = v2u(hdr.dwWidth, hdr.dwHeight);
std::size_t size;
switch (format)
{
switch ( format ) {
case image_data_format::rgb_dxt1:
case image_data_format::rgba_dxt3:
case image_data_format::rgba_dxt5:
@@ -171,6 +149,7 @@ namespace e2d::images::impl
size = dimension.x * dimension.y * bytes_per_block;
break;
}
dst = image(dimension, format, buffer(content, size));
return true;
}

View File

@@ -118,7 +118,7 @@ namespace
bool get_pvr_format(const pvr_header& hdr, image_data_format& out_format, u32& out_bytes_per_block, v2u& out_block_size) {
if ( pvr_color_space(hdr.colorSpace) != pvr_color_space::linear ) {
return false; // only linear color space is supported
return false;
}
const pvr_pixel_format fmt = pvr_pixel_format(hdr.pixelFormat0 | (u64(hdr.pixelFormat1) << 32));
switch (fmt)
@@ -189,7 +189,7 @@ namespace
out_block_size = v2u(1,1);
break;
default:
return false; // unsupported format
return false;
}
return true;
}
@@ -206,15 +206,11 @@ namespace e2d::images::impl
if ( hdr.numSurfaces != 1 || hdr.numFaces != 1 || hdr.depth > 1 ) {
return false; // cubemap and volume textures are not supported
}
// TODO:
// if ( math::check_all_flags(hdr.flags, pvr_flags::premultiplied) ) {
// ...
// }
image_data_format format = image_data_format(-1);
u32 bytes_per_block = 0;
v2u block_size = v2u(1,1);
if ( !get_pvr_format(hdr, format, bytes_per_block, block_size) ) {
return false; // unsupported format
return false;
}
v2u dimension = v2u(hdr.width, hdr.height);
std::size_t size = bytes_per_block *

View File

@@ -661,8 +661,4 @@ TEST_CASE("math") {
REQUIRE_FALSE(math::approximately<u32>(umin,umax,1));
REQUIRE_FALSE(math::approximately<u32>(umax,umin,1));
}
{
REQUIRE(math::align_ceil(11, 4) == 12);
REQUIRE(math::align_floor(11, 4u) == 8);
}
}

View File

@@ -131,10 +131,11 @@ TEST_CASE("images") {
}
{
struct img_info {
str_view name;
const char* name;
bool can_load;
image_data_format format;
};
const img_info test_images[] = {
{"bin/images/ship_pvrtc_2bpp_rgba.pvr", true, image_data_format::rgba_pvrtc2},
{"bin/images/ship_pvrtc_2bpp_rgb.pvr", true, image_data_format::rgb_pvrtc2},
@@ -151,12 +152,13 @@ TEST_CASE("images") {
{"bin/images/ship_rg8.pvr", true, image_data_format::ga8},
{"bin/images/ship_rgb8.pvr", true, image_data_format::rgb8}
};
str resources;
REQUIRE(filesystem::extract_predef_path(
resources,
filesystem::predef_path::resources));
for (auto& info : test_images) {
for ( const auto& info : test_images ) {
input_stream_uptr stream = make_read_file(path::combine(resources, info.name));
REQUIRE(stream);
image img;