[sixel] create sixelmap for rematerialization #1440

This commit is contained in:
nick black 2021-04-27 12:27:19 -04:00 committed by Nick Black
parent eb5c9185e5
commit 262550c5ea
3 changed files with 59 additions and 5 deletions

View File

@ -32,6 +32,7 @@ extern "C" {
#define ALLOC __attribute__((malloc)) __attribute__((warn_unused_result)) #define ALLOC __attribute__((malloc)) __attribute__((warn_unused_result))
struct esctrie; struct esctrie;
struct sixelmap;
struct ncvisual_details; struct ncvisual_details;
// Does this glyph completely obscure the background? If so, there's no need // Does this glyph completely obscure the background? If so, there's no need
@ -163,7 +164,7 @@ typedef struct tament {
typedef struct sprixel { typedef struct sprixel {
char* glyph; // glyph; can be quite large char* glyph; // glyph; can be quite large
int glyphlen; // length of the glyph in bytes int glyphlen; // length of the glyph in bytes
uint32_t id; // embedded into glusters field of nccell, 24 bits uint32_t id; // embedded into gcluster field of nccell, 24 bits
// both the plane and visual can die before the sprixel does. they are // both the plane and visual can die before the sprixel does. they are
// responsible in such a case for NULLing out this link themselves. // responsible in such a case for NULLing out this link themselves.
struct ncplane* n; // associated ncplane struct ncplane* n; // associated ncplane
@ -176,10 +177,13 @@ typedef struct sprixel {
int cellpxy, cellpxx; // cell-pixel geometry at time of creation int cellpxy, cellpxx; // cell-pixel geometry at time of creation
// each tacache entry is one of 0 (standard opaque cell), 1 (cell with // each tacache entry is one of 0 (standard opaque cell), 1 (cell with
// some transparency), 2 (annihilated, excised) // some transparency), 2 (annihilated, excised)
int parse_start; // where to start parsing for cell wipes
int movedfromy; // for SPRIXEL_MOVED, the starting absolute position, int movedfromy; // for SPRIXEL_MOVED, the starting absolute position,
int movedfromx; // so that we can damage old cells when redrawn int movedfromx; // so that we can damage old cells when redrawn
bool wipes_outstanding; // do we need execute wipes on move? // only used for kitty-based sprixels
int parse_start; // where to start parsing for cell wipes
// only used for sixel-based sprixels
struct sixelmap* smap; // copy of palette indices + transparency bits
bool wipes_outstanding; // do we need rebuild the sixel next render?
} sprixel; } sprixel;
// A plane is memory for some rectilinear virtual window, plus current cursor // A plane is memory for some rectilinear virtual window, plus current cursor
@ -966,6 +970,7 @@ sprixel* sprixel_by_id(const ncpile* n, uint32_t id);
void sprixel_invalidate(sprixel* s, int y, int x); void sprixel_invalidate(sprixel* s, int y, int x);
void sprixel_movefrom(sprixel* s, int y, int x); void sprixel_movefrom(sprixel* s, int y, int x);
void sprixel_debug(FILE* out, const sprixel* s); void sprixel_debug(FILE* out, const sprixel* s);
void free_sixelmap(struct sixelmap *s);
// create an auxiliary vector suitable for a sprixcell, and zero it out // create an auxiliary vector suitable for a sprixcell, and zero it out
uint8_t* sprixel_auxiliary_vector(const sprixel* s); uint8_t* sprixel_auxiliary_vector(const sprixel* s);

View File

@ -10,6 +10,51 @@ typedef enum {
SIXEL_P2_TRANS = 1, SIXEL_P2_TRANS = 1,
} sixel_p2_e; } sixel_p2_e;
// we keep a copy of the visual data, reduced to a color index and a
// transparency bit per pixel. we keep the two arrays separate so the
// transparency bits don't absolutely destroy cache efficiency for the
// data array. this allows us to rebuild wiped sprixcells by simply
// rerunning the sprixel generation process following palette quantization,
// which is much, much easier than rebuilding inline, and can be done at
// the same time as wiping, and batches them both, and is probably just as
// fast (slow) as the complex in-place rebuild would be. there is, of course,
// a memory cost of about 1.125MB for a 1024x1024 sixel, but at least we
// needn't muck with auxvectors.
typedef struct sixelmap {
uint8_t* pixels; // 1 byte per pixel, index into color table
uint8_t* transmap; // 1 bit per pixel, 1 == transparent, 0 == opaque
} sixelmap;
// whip up an all-zero sixelmap for the specified number of pixels
static sixelmap*
create_sixelmap(int pixels){
sixelmap* ret = malloc(sizeof(*ret));
if(ret){
size_t pixsize = sizeof(*ret->pixels) * pixels;
ret->pixels = malloc(pixsize);
if(ret->pixels){
size_t transsize = (pixels + 7) / 8;
ret->transmap = malloc(transsize);
if(ret->transmap){
memset(ret->transmap, 0, transsize);
memset(ret->pixels, 0, pixsize);
return ret;
}
free(ret->pixels);
}
free(ret);
}
return NULL;
}
void free_sixelmap(sixelmap *s){
if(s){
free(s->transmap);
free(s->pixels);
free(s);
}
}
// the P2 parameter on a sixel specifies how unspecified pixels are drawn. // the P2 parameter on a sixel specifies how unspecified pixels are drawn.
// if P2 is 1, unspecified pixels are transparent. otherwise, they're drawn // if P2 is 1, unspecified pixels are transparent. otherwise, they're drawn
// as something else. some terminals (e.g. foot) can draw more quickly if // as something else. some terminals (e.g. foot) can draw more quickly if
@ -49,6 +94,7 @@ typedef struct cdetails {
// second pass: construct data for extracted colors over the sixels // second pass: construct data for extracted colors over the sixels
typedef struct sixeltable { typedef struct sixeltable {
sixelmap* map; // copy of palette indices / transparency bits
// FIXME keep these internal to palette extraction; finalize there // FIXME keep these internal to palette extraction; finalize there
int colors; int colors;
cdetails* deets; // |colorregs| cdetails structures cdetails* deets; // |colorregs| cdetails structures
@ -469,6 +515,7 @@ int sixel_blit(ncplane* n, int linesize, const void* data,
colorregs = 256; colorregs = 256;
} }
sixeltable stable = { sixeltable stable = {
.map = create_sixelmap(sixelcount * 6),
.data = malloc(colorregs * sixelcount), .data = malloc(colorregs * sixelcount),
.deets = malloc(colorregs * sizeof(cdetails)), .deets = malloc(colorregs * sizeof(cdetails)),
.table = malloc(colorregs * CENTSIZE), .table = malloc(colorregs * CENTSIZE),
@ -477,7 +524,9 @@ int sixel_blit(ncplane* n, int linesize, const void* data,
.colors = 0, .colors = 0,
.p2 = SIXEL_P2_ALLOPAQUE, .p2 = SIXEL_P2_ALLOPAQUE,
}; };
if(stable.data == NULL || stable.deets == NULL || stable.table == NULL){ if(stable.data == NULL || stable.deets == NULL || stable.table == NULL
|| stable.map == NULL){
free_sixelmap(stable.map);
free(stable.table); free(stable.table);
free(stable.deets); free(stable.deets);
free(stable.data); free(stable.data);

View File

@ -40,6 +40,7 @@ void sprixel_free(sprixel* s){
if(s->n){ if(s->n){
s->n->sprite = NULL; s->n->sprite = NULL;
} }
free_sixelmap(s->smap);
free(s->glyph); free(s->glyph);
free(s); free(s);
} }
@ -131,7 +132,6 @@ sprixel* sprixel_alloc(ncplane* n, int dimy, int dimx, int placey, int placex){
ret->y = placey; ret->y = placey;
ret->x = placex; ret->x = placex;
ret->id = ++sprixelid_nonce; ret->id = ++sprixelid_nonce;
ret->wipes_outstanding = false;
//fprintf(stderr, "LOOKING AT %p (p->n = %p)\n", ret, ret->n); //fprintf(stderr, "LOOKING AT %p (p->n = %p)\n", ret, ret->n);
if(ncplane_pile(ret->n)){ if(ncplane_pile(ret->n)){
ncpile* np = ncplane_pile(ret->n); ncpile* np = ncplane_pile(ret->n);