Linux framebuffer in direct mode (#1959)

In direct mode, we need to call through to `pixel_draw()` rather than just printing it ourselves, given that Linux framebuffer drawing doesn't involve printing (but instead writing to the memory map). Do so.
pull/1988/head
nick black 3 years ago committed by GitHub
parent 4f1de02710
commit 45986668a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -515,7 +515,7 @@ ncdirect_dump_plane(ncdirect* n, const ncplane* np, int xoff){
if(ncdirect_flush(n)){ if(ncdirect_flush(n)){
return -1; return -1;
} }
if(blocking_write(fileno(n->ttyfp), np->sprite->glyph, np->sprite->glyphlen) < 0){ if(sprite_draw(&n->tcache, NULL, np->sprite, n->ttyfp, 0, xoff)){
return -1; return -1;
} }
if(sprite_commit(&n->tcache, n->ttyfp, np->sprite, true)){ if(sprite_commit(&n->tcache, n->ttyfp, np->sprite, true)){

@ -682,28 +682,28 @@ sprite_scrub(const notcurses* n, const ncpile* p, sprixel* s){
// precondition: s->invalidated is SPRIXEL_INVALIDATED or SPRIXEL_MOVED. // precondition: s->invalidated is SPRIXEL_INVALIDATED or SPRIXEL_MOVED.
// returns -1 on error, or the number of bytes written. // returns -1 on error, or the number of bytes written.
static inline int static inline int
sprite_draw(const notcurses* n, const ncpile* p, sprixel* s, FILE* out, sprite_draw(const tinfo* ti, const ncpile* p, sprixel* s, FILE* out,
int y, int x){ int y, int x){
//sprixel_debug(s, stderr); //sprixel_debug(s, stderr);
logdebug("Sprixel %u state %d\n", s->id, s->invalidated); logdebug("Sprixel %u state %d\n", s->id, s->invalidated);
return n->tcache.pixel_draw(p, s, out, y, x); return ti->pixel_draw(ti, p, s, out, y, x);
} }
// precondition: s->invalidated is SPRIXEL_MOVED or SPRIXEL_INVALIDATED // precondition: s->invalidated is SPRIXEL_MOVED or SPRIXEL_INVALIDATED
// returns -1 on error, or the number of bytes written. // returns -1 on error, or the number of bytes written.
static inline int static inline int
sprite_redraw(const notcurses* n, const ncpile* p, sprixel* s, FILE* out, sprite_redraw(const tinfo* ti, const ncpile* p, sprixel* s, FILE* out,
int y, int x){ int y, int x){
//sprixel_debug(s, stderr); //sprixel_debug(s, stderr);
logdebug("Sprixel %u state %d\n", s->id, s->invalidated); logdebug("Sprixel %u state %d\n", s->id, s->invalidated);
if(s->invalidated == SPRIXEL_MOVED && n->tcache.pixel_move){ if(s->invalidated == SPRIXEL_MOVED && ti->pixel_move){
// if we are kitty prior to 0.20.0, C=1 isn't available to us, and we must // if we are kitty prior to 0.20.0, C=1 isn't available to us, and we must
// not emit it. we use sixel_maxy_pristine as a side channel to encode // not emit it. we use sixel_maxy_pristine as a side channel to encode
// this version information. // this version information.
bool noscroll = !n->tcache.sixel_maxy_pristine; bool noscroll = !ti->sixel_maxy_pristine;
return n->tcache.pixel_move(s, out, noscroll); return ti->pixel_move(s, out, noscroll);
}else{ }else{
return n->tcache.pixel_draw(p, s, out, y, x); return ti->pixel_draw(ti, p, s, out, y, x);
} }
} }

@ -26,9 +26,12 @@ int iterm_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec){
} }
// spit out the control sequence and data. // spit out the control sequence and data.
int iterm_draw(const ncpile *p, sprixel* s, FILE* out, int y, int x){ int iterm_draw(const tinfo* ti, const ncpile *p, sprixel* s, FILE* out, int y, int x){
if(goto_location(p->nc, out, y, x)){ (void)ti;
return -1; if(p){
if(goto_location(p->nc, out, y, x)){
return -1;
}
} }
if(fwrite(s->glyph, s->glyphlen, 1, out) != 1){ if(fwrite(s->glyph, s->glyphlen, 1, out) != 1){
return -1; return -1;

@ -952,7 +952,9 @@ int kitty_scrub(const ncpile* p, sprixel* s){
} }
// returns the number of bytes written // returns the number of bytes written
int kitty_draw(const ncpile* p, sprixel* s, FILE* out, int y, int x){ int kitty_draw(const tinfo* ti, const ncpile* p, sprixel* s, FILE* out,
int y, int x){
(void)ti;
(void)p; (void)p;
(void)y; (void)y;
(void)x; (void)x;

@ -124,16 +124,16 @@ int fbcon_scrub(const struct ncpile* p, sprixel* s){
return 0; return 0;
} }
int fbcon_draw(const struct ncpile *p, sprixel* s, FILE* out, int y, int x){ int fbcon_draw(const tinfo* ti, const struct ncpile *p, sprixel* s, FILE* out, int y, int x){
(void)p;
(void)out; // we don't write to the stream (void)out; // we don't write to the stream
const tinfo* ti = &p->nc->tcache;
int wrote = 0; int wrote = 0;
for(int l = 0 ; l < s->pixy ; ++l){ for(unsigned l = 0 ; l < (unsigned)s->pixy && l < ti->pixy ; ++l){
// FIXME pixel size isn't necessarily 4B, line isn't necessarily psize*pixx // FIXME pixel size isn't necessarily 4B, line isn't necessarily psize*pixx
size_t offset = ((l + y * ti->cellpixy) * ti->pixx + x * ti->cellpixx) * 4; size_t offset = ((l + y * ti->cellpixy) * ti->pixx + x * ti->cellpixx) * 4;
uint8_t* tl = ti->linux_fbuffer + offset; uint8_t* tl = ti->linux_fbuffer + offset;
const char* src = s->glyph + (l * s->pixx * 4); const char* src = s->glyph + (l * s->pixx * 4);
for(int c = 0 ; c < s->pixx ; ++c){ for(unsigned c = 0 ; c < (unsigned)s->pixx && c < ti->pixx ; ++c){
uint32_t pixel; uint32_t pixel;
memcpy(&pixel, src, 4); memcpy(&pixel, src, 4);
if(!rgba_trans_p(pixel, 0)){ if(!rgba_trans_p(pixel, 0)){

@ -862,7 +862,7 @@ clean_sprixels(notcurses* nc, ncpile* p, FILE* out){
if(goto_location(nc, out, y + nc->margin_t, x + nc->margin_l)){ if(goto_location(nc, out, y + nc->margin_t, x + nc->margin_l)){
return -1; return -1;
} }
int r = sprite_redraw(nc, p, s, out, y + nc->margin_t, x + nc->margin_l); int r = sprite_redraw(&nc->tcache, p, s, out, y + nc->margin_t, x + nc->margin_l);
if(r < 0){ if(r < 0){
return -1; return -1;
} }
@ -923,7 +923,7 @@ rasterize_sprixels(notcurses* nc, ncpile* p, FILE* out){
//fprintf(stderr, "3 DRAWING BITMAP %d STATE %d AT %d/%d for %p\n", s->id, s->invalidated, y + nc->margin_t, x + nc->margin_l, s->n); //fprintf(stderr, "3 DRAWING BITMAP %d STATE %d AT %d/%d for %p\n", s->id, s->invalidated, y + nc->margin_t, x + nc->margin_l, s->n);
int y,x; int y,x;
ncplane_yx(s->n, &y, &x); ncplane_yx(s->n, &y, &x);
int r = sprite_draw(nc, p, s, out, y + nc->margin_t, x + nc->margin_l); int r = sprite_draw(&nc->tcache, p, s, out, y + nc->margin_t, x + nc->margin_l);
if(r < 0){ if(r < 0){
return -1; return -1;
} }

@ -828,7 +828,9 @@ int sixel_scrub(const ncpile* p, sprixel* s){
} }
// returns the number of bytes written // returns the number of bytes written
int sixel_draw(const ncpile* p, sprixel* s, FILE* out, int y, int x){ int sixel_draw(const tinfo* ti, const ncpile* p, sprixel* s, FILE* out,
int y, int x){
(void)ti;
// if we've wiped or rebuilt any cells, effect those changes now, or else // if we've wiped or rebuilt any cells, effect those changes now, or else
// we'll get flicker when we move to the new location. // we'll get flicker when we move to the new location.
if(s->wipes_outstanding){ if(s->wipes_outstanding){
@ -837,15 +839,17 @@ int sixel_draw(const ncpile* p, sprixel* s, FILE* out, int y, int x){
} }
s->wipes_outstanding = false; s->wipes_outstanding = false;
} }
if(goto_location(p->nc, out, y, x)){ if(p){
return -1; if(goto_location(p->nc, out, y, x)){
} return -1;
if(s->invalidated == SPRIXEL_MOVED){ }
for(int yy = s->movedfromy ; yy < s->movedfromy + s->dimy && yy < p->dimy ; ++yy){ if(s->invalidated == SPRIXEL_MOVED){
for(int xx = s->movedfromx ; xx < s->movedfromx + s->dimx && xx < p->dimx ; ++xx){ for(int yy = s->movedfromy ; yy < s->movedfromy + s->dimy && yy < p->dimy ; ++yy){
struct crender *r = &p->crender[yy * p->dimx + xx]; for(int xx = s->movedfromx ; xx < s->movedfromx + s->dimx && xx < p->dimx ; ++xx){
if(!r->sprixel || sprixel_state(r->sprixel, yy, xx) != SPRIXCELL_OPAQUE_SIXEL){ struct crender *r = &p->crender[yy * p->dimx + xx];
r->s.damaged = 1; if(!r->sprixel || sprixel_state(r->sprixel, yy, xx) != SPRIXCELL_OPAQUE_SIXEL){
r->s.damaged = 1;
}
} }
} }
} }

@ -172,9 +172,12 @@ int kitty_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec);
int iterm_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec); int iterm_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec);
int fbcon_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec); int fbcon_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec);
int kitty_rebuild_animation(sprixel* s, int ycell, int xcell, uint8_t* auxvec); int kitty_rebuild_animation(sprixel* s, int ycell, int xcell, uint8_t* auxvec);
int sixel_draw(const struct ncpile *p, sprixel* s, FILE* out, int y, int x); int sixel_draw(const tinfo* ti, const struct ncpile *p, sprixel* s,
int kitty_draw(const struct ncpile *p, sprixel* s, FILE* out, int y, int x); FILE* out, int y, int x);
int iterm_draw(const struct ncpile *p, sprixel* s, FILE* out, int y, int x); int kitty_draw(const tinfo* ti, const struct ncpile *p, sprixel* s,
FILE* out, int y, int x);
int iterm_draw(const tinfo* ti, const struct ncpile *p, sprixel* s,
FILE* out, int y, int x);
int kitty_move(sprixel* s, FILE* out, unsigned noscroll); int kitty_move(sprixel* s, FILE* out, unsigned noscroll);
int sixel_scrub(const struct ncpile* p, sprixel* s); int sixel_scrub(const struct ncpile* p, sprixel* s);
int kitty_scrub(const struct ncpile* p, sprixel* s); int kitty_scrub(const struct ncpile* p, sprixel* s);
@ -198,7 +201,8 @@ int kitty_blit_animated(struct ncplane* n, int linesize, const void* data,
int leny, int lenx, const struct blitterargs* bargs); int leny, int lenx, const struct blitterargs* bargs);
int fbcon_blit(struct ncplane* nc, int linesize, const void* data, int fbcon_blit(struct ncplane* nc, int linesize, const void* data,
int leny, int lenx, const struct blitterargs* bargs); int leny, int lenx, const struct blitterargs* bargs);
int fbcon_draw(const struct ncpile *p, sprixel* s, FILE* out, int y, int x); int fbcon_draw(const tinfo* ti, const struct ncpile *p, sprixel* s,
FILE* out, int y, int x);
#ifdef __cplusplus #ifdef __cplusplus
} }

@ -152,8 +152,8 @@ typedef struct tinfo {
int (*pixel_rebuild)(struct sprixel* s, int y, int x, uint8_t* auxvec); int (*pixel_rebuild)(struct sprixel* s, int y, int x, uint8_t* auxvec);
int (*pixel_remove)(int id, FILE* out); // kitty only, issue actual delete command int (*pixel_remove)(int id, FILE* out); // kitty only, issue actual delete command
int (*pixel_init)(const struct tinfo*, int fd); // called when support is detected int (*pixel_init)(const struct tinfo*, int fd); // called when support is detected
int (*pixel_draw)(const struct ncpile* p, struct sprixel* s, FILE* out, int (*pixel_draw)(const struct tinfo*, const struct ncpile* p,
int y, int x); struct sprixel* s, FILE* out, int y, int x);
// execute move (erase old graphic, place at new location) if non-NULL // execute move (erase old graphic, place at new location) if non-NULL
int (*pixel_move)(struct sprixel* s, FILE* out, unsigned noscroll); int (*pixel_move)(struct sprixel* s, FILE* out, unsigned noscroll);
int (*pixel_scrub)(const struct ncpile* p, struct sprixel* s); int (*pixel_scrub)(const struct ncpile* p, struct sprixel* s);

Loading…
Cancel
Save