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.

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