[g3dvl] implement clearing of dirty destination surface areas

This commit is contained in:
Christian König 2011-04-27 15:17:24 +02:00
parent 6092fbed46
commit 0d53cb2e83
2 changed files with 75 additions and 13 deletions

View 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;
}

View 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];
};