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.

317 lines
11 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1997 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: drawprim.hpp
  6. * Content: DrawPrimitive common defines
  7. *
  8. ***************************************************************************/
  9. #ifndef _DRAWPRIM_H_
  10. #define _DRAWPRIM_H_
  11. #define MAX_DX6_PRIMCOUNT D3DMAXNUMPRIMITIVES
  12. #define MAX_DX6_VERTICES D3DMAXNUMVERTICES
  13. #ifdef WIN95
  14. #define LOWVERTICESNUMBER 128
  15. #else
  16. #define LOWVERTICESNUMBER 96
  17. #endif
  18. #define D3D_MAX_TLVBUF_CHANGES 5
  19. extern HRESULT DoDrawPrimitive(LPD3DFE_PROCESSVERTICES pv);
  20. extern HRESULT DoDrawIndexedPrimitive(LPD3DFE_PROCESSVERTICES pv);
  21. extern HRESULT CheckDrawPrimitive(LPDIRECT3DDEVICEI lpDevI);
  22. extern HRESULT CheckDrawIndexedPrimitive(LPDIRECT3DDEVICEI lpDevI, DWORD dwStartVertex = 0);
  23. // All vertices from lpDevI->lpVout are copied to the output buffer, expanding
  24. // to D3DTLVERTEX.
  25. // The output buffer is lpAddress if it is not NULL, otherwise it is TLVbuf
  26. //
  27. //---------------------------------------------------------------------
  28. #define FVF_TRANSFORMED(dwFVF) ((dwFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)
  29. #define FVF_DRIVERSUPPORTED(lpDevI) (lpDevI->dwDeviceFlags & D3DDEV_FVF)
  30. #define FVF_TEXCOORD_NUMBER(dwFVF) \
  31. (((dwFVF) & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT)
  32. //----------------------------------------------------------------------
  33. inline DWORD MakeTexTransformFuncIndex(DWORD dwNumInpTexCoord, DWORD dwNumOutTexCoord)
  34. {
  35. DDASSERT(dwNumInpTexCoord <= 4 && dwNumOutTexCoord <= 4);
  36. return (dwNumInpTexCoord - 1) + ((dwNumOutTexCoord - 1) << 2);
  37. }
  38. //---------------------------------------------------------------------
  39. // The function should not be called by ProcessVertices!!!
  40. //
  41. // Computes nOutTexCoord, dwTextureCoordSizeTotal, dwTextureCoordSize and
  42. // dwTextureIndexToCopy in case when a pre-DX6 driver is used.
  43. //
  44. void ComputeTCI2CopyLegacy(LPDIRECT3DDEVICEI lpDevI,
  45. DWORD dwNumInpTexCoord,
  46. DWORD* pdwInpTexCoordSize,
  47. BOOL bVertexTransformed);
  48. //---------------------------------------------------------------------
  49. // Computes size in bytes of the position component of a vertex
  50. //
  51. __inline DWORD GetPositionSizeFVF(DWORD fvf)
  52. {
  53. DWORD size = 3 << 2;
  54. switch (fvf & D3DFVF_POSITION_MASK)
  55. {
  56. case D3DFVF_XYZRHW: size += 4; break;
  57. case D3DFVF_XYZB1: size += 1*4; break;
  58. case D3DFVF_XYZB2: size += 2*4; break;
  59. case D3DFVF_XYZB3: size += 3*4; break;
  60. case D3DFVF_XYZB4: size += 4*4; break;
  61. case D3DFVF_XYZB5: size += 5*4; break;
  62. }
  63. return size;
  64. }
  65. //---------------------------------------------------------------------
  66. // Computes vertex size in bytes for a the vertex ID excluding size of
  67. // texture oordinates
  68. //
  69. __inline DWORD GetVertexSizeFVF(DWORD fvf)
  70. {
  71. DWORD size = GetPositionSizeFVF(fvf);
  72. if (fvf & D3DFVF_NORMAL)
  73. size += 3*4;
  74. if (fvf & D3DFVF_RESERVED1)
  75. size += 4;
  76. if (fvf & D3DFVF_DIFFUSE)
  77. size+= 4;
  78. if (fvf & D3DFVF_SPECULAR)
  79. size += 4;
  80. return size;
  81. }
  82. //---------------------------------------------------------------------
  83. // Entry is texture count. Clears all texture format bits in the FVF DWORD,
  84. // that correspond to the texture count
  85. // for this count
  86. const DWORD g_TextureFormatMask[9] = {
  87. ~0x0000FFFF,
  88. ~0x0003FFFF,
  89. ~0x000FFFFF,
  90. ~0x003FFFFF,
  91. ~0x00FFFFFF,
  92. ~0x03FFFFFF,
  93. ~0x0FFFFFFF,
  94. ~0x3FFFFFFF,
  95. ~0xFFFFFFFF
  96. };
  97. //---------------------------------------------------------------------
  98. // Computes vertex size in bytes from the vertex ID
  99. //
  100. // Texture formats size 00 01 10 11
  101. const BYTE g_TextureSize[4] = {2*4, 3*4, 4*4, 4};
  102. //---------------------------------------------------------------------
  103. // Index is number of floats in a texture coordinate set.
  104. // Value is texture format bits
  105. //
  106. const DWORD g_dwTextureFormat[5] = {0, 3, 0, 1, 2};
  107. //---------------------------------------------------------------------
  108. // Returns total size of texture coordinates
  109. // Computes dwTextureCoordSize[] array - size of every texture coordinate set
  110. //
  111. inline DWORD ComputeTextureCoordSize(DWORD dwFVF, DWORD *dwTextureCoordSize)
  112. {
  113. DWORD dwNumTexCoord = FVF_TEXCOORD_NUMBER(dwFVF);
  114. DWORD dwTextureCoordSizeTotal;
  115. // Compute texture coordinate size
  116. DWORD dwTextureFormats = dwFVF >> 16;
  117. if (dwTextureFormats == 0)
  118. {
  119. dwTextureCoordSizeTotal = (BYTE)dwNumTexCoord * 2 * 4;
  120. for (DWORD i=0; i < dwNumTexCoord; i++)
  121. {
  122. dwTextureCoordSize[i] = 4*2;
  123. }
  124. }
  125. else
  126. {
  127. DWORD dwOffset = 0;
  128. dwTextureCoordSizeTotal = 0;
  129. for (DWORD i=0; i < dwNumTexCoord; i++)
  130. {
  131. BYTE dwSize = g_TextureSize[dwTextureFormats & 3];
  132. dwTextureCoordSize[i] = dwSize;
  133. dwTextureCoordSizeTotal += dwSize;
  134. dwTextureFormats >>= 2;
  135. }
  136. }
  137. return dwTextureCoordSizeTotal;
  138. }
  139. //---------------------------------------------------------------------
  140. #undef DPF_MODNAME
  141. #define DPF_MODNAME "CheckDeviceSettings"
  142. inline HRESULT CheckDeviceSettings(LPDIRECT3DDEVICEI lpDevI)
  143. {
  144. #if DBG
  145. if (!(lpDevI->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INSCENE))
  146. {
  147. D3D_ERR( "Not in scene" );
  148. return D3DERR_SCENE_NOT_IN_SCENE;
  149. }
  150. #endif
  151. return D3D_OK;
  152. }
  153. //---------------------------------------------------------------------
  154. // Computes the number of primtives and also updates the stats accordingly
  155. // Input: lpDevI->primType
  156. // dwNumVertices
  157. // Output: lpDevI->dwNumPrimitives
  158. // return value = dwNumPrimitives
  159. #undef DPF_MODNAME
  160. #define DPF_MODNAME "GetNumPrim"
  161. inline __declspec(nothrow) void GetNumPrim(LPDIRECT3DDEVICEI lpDevI, DWORD dwNumVertices)
  162. {
  163. lpDevI->dwNumPrimitives = 0;
  164. switch (lpDevI->primType)
  165. {
  166. case D3DPT_POINTLIST:
  167. lpDevI->dwNumPrimitives = dwNumVertices;
  168. break;
  169. case D3DPT_LINELIST:
  170. lpDevI->dwNumPrimitives = dwNumVertices >> 1;
  171. break;
  172. case D3DPT_LINESTRIP:
  173. if (dwNumVertices < 2)
  174. return;
  175. lpDevI->dwNumPrimitives = dwNumVertices - 1;
  176. break;
  177. case D3DPT_TRIANGLEFAN:
  178. case D3DPT_TRIANGLESTRIP:
  179. if (dwNumVertices < 3)
  180. return;
  181. lpDevI->dwNumPrimitives = dwNumVertices - 2;
  182. break;
  183. case D3DPT_TRIANGLELIST:
  184. #ifdef _X86_
  185. {
  186. DWORD tmp;
  187. __asm
  188. {
  189. mov eax, 0x55555555 // fractional part of 1.0/3.0
  190. mul dwNumVertices
  191. add eax, 0x80000000 // Rounding
  192. adc edx, 0
  193. mov tmp, edx
  194. }
  195. lpDevI->dwNumPrimitives = tmp;
  196. }
  197. #else
  198. lpDevI->dwNumPrimitives = dwNumVertices / 3;
  199. #endif
  200. break;
  201. }
  202. }
  203. //---------------------------------------------------------------------
  204. // Sets front-end flags every time fog state is changed
  205. //
  206. inline void DIRECT3DDEVICEI::SetFogFlags(void)
  207. {
  208. // Call ForceFVFRecompute only if fog enable state has been changed
  209. BOOL bFogWasEnabled = this->dwDeviceFlags & D3DDEV_FOG;
  210. if (this->lighting.fog_mode != D3DFOG_NONE &&
  211. this->rstates[D3DRENDERSTATE_FOGENABLE])
  212. {
  213. this->dwDeviceFlags |= D3DDEV_FOG;
  214. if (!bFogWasEnabled)
  215. ForceFVFRecompute();
  216. }
  217. else
  218. {
  219. this->dwDeviceFlags &= ~D3DDEV_FOG;
  220. if (bFogWasEnabled)
  221. ForceFVFRecompute();
  222. }
  223. }
  224. //---------------------------------------------------------------------
  225. // Validates DrawPrimitive flags
  226. //
  227. inline BOOL IsDPFlagsValid(DWORD dwFlags)
  228. {
  229. if (dwFlags & ~(D3DDP_WAIT))
  230. {
  231. D3D_ERR( "Invalid bit set in DrawPrimitive flags" );
  232. return FALSE;
  233. }
  234. return TRUE;
  235. }
  236. //---------------------------------------------------------------------
  237. // Restore indices in the texture stages which were re-mapped for texture
  238. // transforms
  239. // We have to do restore if
  240. // - Set or Get render state is issued with _WRAP parameter
  241. // - Set or Get texture stage is issued with TEXCOORDINDEX as a parameter
  242. //
  243. inline void RestoreTextureStages(LPDIRECT3DDEVICEI pDevI)
  244. {
  245. // dwVIDIn is used to force re-compute FVF in the
  246. // SetTextureStageState. so we save and restore it.
  247. DWORD dwVIDInSaved = pDevI->dwVIDIn;
  248. pDevI->dwDeviceFlags &= ~D3DDEV_REMAPTEXTUREINDICES;
  249. for (DWORD i=0; i < pDevI->dwNumTextureStages; i++)
  250. {
  251. LPD3DFE_TEXTURESTAGE pStage = &pDevI->textureStage[i];
  252. // Texture generation mode was stripped out of pStage->dwInpCoordIndex
  253. DWORD dwInpIndex = pStage->dwInpCoordIndex + pStage->dwTexGenMode;
  254. if (dwInpIndex != pStage->dwOutCoordIndex)
  255. {
  256. // We do not call UpdateInternalTextureStageState because it
  257. // will call ForceRecomputeFVF and we do not want this.
  258. pDevI->tsstates[pStage->dwOrgStage][D3DTSS_TEXCOORDINDEX] = dwInpIndex;
  259. // Filter texgen modes for DX6 drivers
  260. if (!IS_TLHAL_DEVICE(pDevI) && dwInpIndex > 7)
  261. continue;
  262. CDirect3DDeviceIDP2 *pDevDP2 = static_cast<CDirect3DDeviceIDP2*>(pDevI);
  263. pDevDP2->SetTSSI(pStage->dwOrgStage, D3DTSS_TEXCOORDINDEX, dwInpIndex);
  264. }
  265. DWORD dwState = D3DRENDERSTATE_WRAP0 + pStage->dwOutCoordIndex;
  266. if (pStage->dwOrgWrapMode != pDevI->rstates[dwState])
  267. {
  268. // We do not call UpdateInternaState because it
  269. // will call ForceRecomputeFVF and we do not want this.
  270. pDevI->rstates[dwState] = pStage->dwOrgWrapMode;
  271. pDevI->SetRenderStateI((D3DRENDERSTATETYPE)dwState, pStage->dwOrgWrapMode);
  272. }
  273. }
  274. pDevI->dwVIDIn = dwVIDInSaved;
  275. }
  276. //---------------------------------------------------------------------
  277. // the function works when there are texture transforms.
  278. // It computes number of output texture coordinates, texture coordinate size and format.
  279. // It prepares texture stages to re-map texture coordinates
  280. //
  281. HRESULT EvalTextureTransforms(LPDIRECT3DDEVICEI pDevI, DWORD dwTexTransform,
  282. DWORD *pdwOutTextureSize, DWORD *pdwOutTextureFormat);
  283. //----------------------------------------------------------------------
  284. // Sets texture transform pointer for every input texture coordinate set
  285. //
  286. void SetupTextureTransforms(LPDIRECT3DDEVICEI pDevI);
  287. //----------------------------------------------------------------------
  288. inline BOOL TextureTransformEnabled(LPDIRECT3DDEVICEI pDevI)
  289. {
  290. return __TEXTURETRANSFORMENABLED(pDevI);
  291. }
  292. //---------------------------------------------------------------------
  293. inline void ComputeOutputVertexOffsets(LPD3DFE_PROCESSVERTICES pv)
  294. {
  295. DWORD i = 4*sizeof(D3DVALUE);
  296. pv->diffuseOffsetOut = i;
  297. if (pv->dwVIDOut & D3DFVF_DIFFUSE)
  298. i += sizeof(DWORD);
  299. pv->specularOffsetOut = i;
  300. if (pv->dwVIDOut & D3DFVF_SPECULAR)
  301. i += sizeof(DWORD);
  302. pv->texOffsetOut = i;
  303. }
  304. #endif _DRAWPRIM_H_