1 /**************************************************************************
3 * Copyright 2008 VMware, Inc.
5 * Copyright 2008 VMware, Inc. All rights reserved.
6 * Copyright 2014 Advanced Micro Devices, Inc.
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:
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
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.
28 **************************************************************************/
32 * Mipmap generation utility
34 * @author Brian Paul, Marek Olšák
38 #include "util/u_gen_mipmap.h"
39 #include "util/u_format.h"
40 #include "util/u_inlines.h"
44 * Generate mipmap images. It's assumed all needed texture memory is
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
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
)
63 struct pipe_screen
*screen
= pipe
->screen
;
64 struct pipe_blit_info blit
;
66 boolean is_zs
= util_format_is_depth_or_stencil(format
);
68 util_format_has_depth(util_format_description(format
));
70 /* nothing to do for stencil-only formats */
71 if (is_zs
&& !has_depth
)
74 /* nothing to do for integer formats */
75 if (!is_zs
&& util_format_is_pure_integer(format
))
78 if (!screen
->is_format_supported(screen
, format
, pt
->target
,
79 pt
->nr_samples
, pt
->nr_storage_samples
,
80 PIPE_BIND_SAMPLER_VIEW
|
81 (is_zs
? PIPE_BIND_DEPTH_STENCIL
:
82 PIPE_BIND_RENDER_TARGET
))) {
86 /* The texture object should have room for the levels which we're
89 assert(last_level
<= pt
->last_level
);
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
);
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
;
103 for (dstLevel
= base_level
+ 1; dstLevel
<= last_level
; dstLevel
++) {
104 blit
.src
.level
= dstLevel
- 1;
105 blit
.dst
.level
= dstLevel
;
107 blit
.src
.box
.width
= u_minify(pt
->width0
, blit
.src
.level
);
108 blit
.src
.box
.height
= u_minify(pt
->height0
, blit
.src
.level
);
110 blit
.dst
.box
.width
= u_minify(pt
->width0
, blit
.dst
.level
);
111 blit
.dst
.box
.height
= u_minify(pt
->height0
, blit
.dst
.level
);
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
);
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
);
125 pipe
->blit(pipe
, &blit
);