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.

471 lines
14 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // d3dutil.cpp
  4. //
  5. // Miscellanous utility functions.
  6. //
  7. // Copyright (C) Microsoft Corporation, 1997.
  8. //
  9. //----------------------------------------------------------------------------
  10. #include "rgb_pch.h"
  11. #pragma hdrstop
  12. extern "C" {
  13. //----------------------------------------------------------------------------
  14. //
  15. // TextureDiff
  16. //
  17. // Computes the difference between two texture coordinates according
  18. // to the given texture wrap mode.
  19. //
  20. //----------------------------------------------------------------------------
  21. FLOAT FASTCALL
  22. TextureDiff(FLOAT fTb, FLOAT fTa, INT iMode)
  23. {
  24. FLOAT fDiff1 = fTb - fTa;
  25. if (iMode == 0)
  26. {
  27. // Wrap not set, return plain difference.
  28. return fDiff1;
  29. }
  30. else
  31. {
  32. FLOAT fDiff2;
  33. // Wrap set, compute shortest distance of plain difference
  34. // and wrap difference.
  35. fDiff2 = fDiff1;
  36. if (FLOAT_LTZ(fDiff1))
  37. {
  38. fDiff2 += g_fOne;
  39. }
  40. else if (FLOAT_GTZ(fDiff1))
  41. {
  42. fDiff2 -= g_fOne;
  43. }
  44. if (ABSF(fDiff1) < ABSF(fDiff2))
  45. {
  46. return fDiff1;
  47. }
  48. else
  49. {
  50. return fDiff2;
  51. }
  52. }
  53. }
  54. //----------------------------------------------------------------------------
  55. //
  56. // DebugBreakFn
  57. //
  58. // Stub function that should never be called. Prints a warning and
  59. // DebugBreaks. Can be inserted in any function table, although it
  60. // will destroy the stack frame with callconv or argument mismatch.
  61. // That's OK since if it's called something has gone wrong.
  62. //
  63. //----------------------------------------------------------------------------
  64. void FASTCALL
  65. DebugBreakFn(void)
  66. {
  67. DebugBreak();
  68. }
  69. //----------------------------------------------------------------------------
  70. //
  71. // OctagonNorm
  72. //
  73. // Returns a good approximation to sqrt(fX*fX + fY*fY)
  74. //
  75. //----------------------------------------------------------------------------
  76. FLOAT FASTCALL
  77. OctagonNorm(FLOAT fX, FLOAT fY)
  78. {
  79. fX = ABSF(fX);
  80. fY = ABSF(fY);
  81. return ((11.0f/32.0f)*(fX + fY) + (21.0f/32.0f)*max(fX, fY));
  82. }
  83. //----------------------------------------------------------------------------
  84. //
  85. // ComputeLOD
  86. //
  87. // Computes mipmap level for the given W by deriving U and V and
  88. // then computing LOD from the dU and dV gradients.
  89. //
  90. //----------------------------------------------------------------------------
  91. INT FASTCALL
  92. ComputeLOD(PCD3DI_RASTCTX pCtx,
  93. FLOAT fU, FLOAT fV, FLOAT fW,
  94. FLOAT fDUoWDX, FLOAT fDVoWDX, FLOAT fDOoWDX,
  95. FLOAT fDUoWDY, FLOAT fDVoWDY, FLOAT fDOoWDY)
  96. {
  97. // Compute coverage gradients.
  98. FLOAT fDUDX = ABSF(fW * (fDUoWDX - fU * fDOoWDX));
  99. FLOAT fDUDY = ABSF(fW * (fDUoWDY - fU * fDOoWDY));
  100. FLOAT fDVDX = ABSF(fW * (fDVoWDX - fV * fDOoWDX));
  101. FLOAT fDVDY = ABSF(fW * (fDVoWDY - fV * fDOoWDY));
  102. // Scale gradients to texture LOD 0 size.
  103. fDUDX *= (FLOAT)pCtx->pTexture[0]->iSizeU;
  104. fDUDY *= (FLOAT)pCtx->pTexture[0]->iSizeU;
  105. fDVDX *= (FLOAT)pCtx->pTexture[0]->iSizeV;
  106. fDVDY *= (FLOAT)pCtx->pTexture[0]->iSizeV;
  107. // Determine pixel coverage value to use.
  108. FLOAT fCoverage;
  109. // too fuzzy
  110. #ifdef COVERAGE_MAXGRAD
  111. fCoverage = max(fDUDX, fDUDY);
  112. fCoverage = max(fCoverage, fDVDX);
  113. fCoverage = max(fCoverage, fDVDY);
  114. #endif
  115. // too sharp, in particular, for aligned cases, fCoverage is always 0
  116. // which leads to iLOD of LOD_MIN regardless of orientation
  117. #ifdef COVERAGE_MINGRAD
  118. fCoverage = min(fDUDX, fDUDY);
  119. fCoverage = min(fCoverage, fDVDX);
  120. fCoverage = min(fCoverage, fDVDY);
  121. #endif
  122. #ifdef COVERAGE_AVERAGE
  123. // use OctagonNorm to approximate each length of parallelogram
  124. // approximating texture coverage, and arithmetically average those to
  125. // get the coverage.
  126. fCoverage = (OctagonNorm(fDUDX, fDVDX) + OctagonNorm(fDUDY, fDVDY))/2.0f;
  127. #endif
  128. #define MAX_LEN 1
  129. #ifdef MAX_LEN
  130. // use OctagonNorm to approximate each length of parallelogram
  131. // approximating texture coverage, and take the max of each length
  132. // like classic OpenGL and the current RefRast implementation
  133. fCoverage = max(OctagonNorm(fDUDX, fDVDX), OctagonNorm(fDUDY, fDVDY));
  134. #endif
  135. // Compute approximate log2 of coverage.
  136. FLOAT fLOD = APPXLG2F(fCoverage);
  137. // Apply LOD bias.
  138. fLOD += pCtx->pTexture[0]->fLODBias;
  139. INT iLOD = FTOI(fLOD * LOD_SCALE);
  140. // Clamp to available levels. Not clamped to zero so that the span
  141. // code can check for magnification cases with a sign check.
  142. iLOD = min(iLOD, pCtx->pTexture[0]->iMaxScaledLOD);
  143. return max(LOD_MIN, iLOD);
  144. }
  145. //----------------------------------------------------------------------------
  146. //
  147. // ComputeTableFog
  148. //
  149. // Computes table fog values based on render state and the given Z.
  150. // ATTENTION - Brute force for non-linear modes. Should be optimized
  151. // to use a table-based approximation.
  152. //
  153. //----------------------------------------------------------------------------
  154. UINT FASTCALL
  155. ComputeTableFog(PDWORD pdwRenderState,
  156. FLOAT fZ)
  157. {
  158. double dPow;
  159. switch(pdwRenderState[D3DRENDERSTATE_FOGTABLEMODE])
  160. {
  161. case D3DFOG_LINEAR:
  162. {
  163. FLOAT fFogStart = ASFLOAT(pdwRenderState[D3DRENDERSTATE_FOGSTART]);
  164. FLOAT fFogEnd = ASFLOAT(pdwRenderState[D3DRENDERSTATE_FOGEND]);
  165. if (fZ >= fFogEnd)
  166. {
  167. return 0;
  168. }
  169. if (fZ <= fFogStart)
  170. {
  171. return FTOI(FOG_ONE_SCALE-1.0F);
  172. }
  173. return FTOI(((fFogEnd - fZ) / (fFogEnd - fFogStart)) * (FOG_ONE_SCALE-1.0F));
  174. }
  175. case D3DFOG_EXP:
  176. dPow = (double)
  177. (ASFLOAT(pdwRenderState[D3DRENDERSTATE_FOGDENSITY]) * fZ);
  178. // note that exp(-x) returns a result in the range (0.0, 1.0]
  179. // for x >= 0
  180. dPow = exp(-dPow);
  181. return FTOI((FLOAT)dPow * (FOG_ONE_SCALE-1.0F));
  182. case D3DFOG_EXP2:
  183. dPow = (double)
  184. (ASFLOAT(pdwRenderState[D3DRENDERSTATE_FOGDENSITY]) * fZ);
  185. dPow = exp(-dPow * dPow);
  186. return FTOI((FLOAT)dPow * (FOG_ONE_SCALE-1.0F));
  187. }
  188. return 0;
  189. }
  190. //-----------------------------------------------------------------------------
  191. //
  192. // IntLog2
  193. //
  194. // Do a quick, integer log2 for exact powers of 2.
  195. //
  196. //-----------------------------------------------------------------------------
  197. UINT32 FASTCALL
  198. IntLog2(UINT32 x)
  199. {
  200. UINT32 y = 0;
  201. x >>= 1;
  202. while(x != 0)
  203. {
  204. x >>= 1;
  205. y++;
  206. }
  207. return y;
  208. }
  209. //---------------------------------------------------------------------
  210. // This function uses Cramer's Rule to calculate the matrix inverse.
  211. // See nt\private\windows\opengl\serever\soft\so_math.c
  212. //
  213. // Returns:
  214. // 0 - if success
  215. // -1 - if input matrix is singular
  216. //
  217. int Inverse4x4(D3DMATRIX *src, D3DMATRIX *inverse)
  218. {
  219. double x00, x01, x02;
  220. double x10, x11, x12;
  221. double x20, x21, x22;
  222. double rcp;
  223. double x30, x31, x32;
  224. double y01, y02, y03, y12, y13, y23;
  225. double z02, z03, z12, z13, z22, z23, z32, z33;
  226. #define x03 x01
  227. #define x13 x11
  228. #define x23 x21
  229. #define x33 x31
  230. #define z00 x02
  231. #define z10 x12
  232. #define z20 x22
  233. #define z30 x32
  234. #define z01 x03
  235. #define z11 x13
  236. #define z21 x23
  237. #define z31 x33
  238. /* read 1st two columns of matrix into registers */
  239. x00 = src->_11;
  240. x01 = src->_12;
  241. x10 = src->_21;
  242. x11 = src->_22;
  243. x20 = src->_31;
  244. x21 = src->_32;
  245. x30 = src->_41;
  246. x31 = src->_42;
  247. /* compute all six 2x2 determinants of 1st two columns */
  248. y01 = x00*x11 - x10*x01;
  249. y02 = x00*x21 - x20*x01;
  250. y03 = x00*x31 - x30*x01;
  251. y12 = x10*x21 - x20*x11;
  252. y13 = x10*x31 - x30*x11;
  253. y23 = x20*x31 - x30*x21;
  254. /* read 2nd two columns of matrix into registers */
  255. x02 = src->_13;
  256. x03 = src->_14;
  257. x12 = src->_23;
  258. x13 = src->_24;
  259. x22 = src->_33;
  260. x23 = src->_34;
  261. x32 = src->_43;
  262. x33 = src->_44;
  263. /* compute all 3x3 cofactors for 2nd two columns */
  264. z33 = x02*y12 - x12*y02 + x22*y01;
  265. z23 = x12*y03 - x32*y01 - x02*y13;
  266. z13 = x02*y23 - x22*y03 + x32*y02;
  267. z03 = x22*y13 - x32*y12 - x12*y23;
  268. z32 = x13*y02 - x23*y01 - x03*y12;
  269. z22 = x03*y13 - x13*y03 + x33*y01;
  270. z12 = x23*y03 - x33*y02 - x03*y23;
  271. z02 = x13*y23 - x23*y13 + x33*y12;
  272. /* compute all six 2x2 determinants of 2nd two columns */
  273. y01 = x02*x13 - x12*x03;
  274. y02 = x02*x23 - x22*x03;
  275. y03 = x02*x33 - x32*x03;
  276. y12 = x12*x23 - x22*x13;
  277. y13 = x12*x33 - x32*x13;
  278. y23 = x22*x33 - x32*x23;
  279. /* read 1st two columns of matrix into registers */
  280. x00 = src->_11;
  281. x01 = src->_12;
  282. x10 = src->_21;
  283. x11 = src->_22;
  284. x20 = src->_31;
  285. x21 = src->_32;
  286. x30 = src->_41;
  287. x31 = src->_42;
  288. /* compute all 3x3 cofactors for 1st column */
  289. z30 = x11*y02 - x21*y01 - x01*y12;
  290. z20 = x01*y13 - x11*y03 + x31*y01;
  291. z10 = x21*y03 - x31*y02 - x01*y23;
  292. z00 = x11*y23 - x21*y13 + x31*y12;
  293. /* compute 4x4 determinant & its reciprocal */
  294. rcp = x30*z30 + x20*z20 + x10*z10 + x00*z00;
  295. if (rcp == (float)0)
  296. return -1;
  297. rcp = (float)1/rcp;
  298. /* compute all 3x3 cofactors for 2nd column */
  299. z31 = x00*y12 - x10*y02 + x20*y01;
  300. z21 = x10*y03 - x30*y01 - x00*y13;
  301. z11 = x00*y23 - x20*y03 + x30*y02;
  302. z01 = x20*y13 - x30*y12 - x10*y23;
  303. /* multiply all 3x3 cofactors by reciprocal */
  304. inverse->_11 = (float)(z00*rcp);
  305. inverse->_21 = (float)(z01*rcp);
  306. inverse->_12 = (float)(z10*rcp);
  307. inverse->_31 = (float)(z02*rcp);
  308. inverse->_13 = (float)(z20*rcp);
  309. inverse->_41 = (float)(z03*rcp);
  310. inverse->_14 = (float)(z30*rcp);
  311. inverse->_22 = (float)(z11*rcp);
  312. inverse->_32 = (float)(z12*rcp);
  313. inverse->_23 = (float)(z21*rcp);
  314. inverse->_42 = (float)(z13*rcp);
  315. inverse->_24 = (float)(z31*rcp);
  316. inverse->_33 = (float)(z22*rcp);
  317. inverse->_43 = (float)(z23*rcp);
  318. inverse->_34 = (float)(z32*rcp);
  319. inverse->_44 = (float)(z33*rcp);
  320. return 0;
  321. }
  322. //---------------------------------------------------------------------
  323. #define MATRIX_PRODUCT(res, a, b) \
  324. res->_11 = a->_11*b->_11 + a->_12*b->_21 + a->_13*b->_31 + a->_14*b->_41; \
  325. res->_12 = a->_11*b->_12 + a->_12*b->_22 + a->_13*b->_32 + a->_14*b->_42; \
  326. res->_13 = a->_11*b->_13 + a->_12*b->_23 + a->_13*b->_33 + a->_14*b->_43; \
  327. res->_14 = a->_11*b->_14 + a->_12*b->_24 + a->_13*b->_34 + a->_14*b->_44; \
  328. \
  329. res->_21 = a->_21*b->_11 + a->_22*b->_21 + a->_23*b->_31 + a->_24*b->_41; \
  330. res->_22 = a->_21*b->_12 + a->_22*b->_22 + a->_23*b->_32 + a->_24*b->_42; \
  331. res->_23 = a->_21*b->_13 + a->_22*b->_23 + a->_23*b->_33 + a->_24*b->_43; \
  332. res->_24 = a->_21*b->_14 + a->_22*b->_24 + a->_23*b->_34 + a->_24*b->_44; \
  333. \
  334. res->_31 = a->_31*b->_11 + a->_32*b->_21 + a->_33*b->_31 + a->_34*b->_41; \
  335. res->_32 = a->_31*b->_12 + a->_32*b->_22 + a->_33*b->_32 + a->_34*b->_42; \
  336. res->_33 = a->_31*b->_13 + a->_32*b->_23 + a->_33*b->_33 + a->_34*b->_43; \
  337. res->_34 = a->_31*b->_14 + a->_32*b->_24 + a->_33*b->_34 + a->_34*b->_44; \
  338. \
  339. res->_41 = a->_41*b->_11 + a->_42*b->_21 + a->_43*b->_31 + a->_44*b->_41; \
  340. res->_42 = a->_41*b->_12 + a->_42*b->_22 + a->_43*b->_32 + a->_44*b->_42; \
  341. res->_43 = a->_41*b->_13 + a->_42*b->_23 + a->_43*b->_33 + a->_44*b->_43; \
  342. res->_44 = a->_41*b->_14 + a->_42*b->_24 + a->_43*b->_34 + a->_44*b->_44;
  343. //---------------------------------------------------------------------
  344. // result = a*b
  345. // result is the same as a or b
  346. //
  347. void MatrixProduct2(D3DMATRIX *result, D3DMATRIX *a, D3DMATRIX *b)
  348. {
  349. D3DMATRIX res;
  350. MATRIX_PRODUCT((&res), a, b);
  351. *result = res;
  352. }
  353. //---------------------------------------------------------------------
  354. // result = a*b.
  355. // "result" pointer could be equal to "a" or "b"
  356. //
  357. void MatrixProduct(D3DMATRIX *result, D3DMATRIX *a, D3DMATRIX *b)
  358. {
  359. if (result == a || result == b)
  360. {
  361. MatrixProduct2(result, a, b);
  362. return;
  363. }
  364. MATRIX_PRODUCT(result, a, b);
  365. }
  366. //---------------------------------------------------------------------
  367. // Checks the FVF flags for errors and returns the stride in bytes between
  368. // vertices.
  369. //
  370. // Returns:
  371. // HRESULT and stride in bytes between vertices
  372. //
  373. //---------------------------------------------------------------------
  374. HRESULT FASTCALL
  375. FVFCheckAndStride(DWORD dwFVF, DWORD* pdwStride)
  376. {
  377. if (NULL == pdwStride)
  378. {
  379. return DDERR_INVALIDPARAMS;
  380. }
  381. if ( (dwFVF & (D3DFVF_RESERVED0 | D3DFVF_RESERVED2 |
  382. D3DFVF_NORMAL)) ||
  383. ((dwFVF & (D3DFVF_XYZ | D3DFVF_XYZRHW)) == 0) )
  384. {
  385. // can't set reserved bits, shouldn't have normals in
  386. // output to rasterizers, and must have coordinates
  387. return DDERR_INVALIDPARAMS;
  388. }
  389. DWORD dwStride;
  390. if (dwFVF != D3DFVF_TLVERTEX)
  391. { // New (non TL)FVF vertex
  392. // XYZ
  393. dwStride = sizeof(D3DVALUE) * 3;
  394. if (dwFVF & D3DFVF_XYZRHW)
  395. {
  396. dwStride += sizeof(D3DVALUE);
  397. }
  398. if (dwFVF & D3DFVF_PSIZE)
  399. {
  400. dwStride += sizeof(D3DVALUE);
  401. }
  402. if (dwFVF & D3DFVF_DIFFUSE)
  403. {
  404. dwStride += sizeof(D3DCOLOR);
  405. }
  406. if (dwFVF & D3DFVF_SPECULAR)
  407. {
  408. dwStride += sizeof(D3DCOLOR);
  409. }
  410. INT iTexCount = (dwFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
  411. for (INT i = 0; i < iTexCount; i++)
  412. {
  413. switch (D3DFVF_GETTEXCOORDSIZE(dwFVF, i))
  414. {
  415. case D3DFVF_TEXTUREFORMAT2: dwStride += sizeof(D3DVALUE) * 2; break;
  416. case D3DFVF_TEXTUREFORMAT1: dwStride += sizeof(D3DVALUE) * 1; break;
  417. case D3DFVF_TEXTUREFORMAT3: dwStride += sizeof(D3DVALUE) * 3; break;
  418. case D3DFVF_TEXTUREFORMAT4: dwStride += sizeof(D3DVALUE) * 4; break;
  419. }
  420. }
  421. }
  422. else
  423. { // (Legacy) TL vertex
  424. dwStride = sizeof(D3DTLVERTEX);
  425. }
  426. *pdwStride = dwStride;
  427. return DD_OK;
  428. }
  429. }