+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;
+}
+
+static bool
+_is_internalformat_supported(struct gl_context *ctx, GLenum target,
+ GLenum internalformat)
+{
+ /* From the ARB_internalformat_query2 specification:
+ *
+ * "- INTERNALFORMAT_SUPPORTED: If <internalformat> is an internal format
+ * that is supported by the implementation in at least some subset of
+ * possible operations, TRUE is written to <params>. If <internalformat>
+ * if not a valid token for any internal format usage, FALSE is returned.
+ *
+ * <internalformats> that must be supported (in GL 4.2 or later) include
+ * the following:
+ * - "sized internal formats" from Table 3.12, 3.13, and 3.15,
+ * - any specific "compressed internal format" from Table 3.14,
+ * - any "image unit format" from Table 3.21.
+ * - any generic "compressed internal format" from Table 3.14, if the
+ * implementation accepts it for any texture specification commands, and
+ * - unsized or base internal format, if the implementation accepts
+ * it for texture or image specification.
+ */
+ GLint buffer[1];
+
+ /* At this point an internalformat is valid if it is valid as a texture or
+ * as a renderbuffer format. The checks are different because those methods
+ * return different values when passing non supported internalformats */
+ if (_mesa_base_tex_format(ctx, internalformat) < 0 &&
+ _mesa_base_fbo_format(ctx, internalformat) == 0)
+ return false;
+
+ /* Let the driver have the final word */
+ ctx->Driver.QueryInternalFormat(ctx, target, internalformat,
+ GL_INTERNALFORMAT_SUPPORTED, buffer);
+
+ return (buffer[0] == GL_TRUE);
+}
+
+static bool
+_legal_target_for_framebuffer_texture_layer(struct gl_context *ctx,
+ GLenum target)
+{
+ switch (target) {
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_1D_ARRAY:
+ case GL_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_CUBE_MAP_ARRAY:
+ case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+ case GL_TEXTURE_CUBE_MAP:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static GLenum
+_mesa_generic_type_for_internal_format(GLenum internalFormat)
+{
+ if (_mesa_is_enum_format_unsigned_int(internalFormat))
+ return GL_UNSIGNED_BYTE;
+ else if (_mesa_is_enum_format_signed_int(internalFormat))
+ return GL_BYTE;
+ else
+ return GL_FLOAT;
+}
+