From 645b61e9dcfcdfeceb3f015b1b669ca5bee99bd9 Mon Sep 17 00:00:00 2001 From: nick black Date: Mon, 15 Mar 2021 00:13:55 -0400 Subject: [PATCH] [pixel] pass celldimy through blitterargs #1401 --- include/notcurses/notcurses.h | 4 -- src/lib/direct.cpp | 1 + src/lib/egcpool.h | 8 +-- src/lib/internal.h | 12 ++++ src/lib/kitty.c | 15 +++-- src/lib/render.c | 116 ++++++++++++++++------------------ src/lib/sixel.c | 14 ++-- src/lib/visual.cpp | 1 + 8 files changed, 87 insertions(+), 84 deletions(-) diff --git a/include/notcurses/notcurses.h b/include/notcurses/notcurses.h index fb100251a..5f38433d3 100644 --- a/include/notcurses/notcurses.h +++ b/include/notcurses/notcurses.h @@ -586,10 +586,6 @@ typedef struct nccell { // are single-byte ASCII-derived values. The XXXXXX is interpreted as a 24-bit // index into the egcpool. These pools may thus be up to 16MB. // - // A pixel graphic (a "sprixel") is indicated by the value 0x02XXXXXX. This - // is safe for the same reasons as a spilled EGC. The remaining 24 bits are - // an identifier for the sprixel cache, shared across the notcurses context. - // // The cost of this scheme is that the character 0x01 (SOH) cannot be encoded // in a nccell, which is absolutely fine because what 70s horseshit is SOH? // It must not be allowed through the API, or havoc will result. diff --git a/src/lib/direct.cpp b/src/lib/direct.cpp index 69f12e4a5..f6dae6056 100644 --- a/src/lib/direct.cpp +++ b/src/lib/direct.cpp @@ -519,6 +519,7 @@ ncdirectv* ncdirect_render_frame(ncdirect* n, const char* file, blitterargs bargs = { .pixel = { .celldimx = n->tcache.cellpixx, + .celldimy = n->tcache.cellpixy, .colorregs = n->tcache.color_registers, }, }; diff --git a/src/lib/egcpool.h b/src/lib/egcpool.h index f1da484d5..fc9d6b1cd 100644 --- a/src/lib/egcpool.h +++ b/src/lib/egcpool.h @@ -256,16 +256,10 @@ cell_extended_p(const nccell* c){ return (htole(c->gcluster) & htole(0xff000000ul)) == htole(0x01000000ul); } -// Is the cell a sprixel? -static inline bool -cell_pixels_p(const nccell* c){ - return (htole(c->gcluster) & htole(0xff000000ul)) == htole(0x02000000ul); -} - // Is the cell simple (a UTF8-encoded EGC of four bytes or fewer)? static inline bool cell_simple_p(const nccell* c){ - return !cell_pixels_p(c) && !cell_extended_p(c); + return !cell_extended_p(c); } // only applies to complex cells, do not use on simple cells diff --git a/src/lib/internal.h b/src/lib/internal.h index 80fb17036..d222f357c 100644 --- a/src/lib/internal.h +++ b/src/lib/internal.h @@ -401,6 +401,7 @@ typedef union { unsigned blendcolors; // for cells struct { int celldimx; // horizontal pixels per cell + int celldimy; // vertical pixels per cell int colorregs; // number of color registers } pixel; // for pixels } blitterargs; @@ -1068,6 +1069,17 @@ egc_rtl(const char* egc, int* bytes){ return s; } +static inline int +plane_blit_sixel(ncplane* n, const char* s, int bytes, int leny, int lenx){ + (void)n; + (void)s; + (void)bytes; + (void)leny; + (void)lenx; + // FIXME + return 0; +} + // lowest level of cell+pool setup. if the EGC changes the output to RTL, it // must be suffixed with a LTR-forcing character by now. The four bits of // CELL_BLITTERSTACK_MASK ought already be initialized. If gcluster is four diff --git a/src/lib/kitty.c b/src/lib/kitty.c index fa3028edb..34203b7bb 100644 --- a/src/lib/kitty.c +++ b/src/lib/kitty.c @@ -118,9 +118,10 @@ write_kitty_data(FILE* fp, int linesize, int leny, int lenx, const uint32_t* dat // Kitty graphics blitter. Kitty can take in up to 4KiB at a time of (optionally // deflate-compressed) 24bit RGB. -int kitty_blit_inner(ncplane* nc, int placey, int placex, int linesize, - int leny, int lenx, unsigned cellpixx, const void* data){ - unsigned width = lenx / cellpixx + !!(lenx % cellpixx); +int kitty_blit_inner(ncplane* nc, int linesize, int leny, int lenx, + const void* data, const blitterargs* bargs){ + int rows = leny / bargs->pixel.celldimx + !!(leny % bargs->pixel.celldimx); + int cols = lenx / bargs->pixel.celldimx + !!(lenx % bargs->pixel.celldimx); char* buf = NULL; size_t size = 0; FILE* fp = open_memstream(&buf, &size); @@ -132,8 +133,7 @@ int kitty_blit_inner(ncplane* nc, int placey, int placex, int linesize, free(buf); return -1; } - nccell* c = ncplane_cell_ref_yx(nc, placey, placex); - if(pool_blit_direct(&nc->pool, c, buf, size, width) < 0){ + if(plane_blit_sixel(nc, buf, size, rows, cols) < 0){ free(buf); return -1; } @@ -147,9 +147,10 @@ int kitty_blit(ncplane* nc, int placey, int placex, int linesize, int leny, int lenx, const blitterargs* bargs){ (void)begy; (void)begx; + (void)placey; + (void)placex; //fprintf(stderr, "s=%d,v=%d\n", lenx, leny); - int r = kitty_blit_inner(nc, placey, placex, linesize, leny, lenx, - bargs->pixel.celldimx, data); + int r = kitty_blit_inner(nc, linesize, leny, lenx, data, bargs); if(r < 0){ return -1; } diff --git a/src/lib/render.c b/src/lib/render.c index 0ba555146..e10962db5 100644 --- a/src/lib/render.c +++ b/src/lib/render.c @@ -960,76 +960,72 @@ notcurses_rasterize_inner(notcurses* nc, const ncpile* p, FILE* out){ if(goto_location(nc, out, y, x, &nc->rstate.hardcursorpos)){ return -1; } - if(!cell_pixels_p(srccell)){ - // set the style. this can change the color back to the default; if it - // does, we need update our elision possibilities. - if(term_setstyles(out, nc, srccell)){ + // set the style. this can change the color back to the default; if it + // does, we need update our elision possibilities. + if(term_setstyles(out, nc, srccell)){ + return -1; + } + // if our cell has a default foreground *or* background, we can elide + // the default set iff one of: + // * we are a partial glyph, and the previous was default on both, or + // * we are a no-foreground glyph, and the previous was default background, or + // * we are a no-background glyph, and the previous was default foreground + bool nobackground = cell_nobackground_p(srccell); + if((cell_fg_default_p(srccell)) || (!nobackground && cell_bg_default_p(srccell))){ + if(raster_defaults(nc, cell_fg_default_p(srccell), + !nobackground && cell_bg_default_p(srccell), out)){ return -1; } - // if our cell has a default foreground *or* background, we can elide - // the default set iff one of: - // * we are a partial glyph, and the previous was default on both, or - // * we are a no-foreground glyph, and the previous was default background, or - // * we are a no-background glyph, and the previous was default foreground - bool nobackground = cell_nobackground_p(srccell); - if((cell_fg_default_p(srccell)) || (!nobackground && cell_bg_default_p(srccell))){ - if(raster_defaults(nc, cell_fg_default_p(srccell), - !nobackground && cell_bg_default_p(srccell), out)){ + } + // if our cell has a non-default foreground, we can elide the + // non-default foreground set iff either: + // * the previous was non-default, and matches what we have now, or + // * we are a no-foreground glyph (iswspace() is true) + if(cell_fg_palindex_p(srccell)){ // palette-indexed foreground + if(emit_fg_palindex(nc, out, srccell)){ + return -1; + } + }else if(!cell_fg_default_p(srccell)){ // rgb foreground + cell_fg_rgb8(srccell, &r, &g, &b); + if(nc->rstate.fgelidable && nc->rstate.lastr == r && nc->rstate.lastg == g && nc->rstate.lastb == b){ + ++nc->stats.fgelisions; + }else{ + if(term_fg_rgb8(nc->tcache.RGBflag, nc->tcache.setaf, nc->tcache.colors, out, r, g, b)){ return -1; } + ++nc->stats.fgemissions; + nc->rstate.fgelidable = true; } - // if our cell has a non-default foreground, we can elide the - // non-default foreground set iff either: - // * the previous was non-default, and matches what we have now, or - // * we are a no-foreground glyph (iswspace() is true) - if(cell_fg_palindex_p(srccell)){ // palette-indexed foreground - if(emit_fg_palindex(nc, out, srccell)){ - return -1; - } - }else if(!cell_fg_default_p(srccell)){ // rgb foreground - cell_fg_rgb8(srccell, &r, &g, &b); - if(nc->rstate.fgelidable && nc->rstate.lastr == r && nc->rstate.lastg == g && nc->rstate.lastb == b){ - ++nc->stats.fgelisions; - }else{ - if(term_fg_rgb8(nc->tcache.RGBflag, nc->tcache.setaf, nc->tcache.colors, out, r, g, b)){ - return -1; - } - ++nc->stats.fgemissions; - nc->rstate.fgelidable = true; - } - nc->rstate.lastr = r; nc->rstate.lastg = g; nc->rstate.lastb = b; - nc->rstate.fgdefelidable = false; - nc->rstate.fgpalelidable = false; + nc->rstate.lastr = r; nc->rstate.lastg = g; nc->rstate.lastb = b; + nc->rstate.fgdefelidable = false; + nc->rstate.fgpalelidable = false; + } + // if our cell has a non-default background, we can elide the + // non-default background set iff either: + // * we do not use the background, because the cell is all-foreground, + // * the previous was non-default, and matches what we have now, or + if(nobackground){ + ++nc->stats.bgelisions; + }else if(cell_bg_palindex_p(srccell)){ // palette-indexed background + if(emit_bg_palindex(nc, out, srccell)){ + return -1; } - // if our cell has a non-default background, we can elide the - // non-default background set iff either: - // * we do not use the background, because the cell is all-foreground, - // * the previous was non-default, and matches what we have now, or - if(nobackground){ + }else if(!cell_bg_default_p(srccell)){ // rgb background + cell_bg_rgb8(srccell, &br, &bg, &bb); + if(nc->rstate.bgelidable && nc->rstate.lastbr == br && nc->rstate.lastbg == bg && nc->rstate.lastbb == bb){ ++nc->stats.bgelisions; - }else if(cell_bg_palindex_p(srccell)){ // palette-indexed background - if(emit_bg_palindex(nc, out, srccell)){ + }else{ + if(term_bg_rgb8(nc->tcache.RGBflag, nc->tcache.setab, + nc->tcache.colors, out, br, bg, bb, + nc->tcache.bg_collides_default)){ return -1; } - }else if(!cell_bg_default_p(srccell)){ // rgb background - cell_bg_rgb8(srccell, &br, &bg, &bb); - if(nc->rstate.bgelidable && nc->rstate.lastbr == br && nc->rstate.lastbg == bg && nc->rstate.lastbb == bb){ - ++nc->stats.bgelisions; - }else{ - if(term_bg_rgb8(nc->tcache.RGBflag, nc->tcache.setab, - nc->tcache.colors, out, br, bg, bb, - nc->tcache.bg_collides_default)){ - return -1; - } - ++nc->stats.bgemissions; - nc->rstate.bgelidable = true; - } - nc->rstate.lastbr = br; nc->rstate.lastbg = bg; nc->rstate.lastbb = bb; - nc->rstate.bgdefelidable = false; - nc->rstate.bgpalelidable = false; + ++nc->stats.bgemissions; + nc->rstate.bgelidable = true; } - }else{ - nc->rstate.hardcursorpos = true; + nc->rstate.lastbr = br; nc->rstate.lastbg = bg; nc->rstate.lastbb = bb; + nc->rstate.bgdefelidable = false; + nc->rstate.bgpalelidable = false; } //fprintf(stderr, "RAST %08x [%s] to %d/%d cols: %u %016lx\n", srccell->gcluster, pool_extended_gcluster(&nc->pool, srccell), y, x, srccell->width, srccell->channels); if(term_putc(out, &nc->pool, srccell)){ diff --git a/src/lib/sixel.c b/src/lib/sixel.c index a13e6dff7..4393012e5 100644 --- a/src/lib/sixel.c +++ b/src/lib/sixel.c @@ -243,8 +243,8 @@ write_sixel_data(FILE* fp, int lenx, sixeltable* stab){ // are programmed as a set of registers, which are then referenced by the // stacks. There is also a RLE component, handled in rasterization. // A pixel block is indicated by setting cell_pixels_p(). -int sixel_blit_inner(ncplane* nc, int placey, int placex, int lenx, - sixeltable* stab, unsigned cellpixx){ +int sixel_blit_inner(ncplane* nc, int leny, int lenx, sixeltable* stab, + const blitterargs* bargs){ char* buf = NULL; size_t size = 0; FILE* fp = open_memstream(&buf, &size); @@ -256,9 +256,9 @@ int sixel_blit_inner(ncplane* nc, int placey, int placex, int lenx, free(buf); return -1; } - nccell* c = ncplane_cell_ref_yx(nc, placey, placex); - unsigned width = lenx / cellpixx + !!(lenx % cellpixx); - if(pool_blit_direct(&nc->pool, c, buf, size, width) < 0){ + unsigned cols = lenx / bargs->pixel.celldimx + !!(lenx % bargs->pixel.celldimx); + unsigned rows = leny / bargs->pixel.celldimy + !!(leny % bargs->pixel.celldimx); + if(plane_blit_sixel(nc, buf, size, rows, cols) < 0){ free(buf); return -1; } @@ -269,6 +269,8 @@ int sixel_blit_inner(ncplane* nc, int placey, int placex, int lenx, int sixel_blit(ncplane* nc, int placey, int placex, int linesize, const void* data, int begy, int begx, int leny, int lenx, const blitterargs* bargs){ + (void)placey; + (void)placex; int sixelcount = (lenx - begx) * ((leny - begy + 5) / 6); sixeltable stable = { .data = malloc(MAXCOLORS * sixelcount), @@ -292,7 +294,7 @@ int sixel_blit(ncplane* nc, int placey, int placex, int linesize, free(stable.deets); return -1; } - int r = sixel_blit_inner(nc, placey, placex, lenx, &stable, bargs->pixel.celldimx); + int r = sixel_blit_inner(nc, leny, lenx, &stable, bargs); free(stable.data); free(stable.deets); free(stable.table); diff --git a/src/lib/visual.cpp b/src/lib/visual.cpp index bea83179a..0297ce449 100644 --- a/src/lib/visual.cpp +++ b/src/lib/visual.cpp @@ -528,6 +528,7 @@ auto ncvisual_render_pixels(tinfo* tcache, ncvisual* ncv, const blitset* bset, //fprintf(stderr, "pblit: %dx%d <- %dx%d of %d/%d stride %u @%dx%d %p %u\n", disprows, dispcols, begy, begx, ncv->rows, ncv->cols, ncv->rowstride, placey, placex, ncv->data, ncplane_notcurses(stdn)->tcache.cellpixx); blitterargs bargs; bargs.pixel.celldimx = ncplane_notcurses(stdn)->tcache.cellpixx; + bargs.pixel.celldimy = ncplane_notcurses(stdn)->tcache.cellpixy; bargs.pixel.colorregs = ncplane_notcurses(stdn)->tcache.color_registers; if(ncvisual_blit(ncv, disprows, dispcols, n, bset, placey, placex, begy, begx, disprows, dispcols, &bargs)){