Advertisement
Guest User

DDSTextureLoader.cpp

a guest
Sep 17th, 2017
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 59.73 KB | None | 0 0
  1. #include "DDSTextureLoader.h"
  2.  
  3. #if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) )
  4. #pragma comment(lib,"dxguid.lib")
  5. #endif
  6.  
  7. using namespace DirectX;
  8.  
  9. //--------------------------------------------------------------------------------------
  10. // Macros
  11. //--------------------------------------------------------------------------------------
  12. #ifndef MAKEFOURCC
  13. #define MAKEFOURCC(ch0, ch1, ch2, ch3) \
  14. ((uint32_t)(uint8_t)(ch0) | ((uint32_t)(uint8_t)(ch1) << 8) | \
  15. ((uint32_t)(uint8_t)(ch2) << 16) | ((uint32_t)(uint8_t)(ch3) << 24))
  16. #endif /* defined(MAKEFOURCC) */
  17.  
  18. //--------------------------------------------------------------------------------------
  19. // DDS file structure definitions
  20. //
  21. // See DDS.h in the 'Texconv' sample and the 'DirectXTex' library
  22. //--------------------------------------------------------------------------------------
  23. #pragma pack(push,1)
  24.  
  25. const uint32_t DDS_MAGIC = 0x20534444; // "DDS "
  26.  
  27. struct DDS_PIXELFORMAT
  28. {
  29. uint32_t size;
  30. uint32_t flags;
  31. uint32_t fourCC;
  32. uint32_t RGBBitCount;
  33. uint32_t RBitMask;
  34. uint32_t GBitMask;
  35. uint32_t BBitMask;
  36. uint32_t ABitMask;
  37. };
  38.  
  39. #define DDS_FOURCC 0x00000004 // DDPF_FOURCC
  40. #define DDS_RGB 0x00000040 // DDPF_RGB
  41. #define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE
  42. #define DDS_ALPHA 0x00000002 // DDPF_ALPHA
  43.  
  44. #define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH
  45.  
  46. #define DDS_HEIGHT 0x00000002 // DDSD_HEIGHT
  47. #define DDS_WIDTH 0x00000004 // DDSD_WIDTH
  48.  
  49. #define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX
  50. #define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX
  51. #define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY
  52. #define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY
  53. #define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ
  54. #define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ
  55.  
  56. #define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\
  57. DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY | \
  58. DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ)
  59.  
  60. #define DDS_CUBEMAP 0x00000200 // DDSCAPS2_CUBEMAP
  61.  
  62. enum DDS_MISC_FLAGS2
  63. {
  64. DDS_MISC_FLAGS2_ALPHA_MODE_MASK = 0x7L,
  65. };
  66.  
  67. struct DDS_HEADER
  68. {
  69. uint32_t size;
  70. uint32_t flags;
  71. uint32_t height;
  72. uint32_t width;
  73. uint32_t pitchOrLinearSize;
  74. uint32_t depth; // only if DDS_HEADER_FLAGS_VOLUME is set in flags
  75. uint32_t mipMapCount;
  76. uint32_t reserved1[11];
  77. DDS_PIXELFORMAT ddspf;
  78. uint32_t caps;
  79. uint32_t caps2;
  80. uint32_t caps3;
  81. uint32_t caps4;
  82. uint32_t reserved2;
  83. };
  84.  
  85. struct DDS_HEADER_DXT10
  86. {
  87. DXGI_FORMAT dxgiFormat;
  88. uint32_t resourceDimension;
  89. uint32_t miscFlag; // see D3D11_RESOURCE_MISC_FLAG
  90. uint32_t arraySize;
  91. uint32_t miscFlags2;
  92. };
  93.  
  94. #pragma pack(pop)
  95.  
  96. //--------------------------------------------------------------------------------------
  97. namespace
  98. {
  99. struct handle_closer
  100. {
  101. void operator()(HANDLE h)
  102. {
  103. if (h)
  104. CloseHandle( h );
  105. }
  106. };
  107.  
  108. typedef
  109. public
  110. std::unique_ptr<void, handle_closer> ScopedHandle;
  111.  
  112. inline HANDLE safe_handle(HANDLE h)
  113. {
  114. return (h == INVALID_HANDLE_VALUE) ? 0 : h;
  115. }
  116.  
  117. template<UINT TNameLength>
  118. inline void SetDebugObjectName(_In_ ID3D11DeviceChild *resource, _In_ const char (&name)[TNameLength])
  119. {
  120. #if defined(_DEBUG) || defined(PROFILE)
  121. resource->SetPrivateData( WKPDID_D3DDebugObjectName, TNameLength - 1, name );
  122. #else
  123. UNREFERENCED_PARAMETER(resource);
  124. UNREFERENCED_PARAMETER(name);
  125. #endif
  126. }
  127. };
  128.  
  129. //--------------------------------------------------------------------------------------
  130. static HRESULT LoadTextureDataFromFile(_In_z_ const wchar_t *fileName,
  131. std::unique_ptr<uint8_t[]> &ddsData,
  132. DDS_HEADER **header,
  133. uint8_t **bitData,
  134. size_t *bitSize
  135. )
  136. {
  137. if (!header || !bitData || !bitSize)
  138. {
  139. return E_POINTER;
  140. }
  141.  
  142. // open the file
  143. #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
  144. ScopedHandle hFile( safe_handle( CreateFile2( fileName,
  145. GENERIC_READ,
  146. FILE_SHARE_READ,
  147. OPEN_EXISTING,
  148. nullptr ) ) );
  149. #else
  150. ScopedHandle hFile(safe_handle(CreateFileW(fileName,
  151. GENERIC_READ,
  152. FILE_SHARE_READ,
  153. nullptr,
  154. OPEN_EXISTING,
  155. FILE_ATTRIBUTE_NORMAL,
  156. nullptr)));
  157. #endif
  158.  
  159. if (!hFile)
  160. {
  161. return HRESULT_FROM_WIN32( GetLastError( ) );
  162. }
  163.  
  164. // Get the file size
  165. LARGE_INTEGER FileSize = { 0 };
  166.  
  167. #if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
  168. FILE_STANDARD_INFO fileInfo;
  169. if (!GetFileInformationByHandleEx( hFile.get( ), FileStandardInfo, &fileInfo, sizeof(fileInfo) ))
  170. {
  171. return HRESULT_FROM_WIN32( GetLastError( ) );
  172. }
  173. FileSize = fileInfo.EndOfFile;
  174. #else
  175. GetFileSizeEx(hFile.get(), &FileSize);
  176. #endif
  177.  
  178. // File is too big for 32-bit allocation, so reject read
  179. if (FileSize.HighPart > 0)
  180. {
  181. return E_FAIL;
  182. }
  183.  
  184. // Need at least enough data to fill the header and magic number to be a valid DDS
  185. if (FileSize.LowPart < (sizeof(DDS_HEADER) + sizeof(uint32_t)))
  186. {
  187. return E_FAIL;
  188. }
  189.  
  190. // create enough space for the file data
  191. ddsData.reset( new( std::nothrow ) uint8_t[FileSize.LowPart] );
  192. if (!ddsData)
  193. {
  194. return E_OUTOFMEMORY;
  195. }
  196.  
  197. // read the data in
  198. DWORD BytesRead = 0;
  199. if (!ReadFile( hFile.get( ),
  200. ddsData.get( ),
  201. FileSize.LowPart,
  202. &BytesRead,
  203. nullptr
  204. ))
  205. {
  206. return HRESULT_FROM_WIN32( GetLastError( ) );
  207. }
  208.  
  209. if (BytesRead < FileSize.LowPart)
  210. {
  211. return E_FAIL;
  212. }
  213.  
  214. // DDS files always start with the same magic number ("DDS ")
  215. uint32_t dwMagicNumber = *( const uint32_t* )(ddsData.get( ));
  216. if (dwMagicNumber != DDS_MAGIC)
  217. {
  218. return E_FAIL;
  219. }
  220.  
  221. auto hdr = reinterpret_cast<DDS_HEADER*>( ddsData.get( ) + sizeof(uint32_t) );
  222.  
  223. // Verify header to validate DDS file
  224. if (hdr->size != sizeof(DDS_HEADER) ||
  225. hdr->ddspf.size != sizeof(DDS_PIXELFORMAT))
  226. {
  227. return E_FAIL;
  228. }
  229.  
  230. // Check for DX10 extension
  231. bool bDXT10Header = false;
  232. if ((hdr->ddspf.flags & DDS_FOURCC) &&
  233. (MAKEFOURCC('D', 'X', '1', '0') == hdr->ddspf.fourCC))
  234. {
  235. // Must be long enough for both headers and magic value
  236. if (FileSize.LowPart < (sizeof(DDS_HEADER) + sizeof(uint32_t) + sizeof(DDS_HEADER_DXT10)))
  237. {
  238. return E_FAIL;
  239. }
  240.  
  241. bDXT10Header = true;
  242. }
  243.  
  244. // setup the pointers in the process request
  245. *header = hdr;
  246. ptrdiff_t offset = sizeof(uint32_t) + sizeof(DDS_HEADER)
  247. + (bDXT10Header ? sizeof(DDS_HEADER_DXT10) : 0);
  248. *bitData = ddsData.get( ) + offset;
  249. *bitSize = FileSize.LowPart - offset;
  250.  
  251. return S_OK;
  252. }
  253.  
  254.  
  255. //--------------------------------------------------------------------------------------
  256. // Return the BPP for a particular format
  257. //--------------------------------------------------------------------------------------
  258. static size_t BitsPerPixel(_In_ DXGI_FORMAT fmt)
  259. {
  260. switch (fmt)
  261. {
  262. case DXGI_FORMAT_R32G32B32A32_TYPELESS:
  263. case DXGI_FORMAT_R32G32B32A32_FLOAT:
  264. case DXGI_FORMAT_R32G32B32A32_UINT:
  265. case DXGI_FORMAT_R32G32B32A32_SINT:
  266. return 128;
  267.  
  268. case DXGI_FORMAT_R32G32B32_TYPELESS:
  269. case DXGI_FORMAT_R32G32B32_FLOAT:
  270. case DXGI_FORMAT_R32G32B32_UINT:
  271. case DXGI_FORMAT_R32G32B32_SINT:
  272. return 96;
  273.  
  274. case DXGI_FORMAT_R16G16B16A16_TYPELESS:
  275. case DXGI_FORMAT_R16G16B16A16_FLOAT:
  276. case DXGI_FORMAT_R16G16B16A16_UNORM:
  277. case DXGI_FORMAT_R16G16B16A16_UINT:
  278. case DXGI_FORMAT_R16G16B16A16_SNORM:
  279. case DXGI_FORMAT_R16G16B16A16_SINT:
  280. case DXGI_FORMAT_R32G32_TYPELESS:
  281. case DXGI_FORMAT_R32G32_FLOAT:
  282. case DXGI_FORMAT_R32G32_UINT:
  283. case DXGI_FORMAT_R32G32_SINT:
  284. case DXGI_FORMAT_R32G8X24_TYPELESS:
  285. case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
  286. case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
  287. case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
  288. case DXGI_FORMAT_Y416:
  289. case DXGI_FORMAT_Y210:
  290. case DXGI_FORMAT_Y216:
  291. return 64;
  292.  
  293. case DXGI_FORMAT_R10G10B10A2_TYPELESS:
  294. case DXGI_FORMAT_R10G10B10A2_UNORM:
  295. case DXGI_FORMAT_R10G10B10A2_UINT:
  296. case DXGI_FORMAT_R11G11B10_FLOAT:
  297. case DXGI_FORMAT_R8G8B8A8_TYPELESS:
  298. case DXGI_FORMAT_R8G8B8A8_UNORM:
  299. case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
  300. case DXGI_FORMAT_R8G8B8A8_UINT:
  301. case DXGI_FORMAT_R8G8B8A8_SNORM:
  302. case DXGI_FORMAT_R8G8B8A8_SINT:
  303. case DXGI_FORMAT_R16G16_TYPELESS:
  304. case DXGI_FORMAT_R16G16_FLOAT:
  305. case DXGI_FORMAT_R16G16_UNORM:
  306. case DXGI_FORMAT_R16G16_UINT:
  307. case DXGI_FORMAT_R16G16_SNORM:
  308. case DXGI_FORMAT_R16G16_SINT:
  309. case DXGI_FORMAT_R32_TYPELESS:
  310. case DXGI_FORMAT_D32_FLOAT:
  311. case DXGI_FORMAT_R32_FLOAT:
  312. case DXGI_FORMAT_R32_UINT:
  313. case DXGI_FORMAT_R32_SINT:
  314. case DXGI_FORMAT_R24G8_TYPELESS:
  315. case DXGI_FORMAT_D24_UNORM_S8_UINT:
  316. case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
  317. case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
  318. case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
  319. case DXGI_FORMAT_R8G8_B8G8_UNORM:
  320. case DXGI_FORMAT_G8R8_G8B8_UNORM:
  321. case DXGI_FORMAT_B8G8R8A8_UNORM:
  322. case DXGI_FORMAT_B8G8R8X8_UNORM:
  323. case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
  324. case DXGI_FORMAT_B8G8R8A8_TYPELESS:
  325. case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
  326. case DXGI_FORMAT_B8G8R8X8_TYPELESS:
  327. case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
  328. case DXGI_FORMAT_AYUV:
  329. case DXGI_FORMAT_Y410:
  330. case DXGI_FORMAT_YUY2:
  331. return 32;
  332.  
  333. case DXGI_FORMAT_P010:
  334. case DXGI_FORMAT_P016:
  335. return 24;
  336.  
  337. case DXGI_FORMAT_R8G8_TYPELESS:
  338. case DXGI_FORMAT_R8G8_UNORM:
  339. case DXGI_FORMAT_R8G8_UINT:
  340. case DXGI_FORMAT_R8G8_SNORM:
  341. case DXGI_FORMAT_R8G8_SINT:
  342. case DXGI_FORMAT_R16_TYPELESS:
  343. case DXGI_FORMAT_R16_FLOAT:
  344. case DXGI_FORMAT_D16_UNORM:
  345. case DXGI_FORMAT_R16_UNORM:
  346. case DXGI_FORMAT_R16_UINT:
  347. case DXGI_FORMAT_R16_SNORM:
  348. case DXGI_FORMAT_R16_SINT:
  349. case DXGI_FORMAT_B5G6R5_UNORM:
  350. case DXGI_FORMAT_B5G5R5A1_UNORM:
  351. case DXGI_FORMAT_A8P8:
  352. case DXGI_FORMAT_B4G4R4A4_UNORM:
  353. return 16;
  354.  
  355. case DXGI_FORMAT_NV12:
  356. case DXGI_FORMAT_420_OPAQUE:
  357. case DXGI_FORMAT_NV11:
  358. return 12;
  359.  
  360. case DXGI_FORMAT_R8_TYPELESS:
  361. case DXGI_FORMAT_R8_UNORM:
  362. case DXGI_FORMAT_R8_UINT:
  363. case DXGI_FORMAT_R8_SNORM:
  364. case DXGI_FORMAT_R8_SINT:
  365. case DXGI_FORMAT_A8_UNORM:
  366. case DXGI_FORMAT_AI44:
  367. case DXGI_FORMAT_IA44:
  368. case DXGI_FORMAT_P8:
  369. return 8;
  370.  
  371. case DXGI_FORMAT_R1_UNORM:
  372. return 1;
  373.  
  374. case DXGI_FORMAT_BC1_TYPELESS:
  375. case DXGI_FORMAT_BC1_UNORM:
  376. case DXGI_FORMAT_BC1_UNORM_SRGB:
  377. case DXGI_FORMAT_BC4_TYPELESS:
  378. case DXGI_FORMAT_BC4_UNORM:
  379. case DXGI_FORMAT_BC4_SNORM:
  380. return 4;
  381.  
  382. case DXGI_FORMAT_BC2_TYPELESS:
  383. case DXGI_FORMAT_BC2_UNORM:
  384. case DXGI_FORMAT_BC2_UNORM_SRGB:
  385. case DXGI_FORMAT_BC3_TYPELESS:
  386. case DXGI_FORMAT_BC3_UNORM:
  387. case DXGI_FORMAT_BC3_UNORM_SRGB:
  388. case DXGI_FORMAT_BC5_TYPELESS:
  389. case DXGI_FORMAT_BC5_UNORM:
  390. case DXGI_FORMAT_BC5_SNORM:
  391. case DXGI_FORMAT_BC6H_TYPELESS:
  392. case DXGI_FORMAT_BC6H_UF16:
  393. case DXGI_FORMAT_BC6H_SF16:
  394. case DXGI_FORMAT_BC7_TYPELESS:
  395. case DXGI_FORMAT_BC7_UNORM:
  396. case DXGI_FORMAT_BC7_UNORM_SRGB:
  397. return 8;
  398.  
  399. #if defined(_XBOX_ONE) && defined(_TITLE)
  400.  
  401. case DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT:
  402. case DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT:
  403. return 32;
  404.  
  405. #if MONOLITHIC
  406. case DXGI_FORMAT_D16_UNORM_S8_UINT:
  407. case DXGI_FORMAT_R16_UNORM_X8_TYPELESS:
  408. case DXGI_FORMAT_X16_TYPELESS_G8_UINT:
  409. return 24;
  410. #endif
  411.  
  412. #endif // _XBOX_ONE && _TITLE
  413.  
  414.  
  415. default:
  416. return 0;
  417. }
  418. }
  419.  
  420.  
  421. //--------------------------------------------------------------------------------------
  422. // Get surface information for a particular format
  423. //--------------------------------------------------------------------------------------
  424. static void GetSurfaceInfo(_In_ size_t width,
  425. _In_ size_t height,
  426. _In_ DXGI_FORMAT fmt,
  427. _Out_opt_ size_t *outNumBytes,
  428. _Out_opt_ size_t *outRowBytes,
  429. _Out_opt_ size_t *outNumRows)
  430. {
  431. size_t numBytes = 0;
  432. size_t rowBytes = 0;
  433. size_t numRows = 0;
  434.  
  435. bool bc = false;
  436. bool packed = false;
  437. bool planar = false;
  438. size_t bpe = 0;
  439. switch (fmt)
  440. {
  441. case DXGI_FORMAT_BC1_TYPELESS:
  442. case DXGI_FORMAT_BC1_UNORM:
  443. case DXGI_FORMAT_BC1_UNORM_SRGB:
  444. case DXGI_FORMAT_BC4_TYPELESS:
  445. case DXGI_FORMAT_BC4_UNORM:
  446. case DXGI_FORMAT_BC4_SNORM:
  447. bc = true;
  448. bpe = 8;
  449. break;
  450.  
  451. case DXGI_FORMAT_BC2_TYPELESS:
  452. case DXGI_FORMAT_BC2_UNORM:
  453. case DXGI_FORMAT_BC2_UNORM_SRGB:
  454. case DXGI_FORMAT_BC3_TYPELESS:
  455. case DXGI_FORMAT_BC3_UNORM:
  456. case DXGI_FORMAT_BC3_UNORM_SRGB:
  457. case DXGI_FORMAT_BC5_TYPELESS:
  458. case DXGI_FORMAT_BC5_UNORM:
  459. case DXGI_FORMAT_BC5_SNORM:
  460. case DXGI_FORMAT_BC6H_TYPELESS:
  461. case DXGI_FORMAT_BC6H_UF16:
  462. case DXGI_FORMAT_BC6H_SF16:
  463. case DXGI_FORMAT_BC7_TYPELESS:
  464. case DXGI_FORMAT_BC7_UNORM:
  465. case DXGI_FORMAT_BC7_UNORM_SRGB:
  466. bc = true;
  467. bpe = 16;
  468. break;
  469.  
  470. case DXGI_FORMAT_R8G8_B8G8_UNORM:
  471. case DXGI_FORMAT_G8R8_G8B8_UNORM:
  472. case DXGI_FORMAT_YUY2:
  473. packed = true;
  474. bpe = 4;
  475. break;
  476.  
  477. case DXGI_FORMAT_Y210:
  478. case DXGI_FORMAT_Y216:
  479. packed = true;
  480. bpe = 8;
  481. break;
  482.  
  483. case DXGI_FORMAT_NV12:
  484. case DXGI_FORMAT_420_OPAQUE:
  485. planar = true;
  486. bpe = 2;
  487. break;
  488.  
  489. case DXGI_FORMAT_P010:
  490. case DXGI_FORMAT_P016:
  491. planar = true;
  492. bpe = 4;
  493. break;
  494.  
  495. #if defined(_XBOX_ONE) && defined(_TITLE) && MONOLITHIC
  496.  
  497. case DXGI_FORMAT_D16_UNORM_S8_UINT:
  498. case DXGI_FORMAT_R16_UNORM_X8_TYPELESS:
  499. case DXGI_FORMAT_X16_TYPELESS_G8_UINT:
  500. planar = true;
  501. bpe = 4;
  502. break;
  503.  
  504. #endif
  505. }
  506.  
  507. if (bc)
  508. {
  509. size_t numBlocksWide = 0;
  510. if (width > 0)
  511. {
  512. numBlocksWide = std::max<size_t>( 1, (width + 3) / 4 );
  513. }
  514. size_t numBlocksHigh = 0;
  515. if (height > 0)
  516. {
  517. numBlocksHigh = std::max<size_t>( 1, (height + 3) / 4 );
  518. }
  519. rowBytes = numBlocksWide * bpe;
  520. numRows = numBlocksHigh;
  521. numBytes = rowBytes * numBlocksHigh;
  522. }
  523. else if (packed)
  524. {
  525. rowBytes = ((width + 1) >> 1) * bpe;
  526. numRows = height;
  527. numBytes = rowBytes * height;
  528. }
  529. else if (fmt == DXGI_FORMAT_NV11)
  530. {
  531. rowBytes = ((width + 3) >> 2) * 4;
  532. numRows = height * 2; // Direct3D makes this simplifying assumption, although it is larger than the 4:1:1 data
  533. numBytes = rowBytes * numRows;
  534. }
  535. else if (planar)
  536. {
  537. rowBytes = ((width + 1) >> 1) * bpe;
  538. numBytes = (rowBytes * height) + ((rowBytes * height + 1) >> 1);
  539. numRows = height + ((height + 1) >> 1);
  540. }
  541. else
  542. {
  543. size_t bpp = BitsPerPixel( fmt );
  544. rowBytes = (width * bpp + 7) / 8; // round up to nearest byte
  545. numRows = height;
  546. numBytes = rowBytes * height;
  547. }
  548.  
  549. if (outNumBytes)
  550. {
  551. *outNumBytes = numBytes;
  552. }
  553. if (outRowBytes)
  554. {
  555. *outRowBytes = rowBytes;
  556. }
  557. if (outNumRows)
  558. {
  559. *outNumRows = numRows;
  560. }
  561. }
  562.  
  563.  
  564. //--------------------------------------------------------------------------------------
  565. #define ISBITMASK( r,g,b,a ) ( ddpf.RBitMask == r && ddpf.GBitMask == g && ddpf.BBitMask == b && ddpf.ABitMask == a )
  566.  
  567. static DXGI_FORMAT GetDXGIFormat(const DDS_PIXELFORMAT &ddpf)
  568. {
  569. if (ddpf.flags & DDS_RGB)
  570. {
  571. // Note that sRGB formats are written using the "DX10" extended header
  572.  
  573. switch (ddpf.RGBBitCount)
  574. {
  575. case 32:
  576. if (ISBITMASK(0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000))
  577. {
  578. return DXGI_FORMAT_R8G8B8A8_UNORM;
  579. }
  580.  
  581. if (ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000))
  582. {
  583. return DXGI_FORMAT_B8G8R8A8_UNORM;
  584. }
  585.  
  586. if (ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000))
  587. {
  588. return DXGI_FORMAT_B8G8R8X8_UNORM;
  589. }
  590.  
  591. // No DXGI format maps to ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0x00000000) aka D3DFMT_X8B8G8R8
  592.  
  593. // Note that many common DDS reader/writers (including D3DX) swap the
  594. // the RED/BLUE masks for 10:10:10:2 formats. We assumme
  595. // below that the 'backwards' header mask is being used since it is most
  596. // likely written by D3DX. The more robust solution is to use the 'DX10'
  597. // header extension and specify the DXGI_FORMAT_R10G10B10A2_UNORM format directly
  598.  
  599. // For 'correct' writers, this should be 0x000003ff,0x000ffc00,0x3ff00000 for RGB data
  600. if (ISBITMASK(0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000))
  601. {
  602. return DXGI_FORMAT_R10G10B10A2_UNORM;
  603. }
  604.  
  605. // No DXGI format maps to ISBITMASK(0x000003ff,0x000ffc00,0x3ff00000,0xc0000000) aka D3DFMT_A2R10G10B10
  606.  
  607. if (ISBITMASK(0x0000ffff, 0xffff0000, 0x00000000, 0x00000000))
  608. {
  609. return DXGI_FORMAT_R16G16_UNORM;
  610. }
  611.  
  612. if (ISBITMASK(0xffffffff, 0x00000000, 0x00000000, 0x00000000))
  613. {
  614. // Only 32-bit color channel format in D3D9 was R32F
  615. return DXGI_FORMAT_R32_FLOAT; // D3DX writes this out as a FourCC of 114
  616. }
  617. break;
  618.  
  619. case 24:
  620. // No 24bpp DXGI formats aka D3DFMT_R8G8B8
  621. break;
  622.  
  623. case 16:
  624. if (ISBITMASK(0x7c00, 0x03e0, 0x001f, 0x8000))
  625. {
  626. return DXGI_FORMAT_B5G5R5A1_UNORM;
  627. }
  628. if (ISBITMASK(0xf800, 0x07e0, 0x001f, 0x0000))
  629. {
  630. return DXGI_FORMAT_B5G6R5_UNORM;
  631. }
  632.  
  633. // No DXGI format maps to ISBITMASK(0x7c00,0x03e0,0x001f,0x0000) aka D3DFMT_X1R5G5B5
  634.  
  635. if (ISBITMASK(0x0f00, 0x00f0, 0x000f, 0xf000))
  636. {
  637. return DXGI_FORMAT_B4G4R4A4_UNORM;
  638. }
  639.  
  640. // No DXGI format maps to ISBITMASK(0x0f00,0x00f0,0x000f,0x0000) aka D3DFMT_X4R4G4B4
  641.  
  642. // No 3:3:2, 3:3:2:8, or paletted DXGI formats aka D3DFMT_A8R3G3B2, D3DFMT_R3G3B2, D3DFMT_P8, D3DFMT_A8P8, etc.
  643. break;
  644. }
  645. }
  646. else if (ddpf.flags & DDS_LUMINANCE)
  647. {
  648. if (8 == ddpf.RGBBitCount)
  649. {
  650. if (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x00000000))
  651. {
  652. return DXGI_FORMAT_R8_UNORM; // D3DX10/11 writes this out as DX10 extension
  653. }
  654.  
  655. // No DXGI format maps to ISBITMASK(0x0f,0x00,0x00,0xf0) aka D3DFMT_A4L4
  656. }
  657.  
  658. if (16 == ddpf.RGBBitCount)
  659. {
  660. if (ISBITMASK(0x0000ffff, 0x00000000, 0x00000000, 0x00000000))
  661. {
  662. return DXGI_FORMAT_R16_UNORM; // D3DX10/11 writes this out as DX10 extension
  663. }
  664. if (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x0000ff00))
  665. {
  666. return DXGI_FORMAT_R8G8_UNORM; // D3DX10/11 writes this out as DX10 extension
  667. }
  668. }
  669. }
  670. else if (ddpf.flags & DDS_ALPHA)
  671. {
  672. if (8 == ddpf.RGBBitCount)
  673. {
  674. return DXGI_FORMAT_A8_UNORM;
  675. }
  676. }
  677. else if (ddpf.flags & DDS_FOURCC)
  678. {
  679. if (MAKEFOURCC('D', 'X', 'T', '1') == ddpf.fourCC)
  680. {
  681. return DXGI_FORMAT_BC1_UNORM;
  682. }
  683. if (MAKEFOURCC('D', 'X', 'T', '3') == ddpf.fourCC)
  684. {
  685. return DXGI_FORMAT_BC2_UNORM;
  686. }
  687. if (MAKEFOURCC('D', 'X', 'T', '5') == ddpf.fourCC)
  688. {
  689. return DXGI_FORMAT_BC3_UNORM;
  690. }
  691.  
  692. // While pre-mulitplied alpha isn't directly supported by the DXGI formats,
  693. // they are basically the same as these BC formats so they can be mapped
  694. if (MAKEFOURCC('D', 'X', 'T', '2') == ddpf.fourCC)
  695. {
  696. return DXGI_FORMAT_BC2_UNORM;
  697. }
  698. if (MAKEFOURCC('D', 'X', 'T', '4') == ddpf.fourCC)
  699. {
  700. return DXGI_FORMAT_BC3_UNORM;
  701. }
  702.  
  703. if (MAKEFOURCC('A', 'T', 'I', '1') == ddpf.fourCC)
  704. {
  705. return DXGI_FORMAT_BC4_UNORM;
  706. }
  707. if (MAKEFOURCC('B', 'C', '4', 'U') == ddpf.fourCC)
  708. {
  709. return DXGI_FORMAT_BC4_UNORM;
  710. }
  711. if (MAKEFOURCC('B', 'C', '4', 'S') == ddpf.fourCC)
  712. {
  713. return DXGI_FORMAT_BC4_SNORM;
  714. }
  715.  
  716. if (MAKEFOURCC('A', 'T', 'I', '2') == ddpf.fourCC)
  717. {
  718. return DXGI_FORMAT_BC5_UNORM;
  719. }
  720. if (MAKEFOURCC('B', 'C', '5', 'U') == ddpf.fourCC)
  721. {
  722. return DXGI_FORMAT_BC5_UNORM;
  723. }
  724. if (MAKEFOURCC('B', 'C', '5', 'S') == ddpf.fourCC)
  725. {
  726. return DXGI_FORMAT_BC5_SNORM;
  727. }
  728.  
  729. // BC6H and BC7 are written using the "DX10" extended header
  730.  
  731. if (MAKEFOURCC('R', 'G', 'B', 'G') == ddpf.fourCC)
  732. {
  733. return DXGI_FORMAT_R8G8_B8G8_UNORM;
  734. }
  735. if (MAKEFOURCC('G', 'R', 'G', 'B') == ddpf.fourCC)
  736. {
  737. return DXGI_FORMAT_G8R8_G8B8_UNORM;
  738. }
  739.  
  740. if (MAKEFOURCC('Y', 'U', 'Y', '2') == ddpf.fourCC)
  741. {
  742. return DXGI_FORMAT_YUY2;
  743. }
  744.  
  745. // Check for D3DFORMAT enums being set here
  746. switch (ddpf.fourCC)
  747. {
  748. case 36: // D3DFMT_A16B16G16R16
  749. return DXGI_FORMAT_R16G16B16A16_UNORM;
  750.  
  751. case 110: // D3DFMT_Q16W16V16U16
  752. return DXGI_FORMAT_R16G16B16A16_SNORM;
  753.  
  754. case 111: // D3DFMT_R16F
  755. return DXGI_FORMAT_R16_FLOAT;
  756.  
  757. case 112: // D3DFMT_G16R16F
  758. return DXGI_FORMAT_R16G16_FLOAT;
  759.  
  760. case 113: // D3DFMT_A16B16G16R16F
  761. return DXGI_FORMAT_R16G16B16A16_FLOAT;
  762.  
  763. case 114: // D3DFMT_R32F
  764. return DXGI_FORMAT_R32_FLOAT;
  765.  
  766. case 115: // D3DFMT_G32R32F
  767. return DXGI_FORMAT_R32G32_FLOAT;
  768.  
  769. case 116: // D3DFMT_A32B32G32R32F
  770. return DXGI_FORMAT_R32G32B32A32_FLOAT;
  771. }
  772. }
  773.  
  774. return DXGI_FORMAT_UNKNOWN;
  775. }
  776.  
  777.  
  778. //--------------------------------------------------------------------------------------
  779. static DXGI_FORMAT MakeSRGB(_In_ DXGI_FORMAT format)
  780. {
  781. switch (format)
  782. {
  783. case DXGI_FORMAT_R8G8B8A8_UNORM:
  784. return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
  785.  
  786. case DXGI_FORMAT_BC1_UNORM:
  787. return DXGI_FORMAT_BC1_UNORM_SRGB;
  788.  
  789. case DXGI_FORMAT_BC2_UNORM:
  790. return DXGI_FORMAT_BC2_UNORM_SRGB;
  791.  
  792. case DXGI_FORMAT_BC3_UNORM:
  793. return DXGI_FORMAT_BC3_UNORM_SRGB;
  794.  
  795. case DXGI_FORMAT_B8G8R8A8_UNORM:
  796. return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
  797.  
  798. case DXGI_FORMAT_B8G8R8X8_UNORM:
  799. return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB;
  800.  
  801. case DXGI_FORMAT_BC7_UNORM:
  802. return DXGI_FORMAT_BC7_UNORM_SRGB;
  803.  
  804. default:
  805. return format;
  806. }
  807. }
  808.  
  809.  
  810. //--------------------------------------------------------------------------------------
  811. static HRESULT FillInitData(_In_ size_t width,
  812. _In_ size_t height,
  813. _In_ size_t depth,
  814. _In_ size_t mipCount,
  815. _In_ size_t arraySize,
  816. _In_ DXGI_FORMAT format,
  817. _In_ size_t maxsize,
  818. _In_ size_t bitSize,
  819. _In_reads_bytes_(bitSize) const uint8_t *bitData,
  820. _Out_ size_t &twidth,
  821. _Out_ size_t &theight,
  822. _Out_ size_t &tdepth,
  823. _Out_ size_t &skipMip,
  824. _Out_writes_(mipCount*arraySize) D3D11_SUBRESOURCE_DATA *initData)
  825. {
  826. if (!bitData || !initData)
  827. {
  828. return E_POINTER;
  829. }
  830.  
  831. skipMip = 0;
  832. twidth = 0;
  833. theight = 0;
  834. tdepth = 0;
  835.  
  836. size_t NumBytes = 0;
  837. size_t RowBytes = 0;
  838. const uint8_t *pSrcBits = bitData;
  839. const uint8_t *pEndBits = bitData + bitSize;
  840.  
  841. size_t index = 0;
  842. for (size_t j = 0; j < arraySize; j++)
  843. {
  844. size_t w = width;
  845. size_t h = height;
  846. size_t d = depth;
  847. for (size_t i = 0; i < mipCount; i++)
  848. {
  849. GetSurfaceInfo( w,
  850. h,
  851. format,
  852. &NumBytes,
  853. &RowBytes,
  854. nullptr
  855. );
  856.  
  857. if ((mipCount <= 1) || !maxsize || (w <= maxsize && h <= maxsize && d <= maxsize))
  858. {
  859. if (!twidth)
  860. {
  861. twidth = w;
  862. theight = h;
  863. tdepth = d;
  864. }
  865.  
  866. assert(index < mipCount * arraySize);
  867. _Analysis_assume_(index < mipCount * arraySize);
  868. initData[ index ].pSysMem = ( const void* )pSrcBits;
  869. initData[ index ].SysMemPitch = static_cast<UINT>( RowBytes );
  870. initData[ index ].SysMemSlicePitch = static_cast<UINT>( NumBytes );
  871. ++index;
  872. }
  873. else if (!j)
  874. {
  875. // Count number of skipped mipmaps (first item only)
  876. ++skipMip;
  877. }
  878.  
  879. if (pSrcBits + (NumBytes * d) > pEndBits)
  880. {
  881. return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF );
  882. }
  883.  
  884. pSrcBits += NumBytes * d;
  885.  
  886. w = w >> 1;
  887. h = h >> 1;
  888. d = d >> 1;
  889. if (w == 0)
  890. {
  891. w = 1;
  892. }
  893. if (h == 0)
  894. {
  895. h = 1;
  896. }
  897. if (d == 0)
  898. {
  899. d = 1;
  900. }
  901. }
  902. }
  903.  
  904. return (index > 0) ? S_OK : E_FAIL;
  905. }
  906.  
  907.  
  908. //--------------------------------------------------------------------------------------
  909. static HRESULT CreateD3DResources(_In_ ID3D11Device *d3dDevice,
  910. _In_ uint32_t resDim,
  911. _In_ size_t width,
  912. _In_ size_t height,
  913. _In_ size_t depth,
  914. _In_ size_t mipCount,
  915. _In_ size_t arraySize,
  916. _In_ DXGI_FORMAT format,
  917. _In_ D3D11_USAGE usage,
  918. _In_ unsigned int bindFlags,
  919. _In_ unsigned int cpuAccessFlags,
  920. _In_ unsigned int miscFlags,
  921. _In_ bool forceSRGB,
  922. _In_ bool isCubeMap,
  923. _In_reads_opt_(mipCount*arraySize) D3D11_SUBRESOURCE_DATA *initData,
  924. _Outptr_opt_ ID3D11Resource **texture,
  925. _Outptr_opt_ ID3D11ShaderResourceView **textureView)
  926. {
  927. if (!d3dDevice)
  928. return E_POINTER;
  929.  
  930. HRESULT hr = E_FAIL;
  931.  
  932. if (forceSRGB)
  933. {
  934. format = MakeSRGB( format );
  935. }
  936.  
  937. switch (resDim)
  938. {
  939. case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
  940. {
  941. D3D11_TEXTURE1D_DESC desc;
  942. desc.Width = static_cast<UINT>( width );
  943. desc.MipLevels = static_cast<UINT>( mipCount );
  944. desc.ArraySize = static_cast<UINT>( arraySize );
  945. desc.Format = format;
  946. desc.Usage = usage;
  947. desc.BindFlags = bindFlags;
  948. desc.CPUAccessFlags = cpuAccessFlags;
  949. desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE;
  950.  
  951. ID3D11Texture1D *tex = nullptr;
  952. hr = d3dDevice->CreateTexture1D( &desc,
  953. initData,
  954. &tex
  955. );
  956. if (SUCCEEDED(hr) && tex != 0)
  957. {
  958. if (textureView != 0)
  959. {
  960. D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
  961. memset( &SRVDesc, 0, sizeof(SRVDesc) );
  962. SRVDesc.Format = format;
  963.  
  964. if (arraySize > 1)
  965. {
  966. SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
  967. SRVDesc.Texture1DArray.MipLevels = (!mipCount) ? -1 : desc.MipLevels;
  968. SRVDesc.Texture1DArray.ArraySize = static_cast<UINT>( arraySize );
  969. }
  970. else
  971. {
  972. SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
  973. SRVDesc.Texture1D.MipLevels = (!mipCount) ? -1 : desc.MipLevels;
  974. }
  975.  
  976. hr = d3dDevice->CreateShaderResourceView( tex,
  977. &SRVDesc,
  978. textureView
  979. );
  980. if (FAILED(hr))
  981. {
  982. tex->Release( );
  983. return hr;
  984. }
  985. }
  986.  
  987. if (texture != 0)
  988. {
  989. *texture = tex;
  990. }
  991. else
  992. {
  993. SetDebugObjectName( tex, "DDSTextureLoader" );
  994. tex->Release( );
  995. }
  996. }
  997. }
  998. break;
  999.  
  1000. case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
  1001. {
  1002. D3D11_TEXTURE2D_DESC desc;
  1003. desc.Width = static_cast<UINT>( width );
  1004. desc.Height = static_cast<UINT>( height );
  1005. desc.MipLevels = static_cast<UINT>( mipCount );
  1006. desc.ArraySize = static_cast<UINT>( arraySize );
  1007. desc.Format = format;
  1008. desc.SampleDesc.Count = 1;
  1009. desc.SampleDesc.Quality = 0;
  1010. desc.Usage = usage;
  1011. desc.BindFlags = bindFlags;
  1012. desc.CPUAccessFlags = cpuAccessFlags;
  1013. if (isCubeMap)
  1014. {
  1015. desc.MiscFlags = miscFlags | D3D11_RESOURCE_MISC_TEXTURECUBE;
  1016. }
  1017. else
  1018. {
  1019. desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE;
  1020. }
  1021.  
  1022. ID3D11Texture2D *tex = nullptr;
  1023. hr = d3dDevice->CreateTexture2D( &desc,
  1024. initData,
  1025. &tex
  1026. );
  1027. if (SUCCEEDED(hr) && tex != 0)
  1028. {
  1029. if (textureView != 0)
  1030. {
  1031. D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
  1032. memset( &SRVDesc, 0, sizeof(SRVDesc) );
  1033. SRVDesc.Format = format;
  1034.  
  1035. if (isCubeMap)
  1036. {
  1037. if (arraySize > 6)
  1038. {
  1039. SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY;
  1040. SRVDesc.TextureCubeArray.MipLevels = (!mipCount) ? -1 : desc.MipLevels;
  1041.  
  1042. // Earlier we set arraySize to (NumCubes * 6)
  1043. SRVDesc.TextureCubeArray.NumCubes = static_cast<UINT>( arraySize / 6 );
  1044. }
  1045. else
  1046. {
  1047. SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
  1048. SRVDesc.TextureCube.MipLevels = (!mipCount) ? -1 : desc.MipLevels;
  1049. }
  1050. }
  1051. else if (arraySize > 1)
  1052. {
  1053. SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
  1054. SRVDesc.Texture2DArray.MipLevels = (!mipCount) ? -1 : desc.MipLevels;
  1055. SRVDesc.Texture2DArray.ArraySize = static_cast<UINT>( arraySize );
  1056. }
  1057. else
  1058. {
  1059. SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
  1060. SRVDesc.Texture2D.MipLevels = (!mipCount) ? -1 : desc.MipLevels;
  1061. }
  1062.  
  1063. hr = d3dDevice->CreateShaderResourceView( tex,
  1064. &SRVDesc,
  1065. textureView
  1066. );
  1067. if (FAILED(hr))
  1068. {
  1069. tex->Release( );
  1070. return hr;
  1071. }
  1072. }
  1073.  
  1074. if (texture != 0)
  1075. {
  1076. *texture = tex;
  1077. }
  1078. else
  1079. {
  1080. SetDebugObjectName( tex, "DDSTextureLoader" );
  1081. tex->Release( );
  1082. }
  1083. }
  1084. }
  1085. break;
  1086.  
  1087. case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
  1088. {
  1089. D3D11_TEXTURE3D_DESC desc;
  1090. desc.Width = static_cast<UINT>( width );
  1091. desc.Height = static_cast<UINT>( height );
  1092. desc.Depth = static_cast<UINT>( depth );
  1093. desc.MipLevels = static_cast<UINT>( mipCount );
  1094. desc.Format = format;
  1095. desc.Usage = usage;
  1096. desc.BindFlags = bindFlags;
  1097. desc.CPUAccessFlags = cpuAccessFlags;
  1098. desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE;
  1099.  
  1100. ID3D11Texture3D *tex = nullptr;
  1101. hr = d3dDevice->CreateTexture3D( &desc,
  1102. initData,
  1103. &tex
  1104. );
  1105. if (SUCCEEDED(hr) && tex != 0)
  1106. {
  1107. if (textureView != 0)
  1108. {
  1109. D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
  1110. memset( &SRVDesc, 0, sizeof(SRVDesc) );
  1111. SRVDesc.Format = format;
  1112.  
  1113. SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
  1114. SRVDesc.Texture3D.MipLevels = (!mipCount) ? -1 : desc.MipLevels;
  1115.  
  1116. hr = d3dDevice->CreateShaderResourceView( tex,
  1117. &SRVDesc,
  1118. textureView
  1119. );
  1120. if (FAILED(hr))
  1121. {
  1122. tex->Release( );
  1123. return hr;
  1124. }
  1125. }
  1126.  
  1127. if (texture != 0)
  1128. {
  1129. *texture = tex;
  1130. }
  1131. else
  1132. {
  1133. SetDebugObjectName( tex, "DDSTextureLoader" );
  1134. tex->Release( );
  1135. }
  1136. }
  1137. }
  1138. break;
  1139. }
  1140.  
  1141. return hr;
  1142. }
  1143.  
  1144.  
  1145. //--------------------------------------------------------------------------------------
  1146. static HRESULT CreateTextureFromDDS(_In_ ID3D11Device *d3dDevice,
  1147. _In_opt_ ID3D11DeviceContext *d3dContext,
  1148. _In_ const DDS_HEADER *header,
  1149. _In_reads_bytes_(bitSize) const uint8_t *bitData,
  1150. _In_ size_t bitSize,
  1151. _In_ size_t maxsize,
  1152. _In_ D3D11_USAGE usage,
  1153. _In_ unsigned int bindFlags,
  1154. _In_ unsigned int cpuAccessFlags,
  1155. _In_ unsigned int miscFlags,
  1156. _In_ bool forceSRGB,
  1157. _Outptr_opt_ ID3D11Resource **texture,
  1158. _Outptr_opt_ ID3D11ShaderResourceView **textureView)
  1159. {
  1160. HRESULT hr = S_OK;
  1161.  
  1162. size_t width = header->width;
  1163. size_t height = header->height;
  1164. size_t depth = header->depth;
  1165.  
  1166. uint32_t resDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
  1167. size_t arraySize = 1;
  1168. DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
  1169. bool isCubeMap = false;
  1170.  
  1171. size_t mipCount = header->mipMapCount;
  1172. if (0 == mipCount)
  1173. {
  1174. mipCount = 1;
  1175. }
  1176.  
  1177. if ((header->ddspf.flags & DDS_FOURCC) &&
  1178. (MAKEFOURCC('D', 'X', '1', '0') == header->ddspf.fourCC))
  1179. {
  1180. auto d3d10ext = reinterpret_cast<const DDS_HEADER_DXT10*>( ( const char* )header + sizeof(DDS_HEADER) );
  1181.  
  1182. arraySize = d3d10ext->arraySize;
  1183. if (arraySize == 0)
  1184. {
  1185. return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
  1186. }
  1187.  
  1188. switch (d3d10ext->dxgiFormat)
  1189. {
  1190. case DXGI_FORMAT_AI44:
  1191. case DXGI_FORMAT_IA44:
  1192. case DXGI_FORMAT_P8:
  1193. case DXGI_FORMAT_A8P8:
  1194. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  1195.  
  1196. default:
  1197. if (BitsPerPixel( d3d10ext->dxgiFormat ) == 0)
  1198. {
  1199. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  1200. }
  1201. }
  1202.  
  1203. format = d3d10ext->dxgiFormat;
  1204.  
  1205. switch (d3d10ext->resourceDimension)
  1206. {
  1207. case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
  1208. // D3DX writes 1D textures with a fixed Height of 1
  1209. if ((header->flags & DDS_HEIGHT) && height != 1)
  1210. {
  1211. return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
  1212. }
  1213. height = depth = 1;
  1214. break;
  1215.  
  1216. case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
  1217. if (d3d10ext->miscFlag & D3D11_RESOURCE_MISC_TEXTURECUBE)
  1218. {
  1219. arraySize *= 6;
  1220. isCubeMap = true;
  1221. }
  1222. depth = 1;
  1223. break;
  1224.  
  1225. case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
  1226. if (!(header->flags & DDS_HEADER_FLAGS_VOLUME))
  1227. {
  1228. return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
  1229. }
  1230.  
  1231. if (arraySize > 1)
  1232. {
  1233. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  1234. }
  1235. break;
  1236.  
  1237. default:
  1238. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  1239. }
  1240.  
  1241. resDim = d3d10ext->resourceDimension;
  1242. }
  1243. else
  1244. {
  1245. format = GetDXGIFormat( header->ddspf );
  1246.  
  1247. if (format == DXGI_FORMAT_UNKNOWN)
  1248. {
  1249. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  1250. }
  1251.  
  1252. if (header->flags & DDS_HEADER_FLAGS_VOLUME)
  1253. {
  1254. resDim = D3D11_RESOURCE_DIMENSION_TEXTURE3D;
  1255. }
  1256. else
  1257. {
  1258. if (header->caps2 & DDS_CUBEMAP)
  1259. {
  1260. // We require all six faces to be defined
  1261. if ((header->caps2 & DDS_CUBEMAP_ALLFACES) != DDS_CUBEMAP_ALLFACES)
  1262. {
  1263. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  1264. }
  1265.  
  1266. arraySize = 6;
  1267. isCubeMap = true;
  1268. }
  1269.  
  1270. depth = 1;
  1271. resDim = D3D11_RESOURCE_DIMENSION_TEXTURE2D;
  1272.  
  1273. // Note there's no way for a legacy Direct3D 9 DDS to express a '1D' texture
  1274. }
  1275.  
  1276. assert(BitsPerPixel(format) != 0);
  1277. }
  1278.  
  1279. // Bound sizes (for security purposes we don't trust DDS file metadata larger than the D3D 11.x hardware requirements)
  1280. if (mipCount > D3D11_REQ_MIP_LEVELS)
  1281. {
  1282. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  1283. }
  1284.  
  1285. switch (resDim)
  1286. {
  1287. case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
  1288. if ((arraySize > D3D11_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION) ||
  1289. (width > D3D11_REQ_TEXTURE1D_U_DIMENSION))
  1290. {
  1291. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  1292. }
  1293. break;
  1294.  
  1295. case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
  1296. if (isCubeMap)
  1297. {
  1298. // This is the right bound because we set arraySize to (NumCubes*6) above
  1299. if ((arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) ||
  1300. (width > D3D11_REQ_TEXTURECUBE_DIMENSION) ||
  1301. (height > D3D11_REQ_TEXTURECUBE_DIMENSION))
  1302. {
  1303. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  1304. }
  1305. }
  1306. else if ((arraySize > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) ||
  1307. (width > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION) ||
  1308. (height > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION))
  1309. {
  1310. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  1311. }
  1312. break;
  1313.  
  1314. case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
  1315. if ((arraySize > 1) ||
  1316. (width > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) ||
  1317. (height > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) ||
  1318. (depth > D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION))
  1319. {
  1320. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  1321. }
  1322. break;
  1323. }
  1324.  
  1325. bool autogen = false;
  1326. if (mipCount == 1 && d3dContext != 0 && textureView != 0) // Must have context and shader-view to auto generate mipmaps
  1327. {
  1328. // See if format is supported for auto-gen mipmaps (varies by feature level)
  1329. UINT fmtSupport = 0;
  1330. hr = d3dDevice->CheckFormatSupport( format, &fmtSupport );
  1331. if (SUCCEEDED(hr) && (fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN))
  1332. {
  1333. // 10level9 feature levels do not support auto-gen mipgen for volume textures
  1334. if ((resDim != D3D11_RESOURCE_DIMENSION_TEXTURE3D)
  1335. || (d3dDevice->GetFeatureLevel( ) >= D3D_FEATURE_LEVEL_10_0))
  1336. {
  1337. autogen = true;
  1338. }
  1339. }
  1340. }
  1341.  
  1342. if (autogen)
  1343. {
  1344. // Create texture with auto-generated mipmaps
  1345. ID3D11Resource *tex = nullptr;
  1346. hr = CreateD3DResources( d3dDevice, resDim, width, height, depth, 0, arraySize,
  1347. format, usage,
  1348. bindFlags | D3D11_BIND_RENDER_TARGET,
  1349. cpuAccessFlags,
  1350. miscFlags | D3D11_RESOURCE_MISC_GENERATE_MIPS, forceSRGB,
  1351. isCubeMap, nullptr, &tex, textureView );
  1352. if (SUCCEEDED(hr))
  1353. {
  1354. size_t numBytes = 0;
  1355. size_t rowBytes = 0;
  1356. GetSurfaceInfo( width, height, format, &numBytes, &rowBytes, nullptr );
  1357.  
  1358. if (numBytes > bitSize)
  1359. {
  1360. (*textureView)->Release( );
  1361. *textureView = nullptr;
  1362. tex->Release( );
  1363. return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF );
  1364. }
  1365.  
  1366. if (arraySize > 1)
  1367. {
  1368. D3D11_SHADER_RESOURCE_VIEW_DESC desc;
  1369. (*textureView)->GetDesc( &desc );
  1370.  
  1371. UINT mipLevels = 1;
  1372.  
  1373. switch (desc.ViewDimension)
  1374. {
  1375. case D3D_SRV_DIMENSION_TEXTURE1D: mipLevels = desc.Texture1D.MipLevels;
  1376. break;
  1377. case D3D_SRV_DIMENSION_TEXTURE1DARRAY: mipLevels = desc.Texture1DArray.MipLevels;
  1378. break;
  1379. case D3D_SRV_DIMENSION_TEXTURE2D: mipLevels = desc.Texture2D.MipLevels;
  1380. break;
  1381. case D3D_SRV_DIMENSION_TEXTURE2DARRAY: mipLevels = desc.Texture2DArray.MipLevels;
  1382. break;
  1383. case D3D_SRV_DIMENSION_TEXTURECUBE: mipLevels = desc.TextureCube.MipLevels;
  1384. break;
  1385. case D3D_SRV_DIMENSION_TEXTURECUBEARRAY: mipLevels = desc.TextureCubeArray.MipLevels;
  1386. break;
  1387. default:
  1388. (*textureView)->Release( );
  1389. *textureView = nullptr;
  1390. tex->Release( );
  1391. return E_UNEXPECTED;
  1392. }
  1393.  
  1394. const uint8_t *pSrcBits = bitData;
  1395. const uint8_t *pEndBits = bitData + bitSize;
  1396. for (UINT item = 0; item < arraySize; ++item)
  1397. {
  1398. if ((pSrcBits + numBytes) > pEndBits)
  1399. {
  1400. (*textureView)->Release( );
  1401. *textureView = nullptr;
  1402. tex->Release( );
  1403. return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF );
  1404. }
  1405.  
  1406. UINT res = D3D11CalcSubresource( 0, item, mipLevels );
  1407. d3dContext->UpdateSubresource( tex, res, nullptr, pSrcBits, static_cast<UINT>( rowBytes ), static_cast<UINT>( numBytes ) );
  1408. pSrcBits += numBytes;
  1409. }
  1410. }
  1411. else
  1412. {
  1413. d3dContext->UpdateSubresource( tex, 0, nullptr, bitData, static_cast<UINT>( rowBytes ), static_cast<UINT>( numBytes ) );
  1414. }
  1415.  
  1416. d3dContext->GenerateMips( *textureView );
  1417.  
  1418. if (texture)
  1419. {
  1420. *texture = tex;
  1421. }
  1422. else
  1423. {
  1424. tex->Release( );
  1425. }
  1426. }
  1427. }
  1428. else
  1429. {
  1430. // Create the texture
  1431. std::unique_ptr<D3D11_SUBRESOURCE_DATA[]> initData( new( std::nothrow ) D3D11_SUBRESOURCE_DATA[mipCount * arraySize] );
  1432. if (!initData)
  1433. {
  1434. return E_OUTOFMEMORY;
  1435. }
  1436.  
  1437. size_t skipMip = 0;
  1438. size_t twidth = 0;
  1439. size_t theight = 0;
  1440. size_t tdepth = 0;
  1441. hr = FillInitData( width, height, depth, mipCount, arraySize, format, maxsize, bitSize, bitData,
  1442. twidth, theight, tdepth, skipMip, initData.get( ) );
  1443.  
  1444. if (SUCCEEDED(hr))
  1445. {
  1446. hr = CreateD3DResources( d3dDevice, resDim, twidth, theight, tdepth, mipCount - skipMip, arraySize,
  1447. format, usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB,
  1448. isCubeMap, initData.get( ), texture, textureView );
  1449.  
  1450. if (FAILED(hr) && !maxsize && (mipCount > 1))
  1451. {
  1452. // Retry with a maxsize determined by feature level
  1453. switch (d3dDevice->GetFeatureLevel( ))
  1454. {
  1455. case D3D_FEATURE_LEVEL_9_1:
  1456. case D3D_FEATURE_LEVEL_9_2:
  1457. if (isCubeMap)
  1458. {
  1459. maxsize = 512 /*D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION*/;
  1460. }
  1461. else
  1462. {
  1463. maxsize = (resDim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
  1464. ? 256 /*D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/
  1465. : 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
  1466. }
  1467. break;
  1468.  
  1469. case D3D_FEATURE_LEVEL_9_3:
  1470. maxsize = (resDim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
  1471. ? 256 /*D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/
  1472. : 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
  1473. break;
  1474.  
  1475. default: // D3D_FEATURE_LEVEL_10_0 & D3D_FEATURE_LEVEL_10_1
  1476. maxsize = (resDim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
  1477. ? 2048 /*D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/
  1478. : 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
  1479. break;
  1480. }
  1481.  
  1482. hr = FillInitData( width, height, depth, mipCount, arraySize, format, maxsize, bitSize, bitData,
  1483. twidth, theight, tdepth, skipMip, initData.get( ) );
  1484. if (SUCCEEDED(hr))
  1485. {
  1486. hr = CreateD3DResources( d3dDevice, resDim, twidth, theight, tdepth, mipCount - skipMip, arraySize,
  1487. format, usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB,
  1488. isCubeMap, initData.get( ), texture, textureView );
  1489. }
  1490. }
  1491. }
  1492. }
  1493.  
  1494. return hr;
  1495. }
  1496.  
  1497.  
  1498. //--------------------------------------------------------------------------------------
  1499. static DDS_ALPHA_MODE GetAlphaMode(_In_ const DDS_HEADER *header)
  1500. {
  1501. if (header->ddspf.flags & DDS_FOURCC)
  1502. {
  1503. if (MAKEFOURCC('D', 'X', '1', '0') == header->ddspf.fourCC)
  1504. {
  1505. auto d3d10ext = reinterpret_cast<const DDS_HEADER_DXT10*>( ( const char* )header + sizeof(DDS_HEADER) );
  1506. auto mode = static_cast<DDS_ALPHA_MODE>( d3d10ext->miscFlags2 & DDS_MISC_FLAGS2_ALPHA_MODE_MASK );
  1507. switch (mode)
  1508. {
  1509. case DDS_ALPHA_MODE_STRAIGHT:
  1510. case DDS_ALPHA_MODE_PREMULTIPLIED:
  1511. case DDS_ALPHA_MODE_OPAQUE:
  1512. case DDS_ALPHA_MODE_CUSTOM:
  1513. return mode;
  1514. }
  1515. }
  1516. else if ((MAKEFOURCC('D', 'X', 'T', '2') == header->ddspf.fourCC)
  1517. || (MAKEFOURCC('D', 'X', 'T', '4') == header->ddspf.fourCC))
  1518. {
  1519. return DDS_ALPHA_MODE_PREMULTIPLIED;
  1520. }
  1521. }
  1522.  
  1523. return DDS_ALPHA_MODE_UNKNOWN;
  1524. }
  1525.  
  1526.  
  1527. //--------------------------------------------------------------------------------------
  1528. _Use_decl_annotations_
  1529. HRESULT DirectX::CreateDDSTextureFromMemory(ID3D11Device *d3dDevice,
  1530. const uint8_t *ddsData,
  1531. size_t ddsDataSize,
  1532. ID3D11Resource **texture,
  1533. ID3D11ShaderResourceView **textureView,
  1534. size_t maxsize,
  1535. DDS_ALPHA_MODE *alphaMode)
  1536. {
  1537. return CreateDDSTextureFromMemoryEx( d3dDevice, nullptr, ddsData, ddsDataSize, maxsize,
  1538. D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, false,
  1539. texture, textureView, alphaMode );
  1540. }
  1541.  
  1542. _Use_decl_annotations_
  1543. HRESULT DirectX::CreateDDSTextureFromMemory(ID3D11Device *d3dDevice,
  1544. ID3D11DeviceContext *d3dContext,
  1545. const uint8_t *ddsData,
  1546. size_t ddsDataSize,
  1547. ID3D11Resource **texture,
  1548. ID3D11ShaderResourceView **textureView,
  1549. size_t maxsize,
  1550. DDS_ALPHA_MODE *alphaMode)
  1551. {
  1552. return CreateDDSTextureFromMemoryEx( d3dDevice, d3dContext, ddsData, ddsDataSize, maxsize,
  1553. D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, false,
  1554. texture, textureView, alphaMode );
  1555. }
  1556.  
  1557. _Use_decl_annotations_
  1558. HRESULT DirectX::CreateDDSTextureFromMemoryEx(ID3D11Device *d3dDevice,
  1559. const uint8_t *ddsData,
  1560. size_t ddsDataSize,
  1561. size_t maxsize,
  1562. D3D11_USAGE usage,
  1563. unsigned int bindFlags,
  1564. unsigned int cpuAccessFlags,
  1565. unsigned int miscFlags,
  1566. bool forceSRGB,
  1567. ID3D11Resource **texture,
  1568. ID3D11ShaderResourceView **textureView,
  1569. DDS_ALPHA_MODE *alphaMode)
  1570. {
  1571. return CreateDDSTextureFromMemoryEx( d3dDevice, nullptr, ddsData, ddsDataSize, maxsize,
  1572. usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB,
  1573. texture, textureView, alphaMode );
  1574. }
  1575.  
  1576. _Use_decl_annotations_
  1577. HRESULT DirectX::CreateDDSTextureFromMemoryEx(ID3D11Device *d3dDevice,
  1578. ID3D11DeviceContext *d3dContext,
  1579. const uint8_t *ddsData,
  1580. size_t ddsDataSize,
  1581. size_t maxsize,
  1582. D3D11_USAGE usage,
  1583. unsigned int bindFlags,
  1584. unsigned int cpuAccessFlags,
  1585. unsigned int miscFlags,
  1586. bool forceSRGB,
  1587. ID3D11Resource **texture,
  1588. ID3D11ShaderResourceView **textureView,
  1589. DDS_ALPHA_MODE *alphaMode)
  1590. {
  1591. if (texture)
  1592. {
  1593. *texture = nullptr;
  1594. }
  1595. if (textureView)
  1596. {
  1597. *textureView = nullptr;
  1598. }
  1599. if (alphaMode)
  1600. {
  1601. *alphaMode = DDS_ALPHA_MODE_UNKNOWN;
  1602. }
  1603.  
  1604. if (!d3dDevice || !ddsData || (!texture && !textureView))
  1605. {
  1606. return E_INVALIDARG;
  1607. }
  1608.  
  1609. // Validate DDS file in memory
  1610. if (ddsDataSize < (sizeof(uint32_t) + sizeof(DDS_HEADER)))
  1611. {
  1612. return E_FAIL;
  1613. }
  1614.  
  1615. uint32_t dwMagicNumber = *( const uint32_t* )(ddsData);
  1616. if (dwMagicNumber != DDS_MAGIC)
  1617. {
  1618. return E_FAIL;
  1619. }
  1620.  
  1621. auto header = reinterpret_cast<const DDS_HEADER*>( ddsData + sizeof(uint32_t) );
  1622.  
  1623. // Verify header to validate DDS file
  1624. if (header->size != sizeof(DDS_HEADER) ||
  1625. header->ddspf.size != sizeof(DDS_PIXELFORMAT))
  1626. {
  1627. return E_FAIL;
  1628. }
  1629.  
  1630. // Check for DX10 extension
  1631. bool bDXT10Header = false;
  1632. if ((header->ddspf.flags & DDS_FOURCC) &&
  1633. (MAKEFOURCC('D', 'X', '1', '0') == header->ddspf.fourCC))
  1634. {
  1635. // Must be long enough for both headers and magic value
  1636. if (ddsDataSize < (sizeof(DDS_HEADER) + sizeof(uint32_t) + sizeof(DDS_HEADER_DXT10)))
  1637. {
  1638. return E_FAIL;
  1639. }
  1640.  
  1641. bDXT10Header = true;
  1642. }
  1643.  
  1644. ptrdiff_t offset = sizeof(uint32_t)
  1645. + sizeof(DDS_HEADER)
  1646. + (bDXT10Header ? sizeof(DDS_HEADER_DXT10) : 0);
  1647.  
  1648. HRESULT hr = CreateTextureFromDDS( d3dDevice, d3dContext, header,
  1649. ddsData + offset, ddsDataSize - offset, maxsize,
  1650. usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB,
  1651. texture, textureView );
  1652. if (SUCCEEDED(hr))
  1653. {
  1654. if (texture != 0 && *texture != 0)
  1655. {
  1656. SetDebugObjectName( *texture, "DDSTextureLoader" );
  1657. }
  1658.  
  1659. if (textureView != 0 && *textureView != 0)
  1660. {
  1661. SetDebugObjectName( *textureView, "DDSTextureLoader" );
  1662. }
  1663.  
  1664. if (alphaMode)
  1665. *alphaMode = GetAlphaMode( header );
  1666. }
  1667.  
  1668. return hr;
  1669. }
  1670.  
  1671. //--------------------------------------------------------------------------------------
  1672. _Use_decl_annotations_
  1673. HRESULT DirectX::CreateDDSTextureFromFile(ID3D11Device *d3dDevice,
  1674. const wchar_t *fileName,
  1675. ID3D11Resource **texture,
  1676. ID3D11ShaderResourceView **textureView,
  1677. size_t maxsize,
  1678. DDS_ALPHA_MODE *alphaMode)
  1679. {
  1680. return CreateDDSTextureFromFileEx( d3dDevice, nullptr, fileName, maxsize,
  1681. D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, false,
  1682. texture, textureView, alphaMode );
  1683. }
  1684.  
  1685. _Use_decl_annotations_
  1686. HRESULT DirectX::CreateDDSTextureFromFile(ID3D11Device *d3dDevice,
  1687. ID3D11DeviceContext *d3dContext,
  1688. const wchar_t *fileName,
  1689. ID3D11Resource **texture,
  1690. ID3D11ShaderResourceView **textureView,
  1691. size_t maxsize,
  1692. DDS_ALPHA_MODE *alphaMode)
  1693. {
  1694. return CreateDDSTextureFromFileEx( d3dDevice, d3dContext, fileName, maxsize,
  1695. D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, false,
  1696. texture, textureView, alphaMode );
  1697. }
  1698.  
  1699. _Use_decl_annotations_
  1700. HRESULT DirectX::CreateDDSTextureFromFileEx(ID3D11Device *d3dDevice,
  1701. const wchar_t *fileName,
  1702. size_t maxsize,
  1703. D3D11_USAGE usage,
  1704. unsigned int bindFlags,
  1705. unsigned int cpuAccessFlags,
  1706. unsigned int miscFlags,
  1707. bool forceSRGB,
  1708. ID3D11Resource **texture,
  1709. ID3D11ShaderResourceView **textureView,
  1710. DDS_ALPHA_MODE *alphaMode)
  1711. {
  1712. return CreateDDSTextureFromFileEx( d3dDevice, nullptr, fileName, maxsize,
  1713. usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB,
  1714. texture, textureView, alphaMode );
  1715. }
  1716.  
  1717. _Use_decl_annotations_
  1718. HRESULT DirectX::CreateDDSTextureFromFileEx(ID3D11Device *d3dDevice,
  1719. ID3D11DeviceContext *d3dContext,
  1720. const wchar_t *fileName,
  1721. size_t maxsize,
  1722. D3D11_USAGE usage,
  1723. unsigned int bindFlags,
  1724. unsigned int cpuAccessFlags,
  1725. unsigned int miscFlags,
  1726. bool forceSRGB,
  1727. ID3D11Resource **texture,
  1728. ID3D11ShaderResourceView **textureView,
  1729. DDS_ALPHA_MODE *alphaMode)
  1730. {
  1731. if (texture)
  1732. {
  1733. *texture = nullptr;
  1734. }
  1735. if (textureView)
  1736. {
  1737. *textureView = nullptr;
  1738. }
  1739. if (alphaMode)
  1740. {
  1741. *alphaMode = DDS_ALPHA_MODE_UNKNOWN;
  1742. }
  1743.  
  1744. if (!d3dDevice || !fileName || (!texture && !textureView))
  1745. {
  1746. return E_INVALIDARG;
  1747. }
  1748.  
  1749. DDS_HEADER *header = nullptr;
  1750. uint8_t *bitData = nullptr;
  1751. size_t bitSize = 0;
  1752.  
  1753. std::unique_ptr<uint8_t[]> ddsData;
  1754. HRESULT hr = LoadTextureDataFromFile( fileName,
  1755. ddsData,
  1756. &header,
  1757. &bitData,
  1758. &bitSize
  1759. );
  1760. if (FAILED(hr))
  1761. {
  1762. return hr;
  1763. }
  1764.  
  1765. hr = CreateTextureFromDDS( d3dDevice, d3dContext, header,
  1766. bitData, bitSize, maxsize,
  1767. usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB,
  1768. texture, textureView );
  1769.  
  1770. if (SUCCEEDED(hr))
  1771. {
  1772. #if !defined(NO_D3D11_DEBUG_NAME) && ( defined(_DEBUG) || defined(PROFILE) )
  1773. if (texture != 0 || textureView != 0)
  1774. {
  1775. CHAR strFileA[MAX_PATH];
  1776. int result = WideCharToMultiByte( CP_ACP,
  1777. WC_NO_BEST_FIT_CHARS,
  1778. fileName,
  1779. -1,
  1780. strFileA,
  1781. MAX_PATH,
  1782. nullptr,
  1783. FALSE
  1784. );
  1785. if (result > 0)
  1786. {
  1787. const CHAR *pstrName = strrchr( strFileA, '\\' );
  1788. if (!pstrName)
  1789. {
  1790. pstrName = strFileA;
  1791. }
  1792. else
  1793. {
  1794. pstrName++;
  1795. }
  1796.  
  1797. if (texture != 0 && *texture != 0)
  1798. {
  1799. (*texture)->SetPrivateData( WKPDID_D3DDebugObjectName,
  1800. static_cast<UINT>( strnlen_s( pstrName, MAX_PATH ) ),
  1801. pstrName
  1802. );
  1803. }
  1804.  
  1805. if (textureView != 0 && *textureView != 0)
  1806. {
  1807. (*textureView)->SetPrivateData( WKPDID_D3DDebugObjectName,
  1808. static_cast<UINT>( strnlen_s( pstrName, MAX_PATH ) ),
  1809. pstrName
  1810. );
  1811. }
  1812. }
  1813. }
  1814. #endif
  1815.  
  1816. if (alphaMode)
  1817. *alphaMode = GetAlphaMode( header );
  1818. }
  1819.  
  1820. return hr;
  1821. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement