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.
528 lines
15 KiB
528 lines
15 KiB
#ifndef __glcpu_h_
|
|
#define __glcpu_h_
|
|
|
|
/*
|
|
** Copyright 1991, Silicon Graphics, Inc.
|
|
** All Rights Reserved.
|
|
**
|
|
** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
|
|
** the contents of this file may not be disclosed to third parties, copied or
|
|
** duplicated in any form, in whole or in part, without the prior written
|
|
** permission of Silicon Graphics, Inc.
|
|
**
|
|
** RESTRICTED RIGHTS LEGEND:
|
|
** Use, duplication or disclosure by the Government is subject to restrictions
|
|
** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
|
|
** and Computer Software clause at DFARS 252.227-7013, and/or in similar or
|
|
** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
|
|
** rights reserved under the Copyright Laws of the United States.
|
|
**
|
|
** CPU dependent constants.
|
|
*/
|
|
|
|
#include <float.h>
|
|
#include <math.h>
|
|
|
|
#define __GL_BITS_PER_BYTE 8
|
|
#define __GL_STIPPLE_MSB 1
|
|
|
|
#define __GL_FLOAT_MANTISSA_BITS 23
|
|
#define __GL_FLOAT_MANTISSA_SHIFT 0
|
|
#define __GL_FLOAT_EXPONENT_BIAS 127
|
|
#define __GL_FLOAT_EXPONENT_BITS 8
|
|
#define __GL_FLOAT_EXPONENT_SHIFT 23
|
|
#define __GL_FLOAT_SIGN_SHIFT 31
|
|
#define __GL_FLOAT_MANTISSA_MASK (((1 << __GL_FLOAT_MANTISSA_BITS) - 1) << __GL_FLOAT_MANTISSA_SHIFT)
|
|
#define __GL_FLOAT_EXPONENT_MASK (((1 << __GL_FLOAT_EXPONENT_BITS) - 1) << __GL_FLOAT_EXPONENT_SHIFT)
|
|
|
|
// 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 __GL_FIXED_FLOAT_TO_INT(flt, shift) \
|
|
((*(LONG *)&(flt) >> (shift)) & \
|
|
((1 << (__GL_FLOAT_MANTISSA_BITS-(shift)))-1) | \
|
|
(1 << (__GL_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 __GL_FIXED_FLOAT_TO_INT_NO_MSB(flt, shift) \
|
|
((*(LONG *)&(flt) >> (shift)) & \
|
|
((1 << (__GL_FLOAT_MANTISSA_BITS-(shift)))-1))
|
|
|
|
// Produces the fixed-point form
|
|
// The value must be positive
|
|
#define __GL_FIXED_FLOAT_TO_FIXED(flt) \
|
|
((*(LONG *)&(flt)) & \
|
|
((1 << (__GL_FLOAT_MANTISSA_BITS))-1) | \
|
|
(1 << (__GL_FLOAT_MANTISSA_BITS)))
|
|
|
|
#define __GL_FIXED_FLOAT_TO_FIXED_NO_MSB(flt) \
|
|
((*(LONG *)&(flt)) & \
|
|
((1 << (__GL_FLOAT_MANTISSA_BITS))-1))
|
|
|
|
// The fixed-point fraction as an integer
|
|
// The value must be positive
|
|
#define __GL_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 __GL_FIXED_TO_FIXED_FLOAT(fxed, shift) \
|
|
((fxed) & ((1 << (__GL_FLOAT_MANTISSA_BITS))-1) | \
|
|
((__GL_FLOAT_EXPONENT_BIAS+(shift)) << __GL_FLOAT_EXPONENT_SHIFT))
|
|
|
|
// On the x86, it's faster to do zero compares with an integer cast
|
|
// than it is to do the fcomp.
|
|
// In the case of the equality test there is only a check for
|
|
// +0. IEEE floats can also be -0, so great care should be
|
|
// taken not to use the zero test unless missing this case is
|
|
// unimportant
|
|
//
|
|
// Additionally, FP compares are faster as integers
|
|
|
|
// These operations work for all normalized FP numbers, -0 included
|
|
#ifdef _X86_
|
|
#define __GL_FLOAT_GTZ(flt) (*(LONG *)&(flt) > 0)
|
|
#define __GL_FLOAT_LTZ(flt) (*(ULONG *)&(flt) > 0x80000000)
|
|
#define __GL_FLOAT_GEZ(flt) (*(ULONG *)&(flt) <= 0x80000000)
|
|
#define __GL_FLOAT_LEZ(flt) (*(LONG *)&(flt) <= 0)
|
|
#define __GL_FLOAT_EQZ(flt) ((*(ULONG *)&(flt) & 0x7fffffff) == 0)
|
|
#define __GL_FLOAT_NEZ(flt) ((*(ULONG *)&(flt) & 0x7fffffff) != 0)
|
|
#define __GL_FLOAT_COMPARE_PONE(flt, op) (*(LONG *)&(flt) op 0x3f800000)
|
|
#else
|
|
#define __GL_FLOAT_GTZ(flt) ((flt) > __glZero)
|
|
#define __GL_FLOAT_LTZ(flt) ((flt) < __glZero)
|
|
#define __GL_FLOAT_GEZ(flt) ((flt) >= __glZero)
|
|
#define __GL_FLOAT_LEZ(flt) ((flt) <= __glZero)
|
|
#define __GL_FLOAT_EQZ(flt) ((flt) == __glZero)
|
|
#define __GL_FLOAT_NEZ(flt) ((flt) != __glZero)
|
|
#define __GL_FLOAT_COMPARE_PONE(flt, op) ((flt) op __glOne)
|
|
#endif // _X86_
|
|
|
|
// These operations only account for positive zero. -0 will not work
|
|
#ifdef _X86_
|
|
#define __GL_FLOAT_EQPZ(flt) (*(LONG *)&(flt) == 0)
|
|
#define __GL_FLOAT_NEPZ(flt) (*(LONG *)&(flt) != 0)
|
|
#define __GL_FLOAT_EQ(f1, f2) (*(LONG *)&(f1) == *(LONG *)&(f2))
|
|
#define __GL_FLOAT_NE(f1, f2) (*(LONG *)&(f1) != *(LONG *)&(f2))
|
|
#else
|
|
#define __GL_FLOAT_EQPZ(flt) ((flt) == __glZero)
|
|
#define __GL_FLOAT_NEPZ(flt) ((flt) != __glZero)
|
|
#define __GL_FLOAT_EQ(f1, f2) ((f1) == (f2))
|
|
#define __GL_FLOAT_NE(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 __GL_FLOAT_SIMPLE_BEGIN_DIVIDE(num, den, result) \
|
|
__asm fld num \
|
|
__asm fdiv den
|
|
#define __GL_FLOAT_SIMPLE_END_DIVIDE(result) \
|
|
__asm fstp DWORD PTR result
|
|
|
|
__inline void __GL_FLOAT_BEGIN_DIVIDE(__GLfloat num, __GLfloat den,
|
|
__GLfloat *result)
|
|
{
|
|
__asm fld num
|
|
__asm fdiv den
|
|
}
|
|
__inline void __GL_FLOAT_END_DIVIDE(__GLfloat *result)
|
|
{
|
|
__asm mov eax, result
|
|
__asm fstp DWORD PTR [eax]
|
|
}
|
|
#else
|
|
#define __GL_FLOAT_SIMPLE_BEGIN_DIVIDE(num, den, result) \
|
|
((result) = (num)/(den))
|
|
#define __GL_FLOAT_SIMPLE_END_DIVIDE(result)
|
|
#define __GL_FLOAT_BEGIN_DIVIDE(num, den, result) (*(result) = (num)/(den))
|
|
#define __GL_FLOAT_END_DIVIDE(result)
|
|
#endif // _X86_
|
|
|
|
//**********************************************************************
|
|
//
|
|
// Math helper functions and macros
|
|
//
|
|
//**********************************************************************
|
|
|
|
#define CASTFIX(a) (*((LONG *)&(a)))
|
|
#define CASTINT(a) CASTFIX(a)
|
|
#define CASTFLOAT(a) (*((__GLfloat *)&(a)))
|
|
|
|
#define FLT_TO_RGBA(ul, pColor) \
|
|
(ul) =\
|
|
(((ULONG)(FLT_TO_UCHAR_SCALE(pColor->a, GENACCEL(gc).aAccelPrimScale)) << 24) | \
|
|
((ULONG)(FLT_TO_UCHAR_SCALE(pColor->r, GENACCEL(gc).rAccelPrimScale)) << 16) | \
|
|
((ULONG)(FLT_TO_UCHAR_SCALE(pColor->g, GENACCEL(gc).gAccelPrimScale)) << 8) | \
|
|
((ULONG)(FLT_TO_UCHAR_SCALE(pColor->b, GENACCEL(gc).bAccelPrimScale))))
|
|
|
|
#define FLT_TO_CINDEX(ul, pColor) \
|
|
(ul) =\
|
|
((ULONG)(FLT_TO_UCHAR_SCALE(pColor->r, GENACCEL(gc).rAccelPrimScale)) << 16)
|
|
|
|
#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 FPU_SAVE_MODE() \
|
|
DWORD cwSave; \
|
|
DWORD cwTemp; \
|
|
\
|
|
__asm { \
|
|
_asm fnstcw WORD PTR cwSave \
|
|
_asm mov eax, cwSave \
|
|
_asm mov cwTemp, eax \
|
|
}
|
|
|
|
#define FPU_RESTORE_MODE() \
|
|
__asm { \
|
|
_asm fldcw WORD PTR cwSave \
|
|
}
|
|
|
|
#define FPU_RESTORE_MODE_NO_EXCEPTIONS()\
|
|
__asm { \
|
|
_asm fnclex \
|
|
_asm fldcw WORD PTR cwSave \
|
|
}
|
|
|
|
#define FPU_CHOP_ON() \
|
|
__asm { \
|
|
_asm mov eax, cwTemp \
|
|
_asm or eax, 0x0c00 \
|
|
_asm mov cwTemp, eax \
|
|
_asm fldcw WORD PTR cwTemp \
|
|
}
|
|
|
|
#define FPU_ROUND_ON() \
|
|
__asm { \
|
|
_asm mov eax, cwTemp \
|
|
_asm and eax,0xf3ff \
|
|
_asm mov cwTemp, eax \
|
|
_asm fldcw WORD PTR cwTemp \
|
|
}
|
|
|
|
#define FPU_ROUND_ON_PREC_HI() \
|
|
__asm { \
|
|
_asm mov eax, cwTemp \
|
|
_asm and eax,0xf0ff \
|
|
_asm or eax,0x0200 \
|
|
_asm mov cwTemp, eax \
|
|
_asm fldcw WORD PTR cwTemp \
|
|
}
|
|
|
|
#define FPU_PREC_LOW() \
|
|
__asm { \
|
|
_asm mov eax, cwTemp \
|
|
_asm and eax, 0xfcff \
|
|
_asm mov cwTemp, eax \
|
|
_asm fldcw WORD PTR cwTemp \
|
|
}
|
|
|
|
#define FPU_PREC_LOW_MASK_EXCEPTIONS() \
|
|
__asm { \
|
|
_asm mov eax, cwTemp \
|
|
_asm and eax, 0xfcff \
|
|
_asm or eax, 0x3f \
|
|
_asm mov cwTemp, eax \
|
|
_asm fldcw WORD PTR cwTemp \
|
|
}
|
|
|
|
#define FPU_CHOP_ON_PREC_LOW() \
|
|
__asm { \
|
|
_asm mov eax, cwTemp \
|
|
_asm or eax, 0x0c00 \
|
|
_asm and eax, 0xfcff \
|
|
_asm mov cwTemp, eax \
|
|
_asm fldcw WORD PTR cwTemp \
|
|
}
|
|
|
|
#define FPU_CHOP_OFF_PREC_HI() \
|
|
__asm { \
|
|
_asm mov eax, cwTemp \
|
|
_asm mov ah, 2 \
|
|
_asm mov cwTemp, eax \
|
|
_asm fldcw WORD PTR cwTemp \
|
|
}
|
|
|
|
#define CHOP_ROUND_ON()
|
|
#define CHOP_ROUND_OFF()
|
|
|
|
#if DBG
|
|
#define ASSERT_CHOP_ROUND() \
|
|
{ \
|
|
WORD cw; \
|
|
__asm { \
|
|
__asm fnstcw cw \
|
|
} \
|
|
ASSERTOPENGL((cw & 0xc00) == 0xc00, "Chop round must be on\n"); \
|
|
}
|
|
#else
|
|
#define ASSERT_CHOP_ROUND()
|
|
#endif
|
|
|
|
#else // _X86_
|
|
|
|
#define FTOL(value) \
|
|
((GLint)(value))
|
|
#define UNSAFE_FTOL(value) \
|
|
FTOL(value)
|
|
#define FLT_TO_FIX_SCALE(value_in, scale) \
|
|
((GLint)((__GLfloat)(value_in) * scale))
|
|
#define FLT_TO_UCHAR_SCALE(value_in, scale) \
|
|
((UCHAR)((GLint)((__GLfloat)(value_in) * scale)))
|
|
#define FLT_TO_FIX(value_in) \
|
|
((GLint)((__GLfloat)(value_in) * FIX_SCALEFACT))
|
|
#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 FPU_SAVE_MODE()
|
|
#define FPU_RESTORE_MODE()
|
|
#define FPU_RESTORE_MODE_NO_EXCEPTIONS()
|
|
#define FPU_CHOP_ON()
|
|
#define FPU_ROUND_ON()
|
|
#define FPU_ROUND_ON_PREC_HI()
|
|
#define FPU_PREC_LOW()
|
|
#define FPU_PREC_LOW_MASK_EXCEPTIONS()
|
|
#define FPU_CHOP_ON_PREC_LOW()
|
|
#define FPU_CHOP_OFF_PREC_HI()
|
|
#define CHOP_ROUND_ON()
|
|
#define CHOP_ROUND_OFF()
|
|
#define ASSERT_CHOP_ROUND()
|
|
|
|
#endif //_X86_
|
|
|
|
//**********************************************************************
|
|
//
|
|
// Fast math routines/macros. These may assume that the FPU is in
|
|
// single-precision, truncation mode as defined by the CPU_XXX macros.
|
|
//
|
|
//**********************************************************************
|
|
|
|
#ifdef _X86_
|
|
|
|
__inline float __gl_fast_ceilf(float f)
|
|
{
|
|
LONG i;
|
|
|
|
ASSERT_CHOP_ROUND();
|
|
|
|
i = FTOL(f + ((float)1.0 - (float)FLT_EPSILON));
|
|
|
|
return (float)i;
|
|
}
|
|
|
|
__inline float __gl_fast_floorf(float f)
|
|
{
|
|
LONG i;
|
|
|
|
ASSERT_CHOP_ROUND();
|
|
|
|
if (__GL_FLOAT_LTZ(f)) {
|
|
i = FTOL(f - ((float)1.0 - (float)FLT_EPSILON));
|
|
} else {
|
|
i = FTOL(f);
|
|
}
|
|
|
|
return (float)i;
|
|
}
|
|
|
|
__inline LONG __gl_fast_floorf_i(float f)
|
|
{
|
|
ASSERT_CHOP_ROUND();
|
|
|
|
if (__GL_FLOAT_LTZ(f)) {
|
|
return FTOL(f - ((float)1.0 - (float)FLT_EPSILON));
|
|
} else {
|
|
return FTOL(f);
|
|
}
|
|
}
|
|
|
|
#define __GL_FAST_FLOORF_I(f) __gl_fast_floorf_i(f)
|
|
#define __GL_FAST_FLOORF(f) __gl_fast_floorf(f)
|
|
#define __GL_FAST_CEILF(f) __gl_fast_ceilf(f)
|
|
|
|
#else
|
|
|
|
#define __GL_FAST_FLOORF_I(f) ((GLint)floor((double) (f)))
|
|
#define __GL_FAST_FLOORF(f) ((__GLfloat)floor((double) (f)))
|
|
#define __GL_FAST_CEILF(f) ((__GLfloat)ceil((double) (f)))
|
|
|
|
#endif
|
|
|
|
|
|
//**********************************************************************
|
|
//
|
|
// Other various macros:
|
|
//
|
|
//**********************************************************************
|
|
|
|
|
|
// Z16_SCALE is the same as FIX_SCALEFACT
|
|
#define FLT_TO_Z16_SCALE(value) FLT_TO_FIX(value)
|
|
|
|
/* NOTE: __glzValue better be unsigned */
|
|
#define __GL_Z_SIGN_BIT(z) \
|
|
((z) >> (sizeof(__GLzValue) * __GL_BITS_PER_BYTE - 1))
|
|
|
|
#ifdef NT
|
|
#define __GL_STIPPLE_MSB 1
|
|
#endif /* NT */
|
|
|
|
#endif /* __glcpu_h_ */
|