Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

547 lines
16 KiB

  1. #ifndef __PIXEL_HPP__
  2. #define __PIXEL_HPP__
  3. /*==========================================================================;
  4. *
  5. * Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved.
  6. *
  7. * File: pixel.hpp
  8. * Content: Utility class for working with pixel formats
  9. *
  10. *
  11. ***************************************************************************/
  12. // includes
  13. #include "d3dobj.hpp"
  14. struct IHVFormatInfo
  15. {
  16. D3DFORMAT m_Format;
  17. DWORD m_BPP;
  18. IHVFormatInfo *m_pNext;
  19. };
  20. // This is a utility class that implements useful helpers for
  21. // allocating and accessing various pixel formats. All methods
  22. // are static and hence should be accessed as follows:
  23. // e.g. CPixel::LockOffset(...)
  24. //
  25. class CPixel
  26. {
  27. public:
  28. // Allocate helpers
  29. // Determine the amount of memory that is needed to
  30. // allocate various things..
  31. static UINT ComputeSurfaceSize(UINT cpWidth,
  32. UINT cpHeight,
  33. D3DFORMAT Format);
  34. static UINT ComputeVolumeSize(UINT cpWidth,
  35. UINT cpHeight,
  36. UINT cpDepth,
  37. D3DFORMAT Format);
  38. static UINT ComputeMipMapSize(UINT cpWidth,
  39. UINT cpHeight,
  40. UINT cLevels,
  41. D3DFORMAT Format);
  42. static UINT ComputeMipVolumeSize(UINT cpWidth,
  43. UINT cpHeight,
  44. UINT cpDepth,
  45. UINT cLevels,
  46. D3DFORMAT Format);
  47. // Lock helpers
  48. // Given a surface desc, a level, and pointer to
  49. // bits (pBits in the LockedRectData) and a sub-rect,
  50. // this will fill in the pLockedRectData structure
  51. static void ComputeMipMapOffset(const D3DSURFACE_DESC *pDescTopLevel,
  52. UINT iLevel,
  53. BYTE *pBits,
  54. CONST RECT *pRect,
  55. D3DLOCKED_RECT *pLockedRectData);
  56. // MipVolume version of ComputeMipMapOffset
  57. static void ComputeMipVolumeOffset(const D3DVOLUME_DESC *pDescTopLevel,
  58. UINT iLevel,
  59. BYTE *pBits,
  60. CONST D3DBOX *pBox,
  61. D3DLOCKED_BOX *pLockedBoxData);
  62. // Surface version of ComputeMipMapOffset
  63. static void ComputeSurfaceOffset(const D3DSURFACE_DESC *pDesc,
  64. BYTE *pBits,
  65. CONST RECT *pRect,
  66. D3DLOCKED_RECT *pLockedRectData);
  67. // Is this a supported format?
  68. static BOOL IsSupported(D3DRESOURCETYPE Type, D3DFORMAT Format);
  69. // Is this a IHV non-standard format? i.e. do
  70. // we know the number of bytes per pixel?
  71. static BOOL IsIHVFormat(D3DFORMAT Format);
  72. // Is this a Z format that the user can create?
  73. static BOOL IsEnumeratableZ (D3DFORMAT Format);
  74. // Is this a Z format that needs mapping b4 sending
  75. // to the driver?
  76. static BOOL IsMappedDepthFormat(D3DFORMAT Format);
  77. // All depth formats other than D16 are currently
  78. // defined to be non-lockable. This function will
  79. // return FALSE for:
  80. // non-Z formats
  81. // D16_LOCKABLE
  82. // IHV formats
  83. static BOOL IsNonLockableZ(D3DFORMAT Format);
  84. // Pixel Stride will return negative for DXT formats
  85. // Call AdjustForDXT to work with things at the block level
  86. static UINT ComputePixelStride(D3DFORMAT Format);
  87. // This will adjust cbPixel
  88. // to pixels per block; and width and height will
  89. // be adjusted to pixels. Assumes the IsDXT(cbPixel).
  90. static void AdjustForDXT(UINT *pcpWidth,
  91. UINT *pcpHeight,
  92. UINT *pcbPixel);
  93. // Adjust parameters for VolumeDXT
  94. static void AdjustForVolumeDXT(UINT *pcpWidth,
  95. UINT *pcpHeight,
  96. UINT *pcpDepth,
  97. UINT *pcbPixel);
  98. // returns TRUE if cbPixel is "negative" i.e. DXT/V group
  99. static BOOL IsDXT(UINT cbPixel);
  100. // returns TRUE if format is one of the DXT/V group
  101. static BOOL IsDXT(D3DFORMAT Format);
  102. // returns TRUE if format is one of the DXV family
  103. static BOOL IsVolumeDXT(D3DFORMAT Format);
  104. // returns TRUE if format has stencil bits
  105. static BOOL HasStencilBits(D3DFORMAT Format);
  106. // returns TRUE if format is paletted
  107. static BOOL IsPaletted(D3DFORMAT Format);
  108. // Helpers for validation for DXTs.
  109. static BOOL IsValidRect(D3DFORMAT Format,
  110. UINT Width,
  111. UINT Height,
  112. const RECT *pRect);
  113. static BOOL IsValidBox(D3DFORMAT Format,
  114. UINT Width,
  115. UINT Height,
  116. UINT Depth,
  117. const D3DBOX *pBox);
  118. // Needs 4x4 Rules (DXT/DXVs)
  119. static BOOL Requires4X4(D3DFORMAT Format);
  120. // Detection for "real" FourCC formats
  121. static BOOL IsFourCC(D3DFORMAT Format);
  122. static D3DFORMAT SuppressAlphaChannel(D3DFORMAT Format);
  123. static UINT BytesPerPixel(D3DFORMAT Format);
  124. // Register format for later lookup
  125. static HRESULT Register(D3DFORMAT Format, DWORD BPP);
  126. // Cleanup registry
  127. static void Cleanup();
  128. private:
  129. // Internal functions
  130. static UINT ComputeSurfaceStride(UINT cpWidth, UINT cbPixel);
  131. static UINT ComputeSurfaceSize(UINT cpWidth,
  132. UINT cpHeight,
  133. UINT cbPixel);
  134. static IHVFormatInfo *m_pFormatList;
  135. }; // CPixel
  136. #undef DPF_MODNAME
  137. #define DPF_MODNAME "CPixel::IsIHVFormat"
  138. inline BOOL CPixel::IsIHVFormat(D3DFORMAT Format)
  139. {
  140. // If we know the number of bytes per
  141. // pixel; it's a non-IHV format
  142. if (BytesPerPixel(Format) != 0)
  143. return FALSE;
  144. // Must be an IHV format
  145. return TRUE;
  146. } // IsIHVFormat
  147. #undef DPF_MODNAME
  148. #define DPF_MODNAME "CPixel::ComputeSurfaceOffset"
  149. inline void CPixel::ComputeSurfaceOffset(const D3DSURFACE_DESC *pDesc,
  150. BYTE *pBits,
  151. CONST RECT *pRect,
  152. D3DLOCKED_RECT *pLockedRectData)
  153. {
  154. ComputeMipMapOffset(pDesc, 0, pBits, pRect, pLockedRectData);
  155. } // ComputeSurfaceOffset
  156. #undef DPF_MODNAME
  157. #define DPF_MODNAME "CPixel::ComputeSurfaceSize"
  158. inline UINT CPixel::ComputeSurfaceSize(UINT cpWidth,
  159. UINT cpHeight,
  160. D3DFORMAT Format)
  161. {
  162. UINT cbPixel = ComputePixelStride(Format);
  163. // Adjust pixel->block if necessary
  164. BOOL isDXT = IsDXT(cbPixel);
  165. if (isDXT)
  166. {
  167. AdjustForDXT(&cpWidth, &cpHeight, &cbPixel);
  168. }
  169. return ComputeSurfaceSize(cpWidth,
  170. cpHeight,
  171. cbPixel);
  172. } // ComputeSurfaceSize
  173. #undef DPF_MODNAME
  174. #define DPF_MODNAME "CPixel::AdjustForDXT"
  175. inline void CPixel::AdjustForDXT(UINT *pcpWidth,
  176. UINT *pcpHeight,
  177. UINT *pcbPixel)
  178. {
  179. DXGASSERT(pcbPixel);
  180. DXGASSERT(pcpWidth);
  181. DXGASSERT(pcpHeight);
  182. DXGASSERT(IsDXT(*pcbPixel));
  183. // Adjust width and height for DXT formats to be in blocks
  184. // instead of pixels. Blocks are 4x4 pixels.
  185. *pcpWidth = (*pcpWidth + 3) / 4;
  186. *pcpHeight = (*pcpHeight + 3) / 4;
  187. // Negate the pcbPixel to determine bytes per block
  188. *pcbPixel *= -1;
  189. // We only know of two DXT formats right now...
  190. DXGASSERT(*pcbPixel == 8 || *pcbPixel == 16);
  191. } // CPixel::AdjustForDXT
  192. #undef DPF_MODNAME
  193. #define DPF_MODNAME "CPixel::AdjustForVolumeDXT"
  194. inline void CPixel::AdjustForVolumeDXT(UINT *pcpWidth,
  195. UINT *pcpHeight,
  196. UINT *pcpDepth,
  197. UINT *pcbPixel)
  198. {
  199. DXGASSERT(pcbPixel);
  200. DXGASSERT(pcpWidth);
  201. DXGASSERT(pcpHeight);
  202. DXGASSERT(IsDXT(*pcbPixel));
  203. // Adjust width, height, depth for DXT formats to be in blocks
  204. // instead of pixels. Blocks are 4x4x4 pixels.
  205. *pcpWidth = (*pcpWidth + 3) / 4;
  206. *pcpHeight = (*pcpHeight + 3) / 4;
  207. *pcpDepth = (*pcpDepth + 3) / 4;
  208. // Negate the pcbPixel to determine bytes per block
  209. *pcbPixel *= -1;
  210. // We only know of two DXV formats right now...
  211. DXGASSERT(*pcbPixel == 32 || *pcbPixel == 64);
  212. } // CPixel::AdjustForVolumeDXT
  213. #undef DPF_MODNAME
  214. #define DPF_MODNAME "CPixel::ComputeVolumeSize"
  215. inline UINT CPixel::ComputeVolumeSize(UINT cpWidth,
  216. UINT cpHeight,
  217. UINT cpDepth,
  218. D3DFORMAT Format)
  219. {
  220. UINT cbPixel = ComputePixelStride(Format);
  221. if (IsDXT(cbPixel))
  222. {
  223. if (IsVolumeDXT(Format))
  224. {
  225. AdjustForVolumeDXT(&cpWidth, &cpHeight, &cpDepth, &cbPixel);
  226. }
  227. else
  228. {
  229. AdjustForDXT(&cpWidth, &cpHeight, &cbPixel);
  230. }
  231. }
  232. return cpDepth * ComputeSurfaceSize(cpWidth, cpHeight, cbPixel);
  233. } // ComputeVolumeSize
  234. #undef DPF_MODNAME
  235. #define DPF_MODNAME "CPixel::IsSupported"
  236. inline BOOL CPixel::IsSupported(D3DRESOURCETYPE Type, D3DFORMAT Format)
  237. {
  238. UINT cbPixel = ComputePixelStride(Format);
  239. if (cbPixel == 0)
  240. {
  241. return FALSE;
  242. }
  243. else if (IsVolumeDXT(Format))
  244. {
  245. if (Type == D3DRTYPE_VOLUMETEXTURE)
  246. return TRUE;
  247. else
  248. return FALSE;
  249. }
  250. else
  251. {
  252. return TRUE;
  253. }
  254. } // IsSupported
  255. #undef DPF_MODNAME
  256. #define DPF_MODNAME "CPixel::IsDXT(cbPixel)"
  257. // returns TRUE if cbPixel is "negative"
  258. inline BOOL CPixel::IsDXT(UINT cbPixel)
  259. {
  260. if (((INT)cbPixel) < 0)
  261. return TRUE;
  262. else
  263. return FALSE;
  264. } // IsDXT
  265. #undef DPF_MODNAME
  266. #define DPF_MODNAME "CPixel::IsDXT(format)"
  267. // returns TRUE if this is a linear format
  268. // i.e. DXT or DXV
  269. inline BOOL CPixel::IsDXT(D3DFORMAT Format)
  270. {
  271. // CONSIDER: This is a duplication of Requires4x4 function
  272. switch (Format)
  273. {
  274. // normal DXTs
  275. case D3DFMT_DXT1:
  276. case D3DFMT_DXT2:
  277. case D3DFMT_DXT3:
  278. case D3DFMT_DXT4:
  279. case D3DFMT_DXT5:
  280. #ifdef VOLUME_DXT
  281. // Volume dxts
  282. case D3DFMT_DXV1:
  283. case D3DFMT_DXV2:
  284. case D3DFMT_DXV3:
  285. case D3DFMT_DXV4:
  286. case D3DFMT_DXV5:
  287. #endif //VOLUME_DXT
  288. return TRUE;
  289. }
  290. return FALSE;
  291. } // IsDXT
  292. #undef DPF_MODNAME
  293. #define DPF_MODNAME "CPixel::Requires4X4"
  294. // returns TRUE for formats that have 4x4 rules
  295. inline BOOL CPixel::Requires4X4(D3DFORMAT Format)
  296. {
  297. switch (Format)
  298. {
  299. // normal DXTs
  300. case D3DFMT_DXT1:
  301. case D3DFMT_DXT2:
  302. case D3DFMT_DXT3:
  303. case D3DFMT_DXT4:
  304. case D3DFMT_DXT5:
  305. #ifdef VOLUME_DXT
  306. // Volume dxts
  307. case D3DFMT_DXV1:
  308. case D3DFMT_DXV2:
  309. case D3DFMT_DXV3:
  310. case D3DFMT_DXV4:
  311. case D3DFMT_DXV5:
  312. #endif //VOLUME_DXT
  313. return TRUE;
  314. }
  315. return FALSE;
  316. } // Requires4X4
  317. #undef DPF_MODNAME
  318. #define DPF_MODNAME "CPixel::HasStencilBits"
  319. // returns TRUE if format has stencil bits
  320. inline BOOL CPixel::HasStencilBits(D3DFORMAT Format)
  321. {
  322. switch (Format)
  323. {
  324. case D3DFMT_S1D15:
  325. case D3DFMT_D15S1:
  326. case D3DFMT_S8D24:
  327. case D3DFMT_D24S8:
  328. case D3DFMT_X4S4D24:
  329. case D3DFMT_D24X4S4:
  330. return TRUE;
  331. }
  332. return FALSE;
  333. } // HasStencilBits
  334. #undef DPF_MODNAME
  335. #define DPF_MODNAME "CPixel::IsVolumeDXT"
  336. // returns TRUE if format is one of the DXTV family
  337. inline BOOL CPixel::IsVolumeDXT(D3DFORMAT Format)
  338. {
  339. #ifdef VOLUME_DXT
  340. if (Format >= D3DFMT_DXV1 && Format <= D3DFMT_DXV5)
  341. return TRUE;
  342. else
  343. #endif //VOLUME_DXT
  344. return FALSE;
  345. } // IsVolumeDXT
  346. #undef DPF_MODNAME
  347. #define DPF_MODNAME "CPixel::IsPaletted"
  348. // returns TRUE if Format is paletted
  349. inline BOOL CPixel::IsPaletted(D3DFORMAT Format)
  350. {
  351. return (Format == D3DFMT_P8) || (Format == D3DFMT_A8P8);
  352. } // IsPaletted
  353. #undef DPF_MODNAME
  354. #define DPF_MODNAME "CPixel::IsFourCC"
  355. // returns TRUE if Format is a FourCC
  356. inline BOOL CPixel::IsFourCC(D3DFORMAT Format)
  357. {
  358. DWORD dwFormat = (DWORD)Format;
  359. if (HIBYTE(LOWORD(dwFormat)) != 0)
  360. {
  361. // FourCC formats are non-zero for in their
  362. // third byte.
  363. return TRUE;
  364. }
  365. else
  366. {
  367. return FALSE;
  368. }
  369. } // IsFourCC
  370. #undef DPF_MODNAME
  371. #define DPF_MODNAME "CPixel::IsEnumeratableZ"
  372. // IsEnumeratableZ
  373. //
  374. // We only want to enumerate D16 and the Z formats. We have to know
  375. // about the others so we have to keep them in our list, but we added this
  376. // function so we'd never enumerate them to the app.
  377. inline BOOL CPixel::IsEnumeratableZ (D3DFORMAT Format)
  378. {
  379. if ((Format == D3DFMT_D16) ||
  380. (Format == D3DFMT_D16_LOCKABLE) ||
  381. (Format == D3DFMT_D15S1) ||
  382. (Format == D3DFMT_D24X8) ||
  383. (Format == D3DFMT_D24X4S4) ||
  384. (Format == D3DFMT_D24S8) ||
  385. (Format == D3DFMT_D32))
  386. {
  387. return TRUE;
  388. }
  389. // IHV formats are creatable; so we let them pass
  390. if (IsIHVFormat(Format))
  391. {
  392. return TRUE;
  393. }
  394. return FALSE;
  395. } // IsEnumeratableZ
  396. #undef DPF_MODNAME
  397. #define DPF_MODNAME "CPixel::IsMappedDepthFormat"
  398. // Is this a Z format that needs mapping b4 sending
  399. // to the driver?
  400. inline BOOL CPixel::IsMappedDepthFormat(D3DFORMAT Format)
  401. {
  402. // D16_LOCKABLE and D32 do not need
  403. // mapping
  404. if ((Format == D3DFMT_D16) ||
  405. (Format == D3DFMT_D15S1) ||
  406. (Format == D3DFMT_D24X4S4) ||
  407. (Format == D3DFMT_D24X8) ||
  408. (Format == D3DFMT_D24S8))
  409. {
  410. return TRUE;
  411. }
  412. return FALSE;
  413. } // IsMappedDepthFormat
  414. #undef DPF_MODNAME
  415. #define DPF_MODNAME "CPixel::IsNonLockableZ"
  416. // All depth formats other than D16 are currently
  417. // defined to be non-lockable. This function will
  418. // return FALSE for:
  419. // non-Z formats
  420. // D16_LOCKABLE
  421. // IHV formats
  422. inline BOOL CPixel::IsNonLockableZ(D3DFORMAT Format)
  423. {
  424. if ((Format == D3DFMT_D16) ||
  425. (Format == D3DFMT_D15S1) ||
  426. (Format == D3DFMT_D24X8) ||
  427. (Format == D3DFMT_D24S8) ||
  428. (Format == D3DFMT_D24X4S4) ||
  429. (Format == D3DFMT_D32))
  430. {
  431. return TRUE;
  432. }
  433. // D16_LOCKABLE is lockable; and other
  434. // formats are either lockable i.e. IHV or
  435. // are not a Z format.
  436. return FALSE;
  437. } // IsNonLockableZ
  438. #endif // __PIXEL_HPP__