Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
DirectXTexCompress.cpp
Go to the documentation of this file.
1 //-------------------------------------------------------------------------------------
2 // DirectXTexCompress.cpp
3 //
4 // DirectX Texture Library - Texture compression
5 //
6 // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
7 // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
8 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
9 // PARTICULAR PURPOSE.
10 //
11 // Copyright (c) Microsoft Corporation. All rights reserved.
12 //
13 // http://go.microsoft.com/fwlink/?LinkId=248926
14 //-------------------------------------------------------------------------------------
15 
16 #include "directxtexp.h"
17 
18 #ifdef _OPENMP
19 #include <omp.h>
20 #pragma warning(disable : 4616 6993)
21 #endif
22 
23 #include "bc.h"
24 
25 
26 namespace DirectX
27 {
28 
29 inline static DWORD _GetBCFlags( _In_ DWORD compress )
30 {
31  static_assert( TEX_COMPRESS_RGB_DITHER == BC_FLAGS_DITHER_RGB, "TEX_COMPRESS_* flags should match BC_FLAGS_*" );
32  static_assert( TEX_COMPRESS_A_DITHER == BC_FLAGS_DITHER_A, "TEX_COMPRESS_* flags should match BC_FLAGS_*" );
33  static_assert( TEX_COMPRESS_DITHER == (BC_FLAGS_DITHER_RGB | BC_FLAGS_DITHER_A), "TEX_COMPRESS_* flags should match BC_FLAGS_*" );
34  static_assert( TEX_COMPRESS_UNIFORM == BC_FLAGS_UNIFORM, "TEX_COMPRESS_* flags should match BC_FLAGS_*" );
36 }
37 
38 inline static DWORD _GetSRGBFlags( _In_ DWORD compress )
39 {
40  static_assert( TEX_COMPRESS_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
41  static_assert( TEX_COMPRESS_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
42  static_assert( TEX_COMPRESS_SRGB == TEX_FILTER_SRGB, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
43  return ( compress & TEX_COMPRESS_SRGB );
44 }
45 
46 inline static bool _DetermineEncoderSettings( _In_ DXGI_FORMAT format, _Out_ BC_ENCODE& pfEncode, _Out_ size_t& blocksize, _Out_ DWORD& cflags )
47 {
48  switch(format)
49  {
50  case DXGI_FORMAT_BC1_UNORM:
51  case DXGI_FORMAT_BC1_UNORM_SRGB: pfEncode = nullptr; blocksize = 8; cflags = 0; break;
52  case DXGI_FORMAT_BC2_UNORM:
53  case DXGI_FORMAT_BC2_UNORM_SRGB: pfEncode = D3DXEncodeBC2; blocksize = 16; cflags = 0; break;
54  case DXGI_FORMAT_BC3_UNORM:
55  case DXGI_FORMAT_BC3_UNORM_SRGB: pfEncode = D3DXEncodeBC3; blocksize = 16; cflags = 0; break;
56  case DXGI_FORMAT_BC4_UNORM: pfEncode = D3DXEncodeBC4U; blocksize = 8; cflags = TEX_FILTER_RGB_COPY_RED; break;
57  case DXGI_FORMAT_BC4_SNORM: pfEncode = D3DXEncodeBC4S; blocksize = 8; cflags = TEX_FILTER_RGB_COPY_RED; break;
58  case DXGI_FORMAT_BC5_UNORM: pfEncode = D3DXEncodeBC5U; blocksize = 16; cflags = TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN; break;
59  case DXGI_FORMAT_BC5_SNORM: pfEncode = D3DXEncodeBC5S; blocksize = 16; cflags = TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN; break;
60  case DXGI_FORMAT_BC6H_UF16: pfEncode = D3DXEncodeBC6HU; blocksize = 16; cflags = 0; break;
61  case DXGI_FORMAT_BC6H_SF16: pfEncode = D3DXEncodeBC6HS; blocksize = 16; cflags = 0; break;
62  case DXGI_FORMAT_BC7_UNORM:
63  case DXGI_FORMAT_BC7_UNORM_SRGB: pfEncode = D3DXEncodeBC7; blocksize = 16; cflags = 0; break;
64  default: pfEncode = nullptr; blocksize = 0; cflags = 0; return false;
65  }
66 
67  return true;
68 }
69 
70 
71 //-------------------------------------------------------------------------------------
72 static HRESULT _CompressBC( _In_ const Image& image, _In_ const Image& result, _In_ DWORD bcflags,
73  _In_ DWORD srgb, _In_ float alphaRef )
74 {
75  if ( !image.pixels || !result.pixels )
76  return E_POINTER;
77 
78  assert( image.width == result.width );
79  assert( image.height == result.height );
80 
81  const DXGI_FORMAT format = image.format;
82  size_t sbpp = BitsPerPixel( format );
83  if ( !sbpp )
84  return E_FAIL;
85 
86  if ( sbpp < 8 )
87  {
88  // We don't support compressing from monochrome (DXGI_FORMAT_R1_UNORM)
89  return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
90  }
91 
92  // Round to bytes
93  sbpp = ( sbpp + 7 ) / 8;
94 
95  uint8_t *pDest = result.pixels;
96 
97  // Determine BC format encoder
98  BC_ENCODE pfEncode;
99  size_t blocksize;
100  DWORD cflags;
101  if ( !_DetermineEncoderSettings( result.format, pfEncode, blocksize, cflags ) )
102  return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
103 
104  XMVECTOR temp[16];
105  const uint8_t *pSrc = image.pixels;
106  const size_t rowPitch = image.rowPitch;
107  for( size_t h=0; h < image.height; h += 4 )
108  {
109  const uint8_t *sptr = pSrc;
110  uint8_t* dptr = pDest;
111  size_t ph = std::min<size_t>( 4, image.height - h );
112  size_t w = 0;
113  for( size_t count = 0; count < rowPitch; count += sbpp*4, w += 4 )
114  {
115  size_t pw = std::min<size_t>( 4, image.width - w );
116  assert( pw > 0 && ph > 0 );
117 
118  if ( !_LoadScanline( &temp[0], pw, sptr, rowPitch, format ) )
119  return E_FAIL;
120 
121  if ( ph > 1 )
122  {
123  if ( !_LoadScanline( &temp[4], pw, sptr + rowPitch, rowPitch, format ) )
124  return E_FAIL;
125 
126  if ( ph > 2 )
127  {
128  if ( !_LoadScanline( &temp[8], pw, sptr + rowPitch*2, rowPitch, format ) )
129  return E_FAIL;
130 
131  if ( ph > 3 )
132  {
133  if ( !_LoadScanline( &temp[12], pw, sptr + rowPitch*3, rowPitch, format ) )
134  return E_FAIL;
135  }
136  }
137  }
138 
139  if ( pw != 4 || ph != 4 )
140  {
141  // Replicate pixels for partial block
142  static const size_t uSrc[] = { 0, 0, 0, 1 };
143 
144  if ( pw < 4 )
145  {
146  for( size_t t = 0; t < ph && t < 4; ++t )
147  {
148  for( size_t s = pw; s < 4; ++s )
149  {
150 #pragma prefast(suppress: 26000, "PREFAST false positive")
151  temp[ (t << 2) | s ] = temp[ (t << 2) | uSrc[s] ];
152  }
153  }
154  }
155 
156  if ( ph < 4 )
157  {
158  for( size_t t = ph; t < 4; ++t )
159  {
160  for( size_t s = 0; s < 4; ++s )
161  {
162 #pragma prefast(suppress: 26000, "PREFAST false positive")
163  temp[ (t << 2) | s ] = temp[ (uSrc[t] << 2) | s ];
164  }
165  }
166  }
167  }
168 
169  _ConvertScanline( temp, 16, result.format, format, cflags | srgb );
170 
171  if ( pfEncode )
172  pfEncode( dptr, temp, bcflags );
173  else
174  D3DXEncodeBC1( dptr, temp, alphaRef, bcflags );
175 
176  sptr += sbpp*4;
177  dptr += blocksize;
178  }
179 
180  pSrc += rowPitch*4;
181  pDest += result.rowPitch;
182  }
183 
184  return S_OK;
185 }
186 
187 
188 //-------------------------------------------------------------------------------------
189 #ifdef _OPENMP
190 static HRESULT _CompressBC_Parallel( _In_ const Image& image, _In_ const Image& result, _In_ DWORD bcflags,
191  _In_ DWORD srgb, _In_ float alphaRef )
192 {
193  if ( !image.pixels || !result.pixels )
194  return E_POINTER;
195 
196  assert( image.width == result.width );
197  assert( image.height == result.height );
198 
199  const DXGI_FORMAT format = image.format;
200  size_t sbpp = BitsPerPixel( format );
201  if ( !sbpp )
202  return E_FAIL;
203 
204  if ( sbpp < 8 )
205  {
206  // We don't support compressing from monochrome (DXGI_FORMAT_R1_UNORM)
207  return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
208  }
209 
210  // Round to bytes
211  sbpp = ( sbpp + 7 ) / 8;
212 
213  // Determine BC format encoder
214  BC_ENCODE pfEncode;
215  size_t blocksize;
216  DWORD cflags;
217  if ( !_DetermineEncoderSettings( result.format, pfEncode, blocksize, cflags ) )
218  return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
219 
220  // Refactored version of loop to support parallel independance
221  const size_t nBlocks = std::max<size_t>(1, (image.width + 3) / 4 ) * std::max<size_t>(1, (image.height + 3) / 4 );
222 
223  bool fail = false;
224 
225 #pragma omp parallel for
226  for( int nb=0; nb < static_cast<int>( nBlocks ); ++nb )
227  {
228  const size_t nbWidth = std::max<size_t>(1, (image.width + 3) / 4 );
229 
230  const size_t y = nb / nbWidth;
231  const size_t x = nb - (y*nbWidth);
232 
233  assert( x < image.width && y < image.height );
234 
235  size_t rowPitch = image.rowPitch;
236  const uint8_t *pSrc = image.pixels + (y*4*rowPitch) + (x*4*sbpp);
237 
238  uint8_t *pDest = result.pixels + (nb*blocksize);
239 
240  size_t ph = std::min<size_t>( 4, image.height - y );
241  size_t pw = std::min<size_t>( 4, image.width - x );
242  assert( pw > 0 && ph > 0 );
243 
244  XMVECTOR temp[16];
245  if ( !_LoadScanline( &temp[0], pw, pSrc, rowPitch, format ) )
246  fail = true;
247 
248  if ( ph > 1 )
249  {
250  if ( !_LoadScanline( &temp[4], pw, pSrc + rowPitch, rowPitch, format ) )
251  fail = true;
252 
253  if ( ph > 2 )
254  {
255  if ( !_LoadScanline( &temp[8], pw, pSrc + rowPitch*2, rowPitch, format ) )
256  fail = true;
257 
258  if ( ph > 3 )
259  {
260  if ( !_LoadScanline( &temp[12], pw, pSrc + rowPitch*3, rowPitch, format ) )
261  fail = true;
262  }
263  }
264  }
265 
266  if ( pw != 4 || ph != 4 )
267  {
268  // Replicate pixels for partial block
269  static const size_t uSrc[] = { 0, 0, 0, 1 };
270 
271  if ( pw < 4 )
272  {
273  for( size_t t = 0; t < ph && t < 4; ++t )
274  {
275  for( size_t s = pw; s < 4; ++s )
276  {
277  temp[ (t << 2) | s ] = temp[ (t << 2) | uSrc[s] ];
278  }
279  }
280  }
281 
282  if ( ph < 4 )
283  {
284  for( size_t t = ph; t < 4; ++t )
285  {
286  for( size_t s = 0; s < 4; ++s )
287  {
288  temp[ (t << 2) | s ] = temp[ (uSrc[t] << 2) | s ];
289  }
290  }
291  }
292  }
293 
294  _ConvertScanline( temp, 16, result.format, format, cflags | srgb );
295 
296  if ( pfEncode )
297  pfEncode( pDest, temp, bcflags );
298  else
299  D3DXEncodeBC1( pDest, temp, alphaRef, bcflags );
300  }
301 
302  return (fail) ? E_FAIL : S_OK;
303 }
304 
305 #endif // _OPENMP
306 
307 
308 //-------------------------------------------------------------------------------------
309 static DXGI_FORMAT _DefaultDecompress( _In_ DXGI_FORMAT format )
310 {
311  switch( format )
312  {
313  case DXGI_FORMAT_BC1_TYPELESS:
314  case DXGI_FORMAT_BC1_UNORM:
315  case DXGI_FORMAT_BC2_TYPELESS:
316  case DXGI_FORMAT_BC2_UNORM:
317  case DXGI_FORMAT_BC3_TYPELESS:
318  case DXGI_FORMAT_BC3_UNORM:
319  case DXGI_FORMAT_BC7_TYPELESS:
320  case DXGI_FORMAT_BC7_UNORM:
321  return DXGI_FORMAT_R8G8B8A8_UNORM;
322 
323  case DXGI_FORMAT_BC1_UNORM_SRGB:
324  case DXGI_FORMAT_BC2_UNORM_SRGB:
325  case DXGI_FORMAT_BC3_UNORM_SRGB:
326  case DXGI_FORMAT_BC7_UNORM_SRGB:
327  return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
328 
329  case DXGI_FORMAT_BC4_TYPELESS:
330  case DXGI_FORMAT_BC4_UNORM:
331  return DXGI_FORMAT_R8_UNORM;
332 
333  case DXGI_FORMAT_BC4_SNORM:
334  return DXGI_FORMAT_R8_SNORM;
335 
336  case DXGI_FORMAT_BC5_TYPELESS:
337  case DXGI_FORMAT_BC5_UNORM:
338  return DXGI_FORMAT_R8G8_UNORM;
339 
340  case DXGI_FORMAT_BC5_SNORM:
341  return DXGI_FORMAT_R8G8_SNORM;
342 
343  case DXGI_FORMAT_BC6H_TYPELESS:
344  case DXGI_FORMAT_BC6H_UF16:
345  case DXGI_FORMAT_BC6H_SF16:
346  // We could use DXGI_FORMAT_R32G32B32_FLOAT here since BC6H is always Alpha 1.0,
347  // but this format is more supported by viewers
348  return DXGI_FORMAT_R32G32B32A32_FLOAT;
349 
350  default:
351  return DXGI_FORMAT_UNKNOWN;
352  }
353 }
354 
355 
356 //-------------------------------------------------------------------------------------
357 static HRESULT _DecompressBC( _In_ const Image& cImage, _In_ const Image& result )
358 {
359  if ( !cImage.pixels || !result.pixels )
360  return E_POINTER;
361 
362  assert( cImage.width == result.width );
363  assert( cImage.height == result.height );
364 
365  const DXGI_FORMAT format = result.format;
366  size_t dbpp = BitsPerPixel( format );
367  if ( !dbpp )
368  return E_FAIL;
369 
370  if ( dbpp < 8 )
371  {
372  // We don't support decompressing to monochrome (DXGI_FORMAT_R1_UNORM)
373  return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
374  }
375 
376  // Round to bytes
377  dbpp = ( dbpp + 7 ) / 8;
378 
379  uint8_t *pDest = result.pixels;
380  if ( !pDest )
381  return E_POINTER;
382 
383  // Promote "typeless" BC formats
384  DXGI_FORMAT cformat;
385  switch( cImage.format )
386  {
387  case DXGI_FORMAT_BC1_TYPELESS: cformat = DXGI_FORMAT_BC1_UNORM; break;
388  case DXGI_FORMAT_BC2_TYPELESS: cformat = DXGI_FORMAT_BC2_UNORM; break;
389  case DXGI_FORMAT_BC3_TYPELESS: cformat = DXGI_FORMAT_BC3_UNORM; break;
390  case DXGI_FORMAT_BC4_TYPELESS: cformat = DXGI_FORMAT_BC4_UNORM; break;
391  case DXGI_FORMAT_BC5_TYPELESS: cformat = DXGI_FORMAT_BC5_UNORM; break;
392  case DXGI_FORMAT_BC6H_TYPELESS: cformat = DXGI_FORMAT_BC6H_UF16; break;
393  case DXGI_FORMAT_BC7_TYPELESS: cformat = DXGI_FORMAT_BC7_UNORM; break;
394  default: cformat = cImage.format; break;
395  }
396 
397  // Determine BC format decoder
398  BC_DECODE pfDecode;
399  size_t sbpp;
400  switch(cformat)
401  {
402  case DXGI_FORMAT_BC1_UNORM:
403  case DXGI_FORMAT_BC1_UNORM_SRGB: pfDecode = D3DXDecodeBC1; sbpp = 8; break;
404  case DXGI_FORMAT_BC2_UNORM:
405  case DXGI_FORMAT_BC2_UNORM_SRGB: pfDecode = D3DXDecodeBC2; sbpp = 16; break;
406  case DXGI_FORMAT_BC3_UNORM:
407  case DXGI_FORMAT_BC3_UNORM_SRGB: pfDecode = D3DXDecodeBC3; sbpp = 16; break;
408  case DXGI_FORMAT_BC4_UNORM: pfDecode = D3DXDecodeBC4U; sbpp = 8; break;
409  case DXGI_FORMAT_BC4_SNORM: pfDecode = D3DXDecodeBC4S; sbpp = 8; break;
410  case DXGI_FORMAT_BC5_UNORM: pfDecode = D3DXDecodeBC5U; sbpp = 16; break;
411  case DXGI_FORMAT_BC5_SNORM: pfDecode = D3DXDecodeBC5S; sbpp = 16; break;
412  case DXGI_FORMAT_BC6H_UF16: pfDecode = D3DXDecodeBC6HU; sbpp = 16; break;
413  case DXGI_FORMAT_BC6H_SF16: pfDecode = D3DXDecodeBC6HS; sbpp = 16; break;
414  case DXGI_FORMAT_BC7_UNORM:
415  case DXGI_FORMAT_BC7_UNORM_SRGB: pfDecode = D3DXDecodeBC7; sbpp = 16; break;
416  default:
417  return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
418  }
419 
420  XMVECTOR temp[16];
421  const uint8_t *pSrc = cImage.pixels;
422  const size_t rowPitch = result.rowPitch;
423  for( size_t h=0; h < cImage.height; h += 4 )
424  {
425  const uint8_t *sptr = pSrc;
426  uint8_t* dptr = pDest;
427  size_t ph = std::min<size_t>( 4, cImage.height - h );
428  size_t w = 0;
429  for( size_t count = 0; count < cImage.rowPitch; count += sbpp, w += 4 )
430  {
431  pfDecode( temp, sptr );
432  _ConvertScanline( temp, 16, format, cformat, 0 );
433 
434  size_t pw = std::min<size_t>( 4, cImage.width - w );
435  assert( pw > 0 && ph > 0 );
436 
437  if ( !_StoreScanline( dptr, rowPitch, format, &temp[0], pw ) )
438  return E_FAIL;
439 
440  if ( ph > 1 )
441  {
442  if ( !_StoreScanline( dptr + rowPitch, rowPitch, format, &temp[4], pw ) )
443  return E_FAIL;
444 
445  if ( ph > 2 )
446  {
447  if ( !_StoreScanline( dptr + rowPitch*2, rowPitch, format, &temp[8], pw ) )
448  return E_FAIL;
449 
450  if ( ph > 3 )
451  {
452  if ( !_StoreScanline( dptr + rowPitch*3, rowPitch, format, &temp[12], pw ) )
453  return E_FAIL;
454  }
455  }
456  }
457 
458  sptr += sbpp;
459  dptr += dbpp*4;
460  }
461 
462  pSrc += cImage.rowPitch;
463  pDest += rowPitch*4;
464  }
465 
466  return S_OK;
467 }
468 
469 
470 //-------------------------------------------------------------------------------------
471 bool _IsAlphaAllOpaqueBC( _In_ const Image& cImage )
472 {
473  if ( !cImage.pixels )
474  return false;
475 
476  // Promote "typeless" BC formats
477  DXGI_FORMAT cformat;
478  switch( cImage.format )
479  {
480  case DXGI_FORMAT_BC1_TYPELESS: cformat = DXGI_FORMAT_BC1_UNORM; break;
481  case DXGI_FORMAT_BC2_TYPELESS: cformat = DXGI_FORMAT_BC2_UNORM; break;
482  case DXGI_FORMAT_BC3_TYPELESS: cformat = DXGI_FORMAT_BC3_UNORM; break;
483  case DXGI_FORMAT_BC7_TYPELESS: cformat = DXGI_FORMAT_BC7_UNORM; break;
484  default: cformat = cImage.format; break;
485  }
486 
487  // Determine BC format decoder
488  BC_DECODE pfDecode;
489  size_t sbpp;
490  switch(cformat)
491  {
492  case DXGI_FORMAT_BC1_UNORM:
493  case DXGI_FORMAT_BC1_UNORM_SRGB: pfDecode = D3DXDecodeBC1; sbpp = 8; break;
494  case DXGI_FORMAT_BC2_UNORM:
495  case DXGI_FORMAT_BC2_UNORM_SRGB: pfDecode = D3DXDecodeBC2; sbpp = 16; break;
496  case DXGI_FORMAT_BC3_UNORM:
497  case DXGI_FORMAT_BC3_UNORM_SRGB: pfDecode = D3DXDecodeBC3; sbpp = 16; break;
498  case DXGI_FORMAT_BC7_UNORM:
499  case DXGI_FORMAT_BC7_UNORM_SRGB: pfDecode = D3DXDecodeBC7; sbpp = 16; break;
500  default:
501  // BC4, BC5, and BC6 don't have alpha channels
502  return false;
503  }
504 
505  // Scan blocks for non-opaque alpha
506  static const XMVECTORF32 threshold = { 0.99f, 0.99f, 0.99f, 0.99f };
507 
508  XMVECTOR temp[16];
509  const uint8_t *pPixels = cImage.pixels;
510  for( size_t h = 0; h < cImage.height; h += 4 )
511  {
512  const uint8_t *ptr = pPixels;
513  size_t ph = std::min<size_t>( 4, cImage.height - h );
514  size_t w = 0;
515  for( size_t count = 0; count < cImage.rowPitch; count += sbpp, w += 4 )
516  {
517  pfDecode( temp, ptr );
518 
519  size_t pw = std::min<size_t>( 4, cImage.width - w );
520  assert( pw > 0 && ph > 0 );
521 
522  if ( pw == 4 && ph == 4 )
523  {
524  // Full blocks
525  for( size_t j = 0; j < 16; ++j )
526  {
527  XMVECTOR alpha = XMVectorSplatW( temp[j] );
528  if ( XMVector4Less( alpha, threshold ) )
529  return false;
530  }
531  }
532  else
533  {
534  // Handle partial blocks
535  for( size_t y = 0; y < ph; ++y )
536  {
537  for( size_t x = 0; x < pw; ++x )
538  {
539  XMVECTOR alpha = XMVectorSplatW( temp[ y * 4 + x ] );
540  if ( XMVector4Less( alpha, threshold ) )
541  return false;
542  }
543  }
544  }
545 
546  ptr += sbpp;
547  }
548 
549  pPixels += cImage.rowPitch;
550  }
551 
552  return true;
553 }
554 
555 
556 //=====================================================================================
557 // Entry-points
558 //=====================================================================================
559 
560 //-------------------------------------------------------------------------------------
561 // Compression
562 //-------------------------------------------------------------------------------------
563 _Use_decl_annotations_
564 HRESULT Compress( const Image& srcImage, DXGI_FORMAT format, DWORD compress, float alphaRef, ScratchImage& image )
565 {
566  if ( IsCompressed(srcImage.format) || !IsCompressed(format) )
567  return E_INVALIDARG;
568 
569  if ( IsTypeless(format)
570  || IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format) )
571  return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
572 
573  // Create compressed image
574  HRESULT hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
575  if ( FAILED(hr) )
576  return hr;
577 
578  const Image *img = image.GetImage( 0, 0, 0 );
579  if ( !img )
580  {
581  image.Release();
582  return E_POINTER;
583  }
584 
585  // Compress single image
586  if (compress & TEX_COMPRESS_PARALLEL)
587  {
588 #ifndef _OPENMP
589  return E_NOTIMPL;
590 #else
591  hr = _CompressBC_Parallel( srcImage, *img, _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
592 #endif // _OPENMP
593  }
594  else
595  {
596  hr = _CompressBC( srcImage, *img, _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
597  }
598 
599  if ( FAILED(hr) )
600  image.Release();
601 
602  return hr;
603 }
604 
605 _Use_decl_annotations_
606 HRESULT Compress( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
607  DXGI_FORMAT format, DWORD compress, float alphaRef, ScratchImage& cImages )
608 {
609  if ( !srcImages || !nimages )
610  return E_INVALIDARG;
611 
612  if ( IsCompressed(metadata.format) || !IsCompressed(format) )
613  return E_INVALIDARG;
614 
615  if ( IsTypeless(format)
616  || IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format) )
617  return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
618 
619  cImages.Release();
620 
621  TexMetadata mdata2 = metadata;
622  mdata2.format = format;
623  HRESULT hr = cImages.Initialize( mdata2 );
624  if ( FAILED(hr) )
625  return hr;
626 
627  if ( nimages != cImages.GetImageCount() )
628  {
629  cImages.Release();
630  return E_FAIL;
631  }
632 
633  const Image* dest = cImages.GetImages();
634  if ( !dest )
635  {
636  cImages.Release();
637  return E_POINTER;
638  }
639 
640  for( size_t index=0; index < nimages; ++index )
641  {
642  assert( dest[ index ].format == format );
643 
644  const Image& src = srcImages[ index ];
645 
646  if ( src.width != dest[ index ].width || src.height != dest[ index ].height )
647  {
648  cImages.Release();
649  return E_FAIL;
650  }
651 
652  if ( (compress & TEX_COMPRESS_PARALLEL) )
653  {
654 #ifndef _OPENMP
655  return E_NOTIMPL;
656 #else
657  if ( compress & TEX_COMPRESS_PARALLEL )
658  {
659  hr = _CompressBC_Parallel( src, dest[ index ], _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
660  if ( FAILED(hr) )
661  {
662  cImages.Release();
663  return hr;
664  }
665  }
666 #endif // _OPENMP
667  }
668  else
669  {
670  hr = _CompressBC( src, dest[ index ], _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
671  if ( FAILED(hr) )
672  {
673  cImages.Release();
674  return hr;
675  }
676  }
677  }
678 
679  return S_OK;
680 }
681 
682 
683 //-------------------------------------------------------------------------------------
684 // Decompression
685 //-------------------------------------------------------------------------------------
686 _Use_decl_annotations_
687 HRESULT Decompress( const Image& cImage, DXGI_FORMAT format, ScratchImage& image )
688 {
689  if ( !IsCompressed(cImage.format) || IsCompressed(format) )
690  return E_INVALIDARG;
691 
692  if ( format == DXGI_FORMAT_UNKNOWN )
693  {
694  // Pick a default decompressed format based on BC input format
695  format = _DefaultDecompress( cImage.format );
696  if ( format == DXGI_FORMAT_UNKNOWN )
697  {
698  // Input is not a compressed format
699  return E_INVALIDARG;
700  }
701  }
702  else
703  {
704  if ( !IsValid(format) )
705  return E_INVALIDARG;
706 
707  if ( IsTypeless(format) || IsPlanar(format) || IsPalettized(format) )
708  return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
709  }
710 
711  // Create decompressed image
712  HRESULT hr = image.Initialize2D( format, cImage.width, cImage.height, 1, 1 );
713  if ( FAILED(hr) )
714  return hr;
715 
716  const Image *img = image.GetImage( 0, 0, 0 );
717  if ( !img )
718  {
719  image.Release();
720  return E_POINTER;
721  }
722 
723  // Decompress single image
724  hr = _DecompressBC( cImage, *img );
725  if ( FAILED(hr) )
726  image.Release();
727 
728  return hr;
729 }
730 
731 _Use_decl_annotations_
732 HRESULT Decompress( const Image* cImages, size_t nimages, const TexMetadata& metadata,
733  DXGI_FORMAT format, ScratchImage& images )
734 {
735  if ( !cImages || !nimages )
736  return E_INVALIDARG;
737 
738  if ( !IsCompressed(metadata.format) || IsCompressed(format) )
739  return E_INVALIDARG;
740 
741  if ( format == DXGI_FORMAT_UNKNOWN )
742  {
743  // Pick a default decompressed format based on BC input format
744  format = _DefaultDecompress( cImages[0].format );
745  if ( format == DXGI_FORMAT_UNKNOWN )
746  {
747  // Input is not a compressed format
748  return E_FAIL;
749  }
750  }
751  else
752  {
753  if ( !IsValid(format) )
754  return E_INVALIDARG;
755 
756  if ( IsTypeless(format) || IsPlanar(format) || IsPalettized(format) )
757  HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
758  }
759 
760  images.Release();
761 
762  TexMetadata mdata2 = metadata;
763  mdata2.format = format;
764  HRESULT hr = images.Initialize( mdata2 );
765  if ( FAILED(hr) )
766  return hr;
767 
768  if ( nimages != images.GetImageCount() )
769  {
770  images.Release();
771  return E_FAIL;
772  }
773 
774  const Image* dest = images.GetImages();
775  if ( !dest )
776  {
777  images.Release();
778  return E_POINTER;
779  }
780 
781  for( size_t index=0; index < nimages; ++index )
782  {
783  assert( dest[ index ].format == format );
784 
785  const Image& src = cImages[ index ];
786  if ( !IsCompressed( src.format ) )
787  {
788  images.Release();
789  return E_FAIL;
790  }
791 
792  if ( src.width != dest[ index ].width || src.height != dest[ index ].height )
793  {
794  images.Release();
795  return E_FAIL;
796  }
797 
798  hr = _DecompressBC( src, dest[ index ] );
799  if ( FAILED(hr) )
800  {
801  images.Release();
802  return hr;
803  }
804  }
805 
806  return S_OK;
807 }
808 
809 }; // namespace
_Use_decl_annotations_ void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
Definition: BC.cpp:939
static HRESULT _CompressBC(_In_ const Image &image, _In_ const Image &result, _In_ DWORD bcflags, _In_ DWORD srgb, _In_ float alphaRef)
const Image * GetImage(_In_ size_t mip, _In_ size_t item, _In_ size_t slice) const
void D3DXEncodeBC5U(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags)
void D3DXDecodeBC6HS(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC)
bool _IsAlphaAllOpaqueBC(_In_ const Image &cImage)
void(* BC_DECODE)(XMVECTOR *pColor, const uint8_t *pBC)
Definition: BC.h:865
static DWORD _GetBCFlags(_In_ DWORD compress)
bool IsPlanar(_In_ DXGI_FORMAT fmt)
DXGI_FORMAT format
Definition: DirectXTex.h:125
_Use_decl_annotations_ void D3DXDecodeBC3(XMVECTOR *pColor, const uint8_t *pBC)
Definition: BC.cpp:897
size_t _In_ DXGI_FORMAT size_t _In_ TEXP_LEGACY_FORMAT _In_ DWORD flags assert(pDestination &&outSize > 0)
void D3DXEncodeBC4U(_Out_writes_(8) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags)
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float threshold
Definition: DirectXTexP.h:183
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t y
Definition: DirectXTexP.h:191
HRESULT Initialize(_In_ const TexMetadata &mdata, _In_ DWORD flags=CP_FLAGS_NONE)
void D3DXEncodeBC4S(_Out_writes_(8) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags)
void D3DXDecodeBC4S(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(8) const uint8_t *pBC)
HRESULT Initialize2D(_In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _In_ size_t arraySize, _In_ size_t mipLevels, _In_ DWORD flags=CP_FLAGS_NONE)
void D3DXEncodeBC6HU(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags)
_Use_decl_annotations_ bool _LoadScanline(XMVECTOR *pDestination, size_t count, LPCVOID pSource, size_t size, DXGI_FORMAT format)
void D3DXDecodeBC4U(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(8) const uint8_t *pBC)
void D3DXDecodeBC6HU(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC)
static DXGI_FORMAT _DefaultDecompress(_In_ DXGI_FORMAT format)
bool IsCompressed(_In_ DXGI_FORMAT fmt)
size_t GetImageCount() const
Definition: DirectXTex.h:264
static DWORD _GetSRGBFlags(_In_ DWORD compress)
_In_ size_t _In_ const TexMetadata & metadata
Definition: DirectXTexP.h:116
_Use_decl_annotations_ void _ConvertScanline(XMVECTOR *pBuffer, size_t count, DXGI_FORMAT outFormat, DXGI_FORMAT inFormat, DWORD flags)
_In_ size_t count
Definition: DirectXTexP.h:174
void D3DXDecodeBC7(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC)
void D3DXEncodeBC6HS(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags)
bool IsValid(_In_ DXGI_FORMAT fmt)
void D3DXDecodeBC5U(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC)
bool IsPalettized(_In_ DXGI_FORMAT fmt)
function s(a)
HRESULT Decompress(_In_ const Image &cImage, _In_ DXGI_FORMAT format, _Out_ ScratchImage &image)
_Use_decl_annotations_ void D3DXEncodeBC1(uint8_t *pBC, const XMVECTOR *pColor, float alphaRef, DWORD flags)
Definition: BC.cpp:729
bool IsTypeless(_In_ DXGI_FORMAT fmt, _In_ bool partialTypeless=true)
char * dest
Definition: lz4.h:61
static bool _DetermineEncoderSettings(_In_ DXGI_FORMAT format, _Out_ BC_ENCODE &pfEncode, _Out_ size_t &blocksize, _Out_ DWORD &cflags)
static HRESULT _DecompressBC(_In_ const Image &cImage, _In_ const Image &result)
DXGI_FORMAT format
Definition: DirectXTex.h:227
_In_ size_t _In_ size_t _In_ DXGI_FORMAT format
Definition: DirectXTexP.h:175
void D3DXDecodeBC5S(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC)
void(* BC_ENCODE)(uint8_t *pDXT, const XMVECTOR *pColor, DWORD flags)
Definition: BC.h:866
_Use_decl_annotations_ void D3DXEncodeBC2(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
Definition: BC.cpp:820
void D3DXEncodeBC5S(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags)
const Image * GetImages() const
Definition: DirectXTex.h:263
size_t BitsPerPixel(_In_ DXGI_FORMAT fmt)
_Use_decl_annotations_ void D3DXDecodeBC1(XMVECTOR *pColor, const uint8_t *pBC)
Definition: BC.cpp:722
HRESULT Compress(_In_ const Image &srcImage, _In_ DXGI_FORMAT format, _In_ DWORD compress, _In_ float alphaRef, _Out_ ScratchImage &cImage)
void D3DXEncodeBC7(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags)
_Use_decl_annotations_ bool _StoreScanline(LPVOID pDestination, size_t size, DXGI_FORMAT format, const XMVECTOR *pSource, size_t count, float threshold)
_Use_decl_annotations_ void D3DXDecodeBC2(XMVECTOR *pColor, const uint8_t *pBC)
Definition: BC.cpp:794