Ejemplo n.º 1
0
static bool
copy_format_compatible(const struct gl_context *ctx,
                       GLenum srcFormat, GLenum dstFormat)
{
   /*
    * From ARB_copy_image spec:
    *    For the purposes of CopyImageSubData, two internal formats
    *    are considered compatible if any of the following conditions are
    *    met:
    *    * the formats are the same,
    *    * the formats are considered compatible according to the
    *      compatibility rules used for texture views as defined in
    *      section 3.9.X. In particular, if both internal formats are listed
    *      in the same entry of Table 3.X.2, they are considered compatible, or
    *    * one format is compressed and the other is uncompressed and
    *      Table 4.X.1 lists the two formats in the same row.
    */

   if (_mesa_texture_view_compatible_format(ctx, srcFormat, dstFormat)) {
      /* Also checks if formats are equal. */
      return true;
   } else if (_mesa_is_compressed_format(ctx, srcFormat)) {
      return compressed_format_compatible(ctx, srcFormat, dstFormat);
   } else if (_mesa_is_compressed_format(ctx, dstFormat)) {
      return compressed_format_compatible(ctx, dstFormat, srcFormat);
   }

   return false;
}
Ejemplo n.º 2
0
/**
 * Do error checking for calls to glTexStorage1/2/3D().
 * If an error is found, record it with _mesa_error(), unless the target
 * is a proxy texture.
 * \return GL_TRUE if any error, GL_FALSE otherwise.
 */
static GLboolean
tex_storage_error_check(struct gl_context *ctx,
                        struct gl_texture_object *texObj,
                        GLuint dims, GLenum target,
                        GLsizei levels, GLenum internalformat,
                        GLsizei width, GLsizei height, GLsizei depth,
                        bool dsa)
{
   const char* suffix = dsa ? "ture" : "";

   /* Legal format checking has been moved to texstorage and texturestorage in
    * order to allow meta functions to use legacy formats. */

   /* size check */
   if (!_mesa_valid_tex_storage_dim(width, height, depth)) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glTex%sStorage%uD(width, height or depth < 1)",
                  suffix, dims);
      return GL_TRUE;
   }

   if (_mesa_is_compressed_format(ctx, internalformat)) {
      GLenum err;
      if (!_mesa_target_can_be_compressed(ctx, target, internalformat, &err)) {
         _mesa_error(ctx, err,
                  "glTex%sStorage%dD(internalformat = %s)", suffix, dims,
                  _mesa_enum_to_string(internalformat));
         return GL_TRUE;
      }
   }

   /* levels check */
   if (levels < 1) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glTex%sStorage%uD(levels < 1)",
                  suffix, dims);
      return GL_TRUE;
   }

   /* check levels against maximum (note different error than above) */
   if (levels > (GLint) _mesa_max_texture_levels(ctx, target)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glTex%sStorage%uD(levels too large)",
                  suffix, dims);
      return GL_TRUE;
   }

   /* check levels against width/height/depth */
   if (levels > _mesa_get_tex_max_num_levels(target, width, height, depth)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glTex%sStorage%uD(too many levels"
                  " for max texture dimension)",
                  suffix, dims);
      return GL_TRUE;
   }

   /* non-default texture object check */
   if (!_mesa_is_proxy_texture(target) && (!texObj || (texObj->Name == 0))) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glTex%sStorage%uD(texture object 0)",
                  suffix, dims);
      return GL_TRUE;
   }

   /* Check if texObj->Immutable is set */
   if (!_mesa_is_proxy_texture(target) && texObj->Immutable) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(immutable)",
                  suffix, dims);
      return GL_TRUE;
   }

   /* additional checks for depth textures */
   if (!_mesa_legal_texture_base_format_for_target(ctx, target, internalformat)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(bad target for texture)",
                  suffix, dims);
      return GL_TRUE;
   }

   return GL_FALSE;
}
Ejemplo n.º 3
0
static bool
compressed_format_compatible(const struct gl_context *ctx,
                             GLenum compressedFormat, GLenum otherFormat)
{
   enum mesa_block_class compressedClass, otherClass;

   /* Two view-incompatible compressed formats are never compatible. */
   if (_mesa_is_compressed_format(ctx, otherFormat)) {
      return false;
   }

   /*
    * From ARB_copy_image spec:
    *    Table 4.X.1 (Compatible internal formats for copying between
    *                 compressed and uncompressed internal formats)
    *    ---------------------------------------------------------------------
    *    | Texel / | Uncompressed      |                                     |
    *    | Block   | internal format   | Compressed internal format          |
    *    | size    |                   |                                     |
    *    ---------------------------------------------------------------------
    *    | 128-bit | RGBA32UI,         | COMPRESSED_RGBA_S3TC_DXT3_EXT,      |
    *    |         | RGBA32I,          | COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,|
    *    |         | RGBA32F           | COMPRESSED_RGBA_S3TC_DXT5_EXT,      |
    *    |         |                   | COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,|
    *    |         |                   | COMPRESSED_RG_RGTC2,                |
    *    |         |                   | COMPRESSED_SIGNED_RG_RGTC2,         |
    *    |         |                   | COMPRESSED_RGBA_BPTC_UNORM,         |
    *    |         |                   | COMPRESSED_SRGB_ALPHA_BPTC_UNORM,   |
    *    |         |                   | COMPRESSED_RGB_BPTC_SIGNED_FLOAT,   |
    *    |         |                   | COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT  |
    *    ---------------------------------------------------------------------
    *    | 64-bit  | RGBA16F, RG32F,   | COMPRESSED_RGB_S3TC_DXT1_EXT,       |
    *    |         | RGBA16UI, RG32UI, | COMPRESSED_SRGB_S3TC_DXT1_EXT,      |
    *    |         | RGBA16I, RG32I,   | COMPRESSED_RGBA_S3TC_DXT1_EXT,      |
    *    |         | RGBA16,           | COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,|
    *    |         | RGBA16_SNORM      | COMPRESSED_RED_RGTC1,               |
    *    |         |                   | COMPRESSED_SIGNED_RED_RGTC1         |
    *    ---------------------------------------------------------------------
    */

   switch (compressedFormat) {
      case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
      case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
      case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
      case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
      case GL_COMPRESSED_RG_RGTC2:
      case GL_COMPRESSED_SIGNED_RG_RGTC2:
      case GL_COMPRESSED_RGBA_BPTC_UNORM:
      case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
      case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
      case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
         compressedClass = BLOCK_CLASS_128_BITS;
         break;
      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
      case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
      case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
      case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
      case GL_COMPRESSED_RED_RGTC1:
      case GL_COMPRESSED_SIGNED_RED_RGTC1:
         compressedClass = BLOCK_CLASS_64_BITS;
         break;
      default:
         return false;
   }

   switch (otherFormat) {
      case GL_RGBA32UI:
      case GL_RGBA32I:
      case GL_RGBA32F:
         otherClass = BLOCK_CLASS_128_BITS;
         break;
      case GL_RGBA16F:
      case GL_RG32F:
      case GL_RGBA16UI:
      case GL_RG32UI:
      case GL_RGBA16I:
      case GL_RG32I:
      case GL_RGBA16:
      case GL_RGBA16_SNORM:
         otherClass = BLOCK_CLASS_64_BITS;
         break;
      default:
         return false;
   }

   return compressedClass == otherClass;
}
Ejemplo n.º 4
0
/**
 * Choose an appropriate texture format given the format, type and
 * internalFormat parameters passed to glTexImage().
 *
 * \param ctx  the GL context.
 * \param target  a texture target (GL_TEXTURE_x)
 * \param internalFormat  user's prefered internal texture format.
 * \param format  incoming image pixel format.
 * \param type  incoming image data type.
 *
 * \return the closest mesa_format for the given format/type arguments
 *
 * This is called via dd_function_table::ChooseTextureFormat.  Hardware
 * drivers may override this function with a specialized version.
 */
mesa_format
_mesa_choose_tex_format(struct gl_context *ctx, GLenum target,
                        GLint internalFormat, GLenum format, GLenum type)
{
   (void) format;

   switch (internalFormat) {
   /* shallow RGBA formats */
   case 4:
   case GL_RGBA:
      if (type == GL_UNSIGNED_SHORT_4_4_4_4_REV) {
         RETURN_IF_SUPPORTED(MESA_FORMAT_B4G4R4A4_UNORM);
      } else if (type == GL_UNSIGNED_SHORT_1_5_5_5_REV) {
         RETURN_IF_SUPPORTED(MESA_FORMAT_B5G5R5A1_UNORM);
      } else if (type == GL_UNSIGNED_SHORT_5_5_5_1) {
         RETURN_IF_SUPPORTED(MESA_FORMAT_B5G5R5A1_UNORM);
      } else if (type == GL_UNSIGNED_INT_2_10_10_10_REV) {
         RETURN_IF_SUPPORTED(MESA_FORMAT_B10G10R10A2_UNORM);
      }
      /* fallthrough */

   case GL_RGBA8:
      RETURN_IF_SUPPORTED(MESA_FORMAT_R8G8B8A8_UNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8B8G8R8_UNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8A8_UNORM);
      break;
   case GL_RGB5_A1:
      RETURN_IF_SUPPORTED(MESA_FORMAT_B5G5R5A1_UNORM);
      break;
   case GL_RGBA2:
      RETURN_IF_SUPPORTED(MESA_FORMAT_A4R4G4B4_UNORM); /* just to test another format*/
      RETURN_IF_SUPPORTED(MESA_FORMAT_B4G4R4A4_UNORM);
      break;
   case GL_RGBA4:
      RETURN_IF_SUPPORTED(MESA_FORMAT_B4G4R4A4_UNORM);
      break;

   /* deep RGBA formats */
   case GL_RGB10_A2:
      RETURN_IF_SUPPORTED(MESA_FORMAT_R10G10B10A2_UNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_B10G10R10A2_UNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8A8_UNORM);
      break;
   case GL_RGBA12:
   case GL_RGBA16:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UNORM16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UNORM16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8B8G8R8_UNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8A8_UNORM);
      break;

   /* shallow RGB formats */
   case 3:
   case GL_RGB:
      if (type == GL_UNSIGNED_INT_2_10_10_10_REV) {
         RETURN_IF_SUPPORTED(MESA_FORMAT_B10G10R10A2_UNORM);
      }
      /* fallthrough */
   case GL_RGB8:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_UNORM8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_R8G8B8X8_UNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_R8G8B8A8_UNORM);

      RETURN_IF_SUPPORTED(MESA_FORMAT_BGR_UNORM8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8X8_UNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8A8_UNORM);
      break;
   case GL_R3_G3_B2:
      RETURN_IF_SUPPORTED(MESA_FORMAT_B2G3R3_UNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_B5G6R5_UNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_R5G6B5_UNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_BGR_UNORM8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8X8_UNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8A8_UNORM);
      break;
   case GL_RGB4:
      RETURN_IF_SUPPORTED(MESA_FORMAT_R5G6B5_UNORM); /* just to test another format */
      RETURN_IF_SUPPORTED(MESA_FORMAT_B5G6R5_UNORM);
      break;
   case GL_RGB5:
      RETURN_IF_SUPPORTED(MESA_FORMAT_B5G6R5_UNORM);
      break;

   /* deep RGB formats */
   case GL_RGB10:
   case GL_RGB12:
   case GL_RGB16:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBX_UNORM16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UNORM16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8X8_UNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8A8_UNORM);
      break;

   /* Alpha formats */
   case GL_ALPHA:
   case GL_ALPHA4:
   case GL_ALPHA8:
      RETURN_IF_SUPPORTED(MESA_FORMAT_A_UNORM8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_L8A8_UNORM);
      break;

   case GL_ALPHA12:
   case GL_ALPHA16:
      RETURN_IF_SUPPORTED(MESA_FORMAT_A_UNORM16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A_UNORM8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_L8A8_UNORM);
      break;

   /* Luminance formats */
   case 1:
   case GL_LUMINANCE:
   case GL_LUMINANCE4:
   case GL_LUMINANCE8:
      RETURN_IF_SUPPORTED(MESA_FORMAT_L_UNORM8);
      break;

   case GL_LUMINANCE12:
   case GL_LUMINANCE16:
      RETURN_IF_SUPPORTED(MESA_FORMAT_L_UNORM16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_L_UNORM8);
      break;

      /* Luminance/Alpha formats */
   case GL_LUMINANCE4_ALPHA4:
      RETURN_IF_SUPPORTED(MESA_FORMAT_L4A4_UNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_L8A8_UNORM);
      break;

   case 2:
   case GL_LUMINANCE_ALPHA:
   case GL_LUMINANCE6_ALPHA2:
   case GL_LUMINANCE8_ALPHA8:
      RETURN_IF_SUPPORTED(MESA_FORMAT_L8A8_UNORM);
      break;

   case GL_LUMINANCE12_ALPHA4:
   case GL_LUMINANCE12_ALPHA12:
   case GL_LUMINANCE16_ALPHA16:
      RETURN_IF_SUPPORTED(MESA_FORMAT_L16A16_UNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_L8A8_UNORM);
      break;

   case GL_INTENSITY:
   case GL_INTENSITY4:
   case GL_INTENSITY8:
      RETURN_IF_SUPPORTED(MESA_FORMAT_I_UNORM8);
      break;

   case GL_INTENSITY12:
   case GL_INTENSITY16:
      RETURN_IF_SUPPORTED(MESA_FORMAT_I_UNORM16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_I_UNORM8);
      break;

   case GL_DEPTH_COMPONENT:
   case GL_DEPTH_COMPONENT24:
   case GL_DEPTH_COMPONENT32:
      RETURN_IF_SUPPORTED(MESA_FORMAT_Z_UNORM32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_UNORM_X8_UINT);
      RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_UNORM_S8_UINT);
      break;
   case GL_DEPTH_COMPONENT16:
      RETURN_IF_SUPPORTED(MESA_FORMAT_Z_UNORM16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_UNORM_X8_UINT);
      RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_UNORM_S8_UINT);
      break;

   case GL_COMPRESSED_ALPHA_ARB:
      RETURN_IF_SUPPORTED(MESA_FORMAT_A_UNORM8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_L8A8_UNORM);
      break;
   case GL_COMPRESSED_LUMINANCE_ARB:
      RETURN_IF_SUPPORTED(MESA_FORMAT_L_UNORM8);
      break;
   case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
      RETURN_IF_SUPPORTED(MESA_FORMAT_L8A8_UNORM);
      break;
   case GL_COMPRESSED_INTENSITY_ARB:
      RETURN_IF_SUPPORTED(MESA_FORMAT_I_UNORM8);
      break;
   case GL_COMPRESSED_RGB_ARB:
      /* We don't use texture compression for 1D and 1D array textures.
       * For 1D textures, compressions doesn't buy us much.
       * For 1D ARRAY textures, there's complicated issues with updating
       * sub-regions on non-block boundaries with glCopyTexSubImage, among
       * other issues.  FWIW, the GL_EXT_texture_array extension prohibits
       * 1D ARRAY textures in S3TC format.
       */
      if (target != GL_TEXTURE_1D && target != GL_TEXTURE_1D_ARRAY) {
         if (ctx->Mesa_DXTn)
            RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_DXT1);
         RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FXT1);
      }
      RETURN_IF_SUPPORTED(MESA_FORMAT_BGR_UNORM8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8X8_UNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8A8_UNORM);
      break;
   case GL_COMPRESSED_RGBA_ARB:
      /* We don't use texture compression for 1D and 1D array textures. */
      if (target != GL_TEXTURE_1D && target != GL_TEXTURE_1D_ARRAY) {
         if (ctx->Mesa_DXTn)
            RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT3); /* Not rgba_dxt1, see spec */
         RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FXT1);
      }
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8B8G8R8_UNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8A8_UNORM);
      break;

   case GL_RGB565:
      RETURN_IF_SUPPORTED(MESA_FORMAT_B5G6R5_UNORM);
      break;

   case GL_YCBCR_MESA:
      if (type == GL_UNSIGNED_SHORT_8_8_MESA)
         RETURN_IF_SUPPORTED(MESA_FORMAT_YCBCR);
      else
         RETURN_IF_SUPPORTED(MESA_FORMAT_YCBCR_REV);
      break;

   case GL_ALPHA16F_ARB:
      RETURN_IF_SUPPORTED(MESA_FORMAT_A_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32);
      break;
   case GL_ALPHA32F_ARB:
      RETURN_IF_SUPPORTED(MESA_FORMAT_A_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16);
      break;
   case GL_LUMINANCE16F_ARB:
      RETURN_IF_SUPPORTED(MESA_FORMAT_L_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_L_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32);
      break;
   case GL_LUMINANCE32F_ARB:
      RETURN_IF_SUPPORTED(MESA_FORMAT_L_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_L_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16);
      break;
   case GL_LUMINANCE_ALPHA16F_ARB:
      RETURN_IF_SUPPORTED(MESA_FORMAT_LA_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_LA_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32);
      break;
   case GL_LUMINANCE_ALPHA32F_ARB:
      RETURN_IF_SUPPORTED(MESA_FORMAT_LA_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_LA_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16);
      break;
   case GL_INTENSITY16F_ARB:
      RETURN_IF_SUPPORTED(MESA_FORMAT_I_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_I_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32);
      break;
   case GL_INTENSITY32F_ARB:
      RETURN_IF_SUPPORTED(MESA_FORMAT_I_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_I_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16);
      break;
   case GL_RGB16F_ARB:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBX_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32);
      break;
   case GL_RGB32F_ARB:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBX_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16);
      break;
   case GL_RGBA16F_ARB:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32);
      break;
   case GL_RGBA32F_ARB:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16);
      break;

   case GL_RGB9_E5:
      /* GL_EXT_texture_shared_exponent -- just one format to support */
      assert(ctx->TextureFormatSupported[MESA_FORMAT_R9G9B9E5_FLOAT]);
      return MESA_FORMAT_R9G9B9E5_FLOAT;

   case GL_R11F_G11F_B10F:
      /* GL_EXT_texture_packed_float -- just one format to support */
      assert(ctx->TextureFormatSupported[MESA_FORMAT_R11G11B10_FLOAT]);
      return MESA_FORMAT_R11G11B10_FLOAT;

   case GL_DEPTH_STENCIL_EXT:
   case GL_DEPTH24_STENCIL8_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_S8_UINT_Z24_UNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_UNORM_S8_UINT);
      break;

   case GL_DEPTH_COMPONENT32F:
      assert(ctx->TextureFormatSupported[MESA_FORMAT_Z_FLOAT32]);
      return MESA_FORMAT_Z_FLOAT32;
   case GL_DEPTH32F_STENCIL8:
      assert(ctx->TextureFormatSupported[MESA_FORMAT_Z32_FLOAT_S8X24_UINT]);
      return MESA_FORMAT_Z32_FLOAT_S8X24_UINT;

   case GL_RED_SNORM:
   case GL_R8_SNORM:
      RETURN_IF_SUPPORTED(MESA_FORMAT_R_SNORM8);
      break;
   case GL_RG_SNORM:
   case GL_RG8_SNORM:
      RETURN_IF_SUPPORTED(MESA_FORMAT_R8G8_SNORM);
      break;
   case GL_RGB_SNORM:
   case GL_RGB8_SNORM:
      RETURN_IF_SUPPORTED(MESA_FORMAT_R8G8B8X8_SNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_R8G8B8A8_SNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_X8B8G8R8_SNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8B8G8R8_SNORM);
      break;
   case GL_RGBA_SNORM:
   case GL_RGBA8_SNORM:
      RETURN_IF_SUPPORTED(MESA_FORMAT_R8G8B8A8_SNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8B8G8R8_SNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_R8G8B8A8_SNORM);
      break;
   case GL_ALPHA_SNORM:
   case GL_ALPHA8_SNORM:
      RETURN_IF_SUPPORTED(MESA_FORMAT_A_SNORM8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8B8G8R8_SNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_R8G8B8A8_SNORM);
      break;
   case GL_LUMINANCE_SNORM:
   case GL_LUMINANCE8_SNORM:
      RETURN_IF_SUPPORTED(MESA_FORMAT_L_SNORM8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_X8B8G8R8_SNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8B8G8R8_SNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_R8G8B8A8_SNORM);
      break;
   case GL_LUMINANCE_ALPHA_SNORM:
   case GL_LUMINANCE8_ALPHA8_SNORM:
      RETURN_IF_SUPPORTED(MESA_FORMAT_L8A8_SNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8L8_SNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8B8G8R8_SNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_R8G8B8A8_SNORM);
      break;
   case GL_INTENSITY_SNORM:
   case GL_INTENSITY8_SNORM:
      RETURN_IF_SUPPORTED(MESA_FORMAT_I_SNORM8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8B8G8R8_SNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_R8G8B8A8_SNORM);
      break;
   case GL_R16_SNORM:
      RETURN_IF_SUPPORTED(MESA_FORMAT_R_SNORM16);
      break;
   case GL_RG16_SNORM:
      RETURN_IF_SUPPORTED(MESA_FORMAT_R16G16_SNORM);
      break;
   case GL_RGB16_SNORM:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_SNORM16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBX_SNORM16);
      /* FALLTHROUGH */
   case GL_RGBA16_SNORM:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_SNORM16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8B8G8R8_SNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_R8G8B8A8_SNORM);
      break;
   case GL_ALPHA16_SNORM:
      RETURN_IF_SUPPORTED(MESA_FORMAT_A_SNORM16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_SNORM16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8B8G8R8_SNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_R8G8B8A8_SNORM);
      break;
   case GL_LUMINANCE16_SNORM:
      RETURN_IF_SUPPORTED(MESA_FORMAT_L_SNORM16);
      /* FALLTHROUGH */
   case GL_LUMINANCE16_ALPHA16_SNORM:
      RETURN_IF_SUPPORTED(MESA_FORMAT_LA_SNORM16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_SNORM16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8B8G8R8_SNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_R8G8B8A8_SNORM);
      break;
   case GL_INTENSITY16_SNORM:
      RETURN_IF_SUPPORTED(MESA_FORMAT_I_SNORM16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_SNORM16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8B8G8R8_SNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_R8G8B8A8_SNORM);
      break;

   case GL_SRGB_EXT:
   case GL_SRGB8_EXT:
      /* there is no MESA_FORMAT_RGB_SRGB8 */
      RETURN_IF_SUPPORTED(MESA_FORMAT_R8G8B8X8_SRGB);
      RETURN_IF_SUPPORTED(MESA_FORMAT_R8G8B8A8_SRGB);

      RETURN_IF_SUPPORTED(MESA_FORMAT_BGR_SRGB8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8A8_SRGB);

      RETURN_IF_SUPPORTED(MESA_FORMAT_X8B8G8R8_SRGB);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8R8G8B8_SRGB);
      break;
   case GL_SRGB_ALPHA_EXT:
   case GL_SRGB8_ALPHA8_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_R8G8B8A8_SRGB);

      RETURN_IF_SUPPORTED(MESA_FORMAT_A8B8G8R8_SRGB);
      RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8A8_SRGB);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8R8G8B8_SRGB);
      break;
   case GL_SLUMINANCE_EXT:
   case GL_SLUMINANCE8_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_L_SRGB8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8A8_SRGB);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8R8G8B8_SRGB);
      break;
   case GL_SLUMINANCE_ALPHA_EXT:
   case GL_SLUMINANCE8_ALPHA8_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_L8A8_SRGB);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8L8_SRGB);
      RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8A8_SRGB);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8R8G8B8_SRGB);
      break;
   case GL_COMPRESSED_SLUMINANCE_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_L_SRGB8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8A8_SRGB);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8R8G8B8_SRGB);
      break;
   case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_L8A8_SRGB);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8L8_SRGB);
      RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8A8_SRGB);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8R8G8B8_SRGB);
      break;
   case GL_COMPRESSED_SRGB_EXT:
      if (ctx->Mesa_DXTn)
         RETURN_IF_SUPPORTED(MESA_FORMAT_SRGB_DXT1);
      RETURN_IF_SUPPORTED(MESA_FORMAT_BGR_SRGB8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8A8_SRGB);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8R8G8B8_SRGB);
      break;
   case GL_COMPRESSED_SRGB_ALPHA_EXT:
      if (ctx->Mesa_DXTn)
         RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA_DXT3); /* Not srgba_dxt1, see spec */
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8B8G8R8_SRGB);
      RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8A8_SRGB);
      RETURN_IF_SUPPORTED(MESA_FORMAT_A8R8G8B8_SRGB);
      break;

   case GL_ALPHA8UI_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_A_UINT8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT8);
      break;
   case GL_ALPHA16UI_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_A_UINT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT16);
      break;
   case GL_ALPHA32UI_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_A_UINT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT32);
      break;
   case GL_ALPHA8I_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_A_SINT8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_SINT8);
      break;
   case GL_ALPHA16I_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_A_SINT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_SINT16);
      break;
   case GL_ALPHA32I_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_A_SINT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_SINT32);
      break;
   case GL_LUMINANCE8UI_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_L_UINT8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT8);
      break;
   case GL_LUMINANCE16UI_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_L_UINT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT16);
      break;
   case GL_LUMINANCE32UI_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_L_UINT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT32);
      break;
   case GL_LUMINANCE8I_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_L_SINT8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_SINT8);
      break;
   case GL_LUMINANCE16I_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_L_SINT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_SINT16);
      break;
   case GL_LUMINANCE32I_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_L_SINT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_SINT32);
      break;
   case GL_LUMINANCE_ALPHA8UI_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_LA_UINT8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT8);
      break;
   case GL_LUMINANCE_ALPHA16UI_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_LA_UINT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT16);
      break;
   case GL_LUMINANCE_ALPHA32UI_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_LA_UINT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT32);
      break;
   case GL_LUMINANCE_ALPHA8I_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_LA_SINT8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_SINT8);
      break;
   case GL_LUMINANCE_ALPHA16I_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_LA_SINT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_SINT16);
      break;
   case GL_LUMINANCE_ALPHA32I_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_LA_SINT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_SINT32);
      break;
   case GL_INTENSITY8UI_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_I_UINT8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT8);
      break;
   case GL_INTENSITY16UI_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_I_UINT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT16);
      break;
   case GL_INTENSITY32UI_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_I_UINT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT32);
      break;
   case GL_INTENSITY8I_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_I_SINT8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_SINT8);
      break;
   case GL_INTENSITY16I_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_I_SINT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_SINT16);
      break;
   case GL_INTENSITY32I_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_I_SINT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_SINT32);
      break;

   case GL_RGB8UI_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_UINT8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBX_UINT8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT8);
      break;
   case GL_RGB16UI_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_UINT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBX_UINT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT16);
      break;
   case GL_RGB32UI_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_UINT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBX_UINT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT32);
      break;
   case GL_RGB8I_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_SINT8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBX_SINT8);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_SINT8);
      break;
   case GL_RGB16I_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_SINT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBX_SINT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_SINT16);
      break;
   case GL_RGB32I_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_SINT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBX_SINT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_SINT32);
      break;
   case GL_RGBA8UI_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT8);
      break;
   case GL_RGBA16UI_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT16);
      break;
   case GL_RGBA32UI_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT32);
      break;
   case GL_RGBA8I_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_SINT8);
      break;
   case GL_RGBA16I_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_SINT16);
      break;
   case GL_RGBA32I_EXT:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_SINT32);
      break;

   case GL_R8:
   case GL_RED:
      RETURN_IF_SUPPORTED(MESA_FORMAT_R_UNORM8);
      break;

   case GL_COMPRESSED_RED:
      if (target != GL_TEXTURE_1D && target != GL_TEXTURE_1D_ARRAY)
         RETURN_IF_SUPPORTED(MESA_FORMAT_R_RGTC1_UNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_R_UNORM8);
      break;

   case GL_R16:
      RETURN_IF_SUPPORTED(MESA_FORMAT_R_UNORM16);
      break;

   case GL_RG:
   case GL_RG8:
      RETURN_IF_SUPPORTED(MESA_FORMAT_R8G8_UNORM);
      break;

   case GL_COMPRESSED_RG:
      if (target != GL_TEXTURE_1D && target != GL_TEXTURE_1D_ARRAY)
         RETURN_IF_SUPPORTED(MESA_FORMAT_RG_RGTC2_UNORM);
      RETURN_IF_SUPPORTED(MESA_FORMAT_R8G8_UNORM);
      break;

   case GL_RG16:
      RETURN_IF_SUPPORTED(MESA_FORMAT_R16G16_UNORM);
      break;

   case GL_R16F:
      RETURN_IF_SUPPORTED(MESA_FORMAT_R_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RG_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_R_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RG_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32);
      break;
   case GL_R32F:
      RETURN_IF_SUPPORTED(MESA_FORMAT_R_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RG_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_R_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RG_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16);
      break;
   case GL_RG16F:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RG_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RG_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32);
      break;
   case GL_RG32F:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RG_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RG_FLOAT16);
      RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16);
      break;

   case GL_R8UI:
      RETURN_IF_SUPPORTED(MESA_FORMAT_R_UINT8);
      break;
   case GL_RG8UI:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RG_UINT8);
      break;
   case GL_R16UI:
      RETURN_IF_SUPPORTED(MESA_FORMAT_R_UINT16);
      break;
   case GL_RG16UI:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RG_UINT16);
      break;
   case GL_R32UI:
      RETURN_IF_SUPPORTED(MESA_FORMAT_R_UINT32);
      break;
   case GL_RG32UI:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RG_UINT32);
      break;
   case GL_R8I:
      RETURN_IF_SUPPORTED(MESA_FORMAT_R_SINT8);
      break;
   case GL_RG8I:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RG_SINT8);
      break;
   case GL_R16I:
      RETURN_IF_SUPPORTED(MESA_FORMAT_R_SINT16);
      break;
   case GL_RG16I:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RG_SINT16);
      break;
   case GL_R32I:
      RETURN_IF_SUPPORTED(MESA_FORMAT_R_SINT32);
      break;
   case GL_RG32I:
      RETURN_IF_SUPPORTED(MESA_FORMAT_RG_SINT32);
      break;

   case GL_RGB10_A2UI:
      RETURN_IF_SUPPORTED(MESA_FORMAT_B10G10R10A2_UINT);
      RETURN_IF_SUPPORTED(MESA_FORMAT_R10G10B10A2_UINT);
      break;

   case GL_BGRA:
      RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8A8_UNORM);
      break;

   case GL_STENCIL_INDEX:
   case GL_STENCIL_INDEX8:
      RETURN_IF_SUPPORTED(MESA_FORMAT_S_UINT8);
      break;

   default:
      /* For non-generic compressed format we assert two things:
       *
       * 1. The format has already been validated against the set of available
       *    extensions.
       *
       * 2. The driver only enables the extension if it supports all of the
       *    formats that are part of that extension.
       */
      if (_mesa_is_compressed_format(ctx, internalFormat))
         return _mesa_glenum_to_compressed_format(internalFormat);
   }

   _mesa_problem(ctx, "unexpected format %s in _mesa_choose_tex_format()",
                 _mesa_enum_to_string(internalFormat));
   return MESA_FORMAT_NONE;
}
Ejemplo n.º 5
0
void GLAPIENTRY
_mesa_GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname,
                          GLsizei bufSize, GLint *params)
{
   GLint buffer[16];
   GET_CURRENT_CONTEXT(ctx);

   ASSERT_OUTSIDE_BEGIN_END(ctx);

   /* ARB_internalformat_query is also mandatory for ARB_internalformat_query2 */
   if (!(_mesa_has_ARB_internalformat_query(ctx) ||
         _mesa_is_gles3(ctx))) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetInternalformativ");
      return;
   }

   assert(ctx->Driver.QueryInternalFormat != NULL);

   if (!_legal_parameters(ctx, target, internalformat, pname, bufSize, params))
      return;

   /* initialize the contents of the temporary buffer */
   memcpy(buffer, params, MIN2(bufSize, 16) * sizeof(GLint));

   /* Use the 'unsupported' response defined by the spec for every pname
    * as the default answer.
    */
   _set_default_response(pname, buffer);

   if (!_is_target_supported(ctx, target) ||
       !_is_internalformat_supported(ctx, target, internalformat) ||
       !_is_resource_supported(ctx, target, internalformat, pname))
      goto end;

   switch (pname) {
   case GL_SAMPLES:
      /* fall-through */
   case GL_NUM_SAMPLE_COUNTS:
      /* The ARB_internalformat_query2 sets the response as 'unsupported' for
       * SAMPLES and NUM_SAMPLE_COUNTS:
       *
       *     "If <internalformat> is not color-renderable, depth-renderable, or
       *     stencil-renderable (as defined in section 4.4.4), or if <target>
       *     does not support multiple samples (ie other than
       *     TEXTURE_2D_MULTISAMPLE,  TEXTURE_2D_MULTISAMPLE_ARRAY,
       *     or RENDERBUFFER)."
       */
      if ((target != GL_RENDERBUFFER &&
           target != GL_TEXTURE_2D_MULTISAMPLE &&
           target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY) ||
          !_is_renderable(ctx, internalformat))
         goto end;

      /* The GL ES 3.0 specification, section 6.1.15 page 236 says:
       *
       *     "Since multisampling is not supported for signed and unsigned
       *     integer internal formats, the value of NUM_SAMPLE_COUNTS will be
       *     zero for such formats.
       *
       * Since OpenGL ES 3.1 adds support for multisampled integer formats, we
       * have to check the version for 30 exactly.
       */
      if (pname == GL_NUM_SAMPLE_COUNTS && ctx->API == API_OPENGLES2 &&
          ctx->Version == 30 && _mesa_is_enum_format_integer(internalformat)) {
         goto end;
      }

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_INTERNALFORMAT_SUPPORTED:
      /* Having a supported <internalformat> is implemented as a prerequisite
       * for all the <pnames>. Thus,  if we reach this point, the internalformat is
       * supported.
       */
      buffer[0] = GL_TRUE;
      break;

   case GL_INTERNALFORMAT_PREFERRED:
      /* The ARB_internalformat_query2 spec says:
       *
       *     "- INTERNALFORMAT_PREFERRED: The implementation-preferred internal
       *     format for representing resources of the specified <internalformat> is
       *     returned in <params>.
       *
       * Therefore, we let the driver answer. Note that if we reach this
       * point, it means that the internalformat is supported, so the driver
       * is called just to try to get a preferred format. If not supported,
       * GL_NONE was already returned and the driver is not called.
       */
      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_INTERNALFORMAT_RED_SIZE:
   case GL_INTERNALFORMAT_GREEN_SIZE:
   case GL_INTERNALFORMAT_BLUE_SIZE:
   case GL_INTERNALFORMAT_ALPHA_SIZE:
   case GL_INTERNALFORMAT_DEPTH_SIZE:
   case GL_INTERNALFORMAT_STENCIL_SIZE:
   case GL_INTERNALFORMAT_SHARED_SIZE:
   case GL_INTERNALFORMAT_RED_TYPE:
   case GL_INTERNALFORMAT_GREEN_TYPE:
   case GL_INTERNALFORMAT_BLUE_TYPE:
   case GL_INTERNALFORMAT_ALPHA_TYPE:
   case GL_INTERNALFORMAT_DEPTH_TYPE:
   case GL_INTERNALFORMAT_STENCIL_TYPE: {
      GLint baseformat;
      mesa_format texformat;

      if (target != GL_RENDERBUFFER) {
         if (!_mesa_legal_get_tex_level_parameter_target(ctx, target, true))
            goto end;

         baseformat = _mesa_base_tex_format(ctx, internalformat);
      } else {
         baseformat = _mesa_base_fbo_format(ctx, internalformat);
      }

      /* Let the driver choose the texture format.
       *
       * Disclaimer: I am considering that drivers use for renderbuffers the
       * same format-choice logic as for textures.
       */
      texformat = ctx->Driver.ChooseTextureFormat(ctx, target, internalformat,
                                                  GL_NONE /*format */, GL_NONE /* type */);

      if (texformat == MESA_FORMAT_NONE || baseformat <= 0)
         goto end;

      /* Implementation based on what Mesa does for glGetTexLevelParameteriv
       * and glGetRenderbufferParameteriv functions.
       */
      if (pname == GL_INTERNALFORMAT_SHARED_SIZE) {
         if (_mesa_has_EXT_texture_shared_exponent(ctx) &&
             target != GL_TEXTURE_BUFFER &&
             target != GL_RENDERBUFFER &&
             texformat == MESA_FORMAT_R9G9B9E5_FLOAT) {
            buffer[0] = 5;
         }
         goto end;
      }

      if (!_mesa_base_format_has_channel(baseformat, pname))
         goto end;

      switch (pname) {
      case GL_INTERNALFORMAT_DEPTH_SIZE:
         if (ctx->API != API_OPENGL_CORE &&
             !_mesa_has_ARB_depth_texture(ctx) &&
             target != GL_RENDERBUFFER &&
             target != GL_TEXTURE_BUFFER)
            goto end;
         /* fallthrough */
      case GL_INTERNALFORMAT_RED_SIZE:
      case GL_INTERNALFORMAT_GREEN_SIZE:
      case GL_INTERNALFORMAT_BLUE_SIZE:
      case GL_INTERNALFORMAT_ALPHA_SIZE:
      case GL_INTERNALFORMAT_STENCIL_SIZE:
         buffer[0] = _mesa_get_format_bits(texformat, pname);
         break;

      case GL_INTERNALFORMAT_DEPTH_TYPE:
         if (!_mesa_has_ARB_texture_float(ctx))
            goto end;
         /* fallthrough */
      case GL_INTERNALFORMAT_RED_TYPE:
      case GL_INTERNALFORMAT_GREEN_TYPE:
      case GL_INTERNALFORMAT_BLUE_TYPE:
      case GL_INTERNALFORMAT_ALPHA_TYPE:
      case GL_INTERNALFORMAT_STENCIL_TYPE:
         buffer[0]  = _mesa_get_format_datatype(texformat);
         break;

      default:
         break;

      }
      break;
   }

      /* For WIDTH/HEIGHT/DEPTH/LAYERS there is no reason to think that the
       * returned values should be different to the values returned by
       * GetInteger with MAX_TEXTURE_SIZE, MAX_3D_TEXTURE_SIZE, etc.*/
   case GL_MAX_WIDTH:
   case GL_MAX_HEIGHT:
   case GL_MAX_DEPTH: {
      GLenum get_pname;
      GLint dimensions;
      GLint min_dimensions;

      /* From query2:MAX_HEIGHT spec (as example):
       *
       * "If the resource does not have at least two dimensions, or if the
       * resource is unsupported, zero is returned."
       */
      dimensions = _get_target_dimensions(target);
      min_dimensions = _get_min_dimensions(pname);
      if (dimensions < min_dimensions)
         goto end;

      get_pname = _equivalent_size_pname(target, pname);
      if (get_pname == 0)
         goto end;

      _mesa_GetIntegerv(get_pname, buffer);
      break;
   }

   case GL_MAX_LAYERS:
      if (!_mesa_has_EXT_texture_array(ctx))
         goto end;

      if (!_mesa_is_array_texture(target))
         goto end;

      _mesa_GetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, buffer);
      break;

   case GL_MAX_COMBINED_DIMENSIONS:{
      GLint64 combined_value = 1;
      GLenum max_dimensions_pnames[] = {
         GL_MAX_WIDTH,
         GL_MAX_HEIGHT,
         GL_MAX_DEPTH,
         GL_SAMPLES
      };
      unsigned i;
      GLint current_value;

      /* Combining the dimensions. Note that for array targets, this would
       * automatically include the value of MAX_LAYERS, as that value is
       * returned as MAX_HEIGHT or MAX_DEPTH */
      for (i = 0; i < 4; i++) {
         if (max_dimensions_pnames[i] == GL_SAMPLES &&
             !_is_multisample_target(target))
            continue;

         _mesa_GetInternalformativ(target, internalformat,
                                   max_dimensions_pnames[i],
                                   1, &current_value);

         if (current_value != 0)
            combined_value *= current_value;
      }

      if (_mesa_is_cube_map_texture(target))
         combined_value *= 6;

      /* We pack the 64-bit value on two 32-bit values. Calling the 32-bit
       * query, this would work as far as the value can be hold on a 32-bit
       * signed integer. For the 64-bit query, the wrapper around the 32-bit
       * query will unpack the value */
      memcpy(buffer, &combined_value, sizeof(GLint64));
      break;
   }

   case GL_COLOR_COMPONENTS:
      /* The ARB_internalformat_query2 spec says:
       *
       *     "- COLOR_COMPONENTS: If the internal format contains any color
       *     components (R, G, B, or A), TRUE is returned in <params>.
       *     If the internal format is unsupported or contains no color
       *     components, FALSE is returned."
       */
      if (_mesa_is_color_format(internalformat))
         buffer[0] = GL_TRUE;
      break;

   case GL_DEPTH_COMPONENTS:
      /* The ARB_internalformat_query2 spec says:
       *
       *     "- DEPTH_COMPONENTS: If the internal format contains a depth
       *     component (D), TRUE is returned in <params>. If the internal format
       *     is unsupported or contains no depth component, FALSE is returned."
       */
      if (_mesa_is_depth_format(internalformat) ||
          _mesa_is_depthstencil_format(internalformat))
         buffer[0] = GL_TRUE;
      break;

   case GL_STENCIL_COMPONENTS:
      /* The ARB_internalformat_query2 spec says:
       *
       *     "- STENCIL_COMPONENTS: If the internal format contains a stencil
       *     component (S), TRUE is returned in <params>. If the internal format
       *     is unsupported or contains no stencil component, FALSE is returned.
       */
      if (_mesa_is_stencil_format(internalformat) ||
          _mesa_is_depthstencil_format(internalformat))
         buffer[0] = GL_TRUE;
      break;

   case GL_COLOR_RENDERABLE:
   case GL_DEPTH_RENDERABLE:
   case GL_STENCIL_RENDERABLE:
      if (!_is_renderable(ctx, internalformat))
         goto end;

      if (pname == GL_COLOR_RENDERABLE) {
         if (!_mesa_is_color_format(internalformat))
            goto end;
      } else {
         GLenum baseFormat = _mesa_base_fbo_format(ctx, internalformat);
         if (baseFormat != GL_DEPTH_STENCIL &&
             ((pname == GL_DEPTH_RENDERABLE && baseFormat != GL_DEPTH_COMPONENT) ||
              (pname == GL_STENCIL_RENDERABLE && baseFormat != GL_STENCIL_INDEX)))
            goto end;
      }

      buffer[0] = GL_TRUE;
      break;

   case GL_FRAMEBUFFER_RENDERABLE_LAYERED:
      if (!_mesa_has_EXT_texture_array(ctx) ||
          _legal_target_for_framebuffer_texture_layer(ctx, target))
         goto end;
      /* fallthrough */
   case GL_FRAMEBUFFER_RENDERABLE:
   case GL_FRAMEBUFFER_BLEND:
      if (!_mesa_has_ARB_framebuffer_object(ctx))
         goto end;

      if (target == GL_TEXTURE_BUFFER ||
          !_is_renderable(ctx, internalformat))
         goto end;

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_READ_PIXELS:
   case GL_READ_PIXELS_FORMAT:
   case GL_READ_PIXELS_TYPE:
      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_TEXTURE_IMAGE_FORMAT:
   case GL_GET_TEXTURE_IMAGE_FORMAT:
   case GL_TEXTURE_IMAGE_TYPE:
   case GL_GET_TEXTURE_IMAGE_TYPE:
      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_MIPMAP:
   case GL_MANUAL_GENERATE_MIPMAP:
   case GL_AUTO_GENERATE_MIPMAP:
      if (!_mesa_is_valid_generate_texture_mipmap_target(ctx, target) ||
          !_mesa_is_valid_generate_texture_mipmap_internalformat(ctx,
                                                              internalformat)) {
         goto end;
      }

      if (pname == GL_MIPMAP) {
         buffer[0] = GL_TRUE;
         goto end;
      }
      else if (pname == GL_MANUAL_GENERATE_MIPMAP) {
         if (!_mesa_has_ARB_framebuffer_object(ctx))
            goto end;
      }
      else {
         /* From ARB_internalformat_query2:
          *    "Dependencies on OpenGL 3.2 (Core Profile)
          *     In core profiles for OpenGL 3.2 and later versions, queries
          *     for the AUTO_GENERATE_MIPMAP <pname> return the appropriate
          *     unsupported response."
          */
         if (_mesa_is_desktop_gl(ctx) && ctx->Version >= 32)
            goto end;
      }

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_COLOR_ENCODING:
      if (!_mesa_is_color_format(internalformat))
         goto end;

      if (_mesa_is_srgb_format(internalformat))
         buffer[0] = GL_SRGB;
      else
         buffer[0] = GL_LINEAR;
      break;

   case GL_SRGB_READ:
      if (!_mesa_has_EXT_texture_sRGB(ctx) ||
          !_mesa_is_srgb_format(internalformat)) {
         goto end;
      }

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_SRGB_WRITE:
      if (!_mesa_has_EXT_framebuffer_sRGB(ctx) ||
          !_mesa_is_color_format(internalformat)) {
         goto end;
      }

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_SRGB_DECODE_ARB:
      /* Presence of EXT_texture_sRGB_decode was already verified */
      if (!_mesa_has_EXT_texture_sRGB(ctx) ||
          target == GL_RENDERBUFFER ||
          !_mesa_is_srgb_format(internalformat)) {
         goto end;
      }

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_FILTER:
      /* If it doesn't allow to set sampler parameters then it would not allow
       * to set a filter different to GL_NEAREST. In practice, this method
       * only filters out MULTISAMPLE/MULTISAMPLE_ARRAY */
      if (!_mesa_target_allows_setting_sampler_parameters(target))
         goto end;

      if (_mesa_is_enum_format_integer(internalformat))
         goto end;

      if (target == GL_TEXTURE_BUFFER)
         goto end;

      /* At this point we know that multi-texel filtering is supported. We
       * need to call the driver to know if it is CAVEAT_SUPPORT or
       * FULL_SUPPORT.
       */
      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_VERTEX_TEXTURE:
   case GL_TESS_CONTROL_TEXTURE:
   case GL_TESS_EVALUATION_TEXTURE:
   case GL_GEOMETRY_TEXTURE:
   case GL_FRAGMENT_TEXTURE:
   case GL_COMPUTE_TEXTURE:
      if (target == GL_RENDERBUFFER)
         goto end;

      if ((pname == GL_TESS_CONTROL_TEXTURE ||
           pname == GL_TESS_EVALUATION_TEXTURE) &&
          !_mesa_has_tessellation(ctx))
         goto end;

      if (pname == GL_GEOMETRY_TEXTURE && !_mesa_has_geometry_shaders(ctx))
         goto end;

      if (pname == GL_COMPUTE_TEXTURE && !_mesa_has_compute_shaders(ctx))
         goto end;

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_TEXTURE_GATHER:
   case GL_TEXTURE_GATHER_SHADOW:
      if (!_mesa_has_ARB_texture_gather(ctx))
         goto end;

      /* fallthrough */
   case GL_TEXTURE_SHADOW:
      /* Only depth or depth-stencil image formats make sense in shadow
         samplers */
      if (pname != GL_TEXTURE_GATHER &&
          !_mesa_is_depth_format(internalformat) &&
          !_mesa_is_depthstencil_format(internalformat))
         goto end;

      /* Validate the target for shadow and gather operations */
      switch (target) {
      case GL_TEXTURE_2D:
      case GL_TEXTURE_2D_ARRAY:
      case GL_TEXTURE_CUBE_MAP:
      case GL_TEXTURE_CUBE_MAP_ARRAY:
      case GL_TEXTURE_RECTANGLE:
         break;

      case GL_TEXTURE_1D:
      case GL_TEXTURE_1D_ARRAY:
         /* 1D and 1DArray textures are not admitted in gather operations */
         if (pname != GL_TEXTURE_SHADOW)
            goto end;
         break;

      default:
         goto end;
      }

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_SHADER_IMAGE_LOAD:
   case GL_SHADER_IMAGE_STORE:
      if (!_mesa_has_ARB_shader_image_load_store(ctx))
         goto end;

      /* We call to _mesa_is_shader_image_format_supported
       * using "internalformat" as parameter, because the
       * the ARB_internalformat_query2 spec says:
       * "In this case the <internalformat> is the value of the <format>
       * parameter that is passed to BindImageTexture."
       */
      if (target == GL_RENDERBUFFER ||
          !_mesa_is_shader_image_format_supported(ctx, internalformat))
         goto end;

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_SHADER_IMAGE_ATOMIC:
      if (!_mesa_has_ARB_shader_image_load_store(ctx))
         goto end;

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_IMAGE_TEXEL_SIZE: {
      mesa_format image_format;

      if (!_mesa_has_ARB_shader_image_load_store(ctx) ||
          target == GL_RENDERBUFFER)
         goto end;

      image_format = _mesa_get_shader_image_format(internalformat);
      if (image_format == MESA_FORMAT_NONE)
         goto end;

      /* We return bits */
      buffer[0] = (_mesa_get_format_bytes(image_format) * 8);
      break;
   }

   case GL_IMAGE_COMPATIBILITY_CLASS:
      if (!_mesa_has_ARB_shader_image_load_store(ctx) ||
          target == GL_RENDERBUFFER)
         goto end;

      buffer[0] = _mesa_get_image_format_class(internalformat);
      break;

   case GL_IMAGE_PIXEL_FORMAT: {
      GLint base_format;

      if (!_mesa_has_ARB_shader_image_load_store(ctx) ||
          target == GL_RENDERBUFFER ||
          !_mesa_is_shader_image_format_supported(ctx, internalformat))
         goto end;

      base_format = _mesa_base_tex_format(ctx, internalformat);
      if (base_format == -1)
         goto end;

      if (_mesa_is_enum_format_integer(internalformat))
         buffer[0] = _mesa_base_format_to_integer_format(base_format);
      else
         buffer[0] = base_format;
      break;
   }

   case GL_IMAGE_PIXEL_TYPE: {
      mesa_format image_format;
      GLenum datatype;
      GLuint comps;

      if (!_mesa_has_ARB_shader_image_load_store(ctx) ||
          target == GL_RENDERBUFFER)
         goto end;

      image_format = _mesa_get_shader_image_format(internalformat);
      if (image_format == MESA_FORMAT_NONE)
         goto end;

      _mesa_uncompressed_format_to_type_and_comps(image_format, &datatype,
                                                  &comps);
      if (!datatype)
         goto end;

      buffer[0] = datatype;
      break;
   }

   case GL_IMAGE_FORMAT_COMPATIBILITY_TYPE: {
      if (!_mesa_has_ARB_shader_image_load_store(ctx))
         goto end;

      if (!_mesa_legal_get_tex_level_parameter_target(ctx, target, true))
         goto end;

      /* From spec: "Equivalent to calling GetTexParameter with <value> set
       * to IMAGE_FORMAT_COMPATIBILITY_TYPE."
       *
       * GetTexParameter just returns
       * tex_obj->ImageFormatCompatibilityType. We create a fake tex_obj
       * just with the purpose of getting the value.
       */
      struct gl_texture_object *tex_obj = _mesa_new_texture_object(ctx, 0, target);
      buffer[0] = tex_obj->ImageFormatCompatibilityType;
      _mesa_delete_texture_object(ctx, tex_obj);

      break;
   }

   case GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST:
   case GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST:
   case GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE:
   case GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE:
      if (target == GL_RENDERBUFFER)
         goto end;

      if (!_mesa_is_depthstencil_format(internalformat)) {
         if (((pname == GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST ||
               pname == GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE) &&
              !_mesa_is_depth_format(internalformat)) ||
             ((pname == GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST ||
               pname == GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE) &&
              !_mesa_is_stencil_format(internalformat)))
            goto end;
      }

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_TEXTURE_COMPRESSED:
      buffer[0] = _mesa_is_compressed_format(ctx, internalformat);
      break;

   case GL_TEXTURE_COMPRESSED_BLOCK_WIDTH:
   case GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT:
   case GL_TEXTURE_COMPRESSED_BLOCK_SIZE: {
      mesa_format mesaformat;
      GLint block_size;

      mesaformat = _mesa_glenum_to_compressed_format(internalformat);
      if (mesaformat == MESA_FORMAT_NONE)
         goto end;

      block_size = _mesa_get_format_bytes(mesaformat);
      assert(block_size > 0);

      if (pname == GL_TEXTURE_COMPRESSED_BLOCK_SIZE) {
         buffer[0] = block_size;
      } else {
         GLuint bwidth, bheight;

         /* Returns the width and height in pixels. We return bytes */
         _mesa_get_format_block_size(mesaformat, &bwidth, &bheight);
         assert(bwidth > 0 && bheight > 0);

         if (pname == GL_TEXTURE_COMPRESSED_BLOCK_WIDTH)
            buffer[0] = block_size / bheight;
         else
            buffer[0] = block_size / bwidth;
      }
      break;
   }

   case GL_CLEAR_BUFFER:
      if (target != GL_TEXTURE_BUFFER)
         goto end;

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_TEXTURE_VIEW:
   case GL_VIEW_COMPATIBILITY_CLASS:
      if (!_mesa_has_ARB_texture_view(ctx) ||
          target == GL_TEXTURE_BUFFER ||
          target == GL_RENDERBUFFER)
         goto end;

      if (pname == GL_TEXTURE_VIEW) {
         ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                         buffer);
      } else {
         GLenum view_class = _mesa_texture_view_lookup_view_class(ctx,
                                                                  internalformat);
         if (view_class == GL_FALSE)
            goto end;

         buffer[0] = view_class;
      }
      break;

   default:
      unreachable("bad param");
   }

 end:
   if (bufSize != 0 && params == NULL) {
      /* Emit a warning to aid application debugging, but go ahead and do the
       * memcpy (and probably crash) anyway.
       */
      _mesa_warning(ctx,
                    "glGetInternalformativ(bufSize = %d, but params = NULL)",
                    bufSize);
   }

   /* Copy the data from the temporary buffer to the buffer supplied by the
    * application.  Clamp the size of the copy to the size supplied by the
    * application.
    */
   memcpy(params, buffer, MIN2(bufSize, 16) * sizeof(GLint));

   return;
}
Ejemplo n.º 6
0
static bool
_is_resource_supported(struct gl_context *ctx, GLenum target,
                       GLenum internalformat, GLenum pname)
{
   /* From the ARB_internalformat_query2 spec:
    *
    * In the following descriptions, the term /resource/ is used to generically
    * refer to an object of the appropriate type that has been created with
    * <internalformat> and <target>.  If the particular <target> and
    * <internalformat> combination do not make sense, ... the "unsupported"
    * answer should be given. This is not an error.
    */

   /* In the ARB_internalformat_query2 spec wording, some <pnames> do not care
    * about the /resource/ being supported or not, we return 'true' for those.
    */
   switch (pname) {
   case GL_INTERNALFORMAT_SUPPORTED:
   case GL_INTERNALFORMAT_PREFERRED:
   case GL_COLOR_COMPONENTS:
   case GL_DEPTH_COMPONENTS:
   case GL_STENCIL_COMPONENTS:
   case GL_COLOR_RENDERABLE:
   case GL_DEPTH_RENDERABLE:
   case GL_STENCIL_RENDERABLE:
      return true;
   default:
      break;
   }

   switch(target){
   case GL_TEXTURE_1D:
   case GL_TEXTURE_1D_ARRAY:
   case GL_TEXTURE_2D:
   case GL_TEXTURE_2D_ARRAY:
   case GL_TEXTURE_3D:
   case GL_TEXTURE_CUBE_MAP:
   case GL_TEXTURE_CUBE_MAP_ARRAY:
   case GL_TEXTURE_RECTANGLE:
      /* Based on what Mesa does for glTexImage1D/2D/3D and
       * glCompressedTexImage1D/2D/3D functions.
       */
      if (_mesa_base_tex_format(ctx, internalformat) < 0)
         return false;

      /* additional checks for depth textures */
      if (!_mesa_legal_texture_base_format_for_target(ctx, target, internalformat))
         return false;

      /* additional checks for compressed textures */
      if (_mesa_is_compressed_format(ctx, internalformat) &&
          (!_mesa_target_can_be_compressed(ctx, target, internalformat, NULL) ||
           _mesa_format_no_online_compression(ctx, internalformat)))
         return false;

      break;
   case GL_TEXTURE_2D_MULTISAMPLE:
   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
      /* Based on what Mesa does for glTexImage2D/3DMultisample,
       * glTexStorage2D/3DMultisample and
       * glTextureStorage2D/3DMultisample functions.
       */
      if (!_mesa_is_renderable_texture_format(ctx, internalformat))
         return false;

      break;
   case GL_TEXTURE_BUFFER:
      /* Based on what Mesa does for the glTexBuffer function. */
      if (_mesa_validate_texbuffer_format(ctx, internalformat) ==
          MESA_FORMAT_NONE)
         return false;

      break;
   case GL_RENDERBUFFER:
      /* Based on what Mesa does for glRenderbufferStorage(Multisample) and
       * glNamedRenderbufferStorage functions.
       */
      if (!_mesa_base_fbo_format(ctx, internalformat))
         return false;

      break;
   default:
      unreachable("bad target");
   }

   return true;
}
Ejemplo n.º 7
0
/**
 * Do error checking for calls to glTexStorage1/2/3D().
 * If an error is found, record it with _mesa_error(), unless the target
 * is a proxy texture.
 * \return GL_TRUE if any error, GL_FALSE otherwise.
 */
static GLboolean
tex_storage_error_check(struct gl_context *ctx, GLuint dims, GLenum target,
                        GLsizei levels, GLenum internalformat,
                        GLsizei width, GLsizei height, GLsizei depth)
{
   struct gl_texture_object *texObj;

   if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) {
      _mesa_error(ctx, GL_INVALID_ENUM,
                  "glTexStorage%uD(internalformat = %s)", dims,
                  _mesa_lookup_enum_by_nr(internalformat));
      return GL_TRUE;
   }

   /* size check */
   if (width < 1 || height < 1 || depth < 1) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glTexStorage%uD(width, height or depth < 1)", dims);
      return GL_TRUE;
   }  

   /* target check */
   if (!legal_texobj_target(ctx, dims, target)) {
      _mesa_error(ctx, GL_INVALID_ENUM,
                  "glTexStorage%uD(illegal target=%s)",
                  dims, _mesa_lookup_enum_by_nr(target));
      return GL_TRUE;
   }

   /* From section 3.8.6, page 146 of OpenGL ES 3.0 spec:
    *
    *    "The ETC2/EAC texture compression algorithm supports only
    *     two-dimensional images. If internalformat is an ETC2/EAC format,
    *     CompressedTexImage3D will generate an INVALID_OPERATION error if
    *     target is not TEXTURE_2D_ARRAY."
    *
    * This should also be applicable for glTexStorage3D().
    */
   if (_mesa_is_compressed_format(ctx, internalformat)
       && !_mesa_target_can_be_compressed(ctx, target, internalformat)) {
      _mesa_error(ctx, _mesa_is_desktop_gl(ctx)?
                  GL_INVALID_ENUM : GL_INVALID_OPERATION,
                  "glTexStorage3D(internalformat = %s)",
                  _mesa_lookup_enum_by_nr(internalformat));
   }

   /* levels check */
   if (levels < 1) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(levels < 1)",
                  dims);
      return GL_TRUE;
   }  

   /* check levels against maximum (note different error than above) */
   if (levels > (GLint) _mesa_max_texture_levels(ctx, target)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glTexStorage%uD(levels too large)", dims);
      return GL_TRUE;
   }

   /* check levels against width/height/depth */
   if (levels > _mesa_get_tex_max_num_levels(target, width, height, depth)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glTexStorage%uD(too many levels for max texture dimension)",
                  dims);
      return GL_TRUE;
   }

   /* non-default texture object check */
   texObj = _mesa_get_current_tex_object(ctx, target);
   if (!_mesa_is_proxy_texture(target) && (!texObj || (texObj->Name == 0))) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glTexStorage%uD(texture object 0)", dims);
      return GL_TRUE;
   }

   /* Check if texObj->Immutable is set */
   if (!_mesa_is_proxy_texture(target) && texObj->Immutable) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(immutable)",
                  dims);
      return GL_TRUE;
   }

   /* additional checks for depth textures */
   if (!_mesa_legal_texture_base_format_for_target(ctx, target, internalformat,
                                                   dims, "glTexStorage"))
      return GL_TRUE;

   return GL_FALSE;
}