+ GLint buffer[1];
+
+ if (target == GL_RENDERBUFFER) {
+ if (_mesa_base_fbo_format(ctx, internalformat) == 0) {
+ return false;
+ }
+ } else if (target == GL_TEXTURE_BUFFER) {
+ if (_mesa_validate_texbuffer_format(ctx, internalformat) ==
+ MESA_FORMAT_NONE) {
+ return false;
+ }
+ } else {
+ if (_mesa_base_tex_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;
+}
+
+/* default implementation of QueryInternalFormat driverfunc, for
+ * drivers not implementing ARB_internalformat_query2.
+ */
+void
+_mesa_query_internal_format_default(struct gl_context *ctx, GLenum target,
+ GLenum internalFormat, GLenum pname,
+ GLint *params)
+{
+ (void) target;
+
+ switch (pname) {
+ case GL_SAMPLES:
+ case GL_NUM_SAMPLE_COUNTS:
+ params[0] = 1;
+ break;
+
+ case GL_INTERNALFORMAT_SUPPORTED:
+ params[0] = GL_TRUE;
+ break;
+
+ case GL_INTERNALFORMAT_PREFERRED:
+ params[0] = internalFormat;
+ break;
+
+ case GL_READ_PIXELS_FORMAT: {
+ GLenum base_format = _mesa_base_tex_format(ctx, internalFormat);
+ switch (base_format) {
+ case GL_STENCIL_INDEX:
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_STENCIL:
+ case GL_RED:
+ case GL_RGB:
+ case GL_BGR:
+ case GL_RGBA:
+ case GL_BGRA:
+ params[0] = base_format;
+ break;
+ default:
+ params[0] = GL_NONE;
+ break;
+ }
+ break;
+ }
+
+ case GL_READ_PIXELS_TYPE:
+ case GL_TEXTURE_IMAGE_TYPE:
+ case GL_GET_TEXTURE_IMAGE_TYPE: {
+ GLenum base_format = _mesa_base_tex_format(ctx, internalFormat);
+ if (base_format > 0)
+ params[0] = _mesa_generic_type_for_internal_format(internalFormat);
+ else
+ params[0] = GL_NONE;
+ break;
+ }
+
+ case GL_TEXTURE_IMAGE_FORMAT:
+ case GL_GET_TEXTURE_IMAGE_FORMAT: {
+ GLenum format = GL_NONE;
+ GLenum base_format = _mesa_base_tex_format(ctx, internalFormat);
+ if (base_format > 0) {
+ if (_mesa_is_enum_format_integer(internalFormat))
+ format = _mesa_base_format_to_integer_format(base_format);
+ else
+ format = base_format;
+ }
+
+ params[0] = format;
+ break;
+ }
+
+ case GL_MANUAL_GENERATE_MIPMAP:
+ case GL_AUTO_GENERATE_MIPMAP:
+ case GL_SRGB_READ:
+ case GL_SRGB_WRITE:
+ case GL_SRGB_DECODE_ARB:
+ 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:
+ case GL_SHADER_IMAGE_LOAD:
+ case GL_SHADER_IMAGE_STORE:
+ case GL_SHADER_IMAGE_ATOMIC:
+ 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:
+ case GL_CLEAR_BUFFER:
+ case GL_TEXTURE_VIEW:
+ case GL_TEXTURE_SHADOW:
+ case GL_TEXTURE_GATHER:
+ case GL_TEXTURE_GATHER_SHADOW:
+ case GL_FRAMEBUFFER_RENDERABLE:
+ case GL_FRAMEBUFFER_RENDERABLE_LAYERED:
+ case GL_FRAMEBUFFER_BLEND:
+ case GL_FILTER:
+ /*
+ * TODO seems a tad optimistic just saying yes to everything here.
+ * Even for combinations which make no sense...
+ * And things like TESS_CONTROL_TEXTURE should definitely default to
+ * NONE if the driver doesn't even support tessellation...
+ */
+ params[0] = GL_FULL_SUPPORT;
+ break;
+ case GL_NUM_TILING_TYPES_EXT:
+ params[0] = 2;
+ break;
+ case GL_TILING_TYPES_EXT:
+ params[0] = GL_OPTIMAL_TILING_EXT;
+ params[1] = GL_LINEAR_TILING_EXT;
+ break;
+
+ default:
+ _set_default_response(pname, params);
+ break;
+ }
+}
+
+/*
+ * For MAX_WIDTH/MAX_HEIGHT/MAX_DEPTH it returns the equivalent GetInteger
+ * pname for a Getinternalformat pname/target combination. target/pname
+ * combinations that would return 0 due dimension number or unsupported status
+ * should be already filtered out
+ *
+ * Note that this means that the returned value would be independent of the
+ * internalformat. This possibility is already mentioned at the Issue 7 of the
+ * arb_internalformat_query2 spec.
+ */
+static GLenum
+_equivalent_size_pname(GLenum target,
+ GLenum pname)
+{
+ switch (target) {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ return GL_MAX_TEXTURE_SIZE;
+ case GL_TEXTURE_3D:
+ return GL_MAX_3D_TEXTURE_SIZE;
+ case GL_TEXTURE_CUBE_MAP:
+ return GL_MAX_CUBE_MAP_TEXTURE_SIZE;
+ case GL_TEXTURE_RECTANGLE:
+ return GL_MAX_RECTANGLE_TEXTURE_SIZE;
+ case GL_RENDERBUFFER:
+ return GL_MAX_RENDERBUFFER_SIZE;
+ case GL_TEXTURE_1D_ARRAY:
+ if (pname == GL_MAX_HEIGHT)
+ return GL_MAX_ARRAY_TEXTURE_LAYERS;
+ else
+ return GL_MAX_TEXTURE_SIZE;
+ case GL_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+ if (pname == GL_MAX_DEPTH)
+ return GL_MAX_ARRAY_TEXTURE_LAYERS;
+ else
+ return GL_MAX_TEXTURE_SIZE;
+ case GL_TEXTURE_CUBE_MAP_ARRAY:
+ if (pname == GL_MAX_DEPTH)
+ return GL_MAX_ARRAY_TEXTURE_LAYERS;
+ else
+ return GL_MAX_CUBE_MAP_TEXTURE_SIZE;
+ case GL_TEXTURE_BUFFER:
+ return GL_MAX_TEXTURE_BUFFER_SIZE;
+ default:
+ return 0;
+ }
+}
+
+/*
+ * Returns the dimensions associated to a target. GL_TEXTURE_BUFFER and
+ * GL_RENDERBUFFER have associated a dimension, but they are not textures
+ * per-se, so we can't just call _mesa_get_texture_dimension directly.
+ */
+static GLint
+_get_target_dimensions(GLenum target)
+{
+ switch(target) {
+ case GL_TEXTURE_BUFFER:
+ return 1;
+ case GL_RENDERBUFFER:
+ return 2;
+ default:
+ return _mesa_get_texture_dimensions(target);
+ }
+}
+
+/*
+ * Returns the minimum amount of dimensions associated to a pname. So for
+ * example, if querying GL_MAX_HEIGHT, it is assumed that your target would
+ * have as minimum 2 dimensions.
+ *
+ * Useful to handle sentences like this from query2 spec:
+ *
+ * "MAX_HEIGHT:
+ * <skip>
+ * If the resource does not have at least two dimensions
+ * <skip>."
+ */
+static GLint
+_get_min_dimensions(GLenum pname)
+{
+ switch(pname) {
+ case GL_MAX_WIDTH:
+ return 1;
+ case GL_MAX_HEIGHT:
+ return 2;
+ case GL_MAX_DEPTH:
+ return 3;
+ default:
+ return 0;
+ }
+}
+
+/*
+ * Similar to teximage.c:check_multisample_target, but independent of the
+ * dimensions.
+ */
+static bool
+_is_multisample_target(GLenum target)
+{
+ switch(target) {
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+ return true;
+ default:
+ return false;
+ }
+
+}
+
+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");