lima: implement EGL_KHR_partial_update
authorQiang Yu <yuq825@gmail.com>
Sun, 30 Jun 2019 13:44:12 +0000 (21:44 +0800)
committerQiang Yu <yuq825@gmail.com>
Mon, 23 Sep 2019 01:48:15 +0000 (09:48 +0800)
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 <anarsoul@gmail.com>
Signed-off-by: Qiang Yu <yuq825@gmail.com>
src/gallium/drivers/lima/lima_context.h
src/gallium/drivers/lima/lima_draw.c
src/gallium/drivers/lima/lima_resource.c
src/gallium/drivers/lima/lima_resource.h
src/gallium/drivers/lima/lima_state.c

index 286f8dc86c21b2ce690dea142c39a6f042534d16..3d8bf6c2b3f6f47a9ebc70f32b2700c50d46fd83 100644 (file)
@@ -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;
index ab7f1b134c243b0732d2fc26cfb40c220b13ad65..6bd738c55edbe0d5dae141e92df4e832d515e61b 100644 (file)
@@ -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);
index 741fda1f2222417b69f5fccfbe7f5bad4a5f7864..b2e33f4d3ff49939e0a805ce4bf1237f33a1a68b 100644 (file)
@@ -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 *
index ba88b0696fe365377f0e70db45cb09ddb7fc5d6b..7e7a9628a86f020932d7d05c22d6ccf2b1629fa7 100644 (file)
@@ -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;
index fb3b36a4b2b8b4c3ef28104ef393e6ea36ee02c1..286529e9db0795b312f871ffa7484d0b984a14f7 100644 (file)
@@ -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)