Commit afbaed90 authored by Qiang Yu's avatar Qiang Yu

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's avatarVasily Khoruzhick <anarsoul@gmail.com>
Signed-off-by: Qiang Yu's avatarQiang Yu <yuq825@gmail.com>
parent 8278b236
......@@ -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;
......
......@@ -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);
......
......@@ -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 *
......
......@@ -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;
......
......@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment