mesa: add glformats integer type/format detection routines
[mesa.git] / src / mesa / main / image.c
index 98f7581e187c0bdca33f1deecdb8ee218ca51126..798280f7310cd116cb4563c3a860757fbe561b94 100644 (file)
 
 #include "glheader.h"
 #include "colormac.h"
-#include "enums.h"
 #include "image.h"
 #include "imports.h"
 #include "macros.h"
+#include "mfeatures.h"
+#include "mtypes.h"
 
 
-/**
- * NOTE:
- * Normally, BYTE_TO_FLOAT(0) returns 0.00392  That causes problems when
- * we later convert the float to a packed integer value (such as for
- * GL_RGB5_A1) because we'll wind up with a non-zero value.
- *
- * We redefine the macros here so zero is handled correctly.
- */
-#undef BYTE_TO_FLOAT
-#define BYTE_TO_FLOAT(B)    ((B) == 0 ? 0.0F : ((2.0F * (B) + 1.0F) * (1.0F/255.0F)))
-
-#undef SHORT_TO_FLOAT
-#define SHORT_TO_FLOAT(S)   ((S) == 0 ? 0.0F : ((2.0F * (S) + 1.0F) * (1.0F/65535.0F)))
-
-
-
-/** Compute ceiling of integer quotient of A divided by B. */
-#define CEILING( A, B )  ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
-
 
 /**
  * \return GL_TRUE if type is packed pixel type, GL_FALSE otherwise.
@@ -67,6 +49,7 @@ _mesa_type_is_packed(GLenum type)
    switch (type) {
    case GL_UNSIGNED_BYTE_3_3_2:
    case GL_UNSIGNED_BYTE_2_3_3_REV:
+   case MESA_UNSIGNED_BYTE_4_4:
    case GL_UNSIGNED_SHORT_5_6_5:
    case GL_UNSIGNED_SHORT_5_6_5_REV:
    case GL_UNSIGNED_SHORT_4_4_4_4:
@@ -80,6 +63,9 @@ _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:
+   case GL_UNSIGNED_INT_10F_11F_11F_REV:
+   case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
       return GL_TRUE;
    }
 
@@ -155,6 +141,8 @@ _mesa_sizeof_type( GLenum type )
         return sizeof(GLdouble);
       case GL_HALF_FLOAT_ARB:
         return sizeof(GLhalfARB);
+      case GL_FIXED:
+        return sizeof(GLfixed);
       default:
          return -1;
    }
@@ -188,34 +176,28 @@ _mesa_sizeof_packed_type( GLenum type )
       case GL_FLOAT:
         return sizeof(GLfloat);
       case GL_UNSIGNED_BYTE_3_3_2:
-         return sizeof(GLubyte);
       case GL_UNSIGNED_BYTE_2_3_3_REV:
+      case MESA_UNSIGNED_BYTE_4_4:
          return sizeof(GLubyte);
       case GL_UNSIGNED_SHORT_5_6_5:
-         return sizeof(GLushort);
       case GL_UNSIGNED_SHORT_5_6_5_REV:
-         return sizeof(GLushort);
       case GL_UNSIGNED_SHORT_4_4_4_4:
-         return sizeof(GLushort);
       case GL_UNSIGNED_SHORT_4_4_4_4_REV:
-         return sizeof(GLushort);
       case GL_UNSIGNED_SHORT_5_5_5_1:
-         return sizeof(GLushort);
       case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+      case GL_UNSIGNED_SHORT_8_8_MESA:
+      case GL_UNSIGNED_SHORT_8_8_REV_MESA:
          return sizeof(GLushort);
       case GL_UNSIGNED_INT_8_8_8_8:
-         return sizeof(GLuint);
       case GL_UNSIGNED_INT_8_8_8_8_REV:
-         return sizeof(GLuint);
       case GL_UNSIGNED_INT_10_10_10_2:
-         return sizeof(GLuint);
       case GL_UNSIGNED_INT_2_10_10_10_REV:
-         return sizeof(GLuint);
-      case GL_UNSIGNED_SHORT_8_8_MESA:
-      case GL_UNSIGNED_SHORT_8_8_REV_MESA:
-         return sizeof(GLushort);      
       case GL_UNSIGNED_INT_24_8_EXT:
+      case GL_UNSIGNED_INT_5_9_9_9_REV:
+      case GL_UNSIGNED_INT_10F_11F_11F_REV:
          return sizeof(GLuint);
+      case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+         return 8;
       default:
          return -1;
    }
@@ -234,12 +216,6 @@ _mesa_components_in_format( GLenum format )
 {
    switch (format) {
       case GL_COLOR_INDEX:
-      case GL_COLOR_INDEX1_EXT:
-      case GL_COLOR_INDEX2_EXT:
-      case GL_COLOR_INDEX4_EXT:
-      case GL_COLOR_INDEX8_EXT:
-      case GL_COLOR_INDEX12_EXT:
-      case GL_COLOR_INDEX16_EXT:
       case GL_STENCIL_INDEX:
       case GL_DEPTH_COMPONENT:
       case GL_RED:
@@ -254,29 +230,30 @@ _mesa_components_in_format( GLenum format )
       case GL_LUMINANCE_INTEGER_EXT:
       case GL_INTENSITY:
          return 1;
+
       case GL_LUMINANCE_ALPHA:
       case GL_LUMINANCE_ALPHA_INTEGER_EXT:
       case GL_RG:
+      case GL_YCBCR_MESA:
+      case GL_DEPTH_STENCIL_EXT:
+      case GL_DUDV_ATI:
+      case GL_DU8DV8_ATI:
+      case GL_RG_INTEGER:
         return 2;
+
       case GL_RGB:
+      case GL_BGR:
       case GL_RGB_INTEGER_EXT:
+      case GL_BGR_INTEGER_EXT:
         return 3;
+
       case GL_RGBA:
-      case GL_RGBA_INTEGER_EXT:
-        return 4;
-      case GL_BGR:
-        return 3;
       case GL_BGRA:
-        return 4;
       case GL_ABGR_EXT:
+      case GL_RGBA_INTEGER_EXT:
+      case GL_BGRA_INTEGER_EXT:
          return 4;
-      case GL_YCBCR_MESA:
-         return 2;
-      case GL_DEPTH_STENCIL_EXT:
-         return 2;
-      case GL_DUDV_ATI:
-      case GL_DU8DV8_ATI:
-         return 2;
+
       default:
          return -1;
    }
@@ -316,13 +293,15 @@ _mesa_bytes_per_pixel( GLenum format, GLenum type )
          return comps * sizeof(GLhalfARB);
       case GL_UNSIGNED_BYTE_3_3_2:
       case GL_UNSIGNED_BYTE_2_3_3_REV:
-         if (format == GL_RGB || format == GL_BGR)
+         if (format == GL_RGB || format == GL_BGR ||
+             format == GL_RGB_INTEGER_EXT || format == GL_BGR_INTEGER_EXT)
             return sizeof(GLubyte);
          else
             return -1;  /* error */
       case GL_UNSIGNED_SHORT_5_6_5:
       case GL_UNSIGNED_SHORT_5_6_5_REV:
-         if (format == GL_RGB || format == GL_BGR)
+         if (format == GL_RGB || format == GL_BGR ||
+             format == GL_RGB_INTEGER_EXT || format == GL_BGR_INTEGER_EXT)
             return sizeof(GLushort);
          else
             return -1;  /* error */
@@ -330,7 +309,8 @@ _mesa_bytes_per_pixel( GLenum format, GLenum type )
       case GL_UNSIGNED_SHORT_4_4_4_4_REV:
       case GL_UNSIGNED_SHORT_5_5_5_1:
       case GL_UNSIGNED_SHORT_1_5_5_5_REV:
-         if (format == GL_RGBA || format == GL_BGRA || format == GL_ABGR_EXT)
+         if (format == GL_RGBA || format == GL_BGRA || format == GL_ABGR_EXT ||
+             format == GL_RGBA_INTEGER_EXT || format == GL_BGRA_INTEGER_EXT)
             return sizeof(GLushort);
          else
             return -1;
@@ -338,7 +318,8 @@ _mesa_bytes_per_pixel( GLenum format, GLenum type )
       case GL_UNSIGNED_INT_8_8_8_8_REV:
       case GL_UNSIGNED_INT_10_10_10_2:
       case GL_UNSIGNED_INT_2_10_10_10_REV:
-         if (format == GL_RGBA || format == GL_BGRA || format == GL_ABGR_EXT)
+         if (format == GL_RGBA || format == GL_BGRA || format == GL_ABGR_EXT ||
+             format == GL_RGBA_INTEGER_EXT || format == GL_BGRA_INTEGER_EXT)
             return sizeof(GLuint);
          else
             return -1;
@@ -353,6 +334,21 @@ _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;
+      case GL_UNSIGNED_INT_10F_11F_11F_REV:
+         if (format == GL_RGB)
+            return sizeof(GLuint);
+         else
+            return -1;
+      case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+         if (format == GL_DEPTH_STENCIL)
+            return 8;
+         else
+            return -1;
       default:
          return -1;
    }
@@ -360,17 +356,92 @@ _mesa_bytes_per_pixel( GLenum format, GLenum type )
 
 
 /**
- * Test for a legal pixel format and type.
+ * Do error checking of format/type combinations for glReadPixels,
+ * glDrawPixels and glTex[Sub]Image.  Note that depending on the format
+ * and type values, we may either generate GL_INVALID_OPERATION or
+ * GL_INVALID_ENUM.
  *
  * \param format pixel format.
  * \param type pixel type.
  *
- * \return GL_TRUE if the given pixel format and type are legal, or GL_FALSE
- * otherwise.
+ * \return GL_INVALID_ENUM, GL_INVALID_OPERATION or GL_NO_ERROR
  */
-GLboolean
-_mesa_is_legal_format_and_type( struct gl_context *ctx, GLenum format, GLenum type )
+GLenum
+_mesa_error_check_format_and_type(const struct gl_context *ctx,
+                                  GLenum format, GLenum type)
 {
+   /* special type-based checks (see glReadPixels, glDrawPixels error lists) */
+   switch (type) {
+   case GL_BITMAP:
+      if (format != GL_COLOR_INDEX && format != GL_STENCIL_INDEX) {
+         return GL_INVALID_ENUM;
+      }
+      break;
+
+   case GL_UNSIGNED_BYTE_3_3_2:
+   case GL_UNSIGNED_BYTE_2_3_3_REV:
+   case GL_UNSIGNED_SHORT_5_6_5:
+   case GL_UNSIGNED_SHORT_5_6_5_REV:
+      if (format == GL_RGB) {
+         break; /* OK */
+      }
+      if (format == GL_RGB_INTEGER_EXT &&
+          ctx->Extensions.ARB_texture_rgb10_a2ui) {
+         break; /* OK */
+      }
+      return GL_INVALID_OPERATION;
+
+   case GL_UNSIGNED_SHORT_4_4_4_4:
+   case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+   case GL_UNSIGNED_SHORT_5_5_5_1:
+   case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+   case GL_UNSIGNED_INT_8_8_8_8:
+   case GL_UNSIGNED_INT_8_8_8_8_REV:
+   case GL_UNSIGNED_INT_10_10_10_2:
+   case GL_UNSIGNED_INT_2_10_10_10_REV:
+      if (format == GL_RGBA ||
+          format == GL_BGRA ||
+          format == GL_ABGR_EXT) {
+         break; /* OK */
+      }
+      if ((format == GL_RGBA_INTEGER_EXT || format == GL_BGRA_INTEGER_EXT) &&
+          ctx->Extensions.ARB_texture_rgb10_a2ui) {
+         break; /* OK */
+      }
+      return GL_INVALID_OPERATION;
+
+   case GL_UNSIGNED_INT_24_8:
+      if (!ctx->Extensions.EXT_packed_depth_stencil) {
+         return GL_INVALID_ENUM;
+      }
+      if (format != GL_DEPTH_STENCIL) {
+         return GL_INVALID_OPERATION;
+      }
+      return GL_NO_ERROR;
+
+   case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+      if (!ctx->Extensions.ARB_depth_buffer_float) {
+         return GL_INVALID_ENUM;
+      }
+      if (format != GL_DEPTH_STENCIL) {
+         return GL_INVALID_OPERATION;
+      }
+      return GL_NO_ERROR;
+
+   case GL_UNSIGNED_INT_10F_11F_11F_REV:
+      if (!ctx->Extensions.EXT_packed_float) {
+         return GL_INVALID_ENUM;
+      }
+      if (format != GL_RGB) {
+         return GL_INVALID_OPERATION;
+      }
+      return GL_NO_ERROR;
+
+   default:
+      ; /* fall-through */
+   }
+
+   /* now, for each format, check the type for compatibility */
    switch (format) {
       case GL_COLOR_INDEX:
       case GL_STENCIL_INDEX:
@@ -383,12 +454,14 @@ _mesa_is_legal_format_and_type( struct gl_context *ctx, GLenum format, GLenum ty
             case GL_INT:
             case GL_UNSIGNED_INT:
             case GL_FLOAT:
-               return GL_TRUE;
-            case GL_HALF_FLOAT_ARB:
-               return ctx->Extensions.ARB_half_float_pixel;
+               return GL_NO_ERROR;
+            case GL_HALF_FLOAT:
+               return ctx->Extensions.ARB_half_float_pixel
+                  ? GL_NO_ERROR : GL_INVALID_ENUM;
             default:
-               return GL_FALSE;
+               return GL_INVALID_ENUM;
          }
+
       case GL_RED:
       case GL_GREEN:
       case GL_BLUE:
@@ -407,16 +480,17 @@ _mesa_is_legal_format_and_type( struct gl_context *ctx, GLenum format, GLenum ty
             case GL_INT:
             case GL_UNSIGNED_INT:
             case GL_FLOAT:
-               return GL_TRUE;
-            case GL_HALF_FLOAT_ARB:
-               return ctx->Extensions.ARB_half_float_pixel;
+               return GL_NO_ERROR;
+            case GL_HALF_FLOAT:
+               return ctx->Extensions.ARB_half_float_pixel
+                  ? GL_NO_ERROR : GL_INVALID_ENUM;
             default:
-               return GL_FALSE;
+               return GL_INVALID_ENUM;
          }
+
       case GL_RG:
         if (!ctx->Extensions.ARB_texture_rg)
-           return GL_FALSE;
-
+           return GL_INVALID_ENUM;
          switch (type) {
             case GL_BYTE:
             case GL_UNSIGNED_BYTE:
@@ -425,12 +499,14 @@ _mesa_is_legal_format_and_type( struct gl_context *ctx, GLenum format, GLenum ty
             case GL_INT:
             case GL_UNSIGNED_INT:
             case GL_FLOAT:
-               return GL_TRUE;
-            case GL_HALF_FLOAT_ARB:
-               return ctx->Extensions.ARB_half_float_pixel;
+               return GL_NO_ERROR;
+            case GL_HALF_FLOAT:
+               return ctx->Extensions.ARB_half_float_pixel
+                  ? GL_NO_ERROR : GL_INVALID_ENUM;
             default:
-               return GL_FALSE;
+               return GL_INVALID_ENUM;
          }
+
       case GL_RGB:
          switch (type) {
             case GL_BYTE:
@@ -444,12 +520,20 @@ _mesa_is_legal_format_and_type( struct gl_context *ctx, GLenum format, GLenum ty
             case GL_UNSIGNED_BYTE_2_3_3_REV:
             case GL_UNSIGNED_SHORT_5_6_5:
             case GL_UNSIGNED_SHORT_5_6_5_REV:
-               return GL_TRUE;
-            case GL_HALF_FLOAT_ARB:
-               return ctx->Extensions.ARB_half_float_pixel;
+               return GL_NO_ERROR;
+            case GL_HALF_FLOAT:
+               return ctx->Extensions.ARB_half_float_pixel
+                  ? GL_NO_ERROR : GL_INVALID_ENUM;
+            case GL_UNSIGNED_INT_5_9_9_9_REV:
+               return ctx->Extensions.EXT_texture_shared_exponent
+                  ? GL_NO_ERROR : GL_INVALID_ENUM;
+            case GL_UNSIGNED_INT_10F_11F_11F_REV:
+               return ctx->Extensions.EXT_packed_float
+                  ? GL_NO_ERROR : GL_INVALID_ENUM;
             default:
-               return GL_FALSE;
+               return GL_INVALID_ENUM;
          }
+
       case GL_BGR:
          switch (type) {
             /* NOTE: no packed types are supported with BGR.  That's
@@ -462,12 +546,14 @@ _mesa_is_legal_format_and_type( struct gl_context *ctx, GLenum format, GLenum ty
             case GL_INT:
             case GL_UNSIGNED_INT:
             case GL_FLOAT:
-               return GL_TRUE;
-            case GL_HALF_FLOAT_ARB:
-               return ctx->Extensions.ARB_half_float_pixel;
+               return GL_NO_ERROR;
+            case GL_HALF_FLOAT:
+               return ctx->Extensions.ARB_half_float_pixel
+                  ? GL_NO_ERROR : GL_INVALID_ENUM;
             default:
-               return GL_FALSE;
+               return GL_INVALID_ENUM;
          }
+
       case GL_RGBA:
       case GL_BGRA:
       case GL_ABGR_EXT:
@@ -487,26 +573,37 @@ _mesa_is_legal_format_and_type( struct gl_context *ctx, GLenum format, GLenum ty
             case GL_UNSIGNED_INT_8_8_8_8_REV:
             case GL_UNSIGNED_INT_10_10_10_2:
             case GL_UNSIGNED_INT_2_10_10_10_REV:
-               return GL_TRUE;
-            case GL_HALF_FLOAT_ARB:
-               return ctx->Extensions.ARB_half_float_pixel;
+               return GL_NO_ERROR;
+            case GL_HALF_FLOAT:
+               return ctx->Extensions.ARB_half_float_pixel
+                  ? GL_NO_ERROR : GL_INVALID_ENUM;
             default:
-               return GL_FALSE;
+               return GL_INVALID_ENUM;
          }
+
       case GL_YCBCR_MESA:
+         if (!ctx->Extensions.MESA_ycbcr_texture)
+            return GL_INVALID_ENUM;
          if (type == GL_UNSIGNED_SHORT_8_8_MESA ||
              type == GL_UNSIGNED_SHORT_8_8_REV_MESA)
-            return GL_TRUE;
+            return GL_NO_ERROR;
          else
-            return GL_FALSE;
+            return GL_INVALID_OPERATION;
+
       case GL_DEPTH_STENCIL_EXT:
-         if (ctx->Extensions.EXT_packed_depth_stencil
-             && type == GL_UNSIGNED_INT_24_8_EXT)
-            return GL_TRUE;
+         if (ctx->Extensions.EXT_packed_depth_stencil &&
+             type == GL_UNSIGNED_INT_24_8)
+            return GL_NO_ERROR;
+         else if (ctx->Extensions.ARB_depth_buffer_float &&
+             type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV)
+            return GL_NO_ERROR;
          else
-            return GL_FALSE;
+            return GL_INVALID_ENUM;
+
       case GL_DUDV_ATI:
       case GL_DU8DV8_ATI:
+         if (!ctx->Extensions.ATI_envmap_bumpmap)
+            return GL_INVALID_ENUM;
          switch (type) {
             case GL_BYTE:
             case GL_UNSIGNED_BYTE:
@@ -515,18 +612,94 @@ _mesa_is_legal_format_and_type( struct gl_context *ctx, GLenum format, GLenum ty
             case GL_INT:
             case GL_UNSIGNED_INT:
             case GL_FLOAT:
-               return GL_TRUE;
+               return GL_NO_ERROR;
             default:
-               return GL_FALSE;
+               return GL_INVALID_ENUM;
          }
+
+      /* integer-valued formats */
       case GL_RED_INTEGER_EXT:
       case GL_GREEN_INTEGER_EXT:
       case GL_BLUE_INTEGER_EXT:
       case GL_ALPHA_INTEGER_EXT:
+      case GL_RG_INTEGER:
+         switch (type) {
+            case GL_BYTE:
+            case GL_UNSIGNED_BYTE:
+            case GL_SHORT:
+            case GL_UNSIGNED_SHORT:
+            case GL_INT:
+            case GL_UNSIGNED_INT:
+               return (ctx->VersionMajor >= 3 ||
+                       ctx->Extensions.EXT_texture_integer)
+                  ? GL_NO_ERROR : GL_INVALID_ENUM;
+            default:
+               return GL_INVALID_ENUM;
+         }
+
       case GL_RGB_INTEGER_EXT:
-      case GL_RGBA_INTEGER_EXT:
+         switch (type) {
+            case GL_BYTE:
+            case GL_UNSIGNED_BYTE:
+            case GL_SHORT:
+            case GL_UNSIGNED_SHORT:
+            case GL_INT:
+            case GL_UNSIGNED_INT:
+               return (ctx->VersionMajor >= 3 ||
+                       ctx->Extensions.EXT_texture_integer)
+                  ? GL_NO_ERROR : GL_INVALID_ENUM;
+            case GL_UNSIGNED_BYTE_3_3_2:
+            case GL_UNSIGNED_BYTE_2_3_3_REV:
+            case GL_UNSIGNED_SHORT_5_6_5:
+            case GL_UNSIGNED_SHORT_5_6_5_REV:
+               return ctx->Extensions.ARB_texture_rgb10_a2ui
+                  ? GL_NO_ERROR : GL_INVALID_ENUM;
+            default:
+               return GL_INVALID_ENUM;
+         }
+
       case GL_BGR_INTEGER_EXT:
+         switch (type) {
+            case GL_BYTE:
+            case GL_UNSIGNED_BYTE:
+            case GL_SHORT:
+            case GL_UNSIGNED_SHORT:
+            case GL_INT:
+            case GL_UNSIGNED_INT:
+            /* NOTE: no packed formats w/ BGR format */
+               return (ctx->VersionMajor >= 3 ||
+                       ctx->Extensions.EXT_texture_integer)
+                  ? GL_NO_ERROR : GL_INVALID_ENUM;
+            default:
+               return GL_INVALID_ENUM;
+         }
+
+      case GL_RGBA_INTEGER_EXT:
       case GL_BGRA_INTEGER_EXT:
+         switch (type) {
+            case GL_BYTE:
+            case GL_UNSIGNED_BYTE:
+            case GL_SHORT:
+            case GL_UNSIGNED_SHORT:
+            case GL_INT:
+            case GL_UNSIGNED_INT:
+               return (ctx->VersionMajor >= 3 ||
+                       ctx->Extensions.EXT_texture_integer)
+                  ? GL_NO_ERROR : GL_INVALID_ENUM;
+            case GL_UNSIGNED_SHORT_4_4_4_4:
+            case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+            case GL_UNSIGNED_SHORT_5_5_5_1:
+            case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+            case GL_UNSIGNED_INT_8_8_8_8:
+            case GL_UNSIGNED_INT_8_8_8_8_REV:
+            case GL_UNSIGNED_INT_10_10_10_2:
+            case GL_UNSIGNED_INT_2_10_10_10_REV:
+               return ctx->Extensions.ARB_texture_rgb10_a2ui
+                  ? GL_NO_ERROR : GL_INVALID_ENUM;
+            default:
+               return GL_INVALID_ENUM;
+         }
+
       case GL_LUMINANCE_INTEGER_EXT:
       case GL_LUMINANCE_ALPHA_INTEGER_EXT:
          switch (type) {
@@ -536,15 +709,16 @@ _mesa_is_legal_format_and_type( struct gl_context *ctx, GLenum format, GLenum ty
             case GL_UNSIGNED_SHORT:
             case GL_INT:
             case GL_UNSIGNED_INT:
-               return ctx->Extensions.EXT_texture_integer;
+               return ctx->Extensions.EXT_texture_integer
+                  ? GL_NO_ERROR : GL_INVALID_ENUM;
             default:
-               return GL_FALSE;
+               return GL_INVALID_ENUM;
          }
 
       default:
-         ; /* fall-through */
+         return GL_INVALID_ENUM;
    }
-   return GL_FALSE;
+   return GL_NO_ERROR;
 }
 
 
@@ -596,6 +770,7 @@ _mesa_is_color_format(GLenum format)
       case GL_R3_G3_B2:
       case GL_RGB4:
       case GL_RGB5:
+      case GL_RGB565:
       case GL_RGB8:
       case GL_RGB10:
       case GL_RGB12:
@@ -669,9 +844,12 @@ _mesa_is_color_format(GLenum format)
       case GL_COMPRESSED_SIGNED_RED_RGTC1:
       case GL_COMPRESSED_RG_RGTC2:
       case GL_COMPRESSED_SIGNED_RG_RGTC2:
-      /* signed, normalized texture formats */
-      case GL_RGBA_SNORM:
-      case GL_RGBA8_SNORM:
+      case GL_COMPRESSED_LUMINANCE_LATC1_EXT:
+      case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT:
+      case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
+      case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT:
+      case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI:
+      case GL_ETC1_RGB8_OES:
       /* generic integer formats */
       case GL_RED_INTEGER_EXT:
       case GL_GREEN_INTEGER_EXT:
@@ -681,45 +859,86 @@ _mesa_is_color_format(GLenum format)
       case GL_RGBA_INTEGER_EXT:
       case GL_BGR_INTEGER_EXT:
       case GL_BGRA_INTEGER_EXT:
+      case GL_RG_INTEGER:
       case GL_LUMINANCE_INTEGER_EXT:
       case GL_LUMINANCE_ALPHA_INTEGER_EXT:
       /* sized integer formats */
       case GL_RGBA32UI_EXT:
       case GL_RGB32UI_EXT:
+      case GL_RG32UI:
+      case GL_R32UI:
       case GL_ALPHA32UI_EXT:
       case GL_INTENSITY32UI_EXT:
       case GL_LUMINANCE32UI_EXT:
       case GL_LUMINANCE_ALPHA32UI_EXT:
       case GL_RGBA16UI_EXT:
       case GL_RGB16UI_EXT:
+      case GL_RG16UI:
+      case GL_R16UI:
       case GL_ALPHA16UI_EXT:
       case GL_INTENSITY16UI_EXT:
       case GL_LUMINANCE16UI_EXT:
       case GL_LUMINANCE_ALPHA16UI_EXT:
       case GL_RGBA8UI_EXT:
       case GL_RGB8UI_EXT:
+      case GL_RG8UI:
+      case GL_R8UI:
       case GL_ALPHA8UI_EXT:
       case GL_INTENSITY8UI_EXT:
       case GL_LUMINANCE8UI_EXT:
       case GL_LUMINANCE_ALPHA8UI_EXT:
       case GL_RGBA32I_EXT:
       case GL_RGB32I_EXT:
+      case GL_RG32I:
+      case GL_R32I:
       case GL_ALPHA32I_EXT:
       case GL_INTENSITY32I_EXT:
       case GL_LUMINANCE32I_EXT:
       case GL_LUMINANCE_ALPHA32I_EXT:
       case GL_RGBA16I_EXT:
       case GL_RGB16I_EXT:
+      case GL_RG16I:
+      case GL_R16I:
       case GL_ALPHA16I_EXT:
       case GL_INTENSITY16I_EXT:
       case GL_LUMINANCE16I_EXT:
       case GL_LUMINANCE_ALPHA16I_EXT:
       case GL_RGBA8I_EXT:
       case GL_RGB8I_EXT:
+      case GL_RG8I:
+      case GL_R8I:
       case GL_ALPHA8I_EXT:
       case GL_INTENSITY8I_EXT:
       case GL_LUMINANCE8I_EXT:
       case GL_LUMINANCE_ALPHA8I_EXT:
+      /* signed, normalized texture formats */
+      case GL_RED_SNORM:
+      case GL_R8_SNORM:
+      case GL_R16_SNORM:
+      case GL_RG_SNORM:
+      case GL_RG8_SNORM:
+      case GL_RG16_SNORM:
+      case GL_RGB_SNORM:
+      case GL_RGB8_SNORM:
+      case GL_RGB16_SNORM:
+      case GL_RGBA_SNORM:
+      case GL_RGBA8_SNORM:
+      case GL_RGBA16_SNORM:
+      case GL_ALPHA_SNORM:
+      case GL_ALPHA8_SNORM:
+      case GL_ALPHA16_SNORM:
+      case GL_LUMINANCE_SNORM:
+      case GL_LUMINANCE8_SNORM:
+      case GL_LUMINANCE16_SNORM:
+      case GL_LUMINANCE_ALPHA_SNORM:
+      case GL_LUMINANCE8_ALPHA8_SNORM:
+      case GL_LUMINANCE16_ALPHA16_SNORM:
+      case GL_INTENSITY_SNORM:
+      case GL_INTENSITY8_SNORM:
+      case GL_INTENSITY16_SNORM:
+      case GL_RGB9_E5:
+      case GL_R11F_G11F_B10F:
+      case GL_RGB10_A2UI:
          return GL_TRUE;
       case GL_YCBCR_MESA:  /* not considered to be RGB */
          /* fall-through */
@@ -729,27 +948,6 @@ _mesa_is_color_format(GLenum format)
 }
 
 
-/**
- * Test if the given image format is a color index format.
- */
-GLboolean
-_mesa_is_index_format(GLenum format)
-{
-   switch (format) {
-      case GL_COLOR_INDEX:
-      case GL_COLOR_INDEX1_EXT:
-      case GL_COLOR_INDEX2_EXT:
-      case GL_COLOR_INDEX4_EXT:
-      case GL_COLOR_INDEX8_EXT:
-      case GL_COLOR_INDEX12_EXT:
-      case GL_COLOR_INDEX16_EXT:
-         return GL_TRUE;
-      default:
-         return GL_FALSE;
-   }
-}
-
-
 /**
  * Test if the given image format is a depth component format.
  */
@@ -761,6 +959,7 @@ _mesa_is_depth_format(GLenum format)
       case GL_DEPTH_COMPONENT16:
       case GL_DEPTH_COMPONENT24:
       case GL_DEPTH_COMPONENT32:
+      case GL_DEPTH_COMPONENT32F:
          return GL_TRUE;
       default:
          return GL_FALSE;
@@ -776,7 +975,6 @@ _mesa_is_stencil_format(GLenum format)
 {
    switch (format) {
       case GL_STENCIL_INDEX:
-      case GL_DEPTH_STENCIL:
          return GL_TRUE;
       default:
          return GL_FALSE;
@@ -808,6 +1006,7 @@ _mesa_is_depthstencil_format(GLenum format)
    switch (format) {
       case GL_DEPTH24_STENCIL8_EXT:
       case GL_DEPTH_STENCIL_EXT:
+      case GL_DEPTH32F_STENCIL8:
          return GL_TRUE;
       default:
          return GL_FALSE;
@@ -833,6 +1032,8 @@ _mesa_is_depth_or_stencil_format(GLenum format)
       case GL_STENCIL_INDEX16_EXT:
       case GL_DEPTH_STENCIL_EXT:
       case GL_DEPTH24_STENCIL8_EXT:
+      case GL_DEPTH_COMPONENT32F:
+      case GL_DEPTH32F_STENCIL8:
          return GL_TRUE;
       default:
          return GL_FALSE;
@@ -856,68 +1057,6 @@ _mesa_is_dudv_format(GLenum format)
 }
 
 
-/**
- * Test if the given format is an integer (non-normalized) format.
- */
-GLboolean
-_mesa_is_integer_format(GLenum format)
-{
-   switch (format) {
-   /* generic integer formats */
-   case GL_RED_INTEGER_EXT:
-   case GL_GREEN_INTEGER_EXT:
-   case GL_BLUE_INTEGER_EXT:
-   case GL_ALPHA_INTEGER_EXT:
-   case GL_RGB_INTEGER_EXT:
-   case GL_RGBA_INTEGER_EXT:
-   case GL_BGR_INTEGER_EXT:
-   case GL_BGRA_INTEGER_EXT:
-   case GL_LUMINANCE_INTEGER_EXT:
-   case GL_LUMINANCE_ALPHA_INTEGER_EXT:
-   /* specific integer formats */
-   case GL_RGBA32UI_EXT:
-   case GL_RGB32UI_EXT:
-   case GL_ALPHA32UI_EXT:
-   case GL_INTENSITY32UI_EXT:
-   case GL_LUMINANCE32UI_EXT:
-   case GL_LUMINANCE_ALPHA32UI_EXT:
-   case GL_RGBA16UI_EXT:
-   case GL_RGB16UI_EXT:
-   case GL_ALPHA16UI_EXT:
-   case GL_INTENSITY16UI_EXT:
-   case GL_LUMINANCE16UI_EXT:
-   case GL_LUMINANCE_ALPHA16UI_EXT:
-   case GL_RGBA8UI_EXT:
-   case GL_RGB8UI_EXT:
-   case GL_ALPHA8UI_EXT:
-   case GL_INTENSITY8UI_EXT:
-   case GL_LUMINANCE8UI_EXT:
-   case GL_LUMINANCE_ALPHA8UI_EXT:
-   case GL_RGBA32I_EXT:
-   case GL_RGB32I_EXT:
-   case GL_ALPHA32I_EXT:
-   case GL_INTENSITY32I_EXT:
-   case GL_LUMINANCE32I_EXT:
-   case GL_LUMINANCE_ALPHA32I_EXT:
-   case GL_RGBA16I_EXT:
-   case GL_RGB16I_EXT:
-   case GL_ALPHA16I_EXT:
-   case GL_INTENSITY16I_EXT:
-   case GL_LUMINANCE16I_EXT:
-   case GL_LUMINANCE_ALPHA16I_EXT:
-   case GL_RGBA8I_EXT:
-   case GL_RGB8I_EXT:
-   case GL_ALPHA8I_EXT:
-   case GL_INTENSITY8I_EXT:
-   case GL_LUMINANCE8I_EXT:
-   case GL_LUMINANCE_ALPHA8I_EXT:
-      return GL_TRUE;
-   default:
-      return GL_FALSE;
-   }
-}
-
-
 /**
  * Test if an image format is a supported compressed format.
  * \param format the internal format token provided by the user.
@@ -951,6 +1090,28 @@ _mesa_is_compressed_format(struct gl_context *ctx, GLenum format)
    case GL_COMPRESSED_RG_RGTC2:
    case GL_COMPRESSED_SIGNED_RG_RGTC2:
       return ctx->Extensions.ARB_texture_compression_rgtc;
+   case GL_COMPRESSED_LUMINANCE_LATC1_EXT:
+   case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT:
+   case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
+   case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT:
+      return ctx->Extensions.EXT_texture_compression_latc;
+   case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI:
+      return ctx->Extensions.ATI_texture_compression_3dc;
+   case GL_ETC1_RGB8_OES:
+      return ctx->Extensions.OES_compressed_ETC1_RGB8_texture;
+#if FEATURE_ES
+   case GL_PALETTE4_RGB8_OES:
+   case GL_PALETTE4_RGBA8_OES:
+   case GL_PALETTE4_R5_G6_B5_OES:
+   case GL_PALETTE4_RGBA4_OES:
+   case GL_PALETTE4_RGB5_A1_OES:
+   case GL_PALETTE8_RGB8_OES:
+   case GL_PALETTE8_RGBA8_OES:
+   case GL_PALETTE8_R5_G6_B5_OES:
+   case GL_PALETTE8_RGBA4_OES:
+   case GL_PALETTE8_RGB5_A1_OES:
+      return ctx->API == API_OPENGLES;
+#endif
    default:
       return GL_FALSE;
    }
@@ -958,32 +1119,117 @@ _mesa_is_compressed_format(struct gl_context *ctx, GLenum format)
 
 
 /**
- * Return the address of a specific pixel in an image (1D, 2D or 3D).
+ * Does the given base texture/renderbuffer format have the channel
+ * named by 'pname'?
+ */
+GLboolean
+_mesa_base_format_has_channel(GLenum base_format, GLenum pname)
+{
+   switch (pname) {
+   case GL_TEXTURE_RED_SIZE:
+   case GL_TEXTURE_RED_TYPE:
+   case GL_RENDERBUFFER_RED_SIZE_EXT:
+   case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
+      if (base_format == GL_RED ||
+         base_format == GL_RG ||
+         base_format == GL_RGB ||
+         base_format == GL_RGBA) {
+        return GL_TRUE;
+      }
+      return GL_FALSE;
+   case GL_TEXTURE_GREEN_SIZE:
+   case GL_TEXTURE_GREEN_TYPE:
+   case GL_RENDERBUFFER_GREEN_SIZE_EXT:
+   case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
+      if (base_format == GL_RG ||
+         base_format == GL_RGB ||
+         base_format == GL_RGBA) {
+        return GL_TRUE;
+      }
+      return GL_FALSE;
+   case GL_TEXTURE_BLUE_SIZE:
+   case GL_TEXTURE_BLUE_TYPE:
+   case GL_RENDERBUFFER_BLUE_SIZE_EXT:
+   case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
+      if (base_format == GL_RGB ||
+         base_format == GL_RGBA) {
+        return GL_TRUE;
+      }
+      return GL_FALSE;
+   case GL_TEXTURE_ALPHA_SIZE:
+   case GL_TEXTURE_ALPHA_TYPE:
+   case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
+   case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
+      if (base_format == GL_RGBA ||
+         base_format == GL_ALPHA ||
+         base_format == GL_LUMINANCE_ALPHA) {
+        return GL_TRUE;
+      }
+      return GL_FALSE;
+   case GL_TEXTURE_LUMINANCE_SIZE:
+   case GL_TEXTURE_LUMINANCE_TYPE:
+      if (base_format == GL_LUMINANCE ||
+         base_format == GL_LUMINANCE_ALPHA) {
+        return GL_TRUE;
+      }
+      return GL_FALSE;
+   case GL_TEXTURE_INTENSITY_SIZE:
+   case GL_TEXTURE_INTENSITY_TYPE:
+      if (base_format == GL_INTENSITY) {
+        return GL_TRUE;
+      }
+      return GL_FALSE;
+   case GL_TEXTURE_DEPTH_SIZE:
+   case GL_TEXTURE_DEPTH_TYPE:
+   case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
+   case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
+      if (base_format == GL_DEPTH_STENCIL ||
+         base_format == GL_DEPTH_COMPONENT) {
+        return GL_TRUE;
+      }
+      return GL_FALSE;
+   case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
+   case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
+      if (base_format == GL_DEPTH_STENCIL ||
+         base_format == GL_STENCIL_INDEX) {
+        return GL_TRUE;
+      }
+      return GL_FALSE;
+   default:
+      _mesa_warning(NULL, "%s: Unexpected channel token 0x%x\n",
+                   __FUNCTION__, pname);
+      return GL_FALSE;
+   }
+
+   return GL_FALSE;
+}
+
+
+/**
+ * Return the byte offset of a specific pixel in an image (1D, 2D or 3D).
  *
  * Pixel unpacking/packing parameters are observed according to \p packing.
  *
  * \param dimensions either 1, 2 or 3 to indicate dimensionality of image
- * \param image  starting address of image data
- * \param width  the image width
- * \param height  theimage height
- * \param format  the pixel format
- * \param type  the pixel data type
  * \param packing  the pixelstore attributes
+ * \param width  the image width
+ * \param height  the image height
+ * \param format  the pixel format (must be validated beforehand)
+ * \param type  the pixel data type (must be validated beforehand)
  * \param img  which image in the volume (0 for 1D or 2D images)
  * \param row  row of pixel in the image (0 for 1D images)
  * \param column column of pixel in the image
- * 
- * \return address of pixel on success, or NULL on error.
+ *
+ * \return offset of pixel.
  *
  * \sa gl_pixelstore_attrib.
  */
-GLvoid *
-_mesa_image_address( GLuint dimensions,
-                     const struct gl_pixelstore_attrib *packing,
-                     const GLvoid *image,
-                     GLsizei width, GLsizei height,
-                     GLenum format, GLenum type,
-                     GLint img, GLint row, GLint column )
+GLintptr
+_mesa_image_offset( GLuint dimensions,
+                    const struct gl_pixelstore_attrib *packing,
+                    GLsizei width, GLsizei height,
+                    GLenum format, GLenum type,
+                    GLint img, GLint row, GLint column )
 {
    GLint alignment;        /* 1, 2 or 4 */
    GLint pixels_per_row;
@@ -991,7 +1237,7 @@ _mesa_image_address( GLuint dimensions,
    GLint skiprows;
    GLint skippixels;
    GLint skipimages;       /* for 3-D volume images */
-   GLubyte *pixel_addr;
+   GLintptr offset;
 
    ASSERT(dimensions >= 1 && dimensions <= 3);
 
@@ -1017,30 +1263,20 @@ _mesa_image_address( GLuint dimensions,
 
    if (type == GL_BITMAP) {
       /* BITMAP data */
-      GLint comp_per_pixel;   /* components per pixel */
-      GLint bytes_per_comp;   /* bytes per component */
       GLint bytes_per_row;
       GLint bytes_per_image;
+      /* components per pixel for color or stencil index: */
+      const GLint comp_per_pixel = 1;
 
-      /* Compute bytes per component */
-      bytes_per_comp = _mesa_sizeof_packed_type( type );
-      if (bytes_per_comp < 0) {
-         return NULL;
-      }
-
-      /* Compute number of components per pixel */
-      comp_per_pixel = _mesa_components_in_format( format );
-      if (comp_per_pixel < 0) {
-         return NULL;
-      }
+      /* The pixel type and format should have been error checked earlier */
+      assert(format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX);
 
       bytes_per_row = alignment
                     * CEILING( comp_per_pixel*pixels_per_row, 8*alignment );
 
       bytes_per_image = bytes_per_row * rows_per_image;
 
-      pixel_addr = (GLubyte *) image
-                 + (skipimages + img) * bytes_per_image
+      offset = (skipimages + img) * bytes_per_image
                  + (skiprows + row) * bytes_per_row
                  + (skippixels + column) / 8;
    }
@@ -1073,14 +1309,50 @@ _mesa_image_address( GLuint dimensions,
       }
 
       /* compute final pixel address */
-      pixel_addr = (GLubyte *) image
-                 + (skipimages + img) * bytes_per_image
+      offset = (skipimages + img) * bytes_per_image
                  + topOfImage
                  + (skiprows + row) * bytes_per_row
                  + (skippixels + column) * bytes_per_pixel;
    }
 
-   return (GLvoid *) pixel_addr;
+   return offset;
+}
+
+
+/**
+ * Return the address of a specific pixel in an image (1D, 2D or 3D).
+ *
+ * Pixel unpacking/packing parameters are observed according to \p packing.
+ *
+ * \param dimensions either 1, 2 or 3 to indicate dimensionality of image
+ * \param packing  the pixelstore attributes
+ * \param image  starting address of image data
+ * \param width  the image width
+ * \param height  the image height
+ * \param format  the pixel format (must be validated beforehand)
+ * \param type  the pixel data type (must be validated beforehand)
+ * \param img  which image in the volume (0 for 1D or 2D images)
+ * \param row  row of pixel in the image (0 for 1D images)
+ * \param column column of pixel in the image
+ *
+ * \return address of pixel.
+ *
+ * \sa gl_pixelstore_attrib.
+ */
+GLvoid *
+_mesa_image_address( GLuint dimensions,
+                     const struct gl_pixelstore_attrib *packing,
+                     const GLvoid *image,
+                     GLsizei width, GLsizei height,
+                     GLenum format, GLenum type,
+                     GLint img, GLint row, GLint column )
+{
+   const GLubyte *addr = (const GLubyte *) image;
+
+   addr += _mesa_image_offset(dimensions, packing, width, height,
+                              format, type, img, row, column);
+
+   return (GLvoid *) addr;
 }
 
 
@@ -1318,9 +1590,13 @@ _mesa_convert_colors(GLenum srcType, const GLvoid *src,
                      GLenum dstType, GLvoid *dst,
                      GLuint count, const GLubyte mask[])
 {
-   GLuint tempBuffer[MAX_WIDTH][4];
+   GLuint *tempBuffer;
    const GLboolean useTemp = (src == dst);
 
+   tempBuffer = malloc(count * MAX_PIXEL_BYTES);
+   if (!tempBuffer)
+      return;
+
    ASSERT(srcType != dstType);
 
    switch (srcType) {
@@ -1396,12 +1672,8 @@ _mesa_convert_colors(GLenum srcType, const GLvoid *src,
          GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst);
          GLuint i;
          for (i = 0; i < count; i++) {
-            if (!mask || mask[i]) {
-               UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][RCOMP], src4[i][RCOMP]);
-               UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][GCOMP], src4[i][GCOMP]);
-               UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][BCOMP], src4[i][BCOMP]);
-               UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][ACOMP], src4[i][ACOMP]);
-            }
+            if (!mask || mask[i])
+               _mesa_unclamped_float_rgba_to_ubyte(dst1[i], src4[i]);
          }
          if (useTemp)
             memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte));
@@ -1426,6 +1698,8 @@ _mesa_convert_colors(GLenum srcType, const GLvoid *src,
    default:
       _mesa_problem(NULL, "Invalid datatype in _mesa_convert_colors");
    }
+
+   free(tempBuffer);
 }
 
 
@@ -1510,8 +1784,8 @@ _mesa_clip_drawpixels(const struct gl_context *ctx,
  * scissor box is ignored, and we use the bounds of the current readbuffer
  * surface.
  *
- * \return  GL_TRUE if image is ready for drawing or
- *          GL_FALSE if image was completely clipped away (draw nothing)
+ * \return  GL_TRUE if region to read is in bounds
+ *          GL_FALSE if region is completely out of bounds (nothing to read)
  */
 GLboolean
 _mesa_clip_readpixels(const struct gl_context *ctx,
@@ -1630,7 +1904,7 @@ _mesa_clip_to_region(GLint xmin, GLint ymin,
 /**
  * Clip dst coords against Xmax (or Ymax).
  */
-static INLINE void
+static inline void
 clip_right_or_top(GLint *srcX0, GLint *srcX1,
                   GLint *dstX0, GLint *dstX1,
                   GLint maxValue)
@@ -1663,7 +1937,7 @@ clip_right_or_top(GLint *srcX0, GLint *srcX1,
 /**
  * Clip dst coords against Xmin (or Ymin).
  */
-static INLINE void
+static inline void
 clip_left_or_bottom(GLint *srcX0, GLint *srcX1,
                     GLint *dstX0, GLint *dstX1,
                     GLint minValue)