mesa: Replace F_TO_I() with _mesa_lroundevenf().

I'm not sure what the true meaning of "The rounding mode may vary." is,
but it is the case that the IROUND() path rounds differently than the
other paths (and does it wrong, at that).

Like _mesa_roundeven{f,}(), just add an use _mesa_lroundeven{f,}() that
has known semantics.

Reviewed-by: Roland Scheidegger <sroland@vmware.com>
This commit is contained in:
Matt Turner
2015-06-25 16:47:52 -07:00
parent f55c408067
commit 594fc0f859
6 changed files with 42 additions and 42 deletions

View File

@@ -33,6 +33,7 @@
#include "imports.h" #include "imports.h"
#include "macros.h" #include "macros.h"
#include "util/rounding.h"
extern const mesa_array_format RGBA32_FLOAT; extern const mesa_array_format RGBA32_FLOAT;
extern const mesa_array_format RGBA8_UBYTE; extern const mesa_array_format RGBA8_UBYTE;
@@ -84,7 +85,7 @@ _mesa_float_to_unorm(float x, unsigned dst_bits)
else if (x > 1.0f) else if (x > 1.0f)
return MAX_UINT(dst_bits); return MAX_UINT(dst_bits);
else else
return F_TO_I(x * MAX_UINT(dst_bits)); return _mesa_lroundevenf(x * MAX_UINT(dst_bits));
} }
static inline unsigned static inline unsigned
@@ -128,7 +129,7 @@ _mesa_float_to_snorm(float x, unsigned dst_bits)
else if (x > 1.0f) else if (x > 1.0f)
return MAX_INT(dst_bits); return MAX_INT(dst_bits);
else else
return F_TO_I(x * MAX_INT(dst_bits)); return _mesa_lroundevenf(x * MAX_INT(dst_bits));
} }
static inline int static inline int

View File

@@ -170,34 +170,6 @@ static inline int IROUND_POS(float f)
return (int) (f + 0.5F); return (int) (f + 0.5F);
} }
#ifdef __x86_64__
# include <xmmintrin.h>
#endif
/**
* Convert float to int using a fast method. The rounding mode may vary.
*/
static inline int F_TO_I(float f)
{
#if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__)
int r;
__asm__ ("fistpl %0" : "=m" (r) : "t" (f) : "st");
return r;
#elif defined(USE_X86_ASM) && defined(_MSC_VER)
int r;
_asm {
fld f
fistp r
}
return r;
#elif defined(__x86_64__)
return _mm_cvt_ss2si(_mm_load_ss(&f));
#else
return IROUND(f);
#endif
}
/** Return (as an integer) floor of float */ /** Return (as an integer) floor of float */
static inline int IFLOOR(float f) static inline int IFLOOR(float f)
{ {

View File

@@ -33,6 +33,7 @@
#include "util/macros.h" #include "util/macros.h"
#include "util/u_math.h" #include "util/u_math.h"
#include "util/rounding.h"
#include "imports.h" #include "imports.h"
@@ -131,12 +132,12 @@ extern GLfloat _mesa_ubyte_to_float_color_tab[256];
#define INT_TO_USHORT(i) ((i) < 0 ? 0 : ((GLushort) ((i) >> 15))) #define INT_TO_USHORT(i) ((i) < 0 ? 0 : ((GLushort) ((i) >> 15)))
#define UINT_TO_USHORT(i) ((i) < 0 ? 0 : ((GLushort) ((i) >> 16))) #define UINT_TO_USHORT(i) ((i) < 0 ? 0 : ((GLushort) ((i) >> 16)))
#define UNCLAMPED_FLOAT_TO_USHORT(us, f) \ #define UNCLAMPED_FLOAT_TO_USHORT(us, f) \
us = ( (GLushort) F_TO_I( CLAMP((f), 0.0F, 1.0F) * 65535.0F) ) us = ( (GLushort) _mesa_lroundevenf( CLAMP((f), 0.0F, 1.0F) * 65535.0F) )
#define CLAMPED_FLOAT_TO_USHORT(us, f) \ #define CLAMPED_FLOAT_TO_USHORT(us, f) \
us = ( (GLushort) F_TO_I( (f) * 65535.0F) ) us = ( (GLushort) _mesa_lroundevenf( (f) * 65535.0F) )
#define UNCLAMPED_FLOAT_TO_SHORT(s, f) \ #define UNCLAMPED_FLOAT_TO_SHORT(s, f) \
s = ( (GLshort) F_TO_I( CLAMP((f), -1.0F, 1.0F) * 32767.0F) ) s = ( (GLshort) _mesa_lroundevenf( CLAMP((f), -1.0F, 1.0F) * 32767.0F) )
/*** /***
*** UNCLAMPED_FLOAT_TO_UBYTE: clamp float to [0,1] and map to ubyte in [0,255] *** UNCLAMPED_FLOAT_TO_UBYTE: clamp float to [0,1] and map to ubyte in [0,255]
@@ -167,9 +168,9 @@ extern GLfloat _mesa_ubyte_to_float_color_tab[256];
} while (0) } while (0)
#else #else
#define UNCLAMPED_FLOAT_TO_UBYTE(ub, f) \ #define UNCLAMPED_FLOAT_TO_UBYTE(ub, f) \
ub = ((GLubyte) F_TO_I(CLAMP((f), 0.0F, 1.0F) * 255.0F)) ub = ((GLubyte) _mesa_lroundevenf(CLAMP((f), 0.0F, 1.0F) * 255.0F))
#define CLAMPED_FLOAT_TO_UBYTE(ub, f) \ #define CLAMPED_FLOAT_TO_UBYTE(ub, f) \
ub = ((GLubyte) F_TO_I((f) * 255.0F)) ub = ((GLubyte) _mesa_lroundevenf((f) * 255.0F))
#endif #endif
static fi_type UINT_AS_UNION(GLuint u) static fi_type UINT_AS_UNION(GLuint u)

View File

@@ -470,7 +470,7 @@ extract_uint_indexes(GLuint n, GLuint indexes[],
static inline GLuint static inline GLuint
clamp_float_to_uint(GLfloat f) clamp_float_to_uint(GLfloat f)
{ {
return f < 0.0F ? 0 : F_TO_I(f); return f < 0.0F ? 0 : _mesa_lroundevenf(f);
} }
@@ -478,7 +478,7 @@ static inline GLuint
clamp_half_to_uint(GLhalfARB h) clamp_half_to_uint(GLhalfARB h)
{ {
GLfloat f = _mesa_half_to_float(h); GLfloat f = _mesa_half_to_float(h);
return f < 0.0F ? 0 : F_TO_I(f); return f < 0.0F ? 0 : _mesa_lroundevenf(f);
} }

View File

@@ -35,6 +35,7 @@
#include "pixeltransfer.h" #include "pixeltransfer.h"
#include "imports.h" #include "imports.h"
#include "mtypes.h" #include "mtypes.h"
#include "util/rounding.h"
/* /*
@@ -94,10 +95,10 @@ _mesa_map_rgba( const struct gl_context *ctx, GLuint n, GLfloat rgba[][4] )
GLfloat g = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F); GLfloat g = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F);
GLfloat b = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F); GLfloat b = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F);
GLfloat a = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F); GLfloat a = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F);
rgba[i][RCOMP] = rMap[F_TO_I(r * rscale)]; rgba[i][RCOMP] = rMap[(int)_mesa_lroundevenf(r * rscale)];
rgba[i][GCOMP] = gMap[F_TO_I(g * gscale)]; rgba[i][GCOMP] = gMap[(int)_mesa_lroundevenf(g * gscale)];
rgba[i][BCOMP] = bMap[F_TO_I(b * bscale)]; rgba[i][BCOMP] = bMap[(int)_mesa_lroundevenf(b * bscale)];
rgba[i][ACOMP] = aMap[F_TO_I(a * ascale)]; rgba[i][ACOMP] = aMap[(int)_mesa_lroundevenf(a * ascale)];
} }
} }
@@ -236,7 +237,7 @@ _mesa_apply_ci_transfer_ops(const struct gl_context *ctx,
GLuint i; GLuint i;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
const GLuint j = indexes[i] & mask; const GLuint j = indexes[i] & mask;
indexes[i] = F_TO_I(ctx->PixelMaps.ItoI.Map[j]); indexes[i] = _mesa_lroundevenf(ctx->PixelMaps.ItoI.Map[j]);
} }
} }
} }

View File

@@ -21,6 +21,9 @@
* IN THE SOFTWARE. * IN THE SOFTWARE.
*/ */
#ifndef _ROUNDING_H
#define _ROUNDING_H
#include <math.h> #include <math.h>
#ifdef __SSE4_1__ #ifdef __SSE4_1__
@@ -76,3 +79,25 @@ _mesa_roundeven(double x)
return rint(x); return rint(x);
#endif #endif
} }
/**
* \brief Rounds \c x to the nearest integer, with ties to the even integer,
* and returns the value as a long int.
*/
static inline long
_mesa_lroundevenf(float x)
{
return lrintf(x);
}
/**
* \brief Rounds \c x to the nearest integer, with ties to the even integer,
* and returns the value as a long int.
*/
static inline long
_mesa_lroundeven(double x)
{
return lrint(x);
}
#endif