1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5848b8605Smrg * Copyright (C) 1999-2013 VMware, Inc. All Rights Reserved. 6848b8605Smrg * 7848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 8848b8605Smrg * copy of this software and associated documentation files (the "Software"), 9848b8605Smrg * to deal in the Software without restriction, including without limitation 10848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 12848b8605Smrg * Software is furnished to do so, subject to the following conditions: 13848b8605Smrg * 14848b8605Smrg * The above copyright notice and this permission notice shall be included 15848b8605Smrg * in all copies or substantial portions of the Software. 16848b8605Smrg * 17848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 24848b8605Smrg */ 25848b8605Smrg 26848b8605Smrg 27848b8605Smrg/* 28848b8605Smrg * glGenerateMipmap function 29848b8605Smrg */ 30848b8605Smrg 31848b8605Smrg#include "context.h" 32848b8605Smrg#include "enums.h" 33848b8605Smrg#include "genmipmap.h" 34848b8605Smrg#include "glformats.h" 35848b8605Smrg#include "macros.h" 36848b8605Smrg#include "mtypes.h" 37848b8605Smrg#include "teximage.h" 38848b8605Smrg#include "texobj.h" 39b8e80941Smrg#include "hash.h" 40848b8605Smrg 41b8e80941Smrgbool 42b8e80941Smrg_mesa_is_valid_generate_texture_mipmap_target(struct gl_context *ctx, 43b8e80941Smrg GLenum target) 44848b8605Smrg{ 45b8e80941Smrg bool error; 46848b8605Smrg 47848b8605Smrg switch (target) { 48848b8605Smrg case GL_TEXTURE_1D: 49848b8605Smrg error = _mesa_is_gles(ctx); 50848b8605Smrg break; 51848b8605Smrg case GL_TEXTURE_2D: 52b8e80941Smrg error = false; 53848b8605Smrg break; 54848b8605Smrg case GL_TEXTURE_3D: 55848b8605Smrg error = ctx->API == API_OPENGLES; 56848b8605Smrg break; 57848b8605Smrg case GL_TEXTURE_CUBE_MAP: 58848b8605Smrg error = !ctx->Extensions.ARB_texture_cube_map; 59848b8605Smrg break; 60848b8605Smrg case GL_TEXTURE_1D_ARRAY: 61848b8605Smrg error = _mesa_is_gles(ctx) || !ctx->Extensions.EXT_texture_array; 62848b8605Smrg break; 63848b8605Smrg case GL_TEXTURE_2D_ARRAY: 64848b8605Smrg error = (_mesa_is_gles(ctx) && ctx->Version < 30) 65848b8605Smrg || !ctx->Extensions.EXT_texture_array; 66848b8605Smrg break; 67848b8605Smrg case GL_TEXTURE_CUBE_MAP_ARRAY: 68b8e80941Smrg error = !_mesa_has_texture_cube_map_array(ctx); 69848b8605Smrg break; 70848b8605Smrg default: 71b8e80941Smrg error = true; 72848b8605Smrg } 73848b8605Smrg 74b8e80941Smrg return !error; 75b8e80941Smrg} 76b8e80941Smrg 77b8e80941Smrgbool 78b8e80941Smrg_mesa_is_valid_generate_texture_mipmap_internalformat(struct gl_context *ctx, 79b8e80941Smrg GLenum internalformat) 80b8e80941Smrg{ 81b8e80941Smrg if (_mesa_is_gles3(ctx)) { 82b8e80941Smrg /* From the ES 3.2 specification's description of GenerateMipmap(): 83b8e80941Smrg * "An INVALID_OPERATION error is generated if the levelbase array was 84b8e80941Smrg * not specified with an unsized internal format from table 8.3 or a 85b8e80941Smrg * sized internal format that is both color-renderable and 86b8e80941Smrg * texture-filterable according to table 8.10." 87b8e80941Smrg * 88b8e80941Smrg * GL_EXT_texture_format_BGRA8888 adds a GL_BGRA_EXT unsized internal 89b8e80941Smrg * format, and includes it in a very similar looking table. So we 90b8e80941Smrg * include it here as well. 91b8e80941Smrg */ 92b8e80941Smrg return internalformat == GL_RGBA || internalformat == GL_RGB || 93b8e80941Smrg internalformat == GL_LUMINANCE_ALPHA || 94b8e80941Smrg internalformat == GL_LUMINANCE || internalformat == GL_ALPHA || 95b8e80941Smrg internalformat == GL_BGRA_EXT || 96b8e80941Smrg (_mesa_is_es3_color_renderable(ctx, internalformat) && 97b8e80941Smrg _mesa_is_es3_texture_filterable(ctx, internalformat)); 98848b8605Smrg } 99848b8605Smrg 100b8e80941Smrg return (!_mesa_is_enum_format_integer(internalformat) && 101b8e80941Smrg !_mesa_is_depthstencil_format(internalformat) && 102b8e80941Smrg !_mesa_is_astc_format(internalformat) && 103b8e80941Smrg !_mesa_is_stencil_format(internalformat)); 104b8e80941Smrg} 105b8e80941Smrg 106b8e80941Smrg/** 107b8e80941Smrg * Implements glGenerateMipmap and glGenerateTextureMipmap. 108b8e80941Smrg * Generates all the mipmap levels below the base level. 109b8e80941Smrg */ 110b8e80941Smrgstatic ALWAYS_INLINE void 111b8e80941Smrggenerate_texture_mipmap(struct gl_context *ctx, 112b8e80941Smrg struct gl_texture_object *texObj, GLenum target, 113b8e80941Smrg bool dsa, bool no_error) 114b8e80941Smrg{ 115b8e80941Smrg struct gl_texture_image *srcImage; 116b8e80941Smrg const char *suffix = dsa ? "Texture" : ""; 117b8e80941Smrg 118b8e80941Smrg FLUSH_VERTICES(ctx, 0); 119848b8605Smrg 120848b8605Smrg if (texObj->BaseLevel >= texObj->MaxLevel) { 121848b8605Smrg /* nothing to do */ 122848b8605Smrg return; 123848b8605Smrg } 124848b8605Smrg 125b8e80941Smrg if (!no_error && texObj->Target == GL_TEXTURE_CUBE_MAP && 126848b8605Smrg !_mesa_cube_complete(texObj)) { 127848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 128b8e80941Smrg "glGenerate%sMipmap(incomplete cube map)", suffix); 129848b8605Smrg return; 130848b8605Smrg } 131848b8605Smrg 132848b8605Smrg _mesa_lock_texture(ctx, texObj); 133848b8605Smrg 134b8e80941Smrg srcImage = _mesa_select_tex_image(texObj, target, texObj->BaseLevel); 135b8e80941Smrg if (!no_error) { 136b8e80941Smrg if (!srcImage) { 137b8e80941Smrg _mesa_unlock_texture(ctx, texObj); 138b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 139b8e80941Smrg "glGenerate%sMipmap(zero size base image)", suffix); 140b8e80941Smrg return; 141b8e80941Smrg } 142b8e80941Smrg 143b8e80941Smrg if (!_mesa_is_valid_generate_texture_mipmap_internalformat(ctx, 144b8e80941Smrg srcImage->InternalFormat)) { 145b8e80941Smrg _mesa_unlock_texture(ctx, texObj); 146b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 147b8e80941Smrg "glGenerate%sMipmap(invalid internal format %s)", suffix, 148b8e80941Smrg _mesa_enum_to_string(srcImage->InternalFormat)); 149b8e80941Smrg return; 150b8e80941Smrg } 151848b8605Smrg } 152848b8605Smrg 153b8e80941Smrg if (srcImage->Width == 0 || srcImage->Height == 0) { 154848b8605Smrg _mesa_unlock_texture(ctx, texObj); 155848b8605Smrg return; 156848b8605Smrg } 157848b8605Smrg 158848b8605Smrg if (target == GL_TEXTURE_CUBE_MAP) { 159848b8605Smrg GLuint face; 160b8e80941Smrg for (face = 0; face < 6; face++) { 161b8e80941Smrg ctx->Driver.GenerateMipmap(ctx, 162b8e80941Smrg GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texObj); 163b8e80941Smrg } 164848b8605Smrg } 165848b8605Smrg else { 166848b8605Smrg ctx->Driver.GenerateMipmap(ctx, target, texObj); 167848b8605Smrg } 168848b8605Smrg _mesa_unlock_texture(ctx, texObj); 169848b8605Smrg} 170b8e80941Smrg 171b8e80941Smrgstatic void 172b8e80941Smrggenerate_texture_mipmap_error(struct gl_context *ctx, 173b8e80941Smrg struct gl_texture_object *texObj, GLenum target, 174b8e80941Smrg bool dsa) 175b8e80941Smrg{ 176b8e80941Smrg generate_texture_mipmap(ctx, texObj, target, dsa, false); 177b8e80941Smrg} 178b8e80941Smrg 179b8e80941Smrgstatic void 180b8e80941Smrggenerate_texture_mipmap_no_error(struct gl_context *ctx, 181b8e80941Smrg struct gl_texture_object *texObj, 182b8e80941Smrg GLenum target, bool dsa) 183b8e80941Smrg{ 184b8e80941Smrg generate_texture_mipmap(ctx, texObj, target, dsa, true); 185b8e80941Smrg} 186b8e80941Smrg 187b8e80941Smrg/** 188b8e80941Smrg * Generate all the mipmap levels below the base level. 189b8e80941Smrg * Note: this GL function would be more useful if one could specify a 190b8e80941Smrg * cube face, a set of array slices, etc. 191b8e80941Smrg */ 192b8e80941Smrgvoid GLAPIENTRY 193b8e80941Smrg_mesa_GenerateMipmap_no_error(GLenum target) 194b8e80941Smrg{ 195b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 196b8e80941Smrg 197b8e80941Smrg struct gl_texture_object *texObj = _mesa_get_current_tex_object(ctx, target); 198b8e80941Smrg generate_texture_mipmap_no_error(ctx, texObj, target, false); 199b8e80941Smrg} 200b8e80941Smrg 201b8e80941Smrgvoid GLAPIENTRY 202b8e80941Smrg_mesa_GenerateMipmap(GLenum target) 203b8e80941Smrg{ 204b8e80941Smrg struct gl_texture_object *texObj; 205b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 206b8e80941Smrg 207b8e80941Smrg if (!_mesa_is_valid_generate_texture_mipmap_target(ctx, target)) { 208b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmap(target=%s)", 209b8e80941Smrg _mesa_enum_to_string(target)); 210b8e80941Smrg return; 211b8e80941Smrg } 212b8e80941Smrg 213b8e80941Smrg texObj = _mesa_get_current_tex_object(ctx, target); 214b8e80941Smrg if (!texObj) 215b8e80941Smrg return; 216b8e80941Smrg 217b8e80941Smrg generate_texture_mipmap_error(ctx, texObj, target, false); 218b8e80941Smrg} 219b8e80941Smrg 220b8e80941Smrg/** 221b8e80941Smrg * Generate all the mipmap levels below the base level. 222b8e80941Smrg */ 223b8e80941Smrgvoid GLAPIENTRY 224b8e80941Smrg_mesa_GenerateTextureMipmap_no_error(GLuint texture) 225b8e80941Smrg{ 226b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 227b8e80941Smrg 228b8e80941Smrg struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, texture); 229b8e80941Smrg generate_texture_mipmap_no_error(ctx, texObj, texObj->Target, true); 230b8e80941Smrg} 231b8e80941Smrg 232b8e80941Smrgvoid GLAPIENTRY 233b8e80941Smrg_mesa_GenerateTextureMipmap(GLuint texture) 234b8e80941Smrg{ 235b8e80941Smrg struct gl_texture_object *texObj; 236b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 237b8e80941Smrg 238b8e80941Smrg texObj = _mesa_lookup_texture_err(ctx, texture, "glGenerateTextureMipmap"); 239b8e80941Smrg if (!texObj) 240b8e80941Smrg return; 241b8e80941Smrg 242b8e80941Smrg if (!_mesa_is_valid_generate_texture_mipmap_target(ctx, texObj->Target)) { 243b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateTextureMipmap(target=%s)", 244b8e80941Smrg _mesa_enum_to_string(texObj->Target)); 245b8e80941Smrg return; 246b8e80941Smrg } 247b8e80941Smrg 248b8e80941Smrg generate_texture_mipmap_error(ctx, texObj, texObj->Target, true); 249b8e80941Smrg} 250