[pixel] pass celldimy through blitterargs #1401

This commit is contained in:
nick black 2021-03-15 00:13:55 -04:00 committed by Nick Black
parent b2ef9a074b
commit 645b61e9dc
8 changed files with 87 additions and 84 deletions

View File

@ -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.

View File

@ -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,
},
};

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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)){

View File

@ -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);

View File

@ -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)){