Source code of Windows XP (NT5)
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.

306 lines
8.3 KiB

  1. #ifndef __TEXTURE_HPP__
  2. #define __TEXTURE_HPP__
  3. /*==========================================================================;
  4. *
  5. * Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved.
  6. *
  7. * File: texture.h
  8. * Content: Base class for all texture objects. Texture management is
  9. * done at this level.
  10. *
  11. *
  12. ***************************************************************************/
  13. // The mip texture class has all of the functionality of the
  14. // the Base Object class along with some additional state for
  15. // managing LODs.
  16. #include <limits.h>
  17. #include "resource.hpp"
  18. #include "pixel.hpp"
  19. #define __INVALIDPALETTE USHRT_MAX
  20. class CBaseTexture : public IDirect3DBaseTexture8, public CResource
  21. {
  22. public:
  23. // Constructor
  24. CBaseTexture(
  25. CBaseDevice *pDevice,
  26. DWORD cLevels,
  27. D3DPOOL UserPool,
  28. D3DFORMAT UserFormat,
  29. REF_TYPE refType);
  30. // Function to convert a IDirect3DBaseTexture8 * to
  31. // a CBaseTexture *.
  32. static CBaseTexture *SafeCast(IDirect3DBaseTexture8 *pInterface);
  33. // Returns the format that the user passed in
  34. D3DFORMAT GetUserFormat() const
  35. {
  36. return m_formatUser;
  37. } // GetUserFormat
  38. BOOL IsPaletted() const
  39. {
  40. DXGASSERT(GetBufferDesc()->Format == GetUserFormat());
  41. return CPixel::IsPaletted(GetUserFormat());
  42. }
  43. // Returns the current palette
  44. DWORD GetPalette() const
  45. {
  46. DXGASSERT(GetBufferDesc()->Format == GetUserFormat());
  47. DXGASSERT(CPixel::IsPaletted(GetUserFormat()));
  48. return m_Palette;
  49. } // GetPalette
  50. // Set the current palette
  51. void SetPalette(DWORD Palette)
  52. {
  53. DXGASSERT(GetBufferDesc()->Format == GetUserFormat());
  54. #if DBG
  55. if(Palette != __INVALIDPALETTE)
  56. {
  57. DXGASSERT(CPixel::IsPaletted(GetUserFormat()));
  58. }
  59. #endif
  60. DXGASSERT(Palette <= USHRT_MAX);
  61. m_Palette = (WORD)Palette;
  62. } // SetPalette
  63. // Return current LOD
  64. DWORD GetLODI() const
  65. {
  66. return m_LOD;
  67. }
  68. // Sets current LOD (but doesn't actually do any work)
  69. DWORD SetLODI(DWORD LOD)
  70. {
  71. DXGASSERT(LOD <= UCHAR_MAX);
  72. DWORD oldLOD = m_LOD;
  73. m_LOD = (BYTE)LOD;
  74. return oldLOD;
  75. }
  76. // Method for UpdateTexture to call; does type-specific
  77. // parameter checking before calling UpdateDirtyPortion
  78. virtual HRESULT UpdateTexture(CBaseTexture *pTextureTarget) PURE;
  79. // Parameter validation method to make sure that no part of
  80. // the texture is locked.
  81. #ifdef DEBUG
  82. virtual BOOL IsTextureLocked() PURE;
  83. #endif // DEBUG
  84. #ifdef DEBUG
  85. // DPF helper for explaining why lock failed
  86. void ReportWhyLockFailed(void) const;
  87. #else // !DEBUG
  88. void ReportWhyLockFailed(void) const
  89. {
  90. // Do Nothing In Retail
  91. } // ReportWhyLockFailed
  92. #endif // !DEBUG
  93. protected:
  94. // Remember the format that the user passed in
  95. D3DFORMAT m_formatUser;
  96. // Currently all textures have a number of levels;
  97. // If that changes, then we should create a derived
  98. // class CMipTexture and move this data member there.
  99. BYTE m_cLevels;
  100. // Contains the current LOD for D3D managed textures
  101. BYTE m_LOD;
  102. // Currently set palette (valid only if format is paletted)
  103. WORD m_Palette;
  104. // Level Count accessor
  105. DWORD GetLevelCountImpl() const
  106. {
  107. return m_cLevels;
  108. }; // GetLevelCountImpl
  109. // Function to verify external parameters
  110. // to various texture create APIs
  111. static HRESULT Validate(CBaseDevice *pDevice,
  112. D3DRESOURCETYPE Type,
  113. D3DPOOL Pool,
  114. DWORD Usage,
  115. D3DFORMAT Format);
  116. // Infer usage flags based on external parameters
  117. // (All inferences MUST be device-independent.)
  118. static DWORD InferUsageFlags(D3DPOOL Pool,
  119. DWORD Usage,
  120. D3DFORMAT Format);
  121. // Helper to check if TexBlt is support on this
  122. // device for this texture
  123. BOOL CanTexBlt(CBaseTexture *pDestTexture) const;
  124. // Helper function to scale a Rect down by some
  125. // number of powers of two; useful for figuring out
  126. // what part of mip-sub-levels to copy
  127. static void ScaleRectDown(RECT *pRect, UINT PowersOfTwo = 1);
  128. // Box version for volumes
  129. static void ScaleBoxDown(D3DBOX *pBox, UINT PowersOfTwo = 1);
  130. // Compute Levels for the user
  131. static UINT ComputeLevels(UINT width, UINT height = 0, UINT depth = 0);
  132. // Common implementation for Set/Get LOD.
  133. DWORD SetLODImpl(DWORD LOD);
  134. DWORD GetLODImpl();
  135. private:
  136. // Textures overload this to call OnTextureDestroy on the
  137. // Device before calling Sync.
  138. virtual void OnDestroy(void);
  139. }; // class CBaseTexture
  140. #undef DPF_MODNAME
  141. #define DPF_MODNAME "CBaseTexture::CBaseTexture"
  142. // Inlines
  143. inline CBaseTexture::CBaseTexture(
  144. CBaseDevice *pDevice,
  145. DWORD cLevels,
  146. D3DPOOL UserPool,
  147. D3DFORMAT UserFormat,
  148. REF_TYPE refType)
  149. :
  150. CResource(pDevice, UserPool, refType),
  151. m_cLevels((BYTE)cLevels),
  152. m_Palette(__INVALIDPALETTE),
  153. m_formatUser(UserFormat)
  154. {
  155. DXGASSERT(cLevels > 0 && cLevels < 256);
  156. }; // CBaseTexture::CBaseTexture
  157. #undef DPF_MODNAME
  158. #define DPF_MODNAME "CBaseTexture::SafeCast"
  159. // Function to convert a IDirect3DBaseTexture8 * to
  160. // a CBaseTexture *. Classes that expose IDirect3DBaseTexture8
  161. // must list CBaseTexture FIRST and IDirect3DFoo8*
  162. // SECOND in their list of inheritances. (The Foo8 interface
  163. // must itself inherit from IDirect3DBaseTexture8*.
  164. inline CBaseTexture * CBaseTexture::SafeCast(IDirect3DBaseTexture8 *pInterface)
  165. {
  166. if (pInterface == NULL)
  167. return NULL;
  168. // Textures must by law obey certain layout rules. In
  169. // particular the CBaseTexture object must reside precisely
  170. // before the IDirect3DBaseTexture8 interface
  171. BYTE *pbInt = reinterpret_cast<BYTE *>(pInterface);
  172. CBaseTexture *pTex = reinterpret_cast<CBaseTexture *>(pbInt - sizeof(CBaseTexture));
  173. return pTex;
  174. } // CBaseTexture::SafeCast
  175. #undef DPF_MODNAME
  176. #define DPF_MODNAME "CBaseTexture::ScaleRectDown"
  177. // We round down on for left and top; and we round up for
  178. // right and bottom
  179. inline void CBaseTexture::ScaleRectDown(RECT *pRect, UINT PowersOfTwo)
  180. {
  181. DXGASSERT(PowersOfTwo > 0);
  182. DXGASSERT(PowersOfTwo < 32);
  183. DXGASSERT(pRect->right > 0);
  184. DXGASSERT(pRect->bottom > 0);
  185. DXGASSERT(pRect->left < pRect->right);
  186. DXGASSERT(pRect->top < pRect->bottom);
  187. DXGASSERT(pRect->left >= 0);
  188. DXGASSERT(pRect->top >= 0);
  189. // Rounding down is automatic with the shift operator
  190. pRect->left >>= PowersOfTwo;
  191. pRect->top >>= PowersOfTwo;
  192. if (pRect->right & ((1 << PowersOfTwo) - 1))
  193. {
  194. pRect->right >>= PowersOfTwo;
  195. pRect->right++;
  196. }
  197. else
  198. {
  199. pRect->right >>= PowersOfTwo;
  200. }
  201. if (pRect->bottom & ((1 << PowersOfTwo) - 1))
  202. {
  203. pRect->bottom >>= PowersOfTwo;
  204. pRect->bottom++;
  205. }
  206. else
  207. {
  208. pRect->bottom >>= PowersOfTwo;
  209. }
  210. return;
  211. } // CBaseTexture::ScaleRectDown
  212. #undef DPF_MODNAME
  213. #define DPF_MODNAME "CBaseTexture::ScaleBoxDown"
  214. inline void CBaseTexture::ScaleBoxDown(D3DBOX *pBox, UINT PowersOfTwo)
  215. {
  216. DXGASSERT(pBox);
  217. DXGASSERT(pBox->Front < pBox->Back);
  218. DXGASSERT(pBox->Back > 0);
  219. ScaleRectDown((RECT*)pBox, PowersOfTwo);
  220. // Rounding down is automatic with the shift operator
  221. pBox->Front >>= PowersOfTwo;
  222. if (pBox->Back & ((1 << PowersOfTwo) - 1))
  223. {
  224. pBox->Back >>= PowersOfTwo;
  225. pBox->Back++;
  226. }
  227. else
  228. {
  229. pBox->Back >>= PowersOfTwo;
  230. }
  231. } // CBaseTexture::ScaleBoxDown
  232. #undef DPF_MODNAME
  233. #define DPF_MODNAME "CBaseTexture::ComputeLevels"
  234. inline UINT CBaseTexture::ComputeLevels(UINT width,
  235. UINT height, // = 0,
  236. UINT depth // = 0
  237. )
  238. {
  239. UINT maxEdge = max(width, height);
  240. maxEdge = max(maxEdge, depth);
  241. UINT cLevels = 0;
  242. while (maxEdge)
  243. {
  244. cLevels++;
  245. // D3D rule is that sizes round down always
  246. maxEdge >>= 1;
  247. }
  248. return cLevels;
  249. } // CBaseTexture::ComputeLevels
  250. #endif // __TEXTURE_HPP__