Re: [Mesa-dev] [PATCH 1/2] gallium/u_blitter: implement mipmap generation
Reviewed-by: Nicolai HähnleOn 13.06.2016 19:30, Marek Olšák wrote: From: Marek Olšák for pipe_context::generate_mipmap first move some of the blit code from util_blitter_blit_generic to a separate function, then use it from util_blitter_generate_mipmap --- src/gallium/auxiliary/util/u_blitter.c | 346 ++--- src/gallium/auxiliary/util/u_blitter.h | 6 + 2 files changed, 238 insertions(+), 114 deletions(-) diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c index ad645ad..1257bb6 100644 --- a/src/gallium/auxiliary/util/u_blitter.c +++ b/src/gallium/auxiliary/util/u_blitter.c @@ -1501,6 +1501,135 @@ void util_blitter_copy_texture(struct blitter_context *blitter, pipe_sampler_view_reference(_view, NULL); } +static void do_blits(struct blitter_context_priv *ctx, + struct pipe_surface *dst, + const struct pipe_box *dstbox, + struct pipe_sampler_view *src, + unsigned src_width0, + unsigned src_height0, + const struct pipe_box *srcbox, + bool is_zsbuf) +{ + struct pipe_context *pipe = ctx->base.pipe; + unsigned src_samples = src->texture->nr_samples; + unsigned dst_samples = dst->texture->nr_samples; + enum pipe_texture_target src_target = src->texture->target; + struct pipe_framebuffer_state fb_state = {0}; + + /* Initialize framebuffer state. */ + fb_state.width = dst->width; + fb_state.height = dst->height; + fb_state.nr_cbufs = is_zsbuf ? 0 : 1; + + blitter_set_dst_dimensions(ctx, fb_state.width, fb_state.height); + + if ((src_target == PIPE_TEXTURE_1D || +src_target == PIPE_TEXTURE_2D || +src_target == PIPE_TEXTURE_RECT) && + src_samples <= 1) { + /* Draw the quad with the draw_rectangle callback. */ + + /* Set texture coordinates. - use a pipe color union + * for interface purposes. + * XXX pipe_color_union is a wrong name since we use that to set + * texture coordinates too. + */ + union pipe_color_union coord; + get_texcoords(src, src_width0, src_height0, srcbox->x, srcbox->y, +srcbox->x+srcbox->width, srcbox->y+srcbox->height, coord.f); + + /* Set framebuffer state. */ + if (is_zsbuf) { + fb_state.zsbuf = dst; + } else { + fb_state.cbufs[0] = dst; + } + pipe->set_framebuffer_state(pipe, _state); + + /* Draw. */ + pipe->set_sample_mask(pipe, ~0); + ctx->base.draw_rectangle(>base, dstbox->x, dstbox->y, + dstbox->x + dstbox->width, + dstbox->y + dstbox->height, 0, + UTIL_BLITTER_ATTRIB_TEXCOORD, ); + } else { + /* Draw the quad with the generic codepath. */ + 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 (is_zsbuf) { +fb_state.zsbuf = dst; + } else { +fb_state.cbufs[0] = dst; + } + pipe->set_framebuffer_state(pipe, _state); + + /* See if we need to blit a multisample or singlesample buffer. */ + if (src_samples == dst_samples && dst_samples > 1) { +/* MSAA copy. */ +unsigned i, max_sample = dst_samples - 1; + +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 + src_z, + i, srcbox->x, srcbox->y, + srcbox->x + srcbox->width, + srcbox->y + srcbox->height); + blitter_draw(ctx, dstbox->x, dstbox->y, +
[Mesa-dev] [PATCH 1/2] gallium/u_blitter: implement mipmap generation
From: Marek Olšákfor pipe_context::generate_mipmap first move some of the blit code from util_blitter_blit_generic to a separate function, then use it from util_blitter_generate_mipmap --- src/gallium/auxiliary/util/u_blitter.c | 346 ++--- src/gallium/auxiliary/util/u_blitter.h | 6 + 2 files changed, 238 insertions(+), 114 deletions(-) diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c index ad645ad..1257bb6 100644 --- a/src/gallium/auxiliary/util/u_blitter.c +++ b/src/gallium/auxiliary/util/u_blitter.c @@ -1501,6 +1501,135 @@ void util_blitter_copy_texture(struct blitter_context *blitter, pipe_sampler_view_reference(_view, NULL); } +static void do_blits(struct blitter_context_priv *ctx, + struct pipe_surface *dst, + const struct pipe_box *dstbox, + struct pipe_sampler_view *src, + unsigned src_width0, + unsigned src_height0, + const struct pipe_box *srcbox, + bool is_zsbuf) +{ + struct pipe_context *pipe = ctx->base.pipe; + unsigned src_samples = src->texture->nr_samples; + unsigned dst_samples = dst->texture->nr_samples; + enum pipe_texture_target src_target = src->texture->target; + struct pipe_framebuffer_state fb_state = {0}; + + /* Initialize framebuffer state. */ + fb_state.width = dst->width; + fb_state.height = dst->height; + fb_state.nr_cbufs = is_zsbuf ? 0 : 1; + + blitter_set_dst_dimensions(ctx, fb_state.width, fb_state.height); + + if ((src_target == PIPE_TEXTURE_1D || +src_target == PIPE_TEXTURE_2D || +src_target == PIPE_TEXTURE_RECT) && + src_samples <= 1) { + /* Draw the quad with the draw_rectangle callback. */ + + /* Set texture coordinates. - use a pipe color union + * for interface purposes. + * XXX pipe_color_union is a wrong name since we use that to set + * texture coordinates too. + */ + union pipe_color_union coord; + get_texcoords(src, src_width0, src_height0, srcbox->x, srcbox->y, +srcbox->x+srcbox->width, srcbox->y+srcbox->height, coord.f); + + /* Set framebuffer state. */ + if (is_zsbuf) { + fb_state.zsbuf = dst; + } else { + fb_state.cbufs[0] = dst; + } + pipe->set_framebuffer_state(pipe, _state); + + /* Draw. */ + pipe->set_sample_mask(pipe, ~0); + ctx->base.draw_rectangle(>base, dstbox->x, dstbox->y, + dstbox->x + dstbox->width, + dstbox->y + dstbox->height, 0, + UTIL_BLITTER_ATTRIB_TEXCOORD, ); + } else { + /* Draw the quad with the generic codepath. */ + 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 (is_zsbuf) { +fb_state.zsbuf = dst; + } else { +fb_state.cbufs[0] = dst; + } + pipe->set_framebuffer_state(pipe, _state); + + /* See if we need to blit a multisample or singlesample buffer. */ + if (src_samples == dst_samples && dst_samples > 1) { +/* MSAA copy. */ +unsigned i, max_sample = dst_samples - 1; + +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 + src_z, + i, srcbox->x, srcbox->y, + srcbox->x + srcbox->width, + srcbox->y + srcbox->height); + blitter_draw(ctx, dstbox->x, dstbox->y, +dstbox->x + dstbox->width, +dstbox->y +