Re: [Mesa-dev] [PATCH 1/2] gallium/u_blitter: implement mipmap generation

2016-06-14 Thread Nicolai Hähnle

Reviewed-by: Nicolai Hähnle 

On 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

2016-06-13 Thread Marek Olšák
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,
+dstbox->x + dstbox->width,
+dstbox->y +