1 /************************************************************************** 2 * 3 * Copyright 2008 VMware, Inc. 4 * All Rights Reserved. 5 * Copyright 2008 VMware, Inc. All rights reserved. 6 * Copyright 2014 Advanced Micro Devices, Inc. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the 10 * "Software"), to deal in the Software without restriction, including 11 * without limitation the rights to use, copy, modify, merge, publish, 12 * distribute, sub license, and/or sell copies of the Software, and to 13 * permit persons to whom the Software is furnished to do so, subject to 14 * the following conditions: 15 * 16 * The above copyright notice and this permission notice (including the 17 * next paragraph) shall be included in all copies or substantial portions 18 * of the Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 23 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 24 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 * 28 **************************************************************************/ 29 30 /** 31 * @file 32 * Mipmap generation utility 33 * 34 * @author Brian Paul, Marek Olk 35 */ 36 37 38 #include "util/u_gen_mipmap.h" 39 #include "util/u_format.h" 40 #include "util/u_inlines.h" 41 42 43 /** 44 * Generate mipmap images. It's assumed all needed texture memory is 45 * already allocated. 46 * 47 * \param pt the texture to generate mipmap levels for 48 * \param format format of texture 49 * \param first_layer the first layer to generate mipmap levels for 50 * (ignored for 3D textures) 51 * \param last_layer the last layer to generate mipmap levels for 52 * (ignored for 3D textures) 53 * \param base_level the first mipmap level to use as a src 54 * \param last_level the last mipmap level to generate 55 * \param filter the minification filter used to generate mipmap levels with 56 * one of PIPE_TEX_FILTER_LINEAR, PIPE_TEX_FILTER_NEAREST 57 */ 58 boolean 59 util_gen_mipmap(struct pipe_context *pipe, struct pipe_resource *pt, 60 enum pipe_format format, uint base_level, uint last_level, 61 uint first_layer, uint last_layer, uint filter) 62 { 63 struct pipe_screen *screen = pipe->screen; 64 struct pipe_blit_info blit; 65 uint dstLevel; 66 boolean is_zs = util_format_is_depth_or_stencil(format); 67 boolean has_depth = 68 util_format_has_depth(util_format_description(format)); 69 70 /* nothing to do for stencil-only formats */ 71 if (is_zs && !has_depth) 72 return TRUE; 73 74 /* nothing to do for integer formats */ 75 if (!is_zs && util_format_is_pure_integer(format)) 76 return TRUE; 77 78 if (!screen->is_format_supported(screen, format, pt->target, 79 pt->nr_samples, 80 PIPE_BIND_SAMPLER_VIEW | 81 (is_zs ? PIPE_BIND_DEPTH_STENCIL : 82 PIPE_BIND_RENDER_TARGET))) { 83 return FALSE; 84 } 85 86 /* The texture object should have room for the levels which we're 87 * about to generate. 88 */ 89 assert(last_level <= pt->last_level); 90 91 /* If this fails, why are we here? */ 92 assert(last_level > base_level); 93 assert(filter == PIPE_TEX_FILTER_LINEAR || 94 filter == PIPE_TEX_FILTER_NEAREST); 95 96 memset(&blit, 0, sizeof(blit)); 97 blit.src.resource = blit.dst.resource = pt; 98 blit.src.format = blit.dst.format = format; 99 /* don't set the stencil mask, stencil shouldn't be changed */ 100 blit.mask = is_zs ? PIPE_MASK_Z : PIPE_MASK_RGBA; 101 blit.filter = filter; 102 103 for (dstLevel = base_level + 1; dstLevel <= last_level; dstLevel++) { 104 blit.src.level = dstLevel - 1; 105 blit.dst.level = dstLevel; 106 107 blit.src.box.width = u_minify(pt->width0, blit.src.level); 108 blit.src.box.height = u_minify(pt->height0, blit.src.level); 109 110 blit.dst.box.width = u_minify(pt->width0, blit.dst.level); 111 blit.dst.box.height = u_minify(pt->height0, blit.dst.level); 112 113 if (pt->target == PIPE_TEXTURE_3D) { 114 /* generate all layers/slices at once */ 115 blit.src.box.z = blit.dst.box.z = 0; 116 blit.src.box.depth = util_num_layers(pt, blit.src.level); 117 blit.dst.box.depth = util_num_layers(pt, blit.dst.level); 118 } 119 else { 120 blit.src.box.z = blit.dst.box.z = first_layer; 121 blit.src.box.depth = blit.dst.box.depth = 122 (last_layer + 1 - first_layer); 123 } 124 125 pipe->blit(pipe, &blit); 126 } 127 return TRUE; 128 } 129