From 83296b46880930fc4e9ebef1fec890223885cec5 Mon Sep 17 00:00:00 2001 From: nick black Date: Thu, 1 Apr 2021 20:11:44 -0400 Subject: [PATCH] Revert "eliminate sixel flicker #1493" This reverts commit aa80af8f87ee80134ecea1a61b4653fa64ec3364. --- src/lib/direct.c | 8 +------- src/lib/internal.h | 30 +++++++++++++++------------- src/lib/kitty.c | 14 +++++++------ src/lib/notcurses.c | 4 ++-- src/lib/render.c | 5 +---- src/lib/sixel.c | 16 ++++++++------- src/lib/sprite.c | 43 +++++++++++++++------------------------- src/lib/visual-details.h | 2 -- src/lib/visual.c | 25 ++++------------------- 9 files changed, 57 insertions(+), 90 deletions(-) diff --git a/src/lib/direct.c b/src/lib/direct.c index 05ef726a7..69e168832 100644 --- a/src/lib/direct.c +++ b/src/lib/direct.c @@ -550,13 +550,7 @@ ncdirectv* ncdirect_render_frame(ncdirect* n, const char* file, bargs.u.pixel.celldimx = n->tcache.cellpixx; bargs.u.pixel.celldimy = n->tcache.cellpixy; bargs.u.pixel.colorregs = n->tcache.color_registers; - int cols = lenx / bargs.u.pixel.celldimx + !!(lenx % bargs.u.pixel.celldimx); - int rows = leny / bargs.u.pixel.celldimy + !!(leny % bargs.u.pixel.celldimy); - if((bargs.u.pixel.spx = sprixel_alloc(ncdv, rows, cols)) == NULL){ - ncvisual_destroy(ncv); - free_plane(ncdv); - return NULL; - } + bargs.u.pixel.sprixelid = n->tcache.sprixelnonce++; } if(ncvisual_blit(ncv, disprows, dispcols, ncdv, bset, leny, lenx, &bargs)){ ncvisual_destroy(ncv); diff --git a/src/lib/internal.h b/src/lib/internal.h index 53cd80f94..626c7d506 100644 --- a/src/lib/internal.h +++ b/src/lib/internal.h @@ -502,7 +502,7 @@ typedef struct { int celldimx; // horizontal pixels per cell int celldimy; // vertical pixels per cell int colorregs; // number of color registers - sprixel* spx; // sprixel object + int sprixelid; // unqie 24-bit id into sprixel cache } pixel; // for pixels } u; } blitterargs; @@ -811,9 +811,9 @@ int sprite_draw(const notcurses* n, const ncpile *p, sprixel* s, FILE* out); int kitty_draw(const notcurses* n, const ncpile *p, sprixel* s, FILE* out); int sixel_draw(const notcurses* n, const ncpile *p, sprixel* s, FILE* out); // dimy and dimx are cell geometry, not pixel. takes ownership of s on success. -sprixel* sprixel_alloc(ncplane* n, int dimy, int dimx); -int sprixel_load(sprixel* spx, char* s, int bytes, int placey, int placex, - int pixy, int pixx, int parse_start); +sprixel* sprixel_create(ncplane* n, char* s, int bytes, int placey, int placex, + int sprixelid, int dimy, int dimx, int pixy, int pixx, + int parse_start); int sprite_wipe_cell(const notcurses* nc, sprixel* s, int y, int x); int sixel_delete(const notcurses* nc, const ncpile* p, FILE* out, sprixel* s); int sprite_kitty_annihilate(const notcurses* nc, const ncpile* p, FILE* out, sprixel* s); @@ -1216,13 +1216,14 @@ egc_rtl(const char* egc, int* bytes){ // a reference to the context-wide sprixel cache. this ought be an entirely // new, purpose-specific plane. static inline int -plane_blit_sixel(sprixel* spx, char* s, int bytes, - int placey, int placex, int leny, int lenx, - int parse_start, sprixcell_e* tacache){ - if(sprixel_load(spx, s, bytes, placey, placex, leny, lenx, parse_start)){ +plane_blit_sixel(ncplane* n, char* s, int bytes, int placey, int placex, + int leny, int lenx, int sprixelid, int dimy, int dimx, + int parse_start, sprixcell_e * tacache){ + sprixel* spx = sprixel_create(n, s, bytes, placey, placex, sprixelid, + leny, lenx, dimy, dimx, parse_start); + if(spx == NULL){ return -1; } - ncplane* n = spx->n; uint32_t gcluster = htole(0x02000000ul) + htole(spx->id); for(int y = placey ; y < placey + leny && y < ncplane_dim_y(n) ; ++y){ for(int x = placex ; x < placex + lenx && x < ncplane_dim_x(n) ; ++x){ @@ -1231,12 +1232,13 @@ plane_blit_sixel(sprixel* spx, char* s, int bytes, c->width = lenx; } } - if(n){ - n->tacache = tacache; - n->tacachey = leny; - n->tacachex = lenx; - n->sprite = spx; + if(n->sprite){ + sprixel_hide(n->sprite); } + n->tacache = tacache; + n->tacachey = leny; + n->tacachex = lenx; + n->sprite = spx; return 0; } diff --git a/src/lib/kitty.c b/src/lib/kitty.c index b95b27ed2..08edff45f 100644 --- a/src/lib/kitty.c +++ b/src/lib/kitty.c @@ -295,8 +295,8 @@ write_kitty_data(FILE* fp, int linesize, int leny, int lenx, // deflate-compressed) 24bit RGB. Returns -1 on error, 1 on success. int kitty_blit(ncplane* n, int linesize, const void* data, int leny, int lenx, const blitterargs* bargs){ - int cols = bargs->u.pixel.spx->dimx; - int rows = bargs->u.pixel.spx->dimy; + int rows = leny / bargs->u.pixel.celldimy + !!(leny % bargs->u.pixel.celldimy); + int cols = lenx / bargs->u.pixel.celldimx + !!(lenx % bargs->u.pixel.celldimx); char* buf = NULL; size_t size = 0; FILE* fp = open_memstream(&buf, &size); @@ -307,6 +307,7 @@ int kitty_blit(ncplane* n, int linesize, const void* data, bool reuse = false; // if we have a sprixel attached to this plane, see if we can reuse it // (we need the same dimensions) and thus immediately apply its T-A table. + int sprixelid; if(n->tacache){ if(n->tacachey == rows && n->tacachex == cols){ tacache = n->tacache; @@ -323,10 +324,11 @@ int kitty_blit(ncplane* n, int linesize, const void* data, } memset(tacache, 0, sizeof(*tacache) * rows * cols); } + sprixelid = bargs->u.pixel.sprixelid; // closes fp on all paths if(write_kitty_data(fp, linesize, leny, lenx, cols, data, bargs->u.pixel.celldimy, bargs->u.pixel.celldimx, - bargs->u.pixel.spx->id, tacache, &parse_start)){ + sprixelid, tacache, &parse_start)){ if(!reuse){ free(tacache); } @@ -334,9 +336,9 @@ int kitty_blit(ncplane* n, int linesize, const void* data, return -1; } // take ownership of |buf| and |tacache| on success - if(plane_blit_sixel(bargs->u.pixel.spx, buf, size, - bargs->placey, bargs->placex, - leny, lenx, parse_start, tacache) < 0){ + if(plane_blit_sixel(n, buf, size, bargs->placey, bargs->placex, + rows, cols, bargs->u.pixel.sprixelid, leny, lenx, + parse_start, tacache) < 0){ if(!reuse){ free(tacache); } diff --git a/src/lib/notcurses.c b/src/lib/notcurses.c index fdcd8ab51..3dd3bd7f4 100644 --- a/src/lib/notcurses.c +++ b/src/lib/notcurses.c @@ -1984,9 +1984,9 @@ void ncplane_yx(const ncplane* n, int* y, int* x){ } void ncplane_erase(ncplane* n){ - /*if(n->sprite){ + if(n->sprite){ sprixel_hide(n->sprite); - }*/ + } // we must preserve the background, but a pure cell_duplicate() would be // wiped out by the egcpool_dump(). do a duplication (to get the stylemask // and channels), and then reload. diff --git a/src/lib/render.c b/src/lib/render.c index 86c3b69f3..b8c98a9f0 100644 --- a/src/lib/render.c +++ b/src/lib/render.c @@ -1085,19 +1085,16 @@ notcurses_rasterize_inner(notcurses* nc, const ncpile* p, FILE* out){ // we explicitly move the cursor at the beginning of each output line, so no // need to home it expliticly. update_palette(nc, out); -fprintf(stderr, "pile %p ymax: %d xmax: %d\n", p, p->dimy + nc->stdplane->absy, p->dimx + nc->stdplane->absx); +//fprintf(stderr, "pile %p ymax: %d xmax: %d\n", p, p->dimy + nc->stdplane->absy, p->dimx + nc->stdplane->absx); if(clean_sprixels(nc, p, out) < 0){ return -1; } -fprintf(stderr, "RASTERIZE CORE\n"); if(rasterize_core(nc, p, out)){ return -1; } -fprintf(stderr, "RASTERIZE SPRIXELS\n"); if(rasterize_sprixels(nc, p, out) < 0){ return -1; } -fprintf(stderr, "RASTERIZE CORE\n"); if(rasterize_core(nc, p, out)){ return -1; } diff --git a/src/lib/sixel.c b/src/lib/sixel.c index 803a51ff7..68bbf9b9d 100644 --- a/src/lib/sixel.c +++ b/src/lib/sixel.c @@ -386,7 +386,7 @@ write_sixel_data(FILE* fp, int lenx, sixeltable* stab, int* parse_start){ // stacks. There is also a RLE component, handled in rasterization. // A pixel block is indicated by setting cell_pixels_p(). static inline int -sixel_blit_inner(int leny, int lenx, sixeltable* stab, +sixel_blit_inner(ncplane* n, int leny, int lenx, sixeltable* stab, const blitterargs* bargs, sprixcell_e* tacache){ char* buf = NULL; size_t size = 0; @@ -395,15 +395,17 @@ sixel_blit_inner(int leny, int lenx, sixeltable* stab, return -1; } int parse_start = 0; + int cols = lenx / bargs->u.pixel.celldimx + !!(lenx % bargs->u.pixel.celldimx); + int rows = leny / bargs->u.pixel.celldimy + !!(leny % bargs->u.pixel.celldimy); // calls fclose() on success if(write_sixel_data(fp, lenx, stab, &parse_start)){ free(buf); return -1; } // take ownership of buf on success - if(plane_blit_sixel(bargs->u.pixel.spx, buf, size, - bargs->placey, bargs->placex, - leny, lenx, parse_start, tacache) < 0){ + if(plane_blit_sixel(n, buf, size, bargs->placey, bargs->placex, + rows, cols, bargs->u.pixel.sprixelid, leny, lenx, + parse_start, tacache) < 0){ free(buf); return -1; } @@ -437,8 +439,8 @@ int sixel_blit(ncplane* n, int linesize, const void* data, // stable.table doesn't need initializing; we start from the bottom memset(stable.data, 0, sixelcount * colorregs); memset(stable.deets, 0, sizeof(*stable.deets) * colorregs); - int cols = bargs->u.pixel.spx->dimx; - int rows = bargs->u.pixel.spx->dimy; + int cols = lenx / bargs->u.pixel.celldimx + !!(lenx % bargs->u.pixel.celldimx); + int rows = leny / bargs->u.pixel.celldimy + !!(leny % bargs->u.pixel.celldimy); sprixcell_e* tacache = NULL; bool reuse = false; // if we have a sprixel attached to this plane, see if we can reuse it @@ -469,7 +471,7 @@ int sixel_blit(ncplane* n, int linesize, const void* data, return -1; } refine_color_table(data, linesize, bargs->begy, bargs->begx, leny, lenx, &stable); - int r = sixel_blit_inner(leny, lenx, &stable, bargs, tacache); + int r = sixel_blit_inner(n, leny, lenx, &stable, bargs, tacache); free(stable.data); free(stable.deets); free(stable.table); diff --git a/src/lib/sprite.c b/src/lib/sprite.c index 3a0225523..3ae63da4a 100644 --- a/src/lib/sprite.c +++ b/src/lib/sprite.c @@ -1,8 +1,5 @@ #include "internal.h" -// FIXME needs be atomic -static uint32_t sprixelid_nonce; - void sprixel_free(sprixel* s){ if(s){ free(s->glyph); @@ -49,42 +46,34 @@ sprixel* sprixel_by_id(const notcurses* nc, uint32_t id){ return NULL; } -sprixel* sprixel_alloc(ncplane* n, int dimy, int dimx){ +// 'y' and 'x' are the cell geometry, not the pixel geometry. takes +// ownership of 's' on success. +sprixel* sprixel_create(ncplane* n, char* s, int bytes, int placey, int placex, + int sprixelid, int dimy, int dimx, int pixy, int pixx, + int parse_start){ sprixel* ret = malloc(sizeof(sprixel)); if(ret){ -fprintf(stderr, "LOADING UP %p with %p\n", ret, n); - memset(ret, 0, sizeof(*ret)); + ret->glyph = s; + ret->glyphlen = bytes; + ret->invalidated = SPRIXEL_INVALIDATED; ret->n = n; ret->dimy = dimy; ret->dimx = dimx; - ret->id = ++sprixelid_nonce; -//fprintf(stderr, "LOOKING AT %p (p->n = %p)\n", ret, ret->n); - if(ncplane_pile(ret->n)){ - notcurses* nc = ncplane_notcurses(ret->n); + ret->pixx = pixx; + ret->pixy = pixy; + ret->y = placey; + ret->x = placex; + ret->parse_start = parse_start; + if(ncplane_pile(n)){ + notcurses* nc = ncplane_notcurses(n); ret->next = nc->sprixelcache; nc->sprixelcache = ret; -//fprintf(stderr, "%p %p %p\n", nc->sprixelcache, ret, nc->sprixelcache->next); + ret->id = sprixelid; } } return ret; } -// 'y' and 'x' are the cell geometry, not the pixel geometry. takes -// ownership of 's' on success. -int sprixel_load(sprixel* spx, char* s, int bytes, int placey, int placex, - int pixy, int pixx, int parse_start){ - assert(spx->n); - spx->glyph = s; - spx->glyphlen = bytes; - spx->invalidated = SPRIXEL_INVALIDATED; - spx->pixx = pixx; - spx->pixy = pixy; - spx->y = placey; - spx->x = placex; - spx->parse_start = parse_start; - return 0; -} - int sprite_wipe_cell(const notcurses* nc, sprixel* s, int ycell, int xcell){ if(s->invalidated == SPRIXEL_HIDE){ // no need to do work if we're killing it return 0; diff --git a/src/lib/visual-details.h b/src/lib/visual-details.h index a20d12757..f67e25808 100644 --- a/src/lib/visual-details.h +++ b/src/lib/visual-details.h @@ -12,7 +12,6 @@ extern "C" { struct blitset; struct ncplane; -struct sprixel; struct ncvisual_details; typedef struct ncvisual { @@ -22,7 +21,6 @@ typedef struct ncvisual { // lines are sometimes padded. this many true bytes per row in data. int rowstride; bool owndata; // we own data iff owndata == true - struct sprixel* spx; // non-NULL if this is NCBLIT_PIXEL } ncvisual; static inline void diff --git a/src/lib/visual.c b/src/lib/visual.c index 43d835f98..5ebf65f5a 100644 --- a/src/lib/visual.c +++ b/src/lib/visual.c @@ -429,7 +429,6 @@ ncplane* ncvisual_render_cells(notcurses* nc, ncvisual* ncv, const struct blitse int leny, int lenx, ncplane* n, ncscale_e scaling, uint64_t flags){ int disprows, dispcols; - ncplane* createdn = NULL; //fprintf(stderr, "INPUT N: %p\n", n); if(n == NULL){ // create plane if(scaling == NCSCALE_NONE || scaling == NCSCALE_NONE_HIRES){ @@ -463,7 +462,6 @@ ncplane* ncvisual_render_cells(notcurses* nc, ncvisual* ncv, const struct blitse if((n = ncplane_create(notcurses_stdplane(nc), &nopts)) == NULL){ return NULL; } - createdn = n; placey = 0; placex = 0; }else{ @@ -501,7 +499,7 @@ ncplane* ncvisual_render_cells(notcurses* nc, ncvisual* ncv, const struct blitse bargs.placex = placex; bargs.u.cell.blendcolors = flags & NCVISUAL_OPTION_BLEND; if(ncvisual_blit(ncv, disprows, dispcols, n, bset, leny, lenx, &bargs)){ - ncplane_destroy(createdn); + ncplane_destroy(n); return NULL; } return n; @@ -526,7 +524,6 @@ ncplane* ncvisual_render_pixels(notcurses* nc, ncvisual* ncv, const struct blits dispcols = ncv->cols; disprows = ncv->rows; } - ncplane* createdn = NULL; //fprintf(stderr, "INPUT N: %p rows: %d cols: %d 0x%016lx\n", n ? n : NULL, disprows, dispcols, flags); if(n == NULL){ // create plane if(scaling == NCSCALE_NONE || scaling == NCSCALE_NONE_HIRES){ @@ -562,7 +559,6 @@ ncplane* ncvisual_render_pixels(notcurses* nc, ncvisual* ncv, const struct blits } placey = 0; placex = 0; - createdn = n; }else{ if(scaling != NCSCALE_NONE && scaling != NCSCALE_NONE_HIRES){ ncplane_dim_yx(n, &disprows, &dispcols); @@ -602,25 +598,12 @@ ncplane* ncvisual_render_pixels(notcurses* nc, ncvisual* ncv, const struct blits bargs.u.pixel.celldimx = nc->tcache.cellpixx; bargs.u.pixel.celldimy = nc->tcache.cellpixy; bargs.u.pixel.colorregs = nc->tcache.color_registers; - if(ncv->spx == NULL){ - int cols = dispcols / bargs.u.pixel.celldimx + !!(dispcols % bargs.u.pixel.celldimx); - int rows = disprows / bargs.u.pixel.celldimy + !!(disprows % bargs.u.pixel.celldimy); - if((ncv->spx = sprixel_alloc(n, rows, cols)) == NULL){ - goto err; - } - } - bargs.u.pixel.spx = ncv->spx; + bargs.u.pixel.sprixelid = nc->tcache.sprixelnonce++; if(ncvisual_blit(ncv, disprows, dispcols, n, bset, disprows, dispcols, &bargs)){ - goto err; + ncplane_destroy(n); + return NULL; } return n; - -err: - if(ncv->spx){ - sprixel_free(ncv->spx); - } - ncplane_destroy(createdn); - return NULL; } ncplane* ncvisual_render(notcurses* nc, ncvisual* ncv, const struct ncvisual_options* vopts){