From 4f5bfe2a5e252f1f7ae047949d645918f374e07c Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Wed, 9 Oct 2019 19:23:54 -0700 Subject: [PATCH] lima: don't reload and redraw tiles that were not updated We don't need to reload and redraw some tiles if framebuffer was not cleared and scissor test was enabled for some of draws. This simple optimization fixes cursor lag in X11 Reviewed-by: Qiang Yu Signed-off-by: Vasily Khoruzhick --- src/gallium/drivers/lima/lima_context.c | 3 ++ src/gallium/drivers/lima/lima_context.h | 1 + src/gallium/drivers/lima/lima_draw.c | 70 ++++++++++++++++++++++--- 3 files changed, 67 insertions(+), 7 deletions(-) diff --git a/src/gallium/drivers/lima/lima_context.c b/src/gallium/drivers/lima/lima_context.c index 44f627ac1da..e2d48d155a3 100644 --- a/src/gallium/drivers/lima/lima_context.c +++ b/src/gallium/drivers/lima/lima_context.c @@ -212,6 +212,9 @@ lima_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) ctx->base.stream_uploader = ctx->uploader; ctx->base.const_uploader = ctx->uploader; + ctx->damage_rect.minx = ctx->damage_rect.miny = 0xffff; + ctx->damage_rect.maxx = ctx->damage_rect.maxy = 0; + util_dynarray_init(&ctx->vs_cmd_array, ctx); util_dynarray_init(&ctx->plbu_cmd_array, ctx); diff --git a/src/gallium/drivers/lima/lima_context.h b/src/gallium/drivers/lima/lima_context.h index b2fa8d1d483..e62630b7a6d 100644 --- a/src/gallium/drivers/lima/lima_context.h +++ b/src/gallium/drivers/lima/lima_context.h @@ -195,6 +195,7 @@ struct lima_context { struct lima_context_framebuffer framebuffer; struct lima_context_viewport_state viewport; struct pipe_scissor_state scissor; + struct pipe_scissor_state damage_rect; struct lima_context_clear clear; struct lima_vs_shader_state *vs; struct lima_fs_shader_state *fs; diff --git a/src/gallium/drivers/lima/lima_draw.c b/src/gallium/drivers/lima/lima_draw.c index 4fb2e12cd12..72cd3f6cb35 100644 --- a/src/gallium/drivers/lima/lima_draw.c +++ b/src/gallium/drivers/lima/lima_draw.c @@ -475,11 +475,19 @@ lima_generate_pp_stream(struct lima_context *ctx, int off_x, int off_y, * close enough which should result close workload */ int max = MAX2(tiled_w, tiled_h); - int dim = util_logbase2_ceil(max); - int count = 1 << (dim + dim); int index = 0; uint32_t *stream[4]; int si[4] = {0}; + int dim = 0; + int count = 0; + + /* Don't update count if we get zero rect. We'll just generate + * PP stream with just terminators in it. + */ + if ((tiled_w * tiled_h) != 0) { + dim = util_logbase2_ceil(max); + count = 1 << (dim + dim); + } for (i = 0; i < num_pp; i++) stream[i] = ps->bo->map + ps->bo_offset + ps->offset[i]; @@ -522,10 +530,31 @@ static void lima_update_damage_pp_stream(struct lima_context *ctx) { struct lima_damage_region *ds = lima_ctx_get_damage(ctx); - struct pipe_scissor_state *bound = &ds->bound; + struct lima_context_framebuffer *fb = &ctx->framebuffer; + struct pipe_scissor_state bound; + + if (ds && ds->region) { + struct pipe_scissor_state *dbound = &ds->bound; + bound.minx = MAX2(dbound->minx, ctx->damage_rect.minx >> 4); + bound.miny = MAX2(dbound->miny, ctx->damage_rect.miny >> 4); + bound.maxx = MIN2(dbound->maxx, (ctx->damage_rect.maxx + 0xf) >> 4); + bound.maxy = MIN2(dbound->maxy, (ctx->damage_rect.maxy + 0xf) >> 4); + } else { + bound.minx = ctx->damage_rect.minx >> 4; + bound.miny = ctx->damage_rect.miny >> 4; + bound.maxx = (ctx->damage_rect.maxx + 0xf) >> 4; + bound.maxy = (ctx->damage_rect.maxy + 0xf) >> 4; + } + + /* Clamp to FB size */ + bound.minx = MIN2(bound.minx, fb->tiled_w); + bound.miny = MIN2(bound.miny, fb->tiled_h); + bound.maxx = MIN2(bound.maxx, fb->tiled_w); + bound.maxy = MIN2(bound.maxy, fb->tiled_h); + + int tiled_w = bound.maxx - bound.minx; + int tiled_h = bound.maxy - bound.miny; - int tiled_w = bound->maxx - bound->minx; - int tiled_h = bound->maxy - bound->miny; struct lima_screen *screen = lima_screen(ctx->base.screen); int size = lima_get_pp_stream_size( screen->num_pp, tiled_w, tiled_h, ctx->pp_stream.offset); @@ -539,7 +568,7 @@ lima_update_damage_pp_stream(struct lima_context *ctx) ctx->pp_stream.bo = res->bo; ctx->pp_stream.bo_offset = offset; - lima_generate_pp_stream(ctx, bound->minx, bound->miny, tiled_w, tiled_h); + lima_generate_pp_stream(ctx, bound.minx, bound.miny, tiled_w, tiled_h); lima_submit_add_bo(ctx->pp_submit, res->bo, LIMA_SUBMIT_BO_READ); pipe_resource_reference(&pres, NULL); @@ -581,11 +610,20 @@ lima_update_full_pp_stream(struct lima_context *ctx) lima_submit_add_bo(ctx->pp_submit, s->bo, LIMA_SUBMIT_BO_READ); } +static bool +lima_damage_fullscreen(struct lima_context *ctx) +{ + return ctx->damage_rect.minx == 0 && + ctx->damage_rect.miny == 0 && + ctx->damage_rect.maxx == ctx->framebuffer.base.width && + ctx->damage_rect.maxy == ctx->framebuffer.base.height; +} + static void lima_update_pp_stream(struct lima_context *ctx) { struct lima_damage_region *damage = lima_ctx_get_damage(ctx); - if (damage && damage->region) + if ((damage && damage->region) || !lima_damage_fullscreen(ctx)) lima_update_damage_pp_stream(ctx); else if (ctx->plb_pp_stream) lima_update_full_pp_stream(ctx); @@ -622,6 +660,15 @@ lima_update_submit_bo(struct lima_context *ctx) lima_submit_add_bo(ctx->pp_submit, screen->pp_buffer, LIMA_SUBMIT_BO_READ); } +static void +lima_damage_rect_union(struct lima_context *ctx, unsigned minx, unsigned maxx, unsigned miny, unsigned maxy) +{ + ctx->damage_rect.minx = MIN2(ctx->damage_rect.minx, minx); + ctx->damage_rect.miny = MIN2(ctx->damage_rect.miny, miny); + ctx->damage_rect.maxx = MAX2(ctx->damage_rect.maxx, maxx); + ctx->damage_rect.maxy = MAX2(ctx->damage_rect.maxy, maxy); +} + static void lima_clear(struct pipe_context *pctx, unsigned buffers, const union pipe_color_union *color, double depth, unsigned stencil) @@ -664,6 +711,9 @@ lima_clear(struct pipe_context *pctx, unsigned buffers, lima_pack_head_plbu_cmd(ctx); ctx->dirty |= LIMA_CONTEXT_DIRTY_CLEAR; + + lima_damage_rect_union(ctx, 0, ctx->framebuffer.base.width, + 0, ctx->framebuffer.base.height); } enum lima_attrib_type { @@ -819,8 +869,11 @@ lima_pack_plbu_cmd(struct lima_context *ctx, const struct pipe_draw_info *info) if (ctx->rasterizer->base.scissor) { struct pipe_scissor_state *scissor = &ctx->scissor; PLBU_CMD_SCISSORS(scissor->minx, scissor->maxx, scissor->miny, scissor->maxy); + lima_damage_rect_union(ctx, scissor->minx, scissor->maxx, + scissor->miny, scissor->maxy); } else { PLBU_CMD_SCISSORS(0, fb->base.width, 0, fb->base.height); + lima_damage_rect_union(ctx, 0, fb->base.width, 0, fb->base.height); } PLBU_CMD_UNKNOWN1(); @@ -1718,6 +1771,9 @@ _lima_flush(struct lima_context *ctx, bool end_of_frame) ctx->pp_max_stack_size = 0; + ctx->damage_rect.minx = ctx->damage_rect.miny = 0xffff; + ctx->damage_rect.maxx = ctx->damage_rect.maxy = 0; + lima_dump_file_next(); } -- 2.30.2