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.

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