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.

452 lines
13 KiB

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