gallium: allow setting of the internal stream output offset
[mesa.git] / src / gallium / auxiliary / util / u_blit.c
index cd95f85b63bddfcbe6efba61658c481b9e69d239..4b25b93dd17e71efbf8df45a5f2b757a3bc92a00 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.
@@ -46,9 +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 "util/u_rect.h"
 
 #include "cso_cache/cso_context.h"
 
 
 #include "cso_cache/cso_context.h"
 
@@ -58,18 +57,17 @@ 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][TGSI_WRITEMASK_XYZW + 1];
 
 
-   struct pipe_buffer *vbuf;  /**< quad vertices */
+   struct pipe_resource *vbuf;  /**< quad vertices */
    unsigned vbuf_slot;
 
    float vertices[4][2][4];   /**< vertex/texcoords for quad */
    unsigned vbuf_slot;
 
    float vertices[4][2][4];   /**< vertex/texcoords for quad */
@@ -94,57 +92,35 @@ 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.front_winding = PIPE_WINDING_CW;
-   ctx->rasterizer.cull_mode = PIPE_WINDING_NONE;
-   ctx->rasterizer.gl_rasterization_rules = 1;
+   ctx->rasterizer.cull_face = PIPE_FACE_NONE;
+   ctx->rasterizer.half_pixel_center = 1;
+   ctx->rasterizer.bottom_edge_rule = 1;
+   ctx->rasterizer.depth_clip = 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;
-      ctx->velem[i].vertex_buffer_index = 0;
+      ctx->velem[i].vertex_buffer_index = cso_get_aux_vertex_buffer_slot(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 */
    }
 
@@ -159,20 +135,66 @@ 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 < Elements(ctx->fs); i++) {
+      for (j = 0; j < Elements(ctx->fs[i]); j++) {
+         if (ctx->fs[i][j])
+            pipe->delete_fs_state(pipe, ctx->fs[i][j]);
+      }
+   }
 
 
-   pipe_buffer_reference(&ctx->vbuf, NULL);
+   pipe_resource_reference(&ctx->vbuf, NULL);
 
    FREE(ctx);
 }
 
 
 
    FREE(ctx);
 }
 
 
+/**
+ * Helper function to set the fragment shaders.
+ */
+static INLINE void
+set_fragment_shader(struct blit_state *ctx, uint writemask,
+                    enum pipe_texture_target pipe_tex)
+{
+   if (!ctx->fs[pipe_tex][writemask]) {
+      unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex, 0);
+
+      ctx->fs[pipe_tex][writemask] =
+         util_make_fragment_tex_shader_writemask(ctx->pipe, tgsi_tex,
+                                                 TGSI_INTERPOLATE_LINEAR,
+                                                 writemask);
+   }
+
+   cso_set_fragment_shader_handle(ctx->cso, ctx->fs[pipe_tex][writemask]);
+}
+
+
+/**
+ * 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);
+   }
+
+   cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
+}
+
+
 /**
  * Get offset of next free slot in vertex buffer for quad vertices.
  */
 /**
  * Get offset of next free slot in vertex buffer for quad vertices.
  */
@@ -181,19 +203,20 @@ 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,
 
    if (!ctx->vbuf) {
       ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
-                                     32,
-                                     PIPE_BUFFER_USAGE_VERTEX,
+                                     PIPE_BIND_VERTEX_BUFFER,
+                                     PIPE_USAGE_STREAM,
                                      max_slots * sizeof ctx->vertices);
    }
    
    return ctx->vbuf_slot++ * sizeof ctx->vertices;
 }
                                      max_slots * sizeof ctx->vertices);
    }
    
    return ctx->vbuf_slot++ * sizeof ctx->vertices;
 }
-                               
 
 
 
 
 
 
@@ -201,9 +224,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,
+                      unsigned 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)
@@ -215,29 +243,45 @@ 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->screen, 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;
 }
@@ -268,6 +312,26 @@ regions_overlap(int srcX0, int srcY0,
 }
 
 
 }
 
 
+/**
+ * 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.
 /**
  * Copy pixel block from src surface to dst surface.
  * Overlapping regions are acceptable.
@@ -276,50 +340,70 @@ regions_overlap(int srcX0, int srcY0,
  * \param writemask  controls which channels in the dest surface are sourced
  *                   from the src surface.  Disabled channels are sourced
  *                   from (0,0,0,1).
  * \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.
  */
 void
  */
 void
-util_blit_pixels_writemask(struct blit_state *ctx,
-                           struct pipe_surface *src,
-                           struct pipe_sampler_view *src_sampler_view,
-                           int srcX0, int srcY0,
-                           int srcX1, int srcY1,
-                           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,
+                 float z, uint filter,
+                 uint writemask, uint zs_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_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_MIPFILTER_NEAREST ||
           filter == PIPE_TEX_MIPFILTER_LINEAR);
 
-   assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
-                                      PIPE_TEXTURE_USAGE_SAMPLER, 0));
-   assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
-                                      PIPE_TEXTURE_USAGE_RENDER_TARGET, 0));
+   assert(src_level <= src_tex->last_level);
 
    /* do the regions overlap? */
 
    /* do the regions overlap? */
-   overlap = util_same_surface(src, dst) &&
+   overlap = src_tex == dst->texture &&
+             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 && (zs_writemask & BLIT_WRITEMASK_Z);
+   blit_stencil = is_stencil && (zs_writemask & BLIT_WRITEMASK_STENCIL);
+
+   assert((writemask && !zs_writemask && !is_depth && !is_stencil) ||
+          (!writemask && (blit_depth || 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 (pipe->surface_copy &&
-       dst->format == src->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 &&
@@ -327,246 +411,80 @@ 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) {
-      pipe->surface_copy(pipe,
-                        dst, dstX0, dstY0, /* dest */
-                        src, srcX0, srcY0, /* src */
-                        srcW, srcH);       /* size */
+      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,
+                                 dst->texture, dst->u.tex.level,
+                                 dstX0, dstY0, dst->u.tex.first_layer,/* dest */
+                                 src_tex, src_level,
+                                 &src_box);
       return;
    }
       return;
    }
-   
-   assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
-                                      PIPE_TEXTURE_USAGE_RENDER_TARGET, 0));
-
-   /* Create a temporary texture when src and dest alias or when src
-    * is anything other than a single-level 2d texture.
-    * 
-    * This can still be improved upon.
-    */
-   if (util_same_surface(src, dst) ||
-       src->texture->target != PIPE_TEXTURE_2D ||
-       src->texture->last_level != 0)
-   {
-      struct pipe_texture texTemp;
-      struct pipe_texture *tex;
-      struct pipe_sampler_view sv_templ;
-      struct pipe_surface *texSurf;
-      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->format;
-      texTemp.last_level = 0;
-      texTemp.width0 = srcW;
-      texTemp.height0 = srcH;
-      texTemp.depth0 = 1;
-
-      tex = screen->texture_create(screen, &texTemp);
-      if (!tex)
-         return;
-
-      u_sampler_view_default_template(&sv_templ, tex, tex->format);
-
-      sampler_view = ctx->pipe->create_sampler_view(ctx->pipe, tex, &sv_templ);
-      if (!sampler_view) {
-         pipe_texture_reference(&tex, NULL);
-         return;
-      }
-
-      texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0, 
-                                        PIPE_BUFFER_USAGE_GPU_WRITE);
-
-      /* load temp texture */
-      if (pipe->surface_copy) {
-         pipe->surface_copy(pipe,
-                            texSurf, 0, 0,   /* dest */
-                            src, srcLeft, srcTop, /* src */
-                            srcW, srcH);     /* size */
-      } else {
-         util_surface_copy(pipe, FALSE,
-                           texSurf, 0, 0,   /* dest */
-                           src, srcLeft, srcTop, /* src */
-                           srcW, srcH);     /* size */
-      }
-
-      /* free the surface, update the texture if necessary.
-       */
-      pipe_surface_reference(&texSurf, NULL);
-      s0 = 0.0f; 
-      s1 = 1.0f;
-      t0 = 0.0f;
-      t1 = 1.0f;
-
-      pipe_texture_reference(&tex, NULL);
-   }
-   else {
-      pipe_sampler_view_reference(&sampler_view, src_sampler_view);
-      s0 = srcX0 / (float)src->texture->width0;
-      s1 = srcX1 / (float)src->texture->width0;
-      t0 = srcY0 / (float)src->texture->height0;
-      t1 = srcY1 / (float)src->texture->height0;
-   }
 
 
-   
-
-   /* 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;
-   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);
-}
-
-
-void
-util_blit_pixels(struct blit_state *ctx,
-                 struct pipe_surface *src,
-                 struct pipe_sampler_view *src_sampler_view,
-                 int srcX0, int srcY0,
-                 int srcX1, int srcY1,
-                 struct pipe_surface *dst,
-                 int dstX0, int dstY0,
-                 int dstX1, int dstY1,
-                 float z, uint filter )
-{
-   util_blit_pixels_writemask( ctx, src, src_sampler_view,
-                               srcX0, srcY0,
-                               srcX1, srcY1,
-                               dst,
-                               dstX0, dstY0,
-                               dstX1, dstY1,
-                               z, filter,
-                               TGSI_WRITEMASK_XYZW );
+   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->texture->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_tex->format;
+   info.mask = writemask | (zs_writemask << 4);
+   info.filter = filter;
+   info.scissor_enable = 0;
+
+   pipe->blit(pipe, &info);
 }
 
 
 }
 
 
-/* Release vertex buffer at end of frame to avoid synchronous
- * rendering.
- */
-void util_blit_flush( struct blit_state *ctx )
-{
-   pipe_buffer_reference(&ctx->vbuf, NULL);
-   ctx->vbuf_slot = 0;
-} 
-
-
-
 /**
 /**
- * Copy pixel block from src texture to dst surface.
- * Overlapping regions are acceptable.
+ * Copy pixel block from src sampler view to dst surface.
+ *
+ * The sampler view's first_level field indicates the source
+ * mipmap level to use.
  *
  *
- * XXX Should support selection of level.
- * XXX need some control over blitting Z and/or stencil.
+ * 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.
+ *
+ * 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,
                      float z, uint filter)
 {
                      struct pipe_surface *dst,
                      int dstX0, int dstY0,
                      int dstX1, int dstY1,
                      float z, uint filter)
 {
+   boolean normalized = src_sampler_view->texture->target != PIPE_TEXTURE_RECT;
    struct pipe_framebuffer_state fb;
    float s0, t0, s1, t1;
    unsigned offset;
    struct pipe_framebuffer_state fb;
    float s0, t0, s1, t1;
    unsigned offset;
-   struct pipe_texture *tex = src_sampler_view->texture;
+   struct pipe_resource *tex = src_sampler_view->texture;
 
    assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
           filter == PIPE_TEX_MIPFILTER_LINEAR);
 
    assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
           filter == PIPE_TEX_MIPFILTER_LINEAR);
@@ -575,40 +493,58 @@ util_blit_pixels_tex(struct blit_state *ctx,
    assert(tex->width0 != 0);
    assert(tex->height0 != 0);
 
    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,
 
    assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format,
                                                  PIPE_TEXTURE_2D,
-                                                 PIPE_TEXTURE_USAGE_RENDER_TARGET,
-                                                 0));
+                                                 dst->texture->nr_samples,
+                                                 PIPE_BIND_RENDER_TARGET));
 
    /* save state (restored below) */
    cso_save_blend(ctx->cso);
    cso_save_depth_stencil_alpha(ctx->cso);
    cso_save_rasterizer(ctx->cso);
 
    /* 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_sample_mask(ctx->cso);
+   cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
+   cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
+   cso_save_stream_outputs(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_framebuffer(ctx->cso);
    cso_save_fragment_shader(ctx->cso);
    cso_save_vertex_shader(ctx->cso);
-   cso_save_clip(ctx->cso);
+   cso_save_geometry_shader(ctx->cso);
    cso_save_vertex_elements(ctx->cso);
    cso_save_vertex_elements(ctx->cso);
+   cso_save_aux_vertex_buffer_slot(ctx->cso);
 
    /* 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_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);
+   cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
+   cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT);
 
    /* viewport */
    ctx->viewport.scale[0] = 0.5f * dst->width;
 
    /* viewport */
    ctx->viewport.scale[0] = 0.5f * dst->width;
@@ -622,11 +558,13 @@ util_blit_pixels_tex(struct blit_state *ctx,
    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, TGSI_WRITEMASK_XYZW,
+                       src_sampler_view->texture->target);
+   set_vertex_shader(ctx);
+   cso_set_geometry_shader_handle(ctx->cso, NULL);
 
    /* drawing dest */
    memset(&fb, 0, sizeof(fb));
 
    /* drawing dest */
    memset(&fb, 0, sizeof(fb));
@@ -638,6 +576,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,
@@ -645,8 +585,9 @@ 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,
+                           cso_get_aux_vertex_buffer_slot(ctx->cso),
+                           offset,
                            PIPE_PRIM_TRIANGLE_FAN,
                            4,  /* verts */
                            2); /* attribs/vert */
                            PIPE_PRIM_TRIANGLE_FAN,
                            4,  /* verts */
                            2); /* attribs/vert */
@@ -655,11 +596,15 @@ util_blit_pixels_tex(struct blit_state *ctx,
    cso_restore_blend(ctx->cso);
    cso_restore_depth_stencil_alpha(ctx->cso);
    cso_restore_rasterizer(ctx->cso);
    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_sample_mask(ctx->cso);
+   cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
+   cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
+   cso_restore_viewport(ctx->cso);
    cso_restore_framebuffer(ctx->cso);
    cso_restore_fragment_shader(ctx->cso);
    cso_restore_vertex_shader(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_geometry_shader(ctx->cso);
    cso_restore_vertex_elements(ctx->cso);
    cso_restore_vertex_elements(ctx->cso);
+   cso_restore_aux_vertex_buffer_slot(ctx->cso);
+   cso_restore_stream_outputs(ctx->cso);
 }
 }