aboutsummaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2014-03-16 03:44:09 +0100
committerMarek Olšák <[email protected]>2014-04-04 19:38:36 +0200
commit78f754b739e80a1a45b87cd22466e447da53b19e (patch)
tree12fe3e94f198982ce9a9a5f06226e0625c98b7c8 /src/gallium
parent8ab7bb4707ae5fb6e5e841f0f2e369c14b5ffbea (diff)
gallium/u_blitter: implement scaled blitting in the Z direction
So that pipe->blit can be used for 3D mipmap generation.
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/auxiliary/util/u_blitter.c40
1 files changed, 31 insertions, 9 deletions
diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index 64a3dcf3aed..7b058fe2239 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -688,7 +688,7 @@ static void set_texcoords_in_vertices(const float coord[4],
static void blitter_set_texcoords(struct blitter_context_priv *ctx,
struct pipe_sampler_view *src,
unsigned src_width0, unsigned src_height0,
- unsigned layer, unsigned sample,
+ float layer, unsigned sample,
int x1, int y1, int x2, int y2)
{
unsigned i;
@@ -700,7 +700,7 @@ static void blitter_set_texcoords(struct blitter_context_priv *ctx,
if (src->texture->target == PIPE_TEXTURE_CUBE ||
src->texture->target == PIPE_TEXTURE_CUBE_ARRAY) {
set_texcoords_in_vertices(coord, &face_coord[0][0], 2);
- util_map_texcoords2d_onto_cubemap(layer % 6,
+ util_map_texcoords2d_onto_cubemap((unsigned)layer % 6,
/* pointer, stride in floats */
&face_coord[0][0], 2,
&ctx->vertices[0][1][0], 8,
@@ -734,7 +734,7 @@ static void blitter_set_texcoords(struct blitter_context_priv *ctx,
case PIPE_TEXTURE_CUBE_ARRAY:
for (i = 0; i < 4; i++)
- ctx->vertices[i][1][3] = (float) (layer / 6); /*w*/
+ ctx->vertices[i][1][3] = (float) ((unsigned)layer / 6); /*w*/
break;
case PIPE_TEXTURE_2D:
@@ -1528,9 +1528,31 @@ void util_blitter_blit_generic(struct blitter_context *blitter,
UTIL_BLITTER_ATTRIB_TEXCOORD, &coord);
} else {
/* Draw the quad with the generic codepath. */
- int z;
- for (z = 0; z < dstbox->depth; z++) {
+ int dst_z;
+ for (dst_z = 0; dst_z < dstbox->depth; dst_z++) {
struct pipe_surface *old;
+ float dst2src_scale = srcbox->depth / (float)dstbox->depth;
+
+ /* Scale Z properly if the blit is scaled.
+ *
+ * When downscaling, we want the coordinates centered, so that
+ * mipmapping works for 3D textures. For example, when generating
+ * a 4x4x4 level, this wouldn't average the pixels:
+ *
+ * src Z: 0 1 2 3 4 5 6 7
+ * dst Z: 0 1 2 3
+ *
+ * Because the pixels are not centered below the pixels of the higher
+ * level. Therefore, we want this:
+ * src Z: 0 1 2 3 4 5 6 7
+ * dst Z: 0 1 2 3
+ *
+ * dst_offset defines the offset needed for centering the pixels and
+ * it works with any scaling (not just 2x).
+ */
+ float dst_offset = ((srcbox->depth - 1) -
+ (dstbox->depth - 1) * dst2src_scale) * 0.5;
+ float src_z = (dst_z + dst_offset) * dst2src_scale;
/* Set framebuffer state. */
if (blit_depth || blit_stencil) {
@@ -1548,7 +1570,7 @@ void util_blitter_blit_generic(struct blitter_context *blitter,
for (i = 0; i <= max_sample; i++) {
pipe->set_sample_mask(pipe, 1 << i);
blitter_set_texcoords(ctx, src, src_width0, src_height0,
- srcbox->z + z,
+ srcbox->z + src_z,
i, srcbox->x, srcbox->y,
srcbox->x + srcbox->width,
srcbox->y + srcbox->height);
@@ -1560,7 +1582,7 @@ void util_blitter_blit_generic(struct blitter_context *blitter,
/* Normal copy, MSAA upsampling, or MSAA resolve. */
pipe->set_sample_mask(pipe, ~0);
blitter_set_texcoords(ctx, src, src_width0, src_height0,
- srcbox->z + z, 0,
+ srcbox->z + src_z, 0,
srcbox->x, srcbox->y,
srcbox->x + srcbox->width,
srcbox->y + srcbox->height);
@@ -1572,10 +1594,10 @@ void util_blitter_blit_generic(struct blitter_context *blitter,
/* Get the next surface or (if this is the last iteration)
* just unreference the last one. */
old = dst;
- if (z < dstbox->depth-1) {
+ if (dst_z < dstbox->depth-1) {
dst = ctx->base.get_next_surface_layer(ctx->base.pipe, dst);
}
- if (z) {
+ if (dst_z) {
pipe_surface_reference(&old, NULL);
}
}