From 5eafafa6529c9185f73d07cc36185642c27f8813 Mon Sep 17 00:00:00 2001 From: nick black Date: Mon, 26 Apr 2021 01:06:08 -0400 Subject: [PATCH] kitty: build out auxvec in wipe #1440 --- src/lib/internal.h | 27 +++++---------------------- src/lib/kitty.c | 44 ++++++++++++++++++++++++++++++++++++++------ src/lib/sixel.c | 3 +-- src/lib/sprite.c | 30 ++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 30 deletions(-) diff --git a/src/lib/internal.h b/src/lib/internal.h index 77fa3a6af..4ed6d48d9 100644 --- a/src/lib/internal.h +++ b/src/lib/internal.h @@ -458,7 +458,7 @@ typedef struct tinfo { // this means dialing down their alpha to 0 (in equivalent space). int (*pixel_cell_wipe)(const struct notcurses* nc, sprixel* s, int y, int x); // perform the inverse of pixel_cell_wipe, restoring an annihilated sprixcell. - int (*pixel_rebuild)(const struct notcurses* nc, sprixel* s, int y, int x); + int (*pixel_rebuild)(sprixel* s, int y, int x); int (*pixel_remove)(int id, FILE* out); // kitty only, issue actual delete command int (*pixel_init)(int fd); // called when support is detected int (*pixel_draw)(const struct notcurses* n, const struct ncpile* p, sprixel* s, FILE* out); @@ -932,8 +932,8 @@ int sixel_wipe(const notcurses* nc, sprixel* s, int ycell, int xcell); // throughout to 0. the same trick doesn't work on sixel, but there we // can just print directly over the bitmap. int kitty_wipe(const notcurses* nc, sprixel* s, int ycell, int xcell); -int sixel_rebuild(const notcurses* nc, sprixel* s, int ycell, int xcell); -int kitty_rebuild(const notcurses* nc, sprixel* s, int ycell, int xcell); +int sixel_rebuild(sprixel* s, int ycell, int xcell); +int kitty_rebuild(sprixel* s, int ycell, int xcell); void sprixel_free(sprixel* s); void sprixel_hide(sprixel* s); @@ -958,6 +958,7 @@ sprixel* sprixel_by_id(const ncpile* n, uint32_t id); // these three all use absolute coordinates void sprixel_invalidate(sprixel* s, int y, int x); void sprixel_movefrom(sprixel* s, int y, int x); +void sprixel_debug(FILE* out, const sprixel* s); // create an auxiliary vector suitable for a sprixcell, and zero it out uint8_t* sprixel_auxiliary_vector(const sprixel* s); @@ -973,24 +974,6 @@ sprite_destroy(const notcurses* nc, const ncpile* p, FILE* out, sprixel* s){ return nc->tcache.pixel_destroy(nc, p, out, s); } -__attribute__ ((unused)) static inline void -sprixel_debug(FILE* out, const sprixel* s){ - fprintf(out, "Sprixel %d (%p) %dx%d (%dx%d) @%d/%d state: %d\n", - s->id, s, s->dimy, s->dimx, s->pixy, s->pixx, - s->n ? s->n->absy : 0, s->n ? s->n->absx : 0, - s->invalidated); - if(s->n){ - int idx = 0; - for(int y = 0 ; y < s->dimy ; ++y){ - for(int x = 0 ; x < s->dimx ; ++x){ - fprintf(out, "%d", s->n->tam[idx].state); - ++idx; - } - fprintf(out, "\n"); - } - } -} - // precondition: s->invalidated is SPRIXEL_INVALIDATED or SPRIXEL_MOVED. static inline int sprite_draw(const notcurses* n, const ncpile* p, sprixel* s, FILE* out){ @@ -1000,7 +983,7 @@ sprite_draw(const notcurses* n, const ncpile* p, sprixel* s, FILE* out){ static inline int sprite_rebuild(const notcurses* nc, sprixel* s, int ycell, int xcell){ - return nc->tcache.pixel_rebuild(nc, s, ycell, xcell); + return nc->tcache.pixel_rebuild(s, ycell, xcell); } static inline void diff --git a/src/lib/kitty.c b/src/lib/kitty.c index 36d30a4d1..90ba765db 100644 --- a/src/lib/kitty.c +++ b/src/lib/kitty.c @@ -132,8 +132,31 @@ base64_rgba3(const uint32_t* pixels, size_t pcount, char* b64, bool wipe[static // E: B3(4..7), A3(0..1) // F: A3(2..7) // so we will only ever zero out bytes 4, 5, 9, A, E, and F + +// get the first alpha from the triplet +static inline uint8_t +triplet_alpha1(const char* triplet){ + uint8_t c1 = b64idx(triplet[0x4]); + uint8_t c2 = b64idx(triplet[0x5]); + return (c1 << 2u) | ((c2 & 0x3) >> 4); +} + +static inline uint8_t +triplet_alpha2(const char* triplet){ + uint8_t c1 = b64idx(triplet[0x9]); + uint8_t c2 = b64idx(triplet[0xA]); + return ((c1 & 0xf) << 4u) | ((c2 & 0x3c) >> 2); +} + +static inline uint8_t +triplet_alpha3(const char* triplet){ + uint8_t c1 = b64idx(triplet[0xE]); + uint8_t c2 = b64idx(triplet[0xF]); + return ((c1 & 0x3) << 6u) | c2; +} + static inline int -kitty_null(char* triplet, int skip, int max, int pleft){ +kitty_null(char* triplet, int skip, int max, int pleft, uint8_t* auxvec){ //fprintf(stderr, "SKIP/MAX/PLEFT %d/%d/%d\n", skip, max, pleft); if(pleft > 3){ pleft = 3; @@ -143,24 +166,30 @@ kitty_null(char* triplet, int skip, int max, int pleft){ } //fprintf(stderr, "alpha-nulling %d after %d\n", max, skip); if(skip == 0){ + auxvec[0] = triplet_alpha1(triplet); triplet[0x4] = b64subs[0]; triplet[0x5] = b64subs[b64idx(triplet[0x5]) & 0xf]; if(max > 1){ + auxvec[1] = triplet_alpha2(triplet); triplet[0x9] = b64subs[b64idx(triplet[0x9]) & 0x30]; triplet[0xA] = b64subs[b64idx(triplet[0xA]) & 0x3]; } if(max == 3){ + auxvec[2] = triplet_alpha3(triplet); triplet[0xE] = b64subs[b64idx(triplet[0xE]) & 0x3c]; triplet[0xF] = b64subs[0]; } }else if(skip == 1){ + auxvec[0] = triplet_alpha2(triplet); triplet[0x9] = b64subs[b64idx(triplet[0x9]) & 0x30]; triplet[0xA] = b64subs[b64idx(triplet[0xA]) & 0x3]; if(max == 2){ + auxvec[1] = triplet_alpha3(triplet); triplet[0xE] = b64subs[b64idx(triplet[0xE]) & 0x3c]; triplet[0xF] = b64subs[0]; } }else{ // skip == 2 + auxvec[0] = triplet_alpha3(triplet); triplet[0xE] = b64subs[b64idx(triplet[0xE]) & 0x3c]; triplet[0xF] = b64subs[0]; } @@ -214,15 +243,14 @@ kitty_restore(char* triplet, int skip, int max, int pleft){ #define RGBA_MAXLEN 768 // 768 base64-encoded pixels in 4096 bytes // restore an annihilated sprixcell by copying the alpha values from the // auxiliary vector back into the actual data. we then free the auxvector. -int kitty_rebuild(const notcurses* nc, sprixel* s, int ycell, int xcell){ +int kitty_rebuild(sprixel* s, int ycell, int xcell){ if(s->n->tam[s->dimx * ycell + xcell].state != SPRIXCELL_ANNIHILATED){ //fprintf(stderr, "CACHED WIPE %d %d/%d\n", s->id, ycell, xcell); return 0; // already annihilated, needn't draw glyph in kitty } - (void)nc; // FIXME const int totalpixels = s->pixy * s->pixx; - const int xpixels = nc->tcache.cellpixx; - const int ypixels = nc->tcache.cellpixy; + const int xpixels = s->cellpxx; + const int ypixels = s->cellpxy; int targx = xpixels; if((xcell + 1) * xpixels > s->pixx){ targx = s->pixx - xcell * xpixels; @@ -314,6 +342,7 @@ int kitty_wipe(const notcurses* nc, sprixel* s, int ycell, int xcell){ int chunkedhandled = 0; const int chunks = totalpixels / RGBA_MAXLEN + !!(totalpixels % RGBA_MAXLEN); sprixcell_e state = SPRIXCELL_OPAQUE_KITTY; + int auxvecidx = 0; while(targy && chunkedhandled < chunks){ // need to null out |targy| rows of |targx| pixels, track with |thisrow| //fprintf(stderr, "PLUCKING FROM [%s]\n", c); int inchunk = totalpixels - chunkedhandled * RGBA_MAXLEN; @@ -335,8 +364,11 @@ int kitty_wipe(const notcurses* nc, sprixel* s, int ycell, int xcell){ // the maximum number of pixels we can convert is the minimum of the // pixels remaining in the target row, and the pixels left in the chunk. //fprintf(stderr, "inchunk: %d total: %d triples: %d\n", inchunk, totalpixels, triples); - int chomped = kitty_null(c + tripbytes, tripskip, thisrow, inchunk - triples * 3); + int chomped = kitty_null(c + tripbytes, tripskip, thisrow, + inchunk - triples * 3, auxvec + auxvecidx); assert(chomped >= 0); + auxvecidx += chomped; + assert(auxvecidx <= s->cellpxy * s->cellpxx); thisrow -= chomped; //fprintf(stderr, "POSTCHIMP CHOMP: %d pixoffset: %d next: %d tripbytes: %d tripskip: %d thisrow: %d\n", chomped, pixoffset, nextpixel, tripbytes, tripskip, thisrow); if(thisrow == 0){ diff --git a/src/lib/sixel.c b/src/lib/sixel.c index aafb96741..776b04dc9 100644 --- a/src/lib/sixel.c +++ b/src/lib/sixel.c @@ -746,8 +746,7 @@ int sixel_init(int fd){ return tty_emit("\e[?80;8452h", fd); } -int sixel_rebuild(const notcurses* nc, sprixel* s, int ycell, int xcell){ - (void)nc; +int sixel_rebuild(sprixel* s, int ycell, int xcell){ (void)s; (void)ycell; (void)xcell; diff --git a/src/lib/sprite.c b/src/lib/sprite.c index c608832d8..febc02d79 100644 --- a/src/lib/sprite.c +++ b/src/lib/sprite.c @@ -4,6 +4,36 @@ // FIXME needs be atomic static uint32_t sprixelid_nonce; +void sprixel_debug(FILE* out, const sprixel* s){ + fprintf(out, "Sprixel %d (%p) %dx%d (%dx%d) @%d/%d state: %d\n", + s->id, s, s->dimy, s->dimx, s->pixy, s->pixx, + s->n ? s->n->absy : 0, s->n ? s->n->absx : 0, + s->invalidated); + if(s->n){ + int idx = 0; + for(int y = 0 ; y < s->dimy ; ++y){ + for(int x = 0 ; x < s->dimx ; ++x){ + fprintf(out, "%d", s->n->tam[idx].state); + ++idx; + } + fprintf(out, "\n"); + } + idx = 0; + for(int y = 0 ; y < s->dimy ; ++y){ + for(int x = 0 ; x < s->dimx ; ++x){ + if(s->n->tam[idx].state == SPRIXCELL_ANNIHILATED){ + fprintf(out, "%03d] ", idx); + for(int p = 0 ; p < s->cellpxx * s->cellpxy ; ++p){ + fprintf(out, "%02x ", s->n->tam[idx].auxvector[idx]); + } + fprintf(out, "\n"); + } + ++idx; + } + } + } +} + // doesn't splice us out of any lists, just frees void sprixel_free(sprixel* s){ if(s){