mesa, util: move RGB9E5 conversion functions to gallium/util
[mesa.git] / src / mesa / main / texstore.c
index f5f94bbf1a47292fbefefde8bdd616b2d7c913b1..39f59e3cbd920aff3fcbaaf0daffec4ce2b473c4 100644 (file)
 #include "image.h"
 #include "macros.h"
 #include "mipmap.h"
+#include "mfeatures.h"
+#include "mtypes.h"
+#include "pack.h"
+#include "pbo.h"
 #include "imports.h"
 #include "texcompress.h"
 #include "texcompress_fxt1.h"
+#include "texcompress_rgtc.h"
 #include "texcompress_s3tc.h"
 #include "teximage.h"
 #include "texstore.h"
 #include "enums.h"
+#include "../../gallium/auxiliary/util/u_format_rgb9e5.h"
 
 
 enum {
@@ -306,16 +312,16 @@ compute_component_mapping(GLenum inFormat, GLenum outFormat,
  * \param srcPacking  source image pixel packing
  * \return resulting image with format = textureBaseFormat and type = GLfloat.
  */
-static GLfloat *
-make_temp_float_image(struct gl_context *ctx, GLuint dims,
-                      GLenum logicalBaseFormat,
-                      GLenum textureBaseFormat,
-                      GLint srcWidth, GLint srcHeight, GLint srcDepth,
-                      GLenum srcFormat, GLenum srcType,
-                      const GLvoid *srcAddr,
-                      const struct gl_pixelstore_attrib *srcPacking)
+GLfloat *
+_mesa_make_temp_float_image(struct gl_context *ctx, GLuint dims,
+                           GLenum logicalBaseFormat,
+                           GLenum textureBaseFormat,
+                           GLint srcWidth, GLint srcHeight, GLint srcDepth,
+                           GLenum srcFormat, GLenum srcType,
+                           const GLvoid *srcAddr,
+                           const struct gl_pixelstore_attrib *srcPacking,
+                           GLbitfield transferOps)
 {
-   GLuint transferOps = ctx->_ImageTransferState;
    GLfloat *tempImage;
    const GLint components = _mesa_components_in_format(logicalBaseFormat);
    const GLint srcStride =
@@ -416,6 +422,115 @@ make_temp_float_image(struct gl_context *ctx, GLuint dims,
 }
 
 
+/**
+ * Make temporary image with uint pixel values.  Used for unsigned
+ * integer-valued textures.
+ */
+static GLuint *
+make_temp_uint_image(struct gl_context *ctx, GLuint dims,
+                     GLenum logicalBaseFormat,
+                     GLenum textureBaseFormat,
+                     GLint srcWidth, GLint srcHeight, GLint srcDepth,
+                     GLenum srcFormat, GLenum srcType,
+                     const GLvoid *srcAddr,
+                     const struct gl_pixelstore_attrib *srcPacking)
+{
+   GLuint *tempImage;
+   const GLint components = _mesa_components_in_format(logicalBaseFormat);
+   const GLint srcStride =
+      _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
+   GLuint *dst;
+   GLint img, row;
+
+   ASSERT(dims >= 1 && dims <= 3);
+
+   ASSERT(logicalBaseFormat == GL_RGBA ||
+          logicalBaseFormat == GL_RGB ||
+          logicalBaseFormat == GL_RG ||
+          logicalBaseFormat == GL_RED ||
+          logicalBaseFormat == GL_LUMINANCE_ALPHA ||
+          logicalBaseFormat == GL_LUMINANCE ||
+          logicalBaseFormat == GL_INTENSITY ||
+          logicalBaseFormat == GL_ALPHA);
+
+   ASSERT(textureBaseFormat == GL_RGBA ||
+          textureBaseFormat == GL_RGB ||
+          textureBaseFormat == GL_RG ||
+          textureBaseFormat == GL_RED ||
+          textureBaseFormat == GL_LUMINANCE_ALPHA ||
+          textureBaseFormat == GL_LUMINANCE ||
+          textureBaseFormat == GL_ALPHA);
+
+   tempImage = (GLuint *) malloc(srcWidth * srcHeight * srcDepth
+                                 * components * sizeof(GLuint));
+   if (!tempImage)
+      return NULL;
+
+   dst = tempImage;
+   for (img = 0; img < srcDepth; img++) {
+      const GLubyte *src
+        = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
+                                                srcWidth, srcHeight,
+                                                srcFormat, srcType,
+                                                img, 0, 0);
+      for (row = 0; row < srcHeight; row++) {
+        _mesa_unpack_color_span_uint(ctx, srcWidth, logicalBaseFormat,
+                                      dst, srcFormat, srcType, src,
+                                      srcPacking);
+        dst += srcWidth * components;
+        src += srcStride;
+      }
+   }
+
+   if (logicalBaseFormat != textureBaseFormat) {
+      /* more work */
+      GLint texComponents = _mesa_components_in_format(textureBaseFormat);
+      GLint logComponents = _mesa_components_in_format(logicalBaseFormat);
+      GLuint *newImage;
+      GLint i, n;
+      GLubyte map[6];
+
+      /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
+      ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA ||
+             textureBaseFormat == GL_LUMINANCE_ALPHA);
+
+      /* The actual texture format should have at least as many components
+       * as the logical texture format.
+       */
+      ASSERT(texComponents >= logComponents);
+
+      newImage = (GLuint *) malloc(srcWidth * srcHeight * srcDepth
+                                   * texComponents * sizeof(GLuint));
+      if (!newImage) {
+         free(tempImage);
+         return NULL;
+      }
+
+      compute_component_mapping(logicalBaseFormat, textureBaseFormat, map);
+
+      n = srcWidth * srcHeight * srcDepth;
+      for (i = 0; i < n; i++) {
+         GLint k;
+         for (k = 0; k < texComponents; k++) {
+            GLint j = map[k];
+            if (j == ZERO)
+               newImage[i * texComponents + k] = 0.0F;
+            else if (j == ONE)
+               newImage[i * texComponents + k] = 1.0F;
+            else
+               newImage[i * texComponents + k] = tempImage[i * logComponents + j];
+         }
+      }
+
+      free(tempImage);
+      tempImage = newImage;
+   }
+
+   return tempImage;
+}
+
+
+
 /**
  * Make a temporary (color) texture image with GLchan components.
  * Apply all needed pixel unpacking and pixel transfer operations.
@@ -1927,6 +2042,132 @@ _mesa_texstore_argb1555(TEXSTORE_PARAMS)
 }
 
 
+static GLboolean
+_mesa_texstore_argb2101010(TEXSTORE_PARAMS)
+{
+   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
+   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
+
+   ASSERT(dstFormat == MESA_FORMAT_ARGB2101010);
+   ASSERT(texelBytes == 4);
+
+   if (!ctx->_ImageTransferState &&
+       !srcPacking->SwapBytes &&
+       dstFormat == MESA_FORMAT_ARGB2101010 &&
+       srcFormat == GL_BGRA &&
+       srcType == GL_UNSIGNED_INT_2_10_10_10_REV &&
+       baseInternalFormat == GL_RGBA) {
+      /* 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 *src = tempImage;
+      GLint img, row, col;
+      if (!tempImage)
+         return GL_FALSE;
+      for (img = 0; img < srcDepth; img++) {
+         GLubyte *dstRow = (GLubyte *) dstAddr
+            + dstImageOffsets[dstZoffset + img] * texelBytes
+            + dstYoffset * dstRowStride
+            + dstXoffset * texelBytes;
+         if (baseInternalFormat == GL_RGBA) {
+            for (row = 0; row < srcHeight; row++) {
+               GLuint *dstUI = (GLuint *) dstRow;
+               for (col = 0; col < srcWidth; col++) {
+                  GLushort a,r,g,b;
+
+                  UNCLAMPED_FLOAT_TO_USHORT(a, src[ACOMP]);
+                  UNCLAMPED_FLOAT_TO_USHORT(r, src[RCOMP]);
+                  UNCLAMPED_FLOAT_TO_USHORT(g, src[GCOMP]);
+                  UNCLAMPED_FLOAT_TO_USHORT(b, src[BCOMP]);
+                  dstUI[col] = PACK_COLOR_2101010_US(a, r, g, b);
+                  src += 4;
+               }
+               dstRow += dstRowStride;
+            }
+         } else if (baseInternalFormat == GL_RGB) {
+            for (row = 0; row < srcHeight; row++) {
+               GLuint *dstUI = (GLuint *) dstRow;
+               for (col = 0; col < srcWidth; col++) {
+                  GLushort r,g,b;
+
+                  UNCLAMPED_FLOAT_TO_USHORT(r, src[RCOMP]);
+                  UNCLAMPED_FLOAT_TO_USHORT(g, src[GCOMP]);
+                  UNCLAMPED_FLOAT_TO_USHORT(b, src[BCOMP]);
+                  dstUI[col] = PACK_COLOR_2101010_US(0xffff, r, g, b);
+                  src += 4;
+               }
+               dstRow += dstRowStride;
+            }
+         } else {
+            ASSERT(0);
+         }
+      }
+      free((void *) tempImage);
+   }
+   return GL_TRUE;
+}
+
+
+/**
+ * Do texstore for 2-channel, 4-bit/channel, unsigned normalized formats.
+ */
+static GLboolean
+_mesa_texstore_unorm44(TEXSTORE_PARAMS)
+{
+   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
+   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
+
+   ASSERT(dstFormat == MESA_FORMAT_AL44);
+   ASSERT(texelBytes == 1);
+
+   {
+      /* general path */
+      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+                                                 baseInternalFormat,
+                                                 baseFormat,
+                                                 srcWidth, srcHeight, srcDepth,
+                                                 srcFormat, srcType, srcAddr,
+                                                 srcPacking);
+      const GLchan *src = tempImage;
+      GLint img, row, col;
+      if (!tempImage)
+         return GL_FALSE;
+      for (img = 0; img < srcDepth; img++) {
+         GLubyte *dstRow = (GLubyte *) dstAddr
+            + dstImageOffsets[dstZoffset + img] * texelBytes
+            + dstYoffset * dstRowStride
+            + dstXoffset * texelBytes;
+         for (row = 0; row < srcHeight; row++) {
+            GLubyte *dstUS = (GLubyte *) dstRow;
+            for (col = 0; col < srcWidth; col++) {
+               /* src[0] is luminance, src[1] is alpha */
+               dstUS[col] = PACK_COLOR_44( CHAN_TO_UBYTE(src[1]),
+                                           CHAN_TO_UBYTE(src[0]) );
+               src += 2;
+            }
+            dstRow += dstRowStride;
+         }
+      }
+      free((void *) tempImage);
+   }
+   return GL_TRUE;
+}
+
+
 /**
  * Do texstore for 2-channel, 8-bit/channel, unsigned normalized formats.
  */
@@ -1945,8 +2186,11 @@ _mesa_texstore_unorm88(TEXSTORE_PARAMS)
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
-       (dstFormat == MESA_FORMAT_AL88 || dstFormat == MESA_FORMAT_RG88) &&
-       baseInternalFormat == srcFormat &&
+       ((dstFormat == MESA_FORMAT_AL88 &&
+         baseInternalFormat == GL_LUMINANCE_ALPHA &&
+         srcFormat == GL_LUMINANCE_ALPHA) ||
+        (dstFormat == MESA_FORMAT_RG88 &&
+         baseInternalFormat == srcFormat)) &&
        srcType == GL_UNSIGNED_BYTE &&
        littleEndian) {
       /* simple memcpy path */
@@ -2064,8 +2308,11 @@ _mesa_texstore_unorm1616(TEXSTORE_PARAMS)
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
-       (dstFormat == MESA_FORMAT_AL1616 || dstFormat == MESA_FORMAT_RG1616) &&
-       baseInternalFormat == srcFormat &&
+       ((dstFormat == MESA_FORMAT_AL1616 &&
+         baseInternalFormat == GL_LUMINANCE_ALPHA &&
+         srcFormat == GL_LUMINANCE_ALPHA) ||
+        (dstFormat == MESA_FORMAT_RG1616 &&
+         baseInternalFormat == srcFormat)) &&
        srcType == GL_UNSIGNED_SHORT &&
        littleEndian) {
       /* simple memcpy path */
@@ -2078,12 +2325,13 @@ _mesa_texstore_unorm1616(TEXSTORE_PARAMS)
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
+                                                 srcPacking,
+                                                 ctx->_ImageTransferState);
       const GLfloat *src = tempImage;
       GLint img, row, col;
       if (!tempImage)
@@ -2125,21 +2373,23 @@ _mesa_texstore_unorm1616(TEXSTORE_PARAMS)
 }
 
 
+/* Texstore for R16, A16, L16, I16. */
 static GLboolean
-_mesa_texstore_r16(TEXSTORE_PARAMS)
+_mesa_texstore_unorm16(TEXSTORE_PARAMS)
 {
    const GLboolean littleEndian = _mesa_little_endian();
    const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
 
-   ASSERT(dstFormat == MESA_FORMAT_R16);
+   ASSERT(dstFormat == MESA_FORMAT_R16 ||
+          dstFormat == MESA_FORMAT_A16 ||
+          dstFormat == MESA_FORMAT_L16 ||
+          dstFormat == MESA_FORMAT_I16);
    ASSERT(texelBytes == 2);
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
-       dstFormat == MESA_FORMAT_R16 &&
-       baseInternalFormat == GL_RED &&
-       srcFormat == GL_RED &&
+       baseInternalFormat == srcFormat &&
        srcType == GL_UNSIGNED_SHORT &&
        littleEndian) {
       /* simple memcpy path */
@@ -2152,12 +2402,13 @@ _mesa_texstore_r16(TEXSTORE_PARAMS)
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
+                                                 srcPacking,
+                                                 ctx->_ImageTransferState);
       const GLfloat *src = tempImage;
       GLint img, row, col;
       if (!tempImage)
@@ -2209,12 +2460,13 @@ _mesa_texstore_rgba_16(TEXSTORE_PARAMS)
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
+                                                 srcPacking,
+                                                 ctx->_ImageTransferState);
       const GLfloat *src = tempImage;
       GLint img, row, col;
       if (!tempImage)
@@ -2254,9 +2506,7 @@ _mesa_texstore_signed_rgba_16(TEXSTORE_PARAMS)
    const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
 
-   ASSERT(dstFormat == MESA_FORMAT_SIGNED_R_16 ||
-          dstFormat == MESA_FORMAT_SIGNED_RG_16 ||
-          dstFormat == MESA_FORMAT_SIGNED_RGB_16 ||
+   ASSERT(dstFormat == MESA_FORMAT_SIGNED_RGB_16 ||
           dstFormat == MESA_FORMAT_SIGNED_RGBA_16);
 
    if (!ctx->_ImageTransferState &&
@@ -2275,12 +2525,13 @@ _mesa_texstore_signed_rgba_16(TEXSTORE_PARAMS)
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
+                                                 srcPacking,
+                                                 ctx->_ImageTransferState);
       const GLfloat *src = tempImage;
       const GLuint comps = _mesa_get_format_bytes(dstFormat) / 2;
       GLint img, row, col;
@@ -2298,16 +2549,29 @@ _mesa_texstore_signed_rgba_16(TEXSTORE_PARAMS)
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
             GLshort *dstRowS = (GLshort *) dstRow;
-            for (col = 0; col < srcWidth; col++) {
-               GLuint c;
-               for (c = 0; c < comps; c++) {
-                  GLshort p;
-                  UNCLAMPED_FLOAT_TO_SHORT(p, src[col * 4 + c]);
-                  dstRowS[col * comps + c] = p;
+            if (dstFormat == MESA_FORMAT_SIGNED_RGBA_16) {
+               for (col = 0; col < srcWidth; col++) {
+                  GLuint c;
+                  for (c = 0; c < comps; c++) {
+                     GLshort p;
+                     UNCLAMPED_FLOAT_TO_SHORT(p, src[col * 4 + c]);
+                     dstRowS[col * comps + c] = p;
+                  }
+               }
+               dstRow += dstRowStride;
+               src += 4 * srcWidth;
+            } else {
+               for (col = 0; col < srcWidth; col++) {
+                  GLuint c;
+                  for (c = 0; c < comps; c++) {
+                     GLshort p;
+                     UNCLAMPED_FLOAT_TO_SHORT(p, src[col * 3 + c]);
+                     dstRowS[col * comps + c] = p;
+                  }
                }
+               dstRow += dstRowStride;
+               src += 3 * srcWidth;
             }
-            dstRow += dstRowStride;
-            src += 4 * srcWidth;
          }
       }
       free((void *) tempImage);
@@ -2374,7 +2638,7 @@ _mesa_texstore_rgb332(TEXSTORE_PARAMS)
  * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
  */
 static GLboolean
-_mesa_texstore_a8(TEXSTORE_PARAMS)
+_mesa_texstore_unorm8(TEXSTORE_PARAMS)
 {
    const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
@@ -2642,41 +2906,56 @@ _mesa_texstore_dudv8(TEXSTORE_PARAMS)
 
 
 /**
- * Store a texture in MESA_FORMAT_SIGNED_R8 format.
+ * Store a texture in a signed normalized 8-bit format.
  */
 static GLboolean
-_mesa_texstore_signed_r8(TEXSTORE_PARAMS)
+_mesa_texstore_snorm8(TEXSTORE_PARAMS)
 {
    const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
 
-   ASSERT(dstFormat == MESA_FORMAT_SIGNED_R8);
+   ASSERT(dstFormat == MESA_FORMAT_SIGNED_A8 ||
+          dstFormat == MESA_FORMAT_SIGNED_L8 ||
+          dstFormat == MESA_FORMAT_SIGNED_I8 ||
+          dstFormat == MESA_FORMAT_SIGNED_R8);
    ASSERT(texelBytes == 1);
 
-   /* XXX look at adding optimized paths */
-   {
+   if (!ctx->_ImageTransferState &&
+       !srcPacking->SwapBytes &&
+       baseInternalFormat == srcFormat &&
+       srcType == GL_BYTE) {
+      /* 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 = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
-      const GLfloat *srcRow = tempImage;
+                                                 srcPacking,
+                                                 ctx->_ImageTransferState);
+      const GLfloat *src = tempImage;
       GLint img, row, col;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
+         GLbyte *dstRow = (GLbyte *) dstAddr
             + dstImageOffsets[dstZoffset + img] * texelBytes
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
-            GLubyte *dstB = (GLubyte *) dstRow;
             for (col = 0; col < srcWidth; col++) {
-               dstB[col] = FLOAT_TO_BYTE_TEX(srcRow[RCOMP]);
+               dstRow[col] = FLOAT_TO_BYTE_TEX(src[col]);
             }
             dstRow += dstRowStride;
+            src += srcWidth;
          }
       }
       free((void *) tempImage);
@@ -2686,40 +2965,57 @@ _mesa_texstore_signed_r8(TEXSTORE_PARAMS)
 
 
 /**
- * Store a texture in MESA_FORMAT_SIGNED_RG88 format.
+ * Store a texture in a signed normalized two-channel 16-bit format.
  */
 static GLboolean
-_mesa_texstore_signed_rg88(TEXSTORE_PARAMS)
+_mesa_texstore_snorm88(TEXSTORE_PARAMS)
 {
+   const GLboolean littleEndian = _mesa_little_endian();
    const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
 
-   ASSERT(dstFormat == MESA_FORMAT_SIGNED_RG88);
-   ASSERT(texelBytes == 1);
+   ASSERT(dstFormat == MESA_FORMAT_SIGNED_AL88 ||
+          dstFormat == MESA_FORMAT_SIGNED_RG88_REV);
+   ASSERT(texelBytes == 2);
 
-   /* XXX look at adding optimized paths */
-   {
+   if (!ctx->_ImageTransferState &&
+       !srcPacking->SwapBytes &&
+       baseInternalFormat == srcFormat &&
+       srcType == GL_BYTE &&
+       littleEndian) {
+      /* 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 = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
-      const GLfloat *srcRow = tempImage;
+                                                 srcPacking,
+                                                 ctx->_ImageTransferState);
+      const GLfloat *src = tempImage;
       GLint img, row, col;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
+         GLbyte *dstRow = (GLbyte *) dstAddr
             + dstImageOffsets[dstZoffset + img] * texelBytes
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
-            GLushort *dstUS = (GLushort *) dstRow;
+            GLbyte *dst = dstRow;
             for (col = 0; col < srcWidth; col++) {
-               dstUS[col] = PACK_COLOR_88(FLOAT_TO_BYTE_TEX(srcRow[RCOMP]),
-                                          FLOAT_TO_BYTE_TEX(srcRow[GCOMP]));
+               dst[0] = FLOAT_TO_BYTE_TEX(src[0]);
+               dst[1] = FLOAT_TO_BYTE_TEX(src[1]);
+               src += 2;
+               dst += 2;
             }
             dstRow += dstRowStride;
          }
@@ -2729,6 +3025,132 @@ _mesa_texstore_signed_rg88(TEXSTORE_PARAMS)
    return GL_TRUE;
 }
 
+/* Texstore for signed R16, A16, L16, I16. */
+static GLboolean
+_mesa_texstore_snorm16(TEXSTORE_PARAMS)
+{
+   const GLboolean littleEndian = _mesa_little_endian();
+   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
+   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
+
+   ASSERT(dstFormat == MESA_FORMAT_SIGNED_R16 ||
+          dstFormat == MESA_FORMAT_SIGNED_A16 ||
+          dstFormat == MESA_FORMAT_SIGNED_L16 ||
+          dstFormat == MESA_FORMAT_SIGNED_I16);
+   ASSERT(texelBytes == 2);
+
+   if (!ctx->_ImageTransferState &&
+       !srcPacking->SwapBytes &&
+       baseInternalFormat == srcFormat &&
+       srcType == GL_SHORT &&
+       littleEndian) {
+      /* 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 *src = tempImage;
+      GLint img, row, col;
+      if (!tempImage)
+         return GL_FALSE;
+      for (img = 0; img < srcDepth; img++) {
+         GLubyte *dstRow = (GLubyte *) dstAddr
+            + dstImageOffsets[dstZoffset + img] * texelBytes
+            + dstYoffset * dstRowStride
+            + dstXoffset * texelBytes;
+         for (row = 0; row < srcHeight; row++) {
+            GLshort *dstUS = (GLshort *) dstRow;
+           for (col = 0; col < srcWidth; col++) {
+              GLushort r;
+
+              UNCLAMPED_FLOAT_TO_SHORT(r, src[0]);
+              dstUS[col] = r;
+              src += 1;
+           }
+            dstRow += dstRowStride;
+         }
+      }
+      free((void *) tempImage);
+   }
+   return GL_TRUE;
+}
+
+/**
+ * Do texstore for 2-channel, 16-bit/channel, signed normalized formats.
+ */
+static GLboolean
+_mesa_texstore_snorm1616(TEXSTORE_PARAMS)
+{
+   const GLboolean littleEndian = _mesa_little_endian();
+   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
+   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
+
+   ASSERT(dstFormat == MESA_FORMAT_SIGNED_AL1616 ||
+          dstFormat == MESA_FORMAT_SIGNED_GR1616);
+   ASSERT(texelBytes == 4);
+
+   if (!ctx->_ImageTransferState &&
+       !srcPacking->SwapBytes &&
+       baseInternalFormat == srcFormat &&
+       srcType == GL_SHORT &&
+       littleEndian) {
+      /* 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 *src = tempImage;
+      GLint img, row, col;
+      if (!tempImage)
+         return GL_FALSE;
+      for (img = 0; img < srcDepth; img++) {
+         GLubyte *dstRow = (GLubyte *) dstAddr
+            + dstImageOffsets[dstZoffset + img] * texelBytes
+            + dstYoffset * dstRowStride
+            + dstXoffset * texelBytes;
+         for (row = 0; row < srcHeight; row++) {
+            GLshort *dst = (GLshort *) dstRow;
+            for (col = 0; col < srcWidth; col++) {
+               GLushort l, a;
+
+               UNCLAMPED_FLOAT_TO_SHORT(l, src[0]);
+               UNCLAMPED_FLOAT_TO_SHORT(a, src[1]);
+               dst[0] = l;
+               dst[1] = a;
+               src += 2;
+               dst += 2;
+            }
+            dstRow += dstRowStride;
+         }
+      }
+      free((void *) tempImage);
+   }
+   return GL_TRUE;
+}
 
 /**
  * Store a texture in MESA_FORMAT_SIGNED_RGBX8888.
@@ -2744,29 +3166,31 @@ _mesa_texstore_signed_rgbx8888(TEXSTORE_PARAMS)
 
    {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
+                                                 srcPacking,
+                                                 ctx->_ImageTransferState);
       const GLfloat *srcRow = tempImage;
       GLint img, row, col;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
+         GLbyte *dstRow = (GLbyte *) dstAddr
             + dstImageOffsets[dstZoffset + img] * texelBytes
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
-            GLuint *dstUI = (GLuint *) dstRow;
+            GLbyte *dst = dstRow;
             for (col = 0; col < srcWidth; col++) {
-               dstUI[col] = PACK_COLOR_8888( FLOAT_TO_BYTE_TEX(srcRow[RCOMP]),
-                                             FLOAT_TO_BYTE_TEX(srcRow[GCOMP]),
-                                             FLOAT_TO_BYTE_TEX(srcRow[BCOMP]),
-                                             0xff );
-               srcRow += 4;
+               dst[3] = FLOAT_TO_BYTE_TEX(srcRow[RCOMP]);
+               dst[2] = FLOAT_TO_BYTE_TEX(srcRow[GCOMP]);
+               dst[1] = FLOAT_TO_BYTE_TEX(srcRow[BCOMP]);
+               dst[0] = 127;
+               srcRow += 3;
+               dst += 4;
             }
             dstRow += dstRowStride;
          }
@@ -2821,74 +3245,44 @@ _mesa_texstore_signed_rgba8888(TEXSTORE_PARAMS)
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
-   else if (!ctx->_ImageTransferState &&
-           (srcType == GL_BYTE) &&
-           can_swizzle(baseInternalFormat) &&
-           can_swizzle(srcFormat)) {
-
-      GLubyte dstmap[4];
-
-      /* dstmap - how to swizzle from RGBA to dst format:
-       */
-      if ((littleEndian && dstFormat == MESA_FORMAT_SIGNED_RGBA8888) ||
-         (!littleEndian && dstFormat == MESA_FORMAT_SIGNED_RGBA8888_REV)) {
-        dstmap[3] = 0;
-        dstmap[2] = 1;
-        dstmap[1] = 2;
-        dstmap[0] = 3;
-      }
-      else {
-        dstmap[3] = 3;
-        dstmap[2] = 2;
-        dstmap[1] = 1;
-        dstmap[0] = 0;
-      }
-      
-      _mesa_swizzle_ubyte_image(ctx, dims,
-                               srcFormat,
-                               srcType,
-                               baseInternalFormat,
-                               dstmap, 4,
-                               dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                               dstRowStride, dstImageOffsets,
-                               srcWidth, srcHeight, srcDepth, srcAddr,
-                               srcPacking);      
-   }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
+                                                 srcPacking,
+                                                 ctx->_ImageTransferState);
       const GLfloat *srcRow = tempImage;
       GLint img, row, col;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
+         GLbyte *dstRow = (GLbyte *) dstAddr
             + dstImageOffsets[dstZoffset + img] * texelBytes
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
-            GLuint *dstUI = (GLuint *) dstRow;
+            GLbyte *dst = dstRow;
             if (dstFormat == MESA_FORMAT_SIGNED_RGBA8888) {
                for (col = 0; col < srcWidth; col++) {
-                  dstUI[col] = PACK_COLOR_8888( FLOAT_TO_BYTE_TEX(srcRow[RCOMP]),
-                                                FLOAT_TO_BYTE_TEX(srcRow[GCOMP]),
-                                                FLOAT_TO_BYTE_TEX(srcRow[BCOMP]),
-                                                FLOAT_TO_BYTE_TEX(srcRow[ACOMP]) );
+                  dst[3] = FLOAT_TO_BYTE_TEX(srcRow[RCOMP]);
+                  dst[2] = FLOAT_TO_BYTE_TEX(srcRow[GCOMP]);
+                  dst[1] = FLOAT_TO_BYTE_TEX(srcRow[BCOMP]);
+                  dst[0] = FLOAT_TO_BYTE_TEX(srcRow[ACOMP]);
                   srcRow += 4;
+                  dst += 4;
                }
             }
             else {
                for (col = 0; col < srcWidth; col++) {
-                  dstUI[col] = PACK_COLOR_8888_REV( FLOAT_TO_BYTE_TEX(srcRow[RCOMP]),
-                                                    FLOAT_TO_BYTE_TEX(srcRow[GCOMP]),
-                                                    FLOAT_TO_BYTE_TEX(srcRow[BCOMP]),
-                                                    FLOAT_TO_BYTE_TEX(srcRow[ACOMP]) );
+                  dst[0] = FLOAT_TO_BYTE_TEX(srcRow[RCOMP]);
+                  dst[1] = FLOAT_TO_BYTE_TEX(srcRow[GCOMP]);
+                  dst[2] = FLOAT_TO_BYTE_TEX(srcRow[BCOMP]);
+                  dst[3] = FLOAT_TO_BYTE_TEX(srcRow[ACOMP]);
                   srcRow += 4;
+                  dst += 4;
                }
             }
             dstRow += dstRowStride;
@@ -3141,18 +3535,23 @@ _mesa_texstore_rgba_float32(TEXSTORE_PARAMS)
           dstFormat == MESA_FORMAT_ALPHA_FLOAT32 ||
           dstFormat == MESA_FORMAT_LUMINANCE_FLOAT32 ||
           dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32 ||
-          dstFormat == MESA_FORMAT_INTENSITY_FLOAT32);
+          dstFormat == MESA_FORMAT_INTENSITY_FLOAT32 ||
+          dstFormat == MESA_FORMAT_R_FLOAT32 ||
+          dstFormat == MESA_FORMAT_RG_FLOAT32);
    ASSERT(baseInternalFormat == GL_RGBA ||
           baseInternalFormat == GL_RGB ||
           baseInternalFormat == GL_ALPHA ||
           baseInternalFormat == GL_LUMINANCE ||
           baseInternalFormat == GL_LUMINANCE_ALPHA ||
-          baseInternalFormat == GL_INTENSITY);
+          baseInternalFormat == GL_INTENSITY ||
+          baseInternalFormat == GL_RED ||
+          baseInternalFormat == GL_RG);
    ASSERT(texelBytes == components * sizeof(GLfloat));
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
        baseInternalFormat == srcFormat &&
+       baseInternalFormat == baseFormat &&
        srcType == GL_FLOAT) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
@@ -3164,12 +3563,13 @@ _mesa_texstore_rgba_float32(TEXSTORE_PARAMS)
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
+                                                 srcPacking,
+                                                 ctx->_ImageTransferState);
       const GLfloat *srcRow = tempImage;
       GLint bytesPerRow;
       GLint img, row;
@@ -3210,18 +3610,23 @@ _mesa_texstore_rgba_float16(TEXSTORE_PARAMS)
           dstFormat == MESA_FORMAT_ALPHA_FLOAT16 ||
           dstFormat == MESA_FORMAT_LUMINANCE_FLOAT16 ||
           dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16 ||
-          dstFormat == MESA_FORMAT_INTENSITY_FLOAT16);
+          dstFormat == MESA_FORMAT_INTENSITY_FLOAT16 ||
+          dstFormat == MESA_FORMAT_R_FLOAT16 ||
+          dstFormat == MESA_FORMAT_RG_FLOAT16);
    ASSERT(baseInternalFormat == GL_RGBA ||
           baseInternalFormat == GL_RGB ||
           baseInternalFormat == GL_ALPHA ||
           baseInternalFormat == GL_LUMINANCE ||
           baseInternalFormat == GL_LUMINANCE_ALPHA ||
-          baseInternalFormat == GL_INTENSITY);
+          baseInternalFormat == GL_INTENSITY ||
+          baseInternalFormat == GL_RED ||
+          baseInternalFormat == GL_RG);
    ASSERT(texelBytes == components * sizeof(GLhalfARB));
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
        baseInternalFormat == srcFormat &&
+       baseInternalFormat == baseFormat &&
        srcType == GL_HALF_FLOAT_ARB) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
@@ -3233,12 +3638,13 @@ _mesa_texstore_rgba_float16(TEXSTORE_PARAMS)
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
+                                                 srcPacking,
+                                                 ctx->_ImageTransferState);
       const GLfloat *src = tempImage;
       GLint img, row;
       if (!tempImage)
@@ -3282,8 +3688,10 @@ _mesa_texstore_rgba_int8(TEXSTORE_PARAMS)
           baseInternalFormat == GL_INTENSITY);
    ASSERT(texelBytes == components * sizeof(GLbyte));
 
-   if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
+   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
+    * to integer formats.
+    */
+   if (!srcPacking->SwapBytes &&
        baseInternalFormat == srcFormat &&
        srcType == GL_BYTE) {
       /* simple memcpy path */
@@ -3296,12 +3704,12 @@ _mesa_texstore_rgba_int8(TEXSTORE_PARAMS)
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
+                                                 srcPacking, 0x0);
       const GLfloat *src = tempImage;
       GLint img, row;
       if (!tempImage)
@@ -3345,10 +3753,12 @@ _mesa_texstore_rgba_int16(TEXSTORE_PARAMS)
           baseInternalFormat == GL_INTENSITY);
    ASSERT(texelBytes == components * sizeof(GLshort));
 
-   if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
+   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
+    * to integer formats.
+    */
+   if (!srcPacking->SwapBytes &&
        baseInternalFormat == srcFormat &&
-       srcType == GL_INT) {
+       srcType == GL_SHORT) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
                      dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
@@ -3359,12 +3769,12 @@ _mesa_texstore_rgba_int16(TEXSTORE_PARAMS)
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
+                                                 srcPacking, 0x0);
       const GLfloat *src = tempImage;
       GLint img, row;
       if (!tempImage)
@@ -3408,8 +3818,10 @@ _mesa_texstore_rgba_int32(TEXSTORE_PARAMS)
           baseInternalFormat == GL_INTENSITY);
    ASSERT(texelBytes == components * sizeof(GLint));
 
-   if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
+   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
+    * to integer formats.
+    */
+   if (!srcPacking->SwapBytes &&
        baseInternalFormat == srcFormat &&
        srcType == GL_INT) {
       /* simple memcpy path */
@@ -3422,12 +3834,12 @@ _mesa_texstore_rgba_int32(TEXSTORE_PARAMS)
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
+                                                 srcPacking, 0x0);
       const GLfloat *src = tempImage;
       GLint img, row;
       if (!tempImage)
@@ -3471,8 +3883,10 @@ _mesa_texstore_rgba_uint8(TEXSTORE_PARAMS)
           baseInternalFormat == GL_INTENSITY);
    ASSERT(texelBytes == components * sizeof(GLubyte));
 
-   if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
+   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
+    * to integer formats.
+    */
+   if (!srcPacking->SwapBytes &&
        baseInternalFormat == srcFormat &&
        srcType == GL_UNSIGNED_BYTE) {
       /* simple memcpy path */
@@ -3485,13 +3899,11 @@ _mesa_texstore_rgba_uint8(TEXSTORE_PARAMS)
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
-                                                 baseInternalFormat,
-                                                 baseFormat,
-                                                 srcWidth, srcHeight, srcDepth,
-                                                 srcFormat, srcType, srcAddr,
-                                                 srcPacking);
-      const GLfloat *src = tempImage;
+      const GLuint *tempImage =
+         make_temp_uint_image(ctx, dims, baseInternalFormat, baseFormat,
+                              srcWidth, srcHeight, srcDepth,
+                              srcFormat, srcType, srcAddr, srcPacking);
+      const GLuint *src = tempImage;
       GLint img, row;
       if (!tempImage)
          return GL_FALSE;
@@ -3504,7 +3916,7 @@ _mesa_texstore_rgba_uint8(TEXSTORE_PARAMS)
             GLubyte *dstTexel = (GLubyte *) dstRow;
             GLint i;
             for (i = 0; i < srcWidth * components; i++) {
-               dstTexel[i] = (GLubyte) src[i];
+               dstTexel[i] = (GLubyte) CLAMP(src[i], 0, 0xff);
             }
             dstRow += dstRowStride;
             src += srcWidth * components;
@@ -3534,8 +3946,10 @@ _mesa_texstore_rgba_uint16(TEXSTORE_PARAMS)
           baseInternalFormat == GL_INTENSITY);
    ASSERT(texelBytes == components * sizeof(GLushort));
 
-   if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
+   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
+    * to integer formats.
+    */
+   if (!srcPacking->SwapBytes &&
        baseInternalFormat == srcFormat &&
        srcType == GL_UNSIGNED_SHORT) {
       /* simple memcpy path */
@@ -3548,13 +3962,11 @@ _mesa_texstore_rgba_uint16(TEXSTORE_PARAMS)
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
-                                                 baseInternalFormat,
-                                                 baseFormat,
-                                                 srcWidth, srcHeight, srcDepth,
-                                                 srcFormat, srcType, srcAddr,
-                                                 srcPacking);
-      const GLfloat *src = tempImage;
+      const GLuint *tempImage =
+         make_temp_uint_image(ctx, dims, baseInternalFormat, baseFormat,
+                              srcWidth, srcHeight, srcDepth,
+                              srcFormat, srcType, srcAddr, srcPacking);
+      const GLuint *src = tempImage;
       GLint img, row;
       if (!tempImage)
          return GL_FALSE;
@@ -3567,7 +3979,7 @@ _mesa_texstore_rgba_uint16(TEXSTORE_PARAMS)
             GLushort *dstTexel = (GLushort *) dstRow;
             GLint i;
             for (i = 0; i < srcWidth * components; i++) {
-               dstTexel[i] = (GLushort) src[i];
+               dstTexel[i] = (GLushort) CLAMP(src[i], 0, 0xffff);
             }
             dstRow += dstRowStride;
             src += srcWidth * components;
@@ -3597,8 +4009,10 @@ _mesa_texstore_rgba_uint32(TEXSTORE_PARAMS)
           baseInternalFormat == GL_INTENSITY);
    ASSERT(texelBytes == components * sizeof(GLuint));
 
-   if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
+   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
+    * to integer formats.
+    */
+   if (!srcPacking->SwapBytes &&
        baseInternalFormat == srcFormat &&
        srcType == GL_UNSIGNED_INT) {
       /* simple memcpy path */
@@ -3611,13 +4025,11 @@ _mesa_texstore_rgba_uint32(TEXSTORE_PARAMS)
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
-                                                 baseInternalFormat,
-                                                 baseFormat,
-                                                 srcWidth, srcHeight, srcDepth,
-                                                 srcFormat, srcType, srcAddr,
-                                                 srcPacking);
-      const GLfloat *src = tempImage;
+      const GLuint *tempImage =
+         make_temp_uint_image(ctx, dims, baseInternalFormat, baseFormat,
+                              srcWidth, srcHeight, srcDepth,
+                              srcFormat, srcType, srcAddr, srcPacking);
+      const GLuint *src = tempImage;
       GLint img, row;
       if (!tempImage)
          return GL_FALSE;
@@ -3630,7 +4042,7 @@ _mesa_texstore_rgba_uint32(TEXSTORE_PARAMS)
             GLuint *dstTexel = (GLuint *) dstRow;
             GLint i;
             for (i = 0; i < srcWidth * components; i++) {
-               dstTexel[i] = (GLuint) src[i];
+               dstTexel[i] = src[i];
             }
             dstRow += dstRowStride;
             src += srcWidth * components;
@@ -3722,7 +4134,7 @@ _mesa_texstore_sl8(TEXSTORE_PARAMS)
    newDstFormat = MESA_FORMAT_L8;
 
    /* _mesa_textore_a8 handles luminance8 too */
-   k = _mesa_texstore_a8(ctx, dims, baseInternalFormat,
+   k = _mesa_texstore_unorm8(ctx, dims, baseInternalFormat,
                          newDstFormat, dstAddr,
                          dstXoffset, dstYoffset, dstZoffset,
                          dstRowStride, dstImageOffsets,
@@ -3765,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;
+}
 
 
 
@@ -3794,23 +4260,28 @@ texstore_funcs[MESA_FORMAT_COUNT] =
    { MESA_FORMAT_RGBA5551, _mesa_texstore_rgba5551 },
    { MESA_FORMAT_ARGB1555, _mesa_texstore_argb1555 },
    { MESA_FORMAT_ARGB1555_REV, _mesa_texstore_argb1555 },
+   { MESA_FORMAT_AL44, _mesa_texstore_unorm44 },
    { MESA_FORMAT_AL88, _mesa_texstore_unorm88 },
    { MESA_FORMAT_AL88_REV, _mesa_texstore_unorm88 },
    { MESA_FORMAT_AL1616, _mesa_texstore_unorm1616 },
    { MESA_FORMAT_AL1616_REV, _mesa_texstore_unorm1616 },
    { MESA_FORMAT_RGB332, _mesa_texstore_rgb332 },
-   { MESA_FORMAT_A8, _mesa_texstore_a8 },
-   { MESA_FORMAT_L8, _mesa_texstore_a8 },
-   { MESA_FORMAT_I8, _mesa_texstore_a8 },
+   { MESA_FORMAT_A8, _mesa_texstore_unorm8 },
+   { MESA_FORMAT_A16, _mesa_texstore_unorm16 },
+   { MESA_FORMAT_L8, _mesa_texstore_unorm8 },
+   { MESA_FORMAT_L16, _mesa_texstore_unorm16 },
+   { MESA_FORMAT_I8, _mesa_texstore_unorm8 },
+   { MESA_FORMAT_I16, _mesa_texstore_unorm16 },
    { MESA_FORMAT_CI8, _mesa_texstore_ci8 },
    { MESA_FORMAT_YCBCR, _mesa_texstore_ycbcr },
    { MESA_FORMAT_YCBCR_REV, _mesa_texstore_ycbcr },
-   { MESA_FORMAT_R8, _mesa_texstore_a8 },
+   { MESA_FORMAT_R8, _mesa_texstore_unorm8 },
    { MESA_FORMAT_RG88, _mesa_texstore_unorm88 },
    { MESA_FORMAT_RG88_REV, _mesa_texstore_unorm88 },
-   { MESA_FORMAT_R16, _mesa_texstore_r16 },
+   { MESA_FORMAT_R16, _mesa_texstore_unorm16 },
    { MESA_FORMAT_RG1616, _mesa_texstore_unorm1616 },
    { MESA_FORMAT_RG1616_REV, _mesa_texstore_unorm1616 },
+   { MESA_FORMAT_ARGB2101010, _mesa_texstore_argb2101010 },
    { MESA_FORMAT_Z24_S8, _mesa_texstore_z24_s8 },
    { MESA_FORMAT_S8_Z24, _mesa_texstore_s8_z24 },
    { MESA_FORMAT_Z16, _mesa_texstore_z16 },
@@ -3845,6 +4316,10 @@ texstore_funcs[MESA_FORMAT_COUNT] =
    { MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16, _mesa_texstore_rgba_float16 },
    { MESA_FORMAT_INTENSITY_FLOAT32, _mesa_texstore_rgba_float32 },
    { MESA_FORMAT_INTENSITY_FLOAT16, _mesa_texstore_rgba_float16 },
+   { MESA_FORMAT_R_FLOAT32, _mesa_texstore_rgba_float32 },
+   { MESA_FORMAT_R_FLOAT16, _mesa_texstore_rgba_float16 },
+   { MESA_FORMAT_RG_FLOAT32, _mesa_texstore_rgba_float32 },
+   { MESA_FORMAT_RG_FLOAT16, _mesa_texstore_rgba_float16 },
 
    { MESA_FORMAT_RGBA_INT8, _mesa_texstore_rgba_int8 },
    { MESA_FORMAT_RGBA_INT16, _mesa_texstore_rgba_int16 },
@@ -3855,18 +4330,42 @@ texstore_funcs[MESA_FORMAT_COUNT] =
 
    { MESA_FORMAT_DUDV8, _mesa_texstore_dudv8 },
 
-   { MESA_FORMAT_SIGNED_R8, _mesa_texstore_signed_r8 },
-   { MESA_FORMAT_SIGNED_RG88, _mesa_texstore_signed_rg88 },
+   { MESA_FORMAT_SIGNED_R8, _mesa_texstore_snorm8 },
+   { MESA_FORMAT_SIGNED_RG88_REV, _mesa_texstore_snorm88 },
    { MESA_FORMAT_SIGNED_RGBX8888, _mesa_texstore_signed_rgbx8888 },
 
    { MESA_FORMAT_SIGNED_RGBA8888, _mesa_texstore_signed_rgba8888 },
    { MESA_FORMAT_SIGNED_RGBA8888_REV, _mesa_texstore_signed_rgba8888 },
 
-   { MESA_FORMAT_SIGNED_R_16, _mesa_texstore_signed_rgba_16 },
-   { MESA_FORMAT_SIGNED_RG_16, _mesa_texstore_signed_rgba_16 },
+   { MESA_FORMAT_SIGNED_R16, _mesa_texstore_snorm16 },
+   { MESA_FORMAT_SIGNED_GR1616, _mesa_texstore_snorm1616 },
    { MESA_FORMAT_SIGNED_RGB_16, _mesa_texstore_signed_rgba_16 },
    { MESA_FORMAT_SIGNED_RGBA_16, _mesa_texstore_signed_rgba_16 },
-   { MESA_FORMAT_RGBA_16, _mesa_texstore_rgba_16 }
+   { MESA_FORMAT_RGBA_16, _mesa_texstore_rgba_16 },
+
+   { MESA_FORMAT_RED_RGTC1, _mesa_texstore_red_rgtc1 },
+   { MESA_FORMAT_SIGNED_RED_RGTC1, _mesa_texstore_signed_red_rgtc1 },
+   { MESA_FORMAT_RG_RGTC2, _mesa_texstore_rg_rgtc2 },
+   { MESA_FORMAT_SIGNED_RG_RGTC2, _mesa_texstore_signed_rg_rgtc2 },
+
+   /* Re-use the R/RG texstore functions.
+    * The code is generic enough to handle LATC too. */
+   { MESA_FORMAT_L_LATC1, _mesa_texstore_red_rgtc1 },
+   { MESA_FORMAT_SIGNED_L_LATC1, _mesa_texstore_signed_red_rgtc1 },
+   { MESA_FORMAT_LA_LATC2, _mesa_texstore_rg_rgtc2 },
+   { MESA_FORMAT_SIGNED_LA_LATC2, _mesa_texstore_signed_rg_rgtc2 },
+
+   { MESA_FORMAT_SIGNED_A8, _mesa_texstore_snorm8 },
+   { MESA_FORMAT_SIGNED_L8, _mesa_texstore_snorm8 },
+   { MESA_FORMAT_SIGNED_AL88, _mesa_texstore_snorm88 },
+   { MESA_FORMAT_SIGNED_I8, _mesa_texstore_snorm8 },
+
+   { MESA_FORMAT_SIGNED_A16, _mesa_texstore_snorm16 },
+   { 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 },
 };
 
 
@@ -3932,94 +4431,6 @@ _mesa_texstore(TEXSTORE_PARAMS)
 }
 
 
-/**
- * Check if an unpack PBO is active prior to fetching a texture image.
- * If so, do bounds checking and map the buffer into main memory.
- * Any errors detected will be recorded.
- * The caller _must_ call _mesa_unmap_teximage_pbo() too!
- */
-const GLvoid *
-_mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions,
-                           GLsizei width, GLsizei height, GLsizei depth,
-                           GLenum format, GLenum type, const GLvoid *pixels,
-                           const struct gl_pixelstore_attrib *unpack,
-                           const char *funcName)
-{
-   GLubyte *buf;
-
-   if (!_mesa_is_bufferobj(unpack->BufferObj)) {
-      /* no PBO */
-      return pixels;
-   }
-   if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
-                                  format, type, pixels)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
-      return NULL;
-   }
-
-   buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
-                                          GL_READ_ONLY_ARB, unpack->BufferObj);
-   if (!buf) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
-      return NULL;
-   }
-
-   return ADD_POINTERS(buf, pixels);
-}
-
-
-/**
- * Check if an unpack PBO is active prior to fetching a compressed texture
- * image.
- * If so, do bounds checking and map the buffer into main memory.
- * Any errors detected will be recorded.
- * The caller _must_ call _mesa_unmap_teximage_pbo() too!
- */
-const GLvoid *
-_mesa_validate_pbo_compressed_teximage(struct gl_context *ctx,
-                                 GLsizei imageSize, const GLvoid *pixels,
-                                 const struct gl_pixelstore_attrib *packing,
-                                 const char *funcName)
-{
-   GLubyte *buf;
-
-   if (!_mesa_is_bufferobj(packing->BufferObj)) {
-      /* not using a PBO - return pointer unchanged */
-      return pixels;
-   }
-   if ((const GLubyte *) pixels + imageSize >
-       ((const GLubyte *) 0) + packing->BufferObj->Size) {
-      /* out of bounds read! */
-      _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
-      return NULL;
-   }
-
-   buf = (GLubyte*) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
-                                         GL_READ_ONLY_ARB, packing->BufferObj);
-   if (!buf) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
-      return NULL;
-   }
-
-   return ADD_POINTERS(buf, pixels);
-}
-
-
-/**
- * This function must be called after either of the validate_pbo_*_teximage()
- * functions.  It unmaps the PBO buffer if it was mapped earlier.
- */
-void
-_mesa_unmap_teximage_pbo(struct gl_context *ctx,
-                         const struct gl_pixelstore_attrib *unpack)
-{
-   if (_mesa_is_bufferobj(unpack->BufferObj)) {
-      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
-                              unpack->BufferObj);
-   }
-}
-
-
 /** Return texture size in bytes */
 static GLuint
 texture_size(const struct gl_texture_image *texImage)
@@ -4321,7 +4732,8 @@ _mesa_store_texsubimage3d(struct gl_context *ctx, GLenum target, GLint level,
  * Fallback for Driver.CompressedTexImage1D()
  */
 void
-_mesa_store_compressed_teximage1d(struct gl_context *ctx, GLenum target, GLint level,
+_mesa_store_compressed_teximage1d(struct gl_context *ctx,
+                                  GLenum target, GLint level,
                                   GLint internalFormat,
                                   GLint width, GLint border,
                                   GLsizei imageSize, const GLvoid *data,
@@ -4344,7 +4756,8 @@ _mesa_store_compressed_teximage1d(struct gl_context *ctx, GLenum target, GLint l
  * Fallback for Driver.CompressedTexImage2D()
  */
 void
-_mesa_store_compressed_teximage2d(struct gl_context *ctx, GLenum target, GLint level,
+_mesa_store_compressed_teximage2d(struct gl_context *ctx,
+                                  GLenum target, GLint level,
                                   GLint internalFormat,
                                   GLint width, GLint height, GLint border,
                                   GLsizei imageSize, const GLvoid *data,
@@ -4388,7 +4801,8 @@ _mesa_store_compressed_teximage2d(struct gl_context *ctx, GLenum target, GLint l
  * Fallback for Driver.CompressedTexImage3D()
  */
 void
-_mesa_store_compressed_teximage3d(struct gl_context *ctx, GLenum target, GLint level,
+_mesa_store_compressed_teximage3d(struct gl_context *ctx,
+                                  GLenum target, GLint level,
                                   GLint internalFormat,
                                   GLint width, GLint height, GLint depth,
                                   GLint border,