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.

239 lines
8.5 KiB

  1. dnl-----------------------------------------------------------------------------
  2. dnl
  3. dnl This file contains the macro for generating texture addressing routines.
  4. dnl
  5. dnl Copyright (C) Microsoft Corporation, 1997.
  6. dnl
  7. dnl-----------------------------------------------------------------------------
  8. dnl
  9. dnl d_WTimesUVoW
  10. dnl
  11. dnl Does integer W * U or V computation
  12. dnl
  13. dnl iW = 1.15.16 << 4 = 1.11.20
  14. dnl UoW = 1.11.20 << 8 = 1.2.28
  15. dnl
  16. dnl 1.11.20 * 1.3.28 == 1.15.48 >> 32 == 1.15.16
  17. dnl
  18. dnl What Steve is doing?
  19. dnl
  20. dnl iW = 1.15.16 >> 8 = 1.15.8
  21. dnl UoW = 1.11.20 >> 12 = 1.11.8
  22. dnl
  23. dnl 1.15.8 * 1.11.8 = 1.15.16
  24. dnl
  25. dnl ATTENTION
  26. dnl What we were doing, and what is still in the MMX code
  27. dnl Note that this does not have much precision, esp on UoW and VoW
  28. dnl which was causing problems in Quake. There are faster alternatives
  29. dnl to this (like getting UoW, VoW in a better range) that we can look at
  30. dnl when we get to optimizing this.
  31. dnl define(`d_WTimesUVoW', `imul32h(($1)<<4, ($2)<<8)')dnl
  32. dnl
  33. define(`d_WTimesUVoW', `imul32h_s20($1, $2)')dnl
  34. dnl
  35. dnl d_WDivide
  36. dnl
  37. dnl Does incremental W divide calculation
  38. dnl
  39. define(`d_WDivide', `ifelse(`DoPlainDivide', `DoNotPlainDivide', `
  40. pS->iW = (0x08000000/(pS->iOoW>>16))<<4; // 1.15.27/1.15 = 1.15.12 << 4 = 1.15.16',`
  41. dnl This was deemed too annoying
  42. dnl #if DBG
  43. dnl if (pS->iOoW <= 0)
  44. dnl {
  45. dnl // D3D_WARN(0, "WDivide, iOoW (%d) out of Range!", pS->iOoW);
  46. dnl // DDASSERT(0);
  47. dnl }
  48. dnl #endif
  49. INT32 iWn0 = pS->iW + pCtx->SI.iDW; // 1.15.16
  50. if (pCtx->SI.iSpecialW < 0)
  51. {
  52. INT32 iWn1;
  53. if (iWn0 < 0)
  54. {
  55. iWn0 = pS->iW >> 1; // use iW/2 as a guess, instead
  56. }
  57. INT32 iWnOld = iWn0 + 0x100; // make sure while fails first time
  58. INT32 iGiveUp = 7;
  59. while((abs(iWnOld - iWn0) > 0x20) && (iGiveUp-- > 0))
  60. {
  61. iWnOld = iWn0;
  62. iWn1 = imul32h(pS->iOoW, iWn0); // 1.31*1.15.16 = 1.16.47 >> 32 = 1.16.15
  63. iWn1 = (1L<<16) - iWn1; // 2.0 - iWn1
  64. while(iWn1 < 0)
  65. {
  66. iWn1=(iWn1+(1L<<15))>>1; // iWn1 = (iWn1 + 1.0)/2
  67. }
  68. iWn1 <<= 15; // 1.16.15 << 15 = 1.1.30
  69. iWn0 = imul32h(iWn1, iWn0)<<2; // 1.1.30 * 1.15.16 = 1.17.46 >> 32 = 1.17.14 << 2 = 1.15.16
  70. }
  71. }
  72. else
  73. {
  74. INT32 iWn1;
  75. iWn1 = imul32h(pS->iOoW, iWn0); // 1.31*1.15.16 = 1.16.47 >> 32 = 1.16.15
  76. iWn1 = (1L<<16) - iWn1; // 2.0 - iWn1
  77. iWn1 <<= 15; // 1.16.15 << 15 = 1.1.30
  78. iWn0 = imul32h(iWn1, iWn0)<<2; // 1.1.30 * 1.15.16 = 1.17.46 >> 32 = 1.17.14 << 2 = 1.15.16
  79. }
  80. pCtx->SI.iDW = iWn0 - pS->iW;
  81. pCtx->SI.iSpecialW += 1; // this is supposed to wrap past 0x7fff sometimes
  82. pS->iW = iWn0;')')
  83. dnl
  84. dnl d_TexAddrWrapMirror
  85. dnl
  86. dnl Does the address computation for Wrap or Mirror
  87. dnl
  88. define(`d_TexAddrWrapMirror', `
  89. iFlip = $2 & (pTex->iFlipMask`'$1>>$4);
  90. iFlip = -((INT16)(iFlip == 0));
  91. iFlip = $3 &~ iFlip;
  92. $2 &= $3;
  93. $2 ^= iFlip;')
  94. dnl
  95. dnl d_TexAddrAll
  96. dnl
  97. dnl Does the address computation for All address modes
  98. dnl
  99. define(`d_TexAddrAll', `
  100. iFlip = $2 & (pTex->iFlipMask`'$1>>$6);
  101. iFlip = -((INT16)(iFlip == 0));
  102. iFlip = $3 &~ iFlip;
  103. $2 &= $3;
  104. $2 ^= iFlip;
  105. iClamp1 = -((INT16)(0 > $4));
  106. iClamp2 = -((INT16)((INT16)$5 > $4));
  107. iClampMinT = pTex->iClampMin`'$1 & iClamp1;
  108. iClampMaxT = (pTex->iClampMax`'$1>>$6) &~ iClamp2;
  109. iClamp2 &= ~iClamp1;
  110. iClamp2 = pTex->iClampEn`'$1 &~ iClamp2;
  111. $2 &= ~iClamp2;
  112. $2 |= iClampMinT;
  113. $2 |= iClampMaxT;')
  114. dnl
  115. dnl d_TexAddr
  116. dnl
  117. dnl Generates all the differentiated texture address routines.
  118. dnl
  119. dnl It takes 5 parameters.
  120. dnl
  121. dnl $1 is one of 0 or 1. 0 is single texture, and 1 is the first multi-texture
  122. dnl $2 is one of TexAddrWrapMirror TexAddrAll
  123. dnl $3 is one of NoPersp Persp
  124. dnl $4 is one of Point Bilinear MaybeBilinear
  125. dnl $5 is one of NoLOD LOD
  126. dnl
  127. define(`d_TexAddr', `
  128. void C_TexAddr_$2_$3_$4_$5(PD3DI_RASTCTX pCtx, PD3DI_RASTPRIM pP,
  129. PD3DI_RASTSPAN pS, INT32 iTex)
  130. {
  131. PD3DI_SPANTEX pTex = pCtx->pTexture[iTex];
  132. ifelse(`$5', `NoLOD', `
  133. const INT16 iLOD0 = 0; // compiler should be able to simplify this wherever possible', `
  134. INT16 iLOD0 = (INT16)(min(max(pS->iLOD >> 11, 0), pTex->cLOD));')
  135. ifelse(`$4', `MaybeBilinear', `
  136. if ((((UINT16)pS->iLOD) >> 15) ^ (INT16)(pTex->uMagFilter == D3DTFG_POINT))
  137. {
  138. // if magnify matches Mag filter, bilinear, else point
  139. C_TexAddr_$2_$3_Bilinear_$5(pCtx, pP, pS, iTex);
  140. }
  141. else
  142. {
  143. C_TexAddr_$2_$3_Point_$5(pCtx, pP, pS, iTex);
  144. }', `
  145. dnl
  146. dnl Either pure point or pure bilinear, frome here down
  147. dnl
  148. INT16 iShiftU0 = pTex->iShiftU - iLOD0;
  149. INT16 iShiftV0 = pTex->iShiftV - iLOD0;
  150. // iU00, iV00 must be 16 bit, since the mask functions below are 16 bit
  151. // ATTENTION faster if we make this 32 bit?
  152. ifelse(`$4', `Point', `
  153. INT16 iU00 = (INT16)(pCtx->SI.TexUV[iTex].iU >> (TEX_FINAL_SHIFT - iShiftU0));
  154. INT16 iV00 = (INT16)(pCtx->SI.TexUV[iTex].iV >> (TEX_FINAL_SHIFT - iShiftV0));
  155. ', `
  156. INT32 iHalf = 1<<(TEX_FINAL_SHIFT - iShiftU0 - 1);
  157. INT32 iUAlign = pCtx->SI.TexUV[iTex].iU - iHalf;
  158. iHalf = 1<<(TEX_FINAL_SHIFT - iShiftV0 - 1);
  159. INT32 iVAlign = pCtx->SI.TexUV[iTex].iV - iHalf;
  160. INT16 iU00 = (INT16)(iUAlign >> (TEX_FINAL_SHIFT - iShiftU0));
  161. INT16 iV00 = (INT16)(iVAlign >> (TEX_FINAL_SHIFT - iShiftV0));
  162. INT32 iUFrac = (iUAlign<<iShiftU0) & TEX_FINAL_FRAC_MASK;
  163. INT32 iVFrac = (iVAlign<<iShiftV0) & TEX_FINAL_FRAC_MASK;
  164. INT16 iU01 = iU00 + 1;
  165. INT16 iV01 = iV00 + 1;')
  166. UINT16 uMaskU0 = pTex->uMaskU >> iLOD0;
  167. UINT16 uMaskV0 = pTex->uMaskV >> iLOD0;
  168. ifelse(`$2', `TexAddrWrapMirror', `
  169. INT16 iFlip;
  170. d_TexAddrWrapMirror(U, iU00, uMaskU0, iLOD0)
  171. d_TexAddrWrapMirror(V, iV00, uMaskV0, iLOD0)
  172. ifelse(`$4', `Point', `', `
  173. d_TexAddrWrapMirror(U, iU01, uMaskU0, iLOD0)
  174. d_TexAddrWrapMirror(V, iV01, uMaskV0, iLOD0)')')dnl
  175. dnl
  176. ifelse(`$2', `TexAddrAll', `
  177. INT16 iFlip, iClamp1, iClamp2, iClampMinT, iClampMaxT, iOoWAdj;
  178. if (iTex == 0)
  179. {
  180. iOoWAdj = (INT16)(pS->iOoW>>23); // 1.31 >> 23 = 1.8
  181. } else
  182. {
  183. iOoWAdj = (INT16)(pCtx->SI.iOoW>>23); // 1.31 >> 23 = 1.8
  184. }
  185. INT16 iUoWAdj = (INT16)(pS->UVoW[iTex].iUoW >> (TEX_SHIFT - 8)); // adjust to match iOoWAdj
  186. INT16 iVoWAdj = (INT16)(pS->UVoW[iTex].iVoW >> (TEX_SHIFT - 8));
  187. d_TexAddrAll(U, iU00, uMaskU0, iUoWAdj, iOoWAdj, iLOD0)
  188. d_TexAddrAll(V, iV00, uMaskV0, iVoWAdj, iOoWAdj, iLOD0)
  189. ifelse(`$4', `Point', `', `
  190. d_TexAddrAll(U, iU01, uMaskU0, iUoWAdj, iOoWAdj, iLOD0)
  191. d_TexAddrAll(V, iV01, uMaskV0, iVoWAdj, iOoWAdj, iLOD0)')')dnl
  192. ifelse(`$4', `Point', `
  193. pCtx->SI.TexCol[iTex] = pCtx->pfnTexRead[iTex](iU00, iV00, pTex->iShiftPitch[iLOD0],
  194. pTex->pBits[iLOD0], pTex);')
  195. ifelse(`$4', `Bilinear', `
  196. UINT32 uTex00 = pCtx->pfnTexRead[iTex](iU00, iV00, pTex->iShiftPitch[iLOD0],
  197. pTex->pBits[iLOD0], pTex);
  198. UINT32 uTex10 = pCtx->pfnTexRead[iTex](iU01, iV00, pTex->iShiftPitch[iLOD0],
  199. pTex->pBits[iLOD0], pTex);
  200. UINT32 uTex01 = pCtx->pfnTexRead[iTex](iU00, iV01, pTex->iShiftPitch[iLOD0],
  201. pTex->pBits[iLOD0], pTex);
  202. UINT32 uTex11 = pCtx->pfnTexRead[iTex](iU01, iV01, pTex->iShiftPitch[iLOD0],
  203. pTex->pBits[iLOD0], pTex);
  204. TexFiltBilinear(&pCtx->SI.TexCol[iTex], iUFrac, iVFrac, uTex00, uTex10, uTex01, uTex11);')
  205. dnl
  206. pS->UVoW[iTex].iUoW += pP->DUVoWDX[iTex].iDUoWDX;
  207. pS->UVoW[iTex].iVoW += pP->DUVoWDX[iTex].iDVoWDX;
  208. if (iTex == 0)
  209. {
  210. pS->iLOD += pS->iDLOD;
  211. pCtx->SI.iOoW = pS->iOoW;
  212. }
  213. ifelse(`$3', `Persp', `
  214. if (iTex == 0)
  215. {
  216. pS->iOoW += pP->iDOoWDX;
  217. d_WDivide()
  218. }
  219. pCtx->SI.TexUV[iTex].iU = d_WTimesUVoW(pS->iW,pS->UVoW[iTex].iUoW);
  220. pCtx->SI.TexUV[iTex].iV = d_WTimesUVoW(pS->iW,pS->UVoW[iTex].iVoW);', `
  221. pCtx->SI.TexUV[iTex].iU = pS->UVoW[iTex].iUoW>>TEX_TO_FINAL_SHIFT; // 1.11.20 >> 4 == 1.15.16
  222. pCtx->SI.TexUV[iTex].iV = pS->UVoW[iTex].iVoW>>TEX_TO_FINAL_SHIFT;')
  223. ')
  224. }')
  225. dnl
  226. dnl
  227. dnl d_TexAddrHdr
  228. dnl
  229. dnl Generates headers with the same format as d_TexAddr
  230. dnl
  231. define(`d_TexAddrHdr', `
  232. void C_TexAddr_$2_$3_$4_$5(PD3DI_RASTCTX pCtx, PD3DI_RASTPRIM pP,
  233. PD3DI_RASTSPAN pS, INT32 iTex);')dnl
  234. dnl