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@vodafone.de>
This commit is contained in:
parent
606d3a3c3d
commit
167b1b32c5
|
@ -40,6 +40,9 @@
|
||||||
#include "vl_types.h"
|
#include "vl_types.h"
|
||||||
#include "vl_compositor.h"
|
#include "vl_compositor.h"
|
||||||
|
|
||||||
|
#define MIN_DIRTY (0)
|
||||||
|
#define MAX_DIRTY (1 << 15)
|
||||||
|
|
||||||
typedef float csc_matrix[16];
|
typedef float csc_matrix[16];
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
|
@ -470,8 +473,27 @@ gen_rect_verts(struct vertex4f *vb, struct vl_compositor_layer *layer)
|
||||||
vb[3].w = layer->src.br.y;
|
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
|
static void
|
||||||
gen_vertex_data(struct vl_compositor *c)
|
gen_vertex_data(struct vl_compositor *c, struct u_rect *dirty)
|
||||||
{
|
{
|
||||||
struct vertex4f *vb;
|
struct vertex4f *vb;
|
||||||
struct pipe_transfer *buf_transfer;
|
struct pipe_transfer *buf_transfer;
|
||||||
|
@ -497,15 +519,18 @@ gen_vertex_data(struct vl_compositor *c)
|
||||||
gen_rect_verts(vb, layer);
|
gen_rect_verts(vb, layer);
|
||||||
vb += 4;
|
vb += 4;
|
||||||
|
|
||||||
if (layer->clearing &&
|
if (dirty && layer->clearing) {
|
||||||
c->dirty_tl.x >= layer->dst.tl.x &&
|
struct u_rect drawn = calc_drawn_area(c, layer);
|
||||||
c->dirty_tl.y >= layer->dst.tl.y &&
|
if (
|
||||||
c->dirty_br.x <= layer->dst.br.x &&
|
dirty->x0 >= drawn.x0 &&
|
||||||
c->dirty_br.y <= layer->dst.br.y) {
|
dirty->y0 >= drawn.y0 &&
|
||||||
|
dirty->x1 <= drawn.x1 &&
|
||||||
|
dirty->y1 <= drawn.y1) {
|
||||||
|
|
||||||
// We clear the dirty area anyway, no need for clear_render_target
|
// We clear the dirty area anyway, no need for clear_render_target
|
||||||
c->dirty_tl.x = c->dirty_tl.y = 1.0f;
|
dirty->x0 = dirty->y0 = MAX_DIRTY;
|
||||||
c->dirty_br.x = c->dirty_br.y = 0.0f;
|
dirty->x1 = dirty->y1 = MIN_DIRTY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -514,7 +539,7 @@ gen_vertex_data(struct vl_compositor *c)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
draw_layers(struct vl_compositor *c)
|
draw_layers(struct vl_compositor *c, struct u_rect *dirty)
|
||||||
{
|
{
|
||||||
unsigned vb_index, i;
|
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);
|
util_draw_arrays(c->pipe, PIPE_PRIM_QUADS, vb_index * 4, 4);
|
||||||
vb_index++;
|
vb_index++;
|
||||||
|
|
||||||
// Remember the currently drawn area as dirty for the next draw command
|
if (dirty) {
|
||||||
c->dirty_tl.x = MIN2(layer->dst.tl.x, c->dirty_tl.x);
|
// Remember the currently drawn area as dirty for the next draw command
|
||||||
c->dirty_tl.y = MIN2(layer->dst.tl.y, c->dirty_tl.y);
|
struct u_rect drawn = calc_drawn_area(c, layer);
|
||||||
c->dirty_br.x = MAX2(layer->dst.br.x, c->dirty_br.x);
|
dirty->x0 = MIN2(drawn.x0, dirty->x0);
|
||||||
c->dirty_br.y = MAX2(layer->dst.br.y, c->dirty_br.y);
|
dirty->y0 = MIN2(drawn.y0, dirty->y0);
|
||||||
|
dirty->x1 = MAX2(drawn.x1, dirty->x1);
|
||||||
|
dirty->y1 = MAX2(drawn.y1, dirty->y1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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;
|
dirty->x0 = dirty->y0 = MIN_DIRTY;
|
||||||
c->dirty_br.x = c->dirty_br.y = 1.0f;
|
dirty->x1 = dirty->y1 = MAX_DIRTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -715,10 +743,8 @@ vl_compositor_render(struct vl_compositor *c,
|
||||||
struct pipe_surface *dst_surface,
|
struct pipe_surface *dst_surface,
|
||||||
struct pipe_video_rect *dst_area,
|
struct pipe_video_rect *dst_area,
|
||||||
struct pipe_video_rect *dst_clip,
|
struct pipe_video_rect *dst_clip,
|
||||||
bool clear_dirty_area)
|
struct u_rect *dirty_area)
|
||||||
{
|
{
|
||||||
struct pipe_scissor_state scissor;
|
|
||||||
|
|
||||||
assert(c);
|
assert(c);
|
||||||
assert(dst_surface);
|
assert(dst_surface);
|
||||||
|
|
||||||
|
@ -739,28 +765,29 @@ vl_compositor_render(struct vl_compositor *c,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dst_clip) {
|
if (dst_clip) {
|
||||||
scissor.minx = dst_clip->x;
|
c->scissor.minx = dst_clip->x;
|
||||||
scissor.miny = dst_clip->y;
|
c->scissor.miny = dst_clip->y;
|
||||||
scissor.maxx = dst_clip->x + dst_clip->w;
|
c->scissor.maxx = dst_clip->x + dst_clip->w;
|
||||||
scissor.maxy = dst_clip->y + dst_clip->h;
|
c->scissor.maxy = dst_clip->y + dst_clip->h;
|
||||||
} else {
|
} else {
|
||||||
scissor.minx = 0;
|
c->scissor.minx = 0;
|
||||||
scissor.miny = 0;
|
c->scissor.miny = 0;
|
||||||
scissor.maxx = dst_surface->width;
|
c->scissor.maxx = dst_surface->width;
|
||||||
scissor.maxy = dst_surface->height;
|
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,
|
util_clear_render_target(c->pipe, dst_surface, &c->clear_color,
|
||||||
0, 0, dst_surface->width, dst_surface->height);
|
0, 0, dst_surface->width, dst_surface->height);
|
||||||
c->dirty_tl.x = c->dirty_tl.y = 1.0f;
|
dirty_area->x0 = dirty_area->y0 = MAX_DIRTY;
|
||||||
c->dirty_br.x = c->dirty_br.y = 0.0f;
|
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_framebuffer_state(c->pipe, &c->fb_state);
|
||||||
c->pipe->set_viewport_state(c->pipe, &c->viewport);
|
c->pipe->set_viewport_state(c->pipe, &c->viewport);
|
||||||
c->pipe->bind_vs_state(c->pipe, c->vs);
|
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->set_constant_buffer(c->pipe, PIPE_SHADER_FRAGMENT, 0, c->csc_matrix);
|
||||||
c->pipe->bind_rasterizer_state(c->pipe, c->rast);
|
c->pipe->bind_rasterizer_state(c->pipe, c->rast);
|
||||||
|
|
||||||
draw_layers(c);
|
draw_layers(c, dirty_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
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[0] = c->clear_color.f[1] = 0.0f;
|
||||||
c->clear_color.f[2] = c->clear_color.f[3] = 0.0f;
|
c->clear_color.f[2] = c->clear_color.f[3] = 0.0f;
|
||||||
vl_compositor_reset_dirty_area(c);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
#include "pipe/p_video_decoder.h"
|
#include "pipe/p_video_decoder.h"
|
||||||
#include "pipe/p_video_state.h"
|
#include "pipe/p_video_state.h"
|
||||||
|
|
||||||
|
#include "util/u_rect.h"
|
||||||
|
|
||||||
#include "vl_types.h"
|
#include "vl_types.h"
|
||||||
|
|
||||||
struct pipe_context;
|
struct pipe_context;
|
||||||
|
@ -62,6 +64,7 @@ struct vl_compositor
|
||||||
|
|
||||||
struct pipe_framebuffer_state fb_state;
|
struct pipe_framebuffer_state fb_state;
|
||||||
struct pipe_viewport_state viewport;
|
struct pipe_viewport_state viewport;
|
||||||
|
struct pipe_scissor_state scissor;
|
||||||
struct pipe_vertex_buffer vertex_buf;
|
struct pipe_vertex_buffer vertex_buf;
|
||||||
struct pipe_resource *csc_matrix;
|
struct pipe_resource *csc_matrix;
|
||||||
|
|
||||||
|
@ -82,7 +85,6 @@ struct vl_compositor
|
||||||
} fs_palette;
|
} fs_palette;
|
||||||
|
|
||||||
union pipe_color_union clear_color;
|
union pipe_color_union clear_color;
|
||||||
struct vertex2f dirty_tl, dirty_br;
|
|
||||||
|
|
||||||
unsigned used_layers:VL_COMPOSITOR_MAX_LAYERS;
|
unsigned used_layers:VL_COMPOSITOR_MAX_LAYERS;
|
||||||
struct vl_compositor_layer 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
|
* reset dirty area, so it's cleared with the clear colour
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
vl_compositor_reset_dirty_area(struct vl_compositor *compositor);
|
vl_compositor_reset_dirty_area(struct u_rect *dirty);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set the clear color
|
* set the clear color
|
||||||
|
@ -178,7 +180,7 @@ vl_compositor_render(struct vl_compositor *compositor,
|
||||||
struct pipe_surface *dst_surface,
|
struct pipe_surface *dst_surface,
|
||||||
struct pipe_video_rect *dst_area,
|
struct pipe_video_rect *dst_area,
|
||||||
struct pipe_video_rect *dst_clip,
|
struct pipe_video_rect *dst_clip,
|
||||||
bool clear_dirty_area);
|
struct u_rect *dirty_area);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* destroy this compositor
|
* destroy this compositor
|
||||||
|
|
|
@ -173,7 +173,7 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer,
|
||||||
vl_compositor_clear_layers(&vmixer->compositor);
|
vl_compositor_clear_layers(&vmixer->compositor);
|
||||||
vl_compositor_set_buffer_layer(&vmixer->compositor, 0, surf->video_buffer,
|
vl_compositor_set_buffer_layer(&vmixer->compositor, 0, surf->video_buffer,
|
||||||
RectToPipe(video_source_rect, &src_rect), NULL);
|
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;
|
return VDP_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -312,7 +312,7 @@ vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface,
|
||||||
vl_compositor_clear_layers(compositor);
|
vl_compositor_clear_layers(compositor);
|
||||||
vl_compositor_set_palette_layer(compositor, 0, sv_idx, sv_tbl, NULL, NULL, false);
|
vl_compositor_set_palette_layer(compositor, 0, sv_idx, sv_tbl, NULL, NULL, false);
|
||||||
vl_compositor_render(compositor, vlsurface->surface,
|
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_idx, NULL);
|
||||||
pipe_sampler_view_reference(&sv_tbl, NULL);
|
pipe_sampler_view_reference(&sv_tbl, NULL);
|
||||||
|
|
|
@ -75,6 +75,8 @@ vlVdpPresentationQueueCreate(VdpDevice device,
|
||||||
goto no_compositor;
|
goto no_compositor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vl_compositor_reset_dirty_area(&pq->dirty_area);
|
||||||
|
|
||||||
*presentation_queue = vlAddDataHTAB(pq);
|
*presentation_queue = vlAddDataHTAB(pq);
|
||||||
if (*presentation_queue == 0) {
|
if (*presentation_queue == 0) {
|
||||||
ret = VDP_STATUS_ERROR;
|
ret = VDP_STATUS_ERROR;
|
||||||
|
@ -234,7 +236,7 @@ vlVdpPresentationQueueDisplay(VdpPresentationQueue presentation_queue,
|
||||||
|
|
||||||
vl_compositor_clear_layers(&pq->compositor);
|
vl_compositor_clear_layers(&pq->compositor);
|
||||||
vl_compositor_set_rgba_layer(&pq->compositor, 0, surf->sampler_view, NULL, NULL);
|
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;
|
pipe = pq->device->context->pipe;
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "pipe/p_video_decoder.h"
|
#include "pipe/p_video_decoder.h"
|
||||||
|
|
||||||
#include "util/u_debug.h"
|
#include "util/u_debug.h"
|
||||||
|
#include "util/u_rect.h"
|
||||||
#include "vl/vl_compositor.h"
|
#include "vl/vl_compositor.h"
|
||||||
|
|
||||||
#include "vl_winsys.h"
|
#include "vl_winsys.h"
|
||||||
|
@ -298,6 +299,7 @@ typedef struct
|
||||||
vlVdpDevice *device;
|
vlVdpDevice *device;
|
||||||
Drawable drawable;
|
Drawable drawable;
|
||||||
struct vl_compositor compositor;
|
struct vl_compositor compositor;
|
||||||
|
struct u_rect dirty_area;
|
||||||
} vlVdpPresentationQueue;
|
} vlVdpPresentationQueue;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|
|
@ -381,7 +381,7 @@ Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
|
||||||
pipe_surface_reference(&context_priv->drawable_surface, NULL);
|
pipe_surface_reference(&context_priv->drawable_surface, NULL);
|
||||||
context_priv->drawable_surface = vl_drawable_surface_get(context_priv->vctx, drawable);
|
context_priv->drawable_surface = vl_drawable_surface_get(context_priv->vctx, drawable);
|
||||||
context_priv->dst_rect = dst_rect;
|
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)
|
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
|
// Workaround for r600g, there seems to be a bug in the fence refcounting code
|
||||||
pipe->screen->fence_reference(pipe->screen, &surface_priv->fence, NULL);
|
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);
|
pipe->flush(pipe, &surface_priv->fence);
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
|
|
||||||
#include "util/u_debug.h"
|
#include "util/u_debug.h"
|
||||||
#include "util/u_math.h"
|
#include "util/u_math.h"
|
||||||
|
#include "util/u_rect.h"
|
||||||
|
|
||||||
#include "vl/vl_csc.h"
|
#include "vl/vl_csc.h"
|
||||||
#include "vl/vl_compositor.h"
|
#include "vl/vl_compositor.h"
|
||||||
|
@ -64,6 +65,7 @@ typedef struct
|
||||||
|
|
||||||
struct pipe_video_rect dst_rect;
|
struct pipe_video_rect dst_rect;
|
||||||
struct pipe_surface *drawable_surface;
|
struct pipe_surface *drawable_surface;
|
||||||
|
struct u_rect dirty_area;
|
||||||
|
|
||||||
} XvMCContextPrivate;
|
} XvMCContextPrivate;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue