[g3dvl] implement clearing of dirty destination surface areas
authorChristian König <deathsimple@vodafone.de>
Wed, 27 Apr 2011 13:17:24 +0000 (15:17 +0200)
committerChristian König <deathsimple@vodafone.de>
Wed, 27 Apr 2011 13:19:35 +0000 (15:19 +0200)
src/gallium/auxiliary/vl/vl_compositor.c
src/gallium/auxiliary/vl/vl_compositor.h

index 2f2b32d7944a311ab3c4e95632a3c07430c1e999..f6f7b65fd6b804b5c911785a443b9fa1f243f0d2 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <util/u_memory.h>
 #include <util/u_draw.h>
+#include <util/u_surface.h>
 
 #include <tgsi/tgsi_ureg.h>
 
@@ -302,6 +303,22 @@ static void cleanup_pipe_state(struct vl_compositor *c)
    c->pipe->delete_rasterizer_state(c->pipe, c->rast);
 }
 
+static bool
+create_vertex_buffer(struct vl_compositor *c)
+{
+   assert(c);
+
+   pipe_resource_reference(&c->vertex_buf.buffer, NULL);
+   c->vertex_buf.buffer = pipe_buffer_create
+   (
+      c->pipe->screen,
+      PIPE_BIND_VERTEX_BUFFER,
+      PIPE_USAGE_STREAM,
+      sizeof(struct vertex4f) * VL_COMPOSITOR_MAX_LAYERS * 4
+   );
+   return c->vertex_buf.buffer != NULL;
+}
+
 static bool
 init_buffers(struct vl_compositor *c)
 {
@@ -314,13 +331,7 @@ init_buffers(struct vl_compositor *c)
     */
    c->vertex_buf.stride = sizeof(struct vertex4f);
    c->vertex_buf.buffer_offset = 0;
-   c->vertex_buf.buffer = pipe_buffer_create
-   (
-      c->pipe->screen,
-      PIPE_BIND_VERTEX_BUFFER,
-      PIPE_USAGE_STREAM,
-      sizeof(struct vertex4f) * (VL_COMPOSITOR_MAX_LAYERS + 1) * 4
-   );
+   create_vertex_buffer(c);
 
    vertex_elems[0].src_offset = 0;
    vertex_elems[0].instance_divisor = 0;
@@ -431,13 +442,30 @@ gen_vertex_data(struct vl_compositor *c)
                         PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD | PIPE_TRANSFER_DONTBLOCK,
                         &buf_transfer);
 
-   if (!vb)
-      return;
+   if (!vb) {
+      // If buffer is still locked from last draw create a new one
+      create_vertex_buffer(c);
+      vb = pipe_buffer_map(c->pipe, c->vertex_buf.buffer,
+                           PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
+                           &buf_transfer);
+   }
 
    for (i = 0; i < VL_COMPOSITOR_MAX_LAYERS; i++) {
       if (c->used_layers & (1 << i)) {
-         gen_rect_verts(vb, &c->layers[i]);
+         struct vl_compositor_layer *layer = &c->layers[i];
+         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;
+         }
       }
    }
 
@@ -453,18 +481,36 @@ draw_layers(struct vl_compositor *c)
 
    for (i = 0, vb_index = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i) {
       if (c->used_layers & (1 << i)) {
-         struct pipe_sampler_view **samplers = &c->layers[i].sampler_views[0];
+         struct vl_compositor_layer *layer = &c->layers[i];
+         struct pipe_sampler_view **samplers = &layer->sampler_views[0];
          unsigned num_sampler_views = !samplers[1] ? 1 : !samplers[2] ? 2 : 3;
 
-         c->pipe->bind_fs_state(c->pipe, c->layers[i].fs);
-         c->pipe->bind_fragment_sampler_states(c->pipe, num_sampler_views, c->layers[i].samplers);
+         c->pipe->bind_fs_state(c->pipe, layer->fs);
+         c->pipe->bind_fragment_sampler_states(c->pipe, num_sampler_views, layer->samplers);
          c->pipe->set_fragment_sampler_views(c->pipe, num_sampler_views, samplers);
          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);
       }
    }
 }
 
+static void
+vl_compositor_reset_dirty_area(struct pipe_video_compositor *compositor)
+{
+   struct vl_compositor *c = (struct vl_compositor *)compositor;
+
+   assert(compositor);
+
+   c->dirty_tl.x = c->dirty_tl.y = 0.0f;
+   c->dirty_br.x = c->dirty_br.y = 1.0f;
+}
+
 static void
 vl_compositor_clear_layers(struct pipe_video_compositor *compositor)
 {
@@ -532,6 +578,7 @@ vl_compositor_set_buffer_layer(struct pipe_video_compositor *compositor,
    assert(layer < VL_COMPOSITOR_MAX_LAYERS);
 
    c->used_layers |= 1 << layer;
+   c->layers[layer].clearing = true;
    c->layers[layer].fs = c->fs_video_buffer;
 
    sampler_views = buffer->get_sampler_view_components(buffer);
@@ -559,6 +606,7 @@ vl_compositor_set_palette_layer(struct pipe_video_compositor *compositor,
    assert(layer < VL_COMPOSITOR_MAX_LAYERS);
 
    c->used_layers |= 1 << layer;
+   c->layers[layer].clearing = false;
    c->layers[layer].fs = c->fs_palette;
    c->layers[layer].samplers[0] = c->sampler_linear;
    c->layers[layer].samplers[1] = c->sampler_nearest;
@@ -585,6 +633,7 @@ vl_compositor_set_rgba_layer(struct pipe_video_compositor *compositor,
    assert(layer < VL_COMPOSITOR_MAX_LAYERS);
 
    c->used_layers |= 1 << layer;
+   c->layers[layer].clearing = false;
    c->layers[layer].fs = c->fs_rgba;
    c->layers[layer].samplers[0] = c->sampler_linear;
    c->layers[layer].samplers[1] = NULL;
@@ -606,6 +655,7 @@ vl_compositor_render(struct pipe_video_compositor *compositor,
 {
    struct vl_compositor *c = (struct vl_compositor *)compositor;
    struct pipe_scissor_state scissor;
+   float clearcolor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
 
    assert(compositor);
    assert(dst_surface);
@@ -631,6 +681,12 @@ vl_compositor_render(struct pipe_video_compositor *compositor,
 
    gen_vertex_data(c);
 
+   if (c->dirty_tl.x < c->dirty_br.x || c->dirty_tl.y < c->dirty_br.y) {
+      util_clear_render_target(c->pipe, dst_surface, clearcolor, 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;
+   }
+
    c->pipe->set_scissor_state(c->pipe, &scissor);
    c->pipe->set_framebuffer_state(c->pipe, &c->fb_state);
    c->pipe->set_viewport_state(c->pipe, &c->viewport);
@@ -682,6 +738,7 @@ vl_compositor_init(struct pipe_video_context *vpipe, struct pipe_context *pipe)
 
    vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY, NULL, true, csc_matrix);
    vl_compositor_set_csc_matrix(&compositor->base, csc_matrix);
+   vl_compositor_reset_dirty_area(&compositor->base);
 
    return &compositor->base;
 }
index 339ea415e8ac125f608f95084f73057f895253f1..725dcc15a136d5a61d6d1b25fca4d8699700e16f 100644 (file)
@@ -40,8 +40,11 @@ struct pipe_context;
 
 struct vl_compositor_layer
 {
+   bool clearing;
+
    void *fs;
    void *samplers[3];
+
    struct pipe_sampler_view *sampler_views[3];
    struct {
       struct vertex2f tl, br;
@@ -69,6 +72,8 @@ struct vl_compositor
    void *fs_palette;
    void *fs_rgba;
 
+   struct vertex2f dirty_tl, dirty_br;
+
    unsigned used_layers:VL_COMPOSITOR_MAX_LAYERS;
    struct vl_compositor_layer layers[VL_COMPOSITOR_MAX_LAYERS];
 };