mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-10 01:29:05 -04:00
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.
This commit is contained in:
parent
4f1de02710
commit
45986668a1
@ -515,7 +515,7 @@ ncdirect_dump_plane(ncdirect* n, const ncplane* np, int xoff){
|
||||
if(ncdirect_flush(n)){
|
||||
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;
|
||||
}
|
||||
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.
|
||||
// returns -1 on error, or the number of bytes written.
|
||||
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){
|
||||
//sprixel_debug(s, stderr);
|
||||
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
|
||||
// returns -1 on error, or the number of bytes written.
|
||||
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){
|
||||
//sprixel_debug(s, stderr);
|
||||
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
|
||||
// not emit it. we use sixel_maxy_pristine as a side channel to encode
|
||||
// this version information.
|
||||
bool noscroll = !n->tcache.sixel_maxy_pristine;
|
||||
return n->tcache.pixel_move(s, out, noscroll);
|
||||
bool noscroll = !ti->sixel_maxy_pristine;
|
||||
return ti->pixel_move(s, out, noscroll);
|
||||
}else{
|
||||
return n->tcache.pixel_draw(p, s, out, y, x);
|
||||
return ti->pixel_draw(ti, p, s, out, y, x);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,10 +26,13 @@ int iterm_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec){
|
||||
}
|
||||
|
||||
// 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){
|
||||
(void)ti;
|
||||
if(p){
|
||||
if(goto_location(p->nc, out, y, x)){
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if(fwrite(s->glyph, s->glyphlen, 1, out) != 1){
|
||||
return -1;
|
||||
}
|
||||
|
@ -952,7 +952,9 @@ int kitty_scrub(const ncpile* p, sprixel* s){
|
||||
}
|
||||
|
||||
// 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)y;
|
||||
(void)x;
|
||||
|
@ -124,16 +124,16 @@ int fbcon_scrub(const struct ncpile* p, sprixel* s){
|
||||
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
|
||||
const tinfo* ti = &p->nc->tcache;
|
||||
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
|
||||
size_t offset = ((l + y * ti->cellpixy) * ti->pixx + x * ti->cellpixx) * 4;
|
||||
uint8_t* tl = ti->linux_fbuffer + offset;
|
||||
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;
|
||||
memcpy(&pixel, src, 4);
|
||||
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)){
|
||||
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){
|
||||
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);
|
||||
int 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){
|
||||
return -1;
|
||||
}
|
||||
|
@ -828,7 +828,9 @@ int sixel_scrub(const ncpile* p, sprixel* s){
|
||||
}
|
||||
|
||||
// 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
|
||||
// we'll get flicker when we move to the new location.
|
||||
if(s->wipes_outstanding){
|
||||
@ -837,6 +839,7 @@ int sixel_draw(const ncpile* p, sprixel* s, FILE* out, int y, int x){
|
||||
}
|
||||
s->wipes_outstanding = false;
|
||||
}
|
||||
if(p){
|
||||
if(goto_location(p->nc, out, y, x)){
|
||||
return -1;
|
||||
}
|
||||
@ -850,6 +853,7 @@ int sixel_draw(const ncpile* p, sprixel* s, FILE* out, int y, int x){
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(fwrite(s->glyph, s->glyphlen, 1, out) != 1){
|
||||
return -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 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 sixel_draw(const struct ncpile *p, sprixel* s, FILE* out, int y, int x);
|
||||
int kitty_draw(const struct ncpile *p, sprixel* s, FILE* out, int y, int x);
|
||||
int iterm_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,
|
||||
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 sixel_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 fbcon_blit(struct ncplane* nc, int linesize, const void* data,
|
||||
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
|
||||
}
|
||||
|
@ -152,8 +152,8 @@ typedef struct tinfo {
|
||||
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_init)(const struct tinfo*, int fd); // called when support is detected
|
||||
int (*pixel_draw)(const struct ncpile* p, struct sprixel* s, FILE* out,
|
||||
int y, int x);
|
||||
int (*pixel_draw)(const struct tinfo*, const struct ncpile* p,
|
||||
struct sprixel* s, FILE* out, int y, int x);
|
||||
// execute move (erase old graphic, place at new location) if non-NULL
|
||||
int (*pixel_move)(struct sprixel* s, FILE* out, unsigned noscroll);
|
||||
int (*pixel_scrub)(const struct ncpile* p, struct sprixel* s);
|
||||
|
Loading…
x
Reference in New Issue
Block a user