st/xorg: Better handling of EXA copies.
authorMichel Dänzer <michel.daenzer@amd.com>
Wed, 16 May 2012 15:45:10 +0000 (17:45 +0200)
committerMichel Dänzer <michel@daenzer.net>
Wed, 16 May 2012 16:30:39 +0000 (18:30 +0200)
Always use the resource_copy_region hook. If a source and destination rectangle
overlap, copy to/from a temporary pixmap.

src/gallium/state_trackers/xorg/xorg_exa.c
src/gallium/state_trackers/xorg/xorg_exa.h
src/gallium/state_trackers/xorg/xorg_renderer.c
src/gallium/state_trackers/xorg/xorg_renderer.h

index db0167ba4c45efca94d0068862640b1f42c4ec47..fa84298855e9fa3b4d0b5173cb5c2e719286e2c3 100644 (file)
@@ -462,41 +462,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;
 }
 
@@ -507,32 +472,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
@@ -548,12 +534,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");
 }
index 47501f9affe0cad688a1743a63b4a095a4ee835a..e8f7c9f66fcc082f0e641cf48d58daa80e74561a 100644 (file)
@@ -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;
 };
 
index ca25b0912f11c109b9ca50e2fa077582d663bcec..bf2d5b75dd74c10740786a067fd86113c23976f1 100644 (file)
@@ -414,156 +414,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,
index fb09fabe156966dbdfdb60a54aa046e00e47ce6b..b652aeb7d0c4a0ffd7d42ce197ab562d60a9d5ca 100644 (file)
@@ -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