From 519f77dd7f8eba7c4c0c076e426178a140ee7ae7 Mon Sep 17 00:00:00 2001 From: nick black Date: Mon, 24 Feb 2020 19:35:39 -0500 Subject: [PATCH] notcurses_refresh: resynthesize unoptimized stream #380 --- src/lib/render.c | 51 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/src/lib/render.c b/src/lib/render.c index b8e8e97ae..ed7d987ff 100644 --- a/src/lib/render.c +++ b/src/lib/render.c @@ -29,18 +29,6 @@ blocking_write(int fd, const char* buf, size_t buflen){ return 0; } -int notcurses_refresh(notcurses* nc){ - int ret; - if(nc->rstate.mstream == NULL){ - ret = -1; // haven't rendered yet, and thus don't know what should be there - }else if(blocking_write(nc->ttyfd, nc->rstate.mstream, nc->rstate.mstrsize)){ - ret = -1; - }else{ - ret = 0; - } - return ret; -} - static void update_render_stats(const struct timespec* time1, const struct timespec* time0, ncstats* stats, int bytes){ @@ -180,12 +168,13 @@ cell_locked_p(const cell* p){ return 0; } -// Extracellular state for a cell during the render process +// Extracellular state for a cell during the render process. This array is +// passed along to rasterization, which uses only the 'damaged' bools. struct crender { + ncplane *p; unsigned fgblends; unsigned bgblends; - ncplane *p; - bool damaged; + bool damaged; // also used in rasterization // if CELL_ALPHA_HIGHCONTRAST is in play, we apply the HSV flip once the // background is locked in. set highcontrast to indicate this. bool highcontrast; @@ -776,6 +765,11 @@ update_palette(notcurses* nc, FILE* out){ // * render -- build up a flat framebuffer from a set of ncplanes // * rasterize -- build up a UTF-8 stream of escapes and EGCs // * refresh -- write the stream to the emulator + +// Takes a rendered frame (a flat framebuffer, where each cell has the desired +// EGC, attribute, and channels) and the previously-rendered frame, and spits +// out an optimal sequence of terminal-appropriate escapes and EGCs. There +// should be an rvec entry for each cell; only the 'damaged' field is used. static int notcurses_rasterize(notcurses* nc, const struct crender* rvec){ FILE* out = nc->rstate.mstreamfp; @@ -948,6 +942,33 @@ fprintf(stderr, "RAST %u [%s] to %d/%d\n", srccell->gcluster, egcpool_extended_g return nc->rstate.mstrsize; } +int notcurses_refresh(notcurses* nc){ + // FIXME need reflow in the event we've been resized + if(term_emit("clear", nc->clearscr, nc->ttyfp, true)){ + return -1; + } + struct crender* rvec = malloc(sizeof(struct crender) * nc->lfdimx * nc->lfdimy); + if(rvec == NULL){ + return -1; + } + for(int i = 0 ; i < nc->lfdimy * nc->lfdimx ; ++i){ + memset(rvec + i, 0, sizeof(*rvec)); + rvec->damaged = true; + } + int ret = notcurses_rasterize(nc, rvec); + free(rvec); + if(ret < 0){ + return -1; + } + if(blocking_write(nc->ttyfd, nc->rstate.mstream, nc->rstate.mstrsize)){ + return -1; + } + if(fflush(nc->ttyfp)){ + return -1; + } + return 0; +} + int notcurses_render(notcurses* nc){ struct timespec start, done; int ret;