[sprixel] unite TAM allocation/resize path #2240

This commit is contained in:
nick black 2021-10-09 07:43:11 -04:00 committed by nick black
parent 4336aec7d5
commit 5b5e97033d
4 changed files with 48 additions and 89 deletions

View File

@ -1054,47 +1054,26 @@ kitty_blit_core(ncplane* n, int linesize, const void* data, int leny, int lenx,
const blitterargs* bargs, ncpixelimpl_e level){
//fprintf(stderr, "IMAGE: start %p end %p\n", data, (const char*)data + leny * linesize);
int cols = bargs->u.pixel.spx->dimx;
int rows = bargs->u.pixel.spx->dimy;
sprixel* s = bargs->u.pixel.spx;
if(init_sprixel_animation(s)){
return -1;
}
tament* tam = NULL;
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->tam){
if(n->leny == rows && n->lenx == cols){
tam = n->tam;
reuse = true;
}
}
int parse_start = 0;
if(!reuse){
tam = malloc(sizeof(*tam) * rows * cols);
if(tam == NULL){
goto error;
}
memset(tam, 0, sizeof(*tam) * rows * cols);
}
fbuf* f = &s->glyph;
if(write_kitty_data(f, linesize, leny, lenx, cols, data,
bargs, tam, &parse_start, level)){
bargs, n->tam, &parse_start, level)){
goto error;
}
if(level == NCPIXEL_KITTY_STATIC){
s->animating = false;
}
// take ownership of |buf| and |tam| on success.
if(plane_blit_sixel(s, &s->glyph, leny, lenx, parse_start, tam, SPRIXEL_UNSEEN) < 0){
if(plane_blit_sixel(s, &s->glyph, leny, lenx, parse_start, n->tam, SPRIXEL_UNSEEN) < 0){
goto error;
}
return 1;
error:
if(!reuse){
free(tam);
}
fbuf_free(&s->glyph);
return -1;
}

View File

@ -32,8 +32,6 @@ int fbcon_wipe(sprixel* s, int ycell, int xcell){
int fbcon_blit(struct ncplane* n, int linesize, const void* data,
int leny, int lenx, const struct blitterargs* bargs){
uint32_t transcolor = bargs->transcolor;
int cols = bargs->u.pixel.spx->dimx;
int rows = bargs->u.pixel.spx->dimy;
sprixel* s = bargs->u.pixel.spx;
int cdimx = s->cellpxx;
int cdimy = s->cellpxy;
@ -42,21 +40,6 @@ int fbcon_blit(struct ncplane* n, int linesize, const void* data,
if(fbuf_reserve(&s->glyph, flen)){
return -1;
}
tament* tam = NULL;
bool reuse = false;
if(n->tam){
if(n->leny == rows && n->lenx == cols){
tam = n->tam;
reuse = true;
}
}
if(!reuse){
tam = malloc(sizeof(*tam) * rows * cols);
if(tam == NULL){
goto error;
}
memset(tam, 0, sizeof(*tam) * rows * cols);
}
for(int l = 0 ; l < leny ; ++l){
int ycell = l / cdimy;
size_t soffset = l * linesize;
@ -66,32 +49,32 @@ int fbcon_blit(struct ncplane* n, int linesize, const void* data,
for(int c = 0 ; c < lenx ; ++c){
int xcell = c / cdimx;
int tyx = xcell + ycell * bargs->u.pixel.spx->dimx;
if(tam[tyx].state >= SPRIXCELL_ANNIHILATED){
if(n->tam[tyx].state >= SPRIXCELL_ANNIHILATED){
if(rgba_trans_p(*(uint32_t*)src, transcolor)){
ncpixel_set_a((uint32_t*)src, 0); // in case it was transcolor
if(c % cdimx == 0 && l % cdimy == 0){
tam[tyx].state = SPRIXCELL_ANNIHILATED_TRANS;
n->tam[tyx].state = SPRIXCELL_ANNIHILATED_TRANS;
}
}else{
tam[tyx].state = SPRIXCELL_ANNIHILATED;
n->tam[tyx].state = SPRIXCELL_ANNIHILATED;
}
dst[3] = 0;
const int vyx = (l % cdimy) * cdimx + (c % cdimx);
tam[tyx].auxvector[vyx] = src[3];
n->tam[tyx].auxvector[vyx] = src[3];
}else{
if(rgba_trans_p(*(uint32_t*)src, transcolor)){
ncpixel_set_a((uint32_t*)src, 0); // in case it was transcolor
if(c % cdimx == 0 && l % cdimy == 0){
tam[tyx].state = SPRIXCELL_TRANSPARENT;
}else if(tam[tyx].state == SPRIXCELL_OPAQUE_SIXEL){
tam[tyx].state = SPRIXCELL_MIXED_SIXEL;
n->tam[tyx].state = SPRIXCELL_TRANSPARENT;
}else if(n->tam[tyx].state == SPRIXCELL_OPAQUE_SIXEL){
n->tam[tyx].state = SPRIXCELL_MIXED_SIXEL;
}
dst[3] = 0;
}else{
if(c % cdimx == 0 && l % cdimy == 0){
tam[tyx].state = SPRIXCELL_OPAQUE_SIXEL;
}else if(tam[tyx].state == SPRIXCELL_TRANSPARENT){
tam[tyx].state = SPRIXCELL_MIXED_SIXEL;
n->tam[tyx].state = SPRIXCELL_OPAQUE_SIXEL;
}else if(n->tam[tyx].state == SPRIXCELL_TRANSPARENT){
n->tam[tyx].state = SPRIXCELL_MIXED_SIXEL;
}
memcpy(dst + 3, src + 3, 1);
}
@ -103,16 +86,13 @@ int fbcon_blit(struct ncplane* n, int linesize, const void* data,
src += 4;
}
}
scrub_tam_boundaries(tam, leny, lenx, cdimy, cdimx);
if(plane_blit_sixel(s, &s->glyph, leny, lenx, 0, tam, SPRIXEL_INVALIDATED) < 0){
scrub_tam_boundaries(n->tam, leny, lenx, cdimy, cdimx);
if(plane_blit_sixel(s, &s->glyph, leny, lenx, 0, n->tam, SPRIXEL_INVALIDATED) < 0){
goto error;
}
return 1;
error:
if(!reuse){
free(tam);
}
fbuf_free(&s->glyph);
s->glyph.size = 0;
return -1;

View File

@ -911,38 +911,16 @@ int sixel_blit(ncplane* n, int linesize, const void* data, int leny, int lenx,
memset(stable.deets, 0, sizeof(*stable.deets) * colorregs);
int cols = bargs->u.pixel.spx->dimx;
int rows = bargs->u.pixel.spx->dimy;
tament* tam = NULL;
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->tam){
if(n->leny == rows && n->lenx == cols){
tam = n->tam;
reuse = true;
}
typeof(bargs->u.pixel.spx->needs_refresh) rmatrix;
rmatrix = malloc(sizeof(*rmatrix) * rows * cols);
if(rmatrix == NULL){
sixelmap_free(stable.map);
free(stable.deets);
return -1;
}
if(!reuse){
tam = malloc(sizeof(*tam) * rows * cols);
if(tam == NULL){
sixelmap_free(stable.map);
free(stable.deets);
return -1;
}
memset(tam, 0, sizeof(*tam) * rows * cols);
}else{
typeof(bargs->u.pixel.spx->needs_refresh) rmatrix;
rmatrix = malloc(sizeof(*rmatrix) * rows * cols);
if(rmatrix == NULL){
sixelmap_free(stable.map);
free(stable.deets);
return -1;
}
bargs->u.pixel.spx->needs_refresh = rmatrix;
}
if(extract_color_table(data, linesize, cols, leny, lenx, &stable, tam, bargs)){
if(!reuse){
free(tam);
}
bargs->u.pixel.spx->needs_refresh = rmatrix;
assert(n->tam);
if(extract_color_table(data, linesize, cols, leny, lenx, &stable, n->tam, bargs)){
free(bargs->u.pixel.spx->needs_refresh);
sixelmap_free(stable.map);
free(stable.deets);
@ -950,7 +928,7 @@ int sixel_blit(ncplane* n, int linesize, const void* data, int leny, int lenx,
}
refine_color_table(data, linesize, bargs->begy, bargs->begx, leny, lenx, &stable);
// takes ownership of sixelmap on success
int r = sixel_blit_inner(leny, lenx, &stable, bargs->u.pixel.spx, tam);
int r = sixel_blit_inner(leny, lenx, &stable, bargs->u.pixel.spx, n->tam);
if(r < 0){
sixelmap_free(stable.map);
}

View File

@ -930,6 +930,15 @@ make_sprixel_plane(notcurses* nc, ncplane* parent, ncvisual* ncv,
return n;
}
static tament*
create_tam(int rows, int cols){
tament* tam = malloc(sizeof(*tam) * rows * cols);
if(tam){
memset(tam, 0, sizeof(*tam) * rows * cols);
}
return tam;
}
// when a sprixel is blitted to a plane, that plane becomes a sprixel plane. it
// must not be used with other output mechanisms unless erased. the plane will
// be shrunk to fit the output, and the output is always placed at the origin.
@ -1010,15 +1019,28 @@ ncplane* ncvisual_render_pixels(notcurses* nc, ncvisual* ncv, const struct blits
bargs.lenx = lenx;
bargs.flags = flags;
bargs.u.pixel.colorregs = nc->tcache.color_registers;
int cols = disppixx / nc->tcache.cellpixx + !!(disppixx % nc->tcache.cellpixx);
int rows = outy / nc->tcache.cellpixy + !!(outy % nc->tcache.cellpixy);
if(n->sprite == NULL){
int cols = disppixx / nc->tcache.cellpixx + !!(disppixx % nc->tcache.cellpixx);
int rows = outy / nc->tcache.cellpixy + !!(outy % nc->tcache.cellpixy);
if((n->sprite = sprixel_alloc(&nc->tcache, n, rows, cols)) == NULL){
ncplane_destroy(createdn);
return NULL;
}
if((n->tam = create_tam(rows, cols)) == NULL){
ncplane_destroy(createdn);
return NULL;;
}
}else{
n->sprite = sprixel_recycle(n);
if(n->sprite->dimy != rows || n->sprite->dimx != cols){
free(n->tam);
if((n->tam = create_tam(rows, cols)) == NULL){
ncplane_destroy(createdn);
return NULL;;
}
}
n->sprite->dimx = cols;
n->sprite->dimy = rows;
}
bargs.u.pixel.spx = n->sprite;
// FIXME need to pull off the ncpile's sprixellist if anything below fails!