gallium: Fix uninitialized variable warning in compute test.
[mesa.git] / src / gallium / auxiliary / util / u_blit.c
index d4fbd658f40394af34fc650558feb3d95c66f908..15edf2f48dc1d6e0f717637028ff6ddf3290d1db 100644 (file)
@@ -1,6 +1,6 @@
 /**************************************************************************
  *
 /**************************************************************************
  *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2008 VMware, Inc.
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -18,7 +18,7 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -28,7 +28,7 @@
 /**
  * @file
  * Copy/blit pixel rect between surfaces
 /**
  * @file
  * Copy/blit pixel rect between surfaces
- *  
+ *
  * @author Brian Paul
  */
 
  * @author Brian Paul
  */
 
@@ -46,8 +46,8 @@
 #include "util/u_math.h"
 #include "util/u_memory.h"
 #include "util/u_sampler.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
 #include "util/u_sampler.h"
+#include "util/u_texture.h"
 #include "util/u_simple_shaders.h"
 #include "util/u_simple_shaders.h"
-#include "util/u_surface.h"
 
 #include "cso_cache/cso_context.h"
 
 
 #include "cso_cache/cso_context.h"
 
@@ -57,16 +57,15 @@ struct blit_state
    struct pipe_context *pipe;
    struct cso_context *cso;
 
    struct pipe_context *pipe;
    struct cso_context *cso;
 
-   struct pipe_blend_state blend;
-   struct pipe_depth_stencil_alpha_state depthstencil;
+   struct pipe_blend_state blend_write_color;
+   struct pipe_depth_stencil_alpha_state dsa_keep_depthstencil;
    struct pipe_rasterizer_state rasterizer;
    struct pipe_sampler_state sampler;
    struct pipe_viewport_state viewport;
    struct pipe_rasterizer_state rasterizer;
    struct pipe_sampler_state sampler;
    struct pipe_viewport_state viewport;
-   struct pipe_clip_state clip;
    struct pipe_vertex_element velem[2];
 
    void *vs;
    struct pipe_vertex_element velem[2];
 
    void *vs;
-   void *fs[TGSI_WRITEMASK_XYZW + 1];
+   void *fs[PIPE_MAX_TEXTURE_TYPES][4];
 
    struct pipe_resource *vbuf;  /**< quad vertices */
    unsigned vbuf_slot;
 
    struct pipe_resource *vbuf;  /**< quad vertices */
    unsigned vbuf_slot;
@@ -93,29 +92,24 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
    ctx->cso = cso;
 
    /* disabled blending/masking */
    ctx->cso = cso;
 
    /* disabled blending/masking */
-   memset(&ctx->blend, 0, sizeof(ctx->blend));
-   ctx->blend.rt[0].colormask = PIPE_MASK_RGBA;
-
-   /* no-op depth/stencil/alpha */
-   memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil));
+   ctx->blend_write_color.rt[0].colormask = PIPE_MASK_RGBA;
 
    /* rasterizer */
 
    /* rasterizer */
-   memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
    ctx->rasterizer.cull_face = PIPE_FACE_NONE;
    ctx->rasterizer.cull_face = PIPE_FACE_NONE;
-   ctx->rasterizer.gl_rasterization_rules = 1;
+   ctx->rasterizer.half_pixel_center = 1;
+   ctx->rasterizer.bottom_edge_rule = 1;
+   ctx->rasterizer.depth_clip_near = 1;
+   ctx->rasterizer.depth_clip_far = 1;
 
    /* samplers */
 
    /* samplers */
-   memset(&ctx->sampler, 0, sizeof(ctx->sampler));
    ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
    ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
    ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
    ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
    ctx->sampler.min_img_filter = 0; /* set later */
    ctx->sampler.mag_img_filter = 0; /* set later */
    ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
    ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
    ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
    ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
    ctx->sampler.min_img_filter = 0; /* set later */
    ctx->sampler.mag_img_filter = 0; /* set later */
-   ctx->sampler.normalized_coords = 1;
 
    /* vertex elements state */
 
    /* vertex elements state */
-   memset(&ctx->velem[0], 0, sizeof(ctx->velem[0]) * 2);
    for (i = 0; i < 2; i++) {
       ctx->velem[i].src_offset = i * 4 * sizeof(float);
       ctx->velem[i].instance_divisor = 0;
    for (i = 0; i < 2; i++) {
       ctx->velem[i].src_offset = i * 4 * sizeof(float);
       ctx->velem[i].instance_divisor = 0;
@@ -123,26 +117,11 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
       ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
    }
 
       ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
    }
 
-   /* vertex shader - still required to provide the linkage between
-    * fragment shader input semantics and vertex_element/buffers.
-    */
-   {
-      const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
-                                      TGSI_SEMANTIC_GENERIC };
-      const uint semantic_indexes[] = { 0, 0 };
-      ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
-                                                    semantic_indexes);
-   }
-
-   /* fragment shader */
-   ctx->fs[TGSI_WRITEMASK_XYZW] =
-      util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_2D);
    ctx->vbuf = NULL;
 
    /* init vertex data that doesn't change */
    for (i = 0; i < 4; i++) {
       ctx->vertices[i][0][3] = 1.0f; /* w */
    ctx->vbuf = NULL;
 
    /* init vertex data that doesn't change */
    for (i = 0; i < 4; i++) {
       ctx->vertices[i][0][3] = 1.0f; /* w */
-      ctx->vertices[i][1][2] = 0.0f; /* r */
       ctx->vertices[i][1][3] = 1.0f; /* q */
    }
 
       ctx->vertices[i][1][3] = 1.0f; /* q */
    }
 
@@ -157,13 +136,17 @@ void
 util_destroy_blit(struct blit_state *ctx)
 {
    struct pipe_context *pipe = ctx->pipe;
 util_destroy_blit(struct blit_state *ctx)
 {
    struct pipe_context *pipe = ctx->pipe;
-   unsigned i;
+   unsigned i, j;
 
 
-   pipe->delete_vs_state(pipe, ctx->vs);
+   if (ctx->vs)
+      pipe->delete_vs_state(pipe, ctx->vs);
 
 
-   for (i = 0; i < Elements(ctx->fs); i++)
-      if (ctx->fs[i])
-         pipe->delete_fs_state(pipe, ctx->fs[i]);
+   for (i = 0; i < ARRAY_SIZE(ctx->fs); i++) {
+      for (j = 0; j < ARRAY_SIZE(ctx->fs[i]); j++) {
+         if (ctx->fs[i][j])
+            pipe->delete_fs_state(pipe, ctx->fs[i][j]);
+      }
+   }
 
    pipe_resource_reference(&ctx->vbuf, NULL);
 
 
    pipe_resource_reference(&ctx->vbuf, NULL);
 
@@ -171,23 +154,97 @@ util_destroy_blit(struct blit_state *ctx)
 }
 
 
 }
 
 
+/**
+ * Helper function to set the fragment shaders.
+ */
+static inline void
+set_fragment_shader(struct blit_state *ctx,
+                    enum pipe_format format,
+                    boolean src_xrbias,
+                    enum pipe_texture_target pipe_tex)
+{
+   enum tgsi_return_type stype;
+   unsigned idx;
+
+   if (util_format_is_pure_uint(format)) {
+      stype = TGSI_RETURN_TYPE_UINT;
+      idx = 0;
+   } else if (util_format_is_pure_sint(format)) {
+      stype = TGSI_RETURN_TYPE_SINT;
+      idx = 1;
+   } else {
+      stype = TGSI_RETURN_TYPE_FLOAT;
+      idx = 2;
+   }
+
+   if (src_xrbias) {
+      assert(stype == TGSI_RETURN_TYPE_FLOAT);
+      idx = 3;
+      if (!ctx->fs[pipe_tex][idx]) {
+         enum tgsi_texture_type tgsi_tex =
+            util_pipe_tex_to_tgsi_tex(pipe_tex, 0);
+         ctx->fs[pipe_tex][idx] =
+            util_make_fragment_tex_shader_xrbias(ctx->pipe, tgsi_tex);
+      }
+   }
+   else if (!ctx->fs[pipe_tex][idx]) {
+      enum tgsi_texture_type tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex, 0);
+
+      /* OpenGL does not allow blits from signed to unsigned integer
+       * or vice versa. */
+      ctx->fs[pipe_tex][idx] =
+         util_make_fragment_tex_shader_writemask(ctx->pipe, tgsi_tex,
+                                                 TGSI_INTERPOLATE_LINEAR,
+                                                 TGSI_WRITEMASK_XYZW,
+                                                 stype, stype, false, false);
+   }
+
+   cso_set_fragment_shader_handle(ctx->cso, ctx->fs[pipe_tex][idx]);
+}
+
+
+/**
+ * Helper function to set the vertex shader.
+ */
+static inline void
+set_vertex_shader(struct blit_state *ctx)
+{
+   /* vertex shader - still required to provide the linkage between
+    * fragment shader input semantics and vertex_element/buffers.
+    */
+   if (!ctx->vs) {
+      const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
+                                      TGSI_SEMANTIC_GENERIC };
+      const uint semantic_indexes[] = { 0, 0 };
+      ctx->vs = util_make_vertex_passthrough_shader(ctx->pipe, 2,
+                                                    semantic_names,
+                                                    semantic_indexes, FALSE);
+   }
+
+   cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
+}
+
+
 /**
  * Get offset of next free slot in vertex buffer for quad vertices.
  */
 static unsigned
 /**
  * Get offset of next free slot in vertex buffer for quad vertices.
  */
 static unsigned
-get_next_slot( struct blit_state *ctx )
+get_next_slot(struct blit_state *ctx)
 {
    const unsigned max_slots = 4096 / sizeof ctx->vertices;
 
 {
    const unsigned max_slots = 4096 / sizeof ctx->vertices;
 
-   if (ctx->vbuf_slot >= max_slots) 
-      util_blit_flush( ctx );
+   if (ctx->vbuf_slot >= max_slots) {
+      pipe_resource_reference(&ctx->vbuf, NULL);
+      ctx->vbuf_slot = 0;
+   }
 
    if (!ctx->vbuf) {
       ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
                                      PIPE_BIND_VERTEX_BUFFER,
 
    if (!ctx->vbuf) {
       ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
                                      PIPE_BIND_VERTEX_BUFFER,
+                                     PIPE_USAGE_STREAM,
                                      max_slots * sizeof ctx->vertices);
    }
                                      max_slots * sizeof ctx->vertices);
    }
-   
+
    return ctx->vbuf_slot++ * sizeof ctx->vertices;
 }
 
    return ctx->vbuf_slot++ * sizeof ctx->vertices;
 }
 
@@ -197,9 +254,14 @@ get_next_slot( struct blit_state *ctx )
 /**
  * Setup vertex data for the textured quad we'll draw.
  * Note: y=0=top
 /**
  * Setup vertex data for the textured quad we'll draw.
  * Note: y=0=top
+ *
+ * FIXME: We should call util_map_texcoords2d_onto_cubemap
+ * for cubemaps.
  */
 static unsigned
 setup_vertex_data_tex(struct blit_state *ctx,
  */
 static unsigned
 setup_vertex_data_tex(struct blit_state *ctx,
+                      enum pipe_texture_target src_target,
+                      unsigned src_face,
                       float x0, float y0, float x1, float y1,
                       float s0, float t0, float s1, float t1,
                       float z)
                       float x0, float y0, float x1, float y1,
                       float s0, float t0, float s1, float t1,
                       float z)
@@ -211,29 +273,46 @@ setup_vertex_data_tex(struct blit_state *ctx,
    ctx->vertices[0][0][2] = z;
    ctx->vertices[0][1][0] = s0; /*s*/
    ctx->vertices[0][1][1] = t0; /*t*/
    ctx->vertices[0][0][2] = z;
    ctx->vertices[0][1][0] = s0; /*s*/
    ctx->vertices[0][1][1] = t0; /*t*/
+   ctx->vertices[0][1][2] = 0;  /*r*/
 
    ctx->vertices[1][0][0] = x1;
    ctx->vertices[1][0][1] = y0;
    ctx->vertices[1][0][2] = z;
    ctx->vertices[1][1][0] = s1; /*s*/
    ctx->vertices[1][1][1] = t0; /*t*/
 
    ctx->vertices[1][0][0] = x1;
    ctx->vertices[1][0][1] = y0;
    ctx->vertices[1][0][2] = z;
    ctx->vertices[1][1][0] = s1; /*s*/
    ctx->vertices[1][1][1] = t0; /*t*/
+   ctx->vertices[1][1][2] = 0;  /*r*/
 
    ctx->vertices[2][0][0] = x1;
    ctx->vertices[2][0][1] = y1;
    ctx->vertices[2][0][2] = z;
    ctx->vertices[2][1][0] = s1;
    ctx->vertices[2][1][1] = t1;
 
    ctx->vertices[2][0][0] = x1;
    ctx->vertices[2][0][1] = y1;
    ctx->vertices[2][0][2] = z;
    ctx->vertices[2][1][0] = s1;
    ctx->vertices[2][1][1] = t1;
+   ctx->vertices[3][1][2] = 0;
 
    ctx->vertices[3][0][0] = x0;
    ctx->vertices[3][0][1] = y1;
    ctx->vertices[3][0][2] = z;
    ctx->vertices[3][1][0] = s0;
    ctx->vertices[3][1][1] = t1;
 
    ctx->vertices[3][0][0] = x0;
    ctx->vertices[3][0][1] = y1;
    ctx->vertices[3][0][2] = z;
    ctx->vertices[3][1][0] = s0;
    ctx->vertices[3][1][1] = t1;
+   ctx->vertices[3][1][2] = 0;
+
+   if (src_target == PIPE_TEXTURE_CUBE ||
+       src_target == PIPE_TEXTURE_CUBE_ARRAY) {
+      /* Map cubemap texture coordinates inplace. */
+      const unsigned stride =
+         sizeof ctx->vertices[0] / sizeof ctx->vertices[0][0][0];
+      util_map_texcoords2d_onto_cubemap(src_face,
+                                        &ctx->vertices[0][1][0], stride,
+                                        &ctx->vertices[0][1][0], stride,
+                                        TRUE);
+   }
 
 
-   offset = get_next_slot( ctx );
+   offset = get_next_slot(ctx);
 
 
-   pipe_buffer_write_nooverlap(ctx->pipe, ctx->vbuf,
-                               offset, sizeof(ctx->vertices), ctx->vertices);
+   if (ctx->vbuf) {
+      pipe_buffer_write_nooverlap(ctx->pipe, ctx->vbuf,
+                                  offset, sizeof(ctx->vertices), ctx->vertices);
+   }
 
    return offset;
 }
 
    return offset;
 }
@@ -248,75 +327,122 @@ regions_overlap(int srcX0, int srcY0,
                 int dstX0, int dstY0,
                 int dstX1, int dstY1)
 {
                 int dstX0, int dstY0,
                 int dstX1, int dstY1)
 {
-   if (MAX2(srcX0, srcX1) < MIN2(dstX0, dstX1))
+   if (MAX2(srcX0, srcX1) <= MIN2(dstX0, dstX1))
       return FALSE; /* src completely left of dst */
 
       return FALSE; /* src completely left of dst */
 
-   if (MAX2(dstX0, dstX1) < MIN2(srcX0, srcX1))
+   if (MAX2(dstX0, dstX1) <= MIN2(srcX0, srcX1))
       return FALSE; /* dst completely left of src */
 
       return FALSE; /* dst completely left of src */
 
-   if (MAX2(srcY0, srcY1) < MIN2(dstY0, dstY1))
+   if (MAX2(srcY0, srcY1) <= MIN2(dstY0, dstY1))
       return FALSE; /* src completely above dst */
 
       return FALSE; /* src completely above dst */
 
-   if (MAX2(dstY0, dstY1) < MIN2(srcY0, srcY1))
+   if (MAX2(dstY0, dstY1) <= MIN2(srcY0, srcY1))
       return FALSE; /* dst completely above src */
 
    return TRUE; /* some overlap */
 }
 
 
       return FALSE; /* dst completely above src */
 
    return TRUE; /* some overlap */
 }
 
 
+/**
+ * Can we blit from src format to dest format with a simple copy?
+ */
+static boolean
+formats_compatible(enum pipe_format src_format,
+                   enum pipe_format dst_format)
+{
+   if (src_format == dst_format) {
+      return TRUE;
+   }
+   else {
+      const struct util_format_description *src_desc =
+         util_format_description(src_format);
+      const struct util_format_description *dst_desc =
+         util_format_description(dst_format);
+      return util_is_format_compatible(src_desc, dst_desc);
+   }
+}
+
+
 /**
  * Copy pixel block from src surface to dst surface.
  * Overlapping regions are acceptable.
  * Flipping and stretching are supported.
 /**
  * Copy pixel block from src surface to dst surface.
  * Overlapping regions are acceptable.
  * Flipping and stretching are supported.
- * \param filter  one of PIPE_TEX_MIPFILTER_NEAREST/LINEAR
- * \param writemask  controls which channels in the dest surface are sourced
- *                   from the src surface.  Disabled channels are sourced
- *                   from (0,0,0,1).
- * XXX need some control over blitting Z and/or stencil.
+ * \param filter  one of PIPE_TEX_FILTER_NEAREST/LINEAR
+ * \param writemask  bitmask of PIPE_MASK_[RGBAZS].  Controls which channels
+ *                   in the dest surface are sourced from the src surface.
+ *                   Disabled color channels are sourced from (0,0,0,1).
  */
 void
  */
 void
-util_blit_pixels_writemask(struct blit_state *ctx,
-                           struct pipe_resource *src_tex,
-                           struct pipe_subresource srcsub,
-                           int srcX0, int srcY0,
-                           int srcX1, int srcY1,
-                           int srcZ0,
-                           struct pipe_surface *dst,
-                           int dstX0, int dstY0,
-                           int dstX1, int dstY1,
-                           float z, uint filter,
-                           uint writemask)
+util_blit_pixels(struct blit_state *ctx,
+                 struct pipe_resource *src_tex,
+                 unsigned src_level,
+                 int srcX0, int srcY0,
+                 int srcX1, int srcY1,
+                 int srcZ0,
+                 struct pipe_surface *dst,
+                 int dstX0, int dstY0,
+                 int dstX1, int dstY1,
+                 MAYBE_UNUSED float z,
+                 enum pipe_tex_filter filter,
+                 uint writemask)
 {
    struct pipe_context *pipe = ctx->pipe;
 {
    struct pipe_context *pipe = ctx->pipe;
-   struct pipe_screen *screen = pipe->screen;
-   struct pipe_sampler_view *sampler_view = NULL;
-   struct pipe_sampler_view sv_templ;
-   struct pipe_framebuffer_state fb;
+   enum pipe_format src_format, dst_format;
    const int srcW = abs(srcX1 - srcX0);
    const int srcH = abs(srcY1 - srcY0);
    const int srcW = abs(srcX1 - srcX0);
    const int srcH = abs(srcY1 - srcY0);
-   unsigned offset;
    boolean overlap;
    boolean overlap;
-   float s0, t0, s1, t1;
+   boolean is_stencil, is_depth, blit_depth, blit_stencil;
+   const struct util_format_description *src_desc =
+         util_format_description(src_tex->format);
+   struct pipe_blit_info info;
 
 
-   assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
-          filter == PIPE_TEX_MIPFILTER_LINEAR);
+   assert(filter == PIPE_TEX_FILTER_NEAREST ||
+          filter == PIPE_TEX_FILTER_LINEAR);
 
 
-   assert(srcsub.level <= src_tex->last_level);
+   assert(src_level <= src_tex->last_level);
 
    /* do the regions overlap? */
    overlap = src_tex == dst->texture &&
 
    /* do the regions overlap? */
    overlap = src_tex == dst->texture &&
-             dst->face == srcsub.face &&
-             dst->level == srcsub.level &&
-             dst->zslice == srcZ0 &&
+             dst->u.tex.level == src_level &&
+             dst->u.tex.first_layer == srcZ0 &&
       regions_overlap(srcX0, srcY0, srcX1, srcY1,
                       dstX0, dstY0, dstX1, dstY1);
 
       regions_overlap(srcX0, srcY0, srcX1, srcY1,
                       dstX0, dstY0, dstX1, dstY1);
 
+   src_format = util_format_linear(src_tex->format);
+   dst_format = util_format_linear(dst->texture->format);
+
+   /* See whether we will blit depth or stencil. */
+   is_depth = util_format_has_depth(src_desc);
+   is_stencil = util_format_has_stencil(src_desc);
+
+   blit_depth = is_depth && (writemask & PIPE_MASK_Z);
+   blit_stencil = is_stencil && (writemask & PIPE_MASK_S);
+
+   if (is_depth || is_stencil) {
+      assert((writemask & PIPE_MASK_RGBA) == 0);
+      assert(blit_depth || blit_stencil);
+   }
+   else {
+      assert((writemask & PIPE_MASK_ZS) == 0);
+      assert(!blit_depth);
+      assert(!blit_stencil);
+   }
+
+   /*
+    * XXX: z parameter is deprecated. dst->u.tex.first_layer
+    * specificies the destination layer.
+    */
+   assert(z == 0.0f);
+
    /*
     * Check for simple case:  no format conversion, no flipping, no stretching,
    /*
     * Check for simple case:  no format conversion, no flipping, no stretching,
-    * no overlapping.
+    * no overlapping, same number of samples.
     * Filter mode should not matter since there's no stretching.
     */
     * Filter mode should not matter since there's no stretching.
     */
-   if (dst->format == src_tex->format &&
+   if (formats_compatible(src_format, dst_format) &&
+       src_tex->nr_samples == dst->texture->nr_samples &&
+       is_stencil == blit_stencil &&
+       is_depth == blit_depth &&
        srcX0 < srcX1 &&
        dstX0 < dstX1 &&
        srcY0 < srcY1 &&
        srcX0 < srcX1 &&
        dstX0 < dstX1 &&
        srcY0 < srcY1 &&
@@ -324,321 +450,169 @@ util_blit_pixels_writemask(struct blit_state *ctx,
        (dstX1 - dstX0) == (srcX1 - srcX0) &&
        (dstY1 - dstY0) == (srcY1 - srcY0) &&
        !overlap) {
        (dstX1 - dstX0) == (srcX1 - srcX0) &&
        (dstY1 - dstY0) == (srcY1 - srcY0) &&
        !overlap) {
-      struct pipe_subresource subdst;
-      subdst.face = dst->face;
-      subdst.level = dst->level;
+      struct pipe_box src_box;
+      src_box.x = srcX0;
+      src_box.y = srcY0;
+      src_box.z = srcZ0;
+      src_box.width = srcW;
+      src_box.height = srcH;
+      src_box.depth = 1;
       pipe->resource_copy_region(pipe,
       pipe->resource_copy_region(pipe,
-                                 dst->texture, subdst,
-                                 dstX0, dstY0, dst->zslice,/* dest */
-                                 src_tex, srcsub,
-                                 srcX0, srcY0, srcZ0,/* src */
-                                 srcW, srcH);       /* size */
+                                 dst->texture, dst->u.tex.level,
+                                 dstX0, dstY0, dst->u.tex.first_layer,/* dest */
+                                 src_tex, src_level,
+                                 &src_box);
       return;
    }
 
       return;
    }
 
-
-   /* Create a temporary texture when src and dest alias or when src
-    * is anything other than a 2d texture.
-    * XXX should just use appropriate shader to access 1d / 3d slice / cube face,
-    * much like the u_blitter code does (should be pretty trivial).
-    * 
-    * This can still be improved upon.
-    */
-   if ((src_tex == dst->texture &&
-       dst->face == srcsub.face &&
-       dst->level == srcsub.level &&
-       dst->zslice == srcZ0) ||
-       src_tex->target != PIPE_TEXTURE_2D)
-   {
-      struct pipe_resource texTemp;
-      struct pipe_resource *tex;
-      struct pipe_sampler_view sv_templ;
-      struct pipe_subresource texsub;
-      const int srcLeft = MIN2(srcX0, srcX1);
-      const int srcTop = MIN2(srcY0, srcY1);
-
-      if (srcLeft != srcX0) {
-         /* left-right flip */
-         int tmp = dstX0;
-         dstX0 = dstX1;
-         dstX1 = tmp;
-      }
-
-      if (srcTop != srcY0) {
-         /* up-down flip */
-         int tmp = dstY0;
-         dstY0 = dstY1;
-         dstY1 = tmp;
-      }
-
-      /* create temp texture */
-      memset(&texTemp, 0, sizeof(texTemp));
-      texTemp.target = PIPE_TEXTURE_2D;
-      texTemp.format = src_tex->format;
-      texTemp.last_level = 0;
-      texTemp.width0 = srcW;
-      texTemp.height0 = srcH;
-      texTemp.depth0 = 1;
-      texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
-
-      tex = screen->resource_create(screen, &texTemp);
-      if (!tex)
-         return;
-
-      texsub.face = 0;
-      texsub.level = 0;
-      /* load temp texture */
-      pipe->resource_copy_region(pipe,
-                                 tex, texsub, 0, 0, 0,  /* dest */
-                                 src_tex, srcsub, srcLeft, srcTop, srcZ0, /* src */
-                                 srcW, srcH);     /* size */
-
-      s0 = 0.0f; 
-      s1 = 1.0f;
-      t0 = 0.0f;
-      t1 = 1.0f;
-
-      u_sampler_view_default_template(&sv_templ, tex, tex->format);
-      sampler_view = pipe->create_sampler_view(pipe, tex, &sv_templ);
-
-      if (!sampler_view) {
-         pipe_resource_reference(&tex, NULL);
-         return;
-      }
-      pipe_resource_reference(&tex, NULL);
-   }
-   else {
-      u_sampler_view_default_template(&sv_templ, src_tex, src_tex->format);
-      sv_templ.first_level = sv_templ.last_level = srcsub.level;
-      sampler_view = pipe->create_sampler_view(pipe, src_tex, &sv_templ);
-
-      if (!sampler_view) {
-         return;
-      }
-
-      s0 = srcX0 / (float)(u_minify(sampler_view->texture->width0, srcsub.level));
-      s1 = srcX1 / (float)(u_minify(sampler_view->texture->width0, srcsub.level));
-      t0 = srcY0 / (float)(u_minify(sampler_view->texture->height0, srcsub.level));
-      t1 = srcY1 / (float)(u_minify(sampler_view->texture->height0, srcsub.level));
-   }
-
-
-   assert(screen->is_format_supported(screen, sampler_view->format, PIPE_TEXTURE_2D,
-                                      sampler_view->texture->nr_samples,
-                                      PIPE_BIND_SAMPLER_VIEW, 0));
-   assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
-                                      dst->texture->nr_samples,
-                                      PIPE_BIND_RENDER_TARGET, 0));
-
-   /* save state (restored below) */
-   cso_save_blend(ctx->cso);
-   cso_save_depth_stencil_alpha(ctx->cso);
-   cso_save_rasterizer(ctx->cso);
-   cso_save_samplers(ctx->cso);
-   cso_save_fragment_sampler_views(ctx->cso);
-   cso_save_viewport(ctx->cso);
-   cso_save_framebuffer(ctx->cso);
-   cso_save_fragment_shader(ctx->cso);
-   cso_save_vertex_shader(ctx->cso);
-   cso_save_clip(ctx->cso);
-   cso_save_vertex_elements(ctx->cso);
-
-   /* set misc state we care about */
-   cso_set_blend(ctx->cso, &ctx->blend);
-   cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
-   cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
-   cso_set_clip(ctx->cso, &ctx->clip);
-   cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
-
-   /* sampler */
-   ctx->sampler.min_img_filter = filter;
-   ctx->sampler.mag_img_filter = filter;
-   /* we've limited this already with the sampler view but you never know... */
-   ctx->sampler.min_lod = srcsub.level;
-   ctx->sampler.max_lod = srcsub.level;
-   cso_single_sampler(ctx->cso, 0, &ctx->sampler);
-   cso_single_sampler_done(ctx->cso);
-
-   /* viewport */
-   ctx->viewport.scale[0] = 0.5f * dst->width;
-   ctx->viewport.scale[1] = 0.5f * dst->height;
-   ctx->viewport.scale[2] = 0.5f;
-   ctx->viewport.scale[3] = 1.0f;
-   ctx->viewport.translate[0] = 0.5f * dst->width;
-   ctx->viewport.translate[1] = 0.5f * dst->height;
-   ctx->viewport.translate[2] = 0.5f;
-   ctx->viewport.translate[3] = 0.0f;
-   cso_set_viewport(ctx->cso, &ctx->viewport);
-
-   /* texture */
-   cso_set_fragment_sampler_views(ctx->cso, 1, &sampler_view);
-
-   if (ctx->fs[writemask] == NULL)
-      ctx->fs[writemask] =
-         util_make_fragment_tex_shader_writemask(pipe, TGSI_TEXTURE_2D,
-                                                 writemask);
-
-   /* shaders */
-   cso_set_fragment_shader_handle(ctx->cso, ctx->fs[writemask]);
-   cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
-
-   /* drawing dest */
-   memset(&fb, 0, sizeof(fb));
-   fb.width = dst->width;
-   fb.height = dst->height;
-   fb.nr_cbufs = 1;
-   fb.cbufs[0] = dst;
-   cso_set_framebuffer(ctx->cso, &fb);
-
-   /* draw quad */
-   offset = setup_vertex_data_tex(ctx,
-                                  (float) dstX0 / dst->width * 2.0f - 1.0f,
-                                  (float) dstY0 / dst->height * 2.0f - 1.0f,
-                                  (float) dstX1 / dst->width * 2.0f - 1.0f,
-                                  (float) dstY1 / dst->height * 2.0f - 1.0f,
-                                  s0, t0,
-                                  s1, t1,
-                                  z);
-
-   util_draw_vertex_buffer(ctx->pipe, ctx->vbuf, offset,
-                           PIPE_PRIM_TRIANGLE_FAN,
-                           4,  /* verts */
-                           2); /* attribs/vert */
-
-   /* restore state we changed */
-   cso_restore_blend(ctx->cso);
-   cso_restore_depth_stencil_alpha(ctx->cso);
-   cso_restore_rasterizer(ctx->cso);
-   cso_restore_samplers(ctx->cso);
-   cso_restore_fragment_sampler_views(ctx->cso);
-   cso_restore_viewport(ctx->cso);
-   cso_restore_framebuffer(ctx->cso);
-   cso_restore_fragment_shader(ctx->cso);
-   cso_restore_vertex_shader(ctx->cso);
-   cso_restore_clip(ctx->cso);
-   cso_restore_vertex_elements(ctx->cso);
-
-   pipe_sampler_view_reference(&sampler_view, NULL);
+   memset(&info, 0, sizeof info);
+   info.dst.resource = dst->texture;
+   info.dst.level = dst->u.tex.level;
+   info.dst.box.x = dstX0;
+   info.dst.box.y = dstY0;
+   info.dst.box.z = dst->u.tex.first_layer;
+   info.dst.box.width = dstX1 - dstX0;
+   info.dst.box.height = dstY1 - dstY0;
+   assert(info.dst.box.width >= 0);
+   assert(info.dst.box.height >= 0);
+   info.dst.box.depth = 1;
+   info.dst.format = dst_format;
+   info.src.resource = src_tex;
+   info.src.level = src_level;
+   info.src.box.x = srcX0;
+   info.src.box.y = srcY0;
+   info.src.box.z = srcZ0;
+   info.src.box.width = srcX1 - srcX0;
+   info.src.box.height = srcY1 - srcY0;
+   info.src.box.depth = 1;
+   info.src.format = src_format;
+   info.mask = writemask;
+   info.filter = filter;
+   info.scissor_enable = 0;
+
+   pipe->blit(pipe, &info);
 }
 
 
 }
 
 
-void
-util_blit_pixels(struct blit_state *ctx,
-                 struct pipe_resource *src_tex,
-                 struct pipe_subresource srcsub,
-                 int srcX0, int srcY0,
-                 int srcX1, int srcY1,
-                 int srcZ,
-                 struct pipe_surface *dst,
-                 int dstX0, int dstY0,
-                 int dstX1, int dstY1,
-                 float z, uint filter )
-{
-   util_blit_pixels_writemask( ctx, src_tex,
-                               srcsub,
-                               srcX0, srcY0,
-                               srcX1, srcY1,
-                               srcZ,
-                               dst,
-                               dstX0, dstY0,
-                               dstX1, dstY1,
-                               z, filter,
-                               TGSI_WRITEMASK_XYZW );
-}
-
-
-/* Release vertex buffer at end of frame to avoid synchronous
- * rendering.
- */
-void util_blit_flush( struct blit_state *ctx )
-{
-   pipe_resource_reference(&ctx->vbuf, NULL);
-   ctx->vbuf_slot = 0;
-} 
-
-
-
 /**
 /**
- * Copy pixel block from src texture to dst surface.
+ * Copy pixel block from src sampler view to dst surface.
+ *
+ * The sampler view's first_level field indicates the source
+ * mipmap level to use.
+ *
+ * The sampler view's first_layer indicate the layer to use, but for
+ * cube maps it must point to the first face.  Face is passed in src_face.
  *
  *
- * XXX Should support selection of level.
- * XXX need some control over blitting Z and/or stencil.
+ * The main advantage over util_blit_pixels is that it allows to specify
+ * swizzles in pipe_sampler_view::swizzle_?.
+ *
+ * But there is no control over blitting Z and/or stencil.
  */
 void
 util_blit_pixels_tex(struct blit_state *ctx,
                      struct pipe_sampler_view *src_sampler_view,
                      int srcX0, int srcY0,
                      int srcX1, int srcY1,
  */
 void
 util_blit_pixels_tex(struct blit_state *ctx,
                      struct pipe_sampler_view *src_sampler_view,
                      int srcX0, int srcY0,
                      int srcX1, int srcY1,
+                     unsigned src_face,
                      struct pipe_surface *dst,
                      int dstX0, int dstY0,
                      int dstX1, int dstY1,
                      struct pipe_surface *dst,
                      int dstX0, int dstY0,
                      int dstX1, int dstY1,
-                     float z, uint filter)
+                     float z, enum pipe_tex_filter filter,
+                     boolean src_xrbias)
 {
 {
+   boolean normalized = src_sampler_view->texture->target != PIPE_TEXTURE_RECT;
    struct pipe_framebuffer_state fb;
    float s0, t0, s1, t1;
    unsigned offset;
    struct pipe_resource *tex = src_sampler_view->texture;
 
    struct pipe_framebuffer_state fb;
    float s0, t0, s1, t1;
    unsigned offset;
    struct pipe_resource *tex = src_sampler_view->texture;
 
-   assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
-          filter == PIPE_TEX_MIPFILTER_LINEAR);
+   assert(filter == PIPE_TEX_FILTER_NEAREST ||
+          filter == PIPE_TEX_FILTER_LINEAR);
 
    assert(tex);
    assert(tex->width0 != 0);
    assert(tex->height0 != 0);
 
 
    assert(tex);
    assert(tex->width0 != 0);
    assert(tex->height0 != 0);
 
-   s0 = srcX0 / (float)tex->width0;
-   s1 = srcX1 / (float)tex->width0;
-   t0 = srcY0 / (float)tex->height0;
-   t1 = srcY1 / (float)tex->height0;
+   s0 = (float) srcX0;
+   s1 = (float) srcX1;
+   t0 = (float) srcY0;
+   t1 = (float) srcY1;
+
+   if (normalized) {
+      /* normalize according to the mipmap level's size */
+      int level = src_sampler_view->u.tex.first_level;
+      float w = (float) u_minify(tex->width0, level);
+      float h = (float) u_minify(tex->height0, level);
+      s0 /= w;
+      s1 /= w;
+      t0 /= h;
+      t1 /= h;
+   }
 
    assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format,
                                                  PIPE_TEXTURE_2D,
                                                  dst->texture->nr_samples,
 
    assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format,
                                                  PIPE_TEXTURE_2D,
                                                  dst->texture->nr_samples,
-                                                 PIPE_BIND_RENDER_TARGET,
-                                                 0));
+                                                 dst->texture->nr_storage_samples,
+                                                 PIPE_BIND_RENDER_TARGET));
 
    /* save state (restored below) */
 
    /* save state (restored below) */
-   cso_save_blend(ctx->cso);
-   cso_save_depth_stencil_alpha(ctx->cso);
-   cso_save_rasterizer(ctx->cso);
-   cso_save_samplers(ctx->cso);
-   cso_save_fragment_sampler_views(ctx->cso);
-   cso_save_framebuffer(ctx->cso);
-   cso_save_fragment_shader(ctx->cso);
-   cso_save_vertex_shader(ctx->cso);
-   cso_save_clip(ctx->cso);
-   cso_save_vertex_elements(ctx->cso);
+   cso_save_state(ctx->cso, (CSO_BIT_BLEND |
+                             CSO_BIT_DEPTH_STENCIL_ALPHA |
+                             CSO_BIT_RASTERIZER |
+                             CSO_BIT_SAMPLE_MASK |
+                             CSO_BIT_MIN_SAMPLES |
+                             CSO_BIT_FRAGMENT_SAMPLERS |
+                             CSO_BIT_FRAGMENT_SAMPLER_VIEWS |
+                             CSO_BIT_STREAM_OUTPUTS |
+                             CSO_BIT_VIEWPORT |
+                             CSO_BIT_FRAMEBUFFER |
+                             CSO_BIT_PAUSE_QUERIES |
+                             CSO_BIT_FRAGMENT_SHADER |
+                             CSO_BIT_VERTEX_SHADER |
+                             CSO_BIT_TESSCTRL_SHADER |
+                             CSO_BIT_TESSEVAL_SHADER |
+                             CSO_BIT_GEOMETRY_SHADER |
+                             CSO_BIT_VERTEX_ELEMENTS |
+                             CSO_BIT_AUX_VERTEX_BUFFER_SLOT));
 
    /* set misc state we care about */
 
    /* set misc state we care about */
-   cso_set_blend(ctx->cso, &ctx->blend);
-   cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
+   cso_set_blend(ctx->cso, &ctx->blend_write_color);
+   cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil);
+   cso_set_sample_mask(ctx->cso, ~0);
+   cso_set_min_samples(ctx->cso, 1);
    cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
    cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
-   cso_set_clip(ctx->cso, &ctx->clip);
    cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
    cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
+   cso_set_stream_outputs(ctx->cso, 0, NULL, NULL);
 
    /* sampler */
 
    /* sampler */
+   ctx->sampler.normalized_coords = normalized;
    ctx->sampler.min_img_filter = filter;
    ctx->sampler.mag_img_filter = filter;
    ctx->sampler.min_img_filter = filter;
    ctx->sampler.mag_img_filter = filter;
-   cso_single_sampler(ctx->cso, 0, &ctx->sampler);
-   cso_single_sampler_done(ctx->cso);
+   {
+      const struct pipe_sampler_state *samplers[] = {&ctx->sampler};
+      cso_set_samplers(ctx->cso, PIPE_SHADER_FRAGMENT, 1, samplers);
+   }
 
    /* viewport */
    ctx->viewport.scale[0] = 0.5f * dst->width;
    ctx->viewport.scale[1] = 0.5f * dst->height;
    ctx->viewport.scale[2] = 0.5f;
 
    /* viewport */
    ctx->viewport.scale[0] = 0.5f * dst->width;
    ctx->viewport.scale[1] = 0.5f * dst->height;
    ctx->viewport.scale[2] = 0.5f;
-   ctx->viewport.scale[3] = 1.0f;
    ctx->viewport.translate[0] = 0.5f * dst->width;
    ctx->viewport.translate[1] = 0.5f * dst->height;
    ctx->viewport.translate[2] = 0.5f;
    ctx->viewport.translate[0] = 0.5f * dst->width;
    ctx->viewport.translate[1] = 0.5f * dst->height;
    ctx->viewport.translate[2] = 0.5f;
-   ctx->viewport.translate[3] = 0.0f;
    cso_set_viewport(ctx->cso, &ctx->viewport);
 
    /* texture */
    cso_set_viewport(ctx->cso, &ctx->viewport);
 
    /* texture */
-   cso_set_fragment_sampler_views(ctx->cso, 1, &src_sampler_view);
+   cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &src_sampler_view);
 
    /* shaders */
 
    /* shaders */
-   cso_set_fragment_shader_handle(ctx->cso, ctx->fs[TGSI_WRITEMASK_XYZW]);
-   cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
+   set_fragment_shader(ctx, src_sampler_view->format,
+                       src_xrbias,
+                       src_sampler_view->texture->target);
+   set_vertex_shader(ctx);
+   cso_set_tessctrl_shader_handle(ctx->cso, NULL);
+   cso_set_tesseval_shader_handle(ctx->cso, NULL);
+   cso_set_geometry_shader_handle(ctx->cso, NULL);
 
    /* drawing dest */
    memset(&fb, 0, sizeof(fb));
 
    /* drawing dest */
    memset(&fb, 0, sizeof(fb));
@@ -650,6 +624,8 @@ util_blit_pixels_tex(struct blit_state *ctx,
 
    /* draw quad */
    offset = setup_vertex_data_tex(ctx,
 
    /* draw quad */
    offset = setup_vertex_data_tex(ctx,
+                                  src_sampler_view->texture->target,
+                                  src_face,
                                   (float) dstX0 / dst->width * 2.0f - 1.0f,
                                   (float) dstY0 / dst->height * 2.0f - 1.0f,
                                   (float) dstX1 / dst->width * 2.0f - 1.0f,
                                   (float) dstX0 / dst->width * 2.0f - 1.0f,
                                   (float) dstY0 / dst->height * 2.0f - 1.0f,
                                   (float) dstX1 / dst->width * 2.0f - 1.0f,
@@ -657,21 +633,12 @@ util_blit_pixels_tex(struct blit_state *ctx,
                                   s0, t0, s1, t1,
                                   z);
 
                                   s0, t0, s1, t1,
                                   z);
 
-   util_draw_vertex_buffer(ctx->pipe, 
-                           ctx->vbuf, offset,
+   util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf, 0,
+                           offset,
                            PIPE_PRIM_TRIANGLE_FAN,
                            4,  /* verts */
                            2); /* attribs/vert */
 
    /* restore state we changed */
                            PIPE_PRIM_TRIANGLE_FAN,
                            4,  /* verts */
                            2); /* attribs/vert */
 
    /* restore state we changed */
-   cso_restore_blend(ctx->cso);
-   cso_restore_depth_stencil_alpha(ctx->cso);
-   cso_restore_rasterizer(ctx->cso);
-   cso_restore_samplers(ctx->cso);
-   cso_restore_fragment_sampler_views(ctx->cso);
-   cso_restore_framebuffer(ctx->cso);
-   cso_restore_fragment_shader(ctx->cso);
-   cso_restore_vertex_shader(ctx->cso);
-   cso_restore_clip(ctx->cso);
-   cso_restore_vertex_elements(ctx->cso);
+   cso_restore_state(ctx->cso);
 }
 }