|
|
#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_ */
|