I think that just means "depends on currently set rounding mode". But well if someone calls into mesa code with different set rounding mode we have a lot more problems...
Am 01.08.2015 um 01:26 schrieb Matt Turner: > 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. > --- > src/mesa/main/format_utils.h | 5 +++-- > src/mesa/main/imports.h | 28 ---------------------------- > src/mesa/main/macros.h | 11 ++++++----- > src/mesa/main/pack.c | 4 ++-- > src/mesa/main/pixeltransfer.c | 11 ++++++----- > src/util/rounding.h | 25 +++++++++++++++++++++++++ > 6 files changed, 42 insertions(+), 42 deletions(-) > > diff --git a/src/mesa/main/format_utils.h b/src/mesa/main/format_utils.h > index 7f500ec..00ec777 100644 > --- a/src/mesa/main/format_utils.h > +++ b/src/mesa/main/format_utils.h > @@ -33,6 +33,7 @@ > > #include "imports.h" > #include "macros.h" > +#include "util/rounding.h" > > extern const mesa_array_format RGBA32_FLOAT; > 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) > return MAX_UINT(dst_bits); > else > - return F_TO_I(x * MAX_UINT(dst_bits)); > + return _mesa_lroundevenf(x * MAX_UINT(dst_bits)); > } > > static inline unsigned > @@ -128,7 +129,7 @@ _mesa_float_to_snorm(float x, unsigned dst_bits) > else if (x > 1.0f) > return MAX_INT(dst_bits); > else > - return F_TO_I(x * MAX_INT(dst_bits)); > + return _mesa_lroundevenf(x * MAX_INT(dst_bits)); > } > > static inline int > diff --git a/src/mesa/main/imports.h b/src/mesa/main/imports.h > index 9ffe3de..d61279a 100644 > --- a/src/mesa/main/imports.h > +++ b/src/mesa/main/imports.h > @@ -170,34 +170,6 @@ static inline int IROUND_POS(float f) > 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 */ > static inline int IFLOOR(float f) > { > diff --git a/src/mesa/main/macros.h b/src/mesa/main/macros.h > index 07919a6..54df50c 100644 > --- a/src/mesa/main/macros.h > +++ b/src/mesa/main/macros.h > @@ -33,6 +33,7 @@ > > #include "util/macros.h" > #include "util/u_math.h" > +#include "util/rounding.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 UINT_TO_USHORT(i) ((i) < 0 ? 0 : ((GLushort) ((i) >> 16))) > #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) ) I just realized we actually generate undefined results for NaNs with this and similar clamp->int conversions. May be fine though (d3d10 generally requires you to return 0 for converting floats to ints for NaN, which you can do if you have a CLAMP anyway without extra effort, if the result is unsigned, by carefully choosing the comparisons - not entirely sure if it compiles into the same amount of instructions though, might be more or less...). > #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) \ > - 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] > @@ -167,9 +168,9 @@ extern GLfloat _mesa_ubyte_to_float_color_tab[256]; > } while (0) > #else > #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) \ > - ub = ((GLubyte) F_TO_I((f) * 255.0F)) > + ub = ((GLubyte) _mesa_lroundevenf((f) * 255.0F)) > #endif > > static fi_type UINT_AS_UNION(GLuint u) > diff --git a/src/mesa/main/pack.c b/src/mesa/main/pack.c > index fb642b8..7147fd6 100644 > --- a/src/mesa/main/pack.c > +++ b/src/mesa/main/pack.c > @@ -470,7 +470,7 @@ extract_uint_indexes(GLuint n, GLuint indexes[], > static inline GLuint > 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) > { > GLfloat f = _mesa_half_to_float(h); > - return f < 0.0F ? 0 : F_TO_I(f); > + return f < 0.0F ? 0 : _mesa_lroundevenf(f); > } > > > diff --git a/src/mesa/main/pixeltransfer.c b/src/mesa/main/pixeltransfer.c > index 51f2ebf..22eac00 100644 > --- a/src/mesa/main/pixeltransfer.c > +++ b/src/mesa/main/pixeltransfer.c > @@ -35,6 +35,7 @@ > #include "pixeltransfer.h" > #include "imports.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 b = CLAMP(rgba[i][BCOMP], 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][GCOMP] = gMap[F_TO_I(g * gscale)]; > - rgba[i][BCOMP] = bMap[F_TO_I(b * bscale)]; > - rgba[i][ACOMP] = aMap[F_TO_I(a * ascale)]; > + rgba[i][RCOMP] = rMap[(int)_mesa_lroundevenf(r * rscale)]; > + rgba[i][GCOMP] = gMap[(int)_mesa_lroundevenf(g * gscale)]; > + rgba[i][BCOMP] = bMap[(int)_mesa_lroundevenf(b * bscale)]; > + 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; > for (i = 0; i < n; i++) { > 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]); > } > } > } > diff --git a/src/util/rounding.h b/src/util/rounding.h > index 0cbe926..2d00760 100644 > --- a/src/util/rounding.h > +++ b/src/util/rounding.h > @@ -21,6 +21,9 @@ > * IN THE SOFTWARE. > */ > > +#ifndef _ROUNDING_H > +#define _ROUNDING_H > + > #include <math.h> > > #ifdef __SSE4_1__ > @@ -76,3 +79,25 @@ _mesa_roundeven(double x) > return rint(x); > #endif > } > + > +/** > + * \brief Rounds \c x to the nearest integer, with ties to the even integer, > + * and returns the value as an long int. an->a > + */ > +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) Is there any need for this one? In any case, Reviewed-by: Roland Scheidegger <srol...@vmware.com> > +{ > + return lrint(x); > +} > + > +#endif > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev