windows-nt/Source/XPSP1/NT/drivers/video/matrox/mga/disp/mcdmath.h
2020-09-26 16:20:57 +08:00

381 lines
9.8 KiB
C

/******************************Module*Header*******************************\
* Module Name: mcdmath.h
*
* Various useful defines and macros to do efficient floating-point
* processing for MCD drivers.
*
* Copyright (c) 1996 Microsoft Corporation
\**************************************************************************/
#define CASTINT(a) (*((LONG *)&(a)))
#define ZERO (MCDFLOAT)0.0
#define __MCDZERO ZERO
#define __MCDONE (MCDFLOAT)1.0
#define __MCDHALF (MCDFLOAT)0.5
#define __MCDFIXSCALE (MCDFLOAT)65536.0
#define __MCD_MAX_WINDOW_SIZE_LOG2 14
#define __MCD_VERTEX_FIX_POINT (__MCD_MAX_WINDOW_SIZE_LOG2+1)
#define __MCD_VERTEX_X_FIX (1 << __MCD_VERTEX_FIX_POINT)
#define __MCD_VERTEX_Y_FIX __MCD_VERTEX_X_FIX
#define __MCD_FLOAT_MANTISSA_BITS 23
#define __MCD_FLOAT_MANTISSA_SHIFT 0
#define __MCD_FLOAT_EXPONENT_BIAS 127
#define __MCD_FLOAT_EXPONENT_BITS 8
#define __MCD_FLOAT_EXPONENT_SHIFT 23
#define __MCD_FLOAT_SIGN_SHIFT 31
// If the MSB of a FP number is known then float-to-int conversion
// becomes a simple shift and mask
// The value must be positive
#define __MCD_FIXED_FLOAT_TO_INT(flt, shift) \
((*(LONG *)&(flt) >> (shift)) & \
((1 << (__MCD_FLOAT_MANTISSA_BITS-(shift)))-1) | \
(1 << (__MCD_FLOAT_MANTISSA_BITS-(shift))))
// Same as above except without the MSB, which can be useful
// for getting unbiased numbers when the bias is only the MSB
// The value must be positive
#define __MCD_FIXED_FLOAT_TO_INT_NO_MSB(flt, shift) \
((*(LONG *)&(flt) >> (shift)) & \
((1 << (__MCD_FLOAT_MANTISSA_BITS-(shift)))-1))
// Produces the fixed-point form
// The value must be positive
#define __MCD_FIXED_FLOAT_TO_FIXED(flt) \
((*(LONG *)&(flt)) & \
((1 << (__MCD_FLOAT_MANTISSA_BITS))-1) | \
(1 << (__MCD_FLOAT_MANTISSA_BITS)))
#define __MCD_FIXED_FLOAT_TO_FIXED_NO_MSB(flt) \
((*(LONG *)&(flt)) & \
((1 << (__MCD_FLOAT_MANTISSA_BITS))-1))
// The fixed-point fraction as an integer
// The value must be positive
#define __MCD_FIXED_FLOAT_FRACTION(flt, shift) \
(*(LONG *)&(flt) & ((1 << (shift))-1))
// Converts the fixed-point form to an IEEE float, but still typed
// as an int because a cast to float would cause the compiler to do
// an int-float conversion
// The value must be positive
#define __MCD_FIXED_TO_FIXED_FLOAT(fxed, shift) \
((fxed) & ((1 << (__MCD_FLOAT_MANTISSA_BITS))-1) | \
((__MCD_FLOAT_EXPONENT_BIAS+(shift)) << __MCD_FLOAT_EXPONENT_SHIFT))
#ifdef _X86_
#define __MCD_FLOAT_GTZ(flt) (*(LONG *)&(flt) > 0)
#define __MCD_FLOAT_LTZ(flt) (*(LONG *)&(flt) < 0)
#define __MCD_FLOAT_EQZ(flt) (*(LONG *)&(flt) == 0)
#define __MCD_FLOAT_LEZ(flt) (*(LONG *)&(flt) <= 0)
#define __MCD_FLOAT_NEQZ(flt) (*(LONG *)&(flt) != 0)
#define __MCD_FLOAT_EQUAL(f1, f2) (*(LONG *)&(f1) == *(LONG *)&(f2))
#define __MCD_FLOAT_NEQUAL(f1, f2) (*(LONG *)&(f1) != *(LONG *)&(f2))
#else
#define __MCD_FLOAT_GTZ(flt) ((flt) > __MCDZERO)
#define __MCD_FLOAT_LTZ(flt) ((flt) < __MCDZERO)
#define __MCD_FLOAT_EQZ(flt) ((flt) == __MCDZERO)
#define __MCD_FLOAT_LEZ(flt) ((flt) <= __MCDZERO)
#define __MCD_FLOAT_NEQZ(flt) ((flt) != __MCDZERO)
#define __MCD_FLOAT_EQUAL(f1, f2) ((f1) == (f2))
#define __MCD_FLOAT_NEQUAL(f1, f2) ((f1) != (f2))
#endif // _X86_
// Macro to start an FP divide in the FPU, used to overlap a
// divide with integer operations
// Can't just use C because it stores the result immediately
#ifdef _X86_
#define __MCD_FLOAT_SIMPLE_BEGIN_DIVIDE(num, den, result) \
__asm fld num \
__asm fdiv den
#define __MCD_FLOAT_SIMPLE_END_DIVIDE(result) \
__asm fstp DWORD PTR result
//USED
__inline void __MCD_FLOAT_BEGIN_DIVIDE(MCDFLOAT num, MCDFLOAT den,
MCDFLOAT *result)
{
__asm fld num
__asm fdiv den
}
__inline void __MCD_FLOAT_END_DIVIDE(MCDFLOAT *result)
{
__asm mov eax, result
__asm fstp DWORD PTR [eax]
}
#else
#define __MCD_FLOAT_SIMPLE_BEGIN_DIVIDE(num, den, result) \
((result) = (num)/(den))
#define __MCD_FLOAT_SIMPLE_END_DIVIDE(result)
#define __MCD_FLOAT_BEGIN_DIVIDE(num, den, result) (*(result) = (num)/(den))
#define __MCD_FLOAT_END_DIVIDE(result)
#endif // _X86_
#ifdef _X86_
#pragma warning(disable:4035) // Function doesn't return a value
// Convert float to int 15.16
__inline LONG __fastcall FLT_TO_FIX(
float a)
{
LARGE_INTEGER li;
__asm {
mov eax, a
test eax, 07fffffffh
jz RetZero
add eax, 08000000h
mov a, eax
fld a
fistp li
mov eax, DWORD PTR li
jmp Done
RetZero:
xor eax, eax
Done:
}
}
// Convert float to int 15.16, can cause overflow exceptions
__inline LONG __fastcall UNSAFE_FLT_TO_FIX(
float a)
{
LONG l;
__asm {
mov eax, a
test eax, 07fffffffh
jz RetZero
add eax, 08000000h
mov a, eax
fld a
fistp l
mov eax, l
jmp Done
RetZero:
xor eax, eax
Done:
}
}
// Convert float to int 0.31
__inline LONG __fastcall FLT_FRACTION(
float a)
{
LARGE_INTEGER li;
__asm {
mov eax, a
test eax, 07fffffffh
jz RetZero
add eax, 0f800000h
mov a, eax
fld a
fistp li
mov eax, DWORD PTR li
jmp Done
RetZero:
xor eax, eax
Done:
}
}
// Convert float to int 0.31, can cause overflow exceptions
__inline LONG __fastcall UNSAFE_FLT_FRACTION(
float a)
{
LONG l;
__asm {
mov eax, a
test eax, 07fffffffh
jz RetZero
add eax, 0f800000h
mov a, eax
fld a
fistp l
mov eax, l
jmp Done
RetZero:
xor eax, eax
Done:
}
}
#pragma warning(default:4035) // Function doesn't return a value
// Convert float*scale to int
__inline LONG __fastcall FLT_TO_FIX_SCALE(
float a,
float b)
{
LARGE_INTEGER li;
__asm {
fld a
fmul b
fistp li
}
return li.LowPart;
}
#define FLT_TO_UCHAR_SCALE(value_in, scale) \
((UCHAR)FLT_TO_FIX_SCALE(value_in, scale))
__inline LONG __fastcall FTOL(
float a)
{
LARGE_INTEGER li;
_asm {
fld a
fistp li
}
return li.LowPart;
}
// Can cause overflow exceptions
__inline LONG __fastcall UNSAFE_FTOL(
float a)
{
LONG l;
_asm {
fld a
fistp l
}
return l;
}
// Requires R-G-B to be FP stack 2-1-0
// Requires gc in edx
#define FLT_STACK_RGB_TO_GC_FIXED(rOffset, gOffset, bOffset) \
__asm fld __glVal65536 \
__asm fmul st(3), st(0) \
__asm fmul st(2), st(0) \
__asm fmulp st(1), st(0) \
__asm fistp DWORD PTR [edx+bOffset] \
__asm fistp DWORD PTR [edx+gOffset] \
__asm fistp DWORD PTR [edx+rOffset]
#define CHOP_ROUND_ON() \
WORD cwSave; \
WORD cwTemp; \
\
__asm { \
_asm wait \
_asm fstcw cwSave \
_asm wait \
_asm mov ax, cwSave \
_asm or ah,0xc \
_asm and ah,0xfc \
_asm mov cwTemp,ax \
_asm fldcw cwTemp \
}
#define CHOP_ROUND_OFF() \
__asm { \
_asm wait \
_asm fldcw cwSave \
}
#else // _X86_
#define FTOL(value) \
((GLint)(value))
#define UNSAFE_FTOL(value) \
FTOL(value)
#define FLT_TO_FIX_SCALE(value_in, scale) \
((GLint)((MCDFLOAT)(value_in) * scale))
#define FLT_TO_UCHAR_SCALE(value_in, scale) \
((UCHAR)((GLint)((MCDFLOAT)(value_in) * scale)))
#define FLT_TO_FIX(value_in) \
((GLint)((MCDFLOAT)(value_in) * __MCDFIXSCALE))
#define UNSAFE_FLT_TO_FIX(value_in) \
FLT_TO_FIX(value_in)
#define FLT_FRACTION(f) \
FTOL((f) * __glVal2147483648)
#define UNSAFE_FLT_FRACTION(f) \
FLT_FRACTION(f)
#define CHOP_ROUND_ON()
#define CHOP_ROUND_OFF()
#define ASSERT_CHOP_ROUND()
#endif //_X86_
#define __MCD_VERTEX_FRAC_BITS \
(__MCD_FLOAT_MANTISSA_BITS-__MCD_VERTEX_FIX_POINT)
//USED
#define __MCD_VERTEX_FRAC_HALF \
(1 << (__MCD_VERTEX_FRAC_BITS-1))
#define __MCD_VERTEX_FRAC_ONE \
(1 << __MCD_VERTEX_FRAC_BITS)
// Converts a floating-point window coordinate to integer
#define __MCD_VERTEX_FLOAT_TO_INT(windowCoord) \
__MCD_FIXED_FLOAT_TO_INT(windowCoord, __MCD_VERTEX_FRAC_BITS)
//USED
// To fixed point
#define __MCD_VERTEX_FLOAT_TO_FIXED(windowCoord) \
__MCD_FIXED_FLOAT_TO_FIXED(windowCoord)
// And back
#define __MCD_VERTEX_FIXED_TO_FLOAT(fxWindowCoord) \
__MCD_FIXED_TO_FIXED_FLOAT(fxWindowCoord, __MCD_VERTEX_FRAC_BITS)
//USED
// Fixed-point to integer
#define __MCD_VERTEX_FIXED_TO_INT(fxWindowCoord) \
((fxWindowCoord) >> __MCD_VERTEX_FRAC_BITS)
// Returns the fraction from a FP window coordinate as an N
// bit integer, where N depends on the FP mantissa size and the
// FIX size
#define __MCD_VERTEX_FLOAT_FRACTION(windowCoord) \
__MCD_FIXED_FLOAT_FRACTION(windowCoord, __MCD_VERTEX_FRAC_BITS)
// Scale the fraction to 2^31 for step values
#define __MCD_VERTEX_PROMOTE_FRACTION(frac) \
((frac) << (31-__MCD_VERTEX_FRAC_BITS))
#define __MCD_VERTEX_PROMOTED_FRACTION(windowCoord) \
__MCD_VERTEX_PROMOTE_FRACTION(__MCD_VERTEX_FLOAT_FRACTION(windowCoord))
// Compare two window coordinates. Since window coordinates
// are fixed-point numbers, they can be compared directly as
// integers
#define __MCD_VERTEX_COMPARE(a, op, b) \
((*(LONG *)&(a)) op (*(LONG *)&(b)))