1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Mesa 3-D graphics library 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5bf215546Sopenharmony_ci * Copyright (C) 1999-2013 VMware, Inc. All Rights Reserved. 6bf215546Sopenharmony_ci * 7bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 8bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 9bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 10bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 12bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included 15bf215546Sopenharmony_ci * in all copies or substantial portions of the Software. 16bf215546Sopenharmony_ci * 17bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 24bf215546Sopenharmony_ci */ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci/* 28bf215546Sopenharmony_ci * glGenerateMipmap function 29bf215546Sopenharmony_ci */ 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ci#include "context.h" 32bf215546Sopenharmony_ci#include "enums.h" 33bf215546Sopenharmony_ci#include "genmipmap.h" 34bf215546Sopenharmony_ci#include "glformats.h" 35bf215546Sopenharmony_ci#include "macros.h" 36bf215546Sopenharmony_ci#include "mtypes.h" 37bf215546Sopenharmony_ci#include "teximage.h" 38bf215546Sopenharmony_ci#include "texobj.h" 39bf215546Sopenharmony_ci#include "hash.h" 40bf215546Sopenharmony_ci#include "api_exec_decl.h" 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci#include "state_tracker/st_gen_mipmap.h" 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_cibool 45bf215546Sopenharmony_ci_mesa_is_valid_generate_texture_mipmap_target(struct gl_context *ctx, 46bf215546Sopenharmony_ci GLenum target) 47bf215546Sopenharmony_ci{ 48bf215546Sopenharmony_ci bool error; 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci switch (target) { 51bf215546Sopenharmony_ci case GL_TEXTURE_1D: 52bf215546Sopenharmony_ci error = _mesa_is_gles(ctx); 53bf215546Sopenharmony_ci break; 54bf215546Sopenharmony_ci case GL_TEXTURE_2D: 55bf215546Sopenharmony_ci error = false; 56bf215546Sopenharmony_ci break; 57bf215546Sopenharmony_ci case GL_TEXTURE_3D: 58bf215546Sopenharmony_ci error = ctx->API == API_OPENGLES; 59bf215546Sopenharmony_ci break; 60bf215546Sopenharmony_ci case GL_TEXTURE_CUBE_MAP: 61bf215546Sopenharmony_ci error = false; 62bf215546Sopenharmony_ci break; 63bf215546Sopenharmony_ci case GL_TEXTURE_1D_ARRAY: 64bf215546Sopenharmony_ci error = _mesa_is_gles(ctx) || !ctx->Extensions.EXT_texture_array; 65bf215546Sopenharmony_ci break; 66bf215546Sopenharmony_ci case GL_TEXTURE_2D_ARRAY: 67bf215546Sopenharmony_ci error = (_mesa_is_gles(ctx) && ctx->Version < 30) 68bf215546Sopenharmony_ci || !ctx->Extensions.EXT_texture_array; 69bf215546Sopenharmony_ci break; 70bf215546Sopenharmony_ci case GL_TEXTURE_CUBE_MAP_ARRAY: 71bf215546Sopenharmony_ci error = !_mesa_has_texture_cube_map_array(ctx); 72bf215546Sopenharmony_ci break; 73bf215546Sopenharmony_ci default: 74bf215546Sopenharmony_ci error = true; 75bf215546Sopenharmony_ci } 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_ci return !error; 78bf215546Sopenharmony_ci} 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_cibool 81bf215546Sopenharmony_ci_mesa_is_valid_generate_texture_mipmap_internalformat(struct gl_context *ctx, 82bf215546Sopenharmony_ci GLenum internalformat) 83bf215546Sopenharmony_ci{ 84bf215546Sopenharmony_ci if (_mesa_is_gles3(ctx)) { 85bf215546Sopenharmony_ci /* From the ES 3.2 specification's description of GenerateMipmap(): 86bf215546Sopenharmony_ci * "An INVALID_OPERATION error is generated if the levelbase array was 87bf215546Sopenharmony_ci * not specified with an unsized internal format from table 8.3 or a 88bf215546Sopenharmony_ci * sized internal format that is both color-renderable and 89bf215546Sopenharmony_ci * texture-filterable according to table 8.10." 90bf215546Sopenharmony_ci * 91bf215546Sopenharmony_ci * GL_EXT_texture_format_BGRA8888 adds a GL_BGRA_EXT unsized internal 92bf215546Sopenharmony_ci * format, and includes it in a very similar looking table. So we 93bf215546Sopenharmony_ci * include it here as well. 94bf215546Sopenharmony_ci */ 95bf215546Sopenharmony_ci return internalformat == GL_RGBA || internalformat == GL_RGB || 96bf215546Sopenharmony_ci internalformat == GL_LUMINANCE_ALPHA || 97bf215546Sopenharmony_ci internalformat == GL_LUMINANCE || internalformat == GL_ALPHA || 98bf215546Sopenharmony_ci internalformat == GL_BGRA_EXT || 99bf215546Sopenharmony_ci (_mesa_is_es3_color_renderable(ctx, internalformat) && 100bf215546Sopenharmony_ci _mesa_is_es3_texture_filterable(ctx, internalformat)); 101bf215546Sopenharmony_ci } 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci return (!_mesa_is_enum_format_integer(internalformat) && 104bf215546Sopenharmony_ci !_mesa_is_depthstencil_format(internalformat) && 105bf215546Sopenharmony_ci !_mesa_is_astc_format(internalformat) && 106bf215546Sopenharmony_ci !_mesa_is_stencil_format(internalformat)); 107bf215546Sopenharmony_ci} 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci/** 110bf215546Sopenharmony_ci * Implements glGenerateMipmap and glGenerateTextureMipmap. 111bf215546Sopenharmony_ci * Generates all the mipmap levels below the base level. 112bf215546Sopenharmony_ci * Error-checking is done only if caller is not NULL. 113bf215546Sopenharmony_ci */ 114bf215546Sopenharmony_cistatic ALWAYS_INLINE void 115bf215546Sopenharmony_cigenerate_texture_mipmap(struct gl_context *ctx, 116bf215546Sopenharmony_ci struct gl_texture_object *texObj, GLenum target, 117bf215546Sopenharmony_ci const char* caller) 118bf215546Sopenharmony_ci{ 119bf215546Sopenharmony_ci struct gl_texture_image *srcImage; 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci FLUSH_VERTICES(ctx, 0, 0); 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci if (texObj->Attrib.BaseLevel >= texObj->Attrib.MaxLevel) { 124bf215546Sopenharmony_ci /* nothing to do */ 125bf215546Sopenharmony_ci return; 126bf215546Sopenharmony_ci } 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci if (caller && texObj->Target == GL_TEXTURE_CUBE_MAP && 129bf215546Sopenharmony_ci !_mesa_cube_complete(texObj)) { 130bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_OPERATION, 131bf215546Sopenharmony_ci "%s(incomplete cube map)", caller); 132bf215546Sopenharmony_ci return; 133bf215546Sopenharmony_ci } 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci _mesa_lock_texture(ctx, texObj); 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci texObj->External = GL_FALSE; 138bf215546Sopenharmony_ci 139bf215546Sopenharmony_ci srcImage = _mesa_select_tex_image(texObj, target, texObj->Attrib.BaseLevel); 140bf215546Sopenharmony_ci if (caller) { 141bf215546Sopenharmony_ci if (!srcImage) { 142bf215546Sopenharmony_ci _mesa_unlock_texture(ctx, texObj); 143bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_OPERATION, 144bf215546Sopenharmony_ci "%s(zero size base image)", caller); 145bf215546Sopenharmony_ci return; 146bf215546Sopenharmony_ci } 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci if (!_mesa_is_valid_generate_texture_mipmap_internalformat(ctx, 149bf215546Sopenharmony_ci srcImage->InternalFormat)) { 150bf215546Sopenharmony_ci _mesa_unlock_texture(ctx, texObj); 151bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_OPERATION, 152bf215546Sopenharmony_ci "%s(invalid internal format %s)", caller, 153bf215546Sopenharmony_ci _mesa_enum_to_string(srcImage->InternalFormat)); 154bf215546Sopenharmony_ci return; 155bf215546Sopenharmony_ci } 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci /* The GLES 2.0 spec says: 158bf215546Sopenharmony_ci * 159bf215546Sopenharmony_ci * "If the level zero array is stored in a compressed internal format, 160bf215546Sopenharmony_ci * the error INVALID_OPERATION is generated." 161bf215546Sopenharmony_ci * 162bf215546Sopenharmony_ci * and this text is gone from the GLES 3.0 spec. 163bf215546Sopenharmony_ci */ 164bf215546Sopenharmony_ci if (ctx->API == API_OPENGLES2 && ctx->Version < 30 && 165bf215546Sopenharmony_ci _mesa_is_format_compressed(srcImage->TexFormat)) { 166bf215546Sopenharmony_ci _mesa_unlock_texture(ctx, texObj); 167bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_OPERATION, "generate mipmaps on compressed texture"); 168bf215546Sopenharmony_ci return; 169bf215546Sopenharmony_ci } 170bf215546Sopenharmony_ci } 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci if (srcImage->Width == 0 || srcImage->Height == 0) { 173bf215546Sopenharmony_ci _mesa_unlock_texture(ctx, texObj); 174bf215546Sopenharmony_ci return; 175bf215546Sopenharmony_ci } 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci if (target == GL_TEXTURE_CUBE_MAP) { 178bf215546Sopenharmony_ci GLuint face; 179bf215546Sopenharmony_ci for (face = 0; face < 6; face++) { 180bf215546Sopenharmony_ci st_generate_mipmap(ctx, 181bf215546Sopenharmony_ci GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texObj); 182bf215546Sopenharmony_ci } 183bf215546Sopenharmony_ci } 184bf215546Sopenharmony_ci else { 185bf215546Sopenharmony_ci st_generate_mipmap(ctx, target, texObj); 186bf215546Sopenharmony_ci } 187bf215546Sopenharmony_ci _mesa_unlock_texture(ctx, texObj); 188bf215546Sopenharmony_ci} 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_ci/** 191bf215546Sopenharmony_ci * Generate all the mipmap levels below the base level. 192bf215546Sopenharmony_ci * Note: this GL function would be more useful if one could specify a 193bf215546Sopenharmony_ci * cube face, a set of array slices, etc. 194bf215546Sopenharmony_ci */ 195bf215546Sopenharmony_civoid GLAPIENTRY 196bf215546Sopenharmony_ci_mesa_GenerateMipmap_no_error(GLenum target) 197bf215546Sopenharmony_ci{ 198bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci struct gl_texture_object *texObj = _mesa_get_current_tex_object(ctx, target); 201bf215546Sopenharmony_ci generate_texture_mipmap(ctx, texObj, target, NULL); 202bf215546Sopenharmony_ci} 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_civoid GLAPIENTRY 205bf215546Sopenharmony_ci_mesa_GenerateMipmap(GLenum target) 206bf215546Sopenharmony_ci{ 207bf215546Sopenharmony_ci struct gl_texture_object *texObj; 208bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci if (!_mesa_is_valid_generate_texture_mipmap_target(ctx, target)) { 211bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmap(target=%s)", 212bf215546Sopenharmony_ci _mesa_enum_to_string(target)); 213bf215546Sopenharmony_ci return; 214bf215546Sopenharmony_ci } 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci texObj = _mesa_get_current_tex_object(ctx, target); 217bf215546Sopenharmony_ci if (!texObj) 218bf215546Sopenharmony_ci return; 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ci generate_texture_mipmap(ctx, texObj, target, "glGenerateMipmap"); 221bf215546Sopenharmony_ci} 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci/** 224bf215546Sopenharmony_ci * Generate all the mipmap levels below the base level. 225bf215546Sopenharmony_ci */ 226bf215546Sopenharmony_civoid GLAPIENTRY 227bf215546Sopenharmony_ci_mesa_GenerateTextureMipmap_no_error(GLuint texture) 228bf215546Sopenharmony_ci{ 229bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, texture); 232bf215546Sopenharmony_ci generate_texture_mipmap(ctx, texObj, texObj->Target, NULL); 233bf215546Sopenharmony_ci} 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_cistatic void 236bf215546Sopenharmony_civalidate_params_and_generate_mipmap(struct gl_texture_object *texObj, const char* caller) 237bf215546Sopenharmony_ci{ 238bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci if (!texObj) 241bf215546Sopenharmony_ci return; 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci if (!_mesa_is_valid_generate_texture_mipmap_target(ctx, texObj->Target)) { 244bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_ENUM, "%s(target=%s)", 245bf215546Sopenharmony_ci caller, 246bf215546Sopenharmony_ci _mesa_enum_to_string(texObj->Target)); 247bf215546Sopenharmony_ci return; 248bf215546Sopenharmony_ci } 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci generate_texture_mipmap(ctx, texObj, texObj->Target, caller); 251bf215546Sopenharmony_ci} 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_civoid GLAPIENTRY 254bf215546Sopenharmony_ci_mesa_GenerateTextureMipmap(GLuint texture) 255bf215546Sopenharmony_ci{ 256bf215546Sopenharmony_ci struct gl_texture_object *texObj; 257bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci texObj = _mesa_lookup_texture_err(ctx, texture, "glGenerateTextureMipmap"); 260bf215546Sopenharmony_ci validate_params_and_generate_mipmap(texObj, "glGenerateTextureMipmap"); 261bf215546Sopenharmony_ci} 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_civoid GLAPIENTRY 264bf215546Sopenharmony_ci_mesa_GenerateTextureMipmapEXT(GLuint texture, GLenum target) 265bf215546Sopenharmony_ci{ 266bf215546Sopenharmony_ci struct gl_texture_object *texObj; 267bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_ci texObj = _mesa_lookup_or_create_texture(ctx, target, texture, 270bf215546Sopenharmony_ci false, true, 271bf215546Sopenharmony_ci "glGenerateTextureMipmapEXT"); 272bf215546Sopenharmony_ci validate_params_and_generate_mipmap(texObj, 273bf215546Sopenharmony_ci "glGenerateTextureMipmapEXT"); 274bf215546Sopenharmony_ci} 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_civoid GLAPIENTRY 277bf215546Sopenharmony_ci_mesa_GenerateMultiTexMipmapEXT(GLenum texunit, GLenum target) 278bf215546Sopenharmony_ci{ 279bf215546Sopenharmony_ci struct gl_texture_object *texObj; 280bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_ci texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target, 283bf215546Sopenharmony_ci texunit - GL_TEXTURE0, 284bf215546Sopenharmony_ci true, 285bf215546Sopenharmony_ci "glGenerateMultiTexMipmapEXT"); 286bf215546Sopenharmony_ci validate_params_and_generate_mipmap(texObj, 287bf215546Sopenharmony_ci "glGenerateMultiTexMipmapEXT"); 288bf215546Sopenharmony_ci} 289