[stream] restore erase(), preserve tacache across sixels #1482

pull/1485/head
nick black 3 years ago
parent da0da25269
commit 5e4c07816d
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC

@ -74,7 +74,6 @@ typedef struct sprixel {
int y, x;
int dimy, dimx; // cell geometry
int pixy, pixx; // pixel geometry (might be smaller than cell geo)
sprixcell_e* tacache; // transparency-annihilation cache (dimy * dimx)
// each tacache entry is one of 0 (standard opaque cell), 1 (cell with
// some transparency), 2 (annihilated, excised)
int parse_start; // where to start parsing for cell wipes
@ -124,6 +123,8 @@ typedef struct ncplane {
struct ncplane* boundto;// plane to which we are bound (ourself for roots)
sprixel* sprite; // pointer into the sprixel cache
sprixcell_e* tacache; // transparency-annihilation sprite matrix
int tacachey, tacachex;// tacache geometry FIXME get rid of this
void* userptr; // slot for the user to stick some opaque pointer
int (*resizecb)(struct ncplane*); // callback after parent is resized
@ -767,12 +768,10 @@ int sprite_destroy(const struct notcurses* nc, const struct ncpile* p, FILE* out
void sprixel_free(sprixel* s);
void sprixel_invalidate(sprixel* s);
void sprixel_hide(sprixel* s);
// takes ownership of g on success
sprixel* sprixel_update(sprixel* s, char* g, int bytes);
// dimy and dimx are cell geometry, not pixel. 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, sprixcell_e* tacache);
int parse_start);
API int sprite_wipe_cell(const notcurses* nc, sprixel* s, int y, int x);
int sprite_kitty_annihilate(const notcurses* nc, const ncpile* p, FILE* out, sprixel* s);
int sprite_kitty_init(int fd);
@ -1178,7 +1177,7 @@ 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, tacache);
leny, lenx, dimy, dimx, parse_start);
if(spx == NULL){
return -1;
}
@ -1193,6 +1192,9 @@ plane_blit_sixel(ncplane* n, char* s, int bytes, int placey, int placex,
if(n->sprite){
sprixel_hide(n->sprite);
}
n->tacache = tacache;
n->tacachey = leny;
n->tacachex = lenx;
n->sprite = spx;
return 0;
}

@ -300,11 +300,9 @@ int kitty_blit(ncplane* n, int linesize, const void* data,
// 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->sprite){
sprixel* s = n->sprite;
if(s->dimy == rows && s->dimx == cols){
tacache = s->tacache;
s->tacache = NULL;
if(n->tacache){
if(n->tacachey == rows && n->tacachex == cols){
tacache = n->tacache;
reuse = true;
}
}
@ -329,11 +327,13 @@ int kitty_blit(ncplane* n, int linesize, const void* data,
free(buf);
return -1;
}
// take ownership of |buf| on success
// take ownership of |buf| and |tacache| on success
if(plane_blit_sixel(n, buf, size, bargs->placey, bargs->placex,
rows, cols, bargs->u.pixel.sprixelid, leny, lenx,
parse_start, tacache) < 0){
free(tacache);
if(!reuse){
free(tacache);
}
free(buf);
return -1;
}

@ -355,6 +355,7 @@ ncplane* ncplane_new_internal(notcurses* nc, ncplane* n,
p->name = strdup(nopts->name ? nopts->name : "");
p->halign = NCALIGN_UNALIGNED;
p->valign = NCALIGN_UNALIGNED;
p->tacache = NULL;
if(!n){ // new root/standard plane
p->absy = nopts->y;
p->absx = nopts->x;

@ -938,7 +938,7 @@ rasterize_sprixels(notcurses* nc, const ncpile* p, FILE* out){
ncplane_yx(s->n, &y, &x);
y += s->y;
x += s->x;
//fprintf(stderr, "DRAWING BITMAP %d AT %d/%d\n", s->id, y + nc->stdplane->absy, x + nc->stdplane->absx);
//fprintf(stderr, "DRAWING BITMAP %d AT %d/%d for %p\n", s->id, y + nc->stdplane->absy, x + nc->stdplane->absx, s->n);
if(goto_location(nc, out, y + nc->stdplane->absy, x + nc->stdplane->absx)){
return -1;
}

@ -384,8 +384,7 @@ write_sixel_data(FILE* fp, int lenx, sixeltable* stab, int* parse_start){
// A pixel block is indicated by setting cell_pixels_p().
static inline int
sixel_blit_inner(ncplane* n, int leny, int lenx, sixeltable* stab,
const blitterargs* bargs, unsigned reuse,
sprixcell_e* tacache){
const blitterargs* bargs, sprixcell_e* tacache){
char* buf = NULL;
size_t size = 0;
FILE* fp = open_memstream(&buf, &size);
@ -400,16 +399,12 @@ sixel_blit_inner(ncplane* n, int leny, int lenx, sixeltable* stab,
free(buf);
return -1;
}
// both paths take ownership of buf on success
if(reuse){
sprixel_update(n->sprite, buf, size);
}else{
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;
}
// take ownership of buf on success
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;
}
return 1;
}
@ -447,10 +442,10 @@ int sixel_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.
if(n->sprite){
sprixel* s = n->sprite;
if(s->dimy == rows && s->dimx == cols){
tacache = s->tacache;
if(n->tacache){
//fprintf(stderr, "OUGHT BE A REUSE %d %d %d %d\n", n->tacachey, rows, n->tacachex, cols);
if(n->tacachey == rows && n->tacachex == cols){
tacache = n->tacache;
reuse = true;
}
}
@ -473,7 +468,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(n, leny, lenx, &stable, bargs, reuse, tacache);
int r = sixel_blit_inner(n, leny, lenx, &stable, bargs, tacache);
free(stable.data);
free(stable.deets);
free(stable.table);

@ -2,15 +2,14 @@
void sprixel_free(sprixel* s){
if(s){
free(s->tacache);
free(s->glyph);
free(s);
}
}
void sprixel_hide(sprixel* s){
s->n->sprite = NULL;
s->invalidated = SPRIXEL_HIDE;
s->n->sprite = NULL;
s->n = NULL;
}
@ -29,25 +28,15 @@ sprixel* sprixel_by_id(notcurses* nc, uint32_t id){
return NULL;
}
// s ought already have been scrubbed according to the T-A matrix
sprixel* sprixel_update(sprixel* s, char* g, int bytes){
free(s->glyph);
s->glyph = g;
s->glyphlen = bytes;
s->invalidated = SPRIXEL_INVALIDATED;
return s;
}
// '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, sprixcell_e* tacache){
int parse_start){
sprixel* ret = malloc(sizeof(sprixel));
if(ret){
ret->glyph = s;
ret->glyphlen = bytes;
ret->tacache = tacache;
ret->invalidated = SPRIXEL_INVALIDATED;
ret->n = n;
ret->dimy = dimy;
@ -79,13 +68,13 @@ int sprite_wipe_cell(const notcurses* nc, sprixel* s, int ycell, int xcell){
logerror(nc, "Bad x coordinate %d (%d)\n", xcell, s->dimx);
return -1;
}
if(s->tacache[s->dimx * ycell + xcell] == SPRIXCELL_ANNIHILATED){
if(s->n->tacache[s->dimx * ycell + xcell] == SPRIXCELL_ANNIHILATED){
//fprintf(stderr, "CACHED WIPE %d %d/%d\n", s->id, ycell, xcell);
return 0; // already annihilated
}
// mark the cell as annihilated whether we actually scrubbed it or not,
// so that we use this fact should we move to another frame
s->tacache[s->dimx * ycell + xcell] = SPRIXCELL_ANNIHILATED;
s->n->tacache[s->dimx * ycell + xcell] = SPRIXCELL_ANNIHILATED;
if(!nc->tcache.pixel_cell_wipe){ // sixel has no cell wiping
return -1;
}

@ -394,6 +394,9 @@ int ffmpeg_stream(notcurses* nc, ncvisual* ncv, float timescale,
// all media when we loop =[. we seem to be accurate enough now with the
// tbase/ppd. see https://github.com/dankamongmen/notcurses/issues/1352.
double tbase = av_q2d(ncv->details->fmtctx->streams[ncv->details->stream_index]->time_base);
if(activevopts.n){
ncplane_erase(activevopts.n); // new frame could be partially transparent
}
// decay the blitter explicitly, so that the callback knows the blitter it
// was actually rendered with
auto bset = rgba_blitter(nc, &activevopts);

Loading…
Cancel
Save