mesa: add glformats integer type/format detection routines
[mesa.git] / src / mesa / main / image.c
index ca31e53a8cfbf046e39c32aca83e7e897ac459fc..798280f7310cd116cb4563c3a860757fbe561b94 100644 (file)
@@ -238,17 +238,20 @@ _mesa_components_in_format( GLenum format )
       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_BGRA:
       case GL_ABGR_EXT:
       case GL_RGBA_INTEGER_EXT:
+      case GL_BGRA_INTEGER_EXT:
          return 4;
 
       default:
@@ -353,18 +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(const 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:
@@ -377,12 +454,14 @@ _mesa_is_legal_format_and_type(const struct gl_context *ctx,
             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:
@@ -401,16 +480,17 @@ _mesa_is_legal_format_and_type(const struct gl_context *ctx,
             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:
@@ -419,12 +499,14 @@ _mesa_is_legal_format_and_type(const struct gl_context *ctx,
             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:
@@ -438,16 +520,20 @@ _mesa_is_legal_format_and_type(const struct gl_context *ctx,
             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;
+               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;
+               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
@@ -460,12 +546,14 @@ _mesa_is_legal_format_and_type(const struct gl_context *ctx,
             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:
@@ -485,28 +573,37 @@ _mesa_is_legal_format_and_type(const struct gl_context *ctx,
             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) ||
-             (ctx->Extensions.ARB_depth_buffer_float &&
-              type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV))
-            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,9 +612,9 @@ _mesa_is_legal_format_and_type(const struct gl_context *ctx,
             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 */
@@ -525,6 +622,7 @@ _mesa_is_legal_format_and_type(const struct gl_context *ctx,
       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:
@@ -532,9 +630,11 @@ _mesa_is_legal_format_and_type(const struct gl_context *ctx,
             case GL_UNSIGNED_SHORT:
             case GL_INT:
             case GL_UNSIGNED_INT:
-               return ctx->Extensions.EXT_texture_integer;
+               return (ctx->VersionMajor >= 3 ||
+                       ctx->Extensions.EXT_texture_integer)
+                  ? GL_NO_ERROR : GL_INVALID_ENUM;
             default:
-               return GL_FALSE;
+               return GL_INVALID_ENUM;
          }
 
       case GL_RGB_INTEGER_EXT:
@@ -545,14 +645,17 @@ _mesa_is_legal_format_and_type(const struct gl_context *ctx,
             case GL_UNSIGNED_SHORT:
             case GL_INT:
             case GL_UNSIGNED_INT:
-               return ctx->Extensions.EXT_texture_integer;
+               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;
+               return ctx->Extensions.ARB_texture_rgb10_a2ui
+                  ? GL_NO_ERROR : GL_INVALID_ENUM;
             default:
-               return GL_FALSE;
+               return GL_INVALID_ENUM;
          }
 
       case GL_BGR_INTEGER_EXT:
@@ -564,9 +667,11 @@ _mesa_is_legal_format_and_type(const struct gl_context *ctx,
             case GL_INT:
             case GL_UNSIGNED_INT:
             /* NOTE: no packed formats w/ BGR format */
-               return ctx->Extensions.EXT_texture_integer;
+               return (ctx->VersionMajor >= 3 ||
+                       ctx->Extensions.EXT_texture_integer)
+                  ? GL_NO_ERROR : GL_INVALID_ENUM;
             default:
-               return GL_FALSE;
+               return GL_INVALID_ENUM;
          }
 
       case GL_RGBA_INTEGER_EXT:
@@ -578,7 +683,9 @@ _mesa_is_legal_format_and_type(const struct gl_context *ctx,
             case GL_UNSIGNED_SHORT:
             case GL_INT:
             case GL_UNSIGNED_INT:
-               return ctx->Extensions.EXT_texture_integer;
+               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:
@@ -587,9 +694,10 @@ _mesa_is_legal_format_and_type(const struct gl_context *ctx,
             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;
+               return ctx->Extensions.ARB_texture_rgb10_a2ui
+                  ? GL_NO_ERROR : GL_INVALID_ENUM;
             default:
-               return GL_FALSE;
+               return GL_INVALID_ENUM;
          }
 
       case GL_LUMINANCE_INTEGER_EXT:
@@ -601,15 +709,16 @@ _mesa_is_legal_format_and_type(const struct gl_context *ctx,
             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;
 }
 
 
@@ -661,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:
@@ -739,6 +849,7 @@ _mesa_is_color_format(GLenum format)
       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:
@@ -748,41 +859,54 @@ _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:
@@ -814,6 +938,7 @@ _mesa_is_color_format(GLenum format)
       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 */
@@ -850,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;
@@ -933,80 +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_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:
-      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.
@@ -1047,6 +1097,8 @@ _mesa_is_compressed_format(struct gl_context *ctx, GLenum format)
       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:
@@ -1067,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;
@@ -1100,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);
 
@@ -1126,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;
    }
@@ -1182,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;
 }
 
 
@@ -1427,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) {
@@ -1531,6 +1698,8 @@ _mesa_convert_colors(GLenum srcType, const GLvoid *src,
    default:
       _mesa_problem(NULL, "Invalid datatype in _mesa_convert_colors");
    }
+
+   free(tempBuffer);
 }