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.

532 lines
18 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 D3DFE_PVFUNCSI::__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. DWORD dwIndexSize = pv->dwIndexSize;
  29. DWORD dwIndexSize3 = pv->dwIndexSize * 3;
  30. // Start indexed of the current in-screen triangle batch
  31. WORD* startVertex = pv->lpwIndices;
  32. // Start index of the current triangle
  33. LPBYTE index = (LPBYTE)pv->lpwIndices;
  34. #else
  35. // Start vertex of the current in-screen triangle batch
  36. BYTE *startVertex = (BYTE*)pv->lpvOut;
  37. #endif
  38. int primitiveCount;
  39. DWORD vertexSize;
  40. ClipVertex cv[3];
  41. BOOL vertexTransformed;
  42. vertexTransformed = pv->dwFlags & D3DPV_TLVCLIP;
  43. clipCode = pv->lpClipFlags;
  44. vertex = (BYTE*)pv->lpvOut;
  45. vertexSize = pv->dwOutputSize;
  46. primitiveCount = 0;
  47. #ifdef __INDEX_PRIM
  48. // Update the address of the vertex array to handle the index base
  49. if (pv->dwIndexOffset != 0)
  50. {
  51. vertex -= pv->dwIndexOffset * vertexSize;
  52. clipCode -= pv->dwIndexOffset;
  53. }
  54. #endif
  55. vertexSize3 = vertexSize*3;
  56. for (i = pv->dwNumPrimitives; i; i--)
  57. {
  58. DWORD f1, f2, f3; // vertex clip flags
  59. #ifdef __INDEX_PRIM
  60. DWORD v1, v2, v3; // Current triangle indices
  61. if (dwIndexSize == 2)
  62. {
  63. v1 = *(WORD*)index;
  64. v2 = *(WORD*)(index + 2);
  65. v3 = *(WORD*)(index + 4);
  66. }
  67. else
  68. {
  69. v1 = *(DWORD*)index;
  70. v2 = *(DWORD*)(index + 4);
  71. v3 = *(DWORD*)(index + 8);
  72. }
  73. f1 = clipCode[v1];
  74. f2 = clipCode[v2];
  75. f3 = clipCode[v3];
  76. #else
  77. f1 = clipCode[0];
  78. f2 = clipCode[1];
  79. f3 = clipCode[2];
  80. #endif
  81. BOOL needClip = FALSE;
  82. BOOL offFrustum = FALSE;
  83. if (f1 & f2 & f3)
  84. offFrustum = TRUE;
  85. else
  86. if ((f1 | f2 | f3) & pv->dwClipMaskOffScreen)
  87. needClip = TRUE;
  88. if (offFrustum || needClip)
  89. {// This tri does need clipping
  90. if (primitiveCount)
  91. { // first draw the ones that didn't need clipping
  92. DWORD vertexCount = primitiveCount*3;
  93. ret = __DRAW(pv, D3DPT_TRIANGLELIST, startVertex,
  94. vertexCount, primitiveCount);
  95. if (ret)
  96. return ret;
  97. }
  98. // reset count and start ptr
  99. primitiveCount = 0;
  100. #ifdef __INDEX_PRIM
  101. startVertex = (WORD*)(index + dwIndexSize3);
  102. #else
  103. pv->pDDI->SkipVertices(3);
  104. startVertex = vertex + vertexSize3;
  105. #endif
  106. // now deal with the single clipped triangle
  107. // first check if it should just be tossed or if it should be clipped
  108. if (!offFrustum)
  109. {
  110. BYTE *p1;
  111. BYTE *p2;
  112. BYTE *p3;
  113. #ifdef __INDEX_PRIM
  114. p1 = vertex + v1*vertexSize;
  115. p2 = vertex + v2*vertexSize;
  116. p3 = vertex + v3*vertexSize;
  117. #else
  118. p1 = vertex;
  119. p2 = vertex + vertexSize;
  120. p3 = p2 + vertexSize;
  121. #endif
  122. MAKE_CLIP_VERTEX_FVF(pv, cv[0], p1, f1, vertexTransformed);
  123. MAKE_CLIP_VERTEX_FVF(pv, cv[1], p2, f2, vertexTransformed);
  124. MAKE_CLIP_VERTEX_FVF(pv, cv[2], p3, f3, vertexTransformed);
  125. #ifdef __INDEX_PRIM
  126. #endif
  127. ret = Clip(pv, &cv[0], &cv[1], &cv[2]);
  128. if (ret) return ret;
  129. }
  130. }
  131. else
  132. primitiveCount++;
  133. #ifdef __INDEX_PRIM
  134. index += dwIndexSize3;
  135. #else
  136. clipCode += 3;
  137. vertex += vertexSize3;
  138. #endif
  139. }
  140. // draw final batch, if any
  141. if (primitiveCount)
  142. {
  143. ret = __DRAW(pv, D3DPT_TRIANGLELIST, startVertex,
  144. primitiveCount*3, primitiveCount);
  145. if (ret)
  146. return ret;
  147. }
  148. return D3D_OK;
  149. }
  150. //------------------------------------------------------------------------------
  151. HRESULT D3DFE_PVFUNCSI::__PROCESS_TRI_STRIP_NAME(D3DFE_PROCESSVERTICES *pv)
  152. {
  153. DWORD lastIndex;
  154. D3DFE_CLIPCODE *clipCode;
  155. DWORD i;
  156. HRESULT ret;
  157. BYTE *vertex;
  158. #ifdef __INDEX_PRIM
  159. DWORD dwIndexSize = pv->dwIndexSize;
  160. LPWORD startVertex = pv->lpwIndices;
  161. LPBYTE index = (LPBYTE)pv->lpwIndices;
  162. #else
  163. BYTE *startVertex = (BYTE*)pv->lpvOut;
  164. #endif
  165. int primitiveCount;
  166. DWORD vertexSize;
  167. ClipVertex cv[3];
  168. BOOL vertexTransformed;
  169. vertexTransformed = pv->dwFlags & D3DPV_TLVCLIP;
  170. clipCode = pv->lpClipFlags;
  171. vertex = (BYTE*)pv->lpvOut;
  172. vertexSize = pv->dwOutputSize;
  173. primitiveCount = 0;
  174. #ifdef __INDEX_PRIM
  175. // Update the address of the vertex array to handle the index base
  176. if (pv->dwIndexOffset != 0)
  177. {
  178. vertex -= pv->dwIndexOffset * vertexSize;
  179. clipCode -= pv->dwIndexOffset;
  180. }
  181. #endif
  182. lastIndex = pv->dwNumPrimitives;
  183. for (i=0; i < lastIndex; i++)
  184. {
  185. DWORD f1, f2, f3; // vertex clip flags
  186. #ifdef __INDEX_PRIM
  187. DWORD v1, v2, v3;
  188. if (dwIndexSize == 2)
  189. {
  190. v1 = *(WORD*)index;
  191. v2 = *(WORD*)(index + 2);
  192. v3 = *(WORD*)(index + 4);
  193. }
  194. else
  195. {
  196. v1 = *(DWORD*)index;
  197. v2 = *(DWORD*)(index + 4);
  198. v3 = *(DWORD*)(index + 8);
  199. }
  200. f1 = clipCode[v1];
  201. f2 = clipCode[v2];
  202. f3 = clipCode[v3];
  203. #else
  204. f1 = clipCode[0];
  205. f2 = clipCode[1];
  206. f3 = clipCode[2];
  207. #endif
  208. BOOL needClip = FALSE;
  209. BOOL offFrustum = FALSE;
  210. if (f1 & f2 & f3)
  211. offFrustum = TRUE;
  212. else
  213. if ((f1 | f2 | f3) & pv->dwClipMaskOffScreen)
  214. needClip = TRUE;
  215. if (offFrustum || needClip)
  216. { // if this tri does need clipping
  217. if (primitiveCount)
  218. { // first draw the ones that didn't need clipping
  219. ret = __DRAW(pv, D3DPT_TRIANGLESTRIP, startVertex,
  220. primitiveCount+2, primitiveCount);
  221. if (ret)
  222. return ret;
  223. #ifndef __INDEX_PRIM
  224. // We need to re-use the last vertex of the unclipped primitive
  225. // So we move the PrimitiveBase and startVertex back
  226. pv->pDDI->MovePrimitiveBase(-1);
  227. startVertex = vertex - vertexSize;
  228. #endif
  229. }
  230. else
  231. {
  232. #ifndef __INDEX_PRIM
  233. // Move PrimitiveBase and UsedVertexCount
  234. pv->pDDI->SkipVertices(1);
  235. startVertex = vertex + vertexSize;
  236. #endif
  237. }
  238. // reset count and start ptr
  239. primitiveCount = 0;
  240. #ifdef __INDEX_PRIM
  241. startVertex = (LPWORD)(index + dwIndexSize);
  242. #endif
  243. // now deal with the single clipped triangle
  244. // first check if it should just be tossed or if it should be clipped
  245. if (!offFrustum)
  246. {
  247. BYTE *p1;
  248. BYTE *p2;
  249. BYTE *p3;
  250. #ifdef __INDEX_PRIM
  251. if (i & 1)
  252. { // For odd triangles we have to change orientation
  253. // First vertex should remain the first, because it defines
  254. // the color in FLAT shade mode
  255. DWORD tmp = f2;
  256. f2 = f3;
  257. f3 = tmp;
  258. p1 = vertex + v1*vertexSize;
  259. p2 = vertex + v3*vertexSize;
  260. p3 = vertex + v2*vertexSize;
  261. }
  262. else
  263. {
  264. p1 = vertex + v1*vertexSize;
  265. p2 = vertex + v2*vertexSize;
  266. p3 = vertex + v3*vertexSize;
  267. }
  268. #else
  269. p1 = vertex;
  270. if (i & 1)
  271. { // For odd triangles we have to change orientation
  272. DWORD tmp = f2;
  273. f2 = f3;
  274. f3 = tmp;
  275. p3 = vertex + vertexSize;
  276. p2 = p3 + vertexSize;
  277. }
  278. else
  279. {
  280. p2 = vertex + vertexSize;
  281. p3 = p2 + vertexSize;
  282. }
  283. #endif
  284. MAKE_CLIP_VERTEX_FVF(pv, cv[0], p1, f1, vertexTransformed);
  285. MAKE_CLIP_VERTEX_FVF(pv, cv[1], p2, f2, vertexTransformed);
  286. MAKE_CLIP_VERTEX_FVF(pv, cv[2], p3, f3, vertexTransformed);
  287. ret = Clip(pv, &cv[0], &cv[1], &cv[2]);
  288. if (ret) return ret;
  289. }
  290. }
  291. else
  292. {
  293. if (primitiveCount == 0 && i & 1)
  294. { // Triangle strip can not start from an odd triangle
  295. // Because we use triangle fan, first vertex in the strip
  296. // should be the second in the fan.
  297. // This vertex defines the color in FLAT shading case.
  298. BYTE tmp[__MAX_VERTEX_SIZE*3];
  299. BYTE *p = tmp;
  300. #ifdef __INDEX_PRIM
  301. BYTE *saveVer = (BYTE*)pv->lpvOut;
  302. DWORD numVer = pv->dwNumVertices;
  303. memcpy (p, vertex + v2*vertexSize, vertexSize);
  304. p += vertexSize;
  305. memcpy (p, vertex + v1*vertexSize, vertexSize);
  306. p += vertexSize;
  307. memcpy (p, vertex + v3*vertexSize, vertexSize);
  308. #else
  309. memcpy(p, vertex + vertexSize, vertexSize);
  310. p += vertexSize;
  311. memcpy(p, vertex, vertexSize);
  312. p += vertexSize;
  313. memcpy(p, vertex + vertexSize + vertexSize, vertexSize);
  314. #endif
  315. pv->dwFlags |= D3DPV_NONCLIPPED;
  316. ret = DRAW_CLIPPED_PRIM(pv, D3DPT_TRIANGLEFAN, tmp, 3, 1);
  317. pv->dwFlags &= ~D3DPV_NONCLIPPED;
  318. if (ret)
  319. return ret;
  320. primitiveCount = 0;
  321. #ifdef __INDEX_PRIM
  322. startVertex = (LPWORD)(index + dwIndexSize);
  323. pv->lpvOut = saveVer;
  324. pv->dwNumVertices = numVer;
  325. #else
  326. pv->pDDI->SkipVertices(1);
  327. startVertex = vertex + vertexSize;
  328. #endif
  329. }
  330. else
  331. primitiveCount++;
  332. }
  333. #ifdef __INDEX_PRIM
  334. index += dwIndexSize;
  335. #else
  336. clipCode++;
  337. vertex += vertexSize;
  338. #endif
  339. }
  340. // draw final batch, if any
  341. if (primitiveCount)
  342. {
  343. ret = __DRAW(pv, D3DPT_TRIANGLESTRIP, startVertex,
  344. primitiveCount+2, primitiveCount);
  345. if (ret)
  346. return ret;
  347. }
  348. return D3D_OK;
  349. }
  350. //-----------------------------------------------------------------------------
  351. // The same functions is used for line lists and line strips
  352. //
  353. HRESULT D3DFE_PVFUNCSI::__PROCESS_LINE_NAME(D3DFE_PROCESSVERTICES *pv)
  354. {
  355. DWORD nextLineOffset; // How many vertices to skip, when going to
  356. // next primitive (1 for strips, 2 for lists)
  357. DWORD nextLineOffsetIndex; // Multiplied by the index size
  358. DWORD countAdd; // Used to compute "real" number of vertices
  359. // from the vertexCount
  360. D3DPRIMITIVETYPE primType;
  361. int numPrim = 0;
  362. D3DFE_CLIPCODE *clipCode;
  363. DWORD i;
  364. HRESULT ret;
  365. BYTE *vertex;
  366. #ifdef __INDEX_PRIM
  367. LPWORD startVertex = pv->lpwIndices;
  368. LPBYTE index = (LPBYTE)pv->lpwIndices;
  369. DWORD dwIndexSize = pv->dwIndexSize;
  370. #else
  371. BYTE *startVertex = (BYTE*)pv->lpvOut;
  372. #endif
  373. int vertexCount; // Primitive count for line strips,
  374. // vertex count for line lists
  375. DWORD vertexSize;
  376. ClipVertex cv[3];
  377. BOOL vertexTransformed;
  378. vertexTransformed = pv->dwFlags & D3DPV_TLVCLIP;
  379. clipCode = pv->lpClipFlags;
  380. vertex = (BYTE*)pv->lpvOut;
  381. vertexSize = pv->dwOutputSize;
  382. vertexCount = 0;
  383. #ifdef __INDEX_PRIM
  384. // Update the address of the vertex array to handle the index base
  385. if (pv->dwIndexOffset != 0)
  386. {
  387. vertex -= pv->dwIndexOffset * vertexSize;
  388. clipCode -= pv->dwIndexOffset;
  389. }
  390. #endif
  391. primType = pv->primType;
  392. if (primType == D3DPT_LINESTRIP)
  393. {
  394. #ifdef __INDEX_PRIM
  395. nextLineOffset = 1;
  396. nextLineOffsetIndex = dwIndexSize;
  397. #else
  398. nextLineOffset = 1;
  399. #endif
  400. countAdd = 1;
  401. }
  402. else
  403. {
  404. #ifdef __INDEX_PRIM
  405. nextLineOffset = 2;
  406. nextLineOffsetIndex = dwIndexSize * 2;
  407. #else
  408. nextLineOffset = 2;
  409. #endif
  410. countAdd = 0;
  411. }
  412. for (i = pv->dwNumPrimitives; i; i--)
  413. {
  414. WORD f1, f2;
  415. #ifdef __INDEX_PRIM
  416. DWORD v1, v2;
  417. if (dwIndexSize == 2)
  418. {
  419. v1 = *(WORD*)index;
  420. v2 = *(WORD*)(index + 2);
  421. }
  422. else
  423. {
  424. v1 = *(DWORD*)index;
  425. v2 = *(DWORD*)(index + 4);
  426. }
  427. f1 = clipCode[v1];
  428. f2 = clipCode[v2];
  429. #else
  430. f1 = clipCode[0];
  431. f2 = clipCode[1];
  432. #endif
  433. BOOL needClip = FALSE;
  434. BOOL offFrustum = FALSE;
  435. if (f1 & f2)
  436. offFrustum = TRUE;
  437. else
  438. if ((f1 | f2) & pv->dwClipMaskOffScreen)
  439. needClip = TRUE;
  440. if (offFrustum || needClip)
  441. { // if this line does need clipping
  442. if (vertexCount)
  443. { // first draw the ones that didn't need clipping
  444. ret = __DRAW(pv, primType, startVertex, vertexCount+countAdd, numPrim);
  445. if (ret)
  446. return ret;
  447. #ifndef __INDEX_PRIM
  448. // For line strips we have to go one vertex back
  449. pv->pDDI->MovePrimitiveBase(-(int)countAdd);
  450. // Now go to the next primitive
  451. pv->pDDI->MovePrimitiveBase(nextLineOffset);
  452. startVertex = vertex + nextLineOffset*vertexSize;
  453. #endif
  454. }
  455. else
  456. {
  457. #ifndef __INDEX_PRIM
  458. pv->pDDI->SkipVertices(nextLineOffset);
  459. startVertex = vertex + nextLineOffset*vertexSize;
  460. #endif
  461. }
  462. // reset count and start ptr
  463. vertexCount = 0;
  464. numPrim = 0;
  465. #ifdef __INDEX_PRIM
  466. startVertex = (LPWORD)(index + nextLineOffsetIndex);
  467. #endif
  468. // now deal with the single clipped line
  469. // first check if it should just be tossed or if it should be clipped
  470. if (!offFrustum)
  471. {
  472. #ifdef __INDEX_PRIM
  473. BYTE *p1 = vertex + v1*vertexSize;
  474. BYTE *p2 = vertex + v2*vertexSize;
  475. #else
  476. BYTE *p1 = vertex;
  477. BYTE *p2 = vertex + vertexSize;
  478. #endif
  479. MAKE_CLIP_VERTEX_FVF(pv, cv[0], p1, f1, vertexTransformed);
  480. MAKE_CLIP_VERTEX_FVF(pv, cv[1], p2, f2, vertexTransformed);
  481. ret = ClipLine(pv, &cv[0], &cv[1]);
  482. if (ret != D3D_OK)
  483. return ret;
  484. }
  485. }
  486. else
  487. {
  488. vertexCount += nextLineOffset;
  489. numPrim++;
  490. }
  491. #ifdef __INDEX_PRIM
  492. index += nextLineOffsetIndex;
  493. #else
  494. vertex += nextLineOffset*vertexSize;
  495. clipCode += nextLineOffset;
  496. #endif
  497. }
  498. // draw final batch, if any
  499. if (vertexCount)
  500. {
  501. ret = __DRAW(pv, primType, startVertex, vertexCount+countAdd, numPrim);
  502. if (ret)
  503. return ret;
  504. }
  505. return D3D_OK;
  506. }
  507. #undef __DRAW
  508. #undef __INDEX_PRIM
  509. #undef __PROCESS_LINE_NAME
  510. #undef __PROCESS_TRI_LIST_NAME
  511. #undef __PROCESS_TRI_STRIP_NAME