Mesa (master): g3dvl/compositor: improve dirty area handling

Christian König deathsimple at kemper.freedesktop.org
Wed Dec 14 13:38:18 UTC 2011


Module: Mesa
Branch: master
Commit: 167b1b32c5ff30d514253072ce54513112c03d4d
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=167b1b32c5ff30d514253072ce54513112c03d4d

Author: Christian König <deathsimple at vodafone.de>
Date:   Mon Dec 12 15:27:34 2011 +0100

g3dvl/compositor: improve dirty area handling

Take viewport and scissors into account and make
the dirty area a parameter instead of a member.

Signed-off-by: Christian König <deathsimple at vodafone.de>

---

 src/gallium/auxiliary/vl/vl_compositor.c           |  104 ++++++++++++--------
 src/gallium/auxiliary/vl/vl_compositor.h           |    8 +-
 src/gallium/state_trackers/vdpau/mixer.c           |    2 +-
 src/gallium/state_trackers/vdpau/output.c          |    2 +-
 src/gallium/state_trackers/vdpau/presentation.c    |    4 +-
 src/gallium/state_trackers/vdpau/vdpau_private.h   |    2 +
 src/gallium/state_trackers/xorg/xvmc/surface.c     |    4 +-
 .../state_trackers/xorg/xvmc/xvmc_private.h        |    2 +
 8 files changed, 81 insertions(+), 47 deletions(-)

diff --git a/src/gallium/auxiliary/vl/vl_compositor.c b/src/gallium/auxiliary/vl/vl_compositor.c
index 322ef8e..98cb616 100644
--- a/src/gallium/auxiliary/vl/vl_compositor.c
+++ b/src/gallium/auxiliary/vl/vl_compositor.c
@@ -40,6 +40,9 @@
 #include "vl_types.h"
 #include "vl_compositor.h"
 
+#define MIN_DIRTY (0)
+#define MAX_DIRTY (1 << 15)
+
 typedef float csc_matrix[16];
 
 static void *
@@ -470,8 +473,27 @@ gen_rect_verts(struct vertex4f *vb, struct vl_compositor_layer *layer)
    vb[3].w = layer->src.br.y;
 }
 
+static INLINE struct u_rect
+calc_drawn_area(struct vl_compositor *c, struct vl_compositor_layer *layer)
+{
+   struct u_rect result;
+
+   // scale
+   result.x0 = layer->dst.tl.x * c->viewport.scale[0] + c->viewport.translate[0];
+   result.y0 = layer->dst.tl.y * c->viewport.scale[1] + c->viewport.translate[1];
+   result.x1 = layer->dst.br.x * c->viewport.scale[0] + c->viewport.translate[0];
+   result.y1 = layer->dst.br.y * c->viewport.scale[1] + c->viewport.translate[1];
+
+   // and clip
+   result.x0 = MAX2(result.x0, c->scissor.minx);
+   result.y0 = MAX2(result.y0, c->scissor.miny);
+   result.x1 = MIN2(result.x1, c->scissor.maxx);
+   result.y1 = MIN2(result.y1, c->scissor.maxy);
+   return result;
+}
+
 static void
-gen_vertex_data(struct vl_compositor *c)
+gen_vertex_data(struct vl_compositor *c, struct u_rect *dirty)
 {
    struct vertex4f *vb;
    struct pipe_transfer *buf_transfer;
@@ -497,15 +519,18 @@ gen_vertex_data(struct vl_compositor *c)
          gen_rect_verts(vb, layer);
          vb += 4;
 
-         if (layer->clearing &&
-             c->dirty_tl.x >= layer->dst.tl.x &&
-             c->dirty_tl.y >= layer->dst.tl.y &&
-             c->dirty_br.x <= layer->dst.br.x &&
-             c->dirty_br.y <= layer->dst.br.y) {
-
-            // We clear the dirty area anyway, no need for clear_render_target
-            c->dirty_tl.x = c->dirty_tl.y = 1.0f;
-            c->dirty_br.x = c->dirty_br.y = 0.0f;
+         if (dirty && layer->clearing) {
+            struct u_rect drawn = calc_drawn_area(c, layer);
+            if (
+             dirty->x0 >= drawn.x0 &&
+             dirty->y0 >= drawn.y0 &&
+             dirty->x1 <= drawn.x1 &&
+             dirty->y1 <= drawn.y1) {
+
+               // We clear the dirty area anyway, no need for clear_render_target
+               dirty->x0 = dirty->y0 = MAX_DIRTY;
+               dirty->x1 = dirty->y1 = MIN_DIRTY;
+            }
          }
       }
    }
@@ -514,7 +539,7 @@ gen_vertex_data(struct vl_compositor *c)
 }
 
 static void
-draw_layers(struct vl_compositor *c)
+draw_layers(struct vl_compositor *c, struct u_rect *dirty)
 {
    unsigned vb_index, i;
 
@@ -533,22 +558,25 @@ draw_layers(struct vl_compositor *c)
          util_draw_arrays(c->pipe, PIPE_PRIM_QUADS, vb_index * 4, 4);
          vb_index++;
 
-         // Remember the currently drawn area as dirty for the next draw command
-         c->dirty_tl.x = MIN2(layer->dst.tl.x, c->dirty_tl.x);
-         c->dirty_tl.y = MIN2(layer->dst.tl.y, c->dirty_tl.y);
-         c->dirty_br.x = MAX2(layer->dst.br.x, c->dirty_br.x);
-         c->dirty_br.y = MAX2(layer->dst.br.y, c->dirty_br.y);
+         if (dirty) {
+            // Remember the currently drawn area as dirty for the next draw command
+            struct u_rect drawn = calc_drawn_area(c, layer);
+            dirty->x0 = MIN2(drawn.x0, dirty->x0);
+            dirty->y0 = MIN2(drawn.y0, dirty->y0);
+            dirty->x1 = MAX2(drawn.x1, dirty->x1);
+            dirty->y1 = MAX2(drawn.y1, dirty->y1);
+         }
       }
    }
 }
 
 void
-vl_compositor_reset_dirty_area(struct vl_compositor *c)
+vl_compositor_reset_dirty_area(struct u_rect *dirty)
 {
-   assert(c);
+   assert(dirty);
 
-   c->dirty_tl.x = c->dirty_tl.y = 0.0f;
-   c->dirty_br.x = c->dirty_br.y = 1.0f;
+   dirty->x0 = dirty->y0 = MIN_DIRTY;
+   dirty->x1 = dirty->y1 = MAX_DIRTY;
 }
 
 void
@@ -715,10 +743,8 @@ vl_compositor_render(struct vl_compositor   *c,
                      struct pipe_surface    *dst_surface,
                      struct pipe_video_rect *dst_area,
                      struct pipe_video_rect *dst_clip,
-                     bool clear_dirty_area)
+                     struct u_rect          *dirty_area)
 {
-   struct pipe_scissor_state scissor;
-
    assert(c);
    assert(dst_surface);
 
@@ -739,28 +765,29 @@ vl_compositor_render(struct vl_compositor   *c,
    }
 
    if (dst_clip) {
-      scissor.minx = dst_clip->x;
-      scissor.miny = dst_clip->y;
-      scissor.maxx = dst_clip->x + dst_clip->w;
-      scissor.maxy = dst_clip->y + dst_clip->h;
+      c->scissor.minx = dst_clip->x;
+      c->scissor.miny = dst_clip->y;
+      c->scissor.maxx = dst_clip->x + dst_clip->w;
+      c->scissor.maxy = dst_clip->y + dst_clip->h;
    } else {
-      scissor.minx = 0;
-      scissor.miny = 0;
-      scissor.maxx = dst_surface->width;
-      scissor.maxy = dst_surface->height;
+      c->scissor.minx = 0;
+      c->scissor.miny = 0;
+      c->scissor.maxx = dst_surface->width;
+      c->scissor.maxy = dst_surface->height;
    }
 
-   gen_vertex_data(c);
+   gen_vertex_data(c, dirty_area);
+
+   if (dirty_area && (dirty_area->x0 < dirty_area->x1 ||
+                      dirty_area->y0 < dirty_area->y1)) {
 
-   if (clear_dirty_area && (c->dirty_tl.x < c->dirty_br.x ||
-                            c->dirty_tl.y < c->dirty_br.y)) {
       util_clear_render_target(c->pipe, dst_surface, &c->clear_color,
                                0, 0, dst_surface->width, dst_surface->height);
-      c->dirty_tl.x = c->dirty_tl.y = 1.0f;
-      c->dirty_br.x = c->dirty_br.y = 0.0f;
+      dirty_area->x0 = dirty_area->y0 = MAX_DIRTY;
+      dirty_area->x0 = dirty_area->y1 = MIN_DIRTY;
    }
 
-   c->pipe->set_scissor_state(c->pipe, &scissor);
+   c->pipe->set_scissor_state(c->pipe, &c->scissor);
    c->pipe->set_framebuffer_state(c->pipe, &c->fb_state);
    c->pipe->set_viewport_state(c->pipe, &c->viewport);
    c->pipe->bind_vs_state(c->pipe, c->vs);
@@ -769,7 +796,7 @@ vl_compositor_render(struct vl_compositor   *c,
    c->pipe->set_constant_buffer(c->pipe, PIPE_SHADER_FRAGMENT, 0, c->csc_matrix);
    c->pipe->bind_rasterizer_state(c->pipe, c->rast);
 
-   draw_layers(c);
+   draw_layers(c, dirty_area);
 }
 
 bool
@@ -800,7 +827,6 @@ vl_compositor_init(struct vl_compositor *c, struct pipe_context *pipe)
 
    c->clear_color.f[0] = c->clear_color.f[1] = 0.0f;
    c->clear_color.f[2] = c->clear_color.f[3] = 0.0f;
-   vl_compositor_reset_dirty_area(c);
 
    return true;
 }
diff --git a/src/gallium/auxiliary/vl/vl_compositor.h b/src/gallium/auxiliary/vl/vl_compositor.h
index f60f7da..0548203 100644
--- a/src/gallium/auxiliary/vl/vl_compositor.h
+++ b/src/gallium/auxiliary/vl/vl_compositor.h
@@ -32,6 +32,8 @@
 #include "pipe/p_video_decoder.h"
 #include "pipe/p_video_state.h"
 
+#include "util/u_rect.h"
+
 #include "vl_types.h"
 
 struct pipe_context;
@@ -62,6 +64,7 @@ struct vl_compositor
 
    struct pipe_framebuffer_state fb_state;
    struct pipe_viewport_state viewport;
+   struct pipe_scissor_state scissor;
    struct pipe_vertex_buffer vertex_buf;
    struct pipe_resource *csc_matrix;
 
@@ -82,7 +85,6 @@ struct vl_compositor
    } fs_palette;
 
    union pipe_color_union clear_color;
-   struct vertex2f dirty_tl, dirty_br;
 
    unsigned used_layers:VL_COMPOSITOR_MAX_LAYERS;
    struct vl_compositor_layer layers[VL_COMPOSITOR_MAX_LAYERS];
@@ -104,7 +106,7 @@ vl_compositor_set_csc_matrix(struct vl_compositor *compositor, const float mat[1
  * reset dirty area, so it's cleared with the clear colour
  */
 void
-vl_compositor_reset_dirty_area(struct vl_compositor *compositor);
+vl_compositor_reset_dirty_area(struct u_rect *dirty);
 
 /**
  * set the clear color
@@ -178,7 +180,7 @@ vl_compositor_render(struct vl_compositor   *compositor,
                      struct pipe_surface    *dst_surface,
                      struct pipe_video_rect *dst_area,
                      struct pipe_video_rect *dst_clip,
-                     bool clear_dirty_area);
+                     struct u_rect          *dirty_area);
 
 /**
  * destroy this compositor
diff --git a/src/gallium/state_trackers/vdpau/mixer.c b/src/gallium/state_trackers/vdpau/mixer.c
index ed5a646..5657e7c 100644
--- a/src/gallium/state_trackers/vdpau/mixer.c
+++ b/src/gallium/state_trackers/vdpau/mixer.c
@@ -173,7 +173,7 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer,
    vl_compositor_clear_layers(&vmixer->compositor);
    vl_compositor_set_buffer_layer(&vmixer->compositor, 0, surf->video_buffer,
                                   RectToPipe(video_source_rect, &src_rect), NULL);
-   vl_compositor_render(&vmixer->compositor, dst->surface, NULL, NULL, false);
+   vl_compositor_render(&vmixer->compositor, dst->surface, NULL, NULL, NULL);
 
    return VDP_STATUS_OK;
 }
diff --git a/src/gallium/state_trackers/vdpau/output.c b/src/gallium/state_trackers/vdpau/output.c
index 0d2f35a..d83831e 100644
--- a/src/gallium/state_trackers/vdpau/output.c
+++ b/src/gallium/state_trackers/vdpau/output.c
@@ -312,7 +312,7 @@ vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface,
    vl_compositor_clear_layers(compositor);
    vl_compositor_set_palette_layer(compositor, 0, sv_idx, sv_tbl, NULL, NULL, false);
    vl_compositor_render(compositor, vlsurface->surface,
-                        RectToPipe(destination_rect, &dst_rect), NULL, false);
+                        RectToPipe(destination_rect, &dst_rect), NULL, NULL);
 
    pipe_sampler_view_reference(&sv_idx, NULL);
    pipe_sampler_view_reference(&sv_tbl, NULL);
diff --git a/src/gallium/state_trackers/vdpau/presentation.c b/src/gallium/state_trackers/vdpau/presentation.c
index 888cf31..df38f63 100644
--- a/src/gallium/state_trackers/vdpau/presentation.c
+++ b/src/gallium/state_trackers/vdpau/presentation.c
@@ -75,6 +75,8 @@ vlVdpPresentationQueueCreate(VdpDevice device,
       goto no_compositor;
    }
 
+   vl_compositor_reset_dirty_area(&pq->dirty_area);
+
    *presentation_queue = vlAddDataHTAB(pq);
    if (*presentation_queue == 0) {
       ret = VDP_STATUS_ERROR;
@@ -234,7 +236,7 @@ vlVdpPresentationQueueDisplay(VdpPresentationQueue presentation_queue,
 
    vl_compositor_clear_layers(&pq->compositor);
    vl_compositor_set_rgba_layer(&pq->compositor, 0, surf->sampler_view, NULL, NULL);
-   vl_compositor_render(&pq->compositor, drawable_surface, NULL, &vo_rect, true);
+   vl_compositor_render(&pq->compositor, drawable_surface, NULL, &vo_rect, &pq->dirty_area);
 
    pipe = pq->device->context->pipe;
 
diff --git a/src/gallium/state_trackers/vdpau/vdpau_private.h b/src/gallium/state_trackers/vdpau/vdpau_private.h
index aae6f78..eba9e2f 100644
--- a/src/gallium/state_trackers/vdpau/vdpau_private.h
+++ b/src/gallium/state_trackers/vdpau/vdpau_private.h
@@ -37,6 +37,7 @@
 #include "pipe/p_video_decoder.h"
 
 #include "util/u_debug.h"
+#include "util/u_rect.h"
 #include "vl/vl_compositor.h"
 
 #include "vl_winsys.h"
@@ -298,6 +299,7 @@ typedef struct
    vlVdpDevice *device;
    Drawable drawable;
    struct vl_compositor compositor;
+   struct u_rect dirty_area;
 } vlVdpPresentationQueue;
 
 typedef struct
diff --git a/src/gallium/state_trackers/xorg/xvmc/surface.c b/src/gallium/state_trackers/xorg/xvmc/surface.c
index e6c5a89..bb7ba1e 100644
--- a/src/gallium/state_trackers/xorg/xvmc/surface.c
+++ b/src/gallium/state_trackers/xorg/xvmc/surface.c
@@ -381,7 +381,7 @@ Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
       pipe_surface_reference(&context_priv->drawable_surface, NULL);
       context_priv->drawable_surface = vl_drawable_surface_get(context_priv->vctx, drawable);
       context_priv->dst_rect = dst_rect;
-      vl_compositor_reset_dirty_area(compositor);
+      vl_compositor_reset_dirty_area(&context_priv->dirty_area);
    }
 
    if (!context_priv->drawable_surface)
@@ -425,7 +425,7 @@ Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
    // Workaround for r600g, there seems to be a bug in the fence refcounting code
    pipe->screen->fence_reference(pipe->screen, &surface_priv->fence, NULL);
 
-   vl_compositor_render(compositor, context_priv->drawable_surface, &dst_rect, NULL, true);
+   vl_compositor_render(compositor, context_priv->drawable_surface, &dst_rect, NULL, &context_priv->dirty_area);
                         
    pipe->flush(pipe, &surface_priv->fence);
 
diff --git a/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h b/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h
index 305e51f..5656c65 100644
--- a/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h
+++ b/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h
@@ -35,6 +35,7 @@
 
 #include "util/u_debug.h"
 #include "util/u_math.h"
+#include "util/u_rect.h"
 
 #include "vl/vl_csc.h"
 #include "vl/vl_compositor.h"
@@ -64,6 +65,7 @@ typedef struct
 
    struct pipe_video_rect dst_rect;
    struct pipe_surface *drawable_surface;
+   struct u_rect dirty_area;
 
 } XvMCContextPrivate;
 




More information about the mesa-commit mailing list