/** * Helper used by _mesa_TextureStorage1/2/3D(). */ static void texturestorage(GLuint dims, GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, const char *caller) { struct gl_texture_object *texObj; GET_CURRENT_CONTEXT(ctx); if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) _mesa_debug(ctx, "%s %d %d %s %d %d %d\n", caller, texture, levels, _mesa_enum_to_string(internalformat), width, height, depth); /* Check the format to make sure it is sized. */ if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalformat = %s)", caller, _mesa_enum_to_string(internalformat)); return; } texObj = _mesa_lookup_texture_err(ctx, texture, caller); if (!texObj) return; /* Check target. This is done here so that texture_storage * can receive unsized formats. */ if (!legal_texobj_target(ctx, dims, texObj->Target)) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(illegal target=%s)", caller, _mesa_enum_to_string(texObj->Target)); return; } texture_storage(ctx, dims, texObj, texObj->Target, levels, internalformat, width, height, depth, true); }
/** * 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; }