Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
tex_dds.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2010 Wildfire Games
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining
4  * a copy of this software and associated documentation files (the
5  * "Software"), to deal in the Software without restriction, including
6  * without limitation the rights to use, copy, modify, merge, publish,
7  * distribute, sublicense, and/or sell copies of the Software, and to
8  * permit persons to whom the Software is furnished to do so, subject to
9  * the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 /*
24  * DDS (DirectDraw Surface) codec.
25  */
26 
27 #include "precompiled.h"
28 
29 #include "lib/byte_order.h"
30 #include "lib/bits.h"
31 #include "lib/timer.h"
33 #include "tex_codec.h"
34 
35 
36 // NOTE: the convention is bottom-up for DDS, but there's no way to tell.
37 
38 
39 //-----------------------------------------------------------------------------
40 // S3TC decompression
41 //-----------------------------------------------------------------------------
42 
43 // note: this code may not be terribly efficient. it's only used to
44 // emulate hardware S3TC support - if that isn't available, performance
45 // will suffer anyway due to increased video memory usage.
46 
47 
48 // for efficiency, we precalculate as much as possible about a block
49 // and store it here.
50 class S3tcBlock
51 {
52 public:
53  S3tcBlock(size_t dxt, const u8* RESTRICT block)
54  : dxt(dxt)
55  {
56  // (careful, 'dxt != 1' doesn't work - there's also DXT1a)
57  const u8* a_block = block;
58  const u8* c_block = (dxt == 3 || dxt == 5)? block+8 : block;
59 
60  PrecalculateAlpha(dxt, a_block);
61  PrecalculateColor(dxt, c_block);
62  }
63 
64  void WritePixel(size_t pixel_idx, u8* RESTRICT out) const
65  {
66  ENSURE(pixel_idx < 16);
67 
68  // pixel index -> color selector (2 bit) -> color
69  const size_t c_selector = access_bit_tbl(c_selectors, pixel_idx, 2);
70  for(int i = 0; i < 3; i++)
71  out[i] = (u8)c[c_selector][i];
72 
73  // if no alpha, done
74  if(dxt == 1)
75  return;
76 
77  size_t a;
78  if(dxt == 3)
79  {
80  // table of 4-bit alpha entries
81  a = access_bit_tbl(a_bits, pixel_idx, 4);
82  a |= a << 4; // expand to 8 bits (replicate high into low!)
83  }
84  else if(dxt == 5)
85  {
86  // pixel index -> alpha selector (3 bit) -> alpha
87  const size_t a_selector = access_bit_tbl(a_bits, pixel_idx, 3);
88  a = dxt5_a_tbl[a_selector];
89  }
90  // (dxt == DXT1A)
91  else
92  a = c[c_selector][A];
93  out[A] = (u8)(a & 0xFF);
94  }
95 
96 private:
97  // pixel colors are stored as size_t[4]. size_t rather than u8 protects from
98  // overflow during calculations, and padding to an even size is a bit
99  // more efficient (even though we don't need the alpha component).
100  enum RGBA { R, G, B, A };
101 
102  static inline void mix_2_3(size_t dst[4], size_t c0[4], size_t c1[4])
103  {
104  for(int i = 0; i < 3; i++) dst[i] = (c0[i]*2 + c1[i] + 1)/3;
105  }
106 
107  static inline void mix_avg(size_t dst[4], size_t c0[4], size_t c1[4])
108  {
109  for(int i = 0; i < 3; i++) dst[i] = (c0[i]+c1[i])/2;
110  }
111 
112  template<typename T>
113  static inline size_t access_bit_tbl(T tbl, size_t idx, size_t bit_width)
114  {
115  size_t val = (tbl >> (idx*bit_width)) & bit_mask<T>(bit_width);
116  return val;
117  }
118 
119  // extract a range of bits and expand to 8 bits (by replicating
120  // MS bits - see http://www.mindcontrol.org/~hplus/graphics/expand-bits.html ;
121  // this is also the algorithm used by graphics cards when decompressing S3TC).
122  // used to convert 565 to 32bpp RGB.
123  static inline size_t unpack_to_8(u16 c, size_t bits_below, size_t num_bits)
124  {
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;
129  }
130 
131  void PrecalculateAlpha(size_t dxt, const u8* RESTRICT a_block)
132  {
133  // read block contents
134  const u8 a0 = a_block[0], a1 = a_block[1];
135  a_bits = read_le64(a_block); // see below
136 
137  if(dxt == 5)
138  {
139  // skip a0,a1 bytes (data is little endian)
140  a_bits >>= 16;
141 
142  const bool is_dxt5_special_combination = (a0 <= a1);
143  u8* a = dxt5_a_tbl; // shorthand
144  if(is_dxt5_special_combination)
145  {
146  a[0] = a0;
147  a[1] = a1;
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;
152  a[6] = 0;
153  a[7] = 255;
154  }
155  else
156  {
157  a[0] = a0;
158  a[1] = a1;
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;
165  }
166  }
167  }
168 
169 
170  void PrecalculateColor(size_t dxt, const u8* RESTRICT c_block)
171  {
172  // read block contents
173  // .. S3TC reference colors (565 format). the color table is generated
174  // from some combination of these, depending on their ordering.
175  u16 rc[2];
176  for(int i = 0; i < 2; i++)
177  rc[i] = read_le16(c_block + 2*i);
178  // .. table of 2-bit color selectors
179  c_selectors = read_le32(c_block+4);
180 
181  const bool is_dxt1_special_combination = (dxt == 1 || dxt == DXT1A) && rc[0] <= rc[1];
182 
183  // c0 and c1 are the values of rc[], converted to 32bpp
184  for(int i = 0; i < 2; i++)
185  {
186  c[i][R] = unpack_to_8(rc[i], 11, 5);
187  c[i][G] = unpack_to_8(rc[i], 5, 6);
188  c[i][B] = unpack_to_8(rc[i], 0, 5);
189  }
190 
191  // c2 and c3 are combinations of c0 and c1:
192  if(is_dxt1_special_combination)
193  {
194  mix_avg(c[2], c[0], c[1]); // c2 = (c0+c1)/2
195  for(int i = 0; i < 3; i++) c[3][i] = 0; // c3 = black
196  c[3][A] = (dxt == DXT1A)? 0 : 255; // (transparent iff DXT1a)
197  }
198  else
199  {
200  mix_2_3(c[2], c[0], c[1]); // c2 = 2/3*c0 + 1/3*c1
201  mix_2_3(c[3], c[1], c[0]); // c3 = 1/3*c0 + 2/3*c1
202  }
203  }
204 
205  // the 4 color choices for each pixel (RGBA)
206  size_t c[4][4]; // c[i][RGBA_component]
207 
208  // (DXT5 only) the 8 alpha choices
210 
211  // alpha block; interpretation depends on dxt.
213 
214  // table of 2-bit color selectors
216 
217  size_t dxt;
218 };
219 
220 
222 {
223  size_t dxt;
225  size_t out_Bpp;
226  u8* out;
227 };
228 
229 static void s3tc_decompress_level(size_t UNUSED(level), size_t level_w, size_t level_h,
230  const u8* RESTRICT level_data, size_t level_data_size, void* RESTRICT cbData)
231 {
232  S3tcDecompressInfo* di = (S3tcDecompressInfo*)cbData;
233  const size_t dxt = di->dxt;
234  const size_t s3tc_block_size = di->s3tc_block_size;
235 
236  // note: 1x1 images are legitimate (e.g. in mipmaps). they report their
237  // width as such for glTexImage, but the S3TC data is padded to
238  // 4x4 pixel block boundaries.
239  const size_t blocks_w = DivideRoundUp(level_w, size_t(4));
240  const size_t blocks_h = DivideRoundUp(level_h, size_t(4));
241  const u8* s3tc_data = level_data;
242  ENSURE(level_data_size % s3tc_block_size == 0);
243 
244  for(size_t block_y = 0; block_y < blocks_h; block_y++)
245  {
246  for(size_t block_x = 0; block_x < blocks_w; block_x++)
247  {
248  S3tcBlock block(dxt, s3tc_data);
249  s3tc_data += s3tc_block_size;
250 
251  size_t pixel_idx = 0;
252  for(int y = 0; y < 4; y++)
253  {
254  // this is ugly, but advancing after x, y and block_y loops
255  // is no better.
256  u8* out = (u8*)di->out + ((block_y*4+y)*blocks_w*4 + block_x*4) * di->out_Bpp;
257  for(int x = 0; x < 4; x++)
258  {
259  block.WritePixel(pixel_idx, out);
260  out += di->out_Bpp;
261  pixel_idx++;
262  }
263  }
264  }
265  }
266 
267  ENSURE(s3tc_data == level_data + level_data_size);
268  di->out += blocks_w*blocks_h * 16 * di->out_Bpp;
269 }
270 
271 
272 // decompress the given image (which is known to be stored as DXTn)
273 // effectively in-place. updates Tex fields.
275 {
276  // alloc new image memory
277  // notes:
278  // - dxt == 1 is the only non-alpha case.
279  // - adding or stripping alpha channels during transform is not
280  // our job; we merely output the same pixel format as given
281  // (tex.cpp's plain transform could cover it, if ever needed).
282  const size_t dxt = t->flags & TEX_DXT;
283  const size_t out_bpp = (dxt != 1)? 32 : 24;
284  const size_t out_size = tex_img_size(t) * out_bpp / t->bpp;
285  shared_ptr<u8> decompressedData;
286  AllocateAligned(decompressedData, out_size, pageSize);
287 
288  const size_t s3tc_block_size = (dxt == 3 || dxt == 5)? 16 : 8;
289  S3tcDecompressInfo di = { dxt, s3tc_block_size, out_bpp/8, decompressedData.get() };
290  const u8* s3tc_data = tex_get_data(t);
291  const int levels_to_skip = (t->flags & TEX_MIPMAPS)? 0 : TEX_BASE_LEVEL_ONLY;
292  tex_util_foreach_mipmap(t->w, t->h, t->bpp, s3tc_data, levels_to_skip, 4, s3tc_decompress_level, &di);
293  t->data = decompressedData;
294  t->dataSize = out_size;
295  t->ofs = 0;
296  t->bpp = out_bpp;
297  t->flags &= ~TEX_DXT;
298  return INFO::OK;
299 }
300 
301 
302 //-----------------------------------------------------------------------------
303 // DDS file format
304 //-----------------------------------------------------------------------------
305 
306 // bit values and structure definitions taken from
307 // http://msdn.microsoft.com/en-us/library/ee417785(VS.85).aspx
308 
309 #pragma pack(push, 1)
310 
311 // DDS_PIXELFORMAT.dwFlags
312 // we've seen some DXT3 files that don't have this set (which is nonsense;
313 // any image lacking alpha should be stored as DXT1). it's authoritative
314 // if fourcc is DXT1 (there's no other way to tell DXT1 and DXT1a apart)
315 // and ignored otherwise.
316 #define DDPF_ALPHAPIXELS 0x00000001
317 #define DDPF_FOURCC 0x00000004
318 #define DDPF_RGB 0x00000040
319 
321 {
322  u32 dwSize; // size of structure (32)
323  u32 dwFlags; // indicates which fields are valid
324  u32 dwFourCC; // (DDPF_FOURCC) FOURCC code, "DXTn"
325  u32 dwRGBBitCount; // (DDPF_RGB) bits per pixel
329  u32 dwABitMask; // (DDPF_ALPHAPIXELS)
330 };
331 
332 
333 // DDS_HEADER.dwFlags (none are optional)
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
342 
343 // DDS_HEADER.dwCaps
344 #define DDSCAPS_MIPMAP 0x00400000 // optional
345 #define DDSCAPS_TEXTURE 0x00001000 // required
346 
348 {
349  // (preceded by the FOURCC "DDS ")
350  u32 dwSize; // size of structure (124)
351  u32 dwFlags; // indicates which fields are valid
352  u32 dwHeight; // (DDSD_HEIGHT) height of main image (pixels)
353  u32 dwWidth; // (DDSD_WIDTH ) width of main image (pixels)
354  u32 dwPitchOrLinearSize; // (DDSD_LINEARSIZE) size [bytes] of top level
355  // (DDSD_PITCH) bytes per row (%4 = 0)
356  u32 dwDepth; // (DDSD_DEPTH) vol. textures: vol. depth
357  u32 dwMipMapCount; // (DDSD_MIPMAPCOUNT) total # levels
358  u32 dwReserved1[11]; // reserved
359  DDS_PIXELFORMAT ddpf; // (DDSD_PIXELFORMAT) surface description
360  u32 dwCaps; // (DDSD_CAPS) misc. surface flags
364  u32 dwReserved2; // reserved
365 };
366 
367 #pragma pack(pop)
368 
369 
370 static bool is_valid_dxt(size_t dxt)
371 {
372  switch(dxt)
373  {
374  case 0:
375  case 1:
376  case DXT1A:
377  case 3:
378  case 5:
379  return true;
380  default:
381  return false;
382  }
383 }
384 
385 
386 // extract all information from DDS pixel format and store in bpp, flags.
387 // pf points to the DDS file's header; all fields must be endian-converted
388 // before use.
389 // output parameters invalid on failure.
390 static Status decode_pf(const DDS_PIXELFORMAT* pf, size_t& bpp, size_t& flags)
391 {
392  bpp = 0;
393  flags = 0;
394 
395  // check struct size
396  if(read_le32(&pf->dwSize) != sizeof(DDS_PIXELFORMAT))
398 
399  // determine type
400  const size_t pf_flags = (size_t)read_le32(&pf->dwFlags);
401  // .. uncompressed
402  if(pf_flags & DDPF_RGB)
403  {
404  const size_t pf_bpp = (size_t)read_le32(&pf->dwRGBBitCount);
405  const size_t pf_r_mask = (size_t)read_le32(&pf->dwRBitMask);
406  const size_t pf_g_mask = (size_t)read_le32(&pf->dwGBitMask);
407  const size_t pf_b_mask = (size_t)read_le32(&pf->dwBBitMask);
408  const size_t pf_a_mask = (size_t)read_le32(&pf->dwABitMask);
409 
410  // (checked below; must be set in case below warning is to be
411  // skipped)
412  bpp = pf_bpp;
413 
414  if(pf_flags & DDPF_ALPHAPIXELS)
415  {
416  // something weird other than RGBA or BGRA
417  if(pf_a_mask != 0xFF000000)
418  goto unsupported_component_ordering;
419  flags |= TEX_ALPHA;
420  }
421 
422  // make sure component ordering is 0xBBGGRR = RGB (see below)
423  if(pf_r_mask != 0xFF || pf_g_mask != 0xFF00 || pf_b_mask != 0xFF0000)
424  {
425  // DDS_PIXELFORMAT in theory supports any ordering of R,G,B,A.
426  // we need to upload to OpenGL, which can only receive BGR(A) or
427  // RGB(A). the former still requires conversion (done by driver),
428  // so it's slower. since the very purpose of supporting uncompressed
429  // DDS is storing images in a format that requires no processing,
430  // we do not allow any weird orderings that require runtime work.
431  // instead, the artists must export with the correct settings.
432  unsupported_component_ordering:
434  }
435 
437  }
438  // .. compressed
439  else if(pf_flags & DDPF_FOURCC)
440  {
441  // set effective bpp and store DXT format in flags & TEX_DXT.
442  // no endian conversion necessary - FOURCC() takes care of that.
443  switch(pf->dwFourCC)
444  {
445  case FOURCC('D','X','T','1'):
446  bpp = 4;
447  if(pf_flags & DDPF_ALPHAPIXELS)
448  flags |= DXT1A | TEX_ALPHA;
449  else
450  flags |= 1;
451  break;
452  case FOURCC('D','X','T','3'):
453  bpp = 8;
454  flags |= 3;
455  flags |= TEX_ALPHA; // see DDPF_ALPHAPIXELS decl
456  break;
457  case FOURCC('D','X','T','5'):
458  bpp = 8;
459  flags |= 5;
460  flags |= TEX_ALPHA; // see DDPF_ALPHAPIXELS decl
461  break;
462 
463  default:
465  }
466  }
467  // .. neither uncompressed nor compressed - invalid
468  else
470 
471  return INFO::OK;
472 }
473 
474 
475 // extract all information from DDS header and store in w, h, bpp, flags.
476 // sd points to the DDS file's header; all fields must be endian-converted
477 // before use.
478 // output parameters invalid on failure.
479 static Status decode_sd(const DDS_HEADER* sd, size_t& w, size_t& h, size_t& bpp, size_t& flags)
480 {
481  // check header size
482  if(read_le32(&sd->dwSize) != sizeof(*sd))
484 
485  // flags (indicate which fields are valid)
486  const size_t sd_flags = (size_t)read_le32(&sd->dwFlags);
487  // .. not all required fields are present
488  // note: we can't guess dimensions - the image may not be square.
489  const size_t sd_req_flags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT;
490  if((sd_flags & sd_req_flags) != sd_req_flags)
492 
493  // image dimensions
494  h = (size_t)read_le32(&sd->dwHeight);
495  w = (size_t)read_le32(&sd->dwWidth);
496 
497  // pixel format
498  RETURN_STATUS_IF_ERR(decode_pf(&sd->ddpf, bpp, flags));
499 
500  // if the image is not aligned with the S3TC block size, it is stored
501  // with extra pixels on the bottom left to fill up the space, so we need
502  // to account for those when calculating how big it should be
503  size_t stored_h, stored_w;
504  if(flags & TEX_DXT)
505  {
506  stored_h = Align<4>(h);
507  stored_w = Align<4>(w);
508  }
509  else
510  {
511  stored_h = h;
512  stored_w = w;
513  }
514 
515  // verify pitch or linear size, if given
516  const size_t pitch = stored_w*bpp/8;
517  const size_t sd_pitch_or_size = (size_t)read_le32(&sd->dwPitchOrLinearSize);
518  if(sd_flags & DDSD_PITCH)
519  {
520  if(sd_pitch_or_size != Align<4>(pitch))
522  }
523  if(sd_flags & DDSD_LINEARSIZE)
524  {
525  // some DDS tools mistakenly store the total size of all levels,
526  // so allow values close to that as well
527  const ssize_t totalSize = ssize_t(pitch*stored_h*1.333333f);
528  if(sd_pitch_or_size != pitch*stored_h && abs(ssize_t(sd_pitch_or_size)-totalSize) > 64)
530  }
531  // note: both flags set would be invalid; no need to check for that,
532  // though, since one of the above tests would fail.
533 
534  // mipmaps
535  if(sd_flags & DDSD_MIPMAPCOUNT)
536  {
537  const size_t mipmap_count = (size_t)read_le32(&sd->dwMipMapCount);
538  if(mipmap_count)
539  {
540  // mipmap chain is incomplete
541  // note: DDS includes the base level in its count, hence +1.
542  if(mipmap_count != ceil_log2(std::max(w,h))+1)
544  flags |= TEX_MIPMAPS;
545  }
546  }
547 
548  // check for volume textures
549  if(sd_flags & DDSD_DEPTH)
550  {
551  const size_t depth = (size_t)read_le32(&sd->dwDepth);
552  if(depth)
554  }
555 
556  // check caps
557  // .. this is supposed to be set, but don't bail if not (pointless)
559  // .. sanity check: warn if mipmap flag not set (don't bail if not
560  // because we've already made the decision).
561  const bool mipmap_cap = (sd->dwCaps & DDSCAPS_MIPMAP) != 0;
562  const bool mipmap_flag = (flags & TEX_MIPMAPS) != 0;
563  ENSURE(mipmap_cap == mipmap_flag);
564  // note: we do not check for cubemaps and volume textures (not supported)
565  // because the file may still have useful data we can read.
566 
567  return INFO::OK;
568 }
569 
570 
571 //-----------------------------------------------------------------------------
572 
573 static bool dds_is_hdr(const u8* file)
574 {
575  return *(u32*)file == FOURCC('D','D','S',' ');
576 }
577 
578 
579 static bool dds_is_ext(const OsPath& extension)
580 {
581  return extension == L".dds";
582 }
583 
584 
585 static size_t dds_hdr_size(const u8* UNUSED(file))
586 {
587  return 4+sizeof(DDS_HEADER);
588 }
589 
590 
591 static Status dds_decode(rpU8 data, size_t UNUSED(size), Tex* RESTRICT t)
592 {
593  const DDS_HEADER* sd = (const DDS_HEADER*)(data+4);
594  RETURN_STATUS_IF_ERR(decode_sd(sd, t->w, t->h, t->bpp, t->flags));
595  return INFO::OK;
596 }
597 
598 
600 {
601  // note: do not return ERR::NOT_SUPPORTED et al. because that would
602  // break tex_write (which assumes either this, 0 or errors are returned).
604 }
605 
606 
607 TIMER_ADD_CLIENT(tc_dds_transform);
608 
609 static Status dds_transform(Tex* t, size_t transforms)
610 {
611  TIMER_ACCRUE(tc_dds_transform);
612 
613  size_t mipmaps = t->flags & TEX_MIPMAPS;
614  size_t dxt = t->flags & TEX_DXT;
615  ENSURE(is_valid_dxt(dxt));
616 
617  const size_t transform_mipmaps = transforms & TEX_MIPMAPS;
618  const size_t transform_dxt = transforms & TEX_DXT;
619  // requesting removal of mipmaps
620  if(mipmaps && transform_mipmaps)
621  {
622  // we don't need to actually change anything except the flag - the
623  // mipmap levels will just be treated as trailing junk
624  t->flags &= ~TEX_MIPMAPS;
625  return INFO::OK;
626  }
627  // requesting decompression
628  if(dxt && transform_dxt)
629  {
631  return INFO::OK;
632  }
633  // both are DXT (unsupported; there are no flags we can change while
634  // compressed) or requesting compression (not implemented) or
635  // both not DXT (nothing we can do) - bail.
637 }
638 
639 
640 TEX_CODEC_REGISTER(dds);
void PrecalculateAlpha(size_t dxt, const u8 *RESTRICT a_block)
Definition: tex_dds.cpp:131
#define u8
Definition: types.h:39
size_t ofs
offset to image data in file.
Definition: tex.h:227
static Status dds_transform(Tex *t, size_t transforms)
Definition: tex_dds.cpp:609
static const size_t pageSize
Definition: alignment.h:61
u32 dwMipMapCount
Definition: tex_dds.cpp:357
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
u32 read_le32(const void *p)
Definition: byte_order.cpp:73
const Status TEX_CODEC_CANNOT_HANDLE
Definition: tex.h:132
T DivideRoundUp(T dividend, T divisor)
Definition: lib.h:75
const int TEX_BASE_LEVEL_ONLY
special value for levels_to_skip: the callback will only be called for the base mipmap level (i...
Definition: tex.h:399
const Status OK
Definition: status.h:386
size_t s3tc_block_size
Definition: tex_dds.cpp:224
#define DDSD_WIDTH
Definition: tex_dds.cpp:336
#define DDSD_HEIGHT
Definition: tex_dds.cpp:335
#define DDPF_FOURCC
Definition: tex_dds.cpp:317
static size_t access_bit_tbl(T tbl, size_t idx, size_t bit_width)
Definition: tex_dds.cpp:113
flags &amp; TEX_DXT is a field indicating compression.
Definition: tex.h:149
static void out(const wchar_t *fmt,...)
Definition: wdbg_sym.cpp:419
mask
Definition: tex.h:199
indicates the image contains an alpha channel.
Definition: tex.h:171
provides a memory range that can be expanded but doesn&#39;t waste physical memory or relocate itself...
Definition: dynarray.h:39
const Status TEX_INCOMPLETE_HEADER
Definition: tex.h:116
shared_ptr< u8 > data
file buffer or image data.
Definition: tex.h:217
static Status s3tc_decompress(Tex *t)
Definition: tex_dds.cpp:274
const Status CORRUPTED
Definition: status.h:413
#define DDSD_CAPS
Definition: tex_dds.cpp:334
void PrecalculateColor(size_t dxt, const u8 *RESTRICT c_block)
Definition: tex_dds.cpp:170
size_t c[4][4]
Definition: tex_dds.cpp:206
u32 dwReserved1[11]
Definition: tex_dds.cpp:358
static Status decode_sd(const DDS_HEADER *sd, size_t &w, size_t &h, size_t &bpp, size_t &flags)
Definition: tex_dds.cpp:479
u64 read_le64(const void *p)
see read_le16
Definition: byte_order.cpp:80
size_t h
Definition: tex.h:230
u32 dwCaps
Definition: tex_dds.cpp:360
static bool dds_is_hdr(const u8 *file)
Definition: tex_dds.cpp:573
static Status dds_encode(Tex *RESTRICT t, DynArray *RESTRICT da)
Definition: tex_dds.cpp:599
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...
Definition: tex.cpp:101
static size_t unpack_to_8(u16 c, size_t bits_below, size_t num_bits)
Definition: tex_dds.cpp:123
#define DDSD_LINEARSIZE
Definition: tex_dds.cpp:340
const Status NOT_SUPPORTED
Definition: status.h:429
#define TIMER_ACCRUE(client)
Measure the time taken to execute code up until end of the current scope; bill it to the given TimerC...
Definition: timer.h:389
u32 dwFlags
Definition: tex_dds.cpp:351
uint8_t *__restrict rpU8
const Status TEX_FMT_INVALID
Definition: tex.h:117
DDS_PIXELFORMAT ddpf
Definition: tex_dds.cpp:359
#define DDSD_MIPMAPCOUNT
Definition: tex_dds.cpp:339
#define ENSURE(expr)
ensure the expression &lt;expr&gt; evaluates to non-zero.
Definition: debug.h:282
size_t bpp
Definition: tex.h:231
#define FOURCC(a, b, c, d)
convert 4 characters to u32 (at compile time) for easy comparison.
Definition: byte_order.h:69
u32 dwCaps3
Definition: tex_dds.cpp:362
u32 dwReserved2
Definition: tex_dds.cpp:364
void WritePixel(size_t pixel_idx, u8 *RESTRICT out) const
Definition: tex_dds.cpp:64
u32 dwCaps2
Definition: tex_dds.cpp:361
u32 dwCaps4
Definition: tex_dds.cpp:363
u32 dwPitchOrLinearSize
Definition: tex_dds.cpp:354
Definition: path.h:75
u32 c_selectors
Definition: tex_dds.cpp:215
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)
Definition: tex_dds.cpp:229
#define DDSD_DEPTH
Definition: tex_dds.cpp:341
u8 * tex_get_data(const Tex *t)
rationale: since Tex is a struct, its fields are accessible to callers.
Definition: tex.cpp:629
u8 dxt5_a_tbl[8]
Definition: tex_dds.cpp:209
static Status decode_pf(const DDS_PIXELFORMAT *pf, size_t &bpp, size_t &flags)
Definition: tex_dds.cpp:390
u64 a_bits
Definition: tex_dds.cpp:212
i64 Status
Error handling system.
Definition: status.h:171
#define T(string_literal)
Definition: secure_crt.cpp:70
T bits(T num, size_t lo_idx, size_t hi_idx)
extract the value of bits hi_idx:lo_idx within num
Definition: bits.h:97
u32 dwWidth
Definition: tex_dds.cpp:353
size_t dataSize
Definition: tex.h:219
#define DDSCAPS_TEXTURE
Definition: tex_dds.cpp:345
stores all data describing an image.
Definition: tex.h:210
static size_t dds_hdr_size(const u8 *file)
Definition: tex_dds.cpp:585
intptr_t ssize_t
Definition: wposix_types.h:82
#define DEBUG_WARN_ERR(status)
display the error dialog with text corresponding to the given error code.
Definition: debug.h:331
#define u16
Definition: types.h:40
static void mix_2_3(size_t dst[4], size_t c0[4], size_t c1[4])
Definition: tex_dds.cpp:102
we need a special value for DXT1a to avoid having to consider flags &amp; TEX_ALPHA to determine S3TC typ...
Definition: tex.h:156
S3tcBlock(size_t dxt, const u8 *RESTRICT block)
Definition: tex_dds.cpp:53
#define DDPF_ALPHAPIXELS
Definition: tex_dds.cpp:316
#define u64
Definition: types.h:42
static bool dds_is_ext(const OsPath &extension)
Definition: tex_dds.cpp:579
#define DDSCAPS_MIPMAP
Definition: tex_dds.cpp:344
const char * extension
Definition: mongoose.cpp:1736
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.
Definition: tex.cpp:132
#define TIMER_ADD_CLIENT(id)
&quot;allocate&quot; a new TimerClient that will keep track of the total time billed to it, along with a descri...
Definition: timer.h:308
static Status AllocateAligned(shared_ptr< T > &p, size_t size, size_t alignment=cacheLineSize)
Definition: shared_ptr.h:66
#define u32
Definition: types.h:41
size_t w
Definition: tex.h:229
u16 read_le16(const void *p)
read a little-endian number from memory into native byte order.
Definition: byte_order.cpp:66
size_t ceil_log2(T x)
ceil(log2(x))
Definition: bits.h:197
#define RESTRICT
#define TEX_CODEC_REGISTER(name)
build codec vtbl and register it.
Definition: tex_codec.h:137
#define DDSD_PIXELFORMAT
Definition: tex_dds.cpp:338
#define WARN_RETURN(status)
Definition: status.h:255
u32 dwDepth
Definition: tex_dds.cpp:356
static Status dds_decode(rpU8 data, size_t size, Tex *RESTRICT t)
Definition: tex_dds.cpp:591
const Status TEX_INVALID_SIZE
Definition: tex.h:122
u32 dwHeight
Definition: tex_dds.cpp:352
size_t tex_img_size(const Tex *t)
return total byte size of the image pixels.
Definition: tex.cpp:683
size_t dxt
Definition: tex_dds.cpp:217
#define DDPF_RGB
Definition: tex_dds.cpp:318
size_t flags
see TexFlags and &quot;Format Conversion&quot; in docs.
Definition: tex.h:234
u32 dwSize
Definition: tex_dds.cpp:350
static void mix_avg(size_t dst[4], size_t c0[4], size_t c1[4])
Definition: tex_dds.cpp:107
static bool is_valid_dxt(size_t dxt)
Definition: tex_dds.cpp:370
#define DDSD_PITCH
Definition: tex_dds.cpp:337
#define RETURN_STATUS_IF_ERR(expression)
Definition: status.h:276