diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2013-10-23 19:59:29 +0200 |
---|---|---|
committer | David Herrmann <dh.herrmann@gmail.com> | 2013-10-23 19:59:29 +0200 |
commit | 492da8a82832b47ee0fc3e27549ef77fbb38ba4e (patch) | |
tree | f6e1ad826c6a23ade267d5a834e7ae7cea0857eb | |
parent | 0ccfd9e707b6c0349321a9f640df27ac959007c7 (diff) |
Render only changed cells
TSM has support for cell-ageing so render only cells that changed. Note
that we still blit the buffer via cairo at the end, but this should be
fast enough for any system. The actual rendering is often what causes
performance-bottlenecks.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
-rw-r--r-- | src/wlt_render.c | 46 | ||||
-rw-r--r-- | src/wlterm.c | 3 | ||||
-rw-r--r-- | src/wlterm.h | 5 |
3 files changed, 41 insertions, 13 deletions
diff --git a/src/wlt_render.c b/src/wlt_render.c index 819b807..af5f702 100644 --- a/src/wlt_render.c +++ b/src/wlt_render.c @@ -43,6 +43,7 @@ struct wlt_renderer { int stride; uint8_t *data; cairo_surface_t *surface; + tsm_age_t age; }; static int wlt_renderer_realloc(struct wlt_renderer *rend, unsigned int width, @@ -230,6 +231,13 @@ static void wlt_renderer_blend(struct wlt_renderer *rend, } } +static bool overlap(const struct wlt_draw_ctx *ctx, double x1, double y1, + double x2, double y2) +{ + return (ctx->x1 < x2 && ctx->x2 > x1 && + ctx->y1 < y2 && ctx->y2 > y1); +} + static int wlt_renderer_draw_cell(struct tsm_screen *screen, uint32_t id, const uint32_t *ch, size_t len, unsigned int cwidth, unsigned int posx, @@ -238,11 +246,25 @@ static int wlt_renderer_draw_cell(struct tsm_screen *screen, uint32_t id, tsm_age_t age, void *data) { const struct wlt_draw_ctx *ctx = data; + struct wlt_renderer *rend = ctx->rend; uint8_t fr, fg, fb, br, bg, bb; unsigned int x, y; struct wlt_glyph *glyph; + bool skip; int r; + x = posx * ctx->cell_width; + y = posy * ctx->cell_height; + + /* If the cell is inside of the dirty-region *and* our age and the + * cell age is non-zero *and* the cell-age is smaller than our age, + * then skip drawing as it's already on-screen. */ + skip = overlap(ctx, x, y, x + ctx->cell_width, y + ctx->cell_height); + skip = skip && age && rend->age && age <= rend->age; + + if (skip) + return 0; + /* invert colors if requested */ if (attr->inverse) { fr = attr->br; @@ -260,23 +282,20 @@ static int wlt_renderer_draw_cell(struct tsm_screen *screen, uint32_t id, bb = attr->bb; } - x = posx * ctx->cell_width; - y = posy * ctx->cell_height; - /* !len means background-only */ if (!len) { - wlt_renderer_fill(ctx->rend, x, y, ctx->cell_width * cwidth, + wlt_renderer_fill(rend, x, y, ctx->cell_width * cwidth, ctx->cell_height, br, bg, bb); - return 0; + } else { + r = wlt_face_render(ctx->face, &glyph, id, ch, len, cwidth); + if (r < 0) + wlt_renderer_fill(rend, x, y, ctx->cell_width * cwidth, + ctx->cell_height, br, bg, bb); + else + wlt_renderer_blend(rend, glyph, x, y, + fr, fg, fb, br, bg, bb); } - r = wlt_face_render(ctx->face, &glyph, id, ch, len, cwidth); - if (r < 0) - return r; - - wlt_renderer_blend(ctx->rend, glyph, x, y, - fr, fg, fb, br, bg, bb); - return 0; } @@ -290,7 +309,8 @@ void wlt_renderer_draw(const struct wlt_draw_ctx *ctx) * but at least it's fast enough to render a whole screen. */ cairo_surface_flush(rend->surface); - tsm_screen_draw(ctx->screen, wlt_renderer_draw_cell, (void*)ctx); + rend->age = tsm_screen_draw(ctx->screen, wlt_renderer_draw_cell, + (void*)ctx); cairo_surface_mark_dirty(rend->surface); cairo_set_source_surface(ctx->cr, rend->surface, 0, 0); diff --git a/src/wlterm.c b/src/wlterm.c index 1d30e83..e9d87e6 100644 --- a/src/wlterm.c +++ b/src/wlterm.c @@ -326,12 +326,15 @@ static gboolean term_redraw_cb(GtkWidget *widget, cairo_t *cr, gpointer data) start = g_get_monotonic_time(); + memset(&ctx, 0, sizeof(ctx)); ctx.rend = term->rend; ctx.cr = cr; ctx.face = term->face; ctx.cell_width = term->cell_width; ctx.cell_height = term->cell_height; ctx.screen = term->screen; + cairo_clip_extents(cr, &ctx.x1, &ctx.y1, &ctx.x2, &ctx.y2); + wlt_renderer_draw(&ctx); end = g_get_monotonic_time(); diff --git a/src/wlterm.h b/src/wlterm.h index c5d9ace..758ed49 100644 --- a/src/wlterm.h +++ b/src/wlterm.h @@ -88,6 +88,11 @@ struct wlt_draw_ctx { unsigned int cell_width; unsigned int cell_height; struct tsm_screen *screen; + + double x1; + double y1; + double x2; + double y2; }; int wlt_renderer_new(struct wlt_renderer **out, unsigned int width, |