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.

393 lines
15 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1997 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: dpclip.c
  6. * Content: DrawPrimitive clipper
  7. *
  8. ***************************************************************************/
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. #include "clipfunc.h"
  12. #include "drawprim.hpp"
  13. //---------------------------------------------------------------------
  14. inline HRESULT DRAW_PRIM(D3DFE_PROCESSVERTICES *pv,
  15. D3DPRIMITIVETYPE primitiveType,
  16. LPVOID startVertex, DWORD vertexCount, DWORD numPrim)
  17. {
  18. pv->lpvOut = startVertex;
  19. pv->primType = primitiveType;
  20. pv->dwNumVertices = vertexCount;
  21. pv->dwNumPrimitives = numPrim;
  22. // PSGP implementation should not implement INSIDEEXECUTE should do
  23. // ret = pv->DrawPrim(); !!!
  24. HRESULT ret = (((LPDIRECT3DDEVICEI)pv)->*(((LPDIRECT3DDEVICEI)pv)->pfnDrawPrim))();
  25. return ret;
  26. }
  27. //---------------------------------------------------------------------
  28. inline HRESULT DRAW_INDEX_PRIM(D3DFE_PROCESSVERTICES *pv,
  29. D3DPRIMITIVETYPE primitiveType,
  30. LPWORD startIndex, DWORD vertexCount, DWORD numPrim)
  31. {
  32. pv->lpwIndices = startIndex;
  33. pv->primType = primitiveType;
  34. pv->dwNumIndices = vertexCount;
  35. pv->dwNumPrimitives = numPrim;
  36. // PSGP implementation should not implement INSIDEEXECUTE. It should do
  37. // ret = pv->DrawIndexPrim(); !!!
  38. HRESULT ret = (((LPDIRECT3DDEVICEI)pv)->*(((LPDIRECT3DDEVICEI)pv)->pfnDrawIndexedPrim))();
  39. return ret;
  40. }
  41. //----------------------------------------------------------------------
  42. __inline HRESULT Clip(D3DFE_PROCESSVERTICES *pv,
  43. int interpolate,
  44. ClipVertex *cv,
  45. WORD wFlags = D3DTRIFLAG_EDGEENABLETRIANGLE)
  46. {
  47. ClipTriangle newtri;
  48. LPVOID saveVer = pv->lpvOut; // For indexed primitive
  49. DWORD numVer = pv->dwNumVertices; // For indexed primitive
  50. newtri.v[0] = &cv[0];
  51. newtri.v[1] = &cv[1];
  52. newtri.v[2] = &cv[2];
  53. newtri.flags = wFlags;
  54. int count;
  55. ClipVertex** ver;
  56. LPDIRECT3DDEVICEI lpDevI = static_cast<LPDIRECT3DDEVICEI>(pv);
  57. if (count = lpDevI->pGeometryFuncs->ClipSingleTriangle(
  58. pv, &newtri, &ver, interpolate))
  59. {
  60. int i;
  61. HRESULT ret;
  62. BYTE *pTLV = (BYTE*)pv->ClipperState.clipBuf.GetAddress();
  63. BYTE *p = pTLV;
  64. for (i = 0; i < count; i++)
  65. {
  66. MAKE_TL_VERTEX_FVF(pv, p, ver[i]);
  67. p += pv->dwOutputSize;
  68. }
  69. pv->dwFlags |= D3DPV_CLIPPERPRIM; // Mark this call as gen by clipper
  70. ret = DRAW_PRIM(pv, D3DPT_TRIANGLEFAN, pTLV, count, count-2);
  71. pv->dwFlags &= ~D3DPV_CLIPPERPRIM;
  72. if (ret)
  73. return ret;
  74. }
  75. pv->lpvOut = saveVer;
  76. pv->dwNumVertices = numVer;
  77. return D3D_OK;
  78. }
  79. //------------------------------------------------------------------------------
  80. HRESULT ProcessClippedTriangleFan(D3DFE_PROCESSVERTICES *pv)
  81. {
  82. BYTE *p1;
  83. DWORD f1;
  84. DWORD clipMaskOffScreen;
  85. D3DFE_CLIPCODE *clipCode;
  86. DWORD i;
  87. int interpolate;
  88. HRESULT ret;
  89. BYTE *vertex;
  90. BYTE *startVertex;
  91. int vertexCount;
  92. DWORD vertexSize;
  93. ClipVertex cv[3];
  94. BOOL vertexTransformed;
  95. vertexTransformed = pv->dwFlags & D3DPV_TLVCLIP;;
  96. clipCode = pv->lpClipFlags;
  97. interpolate = SetInterpolationFlags(pv);
  98. vertex = (BYTE*)pv->lpvOut;
  99. startVertex = (BYTE*)pv->lpvOut;
  100. vertexSize = pv->dwOutputSize;
  101. vertexCount = 0;
  102. if (pv->dwDeviceFlags & D3DDEV_GUARDBAND)
  103. {
  104. clipMaskOffScreen = ~__D3DCLIP_INGUARDBAND;
  105. }
  106. else
  107. {
  108. clipMaskOffScreen = 0xFFFFFFFF;
  109. }
  110. f1 = clipCode[0];
  111. p1 = vertex;
  112. clipCode++;
  113. vertex += vertexSize;
  114. // In the clipper color from the first vertex is propagated to all
  115. // vertices for FLAT shade mode. In triangle fans the second vertex defines
  116. // the color in FLAT shade mode. So we will make the vertex order: 1, 2, 0
  117. MAKE_CLIP_VERTEX_FVF(pv, cv[2], p1, f1, vertexTransformed, clipMaskOffScreen);
  118. for (i = pv->dwNumVertices-2; i; i--)
  119. {
  120. DWORD f2, f3; // vertex clip flags
  121. f2 = clipCode[0];
  122. f3 = clipCode[1];
  123. BOOL needClip = FALSE;
  124. BOOL offFrustum = FALSE;
  125. if (f1 & f2 & f3)
  126. offFrustum = TRUE;
  127. else
  128. if ((f1 | f2 | f3) & clipMaskOffScreen)
  129. needClip = TRUE;
  130. if (offFrustum || needClip)
  131. { // if this tri does need clipping
  132. if (vertexCount)
  133. { // first draw the ones that didn't need clipping
  134. BYTE tmp[__MAX_VERTEX_SIZE];
  135. BYTE *pStart = startVertex;
  136. if (startVertex != p1)
  137. {
  138. pStart -= vertexSize;
  139. memcpy (tmp, pStart, vertexSize);
  140. memcpy (pStart, p1, vertexSize);
  141. }
  142. // Mark this call as gen by clipper, but set non clipped bit
  143. pv->dwFlags |= D3DPV_CLIPPERPRIM | D3DPV_NONCLIPPED;
  144. ret = DRAW_PRIM(pv, D3DPT_TRIANGLEFAN, pStart, vertexCount+2,
  145. vertexCount);
  146. pv->dwFlags &= ~(D3DPV_CLIPPERPRIM | D3DPV_NONCLIPPED);
  147. if (ret)
  148. return ret;
  149. if (startVertex != p1)
  150. memcpy (pStart, tmp, vertexSize);
  151. if (ret)
  152. return ret;
  153. }
  154. // reset count and start ptr
  155. vertexCount = 0;
  156. startVertex = vertex + vertexSize;
  157. // now deal with the single clipped triangle
  158. // first check if it should just be tossed or if it should be clipped
  159. if (!offFrustum)
  160. {
  161. BYTE *p2 = vertex;
  162. BYTE *p3 = vertex + vertexSize;
  163. MAKE_CLIP_VERTEX_FVF(pv, cv[0], p2, f2, vertexTransformed, clipMaskOffScreen);
  164. MAKE_CLIP_VERTEX_FVF(pv, cv[1], p3, f3, vertexTransformed, clipMaskOffScreen);
  165. ret = Clip(pv, interpolate, cv);
  166. if (ret) return ret;
  167. }
  168. } else
  169. vertexCount++;
  170. clipCode++;
  171. vertex += vertexSize;
  172. }
  173. // draw final batch, if any
  174. if (vertexCount)
  175. {
  176. BYTE tmp[__MAX_VERTEX_SIZE];
  177. BYTE *pStart = startVertex;
  178. if (startVertex != p1)
  179. {
  180. pStart -= vertexSize;
  181. memcpy(tmp, pStart, vertexSize);
  182. memcpy(pStart, p1, vertexSize);
  183. }
  184. // Mark this call as gen by clipper
  185. pv->dwFlags |= D3DPV_CLIPPERPRIM | D3DPV_NONCLIPPED;
  186. ret = DRAW_PRIM(pv, D3DPT_TRIANGLEFAN, pStart, vertexCount+2, vertexCount);
  187. pv->dwFlags &= ~(D3DPV_CLIPPERPRIM | D3DPV_NONCLIPPED);
  188. if (ret)
  189. return ret;
  190. if (startVertex != p1)
  191. memcpy(pStart, tmp, vertexSize);
  192. if (ret)
  193. return ret;
  194. }
  195. return D3D_OK;
  196. }
  197. //------------------------------------------------------------------------------
  198. HRESULT ProcessClippedIndexedTriangleFan(D3DFE_PROCESSVERTICES *pv)
  199. {
  200. WORD *p1;
  201. DWORD f1;
  202. DWORD clipMaskOffScreen;
  203. D3DFE_CLIPCODE *clipCode;
  204. DWORD i;
  205. int interpolate;
  206. HRESULT ret;
  207. BYTE *vertex;
  208. LPWORD startVertex;
  209. LPWORD index = pv->lpwIndices; \
  210. int vertexCount;
  211. DWORD vertexSize;
  212. ClipVertex cv[3];
  213. BOOL vertexTransformed;
  214. vertexTransformed = pv->dwFlags & D3DPV_TLVCLIP;
  215. clipCode = pv->lpClipFlags;
  216. interpolate = SetInterpolationFlags(pv);
  217. vertex = (BYTE*)pv->lpvOut;
  218. startVertex = pv->lpwIndices;
  219. vertexSize = pv->dwOutputSize;
  220. vertexCount = 0;
  221. if (pv->dwDeviceFlags & D3DDEV_GUARDBAND)
  222. {
  223. clipMaskOffScreen = ~__D3DCLIP_INGUARDBAND;
  224. }
  225. else
  226. {
  227. clipMaskOffScreen = 0xFFFFFFFF;
  228. }
  229. f1 = clipCode[index[0]];
  230. p1 = index;
  231. index++;
  232. BYTE *ver = vertex + p1[0]*vertexSize;
  233. // In the clipper color from the first vertex is propagated to all
  234. // vertices for FLAT shade mode. In triangle fans the second vertex defines
  235. // the color in FLAT shade mode. So we will make the vertex order: 1, 2, 0
  236. MAKE_CLIP_VERTEX_FVF(pv, cv[2], ver, f1, vertexTransformed, clipMaskOffScreen);
  237. for (i = pv->dwNumPrimitives; i; i--)
  238. {
  239. DWORD f2, f3; // vertex clip flags
  240. WORD v1, v2;
  241. v1 = index[0];
  242. v2 = index[1];
  243. f2 = clipCode[v1];
  244. f3 = clipCode[v2];
  245. BOOL needClip = FALSE;
  246. BOOL offFrustum = FALSE;
  247. if (f1 & f2 & f3)
  248. offFrustum = TRUE;
  249. else
  250. if ((f1 | f2 | f3) & clipMaskOffScreen)
  251. needClip = TRUE;
  252. if (offFrustum || needClip)
  253. { // if this tri does need clipping
  254. if (vertexCount)
  255. { // first draw the ones that didn't need clipping
  256. WORD tmp;
  257. WORD *pStart = startVertex;
  258. if (startVertex != p1)
  259. {
  260. pStart--;
  261. tmp = *pStart; // Save old value to restore later
  262. *pStart = *p1;
  263. }
  264. ret = DRAW_INDEX_PRIM(pv, D3DPT_TRIANGLEFAN, pStart, vertexCount+2,
  265. vertexCount);
  266. if (ret)
  267. return ret;
  268. if (startVertex != p1)
  269. *pStart = tmp; // Restore old value
  270. if (ret)
  271. return ret;
  272. }
  273. // reset count and start ptr
  274. vertexCount = 0;
  275. startVertex = &index[1];
  276. // now deal with the single clipped triangle
  277. // first check if it should just be tossed or if it should be clipped
  278. if (!offFrustum)
  279. {
  280. BYTE *p2 = vertex + v1*vertexSize;
  281. BYTE *p3 = vertex + v2*vertexSize;
  282. MAKE_CLIP_VERTEX_FVF(pv, cv[0], p2, f2, vertexTransformed, clipMaskOffScreen);
  283. MAKE_CLIP_VERTEX_FVF(pv, cv[1], p3, f3, vertexTransformed, clipMaskOffScreen);
  284. ret = Clip(pv, interpolate, cv);
  285. if (ret) return ret;
  286. }
  287. }
  288. else
  289. vertexCount++;
  290. index++;
  291. }
  292. // draw final batch, if any
  293. if (vertexCount)
  294. {
  295. WORD tmp;
  296. WORD *pStart = startVertex;
  297. if (startVertex != p1)
  298. {
  299. pStart--;
  300. tmp = *pStart; // Save old value to restore later
  301. *pStart = *p1;
  302. }
  303. ret = DRAW_INDEX_PRIM(pv, D3DPT_TRIANGLEFAN, pStart, vertexCount+2, vertexCount);
  304. if (ret)
  305. return ret;
  306. if (startVertex != p1)
  307. *pStart = tmp; // Restore old value
  308. if (ret)
  309. return ret;
  310. }
  311. return D3D_OK;
  312. }
  313. #define __PROCESS_LINE_NAME ProcessClippedLine
  314. #define __PROCESS_TRI_LIST_NAME ProcessClippedTriangleList
  315. #define __PROCESS_TRI_STRIP_NAME ProcessClippedTriangleStrip
  316. #include "clipprim.h"
  317. #define __INDEX_PRIM
  318. #define __PROCESS_TRI_LIST_NAME ProcessClippedIndexedTriangleList
  319. #define __PROCESS_TRI_STRIP_NAME ProcessClippedIndexedTriangleStrip
  320. #define __PROCESS_LINE_NAME ProcessClippedIndexedLine
  321. #include "clipprim.h"
  322. //---------------------------------------------------------------------
  323. HRESULT ProcessClippedPoints(D3DFE_PROCESSVERTICES *pv)
  324. {
  325. DWORD i;
  326. WORD count;
  327. BYTE *lpStartVertex;
  328. BYTE *lpCurVertex;
  329. HRESULT ret;
  330. D3DFE_CLIPCODE *clipCode;
  331. const DWORD nVertices = pv->dwNumVertices;
  332. clipCode = pv->lpClipFlags;
  333. count = 0;
  334. lpStartVertex = lpCurVertex = (BYTE*)pv->lpvOut;
  335. DWORD dwVertexBaseOrg = pv->dwVertexBase;
  336. for (i=0; i < nVertices; i++)
  337. {
  338. if (clipCode[i])
  339. { // if this point is clipped
  340. pv->dwVertexBase = dwVertexBaseOrg + i - count;
  341. if (count)
  342. { // first draw the ones that didn't need clipping
  343. ret = DRAW_PRIM(pv, D3DPT_POINTLIST, lpStartVertex, count, count);
  344. if (ret)
  345. return ret;
  346. }
  347. // reset count and start ptr
  348. count = 0;
  349. lpCurVertex += pv->dwOutputSize;
  350. lpStartVertex = lpCurVertex;
  351. }
  352. else
  353. {
  354. count++;
  355. lpCurVertex += pv->dwOutputSize;
  356. }
  357. }
  358. // draw final batch, if any
  359. if (count)
  360. {
  361. pv->dwVertexBase = dwVertexBaseOrg + nVertices - count;
  362. ret = DRAW_PRIM(pv, D3DPT_POINTLIST, lpStartVertex, count, count);
  363. if (ret)
  364. return ret;
  365. }
  366. return D3D_OK;
  367. }