Mesa (master): mesa: implement EXT_texture_shared_exponent

Marek Olšák mareko at kemper.freedesktop.org
Fri Apr 29 02:36:28 PDT 2011


Module: Mesa
Branch: master
Commit: 9d7698c468f4ea7da8bb4ec00520c98f11cca0fa
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=9d7698c468f4ea7da8bb4ec00520c98f11cca0fa

Author: Marek Olšák <maraeo at gmail.com>
Date:   Tue Apr 26 02:18:24 2011 +0200

mesa: implement EXT_texture_shared_exponent

swrast support done.

There is no renderbuffer support in swrast, because it's not required
by the extension.

Reviewed-by: Brian Paul <brianp at vmware.com>

---

 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(-)

diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c
index 82474cf..e0562cc 100644
--- a/src/mesa/main/extensions.c
+++ b/src/mesa/main/extensions.c
@@ -502,6 +502,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);
+   }
+}
+
+/* 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);
+            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 },
 };
 
 



More information about the mesa-commit mailing list