From a5b9a2ed4267c5801e1b7ebbb64f5b91dcab9ee3 Mon Sep 17 00:00:00 2001 From: nick black Date: Sun, 18 Jul 2021 18:01:46 -0400 Subject: [PATCH] linux fbcon blitting! --- src/lib/linux.c | 79 ++++++++++++++++++++++++++++++++++++++------- src/lib/notcurses.c | 11 +++---- src/lib/sprite.h | 1 + src/lib/termdesc.c | 1 + src/lib/termdesc.h | 2 ++ 5 files changed, 76 insertions(+), 18 deletions(-) diff --git a/src/lib/linux.c b/src/lib/linux.c index aacb1d518..9b4828779 100644 --- a/src/lib/linux.c +++ b/src/lib/linux.c @@ -10,16 +10,63 @@ #include #include +int fbcon_wipe(sprixel* s, int ycell, int xcell){ + (void)s; + (void)ycell; + (void)xcell; + logerror("Not yet implemented\n"); + return -1; +} -int fbcon_blit(struct ncplane* nc, int linesize, const void* data, +int fbcon_blit(struct ncplane* n, int linesize, const void* data, int leny, int lenx, const struct blitterargs* bargs){ - (void)nc; - (void)linesize; - (void)data; - (void)leny; - (void)lenx; - (void)bargs; - logerror("Haven't implemented yet FIXME\n"); + int cols = bargs->u.pixel.spx->dimx; + int rows = bargs->u.pixel.spx->dimy; + sprixel* s = bargs->u.pixel.spx; + s->glyphlen = leny * lenx * 4; + s->glyph = malloc(s->glyphlen); + if(s->glyph == NULL){ + return -1; + } + tament* tam = NULL; + bool reuse = false; + if(n->tam){ + if(n->leny == rows && n->lenx == cols){ + tam = n->tam; + reuse = true; + } + } + if(!reuse){ + tam = malloc(sizeof(*tam) * rows * cols); + if(tam == NULL){ + goto error; + } + memset(tam, 0, sizeof(*tam) * rows * cols); + } + for(int l = 0 ; l < leny ; ++l){ + size_t soffset = l * linesize; + const uint8_t* src = (const unsigned char*)data + soffset; + size_t toffset = l * lenx * 4; + char* dst = s->glyph + toffset; + for(int c = 0 ; c < lenx ; ++c){ + memcpy(dst, src + 2, 1); + memcpy(dst + 1, src + 1, 1); + memcpy(dst + 2, src, 1); + memcpy(dst + 3, src + 3, 1); + dst += 4; + src += 4; + } + } + if(plane_blit_sixel(s, s->glyph, s->glyphlen, leny, lenx, 0, tam) < 0){ + goto error; + } + return 1; + +error: + if(!reuse){ + free(tam); + } + free(s->glyph); return -1; } @@ -30,13 +77,21 @@ int fbcon_scrub(const struct ncpile* p, sprixel* s){ } int fbcon_draw(const struct ncpile *p, sprixel* s, FILE* out, int y, int x){ - (void)p; - (void)s; - (void)out; + (void)out; // we don't write to the stream (void)y; (void)x; + const tinfo* ti = &p->nc->tcache; + for(int l = 0 ; l < s->pixy ; ++l){ + // FIXME pixel size isn't necessarily 4B, line isn't necessarily psize*pixx + size_t offset = ((l + y) * ti->pixx + x) * 4; + size_t lsize = ti->pixx * 4; + uint8_t* tl = ti->linux_fbuffer + offset; + // FIXME draw line + const char* src = s->glyph + (l * s->pixx * 4); + memcpy(tl, src, lsize); + } logerror("Haven't implemented yet FIXME\n"); - return -1; + return 0; } // each row is a contiguous set of bits, starting at the msb diff --git a/src/lib/notcurses.c b/src/lib/notcurses.c index c9873f749..50dfa2aaa 100644 --- a/src/lib/notcurses.c +++ b/src/lib/notcurses.c @@ -262,15 +262,14 @@ int update_term_dimensions(int fd, int* rows, int* cols, tinfo* tcache, *cols = ws.ws_col; } if(tcache){ - unsigned y, x; if(tcache->linux_fb_fd >= 0){ - get_linux_fb_pixelgeom(tcache, &y, &x); + get_linux_fb_pixelgeom(tcache, &tcache->pixy, &tcache->pixx); }else{ - y = ws.ws_ypixel; - x = ws.ws_xpixel; + tcache->pixy = ws.ws_ypixel; + tcache->pixx = ws.ws_xpixel; } - tcache->cellpixy = ws.ws_row ? y / ws.ws_row : 0; - tcache->cellpixx = ws.ws_col ? x / ws.ws_col : 0; + tcache->cellpixy = ws.ws_row ? tcache->pixy / ws.ws_row : 0; + tcache->cellpixx = ws.ws_col ? tcache->pixx / ws.ws_col : 0; if(tcache->cellpixy == 0 || tcache->cellpixx == 0){ tcache->pixel_draw = NULL; // disable support } diff --git a/src/lib/sprite.h b/src/lib/sprite.h index 14f510a96..cb3efeed7 100644 --- a/src/lib/sprite.h +++ b/src/lib/sprite.h @@ -166,6 +166,7 @@ int kitty_wipe(sprixel* s, int ycell, int xcell); int kitty_wipe_animation(sprixel* s, int ycell, int xcell); // wipes out a cell by changing the alpha value throughout the PNG cell to 0. int iterm_wipe(sprixel* s, int ycell, int xcell); +int fbcon_wipe(sprixel* s, int ycell, int xcell); int sixel_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec); int kitty_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec); int iterm_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec); diff --git a/src/lib/termdesc.c b/src/lib/termdesc.c index 0dff57f9b..a07e7dfe8 100644 --- a/src/lib/termdesc.c +++ b/src/lib/termdesc.c @@ -114,6 +114,7 @@ setup_kitty_bitmaps(tinfo* ti, int fd, int sixel_maxy_pristine){ static inline void setup_fbcon_bitmaps(tinfo* ti){ // FIXME + ti->pixel_wipe = fbcon_wipe; ti->pixel_draw = fbcon_draw; ti->pixel_scrub = fbcon_scrub; set_pixel_blitter(fbcon_blit); diff --git a/src/lib/termdesc.h b/src/lib/termdesc.h index 7d219fe78..a608eebda 100644 --- a/src/lib/termdesc.h +++ b/src/lib/termdesc.h @@ -129,6 +129,8 @@ typedef struct tinfo { uint16_t escindices[ESCAPE_MAX]; // table of 1-biased indices into esctable char* esctable; // packed table of escape sequences nccapabilities caps; // exported to the user, when requested + unsigned pixy; // total pixel geometry, height + unsigned pixx; // total pixel geometry, width // we use the cell's size in pixels for pixel blitting. this information can // be acquired on all terminals with pixel support. int cellpixy; // cell pixel height, might be 0