diff options
Diffstat (limited to 'src/gallium/auxiliary/util')
-rw-r--r-- | src/gallium/auxiliary/util/u_math.c | 56 | ||||
-rw-r--r-- | src/gallium/auxiliary/util/u_math.h | 7 |
2 files changed, 63 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/util/u_math.c b/src/gallium/auxiliary/util/u_math.c index 2811475fa00..2487bc74b25 100644 --- a/src/gallium/auxiliary/util/u_math.c +++ b/src/gallium/auxiliary/util/u_math.c @@ -28,6 +28,7 @@ #include "util/u_math.h" +#include "util/u_cpu_detect.h" /** 2^x, for x in [-1.0, 1.0) */ @@ -70,4 +71,59 @@ util_init_math(void) } } +/** + * Fetches the contents of the fpstate (mxcsr on x86) register. + * + * On platforms without support for it just returns 0. + */ +unsigned +util_fpstate_get(void) +{ + unsigned mxcsr = 0; + +#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64) + if (util_cpu_caps.has_sse) { + mxcsr = __builtin_ia32_stmxcsr(); + } +#endif + return mxcsr; +} + +/** + * Make sure that the fp treats the denormalized floating + * point numbers as zero. + * + * This is the behavior required by D3D10. OpenGL doesn't care. + */ +unsigned +util_fpstate_set_denorms_to_zero(unsigned current_mxcsr) +{ +#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64) +#define MXCSR_DAZ (1 << 6) /* Enable denormals are zero mode */ +#define MXCSR_FTZ (1 << 15) /* Enable flush to zero mode */ + if (util_cpu_caps.has_sse) { + current_mxcsr |= MXCSR_FTZ; + if (util_cpu_caps.has_sse3) { + current_mxcsr |= MXCSR_DAZ; + } + util_fpstate_set(current_mxcsr); + } +#endif + return current_mxcsr; +} + +/** + * Set the state of the fpstate (mxcsr on x86) register. + * + * On platforms without support for it's a noop. + */ +void +util_fpstate_set(unsigned mxcsr) +{ +#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64) + if (util_cpu_caps.has_sse) { + __builtin_ia32_ldmxcsr(mxcsr); + } +#endif +} diff --git a/src/gallium/auxiliary/util/u_math.h b/src/gallium/auxiliary/util/u_math.h index 64d16cbe715..bc3948875a9 100644 --- a/src/gallium/auxiliary/util/u_math.h +++ b/src/gallium/auxiliary/util/u_math.h @@ -763,6 +763,13 @@ static INLINE int32_t util_signed_fixed(float value, unsigned frac_bits) return (int32_t)(value * (1<<frac_bits)); } +unsigned +util_fpstate_get(void); +unsigned +util_fpstate_set_denorms_to_zero(unsigned current_fpstate); +void +util_fpstate_set(unsigned fpstate); + #ifdef __cplusplus |