mesa: Implement glPushDebugGroup and glPopDebugGroup
[mesa.git] / src / mesa / main / glformats.c
index 047a613a1314bc8ac52b4824a1c057d2b2a6d5a2..dfee6f1963f74b642c85243c7774d817df08eb5d 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,55 @@ _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;
+   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 +383,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 +435,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 +442,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.
  */
@@ -570,6 +640,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:
@@ -788,16 +868,17 @@ _mesa_is_compressed_format(struct gl_context *ctx, GLenum format)
    switch (format) {
    case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-      return ctx->Extensions.EXT_texture_compression_s3tc;
    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
-      return _mesa_is_desktop_gl(ctx)
-         && 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 _mesa_is_desktop_gl(ctx) && 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:
@@ -819,15 +900,25 @@ _mesa_is_compressed_format(struct gl_context *ctx, GLenum format)
    case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT:
    case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
    case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT:
-      return ctx->API == API_OPENGL
+      return ctx->API == API_OPENGL_COMPAT
          && ctx->Extensions.EXT_texture_compression_latc;
    case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI:
-      return ctx->API == API_OPENGL
+      return ctx->API == API_OPENGL_COMPAT
          && ctx->Extensions.ATI_texture_compression_3dc;
    case GL_ETC1_RGB8_OES:
       return _mesa_is_gles(ctx)
          && ctx->Extensions.OES_compressed_ETC1_RGB8_texture;
-#if FEATURE_ES
+   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:
@@ -839,7 +930,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;
    }
@@ -968,6 +1058,32 @@ _mesa_base_format_has_channel(GLenum base_format, GLenum pname)
 }
 
 
+/**
+ * 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.
@@ -1007,6 +1123,119 @@ _mesa_generic_compressed_format_to_uncompressed_format(GLenum 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_SLUMINANCE:
+      return GL_LUMINANCE8;
+
+   case GL_SLUMINANCE_ALPHA:
+      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
@@ -1060,6 +1289,10 @@ _mesa_error_check_format_and_type(const struct gl_context *ctx,
           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:
@@ -1173,6 +1406,10 @@ _mesa_error_check_format_and_type(const struct gl_context *ctx,
             case GL_UNSIGNED_SHORT_5_6_5:
             case GL_UNSIGNED_SHORT_5_6_5_REV:
                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_HALF_FLOAT:
                return ctx->Extensions.ARB_half_float_pixel
                   ? GL_NO_ERROR : GL_INVALID_ENUM;
@@ -1372,3 +1609,507 @@ _mesa_error_check_format_and_type(const struct gl_context *ctx,
    }
    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)
+{
+   GLboolean type_valid = GL_TRUE;
+
+   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 type_valid ? GL_NO_ERROR : GL_INVALID_OPERATION;
+}