[Mesa-dev] [PATCH 08/23] gallium/u_blitter: add gallium blit implementation

Marek Olšák maraeo at gmail.com
Fri Sep 14 10:09:35 PDT 2012


The original blit function is extended and the other functions reuse it.
---
 src/gallium/auxiliary/util/u_blitter.c       |  284 ++++++++++++++++++--------
 src/gallium/auxiliary/util/u_blitter.h       |   66 +++---
 src/gallium/drivers/i915/i915_surface.c      |    4 +-
 src/gallium/drivers/r300/r300_blit.c         |    8 +-
 src/gallium/drivers/r300/r300_context.h      |    3 +-
 src/gallium/drivers/r300/r300_render.c       |    3 +-
 src/gallium/drivers/r600/r600_blit.c         |   38 ++--
 src/gallium/drivers/r600/r600_pipe.h         |    2 +-
 src/gallium/drivers/r600/r600_state_common.c |    2 +-
 src/gallium/drivers/radeonsi/r600_blit.c     |    4 +-
 10 files changed, 258 insertions(+), 156 deletions(-)

diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index a47fba6..2d20d70 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -27,7 +27,7 @@
 /**
  * @file
  * Blitter utility to facilitate acceleration of the clear, clear_render_target,
- * clear_depth_stencil, and resource_copy_region functions.
+ * clear_depth_stencil, resource_copy_region, and blit functions.
  *
  * @author Marek Olšák
  */
@@ -88,8 +88,7 @@ struct blitter_context_priv
    void *fs_texfetch_stencil_msaa[PIPE_MAX_TEXTURE_TYPES];
 
    /* Blend state. */
-   void *blend_write_color;   /**< blend state with writemask of RGBA */
-   void *blend_keep_color;    /**< blend state with writemask of 0 */
+   void *blend[PIPE_MASK_RGBA+1]; /**< blend state with writemask */
 
    /* Depth stencil alpha state. */
    void *dsa_write_depth_stencil;
@@ -104,11 +103,10 @@ struct blitter_context_priv
    void *velem_state_readbuf;
 
    /* Sampler state. */
-   void *sampler_state;
+   void *sampler_state, *sampler_state_linear;
 
    /* Rasterizer state. */
-   void *rs_state;
-   void *rs_discard_state;
+   void *rs_state, *rs_state_scissor, *rs_discard_state;
 
    /* Viewport state. */
    struct pipe_viewport_state viewport;
@@ -182,10 +180,11 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
 
    /* blend state objects */
    memset(&blend, 0, sizeof(blend));
-   ctx->blend_keep_color = pipe->create_blend_state(pipe, &blend);
 
-   blend.rt[0].colormask = PIPE_MASK_RGBA;
-   ctx->blend_write_color = pipe->create_blend_state(pipe, &blend);
+   for (i = 0; i <= PIPE_MASK_RGBA; i++) {
+      blend.rt[0].colormask = i;
+      ctx->blend[i] = pipe->create_blend_state(pipe, &blend);
+   }
 
    /* depth stencil alpha state objects */
    memset(&dsa, 0, sizeof(dsa));
@@ -221,6 +220,10 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
    sampler_state.normalized_coords = 1;
    ctx->sampler_state = pipe->create_sampler_state(pipe, &sampler_state);
 
+   sampler_state.min_img_filter = PIPE_TEX_FILTER_LINEAR;
+   sampler_state.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
+   ctx->sampler_state_linear = pipe->create_sampler_state(pipe, &sampler_state);
+
    /* rasterizer state */
    memset(&rs_state, 0, sizeof(rs_state));
    rs_state.cull_face = PIPE_FACE_NONE;
@@ -229,7 +232,11 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
    rs_state.depth_clip = 1;
    ctx->rs_state = pipe->create_rasterizer_state(pipe, &rs_state);
 
+   rs_state.scissor = 1;
+   ctx->rs_state_scissor = pipe->create_rasterizer_state(pipe, &rs_state);
+
    if (ctx->has_stream_out) {
+      rs_state.scissor = 0;
       rs_state.rasterizer_discard = 1;
       ctx->rs_discard_state = pipe->create_rasterizer_state(pipe, &rs_state);
    }
@@ -304,8 +311,9 @@ void util_blitter_destroy(struct blitter_context *blitter)
    struct pipe_context *pipe = blitter->pipe;
    int i;
 
-   pipe->delete_blend_state(pipe, ctx->blend_write_color);
-   pipe->delete_blend_state(pipe, ctx->blend_keep_color);
+   for (i = 0; i <= PIPE_MASK_RGBA; i++) {
+      pipe->delete_blend_state(pipe, ctx->blend[i]);
+   }
    pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
    pipe->delete_depth_stencil_alpha_state(pipe,
                                           ctx->dsa_write_depth_keep_stencil);
@@ -313,6 +321,7 @@ void util_blitter_destroy(struct blitter_context *blitter)
    pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
 
    pipe->delete_rasterizer_state(pipe, ctx->rs_state);
+   pipe->delete_rasterizer_state(pipe, ctx->rs_state_scissor);
    if (ctx->rs_discard_state)
       pipe->delete_rasterizer_state(pipe, ctx->rs_discard_state);
    pipe->delete_vs_state(pipe, ctx->vs);
@@ -345,6 +354,7 @@ void util_blitter_destroy(struct blitter_context *blitter)
    }
 
    pipe->delete_sampler_state(pipe, ctx->sampler_state);
+   pipe->delete_sampler_state(pipe, ctx->sampler_state_linear);
    u_upload_destroy(ctx->upload);
    FREE(ctx);
 }
@@ -524,8 +534,7 @@ static void blitter_restore_textures(struct blitter_context_priv *ctx)
 }
 
 static void blitter_set_rectangle(struct blitter_context_priv *ctx,
-                                  unsigned x1, unsigned y1,
-                                  unsigned x2, unsigned y2,
+                                  int x1, int y1, int x2, int y2,
                                   float depth)
 {
    int i;
@@ -583,8 +592,7 @@ static void blitter_set_clear_color(struct blitter_context_priv *ctx,
 
 static void get_texcoords(struct pipe_sampler_view *src,
                           unsigned src_width0, unsigned src_height0,
-                          unsigned x1, unsigned y1,
-                          unsigned x2, unsigned y2,
+                          int x1, int y1, int x2, int y2,
                           float out[4])
 {
    struct pipe_resource *tex = src->texture;
@@ -625,8 +633,7 @@ 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,
-                                  unsigned x1, unsigned y1,
-                                  unsigned x2, unsigned y2)
+                                  int x1, int y1, int x2, int y2)
 {
    unsigned i;
    float coord[4];
@@ -895,11 +902,13 @@ void util_blitter_cache_all_shaders(struct blitter_context *blitter)
    }
 }
 
-static void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx)
+static void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx,
+                                               boolean scissor)
 {
    struct pipe_context *pipe = ctx->base.pipe;
 
-   pipe->bind_rasterizer_state(pipe, ctx->rs_state);
+   pipe->bind_rasterizer_state(pipe, scissor ? ctx->rs_state_scissor
+                                             : ctx->rs_state);
    pipe->bind_vs_state(pipe, ctx->vs);
    if (ctx->has_geometry_shader)
       pipe->bind_gs_state(pipe, NULL);
@@ -908,9 +917,7 @@ static void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx)
 }
 
 static void blitter_draw(struct blitter_context_priv *ctx,
-                         unsigned x1, unsigned y1,
-                         unsigned x2, unsigned y2,
-                         float depth)
+                         int x1, int y1, int x2, int y2, float depth)
 {
    struct pipe_resource *buf = NULL;
    unsigned offset = 0;
@@ -926,9 +933,7 @@ static void blitter_draw(struct blitter_context_priv *ctx,
 }
 
 void util_blitter_draw_rectangle(struct blitter_context *blitter,
-                                 unsigned x1, unsigned y1,
-                                 unsigned x2, unsigned y2,
-                                 float depth,
+                                 int x1, int y1, int x2, int y2, float depth,
                                  enum blitter_attrib_type type,
                                  const union pipe_color_union *attrib)
 {
@@ -973,9 +978,9 @@ static void util_blitter_clear_custom(struct blitter_context *blitter,
    if (custom_blend) {
       pipe->bind_blend_state(pipe, custom_blend);
    } else if (clear_buffers & PIPE_CLEAR_COLOR) {
-      pipe->bind_blend_state(pipe, ctx->blend_write_color);
+      pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA]);
    } else {
-      pipe->bind_blend_state(pipe, ctx->blend_keep_color);
+      pipe->bind_blend_state(pipe, ctx->blend[0]);
    }
 
    if (custom_dsa) {
@@ -1003,7 +1008,7 @@ static void util_blitter_clear_custom(struct blitter_context *blitter,
    ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, num_cbufs, int_format));
    pipe->set_sample_mask(pipe, ~0);
 
-   blitter_set_common_draw_rect_state(ctx);
+   blitter_set_common_draw_rect_state(ctx, FALSE);
    blitter_set_dst_dimensions(ctx, width, height);
    blitter->draw_rectangle(blitter, 0, 0, width, height, depth,
                            UTIL_BLITTER_ATTRIB_COLOR, color);
@@ -1037,7 +1042,7 @@ void util_blitter_custom_clear_depth(struct blitter_context *blitter,
 }
 
 static
-boolean is_overlap(unsigned dstx, unsigned dsty, unsigned dstz,
+boolean is_overlap(int dstx, int dsty, int dstz,
 		   const struct pipe_box *srcbox)
 {
    struct pipe_box src = *srcbox;
@@ -1096,10 +1101,12 @@ void util_blitter_default_src_texture(struct pipe_sampler_view *src_templ,
     src_templ->swizzle_a = PIPE_SWIZZLE_ALPHA;
 }
 
-boolean util_blitter_is_copy_supported(struct blitter_context *blitter,
-                                       const struct pipe_resource *dst,
-                                       const struct pipe_resource *src,
-                                       unsigned mask)
+static boolean is_blit_generic_supported(struct blitter_context *blitter,
+                                         const struct pipe_resource *dst,
+                                         enum pipe_format dst_format,
+                                         const struct pipe_resource *src,
+                                         enum pipe_format src_format,
+                                         unsigned mask)
 {
    struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
    struct pipe_screen *screen = ctx->base.pipe->screen;
@@ -1108,7 +1115,7 @@ boolean util_blitter_is_copy_supported(struct blitter_context *blitter,
       unsigned bind;
       boolean is_stencil;
       const struct util_format_description *desc =
-            util_format_description(dst->format);
+            util_format_description(dst_format);
 
       is_stencil = util_format_has_stencil(desc);
 
@@ -1122,7 +1129,7 @@ boolean util_blitter_is_copy_supported(struct blitter_context *blitter,
       else
          bind = PIPE_BIND_RENDER_TARGET;
 
-      if (!screen->is_format_supported(screen, dst->format, dst->target,
+      if (!screen->is_format_supported(screen, dst_format, dst->target,
                                        dst->nr_samples, bind)) {
          return FALSE;
       }
@@ -1133,18 +1140,18 @@ boolean util_blitter_is_copy_supported(struct blitter_context *blitter,
          return FALSE;
       }
 
-      if (!screen->is_format_supported(screen, src->format, src->target,
+      if (!screen->is_format_supported(screen, src_format, src->target,
                                  src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) {
          return FALSE;
       }
 
       /* Check stencil sampler support for stencil copy. */
-      if (util_format_has_stencil(util_format_description(src->format))) {
+      if (util_format_has_stencil(util_format_description(src_format))) {
          enum pipe_format stencil_format =
-               util_format_stencil_only(src->format);
+               util_format_stencil_only(src_format);
          assert(stencil_format != PIPE_FORMAT_NONE);
 
-         if (stencil_format != src->format &&
+         if (stencil_format != src_format &&
              !screen->is_format_supported(screen, stencil_format, src->target,
                                  src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) {
             return FALSE;
@@ -1155,13 +1162,32 @@ boolean util_blitter_is_copy_supported(struct blitter_context *blitter,
    return TRUE;
 }
 
+boolean util_blitter_is_copy_supported(struct blitter_context *blitter,
+                                       const struct pipe_resource *dst,
+                                       const struct pipe_resource *src,
+                                       unsigned mask)
+{
+   return is_blit_generic_supported(blitter, dst, dst->format,
+                                    src, src->format, mask);
+}
+
+boolean util_blitter_is_blit_supported(struct blitter_context *blitter,
+				       const struct pipe_blit_info *info)
+{
+   return is_blit_generic_supported(blitter,
+                                    info->dst.resource, info->dst.format,
+                                    info->src.resource, info->src.format,
+                                    info->mask);
+}
+
 void util_blitter_copy_texture(struct blitter_context *blitter,
                                struct pipe_resource *dst,
-                               unsigned dst_level, unsigned dst_sample_mask,
+                               unsigned dst_level,
                                unsigned dstx, unsigned dsty, unsigned dstz,
                                struct pipe_resource *src,
-                               unsigned src_level, unsigned src_sample,
-                               const struct pipe_box *srcbox)
+                               unsigned src_level,
+                               const struct pipe_box *srcbox, unsigned mask,
+                               boolean copy_all_samples)
 {
    struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
    struct pipe_context *pipe = ctx->base.pipe;
@@ -1180,44 +1206,53 @@ void util_blitter_copy_texture(struct blitter_context *blitter,
    src_view = pipe->create_sampler_view(pipe, src, &src_templ);
 
    /* Copy. */
-   util_blitter_copy_texture_view(blitter, dst_view, dst_sample_mask, dstx,
-				  dsty, src_view, src_sample, srcbox,
-				  src->width0, src->height0, PIPE_MASK_RGBAZS);
+   util_blitter_blit_generic(blitter, dst_view, dstx, dsty,
+                             abs(srcbox->width), abs(srcbox->height),
+                             src_view, srcbox, src->width0, src->height0,
+                             mask, PIPE_TEX_FILTER_NEAREST, NULL,
+                             copy_all_samples);
 
    pipe_surface_reference(&dst_view, NULL);
    pipe_sampler_view_reference(&src_view, NULL);
 }
 
-void util_blitter_copy_texture_view(struct blitter_context *blitter,
-                                    struct pipe_surface *dst,
-                                    unsigned dst_sample_mask,
-                                    unsigned dstx, unsigned dsty,
-                                    struct pipe_sampler_view *src,
-                                    unsigned src_sample,
-                                    const struct pipe_box *srcbox,
-                                    unsigned src_width0, unsigned src_height0,
-                                    unsigned mask)
+void util_blitter_blit_generic(struct blitter_context *blitter,
+                               struct pipe_surface *dst,
+                               int dstx, int dsty,
+                               unsigned dst_width, unsigned dst_height,
+                               struct pipe_sampler_view *src,
+                               const struct pipe_box *srcbox,
+                               unsigned src_width0, unsigned src_height0,
+                               unsigned mask, unsigned filter,
+                               const struct pipe_scissor_state *scissor,
+                               boolean copy_all_samples)
 {
    struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
    struct pipe_context *pipe = ctx->base.pipe;
    struct pipe_framebuffer_state fb_state;
    enum pipe_texture_target src_target = src->texture->target;
-   int abs_width = abs(srcbox->width);
-   int abs_height = abs(srcbox->height);
-   boolean blit_stencil, blit_depth;
+   boolean has_depth, has_stencil, has_color;
+   boolean blit_stencil, blit_depth, blit_color;
+   void *sampler_state;
    const struct util_format_description *src_desc =
          util_format_description(src->format);
-
-   blit_depth = util_format_has_depth(src_desc) && (mask & PIPE_MASK_Z);
-   blit_stencil = util_format_has_stencil(src_desc) && (mask & PIPE_MASK_S);
-
-   /* If you want a fallback for stencil copies,
-    * use util_blitter_copy_texture. */
-   if (blit_stencil && !ctx->has_stencil_export) {
-      blit_stencil = FALSE;
-
-      if (!blit_depth)
-         return;
+   const struct util_format_description *dst_desc =
+         util_format_description(dst->format);
+
+   has_color = src_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS &&
+               dst_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS;
+   has_depth = util_format_has_depth(src_desc) &&
+               util_format_has_depth(dst_desc);
+   has_stencil = util_format_has_stencil(src_desc) &&
+                 util_format_has_stencil(dst_desc);
+
+   blit_color = has_color && (mask & PIPE_MASK_RGBA);
+   blit_depth = has_depth && (mask & PIPE_MASK_Z);
+   blit_stencil = has_stencil && (mask & PIPE_MASK_S) &&
+                  ctx->has_stencil_export;
+
+   if (!blit_stencil && !blit_depth && !blit_color) {
+      return;
    }
 
    /* Sanity checks. */
@@ -1241,7 +1276,7 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter,
    fb_state.height = dst->height;
 
    if (blit_depth || blit_stencil) {
-      pipe->bind_blend_state(pipe, ctx->blend_keep_color);
+      pipe->bind_blend_state(pipe, ctx->blend[0]);
 
       if (blit_depth && blit_stencil) {
          pipe->bind_depth_stencil_alpha_state(pipe,
@@ -1266,7 +1301,7 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter,
       fb_state.nr_cbufs = 0;
       fb_state.zsbuf = dst;
    } else {
-      pipe->bind_blend_state(pipe, ctx->blend_write_color);
+      pipe->bind_blend_state(pipe, ctx->blend[mask & PIPE_MASK_RGBA]);
       pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
       ctx->bind_fs_state(pipe,
             blitter_get_fs_texfetch_col(ctx, src->texture->target,
@@ -1277,11 +1312,22 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter,
       fb_state.zsbuf = 0;
    }
 
+   /* Set the linear filter only for scaled color non-MSAA blits. */
+   if (filter == PIPE_TEX_FILTER_LINEAR &&
+       !blit_depth && !blit_stencil &&
+       src->texture->nr_samples <= 1 &&
+       (dst_width != abs(srcbox->width) || dst_height != abs(srcbox->height))) {
+      sampler_state = ctx->sampler_state_linear;
+   } else {
+      sampler_state = ctx->sampler_state;
+   }
+
+   /* Set samplers. */
    if (blit_depth && blit_stencil) {
       /* Setup two samplers, one for depth and the other one for stencil. */
       struct pipe_sampler_view templ;
       struct pipe_sampler_view *views[2];
-      void *samplers[2] = {ctx->sampler_state, ctx->sampler_state};
+      void *samplers[2] = {sampler_state, sampler_state};
 
       templ = *src;
       templ.format = util_format_stencil_only(templ.format);
@@ -1306,19 +1352,22 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter,
       view = pipe->create_sampler_view(pipe, src->texture, &templ);
 
       pipe->set_fragment_sampler_views(pipe, 1, &view);
-      pipe->bind_fragment_sampler_states(pipe, 1, &ctx->sampler_state);
+      pipe->bind_fragment_sampler_states(pipe, 1, &sampler_state);
 
       pipe_sampler_view_reference(&view, NULL);
    } else {
       pipe->set_fragment_sampler_views(pipe, 1, &src);
-      pipe->bind_fragment_sampler_states(pipe, 1, &ctx->sampler_state);
+      pipe->bind_fragment_sampler_states(pipe, 1, &sampler_state);
    }
 
    pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
    pipe->set_framebuffer_state(pipe, &fb_state);
-   pipe->set_sample_mask(pipe, dst_sample_mask);
 
-   blitter_set_common_draw_rect_state(ctx);
+   if (scissor) {
+      pipe->set_scissor_state(pipe, scissor);
+   }
+
+   blitter_set_common_draw_rect_state(ctx, scissor != NULL);
    blitter_set_dst_dimensions(ctx, dst->width, dst->height);
 
    if ((src_target == PIPE_TEXTURE_1D ||
@@ -1337,25 +1386,82 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter,
                     srcbox->x+srcbox->width, srcbox->y+srcbox->height, coord.f);
 
       /* Draw. */
-      blitter->draw_rectangle(blitter, dstx, dsty, dstx+abs_width, dsty+abs_height, 0,
+      pipe->set_sample_mask(pipe, ~0);
+      blitter->draw_rectangle(blitter, dstx, dsty,
+                              dstx+dst_width, dsty+dst_height, 0,
                               UTIL_BLITTER_ATTRIB_TEXCOORD, &coord);
    } else {
       /* Draw the quad with the generic codepath. */
-      blitter_set_texcoords(ctx, src, src_width0, src_height0, srcbox->z,
-                            src_sample,
-                            srcbox->x, srcbox->y,
-                            srcbox->x + srcbox->width, srcbox->y + srcbox->height);
-      blitter_draw(ctx, dstx, dsty, dstx+abs_width, dsty+abs_height, 0);
+      if (copy_all_samples &&
+          src->texture->nr_samples == dst->texture->nr_samples &&
+          dst->texture->nr_samples > 1) {
+         /* MSAA copy. */
+         unsigned i, max_sample = MAX2(dst->texture->nr_samples, 1) - 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,
+                                  i, srcbox->x, srcbox->y,
+                                  srcbox->x + srcbox->width,
+                                  srcbox->y + srcbox->height);
+            blitter_draw(ctx, dstx, dsty,
+                         dstx+dst_width, dsty+dst_height, 0);
+         }
+      } else {
+         pipe->set_sample_mask(pipe, ~0);
+         blitter_set_texcoords(ctx, src, src_width0, src_height0, srcbox->z, 0,
+                               srcbox->x, srcbox->y,
+                               srcbox->x + srcbox->width,
+                               srcbox->y + srcbox->height);
+         blitter_draw(ctx, dstx, dsty, dstx+dst_width, dsty+dst_height, 0);
+      }
    }
 
    blitter_restore_vertex_states(ctx);
    blitter_restore_fragment_states(ctx);
    blitter_restore_textures(ctx);
    blitter_restore_fb_state(ctx);
+   if (scissor) {
+      pipe->set_scissor_state(pipe, &ctx->base.saved_scissor);
+   }
    blitter_restore_render_cond(ctx);
    blitter_unset_running_flag(ctx);
 }
 
+void
+util_blitter_blit(struct blitter_context *blitter,
+		  const struct pipe_blit_info *info)
+{
+   struct pipe_resource *dst = info->dst.resource;
+   struct pipe_resource *src = info->src.resource;
+   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
+   struct pipe_context *pipe = ctx->base.pipe;
+   struct pipe_surface *dst_view, dst_templ;
+   struct pipe_sampler_view src_templ, *src_view;
+
+   /* Initialize the surface. */
+   util_blitter_default_dst_texture(&dst_templ, dst, info->dst.level,
+                                    info->dst.box.z, &info->src.box);
+   dst_templ.format = info->dst.format;
+   dst_view = pipe->create_surface(pipe, dst, &dst_templ);
+
+   /* Initialize the sampler view. */
+   util_blitter_default_src_texture(&src_templ, src, info->src.level);
+   src_templ.format = info->src.format;
+   src_view = pipe->create_sampler_view(pipe, src, &src_templ);
+
+   /* Copy. */
+   util_blitter_blit_generic(blitter, dst_view,
+                             info->dst.box.x, info->dst.box.y,
+                             info->dst.box.width, info->dst.box.height,
+                             src_view, &info->src.box, src->width0, src->height0,
+                             info->mask, info->filter,
+                             info->scissor_enable ? &info->scissor : NULL, TRUE);
+
+   pipe_surface_reference(&dst_view, NULL);
+   pipe_sampler_view_reference(&src_view, NULL);
+}
+
 /* Clear a region of a color surface to a constant value. */
 void util_blitter_clear_render_target(struct blitter_context *blitter,
                                       struct pipe_surface *dstsurf,
@@ -1379,7 +1485,7 @@ void util_blitter_clear_render_target(struct blitter_context *blitter,
    blitter_disable_render_cond(ctx);
 
    /* bind states */
-   pipe->bind_blend_state(pipe, ctx->blend_write_color);
+   pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA]);
    pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
    ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE));
    pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
@@ -1393,7 +1499,7 @@ void util_blitter_clear_render_target(struct blitter_context *blitter,
    pipe->set_framebuffer_state(pipe, &fb_state);
    pipe->set_sample_mask(pipe, ~0);
 
-   blitter_set_common_draw_rect_state(ctx);
+   blitter_set_common_draw_rect_state(ctx, FALSE);
    blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
    blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0,
                            UTIL_BLITTER_ATTRIB_COLOR, color);
@@ -1431,7 +1537,7 @@ void util_blitter_clear_depth_stencil(struct blitter_context *blitter,
    blitter_disable_render_cond(ctx);
 
    /* bind states */
-   pipe->bind_blend_state(pipe, ctx->blend_keep_color);
+   pipe->bind_blend_state(pipe, ctx->blend[0]);
    if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {
       sr.ref_value[0] = stencil & 0xff;
       pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
@@ -1461,7 +1567,7 @@ void util_blitter_clear_depth_stencil(struct blitter_context *blitter,
    pipe->set_framebuffer_state(pipe, &fb_state);
    pipe->set_sample_mask(pipe, ~0);
 
-   blitter_set_common_draw_rect_state(ctx);
+   blitter_set_common_draw_rect_state(ctx, FALSE);
    blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
    blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, depth,
                            UTIL_BLITTER_ATTRIB_NONE, NULL);
@@ -1496,7 +1602,7 @@ void util_blitter_custom_depth_stencil(struct blitter_context *blitter,
    blitter_disable_render_cond(ctx);
 
    /* bind states */
-   pipe->bind_blend_state(pipe, ctx->blend_write_color);
+   pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA]);
    pipe->bind_depth_stencil_alpha_state(pipe, dsa_stage);
    ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE));
    pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
@@ -1516,7 +1622,7 @@ void util_blitter_custom_depth_stencil(struct blitter_context *blitter,
    pipe->set_framebuffer_state(pipe, &fb_state);
    pipe->set_sample_mask(pipe, sample_mask);
 
-   blitter_set_common_draw_rect_state(ctx);
+   blitter_set_common_draw_rect_state(ctx, FALSE);
    blitter_set_dst_dimensions(ctx, zsurf->width, zsurf->height);
    blitter->draw_rectangle(blitter, 0, 0, zsurf->width, zsurf->height, depth,
                            UTIL_BLITTER_ATTRIB_NONE, NULL);
@@ -1641,7 +1747,7 @@ void util_blitter_custom_resolve_color(struct blitter_context *blitter,
    fb_state.zsbuf = NULL;
    pipe->set_framebuffer_state(pipe, &fb_state);
 
-   blitter_set_common_draw_rect_state(ctx);
+   blitter_set_common_draw_rect_state(ctx, FALSE);
    blitter_set_dst_dimensions(ctx, src->width0, src->height0);
    blitter->draw_rectangle(blitter, 0, 0, src->width0, src->height0,
                            0, 0, NULL);
@@ -1690,7 +1796,7 @@ void util_blitter_custom_color(struct blitter_context *blitter,
    pipe->set_framebuffer_state(pipe, &fb_state);
    pipe->set_sample_mask(pipe, ~0);
 
-   blitter_set_common_draw_rect_state(ctx);
+   blitter_set_common_draw_rect_state(ctx, FALSE);
    blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
    blitter->draw_rectangle(blitter, 0, 0, dstsurf->width, dstsurf->height,
                            0, 0, NULL);
diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h
index 43b7326..026e88b 100644
--- a/src/gallium/auxiliary/util/u_blitter.h
+++ b/src/gallium/auxiliary/util/u_blitter.h
@@ -74,7 +74,7 @@ struct blitter_context
     *       a rectangular point sprite.
     */
    void (*draw_rectangle)(struct blitter_context *blitter,
-                          unsigned x1, unsigned y1, unsigned x2, unsigned y2,
+                          int x1, int y1, int x2, int y2,
                           float depth,
                           enum blitter_attrib_type type,
                           const union pipe_color_union *color);
@@ -94,6 +94,7 @@ struct blitter_context
    struct pipe_framebuffer_state saved_fb_state;  /**< framebuffer state */
    struct pipe_stencil_ref saved_stencil_ref;     /**< stencil ref */
    struct pipe_viewport_state saved_viewport;
+   struct pipe_scissor_state saved_scissor;
    boolean is_sample_mask_saved;
    unsigned saved_sample_mask;
 
@@ -137,9 +138,7 @@ struct pipe_context *util_blitter_get_pipe(struct blitter_context *blitter)
 /* The default function to draw a rectangle. This can only be used
  * inside of the draw_rectangle callback if the driver overrides it. */
 void util_blitter_draw_rectangle(struct blitter_context *blitter,
-                                 unsigned x1, unsigned y1,
-                                 unsigned x2, unsigned y2,
-                                 float depth,
+                                 int x1, int y1, int x2, int y2, float depth,
                                  enum blitter_attrib_type type,
                                  const union pipe_color_union *attrib);
 
@@ -180,19 +179,13 @@ boolean util_blitter_is_copy_supported(struct blitter_context *blitter,
                                        const struct pipe_resource *dst,
                                        const struct pipe_resource *src,
                                        unsigned mask);
+
+boolean util_blitter_is_blit_supported(struct blitter_context *blitter,
+				       const struct pipe_blit_info *info);
+
 /**
  * Copy a block of pixels from one surface to another.
  *
- * You can copy from any color format to any other color format provided
- * the former can be sampled from and the latter can be rendered to. Otherwise,
- * a software fallback path is taken and both surfaces must be of the same
- * format.
- *
- * Only one sample of a multisample texture can be copied and is specified by
- * src_sample. If the destination is a multisample resource, dst_sample_mask
- * specifies the sample mask. For single-sample resources, set dst_sample_mask
- * to ~0.
- *
  * These states must be saved in the blitter in addition to the state objects
  * already required to be saved:
  * - fragment shader
@@ -201,19 +194,21 @@ boolean util_blitter_is_copy_supported(struct blitter_context *blitter,
  * - fragment sampler states
  * - fragment sampler textures
  * - framebuffer state
+ * - sample mask
  */
 void util_blitter_copy_texture(struct blitter_context *blitter,
                                struct pipe_resource *dst,
-                               unsigned dst_level, unsigned dst_sample_mask,
+                               unsigned dst_level,
                                unsigned dstx, unsigned dsty, unsigned dstz,
                                struct pipe_resource *src,
-                               unsigned src_level, unsigned src_sample,
-                               const struct pipe_box *srcbox);
+                               unsigned src_level,
+                               const struct pipe_box *srcbox, unsigned mask,
+                               boolean copy_all_samples);
 
 /**
- * Same as util_blitter_copy_texture, but dst and src are pipe_surface and
- * pipe_sampler_view, respectively. The mipmap level and dstz are part of
- * the views.
+ * Same as util_blitter_copy_texture with the capabilities of util_blitter_blit,
+ * but dst and src are pipe_surface and pipe_sampler_view, respectively.
+ * The mipmap level and dstz are part of the views.
  *
  * Drivers can use this to change resource properties (like format, width,
  * height) by changing how the views interpret them, instead of changing
@@ -227,18 +222,20 @@ void util_blitter_copy_texture(struct blitter_context *blitter,
  *
  * The mask is a combination of the PIPE_MASK_* flags.
  * Set to PIPE_MASK_RGBAZS if unsure.
- *
- * NOTE: There are no checks whether the blit is actually supported.
  */
-void util_blitter_copy_texture_view(struct blitter_context *blitter,
-                                    struct pipe_surface *dst,
-                                    unsigned dst_sample_mask,
-                                    unsigned dstx, unsigned dsty,
-                                    struct pipe_sampler_view *src,
-                                    unsigned src_sample,
-                                    const struct pipe_box *srcbox,
-                                    unsigned src_width0, unsigned src_height0,
-                                    unsigned mask);
+void util_blitter_blit_generic(struct blitter_context *blitter,
+                               struct pipe_surface *dst,
+                               int dstx, int dsty,
+                               unsigned dst_width, unsigned dst_height,
+                               struct pipe_sampler_view *src,
+                               const struct pipe_box *srcbox,
+                               unsigned src_width0, unsigned src_height0,
+                               unsigned mask, unsigned filter,
+                               const struct pipe_scissor_state *scissor,
+                               boolean copy_all_samples);
+
+void util_blitter_blit(struct blitter_context *blitter,
+		       const struct pipe_blit_info *info);
 
 /**
  * Helper function to initialize a view for copy_texture_view.
@@ -416,6 +413,13 @@ void util_blitter_save_viewport(struct blitter_context *blitter,
 }
 
 static INLINE
+void util_blitter_save_scissor(struct blitter_context *blitter,
+                               struct pipe_scissor_state *state)
+{
+   blitter->saved_scissor = *state;
+}
+
+static INLINE
 void util_blitter_save_fragment_sampler_states(
                   struct blitter_context *blitter,
                   int num_sampler_states,
diff --git a/src/gallium/drivers/i915/i915_surface.c b/src/gallium/drivers/i915/i915_surface.c
index 5f0783f..99837fe 100644
--- a/src/gallium/drivers/i915/i915_surface.c
+++ b/src/gallium/drivers/i915/i915_surface.c
@@ -86,8 +86,8 @@ i915_surface_copy_render(struct pipe_context *pipe,
                                             i915->saved_nr_sampler_views,
                                             i915->saved_sampler_views);
 
-   util_blitter_copy_texture(i915->blitter, dst, dst_level, ~0, dstx, dsty, dstz,
-                            src, src_level, 0, src_box);
+   util_blitter_copy_texture(i915->blitter, dst, dst_level, dstx, dsty, dstz,
+                            src, src_level, src_box, PIPE_MASK_RGBAZS, TRUE);
 }
 
 static void
diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c
index f2c67c0..3e82176 100644
--- a/src/gallium/drivers/r300/r300_blit.c
+++ b/src/gallium/drivers/r300/r300_blit.c
@@ -577,9 +577,11 @@ static void r300_resource_copy_region(struct pipe_context *pipe,
     src_view = r300_create_sampler_view_custom(pipe, src, &src_templ, src_width0, src_height0);
 
     r300_blitter_begin(r300, R300_COPY);
-    util_blitter_copy_texture_view(r300->blitter, dst_view, ~0, dstx, dsty,
-                                   src_view, 0, src_box,
-                                   src_width0, src_height0, PIPE_MASK_RGBAZS);
+    util_blitter_blit_generic(r300->blitter, dst_view, dstx, dsty,
+                              abs(src_box->width), abs(src_box->height),
+                              src_view, src_box,
+                              src_width0, src_height0, PIPE_MASK_RGBAZS,
+                              PIPE_TEX_FILTER_NEAREST, NULL, FALSE);
     r300_blitter_end(r300);
 
     pipe_surface_reference(&dst_view, NULL);
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index 2c7b477..1197ab1 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -717,8 +717,7 @@ void r300_plug_in_stencil_ref_fallback(struct r300_context *r300);
 void r300_draw_flush_vbuf(struct r300_context *r300);
 void r500_emit_index_bias(struct r300_context *r300, int index_bias);
 void r300_blitter_draw_rectangle(struct blitter_context *blitter,
-                                 unsigned x1, unsigned y1,
-                                 unsigned x2, unsigned y2,
+                                 int x1, int y1, int x2, int y2,
                                  float depth,
                                  enum blitter_attrib_type type,
                                  const union pipe_color_union *attrib);
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index ceda126..e388260 100644
--- a/src/gallium/drivers/r300/r300_render.c
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -1172,8 +1172,7 @@ void r300_draw_flush_vbuf(struct r300_context *r300)
  * would be computed and stored twice, which makes the clear/copy codepaths
  * somewhat inefficient. Instead we use a rectangular point sprite. */
 void r300_blitter_draw_rectangle(struct blitter_context *blitter,
-                                 unsigned x1, unsigned y1,
-                                 unsigned x2, unsigned y2,
+                                 int x1, int y1, int x2, int y2,
                                  float depth,
                                  enum blitter_attrib_type type,
                                  const union pipe_color_union *attrib)
diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c
index 6cea0e9..1773405 100644
--- a/src/gallium/drivers/r600/r600_blit.c
+++ b/src/gallium/drivers/r600/r600_blit.c
@@ -379,10 +379,11 @@ static void r600_copy_first_sample(struct pipe_context *ctx,
 
 	/* Copy the first sample into dst. */
 	r600_blitter_begin(ctx, R600_COPY_TEXTURE);
-	util_blitter_copy_texture_view(rctx->blitter, dst_view, ~0, info->dst.x0,
-				       info->dst.y0, src_view, 0, &box,
-				       info->src.res->width0, info->src.res->height0,
-				       info->mask);
+	util_blitter_blit_generic(rctx->blitter, dst_view, info->dst.x0,
+                                  info->dst.y0, abs(box.width), abs(box.height),
+                                  src_view, &box,
+                                  info->src.res->width0, info->src.res->height0,
+                                  info->mask, PIPE_TEX_FILTER_NEAREST, NULL, FALSE);
 	r600_blitter_end(ctx);
 
 	pipe_surface_reference(&dst_view, NULL);
@@ -460,8 +461,8 @@ static void r600_color_resolve(struct pipe_context *ctx,
 
 	r600_blitter_begin(ctx, R600_COPY_TEXTURE);
 	util_blitter_copy_texture(rctx->blitter, info->dst.res, info->dst.level,
-				  ~0, info->dst.x0, info->dst.y0, info->dst.layer,
-				  tmp, 0, 0, &box);
+				  info->dst.x0, info->dst.y0, info->dst.layer,
+				  tmp, 0, &box, PIPE_MASK_RGBAZS, FALSE);
 	r600_blitter_end(ctx);
 
 	pipe_resource_reference(&tmp, NULL);
@@ -678,7 +679,6 @@ static void r600_resource_copy_region(struct pipe_context *ctx,
 	struct pipe_box sbox;
 	const struct pipe_box *psbox = src_box;
 	boolean restore_orig[2];
-	unsigned last_sample, i;
 
 	memset(orig_info, 0, sizeof(orig_info));
 
@@ -689,7 +689,6 @@ static void r600_resource_copy_region(struct pipe_context *ctx,
 	}
 
 	assert(u_max_sample(dst) == u_max_sample(src));
-	last_sample = u_max_sample(dst);
 
 	/* The driver doesn't decompress resources automatically while
 	 * u_blitter is rendering. */
@@ -756,21 +755,14 @@ static void r600_resource_copy_region(struct pipe_context *ctx,
 		restore_orig[1] = TRUE;
 	}
 
-	/* XXX Properly implement multisample textures on Cayman. In the meantime,
-	 * copy only the first sample (which is the only one that doesn't return garbage). */
-	if (rctx->chip_class == CAYMAN) {
-		r600_blitter_begin(ctx, R600_COPY_TEXTURE);
-		util_blitter_copy_texture(rctx->blitter, dst, dst_level, ~0, dstx, dsty, dstz,
-					  src, src_level, 0, psbox);
-		r600_blitter_end(ctx);
-	} else {
-		for (i = 0; i <= last_sample; i++) {
-			r600_blitter_begin(ctx, R600_COPY_TEXTURE);
-			util_blitter_copy_texture(rctx->blitter, dst, dst_level, 1 << i, dstx, dsty, dstz,
-						  src, src_level, i, psbox);
-			r600_blitter_end(ctx);
-		}
-	}
+	/* XXX Multisample texturing is unimplemented on Cayman. In the meantime,
+	 * copy only the first sample (which is the only one that is uncompressed
+	 * and therefore doesn't return garbage). */
+	r600_blitter_begin(ctx, R600_COPY_TEXTURE);
+	util_blitter_copy_texture(rctx->blitter, dst, dst_level, dstx, dsty, dstz,
+				  src, src_level, psbox, PIPE_MASK_RGBAZS,
+				  rctx->chip_class != CAYMAN);
+	r600_blitter_end(ctx);
 
 	if (restore_orig[0])
 		r600_reset_blittable_to_orig(src, src_level, &orig_info[0]);
diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
index ba793c7..a16327d 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -627,7 +627,7 @@ void r600_sampler_states_dirty(struct r600_context *rctx,
 void r600_set_max_scissor(struct r600_context *rctx);
 void r600_constant_buffers_dirty(struct r600_context *rctx, struct r600_constbuf_state *state);
 void r600_draw_rectangle(struct blitter_context *blitter,
-			 unsigned x1, unsigned y1, unsigned x2, unsigned y2, float depth,
+			 int x1, int y1, int x2, int y2, float depth,
 			 enum blitter_attrib_type type, const union pipe_color_union *attrib);
 uint32_t r600_translate_stencil_op(int s_op);
 uint32_t r600_translate_fill(uint32_t func);
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index 635804c..10c15fb 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -1341,7 +1341,7 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
 }
 
 void r600_draw_rectangle(struct blitter_context *blitter,
-			 unsigned x1, unsigned y1, unsigned x2, unsigned y2, float depth,
+			 int x1, int y1, int x2, int y2, float depth,
 			 enum blitter_attrib_type type, const union pipe_color_union *attrib)
 {
 	struct r600_context *rctx = (struct r600_context*)util_blitter_get_pipe(blitter);
diff --git a/src/gallium/drivers/radeonsi/r600_blit.c b/src/gallium/drivers/radeonsi/r600_blit.c
index 4406204..e599deb 100644
--- a/src/gallium/drivers/radeonsi/r600_blit.c
+++ b/src/gallium/drivers/radeonsi/r600_blit.c
@@ -249,8 +249,8 @@ static void r600_hw_copy_region(struct pipe_context *ctx,
 	struct r600_context *rctx = (struct r600_context *)ctx;
 
 	r600_blitter_begin(ctx, R600_COPY);
-	util_blitter_copy_texture(rctx->blitter, dst, dst_level, ~0, dstx, dsty, dstz,
-				  src, src_level, 0, src_box);
+	util_blitter_copy_texture(rctx->blitter, dst, dst_level, dstx, dsty, dstz,
+				  src, src_level, src_box, PIPE_MASK_RGBAZS, TRUE);
 	r600_blitter_end(ctx);
 }
 
-- 
1.7.9.5



More information about the mesa-dev mailing list