mesa: fix texture border handling for cube arrays
[mesa.git] / src / mesa / main / glformats.c
index 8c20f7759d95ae85b319184a6016992e31269dc7..77cf26337e10a175dee2f1e878bdfe91e14f4ecb 100644 (file)
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
  */
 
 
@@ -271,7 +272,8 @@ _mesa_bytes_per_pixel(GLenum format, GLenum type)
    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 ||
-          format == GL_RGBA_INTEGER_EXT || format == GL_BGRA_INTEGER_EXT)
+          format == GL_RGBA_INTEGER_EXT || format == GL_BGRA_INTEGER_EXT ||
+          format == GL_RGB)
          return sizeof(GLuint);
       else
          return -1;
@@ -307,25 +309,60 @@ _mesa_bytes_per_pixel(GLenum format, GLenum type)
 }
 
 
+/**
+ * Get the number of bytes for a vertex attrib with the given number of
+ * components and type.
+ *
+ * \param comps number of components.
+ * \param type data type.
+ *
+ * \return bytes per attribute, or -1 if a bad comps/type combination was given.
+ */
+GLint
+_mesa_bytes_per_vertex_attrib(GLint comps, GLenum type)
+{
+   switch (type) {
+   case GL_BYTE:
+   case GL_UNSIGNED_BYTE:
+      return comps * sizeof(GLubyte);
+   case GL_SHORT:
+   case GL_UNSIGNED_SHORT:
+      return comps * sizeof(GLshort);
+   case GL_INT:
+   case GL_UNSIGNED_INT:
+      return comps * sizeof(GLint);
+   case GL_FLOAT:
+      return comps * sizeof(GLfloat);
+   case GL_HALF_FLOAT_ARB:
+      return comps * sizeof(GLhalfARB);
+   case GL_DOUBLE:
+      return comps * sizeof(GLdouble);
+   case GL_FIXED:
+      return comps * sizeof(GLfixed);
+   case GL_INT_2_10_10_10_REV:
+   case GL_UNSIGNED_INT_2_10_10_10_REV:
+      if (comps == 4)
+         return sizeof(GLuint);
+      else
+         return -1;
+   case GL_UNSIGNED_INT_10F_11F_11F_REV:
+      if (comps == 3)
+         return sizeof(GLuint);
+      else
+         return -1;
+   default:
+      return -1;
+   }
+}
+
+
 /**
  * Test if the given format is an integer (non-normalized) format.
  */
 GLboolean
-_mesa_is_enum_format_integer(GLenum format)
+_mesa_is_enum_format_unsigned_int(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:
-   case GL_RG_INTEGER:
    /* specific integer formats */
    case GL_RGBA32UI_EXT:
    case GL_RGB32UI_EXT:
@@ -351,6 +388,34 @@ _mesa_is_enum_format_integer(GLenum format)
    case GL_INTENSITY8UI_EXT:
    case GL_LUMINANCE8UI_EXT:
    case GL_LUMINANCE_ALPHA8UI_EXT:
+   case GL_RGB10_A2UI:
+      return GL_TRUE;
+   default:
+      return GL_FALSE;
+   }
+}
+
+
+/**
+ * Test if the given format is an integer (non-normalized) format.
+ */
+GLboolean
+_mesa_is_enum_format_signed_int(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:
+   case GL_RG_INTEGER:
+   /* specific integer formats */
    case GL_RGBA32I_EXT:
    case GL_RGB32I_EXT:
    case GL_RG32I:
@@ -375,7 +440,6 @@ _mesa_is_enum_format_integer(GLenum format)
    case GL_INTENSITY8I_EXT:
    case GL_LUMINANCE8I_EXT:
    case GL_LUMINANCE_ALPHA8I_EXT:
-   case GL_RGB10_A2UI:
       return GL_TRUE;
    default:
       return GL_FALSE;
@@ -383,6 +447,17 @@ _mesa_is_enum_format_integer(GLenum format)
 }
 
 
+/**
+ * Test if the given format is an integer (non-normalized) format.
+ */
+GLboolean
+_mesa_is_enum_format_integer(GLenum format)
+{
+   return _mesa_is_enum_format_unsigned_int(format) ||
+          _mesa_is_enum_format_signed_int(format);
+}
+
+
 /**
  * Test if the given type is an integer (non-normalized) format.
  */
@@ -544,7 +619,6 @@ _mesa_is_color_format(GLenum format)
       case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
       case GL_COMPRESSED_RGB_FXT1_3DFX:
       case GL_COMPRESSED_RGBA_FXT1_3DFX:
-#if FEATURE_EXT_texture_sRGB
       case GL_SRGB_EXT:
       case GL_SRGB8_EXT:
       case GL_SRGB_ALPHA_EXT:
@@ -561,7 +635,6 @@ _mesa_is_color_format(GLenum format)
       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
       case GL_COMPRESSED_SLUMINANCE_EXT:
       case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
-#endif /* FEATURE_EXT_texture_sRGB */
       case GL_COMPRESSED_RED_RGTC1:
       case GL_COMPRESSED_SIGNED_RED_RGTC1:
       case GL_COMPRESSED_RG_RGTC2:
@@ -572,6 +645,16 @@ _mesa_is_color_format(GLenum format)
       case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT:
       case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI:
       case GL_ETC1_RGB8_OES:
+      case GL_COMPRESSED_RGB8_ETC2:
+      case GL_COMPRESSED_SRGB8_ETC2:
+      case GL_COMPRESSED_RGBA8_ETC2_EAC:
+      case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+      case GL_COMPRESSED_R11_EAC:
+      case GL_COMPRESSED_RG11_EAC:
+      case GL_COMPRESSED_SIGNED_R11_EAC:
+      case GL_COMPRESSED_SIGNED_RG11_EAC:
+      case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+      case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
       /* generic integer formats */
       case GL_RED_INTEGER_EXT:
       case GL_GREEN_INTEGER_EXT:
@@ -792,36 +875,55 @@ _mesa_is_compressed_format(struct gl_context *ctx, GLenum format)
    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
-      return ctx->Extensions.EXT_texture_compression_s3tc;
+      /* Assume that the ANGLE flag will always be set if the EXT flag is set.
+       */
+      return ctx->Extensions.ANGLE_texture_compression_dxt;
    case GL_RGB_S3TC:
    case GL_RGB4_S3TC:
    case GL_RGBA_S3TC:
    case GL_RGBA4_S3TC:
-      return ctx->Extensions.S3_s3tc;
+      return _mesa_is_desktop_gl(ctx) &&
+         ctx->Extensions.ANGLE_texture_compression_dxt;
    case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
-      return ctx->Extensions.EXT_texture_sRGB
+      return _mesa_is_desktop_gl(ctx)
+         && ctx->Extensions.EXT_texture_sRGB
          && ctx->Extensions.EXT_texture_compression_s3tc;
    case GL_COMPRESSED_RGB_FXT1_3DFX:
    case GL_COMPRESSED_RGBA_FXT1_3DFX:
-      return ctx->Extensions.TDFX_texture_compression_FXT1;
+      return _mesa_is_desktop_gl(ctx)
+         && ctx->Extensions.TDFX_texture_compression_FXT1;
    case GL_COMPRESSED_RED_RGTC1:
    case GL_COMPRESSED_SIGNED_RED_RGTC1:
    case GL_COMPRESSED_RG_RGTC2:
    case GL_COMPRESSED_SIGNED_RG_RGTC2:
-      return ctx->Extensions.ARB_texture_compression_rgtc;
+      return _mesa_is_desktop_gl(ctx)
+         && 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;
+      return ctx->API == API_OPENGL_COMPAT
+         && ctx->Extensions.EXT_texture_compression_latc;
    case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI:
-      return ctx->Extensions.ATI_texture_compression_3dc;
+      return ctx->API == API_OPENGL_COMPAT
+         && ctx->Extensions.ATI_texture_compression_3dc;
    case GL_ETC1_RGB8_OES:
-      return ctx->Extensions.OES_compressed_ETC1_RGB8_texture;
-#if FEATURE_ES
+      return _mesa_is_gles(ctx)
+         && ctx->Extensions.OES_compressed_ETC1_RGB8_texture;
+   case GL_COMPRESSED_RGB8_ETC2:
+   case GL_COMPRESSED_SRGB8_ETC2:
+   case GL_COMPRESSED_RGBA8_ETC2_EAC:
+   case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+   case GL_COMPRESSED_R11_EAC:
+   case GL_COMPRESSED_RG11_EAC:
+   case GL_COMPRESSED_SIGNED_R11_EAC:
+   case GL_COMPRESSED_SIGNED_RG11_EAC:
+   case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+   case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+      return _mesa_is_gles3(ctx) || ctx->Extensions.ARB_ES3_compatibility;
    case GL_PALETTE4_RGB8_OES:
    case GL_PALETTE4_RGBA8_OES:
    case GL_PALETTE4_R5_G6_B5_OES:
@@ -833,7 +935,6 @@ _mesa_is_compressed_format(struct gl_context *ctx, GLenum format)
    case GL_PALETTE8_RGBA4_OES:
    case GL_PALETTE8_RGB5_A1_OES:
       return ctx->API == API_OPENGLES;
-#endif
    default:
       return GL_FALSE;
    }
@@ -960,3 +1061,1024 @@ _mesa_base_format_has_channel(GLenum base_format, GLenum pname)
 
    return GL_FALSE;
 }
+
+
+/**
+ * Returns the number of channels/components for a base format.
+ */
+GLint
+_mesa_base_format_component_count(GLenum base_format)
+{
+   switch (base_format) {
+   case GL_RED:
+   case GL_ALPHA:
+   case GL_INTENSITY:
+   case GL_DEPTH_COMPONENT:
+      return 1;
+   case GL_RG:
+   case GL_LUMINANCE_ALPHA:
+   case GL_DEPTH_STENCIL:
+      return 2;
+   case GL_RGB:
+      return 3;
+   case GL_RGBA:
+      return 4;
+   default:
+      return -1;
+   }
+}
+
+
+/**
+ * If format is a generic compressed format, return the corresponding
+ * non-compressed format.  For other formats, return the format as-is.
+ */
+GLenum
+_mesa_generic_compressed_format_to_uncompressed_format(GLenum format)
+{
+   switch (format) {
+   case GL_COMPRESSED_RED:
+      return GL_RED;
+   case GL_COMPRESSED_RG:
+      return GL_RG;
+   case GL_COMPRESSED_RGB:
+      return GL_RGB;
+   case GL_COMPRESSED_RGBA:
+      return GL_RGBA;
+   case GL_COMPRESSED_ALPHA:
+      return GL_ALPHA;
+   case GL_COMPRESSED_LUMINANCE:
+      return GL_LUMINANCE;
+   case GL_COMPRESSED_LUMINANCE_ALPHA:
+      return GL_LUMINANCE_ALPHA;
+   case GL_COMPRESSED_INTENSITY:
+      return GL_INTENSITY;
+   /* sRGB formats */
+   case GL_COMPRESSED_SRGB:
+      return GL_SRGB;
+   case GL_COMPRESSED_SRGB_ALPHA:
+      return GL_SRGB_ALPHA;
+   case GL_COMPRESSED_SLUMINANCE:
+      return GL_SLUMINANCE;
+   case GL_COMPRESSED_SLUMINANCE_ALPHA:
+      return GL_SLUMINANCE_ALPHA;
+   default:
+      return format;
+   }
+}
+
+
+/**
+ * Return the equivalent non-generic internal format.
+ * This is useful for comparing whether two internal formats are equivalent.
+ */
+GLenum
+_mesa_get_nongeneric_internalformat(GLenum format)
+{
+   switch (format) {
+   /* GL 1.1 formats. */
+   case 4:
+   case GL_RGBA:
+      return GL_RGBA8;
+   case 3:
+   case GL_RGB:
+      return GL_RGB8;
+   case 2:
+   case GL_LUMINANCE_ALPHA:
+      return GL_LUMINANCE8_ALPHA8;
+   case 1:
+   case GL_LUMINANCE:
+      return GL_LUMINANCE8;
+   case GL_ALPHA:
+      return GL_ALPHA8;
+   case GL_INTENSITY:
+      return GL_INTENSITY8;
+
+   /* GL_ARB_texture_rg */
+   case GL_RED:
+      return GL_R8;
+   case GL_RG:
+      return GL_RG8;
+
+   /* GL_EXT_texture_sRGB */
+   case GL_SRGB:
+      return GL_SRGB8;
+   case GL_SRGB_ALPHA:
+      return GL_SRGB8_ALPHA8;
+   case GL_SLUMINANCE:
+      return GL_SLUMINANCE8;
+   case GL_SLUMINANCE_ALPHA:
+      return GL_SLUMINANCE8_ALPHA8;
+
+   /* GL_EXT_texture_snorm */
+   case GL_RGBA_SNORM:
+      return GL_RGBA8_SNORM;
+   case GL_RGB_SNORM:
+      return GL_RGB8_SNORM;
+   case GL_RG_SNORM:
+      return GL_RG8_SNORM;
+   case GL_RED_SNORM:
+      return GL_R8_SNORM;
+   case GL_LUMINANCE_ALPHA_SNORM:
+      return GL_LUMINANCE8_ALPHA8_SNORM;
+   case GL_LUMINANCE_SNORM:
+      return GL_LUMINANCE8_SNORM;
+   case GL_ALPHA_SNORM:
+      return GL_ALPHA8_SNORM;
+   case GL_INTENSITY_SNORM:
+      return GL_INTENSITY8_SNORM;
+
+   default:
+      return format;
+   }
+}
+
+
+/**
+ * Convert an sRGB internal format to linear.
+ */
+GLenum
+_mesa_get_linear_internalformat(GLenum format)
+{
+   switch (format) {
+   case GL_SRGB:
+      return GL_RGB;
+   case GL_SRGB_ALPHA:
+      return GL_RGBA;
+   case GL_SRGB8:
+      return GL_RGB8;
+   case GL_SRGB8_ALPHA8:
+      return GL_RGBA8;
+   case GL_SLUMINANCE8:
+      return GL_LUMINANCE8;
+   case GL_SLUMINANCE:
+      return GL_LUMINANCE;
+   case GL_SLUMINANCE_ALPHA:
+      return GL_LUMINANCE_ALPHA;
+   case GL_SLUMINANCE8_ALPHA8:
+      return GL_LUMINANCE8_ALPHA8;
+   default:
+      return format;
+   }
+}
+
+
+/**
+ * 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_INVALID_ENUM, GL_INVALID_OPERATION or GL_NO_ERROR
+ */
+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 */
+      }
+      if (type == GL_UNSIGNED_INT_2_10_10_10_REV && format == GL_RGB &&
+          ctx->API == API_OPENGLES2) {
+         break; /* OK by GL_EXT_texture_type_2_10_10_10_REV */
+      }
+      return GL_INVALID_OPERATION;
+
+   case GL_UNSIGNED_INT_24_8:
+      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:
+         switch (type) {
+            case GL_BITMAP:
+            case GL_BYTE:
+            case GL_UNSIGNED_BYTE:
+            case GL_SHORT:
+            case GL_UNSIGNED_SHORT:
+            case GL_INT:
+            case GL_UNSIGNED_INT:
+            case GL_FLOAT:
+            case GL_HALF_FLOAT:
+               return GL_NO_ERROR;
+            default:
+               return GL_INVALID_ENUM;
+         }
+
+      case GL_RED:
+      case GL_GREEN:
+      case GL_BLUE:
+      case GL_ALPHA:
+#if 0 /* not legal!  see table 3.6 of the 1.5 spec */
+      case GL_INTENSITY:
+#endif
+      case GL_LUMINANCE:
+      case GL_LUMINANCE_ALPHA:
+      case GL_DEPTH_COMPONENT:
+         switch (type) {
+            case GL_BYTE:
+            case GL_UNSIGNED_BYTE:
+            case GL_SHORT:
+            case GL_UNSIGNED_SHORT:
+            case GL_INT:
+            case GL_UNSIGNED_INT:
+            case GL_FLOAT:
+            case GL_HALF_FLOAT:
+               return GL_NO_ERROR;
+            default:
+               return GL_INVALID_ENUM;
+         }
+
+      case GL_RG:
+        if (!ctx->Extensions.ARB_texture_rg)
+           return GL_INVALID_ENUM;
+         switch (type) {
+            case GL_BYTE:
+            case GL_UNSIGNED_BYTE:
+            case GL_SHORT:
+            case GL_UNSIGNED_SHORT:
+            case GL_INT:
+            case GL_UNSIGNED_INT:
+            case GL_FLOAT:
+            case GL_HALF_FLOAT:
+               return GL_NO_ERROR;
+            default:
+               return GL_INVALID_ENUM;
+         }
+
+      case GL_RGB:
+         switch (type) {
+            case GL_BYTE:
+            case GL_UNSIGNED_BYTE:
+            case GL_SHORT:
+            case GL_UNSIGNED_SHORT:
+            case GL_INT:
+            case GL_UNSIGNED_INT:
+            case GL_FLOAT:
+            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:
+            case GL_HALF_FLOAT:
+               return GL_NO_ERROR;
+            case GL_UNSIGNED_INT_2_10_10_10_REV:
+               /* OK by GL_EXT_texture_type_2_10_10_10_REV */
+               return (ctx->API == API_OPENGLES2)
+                  ? 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_INVALID_ENUM;
+         }
+
+      case GL_BGR:
+         switch (type) {
+            /* NOTE: no packed types are supported with BGR.  That's
+             * intentional, according to the GL spec.
+             */
+            case GL_BYTE:
+            case GL_UNSIGNED_BYTE:
+            case GL_SHORT:
+            case GL_UNSIGNED_SHORT:
+            case GL_INT:
+            case GL_UNSIGNED_INT:
+            case GL_FLOAT:
+            case GL_HALF_FLOAT:
+               return GL_NO_ERROR;
+            default:
+               return GL_INVALID_ENUM;
+         }
+
+      case GL_RGBA:
+      case GL_BGRA:
+      case GL_ABGR_EXT:
+         switch (type) {
+            case GL_BYTE:
+            case GL_UNSIGNED_BYTE:
+            case GL_SHORT:
+            case GL_UNSIGNED_SHORT:
+            case GL_INT:
+            case GL_UNSIGNED_INT:
+            case GL_FLOAT:
+            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:
+            case GL_HALF_FLOAT:
+               return GL_NO_ERROR;
+            default:
+               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_NO_ERROR;
+         else
+            return GL_INVALID_OPERATION;
+
+      case GL_DEPTH_STENCIL:
+         if (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_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:
+            case GL_SHORT:
+            case GL_UNSIGNED_SHORT:
+            case GL_INT:
+            case GL_UNSIGNED_INT:
+            case GL_FLOAT:
+               return GL_NO_ERROR;
+            default:
+               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->Version >= 30 ||
+                       ctx->Extensions.EXT_texture_integer)
+                  ? GL_NO_ERROR : GL_INVALID_ENUM;
+            default:
+               return GL_INVALID_ENUM;
+         }
+
+      case GL_RGB_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->Version >= 30 ||
+                       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->Version >= 30 ||
+                       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->Version >= 30 ||
+                       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) {
+            case GL_BYTE:
+            case GL_UNSIGNED_BYTE:
+            case GL_SHORT:
+            case GL_UNSIGNED_SHORT:
+            case GL_INT:
+            case GL_UNSIGNED_INT:
+               return ctx->Extensions.EXT_texture_integer
+                  ? GL_NO_ERROR : GL_INVALID_ENUM;
+            default:
+               return GL_INVALID_ENUM;
+         }
+
+      default:
+         return GL_INVALID_ENUM;
+   }
+   return GL_NO_ERROR;
+}
+
+
+/**
+ * Do error checking of format/type combinations for OpenGL ES glReadPixels
+ * and glTex[Sub]Image.
+ * \return error code, or GL_NO_ERROR.
+ */
+GLenum
+_mesa_es_error_check_format_and_type(GLenum format, GLenum type,
+                                     unsigned dimensions)
+{
+   GLboolean type_valid = GL_TRUE;
+
+   switch (format) {
+   case GL_ALPHA:
+   case GL_LUMINANCE:
+   case GL_LUMINANCE_ALPHA:
+      type_valid = (type == GL_UNSIGNED_BYTE
+                    || type == GL_FLOAT
+                    || type == GL_HALF_FLOAT_OES);
+      break;
+
+   case GL_RGB:
+      type_valid = (type == GL_UNSIGNED_BYTE
+                    || type == GL_UNSIGNED_SHORT_5_6_5
+                    || type == GL_FLOAT
+                    || type == GL_HALF_FLOAT_OES);
+      break;
+
+   case GL_RGBA:
+      type_valid = (type == GL_UNSIGNED_BYTE
+                    || type == GL_UNSIGNED_SHORT_4_4_4_4
+                    || type == GL_UNSIGNED_SHORT_5_5_5_1
+                    || type == GL_FLOAT
+                    || type == GL_HALF_FLOAT_OES
+                    || type == GL_UNSIGNED_INT_2_10_10_10_REV);
+      break;
+
+   case GL_DEPTH_COMPONENT:
+      /* This format is filtered against invalid dimensionalities elsewhere.
+       */
+      type_valid = (type == GL_UNSIGNED_SHORT
+                    || type == GL_UNSIGNED_INT);
+      break;
+
+   case GL_DEPTH_STENCIL:
+      /* This format is filtered against invalid dimensionalities elsewhere.
+       */
+      type_valid = (type == GL_UNSIGNED_INT_24_8);
+      break;
+
+   case GL_BGRA_EXT:
+      type_valid = (type == GL_UNSIGNED_BYTE);
+
+      /* This feels like a bug in the EXT_texture_format_BGRA8888 spec, but
+       * the format does not appear to be allowed for 3D textures in OpenGL
+       * ES.
+       */
+      if (dimensions != 2)
+         return GL_INVALID_VALUE;
+
+      break;
+
+   default:
+      return GL_INVALID_VALUE;
+   }
+
+   return type_valid ? GL_NO_ERROR : GL_INVALID_OPERATION;
+}
+
+
+/**
+ * Do error checking of format/type combinations for OpenGL ES 3
+ * glTex[Sub]Image.
+ * \return error code, or GL_NO_ERROR.
+ */
+GLenum
+_mesa_es3_error_check_format_and_type(GLenum format, GLenum type,
+                                      GLenum internalFormat)
+{
+   switch (format) {
+   case GL_RGBA:
+      switch (type) {
+      case GL_UNSIGNED_BYTE:
+         switch (internalFormat) {
+         case GL_RGBA:
+         case GL_RGBA8:
+         case GL_RGB5_A1:
+         case GL_RGBA4:
+         case GL_SRGB8_ALPHA8_EXT:
+            break;
+         default:
+            return GL_INVALID_OPERATION;
+         }
+         break;
+
+      case GL_BYTE:
+         if (internalFormat != GL_RGBA8_SNORM)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_UNSIGNED_SHORT_4_4_4_4:
+         switch (internalFormat) {
+         case GL_RGBA:
+         case GL_RGBA4:
+            break;
+         default:
+            return GL_INVALID_OPERATION;
+         }
+         break;
+
+      case GL_UNSIGNED_SHORT_5_5_5_1:
+         switch (internalFormat) {
+         case GL_RGBA:
+         case GL_RGB5_A1:
+            break;
+         default:
+            return GL_INVALID_OPERATION;
+         }
+         break;
+
+      case GL_UNSIGNED_INT_2_10_10_10_REV:
+         switch (internalFormat) {
+         case GL_RGBA: /* GL_EXT_texture_type_2_10_10_10_REV */
+         case GL_RGB10_A2:
+         case GL_RGB5_A1:
+            break;
+         default:
+            return GL_INVALID_OPERATION;
+         }
+         break;
+
+      case GL_HALF_FLOAT:
+         if (internalFormat != GL_RGBA16F)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_FLOAT:
+         switch (internalFormat) {
+         case GL_RGBA16F:
+         case GL_RGBA32F:
+            break;
+         default:
+            return GL_INVALID_OPERATION;
+         }
+         break;
+
+      default:
+         return GL_INVALID_OPERATION;
+      }
+      break;
+
+   case GL_RGBA_INTEGER:
+      switch (type) {
+      case GL_UNSIGNED_BYTE:
+         if (internalFormat != GL_RGBA8UI)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_BYTE:
+         if (internalFormat != GL_RGBA8I)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_UNSIGNED_SHORT:
+         if (internalFormat != GL_RGBA16UI)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_SHORT:
+         if (internalFormat != GL_RGBA16I)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_UNSIGNED_INT:
+         if (internalFormat != GL_RGBA32UI)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_INT:
+         if (internalFormat != GL_RGBA32I)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_UNSIGNED_INT_2_10_10_10_REV:
+         if (internalFormat != GL_RGB10_A2UI)
+            return GL_INVALID_OPERATION;
+         break;
+
+      default:
+         return GL_INVALID_OPERATION;
+      }
+      break;
+
+   case GL_RGB:
+      switch (type) {
+      case GL_UNSIGNED_BYTE:
+         switch (internalFormat) {
+         case GL_RGB:
+         case GL_RGB8:
+         case GL_RGB565:
+         case GL_SRGB8:
+            break;
+         default:
+            return GL_INVALID_OPERATION;
+         }
+         break;
+
+      case GL_BYTE:
+         if (internalFormat != GL_RGB8_SNORM)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_UNSIGNED_SHORT_5_6_5:
+         switch (internalFormat) {
+         case GL_RGB:
+         case GL_RGB565:
+            break;
+         default:
+            return GL_INVALID_OPERATION;
+         }
+         break;
+
+      case GL_UNSIGNED_INT_10F_11F_11F_REV:
+         if (internalFormat != GL_R11F_G11F_B10F)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_UNSIGNED_INT_5_9_9_9_REV:
+         if (internalFormat != GL_RGB9_E5)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_HALF_FLOAT:
+         switch (internalFormat) {
+         case GL_RGB16F:
+         case GL_R11F_G11F_B10F:
+         case GL_RGB9_E5:
+            break;
+         default:
+            return GL_INVALID_OPERATION;
+         }
+         break;
+
+      case GL_FLOAT:
+         switch (internalFormat) {
+         case GL_RGB16F:
+         case GL_RGB32F:
+         case GL_R11F_G11F_B10F:
+         case GL_RGB9_E5:
+            break;
+         default:
+            return GL_INVALID_OPERATION;
+         }
+         break;
+
+      case GL_UNSIGNED_INT_2_10_10_10_REV:
+         switch (internalFormat) {
+         case GL_RGB: /* GL_EXT_texture_type_2_10_10_10_REV */
+            break;
+         default:
+            return GL_INVALID_OPERATION;
+         }
+         break;
+
+      default:
+         return GL_INVALID_OPERATION;
+      }
+      break;
+
+   case GL_RGB_INTEGER:
+      switch (type) {
+      case GL_UNSIGNED_BYTE:
+         if (internalFormat != GL_RGB8UI)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_BYTE:
+         if (internalFormat != GL_RGB8I)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_UNSIGNED_SHORT:
+         if (internalFormat != GL_RGB16UI)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_SHORT:
+         if (internalFormat != GL_RGB16I)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_UNSIGNED_INT:
+         if (internalFormat != GL_RGB32UI)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_INT:
+         if (internalFormat != GL_RGB32I)
+            return GL_INVALID_OPERATION;
+         break;
+
+      default:
+         return GL_INVALID_OPERATION;
+      }
+      break;
+
+   case GL_RG:
+      switch (type) {
+      case GL_UNSIGNED_BYTE:
+         if (internalFormat != GL_RG8)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_BYTE:
+         if (internalFormat != GL_RG8_SNORM)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_HALF_FLOAT:
+         if (internalFormat != GL_RG16F)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_FLOAT:
+         switch (internalFormat) {
+         case GL_RG16F:
+         case GL_RG32F:
+            break;
+         default:
+            return GL_INVALID_OPERATION;
+         }
+         break;
+
+      default:
+         return GL_INVALID_OPERATION;
+      }
+      break;
+
+   case GL_RG_INTEGER:
+      switch (type) {
+      case GL_UNSIGNED_BYTE:
+         if (internalFormat != GL_RG8UI)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_BYTE:
+         if (internalFormat != GL_RG8I)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_UNSIGNED_SHORT:
+         if (internalFormat != GL_RG16UI)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_SHORT:
+         if (internalFormat != GL_RG16I)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_UNSIGNED_INT:
+         if (internalFormat != GL_RG32UI)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_INT:
+         if (internalFormat != GL_RG32I)
+            return GL_INVALID_OPERATION;
+         break;
+
+      default:
+         return GL_INVALID_OPERATION;
+      }
+      break;
+
+   case GL_RED:
+      switch (type) {
+      case GL_UNSIGNED_BYTE:
+         if (internalFormat != GL_R8)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_BYTE:
+         if (internalFormat != GL_R8_SNORM)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_HALF_FLOAT:
+         if (internalFormat != GL_R16F)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_FLOAT:
+         switch (internalFormat) {
+         case GL_R16F:
+         case GL_R32F:
+            break;
+         default:
+            return GL_INVALID_OPERATION;
+         }
+         break;
+
+      default:
+         return GL_INVALID_OPERATION;
+      }
+      break;
+
+   case GL_RED_INTEGER:
+      switch (type) {
+      case GL_UNSIGNED_BYTE:
+         if (internalFormat != GL_R8UI)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_BYTE:
+         if (internalFormat != GL_R8I)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_UNSIGNED_SHORT:
+         if (internalFormat != GL_R16UI)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_SHORT:
+         if (internalFormat != GL_R16I)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_UNSIGNED_INT:
+         if (internalFormat != GL_R32UI)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_INT:
+         if (internalFormat != GL_R32I)
+            return GL_INVALID_OPERATION;
+         break;
+
+      default:
+         return GL_INVALID_OPERATION;
+      }
+      break;
+
+   case GL_DEPTH_COMPONENT:
+      switch (type) {
+      case GL_UNSIGNED_SHORT:
+         if (internalFormat != GL_DEPTH_COMPONENT
+             && internalFormat != GL_DEPTH_COMPONENT16)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_UNSIGNED_INT:
+         switch (internalFormat) {
+         case GL_DEPTH_COMPONENT:
+         case GL_DEPTH_COMPONENT16:
+         case GL_DEPTH_COMPONENT24:
+            break;
+         default:
+            return GL_INVALID_OPERATION;
+         }
+         break;
+
+      case GL_FLOAT:
+         if (internalFormat != GL_DEPTH_COMPONENT32F)
+            return GL_INVALID_OPERATION;
+         break;
+
+      default:
+         return GL_INVALID_OPERATION;
+      }
+      break;
+
+   case GL_DEPTH_STENCIL:
+      switch (type) {
+      case GL_UNSIGNED_INT_24_8:
+         if (internalFormat != GL_DEPTH_STENCIL
+             && internalFormat != GL_DEPTH24_STENCIL8)
+            return GL_INVALID_OPERATION;
+         break;
+
+      case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+         if (internalFormat != GL_DEPTH32F_STENCIL8)
+            return GL_INVALID_OPERATION;
+         break;
+
+      default:
+         return GL_INVALID_OPERATION;
+      }
+      break;
+
+   case GL_ALPHA:
+   case GL_LUMINANCE:
+   case GL_LUMINANCE_ALPHA:
+      if (type != GL_UNSIGNED_BYTE || format != internalFormat)
+         return GL_INVALID_OPERATION;
+      break;
+   }
+
+   return GL_NO_ERROR;
+}