[kitty] speed up kitty_null() with parse_start

This commit is contained in:
nick black 2021-03-22 02:01:58 -04:00 committed by Nick Black
parent 889e81d648
commit 760ee94b04
4 changed files with 35 additions and 24 deletions

View File

@ -65,7 +65,8 @@ typedef struct sprixel {
int y, x; int y, x;
int dimy, dimx; // cell geometry int dimy, dimx; // cell geometry
int pixy, pixx; // pixel geometry (might be smaller than cell geo) int pixy, pixx; // pixel geometry (might be smaller than cell geo)
int* tacache; // transparency-annihilatin cache (dimy * dimx) int* tacache; // transparency-annihilatin cache (dimy * dimx)
int parse_start; // where to start parsing for cell wipes
} 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
@ -725,7 +726,8 @@ void sprixel_free(sprixel* s);
void sprixel_hide(sprixel* s); void sprixel_hide(sprixel* s);
// dimy and dimx are cell geometry, not pixel // dimy and dimx are cell geometry, not pixel
sprixel* sprixel_create(ncplane* n, const char* s, int bytes, int placey, int placex, sprixel* sprixel_create(ncplane* n, const char* s, int bytes, int placey, int placex,
int sprixelid, int dimy, int dimx, int pixy, int pixx); int sprixelid, int dimy, int dimx, int pixy, int pixx,
int parse_start);
API int sprite_wipe_cell(const notcurses* nc, sprixel* s, int y, int x); 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_annihilate(const notcurses* nc, const ncpile* p, FILE* out, sprixel* s);
int sprite_kitty_clear_all(const notcurses* nc); int sprite_kitty_clear_all(const notcurses* nc);
@ -1126,8 +1128,10 @@ egc_rtl(const char* egc, int* bytes){
// new, purpose-specific plane. // new, purpose-specific plane.
static inline int static inline int
plane_blit_sixel(ncplane* n, const char* s, int bytes, int placey, int placex, plane_blit_sixel(ncplane* n, const char* s, int bytes, int placey, int placex,
int leny, int lenx, int sprixelid, int dimy, int dimx){ int leny, int lenx, int sprixelid, int dimy, int dimx,
sprixel* spx = sprixel_create(n, s, bytes, placey, placex, sprixelid, leny, lenx, dimy, dimx); int parse_start){
sprixel* spx = sprixel_create(n, s, bytes, placey, placex, sprixelid,
leny, lenx, dimy, dimx, parse_start);
if(spx == NULL){ if(spx == NULL){
return -1; return -1;
} }

View File

@ -132,7 +132,7 @@ int sprite_kitty_cell_wipe(const notcurses* nc, sprixel* s, int ycell, int xcell
if((ycell + 1) * ypixels > s->pixy){ if((ycell + 1) * ypixels > s->pixy){
targy = s->pixy - ycell * ypixels; targy = s->pixy - ycell * ypixels;
} }
char* c = s->glyph; char* c = s->glyph + s->parse_start;
//fprintf(stderr, "TARGET AREA: %d x %d @ %dx%d of %d/%d (%d/%d) len %zu\n", targy, targx, ycell, xcell, s->dimy, s->dimx, s->pixy, s->pixx, strlen(c)); //fprintf(stderr, "TARGET AREA: %d x %d @ %dx%d of %d/%d (%d/%d) len %zu\n", targy, targx, ycell, xcell, s->dimy, s->dimx, s->pixy, s->pixx, strlen(c));
// every pixel was 4 source bytes, 32 bits, 6.33 base64 bytes. every 3 input pixels is // every pixel was 4 source bytes, 32 bits, 6.33 base64 bytes. every 3 input pixels is
// 12 bytes (96 bits), an even 16 base64 bytes. there is chunking to worry about. there // 12 bytes (96 bits), an even 16 base64 bytes. there is chunking to worry about. there
@ -142,11 +142,6 @@ int sprite_kitty_cell_wipe(const notcurses* nc, sprixel* s, int ycell, int xcell
int chunkedhandled = 0; int chunkedhandled = 0;
const int chunks = totalpixels / RGBA_MAXLEN + !!(totalpixels % RGBA_MAXLEN); const int chunks = totalpixels / RGBA_MAXLEN + !!(totalpixels % RGBA_MAXLEN);
while(targy && chunkedhandled < chunks){ // need to null out |targy| rows of |targx| pixels, track with |thisrow| while(targy && chunkedhandled < chunks){ // need to null out |targy| rows of |targx| pixels, track with |thisrow|
//fprintf(stderr, "CHUNK %d NEXTPIXEL: %d NEXTCHUNK: %d\n", chunkedhandled, nextpixel, nextchunk);
while(*c != ';'){
++c;
}
++c;
//fprintf(stderr, "PLUCKING FROM [%s]\n", c); //fprintf(stderr, "PLUCKING FROM [%s]\n", c);
int inchunk = totalpixels - chunkedhandled * RGBA_MAXLEN; int inchunk = totalpixels - chunkedhandled * RGBA_MAXLEN;
if(inchunk > RGBA_MAXLEN){ if(inchunk > RGBA_MAXLEN){
@ -184,8 +179,13 @@ int sprite_kitty_cell_wipe(const notcurses* nc, sprixel* s, int ycell, int xcell
} }
} }
c += RGBA_MAXLEN * 4 * 4 / 3; // 4bpp * 4/3 for base64, 4096b per chunk c += RGBA_MAXLEN * 4 * 4 / 3; // 4bpp * 4/3 for base64, 4096b per chunk
c += 8; // new chunk header
++chunkedhandled; ++chunkedhandled;
//fprintf(stderr, "LOOKING NOW AT %u [%s]\n", c - s->glyph, c); //fprintf(stderr, "LOOKING NOW AT %u [%s]\n", c - s->glyph, c);
while(*c != ';'){
++c;
}
++c;
} }
return -1; return -1;
} }
@ -195,7 +195,7 @@ int sprite_kitty_cell_wipe(const notcurses* nc, sprixel* s, int ycell, int xcell
// 16 base64-encoded bytes. 4096 / 16 == 256 3-pixel groups, or 768 pixels. // 16 base64-encoded bytes. 4096 / 16 == 256 3-pixel groups, or 768 pixels.
static int static int
write_kitty_data(FILE* fp, int linesize, int leny, int lenx, write_kitty_data(FILE* fp, int linesize, int leny, int lenx,
const uint32_t* data, int sprixelid){ const uint32_t* data, int sprixelid, int* parse_start){
if(linesize % sizeof(*data)){ if(linesize % sizeof(*data)){
return -1; return -1;
} }
@ -209,7 +209,8 @@ write_kitty_data(FILE* fp, int linesize, int leny, int lenx,
//fprintf(stderr, "total: %d chunks = %d, s=%d,v=%d\n", total, chunks, lenx, leny); //fprintf(stderr, "total: %d chunks = %d, s=%d,v=%d\n", total, chunks, lenx, leny);
while(chunks--){ while(chunks--){
if(totalout == 0){ if(totalout == 0){
fprintf(fp, "\e_Gf=32,s=%d,v=%d,i=%d,a=T,%c=1;", lenx, leny, sprixelid, chunks ? 'm' : 'q'); *parse_start = fprintf(fp, "\e_Gf=32,s=%d,v=%d,i=%d,a=T,%c=1;",
lenx, leny, sprixelid, chunks ? 'm' : 'q');
}else{ }else{
fprintf(fp, "\e_G%sm=%d;", chunks ? "" : "q=1,", chunks ? 1 : 0); fprintf(fp, "\e_G%sm=%d;", chunks ? "" : "q=1,", chunks ? 1 : 0);
} }
@ -258,13 +259,16 @@ int kitty_blit_inner(ncplane* nc, int linesize, int leny, int lenx,
if(fp == NULL){ if(fp == NULL){
return -1; return -1;
} }
if(write_kitty_data(fp, linesize, leny, lenx, data, bargs->pixel.sprixelid)){ int parse_start = 0;
if(write_kitty_data(fp, linesize, leny, lenx, data, bargs->pixel.sprixelid,
&parse_start)){
fclose(fp); fclose(fp);
free(buf); free(buf);
return -1; return -1;
} }
if(plane_blit_sixel(nc, buf, size, bargs->pixel.placey, bargs->pixel.placex, if(plane_blit_sixel(nc, buf, size, bargs->pixel.placey, bargs->pixel.placex,
rows, cols, bargs->pixel.sprixelid, leny, lenx) < 0){ rows, cols, bargs->pixel.sprixelid, leny, lenx,
parse_start) < 0){
free(buf); free(buf);
return -1; return -1;
} }

View File

@ -415,13 +415,12 @@ write_rle(int* printed, int color, FILE* fp, int seenrle, unsigned char crle){
// Emit the sprixel in its entirety, plus enable and disable pixel mode. // Emit the sprixel in its entirety, plus enable and disable pixel mode.
static int static int
write_sixel_data(FILE* fp, int lenx, sixeltable* stab){ write_sixel_data(FILE* fp, int lenx, sixeltable* stab, int* parse_start){
// \e[?80: DECSDM "sixel scrolling" mode (put output at cursor location) // \e[?80: DECSDM "sixel scrolling" mode (put output at cursor location)
// \x90: 8-bit "device control sequence", lowercase q (start sixel) // \x90: 8-bit "device control sequence", lowercase q (start sixel)
// doesn't seem to work with at least xterm; we instead use '\ePq' // doesn't seem to work with at least xterm; we instead use '\ePq'
// FIXME i think we can print DESDM on the first one, and never again // FIXME i think we can print DESDM on the first one, and never again
fprintf(fp, "\e[?80h\ePq"); *parse_start += fprintf(fp, "\e[?80h\ePq");
//fprintf(fp, "\ePq");
// Set Raster Attributes - pan/pad=1 (pixel aspect ratio), Ph=lenx, Pv=leny // Set Raster Attributes - pan/pad=1 (pixel aspect ratio), Ph=lenx, Pv=leny
// using Ph/Pv causes a background to be drawn using color register 0 for all // using Ph/Pv causes a background to be drawn using color register 0 for all
@ -434,10 +433,10 @@ write_sixel_data(FILE* fp, int lenx, sixeltable* stab){
int count = stab->deets[idx].count; int count = stab->deets[idx].count;
//fprintf(stderr, "RGB: %3u %3u %3u DT: %d SUMS: %3d %3d %3d COUNT: %d\n", rgb[0], rgb[1], rgb[2], idx, stab->deets[idx].sums[0] / count * 100 / 255, stab->deets[idx].sums[1] / count * 100 / 255, stab->deets[idx].sums[2] / count * 100 / 255, count); //fprintf(stderr, "RGB: %3u %3u %3u DT: %d SUMS: %3d %3d %3d COUNT: %d\n", rgb[0], rgb[1], rgb[2], idx, stab->deets[idx].sums[0] / count * 100 / 255, stab->deets[idx].sums[1] / count * 100 / 255, stab->deets[idx].sums[2] / count * 100 / 255, count);
//fprintf(fp, "#%d;2;%u;%u;%u", i, rgb[0], rgb[1], rgb[2]); //fprintf(fp, "#%d;2;%u;%u;%u", i, rgb[0], rgb[1], rgb[2]);
fprintf(fp, "#%d;2;%jd;%jd;%jd", i, *parse_start += fprintf(fp, "#%d;2;%jd;%jd;%jd", i,
(intmax_t)(stab->deets[idx].sums[0] * 100 / count / 255), (intmax_t)(stab->deets[idx].sums[0] * 100 / count / 255),
(intmax_t)(stab->deets[idx].sums[1] * 100 / count / 255), (intmax_t)(stab->deets[idx].sums[1] * 100 / count / 255),
(intmax_t)(stab->deets[idx].sums[2] * 100 / count / 255)); (intmax_t)(stab->deets[idx].sums[2] * 100 / count / 255));
} }
int p = 0; int p = 0;
while(p < stab->sixelcount){ while(p < stab->sixelcount){
@ -498,7 +497,8 @@ int sixel_blit_inner(ncplane* nc, int leny, int lenx, sixeltable* stab,
if(fp == NULL){ if(fp == NULL){
return -1; return -1;
} }
if(write_sixel_data(fp, lenx, stab)){ int parse_start = 0;
if(write_sixel_data(fp, lenx, stab, &parse_start)){
fclose(fp); fclose(fp);
free(buf); free(buf);
return -1; return -1;
@ -506,7 +506,8 @@ int sixel_blit_inner(ncplane* nc, int leny, int lenx, sixeltable* stab,
unsigned cols = lenx / bargs->pixel.celldimx + !!(lenx % bargs->pixel.celldimx); unsigned cols = lenx / bargs->pixel.celldimx + !!(lenx % bargs->pixel.celldimx);
unsigned rows = leny / bargs->pixel.celldimy + !!(leny % bargs->pixel.celldimy); unsigned rows = leny / bargs->pixel.celldimy + !!(leny % bargs->pixel.celldimy);
if(plane_blit_sixel(nc, buf, size, bargs->pixel.placey, bargs->pixel.placex, if(plane_blit_sixel(nc, buf, size, bargs->pixel.placey, bargs->pixel.placex,
rows, cols, bargs->pixel.sprixelid, leny, lenx) < 0){ rows, cols, bargs->pixel.sprixelid, leny, lenx,
parse_start) < 0){
free(buf); free(buf);
return -1; return -1;
} }

View File

@ -18,7 +18,8 @@ void sprixel_hide(sprixel* s){
// y and x are the cell geometry, not the pixel geometry // y and x are the cell geometry, not the pixel geometry
sprixel* sprixel_create(ncplane* n, const char* s, int bytes, int placey, int placex, sprixel* sprixel_create(ncplane* n, const char* s, int bytes, int placey, int placex,
int sprixelid, int dimy, int dimx, int pixy, int pixx){ int sprixelid, int dimy, int dimx, int pixy, int pixx,
int parse_start){
sprixel* ret = malloc(sizeof(sprixel)); sprixel* ret = malloc(sizeof(sprixel));
if(ret){ if(ret){
if((ret->glyph = memdup(s, bytes + 1)) == NULL){ if((ret->glyph = memdup(s, bytes + 1)) == NULL){
@ -42,6 +43,7 @@ sprixel* sprixel_create(ncplane* n, const char* s, int bytes, int placey, int pl
ret->pixy = pixy; ret->pixy = pixy;
ret->y = placey; ret->y = placey;
ret->x = placex; ret->x = placex;
ret->parse_start = parse_start;
if(ncplane_pile(n)){ if(ncplane_pile(n)){
notcurses* nc = ncplane_notcurses(n); notcurses* nc = ncplane_notcurses(n);
ret->next = nc->sprixelcache; ret->next = nc->sprixelcache;