[Mesa-dev] [PATCH 2/5] mesa: implement EXT_texture_shared_exponent

Ian Romanick idr at freedesktop.org
Tue Apr 26 11:11:19 PDT 2011


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 04/26/2011 03:57 AM, Marek Olšák wrote:
> swrast support done.
> 
> There is no renderbuffer support in swrast, because it's not required
> by the extension.
> ---
>  src/mesa/main/extensions.c   |    1 +
>  src/mesa/main/fbobject.c     |   11 +++
>  src/mesa/main/formats.c      |   16 ++++-
>  src/mesa/main/formats.h      |    2 +
>  src/mesa/main/image.c        |   11 +++
>  src/mesa/main/mipmap.c       |   49 ++++++++++++
>  src/mesa/main/pack.c         |   82 +++++++++++++++++++-
>  src/mesa/main/rgb9e5.h       |  173 ++++++++++++++++++++++++++++++++++++++++++
>  src/mesa/main/texfetch.c     |    8 ++
>  src/mesa/main/texfetch_tmp.h |   21 +++++
>  src/mesa/main/texformat.c    |   10 +++
>  src/mesa/main/texparam.c     |    8 +-
>  src/mesa/main/texstore.c     |   57 ++++++++++++++
>  13 files changed, 438 insertions(+), 11 deletions(-)
>  create mode 100644 src/mesa/main/rgb9e5.h
> 
> diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c
> index 8a0ab96..67d0e4c 100644
> --- a/src/mesa/main/extensions.c
> +++ b/src/mesa/main/extensions.c
> @@ -501,6 +501,7 @@ _mesa_enable_sw_extensions(struct gl_context *ctx)
>     ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE;
>     ctx->Extensions.EXT_texture_mirror_clamp = GL_TRUE;
>     ctx->Extensions.EXT_texture_lod_bias = GL_TRUE;
> +   ctx->Extensions.EXT_texture_shared_exponent = GL_TRUE;
>  #if FEATURE_EXT_texture_sRGB
>     ctx->Extensions.EXT_texture_sRGB = GL_TRUE;
>     ctx->Extensions.EXT_texture_sRGB_decode = GL_TRUE;
> diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c
> index 1edb310..b07161e 100644
> --- a/src/mesa/main/fbobject.c
> +++ b/src/mesa/main/fbobject.c
> @@ -418,6 +418,15 @@ _mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
>           case GL_RG:
>              fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
>              return;
> +         case GL_RGB:
> +            switch (rb->Format) {
> +            case MESA_FORMAT_RGB9_E5_FLOAT:
> +               fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
> +               return;
> +            default:;
> +            }
> +            break;
> +
>           default:
>              /* render buffer format is supported by software rendering */
>              ;
> @@ -1175,6 +1184,8 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat)
>     case GL_INTENSITY32F_ARB:
>        return ctx->Extensions.ARB_texture_float &&
>               ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
> +   case GL_RGB9_E5:
> +      return ctx->Extensions.EXT_texture_shared_exponent ? GL_RGB : 0;
>     /* XXX add integer formats eventually */
>     default:
>        return 0;
> diff --git a/src/mesa/main/formats.c b/src/mesa/main/formats.c
> index 4c31ccb..6105ba1 100644
> --- a/src/mesa/main/formats.c
> +++ b/src/mesa/main/formats.c
> @@ -1072,7 +1072,16 @@ static struct gl_format_info format_info[MESA_FORMAT_COUNT] =
>        0, 0, 0, 0,
>        0, 16, 0, 0, 0,
>        1, 1, 2
> -   }
> +   },
> +   {
> +      MESA_FORMAT_RGB9_E5_FLOAT,
> +      "MESA_FORMAT_RGB9_E5",
> +      GL_RGB,
> +      GL_FLOAT,
> +      9, 9, 9, 0,
> +      0, 0, 0, 0, 0,
> +      1, 1, 4
> +   },
>  };
>  
>  
> @@ -1803,6 +1812,11 @@ _mesa_format_to_type_and_comps(gl_format format,
>        *comps = 4;
>        return;
>  
> +   case MESA_FORMAT_RGB9_E5_FLOAT:
> +      *datatype = GL_UNSIGNED_INT_5_9_9_9_REV;
> +      *comps = 3;
> +      return;
> +
>     case MESA_FORMAT_COUNT:
>        assert(0);
>        return;
> diff --git a/src/mesa/main/formats.h b/src/mesa/main/formats.h
> index 15ac62c..68d6e98 100644
> --- a/src/mesa/main/formats.h
> +++ b/src/mesa/main/formats.h
> @@ -206,6 +206,8 @@ typedef enum
>     MESA_FORMAT_SIGNED_AL1616,     /* AAAA AAAA AAAA AAAA LLLL LLLL LLLL LLLL */
>     MESA_FORMAT_SIGNED_I16,        /*                     IIII IIII IIII IIII */
>  
> +   MESA_FORMAT_RGB9_E5_FLOAT,
> +
>     MESA_FORMAT_COUNT
>  } gl_format;
>  
> diff --git a/src/mesa/main/image.c b/src/mesa/main/image.c
> index 28841c2..3e9f996 100644
> --- a/src/mesa/main/image.c
> +++ b/src/mesa/main/image.c
> @@ -82,6 +82,7 @@ _mesa_type_is_packed(GLenum type)
>     case GL_UNSIGNED_SHORT_8_8_MESA:
>     case GL_UNSIGNED_SHORT_8_8_REV_MESA:
>     case GL_UNSIGNED_INT_24_8_EXT:
> +   case GL_UNSIGNED_INT_5_9_9_9_REV:
>        return GL_TRUE;
>     }
>  
> @@ -222,6 +223,8 @@ _mesa_sizeof_packed_type( GLenum type )
>           return sizeof(GLushort);      
>        case GL_UNSIGNED_INT_24_8_EXT:
>           return sizeof(GLuint);
> +      case GL_UNSIGNED_INT_5_9_9_9_REV:
> +         return sizeof(GLuint);
>        default:
>           return -1;
>     }
> @@ -363,6 +366,11 @@ _mesa_bytes_per_pixel( GLenum format, GLenum type )
>              return sizeof(GLuint);
>           else
>              return -1;
> +      case GL_UNSIGNED_INT_5_9_9_9_REV:
> +         if (format == GL_RGB)
> +            return sizeof(GLuint);
> +         else
> +            return -1;
>        default:
>           return -1;
>     }
> @@ -458,6 +466,8 @@ _mesa_is_legal_format_and_type(const struct gl_context *ctx,
>                 return GL_TRUE;
>              case GL_HALF_FLOAT_ARB:
>                 return ctx->Extensions.ARB_half_float_pixel;
> +            case GL_UNSIGNED_INT_5_9_9_9_REV:
> +               return ctx->Extensions.EXT_texture_shared_exponent;
>              default:
>                 return GL_FALSE;
>           }
> @@ -821,6 +831,7 @@ _mesa_is_color_format(GLenum format)
>        case GL_INTENSITY_SNORM:
>        case GL_INTENSITY8_SNORM:
>        case GL_INTENSITY16_SNORM:
> +      case GL_RGB9_E5:
>           return GL_TRUE;
>        case GL_YCBCR_MESA:  /* not considered to be RGB */
>           /* fall-through */
> diff --git a/src/mesa/main/mipmap.c b/src/mesa/main/mipmap.c
> index 0578631..88cb5b5 100644
> --- a/src/mesa/main/mipmap.c
> +++ b/src/mesa/main/mipmap.c
> @@ -34,6 +34,8 @@
>  #include "teximage.h"
>  #include "texstore.h"
>  #include "image.h"
> +#include "macros.h"
> +#include "rgb9e5.h"
>  
>  
>  
> @@ -665,6 +667,25 @@ do_row(GLenum datatype, GLuint comps, GLint srcWidth,
>        }
>     }
>  
> +   else if (datatype == GL_UNSIGNED_INT_5_9_9_9_REV && comps == 3) {
> +      GLuint i, j, k;
> +      const GLuint *rowA = (const GLuint*) srcRowA;
> +      const GLuint *rowB = (const GLuint*) srcRowB;
> +      GLuint *dst = (GLuint*)dstRow;
> +      GLfloat res[3], rowAj[3], rowBj[3], rowAk[3], rowBk[3];
> +      for (i = j = 0, k = k0; i < (GLuint) dstWidth;
> +           i++, j += colStride, k += colStride) {
> +         rgb9e5_to_float3(rowA[j], rowAj);
> +         rgb9e5_to_float3(rowB[j], rowBj);
> +         rgb9e5_to_float3(rowA[k], rowAk);
> +         rgb9e5_to_float3(rowB[k], rowBk);
> +         res[0] = (rowAj[0] + rowAk[0] + rowBj[0] + rowBk[0]) * 0.25F;
> +         res[1] = (rowAj[1] + rowAk[1] + rowBj[1] + rowBk[1]) * 0.25F;
> +         res[2] = (rowAj[2] + rowAk[2] + rowBj[2] + rowBk[2]) * 0.25F;
> +         dst[i] = float3_to_rgb9e5(res);
> +      }
> +   }
> +
>     else {
>        _mesa_problem(NULL, "bad format in do_row()");
>     }
> @@ -1245,6 +1266,34 @@ do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth,
>           dst[i] = (a << 30) | (b << 20) | (g << 10) | r;
>        }
>     }
> +
> +   else if (datatype == GL_UNSIGNED_INT_5_9_9_9_REV && comps == 3) {
> +      DECLARE_ROW_POINTERS0(GLuint);
> +
> +      GLfloat res[3];
> +      GLfloat rowAj[3], rowBj[3], rowCj[3], rowDj[3];
> +      GLfloat rowAk[3], rowBk[3], rowCk[3], rowDk[3];
> +
> +      for (i = j = 0, k = k0; i < (GLuint) dstWidth;
> +           i++, j += colStride, k += colStride) {
> +         rgb9e5_to_float3(rowA[j], rowAj);
> +         rgb9e5_to_float3(rowB[j], rowBj);
> +         rgb9e5_to_float3(rowC[j], rowCj);
> +         rgb9e5_to_float3(rowD[j], rowDj);
> +         rgb9e5_to_float3(rowA[k], rowAk);
> +         rgb9e5_to_float3(rowB[k], rowBk);
> +         rgb9e5_to_float3(rowC[k], rowCk);
> +         rgb9e5_to_float3(rowD[k], rowDk);
> +         res[0] = (rowAj[0] + rowAk[0] + rowBj[0] + rowBk[0] +
> +                   rowCj[0] + rowCk[0] + rowDj[0] + rowDk[0]) * 0.125F;
> +         res[1] = (rowAj[1] + rowAk[1] + rowBj[1] + rowBk[1] +
> +                   rowCj[1] + rowCk[1] + rowDj[1] + rowDk[1]) * 0.125F;
> +         res[2] = (rowAj[2] + rowAk[2] + rowBj[2] + rowBk[2] +
> +                   rowCj[2] + rowCk[2] + rowDj[2] + rowDk[2]) * 0.125F;
> +         dst[i] = float3_to_rgb9e5(res);
> +      }
> +   }
> +
>     else {
>        _mesa_problem(NULL, "bad format in do_row()");
>     }
> diff --git a/src/mesa/main/pack.c b/src/mesa/main/pack.c
> index ad8ab9d..37608f2 100644
> --- a/src/mesa/main/pack.c
> +++ b/src/mesa/main/pack.c
> @@ -37,6 +37,8 @@
>  #include "mtypes.h"
>  #include "pack.h"
>  #include "pixeltransfer.h"
> +#include "imports.h"
> +#include "rgb9e5.h"
>  
>  
>  /**
> @@ -1892,6 +1894,14 @@ _mesa_pack_rgba_span_float(struct gl_context *ctx, GLuint n, GLfloat rgba[][4],
>              }
>           }
>           break;
> +      case GL_UNSIGNED_INT_5_9_9_9_REV:
> +         {
> +            GLuint *dst = (GLuint *) dstAddr;
> +            for (i = 0; i < n; i++) {
> +               dst[i] = float3_to_rgb9e5(rgba[i]);
> +            }
> +         }
> +         break;
>        default:
>           _mesa_problem(ctx, "bad type in _mesa_pack_rgba_span_float");
>           return;
> @@ -2330,7 +2340,8 @@ extract_float_rgba(GLuint n, GLfloat rgba[][4],
>            srcType == GL_UNSIGNED_INT_8_8_8_8 ||
>            srcType == GL_UNSIGNED_INT_8_8_8_8_REV ||
>            srcType == GL_UNSIGNED_INT_10_10_10_2 ||
> -          srcType == GL_UNSIGNED_INT_2_10_10_10_REV);
> +          srcType == GL_UNSIGNED_INT_2_10_10_10_REV ||
> +          srcType == GL_UNSIGNED_INT_5_9_9_9_REV);
>  
>     get_component_mapping(srcFormat,
>                           &rSrc, &gSrc, &bSrc, &aSrc,
> @@ -2800,6 +2811,34 @@ extract_float_rgba(GLuint n, GLfloat rgba[][4],
>              }
>           }
>           break;
> +      case GL_UNSIGNED_INT_5_9_9_9_REV:
> +         if (swapBytes) {
> +            const GLuint *uisrc = (const GLuint *) src;
> +            GLuint i;
> +            GLfloat f[3];
> +            for (i = 0; i < n; i ++) {
> +               GLuint p = uisrc[i];
> +               SWAP4BYTE(p);
> +               rgb9e5_to_float3(p, f);
> +               rgba[i][rDst] = f[0];
> +               rgba[i][gDst] = f[1];
> +               rgba[i][bDst] = f[2];
> +               rgba[i][aDst] = 1.0F;
> +            }
> +         }
> +         else {
> +            const GLuint *uisrc = (const GLuint *) src;
> +            GLuint i;
> +            GLfloat f[3];
> +            for (i = 0; i < n; i ++) {
> +               rgb9e5_to_float3(uisrc[i], f);
> +               rgba[i][rDst] = f[0];
> +               rgba[i][gDst] = f[1];
> +               rgba[i][bDst] = f[2];
> +               rgba[i][aDst] = 1.0F;
> +            }
> +         }
> +         break;
>        default:
>           _mesa_problem(NULL, "bad srcType in extract float data");
>           break;
> @@ -2902,7 +2941,8 @@ extract_uint_rgba(GLuint n, GLuint rgba[][4],
>            srcType == GL_UNSIGNED_INT_8_8_8_8 ||
>            srcType == GL_UNSIGNED_INT_8_8_8_8_REV ||
>            srcType == GL_UNSIGNED_INT_10_10_10_2 ||
> -          srcType == GL_UNSIGNED_INT_2_10_10_10_REV);
> +          srcType == GL_UNSIGNED_INT_2_10_10_10_REV ||
> +          srcType == GL_UNSIGNED_INT_5_9_9_9_REV);
>  
>     get_component_mapping(srcFormat,
>                           &rSrc, &gSrc, &bSrc, &aSrc,
> @@ -3266,6 +3306,35 @@ extract_uint_rgba(GLuint n, GLuint rgba[][4],
>              }
>           }
>           break;
> +      case GL_UNSIGNED_INT_5_9_9_9_REV:
> +         if (swapBytes) {
> +            const GLuint *uisrc = (const GLuint *) src;
> +            GLuint i;
> +            float f[3];
> +            for (i = 0; i < n; i ++) {
> +               GLuint p = uisrc[i];
> +               SWAP4BYTE(p);
> +               rgb9e5_to_float3(p, f);
> +               rgba[i][rDst] = clamp_float_to_uint(f[0]);
> +               rgba[i][gDst] = clamp_float_to_uint(f[1]);
> +               rgba[i][bDst] = clamp_float_to_uint(f[2]);
> +               rgba[i][aDst] = 1;
> +            }
> +         }
> +         else {
> +            const GLuint *uisrc = (const GLuint *) src;
> +            GLuint i;
> +            float f[3];
> +            for (i = 0; i < n; i ++) {
> +               GLuint p = uisrc[i];
> +               rgb9e5_to_float3(p, f);
> +               rgba[i][rDst] = clamp_float_to_uint(f[0]);
> +               rgba[i][gDst] = clamp_float_to_uint(f[1]);
> +               rgba[i][bDst] = clamp_float_to_uint(f[2]);
> +               rgba[i][aDst] = 1;
> +            }
> +         }
> +         break;
>        default:
>           _mesa_problem(NULL, "bad srcType in extract uint data");
>           break;
> @@ -3345,7 +3414,8 @@ _mesa_unpack_color_span_chan( struct gl_context *ctx,
>            srcType == GL_UNSIGNED_INT_8_8_8_8 ||
>            srcType == GL_UNSIGNED_INT_8_8_8_8_REV ||
>            srcType == GL_UNSIGNED_INT_10_10_10_2 ||
> -          srcType == GL_UNSIGNED_INT_2_10_10_10_REV);
> +          srcType == GL_UNSIGNED_INT_2_10_10_10_REV ||
> +          srcType == GL_UNSIGNED_INT_5_9_9_9_REV);
>  
>     /* Try simple cases first */
>     if (transferOps == 0) {
> @@ -3667,7 +3737,8 @@ _mesa_unpack_color_span_float( struct gl_context *ctx,
>            srcType == GL_UNSIGNED_INT_8_8_8_8 ||
>            srcType == GL_UNSIGNED_INT_8_8_8_8_REV ||
>            srcType == GL_UNSIGNED_INT_10_10_10_2 ||
> -          srcType == GL_UNSIGNED_INT_2_10_10_10_REV);
> +          srcType == GL_UNSIGNED_INT_2_10_10_10_REV ||
> +          srcType == GL_UNSIGNED_INT_5_9_9_9_REV);
>  
>     /* general solution, no special cases, yet */
>     {
> @@ -3873,7 +3944,8 @@ _mesa_unpack_color_span_uint(struct gl_context *ctx,
>            srcType == GL_UNSIGNED_INT_8_8_8_8 ||
>            srcType == GL_UNSIGNED_INT_8_8_8_8_REV ||
>            srcType == GL_UNSIGNED_INT_10_10_10_2 ||
> -          srcType == GL_UNSIGNED_INT_2_10_10_10_REV);
> +          srcType == GL_UNSIGNED_INT_2_10_10_10_REV ||
> +          srcType == GL_UNSIGNED_INT_5_9_9_9_REV);
>  
>  
>     /* Extract image data as uint[4] pixels */
> diff --git a/src/mesa/main/rgb9e5.h b/src/mesa/main/rgb9e5.h
> new file mode 100644
> index 0000000..9bb431f
> --- /dev/null
> +++ b/src/mesa/main/rgb9e5.h
> @@ -0,0 +1,173 @@
> +/*
> + * Copyright (C) 2011 Marek Olšák <maraeo at gmail.com>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + */
> +
> +/* Copied from EXT_texture_shared_exponent and edited. */
> +
> +#ifndef RGB9E5_H
> +#define RGB9E5_H
> +
> +#include <math.h>
> +#include <assert.h>
> +
> +#define RGB9E5_EXPONENT_BITS          5
> +#define RGB9E5_MANTISSA_BITS          9
> +#define RGB9E5_EXP_BIAS               15
> +#define RGB9E5_MAX_VALID_BIASED_EXP   31
> +
> +#define MAX_RGB9E5_EXP               (RGB9E5_MAX_VALID_BIASED_EXP - RGB9E5_EXP_BIAS)
> +#define RGB9E5_MANTISSA_VALUES       (1<<RGB9E5_MANTISSA_BITS)
> +#define MAX_RGB9E5_MANTISSA          (RGB9E5_MANTISSA_VALUES-1)
> +#define MAX_RGB9E5                   (((float)MAX_RGB9E5_MANTISSA)/RGB9E5_MANTISSA_VALUES * (1<<MAX_RGB9E5_EXP))
> +#define EPSILON_RGB9E5               ((1.0/RGB9E5_MANTISSA_VALUES) / (1<<RGB9E5_EXP_BIAS))
> +
> +typedef union {
> +   unsigned int raw;
> +   float value;
> +   struct {
> +#if defined(MESA_BIG_ENDIAN) || defined(PIPE_ARCH_BIG_ENDIAN)
> +      unsigned int negative:1;
> +      unsigned int biasedexponent:8;
> +      unsigned int mantissa:23;
> +#else
> +      unsigned int mantissa:23;
> +      unsigned int biasedexponent:8;
> +      unsigned int negative:1;
> +#endif
> +   } field;
> +} float754;
> +
> +typedef union {
> +   unsigned int raw;
> +   struct {
> +#if defined(MESA_BIG_ENDIAN) || defined(PIPE_ARCH_BIG_ENDIAN)
> +      unsigned int biasedexponent:RGB9E5_EXPONENT_BITS;
> +      unsigned int b:RGB9E5_MANTISSA_BITS;
> +      unsigned int g:RGB9E5_MANTISSA_BITS;
> +      unsigned int r:RGB9E5_MANTISSA_BITS;
> +#else
> +      unsigned int r:RGB9E5_MANTISSA_BITS;
> +      unsigned int g:RGB9E5_MANTISSA_BITS;
> +      unsigned int b:RGB9E5_MANTISSA_BITS;
> +      unsigned int biasedexponent:RGB9E5_EXPONENT_BITS;
> +#endif
> +   } field;
> +} rgb9e5;
> +
> +static INLINE float rgb9e5_ClampRange(float x)
> +{
> +   if (x > 0.0) {
> +      if (x >= MAX_RGB9E5) {
> +         return MAX_RGB9E5;
> +      } else {
> +         return x;
> +      }
> +   } else {
> +      /* NaN gets here too since comparisons with NaN always fail! */
> +      return 0.0;
> +   }
> +}
> +
> +static INLINE float rgb9e5_MaxOf3(float x, float y, float z)
> +{
> +   if (x > y) {
> +      return MAX2(x, z);
> +   } else {
> +      return MAX2(y, z);
> +   }
> +}

This could probably be a MAX3 macro defined in the same place as the
existing MAX2 macro.  Also, why did you implement as you did instead of

	MAX2(MAX2(x,y),z)

Just curious...

> +
> +/* Ok, FloorLog2 is not correct for the denorm and zero values, but we
> +   are going to do a max of this value with the minimum rgb9e5 exponent
> +   that will hide these problem cases. */
> +static INLINE int rgb9e5_FloorLog2(float x)
> +{
> +   float754 f;
> +
> +   f.value = x;
> +   return (f.field.biasedexponent - 127);
> +}
> +
> +static INLINE unsigned float3_to_rgb9e5(const float rgb[3])
> +{
> +   rgb9e5 retval;
> +   float maxrgb;
> +   int rm, gm, bm;
> +   float rc, gc, bc;
> +   int exp_shared, maxm;
> +   double denom;
> +
> +   rc = rgb9e5_ClampRange(rgb[0]);
> +   gc = rgb9e5_ClampRange(rgb[1]);
> +   bc = rgb9e5_ClampRange(rgb[2]);
> +
> +   maxrgb = rgb9e5_MaxOf3(rc, gc, bc);
> +   exp_shared = MAX2(-RGB9E5_EXP_BIAS-1, rgb9e5_FloorLog2(maxrgb)) + 1 + RGB9E5_EXP_BIAS;
> +   assert(exp_shared <= RGB9E5_MAX_VALID_BIASED_EXP);
> +   assert(exp_shared >= 0);
> +   /* This pow function could be replaced by a table. */
> +   denom = pow(2, exp_shared - RGB9E5_EXP_BIAS - RGB9E5_MANTISSA_BITS);
> +
> +   maxm = (int) floor(maxrgb / denom + 0.5);
> +   if (maxm == MAX_RGB9E5_MANTISSA+1) {
> +      denom *= 2;
> +      exp_shared += 1;
> +      assert(exp_shared <= RGB9E5_MAX_VALID_BIASED_EXP);
> +   } else {
> +      assert(maxm <= MAX_RGB9E5_MANTISSA);
> +   }
> +
> +   rm = (int) floor(rc / denom + 0.5);
> +   gm = (int) floor(gc / denom + 0.5);
> +   bm = (int) floor(bc / denom + 0.5);
> +
> +   assert(rm <= MAX_RGB9E5_MANTISSA);
> +   assert(gm <= MAX_RGB9E5_MANTISSA);
> +   assert(bm <= MAX_RGB9E5_MANTISSA);
> +   assert(rm >= 0);
> +   assert(gm >= 0);
> +   assert(bm >= 0);
> +
> +   retval.field.r = rm;
> +   retval.field.g = gm;
> +   retval.field.b = bm;
> +   retval.field.biasedexponent = exp_shared;
> +
> +   return retval.raw;
> +}
> +
> +static INLINE void rgb9e5_to_float3(unsigned rgb, float retval[3])
> +{
> +   rgb9e5 v;
> +   int exponent;
> +   float scale;
> +
> +   v.raw = rgb;
> +   exponent = v.field.biasedexponent - RGB9E5_EXP_BIAS - RGB9E5_MANTISSA_BITS;
> +   scale = (float) pow(2, exponent);
> +
> +   retval[0] = v.field.r * scale;
> +   retval[1] = v.field.g * scale;
> +   retval[2] = v.field.b * scale;
> +}
> +
> +#endif
> diff --git a/src/mesa/main/texfetch.c b/src/mesa/main/texfetch.c
> index d091789..4acc938 100644
> --- a/src/mesa/main/texfetch.c
> +++ b/src/mesa/main/texfetch.c
> @@ -41,6 +41,7 @@
>  #include "texcompress_rgtc.h"
>  #include "texfetch.h"
>  #include "teximage.h"
> +#include "rgb9e5.h"
>  
>  
>  /**
> @@ -898,6 +899,13 @@ texfetch_funcs[MESA_FORMAT_COUNT] =
>        fetch_texel_3d_signed_i16,
>        store_texel_signed_i16
>     },
> +   {
> +      MESA_FORMAT_RGB9_E5_FLOAT,
> +      fetch_texel_1d_rgb9_e5,
> +      fetch_texel_2d_rgb9_e5,
> +      fetch_texel_3d_rgb9_e5,
> +      store_texel_rgb9_e5
> +   },
>  };
>  
>  
> diff --git a/src/mesa/main/texfetch_tmp.h b/src/mesa/main/texfetch_tmp.h
> index 0b9d5da..106b812 100644
> --- a/src/mesa/main/texfetch_tmp.h
> +++ b/src/mesa/main/texfetch_tmp.h
> @@ -2332,6 +2332,27 @@ static void store_texel_s8_z24(struct gl_texture_image *texImage,
>  #endif
>  
>  
> +/* MESA_FORMAT_RGB9_E5 ******************************************************/
> +
> +static void FETCH(rgb9_e5)( const struct gl_texture_image *texImage,
> +                            GLint i, GLint j, GLint k, GLfloat *texel )
> +{
> +   const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
> +   rgb9e5_to_float3(*src, texel);
> +   texel[ACOMP] = 1.0F;
> +}
> +
> +#if DIM == 3
> +static void store_texel_rgb9_e5(struct gl_texture_image *texImage,
> +                                GLint i, GLint j, GLint k, const void *texel)
> +{
> +   const GLfloat *src = (const GLfloat *) texel;
> +   GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
> +   *dst = float3_to_rgb9e5(src);
> +}
> +#endif
> +
> +
>  #undef TEXEL_ADDR
>  #undef DIM
>  #undef FETCH
> diff --git a/src/mesa/main/texformat.c b/src/mesa/main/texformat.c
> index cbebec9..3520f24 100644
> --- a/src/mesa/main/texformat.c
> +++ b/src/mesa/main/texformat.c
> @@ -382,6 +382,16 @@ _mesa_choose_tex_format( struct gl_context *ctx, GLint internalFormat,
>        }
>     }
>  
> +   if (ctx->Extensions.EXT_texture_shared_exponent) {
> +      switch (internalFormat) {
> +         case GL_RGB9_E5:
> +            RETURN_IF_SUPPORTED(MESA_FORMAT_RGB9_E5_FLOAT);

I could envision the extension being enabled but the format not being
supported by the hardware.  This would be like the ARB_half_float_pixel
code.  In this case, the fallbacks should be:

   MESA_FORMAT_RGB_FLOAT16
   MESA_FORMAT_RGBA_FLOAT16
   MESA_FORMAT_RGB_FLOAT32
   MESA_FORMAT_RGBA_FLOAT32

The real question is if we ever want to enable any of these "extra
format" extensions without requireing real hardware support.  If we
don't, then these chases should assert that the format is supported.

> +            break;
> +         default:
> +            ; /* fallthrough */
> +      }
> +   }
> +
>     if (ctx->Extensions.EXT_packed_depth_stencil) {
>        switch (internalFormat) {
>           case GL_DEPTH_STENCIL_EXT:
> diff --git a/src/mesa/main/texparam.c b/src/mesa/main/texparam.c
> index 3d56dac..f86a8cf 100644
> --- a/src/mesa/main/texparam.c
> +++ b/src/mesa/main/texparam.c
> @@ -979,11 +979,9 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
>           }
>           break;
>        case GL_TEXTURE_SHARED_SIZE:
> -         if (ctx->VersionMajor >= 3) {
> -            /* XXX return number of exponent bits for shared exponent texture
> -             * formats, like GL_RGB9_E5.
> -             */
> -            *params = 0;
> +         if (ctx->VersionMajor >= 3 ||
> +             ctx->Extensions.EXT_texture_shared_exponent) {
> +            *params = texFormat == MESA_FORMAT_RGB9_E5_FLOAT ? 5 : 0;
>           }
>           else {
>              goto invalid_pname;
> diff --git a/src/mesa/main/texstore.c b/src/mesa/main/texstore.c
> index c4fe82a..5cdde45 100644
> --- a/src/mesa/main/texstore.c
> +++ b/src/mesa/main/texstore.c
> @@ -70,6 +70,7 @@
>  #include "teximage.h"
>  #include "texstore.h"
>  #include "enums.h"
> +#include "rgb9e5.h"
>  
>  
>  enum {
> @@ -4176,6 +4177,60 @@ _mesa_texstore_sla8(TEXSTORE_PARAMS)
>  
>  #endif /* FEATURE_EXT_texture_sRGB */
>  
> +static GLboolean
> +_mesa_texstore_rgb9_e5(TEXSTORE_PARAMS)
> +{
> +   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
> +
> +   ASSERT(dstFormat == MESA_FORMAT_RGB9_E5_FLOAT);
> +   ASSERT(baseInternalFormat == GL_RGB);
> +
> +   if (!ctx->_ImageTransferState &&
> +       !srcPacking->SwapBytes &&
> +       srcFormat == GL_RGB &&
> +       srcType == GL_UNSIGNED_INT_5_9_9_9_REV) {
> +      /* simple memcpy path */
> +      memcpy_texture(ctx, dims,
> +                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
> +                     dstRowStride,
> +                     dstImageOffsets,
> +                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
> +                     srcAddr, srcPacking);
> +   }
> +   else {
> +      /* general path */
> +      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
> +                                                 baseInternalFormat,
> +                                                 baseFormat,
> +                                                 srcWidth, srcHeight, srcDepth,
> +                                                 srcFormat, srcType, srcAddr,
> +                                                 srcPacking,
> +                                                 ctx->_ImageTransferState);
> +      const GLfloat *srcRow = tempImage;
> +      GLint bytesPerRow;
> +      GLint img, row, col;
> +      if (!tempImage)
> +         return GL_FALSE;
> +      bytesPerRow = srcWidth * 3 * sizeof(GLfloat);
> +      for (img = 0; img < srcDepth; img++) {
> +         GLubyte *dstRow = (GLubyte *) dstAddr
> +            + dstImageOffsets[dstZoffset + img] * 4
> +            + dstYoffset * dstRowStride
> +            + dstXoffset * 4;
> +         for (row = 0; row < srcHeight; row++) {
> +            GLuint *dstUI = (GLuint*)dstRow;
> +            for (col = 0; col < srcWidth; col++) {
> +               dstUI[col] = float3_to_rgb9e5(&srcRow[col * 3]);
> +            }
> +            dstRow += dstRowStride;
> +            srcRow += srcWidth * 3;
> +         }
> +      }
> +
> +      free((void *) tempImage);
> +   }
> +   return GL_TRUE;
> +}
>  
>  
>  
> @@ -4309,6 +4364,8 @@ texstore_funcs[MESA_FORMAT_COUNT] =
>     { MESA_FORMAT_SIGNED_L16, _mesa_texstore_snorm16 },
>     { MESA_FORMAT_SIGNED_AL1616, _mesa_texstore_snorm1616 },
>     { MESA_FORMAT_SIGNED_I16, _mesa_texstore_snorm16 },
> +
> +   { MESA_FORMAT_RGB9_E5_FLOAT, _mesa_texstore_rgb9_e5 },
>  };
>  
>  

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/

iEYEARECAAYFAk23CsYACgkQX1gOwKyEAw9roQCfacWhwoIUJ3zQu3Jl8uWjQmrL
JrsAnjuYlef9ywGsVkDYHikPWD4qiFbI
=OGT2
-----END PGP SIGNATURE-----


More information about the mesa-dev mailing list