DirectXTexImage.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. //-------------------------------------------------------------------------------------
  2. // DirectXTexImage.cpp
  3. //
  4. // DirectX Texture Library - Image container
  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. #include "directxtexp.h"
  16. namespace DirectX
  17. {
  18. extern bool _CalculateMipLevels( _In_ size_t width, _In_ size_t height, _Inout_ size_t& mipLevels );
  19. extern bool _CalculateMipLevels3D( _In_ size_t width, _In_ size_t height, _In_ size_t depth, _Inout_ size_t& mipLevels );
  20. extern bool _IsAlphaAllOpaqueBC( _In_ const Image& cImage );
  21. //-------------------------------------------------------------------------------------
  22. // Determines number of image array entries and pixel size
  23. //-------------------------------------------------------------------------------------
  24. _Use_decl_annotations_
  25. void _DetermineImageArray( const TexMetadata& metadata, DWORD cpFlags,
  26. size_t& nImages, size_t& pixelSize )
  27. {
  28. assert( metadata.width > 0 && metadata.height > 0 && metadata.depth > 0 );
  29. assert( metadata.arraySize > 0 );
  30. assert( metadata.mipLevels > 0 );
  31. size_t _pixelSize = 0;
  32. size_t _nimages = 0;
  33. switch( metadata.dimension )
  34. {
  35. case TEX_DIMENSION_TEXTURE1D:
  36. case TEX_DIMENSION_TEXTURE2D:
  37. for( size_t item = 0; item < metadata.arraySize; ++item )
  38. {
  39. size_t w = metadata.width;
  40. size_t h = metadata.height;
  41. for( size_t level=0; level < metadata.mipLevels; ++level )
  42. {
  43. size_t rowPitch, slicePitch;
  44. ComputePitch( metadata.format, w, h, rowPitch, slicePitch, cpFlags );
  45. _pixelSize += slicePitch;
  46. ++_nimages;
  47. if ( h > 1 )
  48. h >>= 1;
  49. if ( w > 1 )
  50. w >>= 1;
  51. }
  52. }
  53. break;
  54. case TEX_DIMENSION_TEXTURE3D:
  55. {
  56. size_t w = metadata.width;
  57. size_t h = metadata.height;
  58. size_t d = metadata.depth;
  59. for( size_t level=0; level < metadata.mipLevels; ++level )
  60. {
  61. size_t rowPitch, slicePitch;
  62. ComputePitch( metadata.format, w, h, rowPitch, slicePitch, cpFlags );
  63. for( size_t slice=0; slice < d; ++slice )
  64. {
  65. _pixelSize += slicePitch;
  66. ++_nimages;
  67. }
  68. if ( h > 1 )
  69. h >>= 1;
  70. if ( w > 1 )
  71. w >>= 1;
  72. if ( d > 1 )
  73. d >>= 1;
  74. }
  75. }
  76. break;
  77. default:
  78. assert( false );
  79. break;
  80. }
  81. nImages = _nimages;
  82. pixelSize = _pixelSize;
  83. }
  84. //-------------------------------------------------------------------------------------
  85. // Fills in the image array entries
  86. //-------------------------------------------------------------------------------------
  87. _Use_decl_annotations_
  88. bool _SetupImageArray( uint8_t *pMemory, size_t pixelSize,
  89. const TexMetadata& metadata, DWORD cpFlags,
  90. Image* images, size_t nImages )
  91. {
  92. assert( pMemory );
  93. assert( pixelSize > 0 );
  94. assert( nImages > 0 );
  95. if ( !images )
  96. return false;
  97. size_t index = 0;
  98. uint8_t* pixels = pMemory;
  99. const uint8_t* pEndBits = pMemory + pixelSize;
  100. switch( metadata.dimension )
  101. {
  102. case TEX_DIMENSION_TEXTURE1D:
  103. case TEX_DIMENSION_TEXTURE2D:
  104. if (metadata.arraySize == 0 || metadata.mipLevels == 0)
  105. {
  106. return false;
  107. }
  108. for( size_t item = 0; item < metadata.arraySize; ++item )
  109. {
  110. size_t w = metadata.width;
  111. size_t h = metadata.height;
  112. for( size_t level=0; level < metadata.mipLevels; ++level )
  113. {
  114. if ( index >= nImages )
  115. {
  116. return false;
  117. }
  118. size_t rowPitch, slicePitch;
  119. ComputePitch( metadata.format, w, h, rowPitch, slicePitch, cpFlags );
  120. images[index].width = w;
  121. images[index].height = h;
  122. images[index].format = metadata.format;
  123. images[index].rowPitch = rowPitch;
  124. images[index].slicePitch = slicePitch;
  125. images[index].pixels = pixels;
  126. ++index;
  127. pixels += slicePitch;
  128. if ( pixels > pEndBits )
  129. {
  130. return false;
  131. }
  132. if ( h > 1 )
  133. h >>= 1;
  134. if ( w > 1 )
  135. w >>= 1;
  136. }
  137. }
  138. return true;
  139. case TEX_DIMENSION_TEXTURE3D:
  140. {
  141. if (metadata.mipLevels == 0 || metadata.depth == 0)
  142. {
  143. return false;
  144. }
  145. size_t w = metadata.width;
  146. size_t h = metadata.height;
  147. size_t d = metadata.depth;
  148. for( size_t level=0; level < metadata.mipLevels; ++level )
  149. {
  150. size_t rowPitch, slicePitch;
  151. ComputePitch( metadata.format, w, h, rowPitch, slicePitch, cpFlags );
  152. for( size_t slice=0; slice < d; ++slice )
  153. {
  154. if ( index >= nImages )
  155. {
  156. return false;
  157. }
  158. // We use the same memory organization that Direct3D 11 needs for D3D11_SUBRESOURCE_DATA
  159. // with all slices of a given miplevel being continuous in memory
  160. images[index].width = w;
  161. images[index].height = h;
  162. images[index].format = metadata.format;
  163. images[index].rowPitch = rowPitch;
  164. images[index].slicePitch = slicePitch;
  165. images[index].pixels = pixels;
  166. ++index;
  167. pixels += slicePitch;
  168. if ( pixels > pEndBits )
  169. {
  170. return false;
  171. }
  172. }
  173. if ( h > 1 )
  174. h >>= 1;
  175. if ( w > 1 )
  176. w >>= 1;
  177. if ( d > 1 )
  178. d >>= 1;
  179. }
  180. }
  181. return true;
  182. default:
  183. return false;
  184. }
  185. }
  186. //=====================================================================================
  187. // ScratchImage - Bitmap image container
  188. //=====================================================================================
  189. ScratchImage& ScratchImage::operator= (ScratchImage&& moveFrom)
  190. {
  191. if ( this != &moveFrom )
  192. {
  193. Release();
  194. _nimages = moveFrom._nimages;
  195. _size = moveFrom._size;
  196. _metadata = moveFrom._metadata;
  197. _image = moveFrom._image;
  198. _memory = moveFrom._memory;
  199. moveFrom._nimages = 0;
  200. moveFrom._size = 0;
  201. moveFrom._image = nullptr;
  202. moveFrom._memory = nullptr;
  203. }
  204. return *this;
  205. }
  206. //-------------------------------------------------------------------------------------
  207. // Methods
  208. //-------------------------------------------------------------------------------------
  209. _Use_decl_annotations_
  210. HRESULT ScratchImage::Initialize( const TexMetadata& mdata, DWORD flags )
  211. {
  212. if ( !IsValid(mdata.format) )
  213. return E_INVALIDARG;
  214. if ( IsPalettized(mdata.format) )
  215. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  216. size_t mipLevels = mdata.mipLevels;
  217. switch( mdata.dimension )
  218. {
  219. case TEX_DIMENSION_TEXTURE1D:
  220. if ( !mdata.width || mdata.height != 1 || mdata.depth != 1 || !mdata.arraySize )
  221. return E_INVALIDARG;
  222. if ( IsVideo(mdata.format) )
  223. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  224. if ( !_CalculateMipLevels(mdata.width,1,mipLevels) )
  225. return E_INVALIDARG;
  226. break;
  227. case TEX_DIMENSION_TEXTURE2D:
  228. if ( !mdata.width || !mdata.height || mdata.depth != 1 || !mdata.arraySize )
  229. return E_INVALIDARG;
  230. if ( mdata.IsCubemap() )
  231. {
  232. if ( (mdata.arraySize % 6) != 0 )
  233. return E_INVALIDARG;
  234. if ( IsVideo(mdata.format) )
  235. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  236. }
  237. if ( !_CalculateMipLevels(mdata.width,mdata.height,mipLevels) )
  238. return E_INVALIDARG;
  239. break;
  240. case TEX_DIMENSION_TEXTURE3D:
  241. if ( !mdata.width || !mdata.height || !mdata.depth || mdata.arraySize != 1 )
  242. return E_INVALIDARG;
  243. if ( IsVideo(mdata.format) || IsPlanar(mdata.format) || IsDepthStencil(mdata.format) )
  244. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  245. if ( !_CalculateMipLevels3D(mdata.width,mdata.height,mdata.depth,mipLevels) )
  246. return E_INVALIDARG;
  247. break;
  248. default:
  249. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  250. }
  251. Release();
  252. _metadata.width = mdata.width;
  253. _metadata.height = mdata.height;
  254. _metadata.depth = mdata.depth;
  255. _metadata.arraySize = mdata.arraySize;
  256. _metadata.mipLevels = mipLevels;
  257. _metadata.miscFlags = mdata.miscFlags;
  258. _metadata.miscFlags2 = mdata.miscFlags2;
  259. _metadata.format = mdata.format;
  260. _metadata.dimension = mdata.dimension;
  261. size_t pixelSize, nimages;
  262. _DetermineImageArray( _metadata, flags, nimages, pixelSize );
  263. _image = new (std::nothrow) Image[ nimages ];
  264. if ( !_image )
  265. return E_OUTOFMEMORY;
  266. _nimages = nimages;
  267. memset( _image, 0, sizeof(Image) * nimages );
  268. _memory = reinterpret_cast<uint8_t*>( _aligned_malloc( pixelSize, 16 ) );
  269. if ( !_memory )
  270. {
  271. Release();
  272. return E_OUTOFMEMORY;
  273. }
  274. _size = pixelSize;
  275. if ( !_SetupImageArray( _memory, pixelSize, _metadata, flags, _image, nimages ) )
  276. {
  277. Release();
  278. return E_FAIL;
  279. }
  280. return S_OK;
  281. }
  282. _Use_decl_annotations_
  283. HRESULT ScratchImage::Initialize1D( DXGI_FORMAT fmt, size_t length, size_t arraySize, size_t mipLevels, DWORD flags )
  284. {
  285. if ( !length || !arraySize )
  286. return E_INVALIDARG;
  287. if ( IsVideo(fmt) )
  288. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  289. // 1D is a special case of the 2D case
  290. HRESULT hr = Initialize2D( fmt, length, 1, arraySize, mipLevels, flags );
  291. if ( FAILED(hr) )
  292. return hr;
  293. _metadata.dimension = TEX_DIMENSION_TEXTURE1D;
  294. return S_OK;
  295. }
  296. _Use_decl_annotations_
  297. HRESULT ScratchImage::Initialize2D( DXGI_FORMAT fmt, size_t width, size_t height, size_t arraySize, size_t mipLevels, DWORD flags )
  298. {
  299. if ( !IsValid(fmt) || !width || !height || !arraySize )
  300. return E_INVALIDARG;
  301. if ( IsPalettized(fmt) )
  302. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  303. if ( !_CalculateMipLevels(width,height,mipLevels) )
  304. return E_INVALIDARG;
  305. Release();
  306. _metadata.width = width;
  307. _metadata.height = height;
  308. _metadata.depth = 1;
  309. _metadata.arraySize = arraySize;
  310. _metadata.mipLevels = mipLevels;
  311. _metadata.miscFlags = 0;
  312. _metadata.miscFlags2 = 0;
  313. _metadata.format = fmt;
  314. _metadata.dimension = TEX_DIMENSION_TEXTURE2D;
  315. size_t pixelSize, nimages;
  316. _DetermineImageArray( _metadata, flags, nimages, pixelSize );
  317. _image = new (std::nothrow) Image[ nimages ];
  318. if ( !_image )
  319. return E_OUTOFMEMORY;
  320. _nimages = nimages;
  321. memset( _image, 0, sizeof(Image) * nimages );
  322. _memory = reinterpret_cast<uint8_t*>( _aligned_malloc( pixelSize, 16 ) );
  323. if ( !_memory )
  324. {
  325. Release();
  326. return E_OUTOFMEMORY;
  327. }
  328. _size = pixelSize;
  329. if ( !_SetupImageArray( _memory, pixelSize, _metadata, flags, _image, nimages ) )
  330. {
  331. Release();
  332. return E_FAIL;
  333. }
  334. return S_OK;
  335. }
  336. _Use_decl_annotations_
  337. HRESULT ScratchImage::Initialize3D( DXGI_FORMAT fmt, size_t width, size_t height, size_t depth, size_t mipLevels, DWORD flags )
  338. {
  339. if ( !IsValid(fmt) || !width || !height || !depth )
  340. return E_INVALIDARG;
  341. if ( IsVideo(fmt) || IsPlanar(fmt) || IsDepthStencil(fmt) )
  342. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  343. if ( !_CalculateMipLevels3D(width,height,depth,mipLevels) )
  344. return E_INVALIDARG;
  345. Release();
  346. _metadata.width = width;
  347. _metadata.height = height;
  348. _metadata.depth = depth;
  349. _metadata.arraySize = 1; // Direct3D 10.x/11 does not support arrays of 3D textures
  350. _metadata.mipLevels = mipLevels;
  351. _metadata.miscFlags = 0;
  352. _metadata.miscFlags2 = 0;
  353. _metadata.format = fmt;
  354. _metadata.dimension = TEX_DIMENSION_TEXTURE3D;
  355. size_t pixelSize, nimages;
  356. _DetermineImageArray( _metadata, flags, nimages, pixelSize );
  357. _image = new (std::nothrow) Image[ nimages ];
  358. if ( !_image )
  359. {
  360. Release();
  361. return E_OUTOFMEMORY;
  362. }
  363. _nimages = nimages;
  364. memset( _image, 0, sizeof(Image) * nimages );
  365. _memory = reinterpret_cast<uint8_t*>( _aligned_malloc( pixelSize, 16 ) );
  366. if ( !_memory )
  367. {
  368. Release();
  369. return E_OUTOFMEMORY;
  370. }
  371. _size = pixelSize;
  372. if ( !_SetupImageArray( _memory, pixelSize, _metadata, flags, _image, nimages ) )
  373. {
  374. Release();
  375. return E_FAIL;
  376. }
  377. return S_OK;
  378. }
  379. _Use_decl_annotations_
  380. HRESULT ScratchImage::InitializeCube( DXGI_FORMAT fmt, size_t width, size_t height, size_t nCubes, size_t mipLevels, DWORD flags )
  381. {
  382. if ( !width || !height || !nCubes )
  383. return E_INVALIDARG;
  384. if ( IsVideo(fmt) )
  385. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  386. // A DirectX11 cubemap is just a 2D texture array that is a multiple of 6 for each cube
  387. HRESULT hr = Initialize2D( fmt, width, height, nCubes * 6, mipLevels, flags );
  388. if ( FAILED(hr) )
  389. return hr;
  390. _metadata.miscFlags |= TEX_MISC_TEXTURECUBE;
  391. return S_OK;
  392. }
  393. _Use_decl_annotations_
  394. HRESULT ScratchImage::InitializeFromImage( const Image& srcImage, bool allow1D, DWORD flags )
  395. {
  396. HRESULT hr = ( srcImage.height > 1 || !allow1D )
  397. ? Initialize2D( srcImage.format, srcImage.width, srcImage.height, 1, 1, flags )
  398. : Initialize1D( srcImage.format, srcImage.width, 1, 1, flags );
  399. if ( FAILED(hr) )
  400. return hr;
  401. size_t rowCount = ComputeScanlines( srcImage.format, srcImage.height );
  402. if ( !rowCount )
  403. return E_UNEXPECTED;
  404. const uint8_t* sptr = reinterpret_cast<const uint8_t*>( srcImage.pixels );
  405. if ( !sptr )
  406. return E_POINTER;
  407. auto dptr = reinterpret_cast<uint8_t*>( _image[0].pixels );
  408. if ( !dptr )
  409. return E_POINTER;
  410. size_t spitch = srcImage.rowPitch;
  411. size_t dpitch = _image[0].rowPitch;
  412. size_t size = std::min<size_t>( dpitch, spitch );
  413. for( size_t y = 0; y < rowCount; ++y )
  414. {
  415. memcpy_s( dptr, dpitch, sptr, size );
  416. sptr += spitch;
  417. dptr += dpitch;
  418. }
  419. return S_OK;
  420. }
  421. _Use_decl_annotations_
  422. HRESULT ScratchImage::InitializeArrayFromImages( const Image* images, size_t nImages, bool allow1D, DWORD flags )
  423. {
  424. if ( !images || !nImages )
  425. return E_INVALIDARG;
  426. DXGI_FORMAT format = images[0].format;
  427. size_t width = images[0].width;
  428. size_t height = images[0].height;
  429. for( size_t index=0; index < nImages; ++index )
  430. {
  431. if ( !images[index].pixels )
  432. return E_POINTER;
  433. if ( images[index].format != format || images[index].width != width || images[index].height != height )
  434. {
  435. // All images must be the same format, width, and height
  436. return E_FAIL;
  437. }
  438. }
  439. HRESULT hr = ( height > 1 || !allow1D )
  440. ? Initialize2D( format, width, height, nImages, 1, flags )
  441. : Initialize1D( format, width, nImages, 1, flags );
  442. if ( FAILED(hr) )
  443. return hr;
  444. size_t rowCount = ComputeScanlines( format, height );
  445. if ( !rowCount )
  446. return E_UNEXPECTED;
  447. for( size_t index=0; index < nImages; ++index )
  448. {
  449. auto sptr = reinterpret_cast<const uint8_t*>( images[index].pixels );
  450. if ( !sptr )
  451. return E_POINTER;
  452. assert( index < _nimages );
  453. auto dptr = reinterpret_cast<uint8_t*>( _image[index].pixels );
  454. if ( !dptr )
  455. return E_POINTER;
  456. size_t spitch = images[index].rowPitch;
  457. size_t dpitch = _image[index].rowPitch;
  458. size_t size = std::min<size_t>( dpitch, spitch );
  459. for( size_t y = 0; y < rowCount; ++y )
  460. {
  461. memcpy_s( dptr, dpitch, sptr, size );
  462. sptr += spitch;
  463. dptr += dpitch;
  464. }
  465. }
  466. return S_OK;
  467. }
  468. _Use_decl_annotations_
  469. HRESULT ScratchImage::InitializeCubeFromImages( const Image* images, size_t nImages, DWORD flags )
  470. {
  471. if ( !images || !nImages )
  472. return E_INVALIDARG;
  473. // A DirectX11 cubemap is just a 2D texture array that is a multiple of 6 for each cube
  474. if ( ( nImages % 6 ) != 0 )
  475. return E_INVALIDARG;
  476. if ( IsVideo(images[0].format) || IsPalettized(images[0].format) )
  477. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  478. HRESULT hr = InitializeArrayFromImages( images, nImages, false, flags );
  479. if ( FAILED(hr) )
  480. return hr;
  481. _metadata.miscFlags |= TEX_MISC_TEXTURECUBE;
  482. return S_OK;
  483. }
  484. _Use_decl_annotations_
  485. HRESULT ScratchImage::Initialize3DFromImages( const Image* images, size_t depth, DWORD flags )
  486. {
  487. if ( !images || !depth )
  488. return E_INVALIDARG;
  489. DXGI_FORMAT format = images[0].format;
  490. size_t width = images[0].width;
  491. size_t height = images[0].height;
  492. for( size_t slice=0; slice < depth; ++slice )
  493. {
  494. if ( !images[slice].pixels )
  495. return E_POINTER;
  496. if ( images[slice].format != format || images[slice].width != width || images[slice].height != height )
  497. {
  498. // All images must be the same format, width, and height
  499. return E_FAIL;
  500. }
  501. }
  502. HRESULT hr = Initialize3D( format, width, height, depth, 1, flags );
  503. if ( FAILED(hr) )
  504. return hr;
  505. size_t rowCount = ComputeScanlines( format, height );
  506. if ( !rowCount )
  507. return E_UNEXPECTED;
  508. for( size_t slice=0; slice < depth; ++slice )
  509. {
  510. auto sptr = reinterpret_cast<const uint8_t*>( images[slice].pixels );
  511. if ( !sptr )
  512. return E_POINTER;
  513. assert( slice < _nimages );
  514. auto dptr = reinterpret_cast<uint8_t*>( _image[slice].pixels );
  515. if ( !dptr )
  516. return E_POINTER;
  517. size_t spitch = images[slice].rowPitch;
  518. size_t dpitch = _image[slice].rowPitch;
  519. size_t size = std::min<size_t>( dpitch, spitch );
  520. for( size_t y = 0; y < rowCount; ++y )
  521. {
  522. memcpy_s( dptr, dpitch, sptr, size );
  523. sptr += spitch;
  524. dptr += dpitch;
  525. }
  526. }
  527. return S_OK;
  528. }
  529. void ScratchImage::Release()
  530. {
  531. _nimages = 0;
  532. _size = 0;
  533. if ( _image )
  534. {
  535. delete [] _image;
  536. _image = 0;
  537. }
  538. if ( _memory )
  539. {
  540. _aligned_free( _memory );
  541. _memory = 0;
  542. }
  543. memset(&_metadata, 0, sizeof(_metadata));
  544. }
  545. _Use_decl_annotations_
  546. bool ScratchImage::OverrideFormat( DXGI_FORMAT f )
  547. {
  548. if ( !_image )
  549. return false;
  550. if ( !IsValid( f ) || IsPlanar( f ) || IsPalettized( f ) )
  551. return false;
  552. if ( ( BitsPerPixel( f ) != BitsPerPixel( _metadata.format ) )
  553. || ( IsCompressed( f ) != IsCompressed( _metadata.format ) )
  554. || ( IsPacked( f ) != IsPacked( _metadata.format ) )
  555. || ( IsVideo( f ) != IsVideo( _metadata.format ) ) )
  556. {
  557. // Can't change the effective pitch of the format this way
  558. return false;
  559. }
  560. for( size_t index = 0; index < _nimages; ++index )
  561. {
  562. _image[ index ].format = f;
  563. }
  564. _metadata.format = f;
  565. return true;
  566. }
  567. _Use_decl_annotations_
  568. const Image* ScratchImage::GetImage(size_t mip, size_t item, size_t slice) const
  569. {
  570. if ( mip >= _metadata.mipLevels )
  571. return nullptr;
  572. size_t index = 0;
  573. switch( _metadata.dimension )
  574. {
  575. case TEX_DIMENSION_TEXTURE1D:
  576. case TEX_DIMENSION_TEXTURE2D:
  577. if ( slice > 0 )
  578. return nullptr;
  579. if ( item >= _metadata.arraySize )
  580. return nullptr;
  581. index = item*( _metadata.mipLevels ) + mip;
  582. break;
  583. case TEX_DIMENSION_TEXTURE3D:
  584. if ( item > 0 )
  585. {
  586. // No support for arrays of volumes
  587. return nullptr;
  588. }
  589. else
  590. {
  591. size_t d = _metadata.depth;
  592. for( size_t level = 0; level < mip; ++level )
  593. {
  594. index += d;
  595. if ( d > 1 )
  596. d >>= 1;
  597. }
  598. if ( slice >= d )
  599. return nullptr;
  600. index += slice;
  601. }
  602. break;
  603. default:
  604. return nullptr;
  605. }
  606. return &_image[index];
  607. }
  608. bool ScratchImage::IsAlphaAllOpaque() const
  609. {
  610. if ( !_image )
  611. return false;
  612. if ( !HasAlpha( _metadata.format ) )
  613. return true;
  614. if ( IsCompressed( _metadata.format ) )
  615. {
  616. for( size_t index = 0; index < _nimages; ++index )
  617. {
  618. if ( !_IsAlphaAllOpaqueBC( _image[ index ] ) )
  619. return false;
  620. }
  621. }
  622. else
  623. {
  624. ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*_metadata.width), 16 ) ) );
  625. if ( !scanline )
  626. return false;
  627. static const XMVECTORF32 threshold = { 0.99f, 0.99f, 0.99f, 0.99f };
  628. for( size_t index = 0; index < _nimages; ++index )
  629. {
  630. #pragma warning( suppress : 6011 )
  631. const Image& img = _image[ index ];
  632. const uint8_t *pPixels = img.pixels;
  633. assert( pPixels );
  634. for( size_t h = 0; h < img.height; ++h )
  635. {
  636. if ( !_LoadScanline( scanline.get(), img.width, pPixels, img.rowPitch, img.format ) )
  637. return false;
  638. XMVECTOR* ptr = scanline.get();
  639. for( size_t w = 0; w < img.width; ++w )
  640. {
  641. XMVECTOR alpha = XMVectorSplatW( *ptr );
  642. if ( XMVector4Less( alpha, threshold ) )
  643. return false;
  644. ++ptr;
  645. }
  646. pPixels += img.rowPitch;
  647. }
  648. }
  649. }
  650. return true;
  651. }
  652. }; // namespace