From 7eb3e9b9648938500c6172a88fb2998e6264467f Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Tue, 18 Nov 2003 03:41:14 +0000 Subject: Some groundwork for supporting GLhalf datatype. --- src/mesa/main/image.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++++ src/mesa/main/imports.c | 148 +++++++++++++++++++++++++++++++++++++++++++- src/mesa/main/imports.h | 6 ++ 3 files changed, 311 insertions(+), 3 deletions(-) diff --git a/src/mesa/main/image.c b/src/mesa/main/image.c index b9f026d7e65..955f14f6b18 100644 --- a/src/mesa/main/image.c +++ b/src/mesa/main/image.c @@ -161,6 +161,8 @@ GLint _mesa_sizeof_type( GLenum type ) return sizeof(GLint); case GL_FLOAT: return sizeof(GLfloat); + case GL_HALF_FLOAT_NV: + return sizeof(GLhalfNV); default: return -1; } @@ -188,6 +190,8 @@ GLint _mesa_sizeof_packed_type( GLenum type ) return sizeof(GLuint); case GL_INT: return sizeof(GLint); + case GL_HALF_FLOAT_NV: + return sizeof(GLhalfNV); case GL_FLOAT: return sizeof(GLfloat); case GL_UNSIGNED_BYTE_3_3_2: @@ -297,6 +301,8 @@ GLint _mesa_bytes_per_pixel( GLenum format, GLenum type ) return comps * sizeof(GLint); case GL_FLOAT: return comps * sizeof(GLfloat); + case GL_HALF_FLOAT_NV: + return comps * sizeof(GLhalfNV); case GL_UNSIGNED_BYTE_3_3_2: case GL_UNSIGNED_BYTE_2_3_3_REV: if (format == GL_RGB || format == GL_BGR) @@ -361,6 +367,7 @@ _mesa_is_legal_format_and_type( GLenum format, GLenum type ) case GL_INT: case GL_UNSIGNED_INT: case GL_FLOAT: + case GL_HALF_FLOAT_NV: return GL_TRUE; default: return GL_FALSE; @@ -381,6 +388,7 @@ _mesa_is_legal_format_and_type( GLenum format, GLenum type ) case GL_INT: case GL_UNSIGNED_INT: case GL_FLOAT: + case GL_HALF_FLOAT_NV: return GL_TRUE; default: return GL_FALSE; @@ -395,6 +403,7 @@ _mesa_is_legal_format_and_type( GLenum format, GLenum type ) case GL_INT: case GL_UNSIGNED_INT: case GL_FLOAT: + case GL_HALF_FLOAT_NV: case GL_UNSIGNED_BYTE_3_3_2: case GL_UNSIGNED_BYTE_2_3_3_REV: case GL_UNSIGNED_SHORT_5_6_5: @@ -414,6 +423,7 @@ _mesa_is_legal_format_and_type( GLenum format, GLenum type ) case GL_INT: case GL_UNSIGNED_INT: case GL_FLOAT: + case GL_HALF_FLOAT_NV: case GL_UNSIGNED_SHORT_4_4_4_4: case GL_UNSIGNED_SHORT_4_4_4_4_REV: case GL_UNSIGNED_SHORT_5_5_5_1: @@ -1538,6 +1548,82 @@ _mesa_pack_float_rgba_span( GLcontext *ctx, } } break; + case GL_HALF_FLOAT_NV: + { + GLhalfNV *dst = (GLhalfNV *) dstAddr; + switch (dstFormat) { + case GL_RED: + for (i=0;iSwapBytes) { + _mesa_swap2( (GLushort *) dst, n * comps ); + } + } + break; case GL_UNSIGNED_BYTE_3_3_2: if (dstFormat == GL_RGB) { GLubyte *dst = (GLubyte *) dstAddr; @@ -1925,6 +2011,7 @@ extract_uint_indexes(GLuint n, GLuint indexes[], srcType == GL_SHORT || srcType == GL_UNSIGNED_INT || srcType == GL_INT || + srcType == GL_HALF_FLOAT_NV || srcType == GL_FLOAT); switch (srcType) { @@ -2062,6 +2149,23 @@ extract_uint_indexes(GLuint n, GLuint indexes[], } } break; + case GL_HALF_FLOAT_NV: + { + GLuint i; + const GLhalfNV *s = (const GLhalfNV *) src; + if (unpack->SwapBytes) { + for (i = 0; i < n; i++) { + GLhalfNV value = s[i]; + SWAP2BYTE(value); + indexes[i] = (GLuint) _mesa_half_to_float(value); + } + } + else { + for (i = 0; i < n; i++) + indexes[i] = (GLuint) _mesa_half_to_float(s[i]); + } + } + break; default: _mesa_problem(NULL, "bad srcType in extract_uint_indexes"); return; @@ -2113,6 +2217,7 @@ extract_float_rgba(GLuint n, GLfloat rgba[][4], srcType == GL_SHORT || srcType == GL_UNSIGNED_INT || srcType == GL_INT || + srcType == GL_HALF_FLOAT_NV || srcType == GL_FLOAT || srcType == GL_UNSIGNED_BYTE_3_3_2 || srcType == GL_UNSIGNED_BYTE_2_3_3_REV || @@ -2291,6 +2396,12 @@ extract_float_rgba(GLuint n, GLfloat rgba[][4], PROCESS(blueIndex, BCOMP, 0.0F, GLfloat, (GLfloat)); PROCESS(alphaIndex, ACOMP, 1.0F, GLfloat, (GLfloat)); break; + case GL_HALF_FLOAT_NV: + PROCESS(redIndex, RCOMP, 0.0F, GLhalfNV, _mesa_half_to_float); + PROCESS(greenIndex, GCOMP, 0.0F, GLhalfNV, _mesa_half_to_float); + PROCESS(blueIndex, BCOMP, 0.0F, GLhalfNV, _mesa_half_to_float); + PROCESS(alphaIndex, ACOMP, 1.0F, GLhalfNV, _mesa_half_to_float); + break; case GL_UNSIGNED_BYTE_3_3_2: { const GLubyte *ubsrc = (const GLubyte *) src; @@ -2626,6 +2737,7 @@ _mesa_unpack_chan_color_span( GLcontext *ctx, srcType == GL_SHORT || srcType == GL_UNSIGNED_INT || srcType == GL_INT || + srcType == GL_HALF_FLOAT_NV || srcType == GL_FLOAT || srcType == GL_UNSIGNED_BYTE_3_3_2 || srcType == GL_UNSIGNED_BYTE_2_3_3_REV || @@ -3019,6 +3131,7 @@ _mesa_unpack_float_color_span( GLcontext *ctx, srcType == GL_SHORT || srcType == GL_UNSIGNED_INT || srcType == GL_INT || + srcType == GL_HALF_FLOAT_NV || srcType == GL_FLOAT || srcType == GL_UNSIGNED_BYTE_3_3_2 || srcType == GL_UNSIGNED_BYTE_2_3_3_REV || @@ -3285,6 +3398,7 @@ _mesa_unpack_index_span( const GLcontext *ctx, GLuint n, srcType == GL_SHORT || srcType == GL_UNSIGNED_INT || srcType == GL_INT || + srcType == GL_HALF_FLOAT_NV || srcType == GL_FLOAT); ASSERT(dstType == GL_UNSIGNED_BYTE || @@ -3457,6 +3571,18 @@ _mesa_pack_index_span( const GLcontext *ctx, GLuint n, } } break; + case GL_HALF_FLOAT_NV: + { + GLhalfNV *dst = (GLhalfNV *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = _mesa_float_to_half((GLfloat) source[i]); + } + if (dstPacking->SwapBytes) { + _mesa_swap2( (GLushort *) dst, n ); + } + } + break; default: _mesa_problem(ctx, "bad type in _mesa_pack_index_span"); } @@ -3491,6 +3617,7 @@ _mesa_unpack_stencil_span( const GLcontext *ctx, GLuint n, srcType == GL_SHORT || srcType == GL_UNSIGNED_INT || srcType == GL_INT || + srcType == GL_HALF_FLOAT_NV || srcType == GL_FLOAT); ASSERT(dstType == GL_UNSIGNED_BYTE || @@ -3677,6 +3804,18 @@ _mesa_pack_stencil_span( const GLcontext *ctx, GLuint n, } } break; + case GL_HALF_FLOAT_NV: + { + GLhalfNV *dst = (GLhalfNV *) dest; + GLuint i; + for (i=0;iSwapBytes) { + _mesa_swap2( (GLushort *) dst, n ); + } + } + break; case GL_BITMAP: if (dstPacking->LsbFirst) { GLubyte *dst = (GLubyte *) dest; @@ -3778,6 +3917,15 @@ _mesa_unpack_depth_span( const GLcontext *ctx, GLuint n, GLfloat *dest, case GL_FLOAT: MEMCPY(dest, source, n * sizeof(GLfloat)); break; + case GL_HALF_FLOAT_NV: + { + GLuint i; + const GLhalfNV *src = (const GLhalfNV *) source; + for (i = 0; i < n; i++) { + dest[i] = _mesa_half_to_float(src[i]); + } + } + break; default: _mesa_problem(NULL, "bad type in _mesa_unpack_depth_span()"); return; @@ -3898,6 +4046,18 @@ _mesa_pack_depth_span( const GLcontext *ctx, GLuint n, GLvoid *dest, } } break; + case GL_HALF_FLOAT_NV: + { + GLhalfNV *dst = (GLhalfNV *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = _mesa_float_to_half(depthSpan[i]); + } + if (dstPacking->SwapBytes) { + _mesa_swap2( (GLushort *) dst, n ); + } + } + break; default: _mesa_problem(ctx, "bad type in _mesa_pack_depth_span"); } diff --git a/src/mesa/main/imports.c b/src/mesa/main/imports.c index 6420303a4ee..d8549f2b10f 100644 --- a/src/mesa/main/imports.c +++ b/src/mesa/main/imports.c @@ -353,6 +353,9 @@ static void init_sqrt_table(void) } +/** + * Single precision square root. + */ float _mesa_sqrtf( float x ) { @@ -497,7 +500,9 @@ _mesa_inv_sqrtf(float n) } -/** Wrapper around either pow() or xf86pow() */ +/** + * Wrapper around either pow() or xf86pow(). + */ double _mesa_pow(double x, double y) { @@ -509,7 +514,7 @@ _mesa_pow(double x, double y) } -/* +/** * Return number of bits set in given GLuint. */ unsigned int @@ -522,6 +527,141 @@ _mesa_bitcount(unsigned int n) return bits; } + +/** + * Convert a 4-byte float to a 2-byte half float. + */ +GLhalfNV +_mesa_float_to_half(float val) +{ + const int flt = *((int *) &val); + const int flt_m = flt & 0x7fffff; + const int flt_e = (flt >> 23) & 0xff; + const int flt_s = (flt >> 31) & 0x1; + int s, e, m; + GLhalfNV result; + + /* sign bit */ + s = flt_s; + + /* handle special cases */ + if ((flt_e == 0) && (flt_m == 0)) { + /* zero */ + m = 0; + e = 0; + } + else if ((flt_e == 0) && (flt_m != 0)) { + /* denorm -- denorm float maps to 0 half */ + m = 0; + e = 0; + } + else if ((flt_e == 0xff) && (flt_m == 0)) { + /* infinity */ + m = 0; + e = 31; + } + else if ((flt_e == 0xff) && (flt_m != 0)) { + /* NaN */ + m = 1; + e = 31; + } + else { + /* regular number */ + const int new_exp = flt_e - 127; + if (new_exp < -24) { + /* this maps to 0 */ + m = 0; + e = 0; + } + else if (new_exp < -14) { + /* this maps to a denorm */ + unsigned int exp_val = (unsigned int) (-14 - new_exp); /* 2^-exp_val*/ + e = 0; + switch (exp_val) { + case 0: + _mesa_warning(NULL, + "float_to_half: logical error in denorm creation!\n"); + m = 0; + break; + case 1: m = 512 + (flt_m >> 14); break; + case 2: m = 256 + (flt_m >> 15); break; + case 3: m = 128 + (flt_m >> 16); break; + case 4: m = 64 + (flt_m >> 17); break; + case 5: m = 32 + (flt_m >> 18); break; + case 6: m = 16 + (flt_m >> 19); break; + case 7: m = 8 + (flt_m >> 20); break; + case 8: m = 4 + (flt_m >> 21); break; + case 9: m = 2 + (flt_m >> 22); break; + case 10: m = 1; break; + } + } + else if (new_exp > 15) { + /* map this value to infinity */ + m = 0; + e = 31; + } + else { + /* regular */ + e = new_exp + 15; + m = flt_m >> 13; + } + } + + result = (s << 15) | (e << 10) | m; + return result; +} + + +/** + * Convert a 2-byte half float to a 4-byte float. + */ +float +_mesa_half_to_float(GLhalfNV val) +{ + /* XXX could also use a 64K-entry lookup table */ + const int m = val & 0x3ff; + const int e = (val >> 10) & 0x1f; + const int s = (val >> 15) & 0x1; + int flt_m, flt_e, flt_s, flt; + float result; + + /* sign bit */ + flt_s = s; + + /* handle special cases */ + if ((e == 0) && (m == 0)) { + /* zero */ + flt_m = 0; + flt_e = 0; + } + else if ((e == 0) && (m != 0)) { + /* denorm -- denorm half will fit in non-denorm single */ + const float half_denorm = 1.0f / 16384.0f; /* 2^-14 */ + float mantissa = ((float) (m)) / 1024.0f; + float sign = s ? -1.0f : 1.0f; + return sign * mantissa * half_denorm; + } + else if ((e == 31) && (m == 0)) { + /* infinity */ + flt_e = 0xff; + flt_m = 0; + } + else if ((e == 31) && (m != 0)) { + /* NaN */ + flt_e = 0xff; + flt_m = 1; + } + else { + /* regular */ + flt_e = e + 112; + flt_m = m << 13; + } + + flt = (flt_s << 31) | (flt_e << 23) | flt_m; + result = *((float *) &flt); + return result; +} + /*@}*/ @@ -529,7 +669,9 @@ _mesa_bitcount(unsigned int n) /** \name Environment vars */ /*@{*/ -/** Wrapper around either () or xf86() */ +/** + * Wrapper for getenv(). + */ char * _mesa_getenv( const char *var ) { diff --git a/src/mesa/main/imports.h b/src/mesa/main/imports.h index 2c9c2fc3429..0c0a291e164 100644 --- a/src/mesa/main/imports.h +++ b/src/mesa/main/imports.h @@ -696,6 +696,12 @@ _mesa_log2(float x); extern unsigned int _mesa_bitcount(unsigned int n); +extern GLhalfNV +_mesa_float_to_half(float f); + +extern float +_mesa_half_to_float(GLhalfNV h); + extern char * _mesa_getenv( const char *var ); -- cgit v1.2.3