Source code of Windows XP (NT5)
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.

380 lines
9.8 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: mcdmath.h
  3. *
  4. * Various useful defines and macros to do efficient floating-point
  5. * processing for MCD drivers.
  6. *
  7. * Copyright (c) 1996 Microsoft Corporation
  8. \**************************************************************************/
  9. #define CASTINT(a) (*((LONG *)&(a)))
  10. #define ZERO (MCDFLOAT)0.0
  11. #define __MCDZERO ZERO
  12. #define __MCDONE (MCDFLOAT)1.0
  13. #define __MCDHALF (MCDFLOAT)0.5
  14. #define __MCDFIXSCALE (MCDFLOAT)65536.0
  15. #define __MCD_MAX_WINDOW_SIZE_LOG2 14
  16. #define __MCD_VERTEX_FIX_POINT (__MCD_MAX_WINDOW_SIZE_LOG2+1)
  17. #define __MCD_VERTEX_X_FIX (1 << __MCD_VERTEX_FIX_POINT)
  18. #define __MCD_VERTEX_Y_FIX __MCD_VERTEX_X_FIX
  19. #define __MCD_FLOAT_MANTISSA_BITS 23
  20. #define __MCD_FLOAT_MANTISSA_SHIFT 0
  21. #define __MCD_FLOAT_EXPONENT_BIAS 127
  22. #define __MCD_FLOAT_EXPONENT_BITS 8
  23. #define __MCD_FLOAT_EXPONENT_SHIFT 23
  24. #define __MCD_FLOAT_SIGN_SHIFT 31
  25. // If the MSB of a FP number is known then float-to-int conversion
  26. // becomes a simple shift and mask
  27. // The value must be positive
  28. #define __MCD_FIXED_FLOAT_TO_INT(flt, shift) \
  29. ((*(LONG *)&(flt) >> (shift)) & \
  30. ((1 << (__MCD_FLOAT_MANTISSA_BITS-(shift)))-1) | \
  31. (1 << (__MCD_FLOAT_MANTISSA_BITS-(shift))))
  32. // Same as above except without the MSB, which can be useful
  33. // for getting unbiased numbers when the bias is only the MSB
  34. // The value must be positive
  35. #define __MCD_FIXED_FLOAT_TO_INT_NO_MSB(flt, shift) \
  36. ((*(LONG *)&(flt) >> (shift)) & \
  37. ((1 << (__MCD_FLOAT_MANTISSA_BITS-(shift)))-1))
  38. // Produces the fixed-point form
  39. // The value must be positive
  40. #define __MCD_FIXED_FLOAT_TO_FIXED(flt) \
  41. ((*(LONG *)&(flt)) & \
  42. ((1 << (__MCD_FLOAT_MANTISSA_BITS))-1) | \
  43. (1 << (__MCD_FLOAT_MANTISSA_BITS)))
  44. #define __MCD_FIXED_FLOAT_TO_FIXED_NO_MSB(flt) \
  45. ((*(LONG *)&(flt)) & \
  46. ((1 << (__MCD_FLOAT_MANTISSA_BITS))-1))
  47. // The fixed-point fraction as an integer
  48. // The value must be positive
  49. #define __MCD_FIXED_FLOAT_FRACTION(flt, shift) \
  50. (*(LONG *)&(flt) & ((1 << (shift))-1))
  51. // Converts the fixed-point form to an IEEE float, but still typed
  52. // as an int because a cast to float would cause the compiler to do
  53. // an int-float conversion
  54. // The value must be positive
  55. #define __MCD_FIXED_TO_FIXED_FLOAT(fxed, shift) \
  56. ((fxed) & ((1 << (__MCD_FLOAT_MANTISSA_BITS))-1) | \
  57. ((__MCD_FLOAT_EXPONENT_BIAS+(shift)) << __MCD_FLOAT_EXPONENT_SHIFT))
  58. #ifdef _X86_
  59. #define __MCD_FLOAT_GTZ(flt) (*(LONG *)&(flt) > 0)
  60. #define __MCD_FLOAT_LTZ(flt) (*(LONG *)&(flt) < 0)
  61. #define __MCD_FLOAT_EQZ(flt) (*(LONG *)&(flt) == 0)
  62. #define __MCD_FLOAT_LEZ(flt) (*(LONG *)&(flt) <= 0)
  63. #define __MCD_FLOAT_NEQZ(flt) (*(LONG *)&(flt) != 0)
  64. #define __MCD_FLOAT_EQUAL(f1, f2) (*(LONG *)&(f1) == *(LONG *)&(f2))
  65. #define __MCD_FLOAT_NEQUAL(f1, f2) (*(LONG *)&(f1) != *(LONG *)&(f2))
  66. #else
  67. #define __MCD_FLOAT_GTZ(flt) ((flt) > __MCDZERO)
  68. #define __MCD_FLOAT_LTZ(flt) ((flt) < __MCDZERO)
  69. #define __MCD_FLOAT_EQZ(flt) ((flt) == __MCDZERO)
  70. #define __MCD_FLOAT_LEZ(flt) ((flt) <= __MCDZERO)
  71. #define __MCD_FLOAT_NEQZ(flt) ((flt) != __MCDZERO)
  72. #define __MCD_FLOAT_EQUAL(f1, f2) ((f1) == (f2))
  73. #define __MCD_FLOAT_NEQUAL(f1, f2) ((f1) != (f2))
  74. #endif // _X86_
  75. // Macro to start an FP divide in the FPU, used to overlap a
  76. // divide with integer operations
  77. // Can't just use C because it stores the result immediately
  78. #ifdef _X86_
  79. #define __MCD_FLOAT_SIMPLE_BEGIN_DIVIDE(num, den, result) \
  80. __asm fld num \
  81. __asm fdiv den
  82. #define __MCD_FLOAT_SIMPLE_END_DIVIDE(result) \
  83. __asm fstp DWORD PTR result
  84. //USED
  85. __inline void __MCD_FLOAT_BEGIN_DIVIDE(MCDFLOAT num, MCDFLOAT den,
  86. MCDFLOAT *result)
  87. {
  88. __asm fld num
  89. __asm fdiv den
  90. }
  91. __inline void __MCD_FLOAT_END_DIVIDE(MCDFLOAT *result)
  92. {
  93. __asm mov eax, result
  94. __asm fstp DWORD PTR [eax]
  95. }
  96. #else
  97. #define __MCD_FLOAT_SIMPLE_BEGIN_DIVIDE(num, den, result) \
  98. ((result) = (num)/(den))
  99. #define __MCD_FLOAT_SIMPLE_END_DIVIDE(result)
  100. #define __MCD_FLOAT_BEGIN_DIVIDE(num, den, result) (*(result) = (num)/(den))
  101. #define __MCD_FLOAT_END_DIVIDE(result)
  102. #endif // _X86_
  103. #ifdef _X86_
  104. #pragma warning(disable:4035) // Function doesn't return a value
  105. // Convert float to int 15.16
  106. __inline LONG __fastcall FLT_TO_FIX(
  107. float a)
  108. {
  109. LARGE_INTEGER li;
  110. __asm {
  111. mov eax, a
  112. test eax, 07fffffffh
  113. jz RetZero
  114. add eax, 08000000h
  115. mov a, eax
  116. fld a
  117. fistp li
  118. mov eax, DWORD PTR li
  119. jmp Done
  120. RetZero:
  121. xor eax, eax
  122. Done:
  123. }
  124. }
  125. // Convert float to int 15.16, can cause overflow exceptions
  126. __inline LONG __fastcall UNSAFE_FLT_TO_FIX(
  127. float a)
  128. {
  129. LONG l;
  130. __asm {
  131. mov eax, a
  132. test eax, 07fffffffh
  133. jz RetZero
  134. add eax, 08000000h
  135. mov a, eax
  136. fld a
  137. fistp l
  138. mov eax, l
  139. jmp Done
  140. RetZero:
  141. xor eax, eax
  142. Done:
  143. }
  144. }
  145. // Convert float to int 0.31
  146. __inline LONG __fastcall FLT_FRACTION(
  147. float a)
  148. {
  149. LARGE_INTEGER li;
  150. __asm {
  151. mov eax, a
  152. test eax, 07fffffffh
  153. jz RetZero
  154. add eax, 0f800000h
  155. mov a, eax
  156. fld a
  157. fistp li
  158. mov eax, DWORD PTR li
  159. jmp Done
  160. RetZero:
  161. xor eax, eax
  162. Done:
  163. }
  164. }
  165. // Convert float to int 0.31, can cause overflow exceptions
  166. __inline LONG __fastcall UNSAFE_FLT_FRACTION(
  167. float a)
  168. {
  169. LONG l;
  170. __asm {
  171. mov eax, a
  172. test eax, 07fffffffh
  173. jz RetZero
  174. add eax, 0f800000h
  175. mov a, eax
  176. fld a
  177. fistp l
  178. mov eax, l
  179. jmp Done
  180. RetZero:
  181. xor eax, eax
  182. Done:
  183. }
  184. }
  185. #pragma warning(default:4035) // Function doesn't return a value
  186. // Convert float*scale to int
  187. __inline LONG __fastcall FLT_TO_FIX_SCALE(
  188. float a,
  189. float b)
  190. {
  191. LARGE_INTEGER li;
  192. __asm {
  193. fld a
  194. fmul b
  195. fistp li
  196. }
  197. return li.LowPart;
  198. }
  199. #define FLT_TO_UCHAR_SCALE(value_in, scale) \
  200. ((UCHAR)FLT_TO_FIX_SCALE(value_in, scale))
  201. __inline LONG __fastcall FTOL(
  202. float a)
  203. {
  204. LARGE_INTEGER li;
  205. _asm {
  206. fld a
  207. fistp li
  208. }
  209. return li.LowPart;
  210. }
  211. // Can cause overflow exceptions
  212. __inline LONG __fastcall UNSAFE_FTOL(
  213. float a)
  214. {
  215. LONG l;
  216. _asm {
  217. fld a
  218. fistp l
  219. }
  220. return l;
  221. }
  222. // Requires R-G-B to be FP stack 2-1-0
  223. // Requires gc in edx
  224. #define FLT_STACK_RGB_TO_GC_FIXED(rOffset, gOffset, bOffset) \
  225. __asm fld __glVal65536 \
  226. __asm fmul st(3), st(0) \
  227. __asm fmul st(2), st(0) \
  228. __asm fmulp st(1), st(0) \
  229. __asm fistp DWORD PTR [edx+bOffset] \
  230. __asm fistp DWORD PTR [edx+gOffset] \
  231. __asm fistp DWORD PTR [edx+rOffset]
  232. #define CHOP_ROUND_ON() \
  233. WORD cwSave; \
  234. WORD cwTemp; \
  235. \
  236. __asm { \
  237. _asm wait \
  238. _asm fstcw cwSave \
  239. _asm wait \
  240. _asm mov ax, cwSave \
  241. _asm or ah,0xc \
  242. _asm and ah,0xfc \
  243. _asm mov cwTemp,ax \
  244. _asm fldcw cwTemp \
  245. }
  246. #define CHOP_ROUND_OFF() \
  247. __asm { \
  248. _asm wait \
  249. _asm fldcw cwSave \
  250. }
  251. #else // _X86_
  252. #define FTOL(value) \
  253. ((GLint)(value))
  254. #define UNSAFE_FTOL(value) \
  255. FTOL(value)
  256. #define FLT_TO_FIX_SCALE(value_in, scale) \
  257. ((GLint)((MCDFLOAT)(value_in) * scale))
  258. #define FLT_TO_UCHAR_SCALE(value_in, scale) \
  259. ((UCHAR)((GLint)((MCDFLOAT)(value_in) * scale)))
  260. #define FLT_TO_FIX(value_in) \
  261. ((GLint)((MCDFLOAT)(value_in) * __MCDFIXSCALE))
  262. #define UNSAFE_FLT_TO_FIX(value_in) \
  263. FLT_TO_FIX(value_in)
  264. #define FLT_FRACTION(f) \
  265. FTOL((f) * __glVal2147483648)
  266. #define UNSAFE_FLT_FRACTION(f) \
  267. FLT_FRACTION(f)
  268. #define CHOP_ROUND_ON()
  269. #define CHOP_ROUND_OFF()
  270. #define ASSERT_CHOP_ROUND()
  271. #endif //_X86_
  272. #define __MCD_VERTEX_FRAC_BITS \
  273. (__MCD_FLOAT_MANTISSA_BITS-__MCD_VERTEX_FIX_POINT)
  274. //USED
  275. #define __MCD_VERTEX_FRAC_HALF \
  276. (1 << (__MCD_VERTEX_FRAC_BITS-1))
  277. #define __MCD_VERTEX_FRAC_ONE \
  278. (1 << __MCD_VERTEX_FRAC_BITS)
  279. // Converts a floating-point window coordinate to integer
  280. #define __MCD_VERTEX_FLOAT_TO_INT(windowCoord) \
  281. __MCD_FIXED_FLOAT_TO_INT(windowCoord, __MCD_VERTEX_FRAC_BITS)
  282. //USED
  283. // To fixed point
  284. #define __MCD_VERTEX_FLOAT_TO_FIXED(windowCoord) \
  285. __MCD_FIXED_FLOAT_TO_FIXED(windowCoord)
  286. // And back
  287. #define __MCD_VERTEX_FIXED_TO_FLOAT(fxWindowCoord) \
  288. __MCD_FIXED_TO_FIXED_FLOAT(fxWindowCoord, __MCD_VERTEX_FRAC_BITS)
  289. //USED
  290. // Fixed-point to integer
  291. #define __MCD_VERTEX_FIXED_TO_INT(fxWindowCoord) \
  292. ((fxWindowCoord) >> __MCD_VERTEX_FRAC_BITS)
  293. // Returns the fraction from a FP window coordinate as an N
  294. // bit integer, where N depends on the FP mantissa size and the
  295. // FIX size
  296. #define __MCD_VERTEX_FLOAT_FRACTION(windowCoord) \
  297. __MCD_FIXED_FLOAT_FRACTION(windowCoord, __MCD_VERTEX_FRAC_BITS)
  298. // Scale the fraction to 2^31 for step values
  299. #define __MCD_VERTEX_PROMOTE_FRACTION(frac) \
  300. ((frac) << (31-__MCD_VERTEX_FRAC_BITS))
  301. #define __MCD_VERTEX_PROMOTED_FRACTION(windowCoord) \
  302. __MCD_VERTEX_PROMOTE_FRACTION(__MCD_VERTEX_FLOAT_FRACTION(windowCoord))
  303. // Compare two window coordinates. Since window coordinates
  304. // are fixed-point numbers, they can be compared directly as
  305. // integers
  306. #define __MCD_VERTEX_COMPARE(a, op, b) \
  307. ((*(LONG *)&(a)) op (*(LONG *)&(b)))