From afbaed906d7ba89467b177e768c36f29d6053ad0 Mon Sep 17 00:00:00 2001 From: Qiang Yu Date: Sun, 30 Jun 2019 21:44:12 +0800 Subject: [PATCH] lima: implement EGL_KHR_partial_update This extension set a damage region for each buffer swap which can be used to reduce buffer reload cost by only feed damage region's tile buffer address for PP. Reviewed-and-Tested-by: Vasily Khoruzhick Signed-off-by: Qiang Yu --- src/gallium/drivers/lima/lima_context.h | 7 ---- src/gallium/drivers/lima/lima_draw.c | 43 +++++++++++++------- src/gallium/drivers/lima/lima_resource.c | 50 ++++++++++++++++++++++++ src/gallium/drivers/lima/lima_resource.h | 7 ++++ src/gallium/drivers/lima/lima_state.c | 44 --------------------- 5 files changed, 86 insertions(+), 65 deletions(-) diff --git a/src/gallium/drivers/lima/lima_context.h b/src/gallium/drivers/lima/lima_context.h index 286f8dc86c2..3d8bf6c2b3f 100644 --- a/src/gallium/drivers/lima/lima_context.h +++ b/src/gallium/drivers/lima/lima_context.h @@ -159,12 +159,6 @@ struct lima_ctx_plb_pp_stream { uint32_t offset[4]; }; -struct lima_damage_state { - struct pipe_scissor_state *region; - unsigned num_region; - bool aligned; -}; - struct lima_pp_stream_state { struct lima_bo *bo; uint32_t bo_offset; @@ -213,7 +207,6 @@ struct lima_context { struct pipe_stencil_ref stencil_ref; struct lima_context_constant_buffer const_buffer[PIPE_SHADER_TYPES]; struct lima_texture_stateobj tex_stateobj; - struct lima_damage_state damage; struct lima_pp_stream_state pp_stream; unsigned min_index; diff --git a/src/gallium/drivers/lima/lima_draw.c b/src/gallium/drivers/lima/lima_draw.c index ab7f1b134c2..6bd738c55ed 100644 --- a/src/gallium/drivers/lima/lima_draw.c +++ b/src/gallium/drivers/lima/lima_draw.c @@ -210,23 +210,36 @@ lima_ctx_dirty(struct lima_context *ctx) return ctx->plbu_cmd_array.size; } +static inline struct lima_damage_region * +lima_ctx_get_damage(struct lima_context *ctx) +{ + if (!ctx->framebuffer.base.nr_cbufs) + return NULL; + + struct lima_surface *surf = lima_surface(ctx->framebuffer.base.cbufs[0]); + struct lima_resource *res = lima_resource(surf->base.texture); + return &res->damage; +} + static bool lima_fb_need_reload(struct lima_context *ctx) { /* Depth buffer is always discarded */ if (!ctx->framebuffer.base.nr_cbufs) return false; - if (ctx->damage.region) { - /* for EGL_KHR_partial_update we just want to reload the - * region not aligned to tile boundary */ - if (!ctx->damage.aligned) - return true; + + struct lima_surface *surf = lima_surface(ctx->framebuffer.base.cbufs[0]); + struct lima_resource *res = lima_resource(surf->base.texture); + if (res->damage.region) { + /* for EGL_KHR_partial_update, when EGL_EXT_buffer_age is enabled, + * we need to reload damage region, otherwise just want to reload + * the region not aligned to tile boundary */ + //if (!res->damage.aligned) + // return true; + return true; } - else { - struct lima_surface *surf = lima_surface(ctx->framebuffer.base.cbufs[0]); - if (surf->reload) + else if (surf->reload) return true; - } return false; } @@ -510,9 +523,9 @@ lima_get_pp_stream_size(int num_pp, int tiled_w, int tiled_h, uint32_t *off) } static bool -inside_damage_region(int x, int y, struct lima_damage_state *ds) +inside_damage_region(int x, int y, struct lima_damage_region *ds) { - if (!ds->region) + if (!ds || !ds->region) return true; for (int i = 0; i < ds->num_region; i++) { @@ -531,6 +544,7 @@ lima_update_pp_stream(struct lima_context *ctx, int off_x, int off_y, { struct lima_pp_stream_state *ps = &ctx->pp_stream; struct lima_context_framebuffer *fb = &ctx->framebuffer; + struct lima_damage_region *damage = lima_ctx_get_damage(ctx); struct lima_screen *screen = lima_screen(ctx->base.screen); int i, num_pp = screen->num_pp; @@ -556,7 +570,7 @@ lima_update_pp_stream(struct lima_context *ctx, int off_x, int off_y, x += off_x; y += off_y; - if (!inside_damage_region(x, y, &ctx->damage)) + if (!inside_damage_region(x, y, damage)) continue; int pp = index % num_pp; @@ -586,7 +600,7 @@ lima_update_pp_stream(struct lima_context *ctx, int off_x, int off_y, static void lima_update_damage_pp_stream(struct lima_context *ctx) { - struct lima_damage_state *ds = &ctx->damage; + struct lima_damage_region *ds = lima_ctx_get_damage(ctx); struct pipe_scissor_state max = ds->region[0]; /* find a max region to cover all the damage region */ @@ -671,7 +685,8 @@ lima_update_submit_bo(struct lima_context *ctx) ctx->plb_gp_size, false, "gp plb stream at va %x\n", ctx->plb_gp_stream->va + ctx->plb_index * ctx->plb_gp_size); - if (ctx->damage.region) + struct lima_damage_region *damage = lima_ctx_get_damage(ctx); + if (damage && damage->region) lima_update_damage_pp_stream(ctx); else if (ctx->plb_pp_stream) lima_update_full_pp_stream(ctx); diff --git a/src/gallium/drivers/lima/lima_resource.c b/src/gallium/drivers/lima/lima_resource.c index 741fda1f222..b2e33f4d3ff 100644 --- a/src/gallium/drivers/lima/lima_resource.c +++ b/src/gallium/drivers/lima/lima_resource.c @@ -264,6 +264,9 @@ lima_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *pres) if (res->scanout) renderonly_scanout_destroy(res->scanout, screen->ro); + if (res->damage.region) + FREE(res->damage.region); + FREE(res); } @@ -343,6 +346,52 @@ lima_resource_get_handle(struct pipe_screen *pscreen, return true; } +static void +lima_resource_set_damage_region(struct pipe_screen *pscreen, + struct pipe_resource *pres, + unsigned int nrects, + const struct pipe_box *rects) +{ + struct lima_resource *res = lima_resource(pres); + struct lima_damage_region *damage = &res->damage; + int i; + + if (damage->region) { + FREE(damage->region); + damage->region = NULL; + damage->num_region = 0; + } + + if (!nrects) + return; + + damage->region = CALLOC(nrects, sizeof(*damage->region)); + if (!damage->region) + return; + + for (i = 0; i < nrects; i++) { + struct pipe_scissor_state *r = damage->region + i; + int y = pres->height0 - (rects[i].y + rects[i].height); + /* region in tile unit */ + r->minx = rects[i].x >> 4; + r->miny = y >> 4; + r->maxx = (rects[i].x + rects[i].width + 0xf) >> 4; + r->maxy = (y + rects[i].height + 0xf) >> 4; + } + + /* is region aligned to tiles? */ + damage->aligned = true; + for (i = 0; i < nrects; i++) { + if (rects[i].x & 0xf || rects[i].y & 0xf || + rects[i].width & 0xf || rects[i].height & 0xf) { + damage->aligned = false; + break; + } + } + + damage->num_region = nrects; +} + void lima_resource_screen_init(struct lima_screen *screen) { @@ -351,6 +400,7 @@ lima_resource_screen_init(struct lima_screen *screen) screen->base.resource_from_handle = lima_resource_from_handle; screen->base.resource_destroy = lima_resource_destroy; screen->base.resource_get_handle = lima_resource_get_handle; + screen->base.set_damage_region = lima_resource_set_damage_region; } static struct pipe_surface * diff --git a/src/gallium/drivers/lima/lima_resource.h b/src/gallium/drivers/lima/lima_resource.h index ba88b0696fe..7e7a9628a86 100644 --- a/src/gallium/drivers/lima/lima_resource.h +++ b/src/gallium/drivers/lima/lima_resource.h @@ -38,9 +38,16 @@ struct lima_resource_level { uint32_t offset; }; +struct lima_damage_region { + struct pipe_scissor_state *region; + unsigned num_region; + bool aligned; +}; + struct lima_resource { struct pipe_resource base; + struct lima_damage_region damage; struct renderonly_scanout *scanout; struct lima_bo *bo; bool tiled; diff --git a/src/gallium/drivers/lima/lima_state.c b/src/gallium/drivers/lima/lima_state.c index fb3b36a4b2b..286529e9db0 100644 --- a/src/gallium/drivers/lima/lima_state.c +++ b/src/gallium/drivers/lima/lima_state.c @@ -414,50 +414,6 @@ lima_set_sampler_views(struct pipe_context *pctx, ctx->dirty |= LIMA_CONTEXT_DIRTY_TEXTURES; } -UNUSED static bool -lima_set_damage_region(struct pipe_context *pctx, unsigned num_rects, int *rects) -{ - struct lima_context *ctx = lima_context(pctx); - struct lima_damage_state *damage = &ctx->damage; - int i; - - if (damage->region) - ralloc_free(damage->region); - - if (!num_rects) { - damage->region = NULL; - damage->num_region = 0; - return true; - } - - damage->region = ralloc_size(ctx, sizeof(*damage->region) * num_rects); - if (!damage->region) { - damage->num_region = 0; - return false; - } - - for (i = 0; i < num_rects; i++) { - struct pipe_scissor_state *r = damage->region + i; - /* region in tile unit */ - r->minx = rects[i * 4] >> 4; - r->miny = rects[i * 4 + 1] >> 4; - r->maxx = (rects[i * 4] + rects[i * 4 + 2] + 0xf) >> 4; - r->maxy = (rects[i * 4 + 1] + rects[i * 4 + 3] + 0xf) >> 4; - } - - /* is region aligned to tiles? */ - damage->aligned = true; - for (i = 0; i < num_rects * 4; i++) { - if (rects[i] & 0xf) { - damage->aligned = false; - break; - } - } - - damage->num_region = num_rects; - return true; -} - static void lima_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask) -- 2.30.2