Detach sprixel from ncvisual

The ncvisual can't own the sprixel -- we could very well
blit it twice to two different planes, wipe cells from one
and not the other, and not want those shared. Instead, it's
owned by the plane. This clears up the ownership/lifetime
story quite a bit, and closes #1548, where only the most
recent of several blittings of a sprixel was visible.
This commit is contained in:
nick black 2021-04-17 23:49:01 -04:00
parent 8c6cd6a630
commit 2d73ba79e4
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC
5 changed files with 18 additions and 43 deletions

View File

@ -547,7 +547,7 @@ ncdirect_render_visual(ncdirect* n, ncvisual* ncv, ncblitter_e blitfxn,
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, ncv, rows, cols, 0, 0)) == NULL){
if((bargs.u.pixel.spx = sprixel_alloc(ncdv, rows, cols, 0, 0)) == NULL){
free_plane(ncdv);
return NULL;
}

View File

@ -922,10 +922,10 @@ void sprixel_hide(sprixel* s);
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, struct ncvisual* ncv, int dimy, int dimx,
int placey, int placex);
sprixel* sprixel_recycle(ncplane* n, struct ncvisual* ncv);
// dimy and dimx are cell geometry, not pixel.
sprixel* sprixel_alloc(ncplane* n, int dimy, int dimx, int placey, int placex);
sprixel* sprixel_recycle(ncplane* n);
// 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);
int sprite_wipe_cell(const notcurses* nc, sprixel* s, int y, int x);

View File

@ -9,25 +9,22 @@ void sprixel_free(sprixel* s){
if(s->n){
s->n->sprite = NULL;
}
if(s->ncv){
s->ncv->spx = NULL;
}
free(s->glyph);
free(s);
}
}
sprixel* sprixel_recycle(ncplane* n, ncvisual* ncv){
sprixel* sprixel_recycle(ncplane* n){
assert(n->sprite);
const notcurses* nc = ncplane_notcurses_const(n);
if(nc->tcache.pixel_destroy == sprite_kitty_annihilate){
sprixel* hides = n->sprite ? n->sprite : ncv->spx;
assert(hides);
sprixel* hides = n->sprite;
int dimy = hides->dimy;
int dimx = hides->dimx;
int y = hides->y;
int x = hides->x;
sprixel_hide(hides);
return sprixel_alloc(n, ncv, dimy, dimx, y, x);
return sprixel_alloc(n, dimy, dimx, y, x);
}
return n->sprite;
}
@ -52,10 +49,6 @@ void sprixel_hide(sprixel* s){
s->invalidated = SPRIXEL_HIDE;
s->movedfromy = ncplane_abs_y(s->n);
s->movedfromx = ncplane_abs_x(s->n);
if(s->ncv){
s->ncv->spx = NULL;
s->ncv = NULL;
}
if(s->n){
s->n->sprite = NULL;
s->n = NULL;
@ -86,13 +79,11 @@ sprixel* sprixel_by_id(const notcurses* nc, uint32_t id){
return NULL;
}
sprixel* sprixel_alloc(ncplane* n, ncvisual* ncv, int dimy, int dimx,
int placey, int placex){
sprixel* sprixel_alloc(ncplane* n, int dimy, int dimx, int placey, int placex){
sprixel* ret = malloc(sizeof(sprixel));
if(ret){
memset(ret, 0, sizeof(*ret));
ret->n = n;
ret->ncv = ncv;
ret->dimy = dimy;
ret->dimx = dimx;
ret->y = placey;

View File

@ -25,8 +25,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
// FIXME this cannot live here! it breaks wiping. associate with plane.
struct sprixel* spx; // non-NULL if this is NCBLIT_PIXEL
} ncvisual;
static inline void

View File

@ -700,22 +700,17 @@ 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 || n->sprite == NULL){
if(n->sprite == 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_hide(ncv->spx);
}
if(n->sprite){
sprixel_hide(n->sprite);
}
if((ncv->spx = sprixel_alloc(n, ncv, rows, cols, placey, placex)) == NULL){
goto err;
if((n->sprite = sprixel_alloc(n, rows, cols, placey, placex)) == NULL){
ncplane_destroy(createdn);
return NULL;
}
}else{
ncv->spx = sprixel_recycle(n, ncv);
n->sprite = sprixel_recycle(n);
}
bargs.u.pixel.spx = ncv->spx;
bargs.u.pixel.spx = n->sprite;
// FIXME only set this if cursor is indeed hidden
if(nc->tcache.sprixel_cursor_hack){
bargs.u.pixel.cursor_hack = nc->tcache.civis;
@ -723,16 +718,10 @@ ncplane* ncvisual_render_pixels(notcurses* nc, ncvisual* ncv, const struct blits
bargs.u.pixel.cursor_hack = NULL;
}
if(ncvisual_blit(ncv, disprows, dispcols, n, bset, disprows, dispcols, &bargs)){
goto err;
ncplane_destroy(createdn);
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){
@ -788,9 +777,6 @@ ncvisual* ncvisual_from_plane(const ncplane* n, ncblitter_e blit, int begy, int
}
void ncvisual_destroy(ncvisual* ncv){
if(ncv->spx){
ncv->spx->ncv = NULL;
}
if(visual_implementation){
visual_implementation->visual_destroy(ncv);
}