st/xorg: split copy operation into prepare/copy/done phases
authorKeith Whitwell <keithw@vmware.com>
Thu, 26 Nov 2009 11:17:06 +0000 (11:17 +0000)
committerKeith Whitwell <keithw@vmware.com>
Thu, 26 Nov 2009 11:23:37 +0000 (11:23 +0000)
Any high-overhead one-off tasks are moved into the prepare hook.

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
src/gallium/state_trackers/xorg/xorg_xv.c

index 336be3f301873f16b5214eacaa02106acf237d1e..b55e161b5255f4bc5cc95d6949b8f462f241c3a0 100644 (file)
@@ -430,8 +430,17 @@ ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
 
     exa->copy.src = src_priv;
     exa->copy.dst = priv;
-    
-    if (0 && exa->pipe->surface_copy) {
+
+    /* For same-surface copies, the pipe->surface_copy path is clearly
+     * superior, providing it is implemented.  In other cases it's not
+     * clear what the better path would be, and eventually we'd
+     * probably want to gather timings and choose dynamically.
+     */
+    if (exa->pipe->surface_copy &&
+        exa->copy.src == exa->copy.dst) {
+
+       exa->copy.use_surface_copy = TRUE;
+       
        exa->copy.src_surface =
           exa->scrn->get_tex_surface( exa->scrn,
                                       exa->copy.src->tex,
@@ -444,6 +453,27 @@ ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
                                       0, 0, 0, 
                                       PIPE_BUFFER_USAGE_GPU_WRITE );
     }
+    else {
+       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_texture_reference(&exa->copy.src_texture,
+                                 exa->copy.src->tex);
+
+       exa->copy.dst_surface =
+          exa->scrn->get_tex_surface(exa->scrn,
+                                     exa->copy.dst->tex,
+                                     0, 0, 0,
+                                     PIPE_BUFFER_USAGE_GPU_WRITE);
+
+
+       renderer_copy_prepare(exa->renderer, 
+                             exa->copy.dst_surface,
+                             exa->copy.src_texture );
+    }
 
 
     return exa->accel;
@@ -465,7 +495,7 @@ ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
 
    debug_assert(priv == exa->copy.dst);
 
-   if (exa->copy.src_surface && exa->copy.dst_surface) {
+   if (exa->copy.use_surface_copy) {
       /* XXX: consider exposing >1 box in surface_copy interface.
        */
       exa->pipe->surface_copy( exa->pipe,
@@ -476,9 +506,12 @@ ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
                              width, height );
    }
    else {
-      renderer_copy_pixmap(exa->renderer, exa->copy.dst, dstX, dstY,
-                           exa->copy.src, srcX, srcY,
-                           width, height);
+      renderer_copy_pixmap(exa->renderer, 
+                           dstX, dstY,
+                           srcX, srcY,
+                           width, height,
+                           exa->copy.src_texture->width[0],
+                           exa->copy.src_texture->height[0]);
    }
 }
 
@@ -499,6 +532,7 @@ ExaDoneCopy(PixmapPtr pPixmap)
    exa->copy.dst = NULL;
    pipe_surface_reference(&exa->copy.src_surface, NULL);
    pipe_surface_reference(&exa->copy.dst_surface, NULL);
+   pipe_texture_reference(&exa->copy.src_texture, NULL);
 }
 
 
index a67dda65a58274606210d4a43acd7f741b999572..0c29187486b653a8cbfb60f4bd429bf5a2765c45 100644 (file)
@@ -35,11 +35,15 @@ struct exa_context
    } transform;
 
    struct {
+      boolean use_surface_copy;
+
       struct exa_pixmap_priv *src;
       struct exa_pixmap_priv *dst;
 
       struct pipe_surface *src_surface;
       struct pipe_surface *dst_surface;
+
+      struct pipe_texture *src_texture;
    } copy;
 };
 
index 589942c9156def4e88d365955cbf1d84b15b7ff8..16ac5d204d9c1c70d15e4568cbcb70882f6ea04f 100644 (file)
@@ -195,23 +195,6 @@ add_vertex_data1(struct xorg_renderer *r,
    add_vertex_1tex(r, dstX, dstY + height, s3, t3);
 }
 
-static struct pipe_buffer *
-setup_vertex_data_tex(struct xorg_renderer *r,
-                      float x0, float y0, float x1, float y1,
-                      float s0, float t0, float s1, float t1,
-                      float z)
-{
-   /* 1st vertex */
-   add_vertex_1tex(r, x0, y0, s0, t0);
-   /* 2nd vertex */
-   add_vertex_1tex(r, x1, y0, s1, t0);
-   /* 3rd vertex */
-   add_vertex_1tex(r, x1, y1, s1, t1);
-   /* 4th vertex */
-   add_vertex_1tex(r, x0, y1, s0, t1);
-
-   return renderer_buffer_create(r);
-}
 
 static INLINE void
 add_vertex_2tex(struct xorg_renderer *r,
@@ -442,47 +425,15 @@ void renderer_set_constants(struct xorg_renderer *r,
 }
 
 
-static void renderer_copy_texture(struct xorg_renderer *r,
-                                  struct pipe_texture *src,
-                                  float sx1, float sy1,
-                                  float sx2, float sy2,
-                                  struct pipe_texture *dst,
-                                  float dx1, float dy1,
-                                  float dx2, float dy2)
+void renderer_copy_prepare(struct xorg_renderer *r,
+                           struct pipe_surface *dst_surface,
+                           struct pipe_texture *src_texture)
 {
    struct pipe_context *pipe = r->pipe;
    struct pipe_screen *screen = pipe->screen;
-   struct pipe_buffer *buf;
-   struct pipe_surface *dst_surf = screen->get_tex_surface(
-      screen, dst, 0, 0, 0,
-      PIPE_BUFFER_USAGE_GPU_WRITE);
-   float s0, t0, s1, t1;
    struct xorg_shader shader;
 
-   assert(src->width[0] != 0);
-   assert(src->height[0] != 0);
-   assert(dst->width[0] != 0);
-   assert(dst->height[0] != 0);
-
-#if 1
-   s0 = sx1 / src->width[0];
-   s1 = sx2 / src->width[0];
-   t0 = sy1 / src->height[0];
-   t1 = sy2 / src->height[0];
-#else
-   s0 = 0;
-   s1 = 1;
-   t0 = 0;
-   t1 = 1;
-#endif
-
-#if 0
-   debug_printf("copy texture src=[%f, %f, %f, %f], dst=[%f, %f, %f, %f], tex=[%f, %f, %f, %f]\n",
-                sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2,
-                s0, t0, s1, t1);
-#endif
-
-   assert(screen->is_format_supported(screen, dst_surf->format,
+   assert(screen->is_format_supported(screen, dst_surface->format,
                                       PIPE_TEXTURE_2D,
                                       PIPE_TEXTURE_USAGE_RENDER_TARGET,
                                       0));
@@ -515,10 +466,10 @@ static void renderer_copy_texture(struct xorg_renderer *r,
       cso_single_sampler_done(r->cso);
    }
 
-   renderer_bind_destination(r, dst_surf);
+   renderer_bind_destination(r, dst_surface);
 
    /* texture */
-   cso_set_sampler_textures(r->cso, 1, &src);
+   cso_set_sampler_textures(r->cso, 1, &src_texture);
 
    /* shaders */
    shader = xorg_shaders_get(r->shaders,
@@ -527,27 +478,12 @@ static void renderer_copy_texture(struct xorg_renderer *r,
    cso_set_vertex_shader_handle(r->cso, shader.vs);
    cso_set_fragment_shader_handle(r->cso, shader.fs);
 
-   /* draw quad */
-   buf = setup_vertex_data_tex(r,
-                               dx1, dy1,
-                               dx2, dy2,
-                               s0, t0, s1, t1,
-                               0.0f);
-
-   if (buf) {
-      util_draw_vertex_buffer(r->pipe, buf, 0,
-                              PIPE_PRIM_QUADS,
-                              4,  /* verts */
-                              2); /* attribs/vert */
-
-      pipe_buffer_reference(&buf, NULL);
-   }
-
-   pipe_surface_reference(&dst_surf, NULL);
+   r->buffer_size = 0;
+   r->attrs_per_vertex = 2;
 }
 
-static struct pipe_texture *
-create_sampler_texture(struct xorg_renderer *r,
+struct pipe_texture *
+renderer_clone_texture(struct xorg_renderer *r,
                        struct pipe_texture *src)
 {
    enum pipe_format format;
@@ -556,7 +492,9 @@ create_sampler_texture(struct xorg_renderer *r,
    struct pipe_texture *pt;
    struct pipe_texture templ;
 
-   pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+   if (pipe->is_texture_referenced(pipe, src, 0, 0) &
+       PIPE_REFERENCED_FOR_WRITE)
+      pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
 
    /* the coming in texture should already have that invariance */
    debug_assert(screen->is_format_supported(screen, src->format,
@@ -610,52 +548,40 @@ create_sampler_texture(struct xorg_renderer *r,
 
 
 void renderer_copy_pixmap(struct xorg_renderer *r,
-                          struct exa_pixmap_priv *dst_priv, int dx, int dy,
-                          struct exa_pixmap_priv *src_priv, int sx, int sy,
-                          int width, int height)
+                          int dx, int dy,
+                          int sx, int sy,
+                          int width, int height,
+                          float src_width,
+                          float src_height)
 {
-   float dst_loc[4], src_loc[4];
-   struct pipe_texture *dst = dst_priv->tex;
-   struct pipe_texture *src = src_priv->tex;
+   float s0, t0, s1, t1;
+   float x0, y0, x1, y1;
 
-   if (r->pipe->is_texture_referenced(r->pipe, src, 0, 0) &
-       PIPE_REFERENCED_FOR_WRITE)
-      r->pipe->flush(r->pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
-
-   dst_loc[0] = dx;
-   dst_loc[1] = dy;
-   dst_loc[2] = width;
-   dst_loc[3] = height;
-
-   src_loc[0] = sx;
-   src_loc[1] = sy;
-   src_loc[2] = width;
-   src_loc[3] = height;
-
-   if (src_loc[2] >= 0 && src_loc[3] >= 0 &&
-       dst_loc[2] >= 0 && dst_loc[3] >= 0) {
-      struct pipe_texture *temp_src = src;
-
-      if (src == dst)
-         temp_src = create_sampler_texture(r, src);
-
-      renderer_copy_texture(r,
-                            temp_src,
-                            src_loc[0],
-                            src_loc[1],
-                            src_loc[0] + src_loc[2],
-                            src_loc[1] + src_loc[3],
-                            dst,
-                            dst_loc[0],
-                            dst_loc[1],
-                            dst_loc[0] + dst_loc[2],
-                            dst_loc[1] + dst_loc[3]);
-
-      if (src == dst)
-         pipe_texture_reference(&temp_src, NULL);
-   }
+
+   /* 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,
                        int src_x, int src_y, int src_w, int src_h,
                        int dst_x, int dst_y, int dst_w, int dst_h,
index 249bb719b6a705f7c1e20962504ee27c08b94030..ba844bf06e4a6e397cf89a524fed65fbc37e85d9 100644 (file)
@@ -48,10 +48,6 @@ void renderer_set_constants(struct xorg_renderer *r,
                             int shader_type,
                             const float *buffer,
                             int size);
-void renderer_copy_pixmap(struct xorg_renderer *r,
-                          struct exa_pixmap_priv *dst_priv, int dx, int dy,
-                          struct exa_pixmap_priv *src_priv, int sx, int sy,
-                          int width, int height);
 
 
 void renderer_draw_yuv(struct xorg_renderer *r,
@@ -78,5 +74,20 @@ void renderer_texture(struct xorg_renderer *r,
 
 void renderer_draw_flush(struct xorg_renderer *r);
 
+struct pipe_texture *
+renderer_clone_texture(struct xorg_renderer *r,
+                       struct pipe_texture *src);
+
+void renderer_copy_prepare(struct xorg_renderer *r,
+                           struct pipe_surface *dst_surface,
+                           struct pipe_texture *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
index 7a43da89887d6fab3018b5cc739b4ce02479dd55..7c05c7af399f3629a2f5b5b7147a904f147f6485 100644 (file)
@@ -453,7 +453,6 @@ display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id,
 
    renderer_bind_destination(pPriv->r, dst_surf);
    bind_blend_state(pPriv);
-   renderer_bind_rasterizer(pPriv->r);
    bind_shaders(pPriv);
    bind_samplers(pPriv);
    setup_fs_video_constants(pPriv->r, hdtv);