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.

458 lines
16 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1997 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: clip.h
  6. * Content: Template for functions to clip primitives
  7. *
  8. * The following symbol should be defined before included this file:
  9. * __PROCESS_LINE_NAME - name for a function to clip triangles
  10. * __INDEX_PRIM - name for a function to clip lines
  11. *
  12. * All these symbols are undefined at the end of this file
  13. ***************************************************************************/
  14. #ifdef __INDEX_PRIM
  15. #define __DRAW DRAW_INDEX_PRIM
  16. #else
  17. #define __DRAW DRAW_PRIM
  18. #endif
  19. //*********************************************************************
  20. HRESULT __PROCESS_TRI_LIST_NAME(D3DFE_PROCESSVERTICES *pv)
  21. {
  22. int vertexSize3;
  23. D3DFE_CLIPCODE *clipCode;
  24. DWORD i;
  25. HRESULT ret;
  26. BYTE *vertex;
  27. #ifdef __INDEX_PRIM
  28. LPWORD startVertex = pv->lpwIndices;
  29. LPWORD index = pv->lpwIndices;
  30. DWORD triangleSize; // 3 for DrawPrimitives,
  31. // 4 for ExecuteBuffers (include wFlags)
  32. triangleSize = 3;
  33. #else
  34. BYTE *startVertex = (BYTE*)pv->lpvOut;
  35. #endif
  36. int primitiveCount;
  37. DWORD vertexSize;
  38. ClipVertex cv[3];
  39. BOOL vertexTransformed;
  40. vertexTransformed = pv->dwFlags & D3DPV_TLVCLIP;
  41. clipCode = pv->lpClipFlags;
  42. vertex = (BYTE*)pv->lpvOut;
  43. vertexSize = pv->dwOutputSize;
  44. primitiveCount = 0;
  45. vertexSize3 = vertexSize*3;
  46. for (i = pv->dwNumPrimitives; i; i--)
  47. {
  48. DWORD f1, f2, f3; // vertex clip flags
  49. #ifdef __INDEX_PRIM
  50. DWORD v1, v2, v3;
  51. v1 = index[0];
  52. v2 = index[1];
  53. v3 = index[2];
  54. f1 = clipCode[v1];
  55. f2 = clipCode[v2];
  56. f3 = clipCode[v3];
  57. #else
  58. f1 = clipCode[0];
  59. f2 = clipCode[1];
  60. f3 = clipCode[2];
  61. #endif
  62. BOOL needClip = FALSE;
  63. BOOL offFrustum = FALSE;
  64. if (f1 & f2 & f3)
  65. offFrustum = TRUE;
  66. else
  67. if ((f1 | f2 | f3) & pv->dwClipMaskOffScreen)
  68. needClip = TRUE;
  69. if (offFrustum || needClip)
  70. {// This tri does need clipping
  71. if (primitiveCount)
  72. { // first draw the ones that didn't need clipping
  73. DWORD vertexCount = primitiveCount*3;
  74. ret = __DRAW(pv, D3DPT_TRIANGLELIST, startVertex,
  75. vertexCount, primitiveCount);
  76. if (ret)
  77. return ret;
  78. #ifndef __INDEX_PRIM
  79. pv->dwVertexBase += vertexCount;
  80. #endif
  81. }
  82. // reset count and start ptr
  83. primitiveCount = 0;
  84. #ifdef __INDEX_PRIM
  85. startVertex = index + triangleSize;
  86. #else
  87. pv->dwVertexBase += 3;
  88. D3D_INFO(7, "VertexBase:%08lx", pv->dwVertexBase);
  89. startVertex = vertex + vertexSize3;
  90. #endif
  91. // now deal with the single clipped triangle
  92. // first check if it should just be tossed or if it should be clipped
  93. if (!offFrustum)
  94. {
  95. BYTE *p1;
  96. BYTE *p2;
  97. BYTE *p3;
  98. #ifdef __INDEX_PRIM
  99. p1 = vertex + v1*vertexSize;
  100. p2 = vertex + v2*vertexSize;
  101. p3 = vertex + v3*vertexSize;
  102. #else
  103. p1 = vertex;
  104. p2 = vertex + vertexSize;
  105. p3 = p2 + vertexSize;
  106. #endif
  107. MAKE_CLIP_VERTEX_FVF(pv, cv[0], p1, f1, vertexTransformed);
  108. MAKE_CLIP_VERTEX_FVF(pv, cv[1], p2, f2, vertexTransformed);
  109. MAKE_CLIP_VERTEX_FVF(pv, cv[2], p3, f3, vertexTransformed);
  110. #ifdef __INDEX_PRIM
  111. #endif
  112. ret = Clip(pv, &cv[0], &cv[1], &cv[2]);
  113. if (ret) return ret;
  114. }
  115. }
  116. else
  117. primitiveCount++;
  118. #ifdef __INDEX_PRIM
  119. index += triangleSize;
  120. #else
  121. clipCode += 3;
  122. vertex += vertexSize3;
  123. #endif
  124. }
  125. // draw final batch, if any
  126. if (primitiveCount)
  127. {
  128. ret = __DRAW(pv, D3DPT_TRIANGLELIST, startVertex,
  129. primitiveCount*3, primitiveCount);
  130. if (ret)
  131. return ret;
  132. }
  133. return D3D_OK;
  134. }
  135. //------------------------------------------------------------------------------
  136. HRESULT __PROCESS_TRI_STRIP_NAME(D3DFE_PROCESSVERTICES *pv)
  137. {
  138. DWORD lastIndex;
  139. D3DFE_CLIPCODE *clipCode;
  140. DWORD i;
  141. HRESULT ret;
  142. BYTE *vertex;
  143. #ifdef __INDEX_PRIM
  144. LPWORD startVertex = pv->lpwIndices;
  145. LPWORD index = pv->lpwIndices;
  146. #else
  147. BYTE *startVertex = (BYTE*)pv->lpvOut;
  148. #endif
  149. int primitiveCount;
  150. DWORD vertexSize;
  151. ClipVertex cv[3];
  152. BOOL vertexTransformed;
  153. vertexTransformed = pv->dwFlags & D3DPV_TLVCLIP;
  154. clipCode = pv->lpClipFlags;
  155. vertex = (BYTE*)pv->lpvOut;
  156. vertexSize = pv->dwOutputSize;
  157. primitiveCount = 0;
  158. lastIndex = pv->dwNumPrimitives;
  159. for (i=0; i < lastIndex; i++)
  160. {
  161. DWORD f1, f2, f3; // vertex clip flags
  162. #ifdef __INDEX_PRIM
  163. DWORD v1, v2, v3;
  164. v1 = index[0];
  165. v2 = index[1];
  166. v3 = index[2];
  167. f1 = clipCode[v1];
  168. f2 = clipCode[v2];
  169. f3 = clipCode[v3];
  170. #else
  171. f1 = clipCode[0];
  172. f2 = clipCode[1];
  173. f3 = clipCode[2];
  174. #endif
  175. BOOL needClip = FALSE;
  176. BOOL offFrustum = FALSE;
  177. if (f1 & f2 & f3)
  178. offFrustum = TRUE;
  179. else
  180. if ((f1 | f2 | f3) & pv->dwClipMaskOffScreen)
  181. needClip = TRUE;
  182. if (offFrustum || needClip)
  183. { // if this tri does need clipping
  184. if (primitiveCount)
  185. { // first draw the ones that didn't need clipping
  186. ret = __DRAW(pv, D3DPT_TRIANGLESTRIP, startVertex,
  187. primitiveCount+2, primitiveCount);
  188. if (ret)
  189. return ret;
  190. #ifndef __INDEX_PRIM
  191. pv->dwVertexBase += primitiveCount;
  192. #endif
  193. }
  194. // reset count and start ptr
  195. primitiveCount = 0;
  196. #ifdef __INDEX_PRIM
  197. startVertex = &index[1];
  198. #else
  199. pv->dwVertexBase++;
  200. D3D_INFO(7, "VertexBase:%08lx", pv->dwVertexBase);
  201. startVertex = vertex + vertexSize;
  202. #endif
  203. // now deal with the single clipped triangle
  204. // first check if it should just be tossed or if it should be clipped
  205. if (!offFrustum)
  206. {
  207. BYTE *p1;
  208. BYTE *p2;
  209. BYTE *p3;
  210. #ifdef __INDEX_PRIM
  211. if (i & 1)
  212. { // For odd triangles we have to change orientation
  213. // First vertex should remain the first, because it defines
  214. // the color in FLAT shade mode
  215. DWORD tmp = f2;
  216. f2 = f3;
  217. f3 = tmp;
  218. p1 = vertex + v1*vertexSize;
  219. p2 = vertex + v3*vertexSize;
  220. p3 = vertex + v2*vertexSize;
  221. }
  222. else
  223. {
  224. p1 = vertex + v1*vertexSize;
  225. p2 = vertex + v2*vertexSize;
  226. p3 = vertex + v3*vertexSize;
  227. }
  228. #else
  229. p1 = vertex;
  230. if (i & 1)
  231. { // For odd triangles we have to change orientation
  232. DWORD tmp = f2;
  233. f2 = f3;
  234. f3 = tmp;
  235. p3 = vertex + vertexSize;
  236. p2 = p3 + vertexSize;
  237. }
  238. else
  239. {
  240. p2 = vertex + vertexSize;
  241. p3 = p2 + vertexSize;
  242. }
  243. #endif
  244. MAKE_CLIP_VERTEX_FVF(pv, cv[0], p1, f1, vertexTransformed);
  245. MAKE_CLIP_VERTEX_FVF(pv, cv[1], p2, f2, vertexTransformed);
  246. MAKE_CLIP_VERTEX_FVF(pv, cv[2], p3, f3, vertexTransformed);
  247. ret = Clip(pv, &cv[0], &cv[1], &cv[2]);
  248. if (ret) return ret;
  249. }
  250. }
  251. else
  252. {
  253. if (primitiveCount == 0 && i & 1)
  254. { // Triangle strip can not start from an odd triangle
  255. // Because we use triangle fan, first vertex in the strip
  256. // should be the second in the fan.
  257. // This vertex defines the color in FLAT shading case.
  258. BYTE tmp[__MAX_VERTEX_SIZE*3];
  259. BYTE *p = tmp;
  260. #ifdef __INDEX_PRIM
  261. BYTE *saveVer = (BYTE*)pv->lpvOut;
  262. DWORD numVer = pv->dwNumVertices;
  263. memcpy (p, vertex + v2*vertexSize, vertexSize);
  264. p += vertexSize;
  265. memcpy (p, vertex + v1*vertexSize, vertexSize);
  266. p += vertexSize;
  267. memcpy (p, vertex + v3*vertexSize, vertexSize);
  268. #else
  269. memcpy(p, vertex + vertexSize, vertexSize);
  270. p += vertexSize;
  271. memcpy(p, vertex, vertexSize);
  272. p += vertexSize;
  273. memcpy(p, vertex + vertexSize + vertexSize, vertexSize);
  274. #endif
  275. pv->dwFlags |= D3DPV_NONCLIPPED;
  276. ret = DRAW_CLIPPED_PRIM(pv, D3DPT_TRIANGLEFAN, tmp, 3, 1);
  277. pv->dwFlags &= ~D3DPV_NONCLIPPED;
  278. if (ret)
  279. return ret;
  280. primitiveCount = 0;
  281. #ifdef __INDEX_PRIM
  282. startVertex = &index[1];
  283. pv->lpvOut = saveVer;
  284. pv->dwNumVertices = numVer;
  285. #else
  286. pv->dwVertexBase++;
  287. D3D_INFO(7, "VertexBase:%08lx", pv->dwVertexBase);
  288. startVertex = vertex + vertexSize;
  289. #endif
  290. }
  291. else
  292. primitiveCount++;
  293. }
  294. #ifdef __INDEX_PRIM
  295. index++;
  296. #else
  297. clipCode++;
  298. vertex += vertexSize;
  299. #endif
  300. }
  301. // draw final batch, if any
  302. if (primitiveCount)
  303. {
  304. ret = __DRAW(pv, D3DPT_TRIANGLESTRIP, startVertex,
  305. primitiveCount+2, primitiveCount);
  306. if (ret)
  307. return ret;
  308. #ifndef __INDEX_PRIM
  309. pv->dwVertexBase += primitiveCount;
  310. #endif
  311. }
  312. return D3D_OK;
  313. }
  314. //-----------------------------------------------------------------------------
  315. // The same functions is used for line lists and line strips
  316. //
  317. HRESULT __PROCESS_LINE_NAME(D3DFE_PROCESSVERTICES *pv)
  318. {
  319. DWORD nextLineOffset; // How many vertices to skip, when going to
  320. // next primitive (1 for strips, 2 for lists)
  321. DWORD countAdd; // Used to compute "real" number of vertices
  322. // from the vertexCount
  323. D3DPRIMITIVETYPE primType;
  324. int numPrim = 0;
  325. D3DFE_CLIPCODE *clipCode;
  326. DWORD i;
  327. HRESULT ret;
  328. BYTE *vertex;
  329. #ifdef __INDEX_PRIM
  330. LPWORD startVertex = pv->lpwIndices;
  331. LPWORD index = pv->lpwIndices;
  332. #else
  333. BYTE *startVertex = (BYTE*)pv->lpvOut;
  334. #endif
  335. int vertexCount; // Primitive count for line strips,
  336. // vertex count for line lists
  337. DWORD vertexSize;
  338. ClipVertex cv[3];
  339. BOOL vertexTransformed;
  340. vertexTransformed = pv->dwFlags & D3DPV_TLVCLIP;
  341. clipCode = pv->lpClipFlags;
  342. vertex = (BYTE*)pv->lpvOut;
  343. vertexSize = pv->dwOutputSize;
  344. vertexCount = 0;
  345. primType = pv->primType;
  346. if (primType == D3DPT_LINESTRIP)
  347. {
  348. nextLineOffset = 1;
  349. countAdd = 1;
  350. }
  351. else
  352. {
  353. nextLineOffset = 2;
  354. countAdd = 0;
  355. }
  356. for (i = pv->dwNumPrimitives; i; i--)
  357. {
  358. WORD f1, f2;
  359. #ifdef __INDEX_PRIM
  360. WORD v1, v2;
  361. v1 = index[0];
  362. v2 = index[1];
  363. f1 = clipCode[v1];
  364. f2 = clipCode[v2];
  365. #else
  366. f1 = clipCode[0];
  367. f2 = clipCode[1];
  368. #endif
  369. BOOL needClip = FALSE;
  370. BOOL offFrustum = FALSE;
  371. if (f1 & f2)
  372. offFrustum = TRUE;
  373. else
  374. if ((f1 | f2) & pv->dwClipMaskOffScreen)
  375. needClip = TRUE;
  376. if (offFrustum || needClip)
  377. { // if this line does need clipping
  378. if (vertexCount)
  379. { // first draw the ones that didn't need clipping
  380. ret = __DRAW(pv, primType, startVertex, vertexCount+countAdd, numPrim);
  381. if (ret)
  382. return ret;
  383. #ifndef __INDEX_PRIM
  384. pv->dwVertexBase += vertexCount;
  385. #endif
  386. }
  387. // reset count and start ptr
  388. vertexCount = 0;
  389. numPrim = 0;
  390. #ifdef __INDEX_PRIM
  391. startVertex = &index[nextLineOffset];
  392. #else
  393. pv->dwVertexBase += nextLineOffset;
  394. D3D_INFO(7, "VertexBase:%08lx", pv->dwVertexBase);
  395. startVertex = vertex + nextLineOffset*vertexSize;
  396. #endif
  397. // now deal with the single clipped line
  398. // first check if it should just be tossed or if it should be clipped
  399. if (!offFrustum)
  400. {
  401. #ifdef __INDEX_PRIM
  402. BYTE *p1 = vertex + v1*vertexSize;
  403. BYTE *p2 = vertex + v2*vertexSize;
  404. #else
  405. BYTE *p1 = vertex;
  406. BYTE *p2 = vertex + vertexSize;
  407. #endif
  408. MAKE_CLIP_VERTEX_FVF(pv, cv[0], p1, f1, vertexTransformed);
  409. MAKE_CLIP_VERTEX_FVF(pv, cv[1], p2, f2, vertexTransformed);
  410. ret = ClipLine(pv, &cv[0], &cv[1]);
  411. if (ret != D3D_OK)
  412. return ret;
  413. }
  414. }
  415. else
  416. {
  417. vertexCount += nextLineOffset;
  418. numPrim++;
  419. }
  420. #ifdef __INDEX_PRIM
  421. index += nextLineOffset;
  422. #else
  423. vertex += nextLineOffset*vertexSize;
  424. clipCode += nextLineOffset;
  425. #endif
  426. }
  427. // draw final batch, if any
  428. if (vertexCount)
  429. {
  430. ret = __DRAW(pv, primType, startVertex, vertexCount+countAdd, numPrim);
  431. if (ret)
  432. return ret;
  433. }
  434. return D3D_OK;
  435. }
  436. #undef __DRAW
  437. #undef __INDEX_PRIM
  438. #undef __PROCESS_LINE_NAME
  439. #undef __PROCESS_TRI_LIST_NAME
  440. #undef __PROCESS_TRI_STRIP_NAME