[Mesa-dev] [PATCH] st/xorg: Better handling of EXA copies.

Michel Dänzer michel at daenzer.net
Tue Aug 23 07:01:43 PDT 2011


From: Michel Dänzer <michel.daenzer at amd.com>

Always use the resource_copy_region hook. If a source and destination rectangle
overlap, copy to/from a temporary pixmap.
---

This gets accelerated tiled fills (such as for the X root weave; EXA expects
each Copy driver hook call to pick up the results of the previous one for
these) basically working with r600g and the svga driver, but unfortunately,
both of them occasionally show some minor corruption in the root weave when
moving around a window above it (looks like leftovers of the window being
moved). Mixing in some texture_barrier hook calls doesn't seem to make any
difference for this with r600g.

Using a temporary pixmap for overlapping copies was inspired by the X radeon
driver.

 src/gallium/state_trackers/xorg/xorg_exa.c      |   94 ++++++--------
 src/gallium/state_trackers/xorg/xorg_exa.h      |    7 +-
 src/gallium/state_trackers/xorg/xorg_renderer.c |  153 -----------------------
 src/gallium/state_trackers/xorg/xorg_renderer.h |   15 ---
 4 files changed, 41 insertions(+), 228 deletions(-)

diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c
index b072f53..ad46be0 100644
--- a/src/gallium/state_trackers/xorg/xorg_exa.c
+++ b/src/gallium/state_trackers/xorg/xorg_exa.c
@@ -457,41 +457,6 @@ ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
     exa->copy.src = src_priv;
     exa->copy.dst = priv;
 
-    /* XXX this used to use resource_copy_region for same-surface copies,
-     * but they were redefined to not allow overlaps (some of the util code
-     * always assumed this anyway).
-     * Drivers should implement accelerated resource_copy_region or it will
-     * be slow - disable for now.
-     */
-    if (0 && exa->copy.src != exa->copy.dst) {
-       exa->copy.use_surface_copy = TRUE;
-    }
-    else {
-       struct pipe_surface surf_tmpl;
-       exa->copy.use_surface_copy = FALSE;
-
-       if (exa->copy.dst == exa->copy.src)
-          exa->copy.src_texture = renderer_clone_texture( exa->renderer,
-                                                          exa->copy.src->tex );
-       else
-          pipe_resource_reference(&exa->copy.src_texture,
-                                 exa->copy.src->tex);
-
-       memset(&surf_tmpl, 0, sizeof(surf_tmpl));
-       u_surface_default_template(&surf_tmpl, exa->copy.dst->tex,
-                                  PIPE_BIND_RENDER_TARGET);
-       exa->copy.dst_surface =
-          exa->pipe->create_surface(exa->pipe,
-                                    exa->copy.dst->tex,
-                                    &surf_tmpl);
-
-
-       renderer_copy_prepare(exa->renderer, 
-                             exa->copy.dst_surface,
-                             exa->copy.src_texture );
-    }
-
-
     return TRUE;
 }
 
@@ -502,32 +467,53 @@ ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
    modesettingPtr ms = modesettingPTR(pScrn);
    struct exa_context *exa = ms->exa;
-   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
+   struct pipe_box src_box;
 
    exa_debug_printf("\tExaCopy(srcx=%d, srcy=%d, dstX=%d, dstY=%d, w=%d, h=%d)\n",
                 srcX, srcY, dstX, dstY, width, height);
 
-   debug_assert(priv == exa->copy.dst);
-   (void) priv;
+   debug_assert(exaGetPixmapDriverPrivate(pDstPixmap) == exa->copy.dst);
+
+   u_box_2d(srcX, srcY, width, height, &src_box);
+
+   /* If source and destination overlap, we have to copy to/from a scratch
+    * pixmap.
+    */
+   if (exa->copy.dst == exa->copy.src &&
+       !((dstX + width) < srcX || dstX > (srcX + width) ||
+	 (dstY + height) < srcY || dstY > (srcY + height))) {
+      struct exa_pixmap_priv *tmp_priv;
+
+      if (!exa->copy.tmp_pix) {
+         exa->copy.tmp_pix = pScrn->pScreen->CreatePixmap(pScrn->pScreen,
+                                                         pDstPixmap->drawable.width,
+                                                         pDstPixmap->drawable.height,
+                                                         pDstPixmap->drawable.depth,
+                                                         pDstPixmap->drawable.width);
+         exaMoveInPixmap(exa->copy.tmp_pix);
+      }
+
+      tmp_priv = exaGetPixmapDriverPrivate(exa->copy.tmp_pix);
 
-   if (exa->copy.use_surface_copy) {
-      struct pipe_box src_box;
-      u_box_2d(srcX, srcY, width, height, &src_box);
+      exa->pipe->resource_copy_region( exa->pipe,
+                                       tmp_priv->tex,
+                                       0,
+                                       srcX, srcY, 0,
+                                       exa->copy.src->tex,
+                                       0, &src_box);
+      exa->pipe->resource_copy_region( exa->pipe,
+                                       exa->copy.dst->tex,
+                                       0,
+                                       dstX, dstY, 0,
+                                       tmp_priv->tex,
+                                       0, &src_box);
+   } else
       exa->pipe->resource_copy_region( exa->pipe,
                                        exa->copy.dst->tex,
                                        0,
                                        dstX, dstY, 0,
                                        exa->copy.src->tex,
                                        0, &src_box);
-   }
-   else {
-      renderer_copy_pixmap(exa->renderer, 
-                           dstX, dstY,
-                           srcX, srcY,
-                           width, height,
-                           exa->copy.src_texture->width0,
-                           exa->copy.src_texture->height0);
-   }
 }
 
 static void
@@ -543,12 +529,12 @@ ExaDoneCopy(PixmapPtr pPixmap)
 
    exa_debug_printf("ExaDoneCopy\n");
 
-   renderer_draw_flush(exa->renderer);
-
+   if (exa->copy.tmp_pix) {
+      pScrn->pScreen->DestroyPixmap(exa->copy.tmp_pix);
+      exa->copy.tmp_pix = NULL;
+   }
    exa->copy.src = NULL;
    exa->copy.dst = NULL;
-   pipe_surface_reference(&exa->copy.dst_surface, NULL);
-   pipe_resource_reference(&exa->copy.src_texture, NULL);
 
    exa_debug_printf("ExaDoneCopy done\n");
 }
diff --git a/src/gallium/state_trackers/xorg/xorg_exa.h b/src/gallium/state_trackers/xorg/xorg_exa.h
index 30b6f0c..2d4bd07 100644
--- a/src/gallium/state_trackers/xorg/xorg_exa.h
+++ b/src/gallium/state_trackers/xorg/xorg_exa.h
@@ -35,14 +35,9 @@ struct exa_context
    } transform;
 
    struct {
-      boolean use_surface_copy;
-
       struct exa_pixmap_priv *src;
       struct exa_pixmap_priv *dst;
-
-      struct pipe_surface *dst_surface;
-
-      struct pipe_resource *src_texture;
+      PixmapPtr tmp_pix;
    } copy;
 };
 
diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.c b/src/gallium/state_trackers/xorg/xorg_renderer.c
index 6b799af..9b021a1 100644
--- a/src/gallium/state_trackers/xorg/xorg_renderer.c
+++ b/src/gallium/state_trackers/xorg/xorg_renderer.c
@@ -440,159 +440,6 @@ void renderer_set_constants(struct xorg_renderer *r,
 }
 
 
-void renderer_copy_prepare(struct xorg_renderer *r,
-                           struct pipe_surface *dst_surface,
-                           struct pipe_resource *src_texture)
-{
-   struct pipe_context *pipe = r->pipe;
-   struct pipe_screen *screen = pipe->screen;
-   struct xorg_shader shader;
-
-   assert(screen->is_format_supported(screen, dst_surface->format,
-                                      PIPE_TEXTURE_2D, 0,
-                                      PIPE_BIND_RENDER_TARGET));
-   (void) screen;
-
-
-   /* set misc state we care about */
-   {
-      struct pipe_blend_state blend;
-      memset(&blend, 0, sizeof(blend));
-      blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
-      blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
-      blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
-      blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
-      blend.rt[0].colormask = PIPE_MASK_RGBA;
-      cso_set_blend(r->cso, &blend);
-   }
-
-   /* sampler */
-   {
-      struct pipe_sampler_state sampler;
-      memset(&sampler, 0, sizeof(sampler));
-      sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
-      sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
-      sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
-      sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
-      sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
-      sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
-      sampler.normalized_coords = 1;
-      cso_single_sampler(r->cso, 0, &sampler);
-      cso_single_sampler_done(r->cso);
-   }
-
-   renderer_bind_destination(r, dst_surface, 
-                             dst_surface->width,
-                             dst_surface->height);
-
-   /* texture/sampler view */
-   {
-      struct pipe_sampler_view templ;
-      struct pipe_sampler_view *src_view;
-      u_sampler_view_default_template(&templ,
-                                      src_texture,
-                                      src_texture->format);
-      src_view = pipe->create_sampler_view(pipe, src_texture, &templ);
-      cso_set_fragment_sampler_views(r->cso, 1, &src_view);
-      pipe_sampler_view_reference(&src_view, NULL);
-   }
-
-   /* shaders */
-   shader = xorg_shaders_get(r->shaders,
-                             VS_COMPOSITE,
-                             FS_COMPOSITE);
-   cso_set_vertex_shader_handle(r->cso, shader.vs);
-   cso_set_fragment_shader_handle(r->cso, shader.fs);
-
-   r->buffer_size = 0;
-   r->attrs_per_vertex = 2;
-}
-
-struct pipe_resource *
-renderer_clone_texture(struct xorg_renderer *r,
-                       struct pipe_resource *src)
-{
-   enum pipe_format format;
-   struct pipe_context *pipe = r->pipe;
-   struct pipe_screen *screen = pipe->screen;
-   struct pipe_resource *pt;
-   struct pipe_resource templ;
-
-   /* the coming in texture should already have that invariance */
-   debug_assert(screen->is_format_supported(screen, src->format,
-                                            PIPE_TEXTURE_2D, 0,
-                                            PIPE_BIND_SAMPLER_VIEW));
-
-   format = src->format;
-
-   memset(&templ, 0, sizeof(templ));
-   templ.target = PIPE_TEXTURE_2D;
-   templ.format = format;
-   templ.last_level = 0;
-   templ.width0 = src->width0;
-   templ.height0 = src->height0;
-   templ.depth0 = 1;
-   templ.array_size = 1;
-   templ.bind = PIPE_BIND_SAMPLER_VIEW;
-
-   pt = screen->resource_create(screen, &templ);
-
-   debug_assert(!pt || pipe_is_referenced(&pt->reference));
-
-   if (!pt)
-      return NULL;
-
-   {
-      /* copy source framebuffer surface into texture */
-      struct pipe_box src_box;
-      u_box_origin_2d(src->width0, src->height0, &src_box);
-
-      pipe->resource_copy_region(pipe,
-                                 pt, /* dest */
-                                 0, /* dest_level */
-                                 0, 0, 0, /* destx/y/z */
-                                 src,
-                                 0, &src_box);
-   }
-
-   return pt;
-}
-
-
-void renderer_copy_pixmap(struct xorg_renderer *r,
-                          int dx, int dy,
-                          int sx, int sy,
-                          int width, int height,
-                          float src_width,
-                          float src_height)
-{
-   float s0, t0, s1, t1;
-   float x0, y0, x1, y1;
-
-
-   /* XXX: could put the texcoord scaling calculation into the vertex
-    * shader.
-    */
-   s0 = sx            / src_width;
-   s1 = (sx + width)  / src_width;
-   t0 = sy            / src_height;
-   t1 = (sy + height) / src_height;
-
-   x0 = dx;
-   x1 = dx + width;
-   y0 = dy;
-   y1 = dy + height;
-
-   /* draw quad */
-   renderer_draw_conditional(r, 4*8);
-   add_vertex_1tex(r, x0, y0, s0, t0);
-   add_vertex_1tex(r, x1, y0, s1, t0);
-   add_vertex_1tex(r, x1, y1, s1, t1);
-   add_vertex_1tex(r, x0, y1, s0, t1);
-}
-
-
-
 
 void renderer_draw_yuv(struct xorg_renderer *r,
                        float src_x, float src_y, float src_w, float src_h,
diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.h b/src/gallium/state_trackers/xorg/xorg_renderer.h
index fb09fab..b652aeb 100644
--- a/src/gallium/state_trackers/xorg/xorg_renderer.h
+++ b/src/gallium/state_trackers/xorg/xorg_renderer.h
@@ -77,20 +77,5 @@ void renderer_texture(struct xorg_renderer *r,
 
 void renderer_draw_flush(struct xorg_renderer *r);
 
-struct pipe_resource *
-renderer_clone_texture(struct xorg_renderer *r,
-                       struct pipe_resource *src);
-
-void renderer_copy_prepare(struct xorg_renderer *r,
-                           struct pipe_surface *dst_surface,
-                           struct pipe_resource *src_texture);
-
-void renderer_copy_pixmap(struct xorg_renderer *r,
-                          int dx, int dy,
-                          int sx, int sy,
-                          int width, int height,
-                          float src_width,
-                          float src_height);
-
 
 #endif
-- 
1.7.5.4




More information about the mesa-dev mailing list