From: Christian König Date: Mon, 12 Dec 2011 14:27:34 +0000 (+0100) Subject: g3dvl/compositor: improve dirty area handling X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=167b1b32c5ff30d514253072ce54513112c03d4d;p=mesa.git 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 --- diff --git a/src/gallium/auxiliary/vl/vl_compositor.c b/src/gallium/auxiliary/vl/vl_compositor.c index 322ef8e9954..98cb6167f88 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 f60f7da3ec1..05482035b4d 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 ed5a6464088..5657e7c83b0 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 0d2f35a433c..d83831e5dd2 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 888cf31d5af..df38f637de9 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 aae6f7841a6..eba9e2f2d37 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 e6c5a898b05..bb7ba1e1ed2 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 305e51fb416..5656c65dc59 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;