27 #include "precompiled.h"
57 const u8* a_block = block;
58 const u8* c_block = (dxt == 3 || dxt == 5)? block+8 : block;
70 for(
int i = 0; i < 3; i++)
71 out[i] = (
u8)
c[c_selector][i];
93 out[
A] = (
u8)(a & 0xFF);
102 static inline void mix_2_3(
size_t dst[4],
size_t c0[4],
size_t c1[4])
104 for(
int i = 0; i < 3; i++) dst[i] = (c0[i]*2 + c1[i] + 1)/3;
107 static inline void mix_avg(
size_t dst[4],
size_t c0[4],
size_t c1[4])
109 for(
int i = 0; i < 3; i++) dst[i] = (c0[i]+c1[i])/2;
115 size_t val = (tbl >> (idx*bit_width)) & bit_mask<T>(bit_width);
125 const size_t num_filler_bits = 8-num_bits;
126 const size_t field = (size_t)
bits(c, bits_below, bits_below+num_bits-1);
127 const size_t filler = field >> (num_bits-num_filler_bits);
128 return (field << num_filler_bits) | filler;
134 const u8 a0 = a_block[0], a1 = a_block[1];
142 const bool is_dxt5_special_combination = (a0 <= a1);
144 if(is_dxt5_special_combination)
148 a[2] = (4*a0 + 1*a1 + 2)/5;
149 a[3] = (3*a0 + 2*a1 + 2)/5;
150 a[4] = (2*a0 + 3*a1 + 2)/5;
151 a[5] = (1*a0 + 4*a1 + 2)/5;
159 a[2] = (6*a0 + 1*a1 + 3)/7;
160 a[3] = (5*a0 + 2*a1 + 3)/7;
161 a[4] = (4*a0 + 3*a1 + 3)/7;
162 a[5] = (3*a0 + 4*a1 + 3)/7;
163 a[6] = (2*a0 + 5*a1 + 3)/7;
164 a[7] = (1*a0 + 6*a1 + 3)/7;
176 for(
int i = 0; i < 2; i++)
181 const bool is_dxt1_special_combination = (dxt == 1 || dxt ==
DXT1A) && rc[0] <= rc[1];
184 for(
int i = 0; i < 2; i++)
192 if(is_dxt1_special_combination)
195 for(
int i = 0; i < 3; i++)
c[3][i] = 0;
196 c[3][
A] = (dxt ==
DXT1A)? 0 : 255;
233 const size_t dxt = di->
dxt;
241 const u8* s3tc_data = level_data;
242 ENSURE(level_data_size % s3tc_block_size == 0);
244 for(
size_t block_y = 0; block_y < blocks_h; block_y++)
246 for(
size_t block_x = 0; block_x < blocks_w; block_x++)
249 s3tc_data += s3tc_block_size;
251 size_t pixel_idx = 0;
252 for(
int y = 0; y < 4; y++)
257 for(
int x = 0; x < 4; x++)
267 ENSURE(s3tc_data == level_data + level_data_size);
268 di->
out += blocks_w*blocks_h * 16 * di->
out_Bpp;
283 const size_t out_bpp = (dxt != 1)? 32 : 24;
285 shared_ptr<u8> decompressedData;
288 const size_t s3tc_block_size = (dxt == 3 || dxt == 5)? 16 : 8;
293 t->
data = decompressedData;
309 #pragma pack(push, 1)
316 #define DDPF_ALPHAPIXELS 0x00000001
317 #define DDPF_FOURCC 0x00000004
318 #define DDPF_RGB 0x00000040
334 #define DDSD_CAPS 0x00000001
335 #define DDSD_HEIGHT 0x00000002
336 #define DDSD_WIDTH 0x00000004
337 #define DDSD_PITCH 0x00000008 // used when texture is uncompressed
338 #define DDSD_PIXELFORMAT 0x00001000
339 #define DDSD_MIPMAPCOUNT 0x00020000
340 #define DDSD_LINEARSIZE 0x00080000 // used when texture is compressed
341 #define DDSD_DEPTH 0x00800000
344 #define DDSCAPS_MIPMAP 0x00400000 // optional
345 #define DDSCAPS_TEXTURE 0x00001000 // required
417 if(pf_a_mask != 0xFF000000)
418 goto unsupported_component_ordering;
423 if(pf_r_mask != 0xFF || pf_g_mask != 0xFF00 || pf_b_mask != 0xFF0000)
432 unsupported_component_ordering:
445 case FOURCC(
'D',
'X',
'T',
'1'):
452 case FOURCC(
'D',
'X',
'T',
'3'):
457 case FOURCC(
'D',
'X',
'T',
'5'):
490 if((sd_flags & sd_req_flags) != sd_req_flags)
503 size_t stored_h, stored_w;
506 stored_h = Align<4>(h);
507 stored_w = Align<4>(w);
516 const size_t pitch = stored_w*bpp/8;
520 if(sd_pitch_or_size != Align<4>(pitch))
528 if(sd_pitch_or_size != pitch*stored_h && abs(
ssize_t(sd_pitch_or_size)-totalSize) > 64)
542 if(mipmap_count !=
ceil_log2(std::max(w,h))+1)
562 const bool mipmap_flag = (flags &
TEX_MIPMAPS) != 0;
563 ENSURE(mipmap_cap == mipmap_flag);
575 return *(
u32*)file ==
FOURCC(
'D',
'D',
'S',
' ');
581 return extension == L
".dds";
617 const size_t transform_mipmaps = transforms &
TEX_MIPMAPS;
618 const size_t transform_dxt = transforms &
TEX_DXT;
620 if(mipmaps && transform_mipmaps)
624 t->
flags &= ~TEX_MIPMAPS;
628 if(dxt && transform_dxt)
void PrecalculateAlpha(size_t dxt, const u8 *RESTRICT a_block)
size_t ofs
offset to image data in file.
static Status dds_transform(Tex *t, size_t transforms)
static const size_t pageSize
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
u32 read_le32(const void *p)
const Status TEX_CODEC_CANNOT_HANDLE
T DivideRoundUp(T dividend, T divisor)
const int TEX_BASE_LEVEL_ONLY
special value for levels_to_skip: the callback will only be called for the base mipmap level (i...
static size_t access_bit_tbl(T tbl, size_t idx, size_t bit_width)
flags & TEX_DXT is a field indicating compression.
static void out(const wchar_t *fmt,...)
indicates the image contains an alpha channel.
provides a memory range that can be expanded but doesn't waste physical memory or relocate itself...
const Status TEX_INCOMPLETE_HEADER
shared_ptr< u8 > data
file buffer or image data.
static Status s3tc_decompress(Tex *t)
void PrecalculateColor(size_t dxt, const u8 *RESTRICT c_block)
static Status decode_sd(const DDS_HEADER *sd, size_t &w, size_t &h, size_t &bpp, size_t &flags)
u64 read_le64(const void *p)
see read_le16
static bool dds_is_hdr(const u8 *file)
static Status dds_encode(Tex *RESTRICT t, DynArray *RESTRICT da)
Status tex_validate_plain_format(size_t bpp, size_t flags)
check if the given texture format is acceptable: 8bpp grey, 24bpp color or 32bpp color+alpha (BGR / u...
static size_t unpack_to_8(u16 c, size_t bits_below, size_t num_bits)
const Status NOT_SUPPORTED
#define TIMER_ACCRUE(client)
Measure the time taken to execute code up until end of the current scope; bill it to the given TimerC...
const Status TEX_FMT_INVALID
#define ENSURE(expr)
ensure the expression <expr> evaluates to non-zero.
#define FOURCC(a, b, c, d)
convert 4 characters to u32 (at compile time) for easy comparison.
void WritePixel(size_t pixel_idx, u8 *RESTRICT out) const
static void s3tc_decompress_level(size_t level, size_t level_w, size_t level_h, const u8 *RESTRICT level_data, size_t level_data_size, void *RESTRICT cbData)
u8 * tex_get_data(const Tex *t)
rationale: since Tex is a struct, its fields are accessible to callers.
static Status decode_pf(const DDS_PIXELFORMAT *pf, size_t &bpp, size_t &flags)
i64 Status
Error handling system.
#define T(string_literal)
T bits(T num, size_t lo_idx, size_t hi_idx)
extract the value of bits hi_idx:lo_idx within num
stores all data describing an image.
static size_t dds_hdr_size(const u8 *file)
#define DEBUG_WARN_ERR(status)
display the error dialog with text corresponding to the given error code.
static void mix_2_3(size_t dst[4], size_t c0[4], size_t c1[4])
we need a special value for DXT1a to avoid having to consider flags & TEX_ALPHA to determine S3TC typ...
S3tcBlock(size_t dxt, const u8 *RESTRICT block)
static bool dds_is_ext(const OsPath &extension)
void tex_util_foreach_mipmap(size_t w, size_t h, size_t bpp, const u8 *pixels, int levels_to_skip, size_t data_padding, MipmapCB cb, void *RESTRICT cbData)
for a series of mipmaps stored from base to highest, call back for each level.
#define TIMER_ADD_CLIENT(id)
"allocate" a new TimerClient that will keep track of the total time billed to it, along with a descri...
static Status AllocateAligned(shared_ptr< T > &p, size_t size, size_t alignment=cacheLineSize)
u16 read_le16(const void *p)
read a little-endian number from memory into native byte order.
size_t ceil_log2(T x)
ceil(log2(x))
#define TEX_CODEC_REGISTER(name)
build codec vtbl and register it.
#define WARN_RETURN(status)
static Status dds_decode(rpU8 data, size_t size, Tex *RESTRICT t)
const Status TEX_INVALID_SIZE
size_t tex_img_size(const Tex *t)
return total byte size of the image pixels.
size_t flags
see TexFlags and "Format Conversion" in docs.
static void mix_avg(size_t dst[4], size_t c0[4], size_t c1[4])
static bool is_valid_dxt(size_t dxt)
#define RETURN_STATUS_IF_ERR(expression)