mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 09:09:03 -04:00
quadblitter: move to uint32_t throughout #1714
This commit is contained in:
parent
f77c008e88
commit
0c6dfceb7b
@ -2647,7 +2647,8 @@ API int ncblit_rgb_loose(const void* data, int linesize,
|
||||
// ncvisual (ncvisuals keep a backing store of 32-bit RGBA pixels, and render
|
||||
// them down to terminal graphics in ncvisual_render()).
|
||||
//
|
||||
// Per libav, we "store as BGRA on little-endian, and ARGB on big-endian".
|
||||
// Per libav, we "store as BGRA on little-endian, and ARGB on big-endian;
|
||||
// an RGBA color is assembled as (A << 24) | (R << 16) | (G << 8) | B".
|
||||
// This is an RGBA *byte-order* scheme. libav emits bytes, not words. Those
|
||||
// bytes are R-G-B-A. When read as words, on little endian this will be ABGR,
|
||||
// and on big-endian this will be RGBA. force everything to LE ABGR, a no-op
|
||||
@ -2655,26 +2656,40 @@ API int ncblit_rgb_loose(const void* data, int linesize,
|
||||
|
||||
// Extract the 8-bit alpha component from a pixel
|
||||
static inline unsigned
|
||||
ncpixel_a(uint32_t pixel){
|
||||
return (htole(pixel) & 0xff000000ul) >> 24u;
|
||||
}
|
||||
|
||||
// Extract the 8-bit red component from an ABGR pixel
|
||||
static inline unsigned
|
||||
ncpixel_r(uint32_t pixel){
|
||||
return (htole(pixel) & 0x000000fful);
|
||||
}
|
||||
|
||||
// Extract the 8-bit red component from an ABGR pixel
|
||||
static inline unsigned
|
||||
ncpixel_a(uint32_t pixel){
|
||||
return (htole(pixel) & 0xff000000ul) >> 24u;
|
||||
}
|
||||
|
||||
// Extract the 8-bit green component from an ABGR pixel
|
||||
static inline unsigned
|
||||
ncpixel_b(uint32_t pixel){
|
||||
return (htole(pixel) & 0x00ff0000ul) >> 16u;
|
||||
}
|
||||
|
||||
// Extract the 8-bit blue component from an ABGR pixel
|
||||
static inline unsigned
|
||||
ncpixel_g(uint32_t pixel){
|
||||
return (htole(pixel) & 0x0000ff00ul) >> 8u;
|
||||
}
|
||||
|
||||
// Extract the 8-bit blue component from an ABGR pixel
|
||||
static inline unsigned
|
||||
ncpixel_b(uint32_t pixel){
|
||||
return (htole(pixel) & 0x00ff0000ul) >> 16u;
|
||||
// Extract the RGB components in a form suitable for use with ncchannels.
|
||||
static inline uint32_t
|
||||
ncpixel_rgb(uint32_t pixel){
|
||||
return pixel >> 8u;
|
||||
}
|
||||
|
||||
// Extract the RGB components as three parts.
|
||||
static inline void
|
||||
ncpixel_rgb8(uint32_t pixel, unsigned* r, unsigned* g, unsigned* b){
|
||||
*r = ncpixel_r(pixel);
|
||||
*b = ncpixel_b(pixel);
|
||||
*g = ncpixel_g(pixel);
|
||||
}
|
||||
|
||||
// Set the 8-bit alpha component of an ABGR pixel
|
||||
|
119
src/lib/blit.c
119
src/lib/blit.c
@ -4,27 +4,27 @@
|
||||
static const uint32_t zeroes32;
|
||||
static const unsigned char zeroes[] = "\x00\x00\x00\x00";
|
||||
|
||||
// linearly interpolate a 24-bit RGB value along each 8-bit channel
|
||||
// linearly interpolate two ncpixels along each 8-bit channel (RGB only)
|
||||
static inline uint32_t
|
||||
lerp(uint32_t c0, uint32_t c1){
|
||||
uint32_t ret = 0;
|
||||
unsigned r0, g0, b0, r1, g1, b1;
|
||||
ncchannel_rgb8(c0, &r0, &g0, &b0);
|
||||
ncchannel_rgb8(c1, &r1, &g1, &b1);
|
||||
ncpixel_rgb8(c0, &r0, &g0, &b0);
|
||||
ncpixel_rgb8(c1, &r1, &g1, &b1);
|
||||
ncchannel_set_rgb8(&ret, (r0 + r1 + 1) / 2,
|
||||
(g0 + g1 + 1) / 2,
|
||||
(b0 + b1 + 1) / 2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// linearly interpolate a 24-bit RGB value along each 8-bit channel
|
||||
// linearly interpolate three ncpixels along each 8-bit channel (RGB only)
|
||||
static inline uint32_t
|
||||
trilerp(uint32_t c0, uint32_t c1, uint32_t c2){
|
||||
uint32_t ret = 0;
|
||||
unsigned r0, g0, b0, r1, g1, b1, r2, g2, b2;
|
||||
ncchannel_rgb8(c0, &r0, &g0, &b0);
|
||||
ncchannel_rgb8(c1, &r1, &g1, &b1);
|
||||
ncchannel_rgb8(c2, &r2, &g2, &b2);
|
||||
ncpixel_rgb8(c0, &r0, &g0, &b0);
|
||||
ncpixel_rgb8(c1, &r1, &g1, &b1);
|
||||
ncpixel_rgb8(c2, &r2, &g2, &b2);
|
||||
ncchannel_set_rgb8(&ret, (r0 + r1 + r2 + 2) / 3,
|
||||
(g0 + g1 + g2 + 2) / 3,
|
||||
(b0 + b1 + b2 + 2) / 3);
|
||||
@ -314,96 +314,92 @@ quadrant_solver(uint32_t tl, uint32_t tr, uint32_t bl, uint32_t br,
|
||||
// FIXME pass in rgbas as array of uint32_t ala sexblitter
|
||||
static inline const char*
|
||||
qtrans_check(nccell* c, unsigned blendcolors,
|
||||
const unsigned char* rgbbase_tl, const unsigned char* rgbbase_tr,
|
||||
const unsigned char* rgbbase_bl, const unsigned char* rgbbase_br,
|
||||
const uint32_t rgbbase_tl, const uint32_t rgbbase_tr,
|
||||
const uint32_t rgbbase_bl, const uint32_t rgbbase_br,
|
||||
uint32_t transcolor){
|
||||
uint32_t tl = 0, tr = 0, bl = 0, br = 0;
|
||||
ncchannel_set_rgb8(&tl, rgbbase_tl[0], rgbbase_tl[1], rgbbase_tl[2]);
|
||||
ncchannel_set_rgb8(&tr, rgbbase_tr[0], rgbbase_tr[1], rgbbase_tr[2]);
|
||||
ncchannel_set_rgb8(&bl, rgbbase_bl[0], rgbbase_bl[1], rgbbase_bl[2]);
|
||||
ncchannel_set_rgb8(&br, rgbbase_br[0], rgbbase_br[1], rgbbase_br[2]);
|
||||
fprintf(stderr, "QTRANS: %08x %08x %08x %08x\n", rgbbase_tl, rgbbase_tr, rgbbase_bl, rgbbase_br);
|
||||
const char* egc = NULL;
|
||||
if(rgba_trans_q(rgbbase_tl, transcolor)){
|
||||
if(rgba_trans_p(rgbbase_tl, transcolor)){
|
||||
// top left is transparent
|
||||
if(rgba_trans_q(rgbbase_tr, transcolor)){
|
||||
if(rgba_trans_p(rgbbase_tr, transcolor)){
|
||||
// all of top is transparent
|
||||
if(rgba_trans_q(rgbbase_bl, transcolor)){
|
||||
if(rgba_trans_p(rgbbase_bl, transcolor)){
|
||||
// top and left are transparent
|
||||
if(rgba_trans_q(rgbbase_br, transcolor)){
|
||||
if(rgba_trans_p(rgbbase_br, transcolor)){
|
||||
// entirety is transparent, load with nul (but not NULL)
|
||||
nccell_set_fg_default(c);
|
||||
cell_set_blitquadrants(c, 0, 0, 0, 0);
|
||||
egc = "";
|
||||
}else{
|
||||
nccell_set_fg_rgb8(c, rgbbase_br[0], rgbbase_br[1], rgbbase_br[2]);
|
||||
nccell_set_fg_rgb(c, ncpixel_rgb(rgbbase_br));
|
||||
cell_set_blitquadrants(c, 0, 0, 0, 1);
|
||||
egc = "▗";
|
||||
}
|
||||
}else{
|
||||
if(rgba_trans_q(rgbbase_br, transcolor)){
|
||||
nccell_set_fg_rgb8(c, rgbbase_bl[0], rgbbase_bl[1], rgbbase_bl[2]);
|
||||
if(rgba_trans_p(rgbbase_br, transcolor)){
|
||||
nccell_set_fg_rgb(c, ncpixel_rgb(rgbbase_bl));
|
||||
cell_set_blitquadrants(c, 0, 0, 1, 0);
|
||||
egc = "▖";
|
||||
}else{
|
||||
cell_set_fchannel(c, lerp(bl, br));
|
||||
cell_set_fchannel(c, lerp(rgbbase_bl, rgbbase_br));
|
||||
cell_set_blitquadrants(c, 0, 0, 1, 1);
|
||||
egc = "▄";
|
||||
}
|
||||
}
|
||||
}else{ // top right is foreground, top left is transparent
|
||||
if(rgba_trans_q(rgbbase_bl, transcolor)){
|
||||
if(rgba_trans_q(rgbbase_br, transcolor)){ // entire bottom is transparent
|
||||
nccell_set_fg_rgb8(c, rgbbase_tr[0], rgbbase_tr[1], rgbbase_tr[2]);
|
||||
if(rgba_trans_p(rgbbase_bl, transcolor)){
|
||||
if(rgba_trans_p(rgbbase_br, transcolor)){ // entire bottom is transparent
|
||||
nccell_set_fg_rgb(c, ncpixel_rgb(rgbbase_tr));
|
||||
cell_set_blitquadrants(c, 0, 1, 0, 0);
|
||||
egc = "▝";
|
||||
}else{
|
||||
cell_set_fchannel(c, lerp(tr, br));
|
||||
cell_set_fchannel(c, lerp(rgbbase_tr, rgbbase_br));
|
||||
cell_set_blitquadrants(c, 0, 1, 0, 1);
|
||||
egc = "▐";
|
||||
}
|
||||
}else if(rgba_trans_q(rgbbase_br, transcolor)){ // only br is transparent
|
||||
cell_set_fchannel(c, lerp(tr, bl));
|
||||
}else if(rgba_trans_p(rgbbase_br, transcolor)){ // only br is transparent
|
||||
cell_set_fchannel(c, lerp(rgbbase_tr, rgbbase_bl));
|
||||
cell_set_blitquadrants(c, 0, 1, 1, 0);
|
||||
egc = "▞";
|
||||
}else{
|
||||
cell_set_fchannel(c, trilerp(tr, bl, br));
|
||||
cell_set_fchannel(c, trilerp(rgbbase_tr, rgbbase_bl, rgbbase_br));
|
||||
cell_set_blitquadrants(c, 0, 1, 1, 1);
|
||||
egc = "▟";
|
||||
}
|
||||
}
|
||||
}else{ // topleft is foreground for all here
|
||||
if(rgba_trans_q(rgbbase_tr, transcolor)){
|
||||
if(rgba_trans_q(rgbbase_bl, transcolor)){
|
||||
if(rgba_trans_q(rgbbase_br, transcolor)){
|
||||
nccell_set_fg_rgb8(c, rgbbase_tl[0], rgbbase_tl[1], rgbbase_tl[2]);
|
||||
if(rgba_trans_p(rgbbase_tr, transcolor)){
|
||||
if(rgba_trans_p(rgbbase_bl, transcolor)){
|
||||
if(rgba_trans_p(rgbbase_br, transcolor)){
|
||||
nccell_set_fg_rgb(c, ncpixel_rgb(rgbbase_tl));
|
||||
cell_set_blitquadrants(c, 1, 0, 0, 0);
|
||||
egc = "▘";
|
||||
}else{
|
||||
cell_set_fchannel(c, lerp(tl, br));
|
||||
cell_set_fchannel(c, lerp(rgbbase_tl, rgbbase_br));
|
||||
cell_set_blitquadrants(c, 1, 0, 0, 1);
|
||||
egc = "▚";
|
||||
}
|
||||
}else if(rgba_trans_q(rgbbase_br, transcolor)){
|
||||
cell_set_fchannel(c, lerp(tl, bl));
|
||||
}else if(rgba_trans_p(rgbbase_br, transcolor)){
|
||||
cell_set_fchannel(c, lerp(rgbbase_tl, rgbbase_bl));
|
||||
cell_set_blitquadrants(c, 1, 0, 1, 0);
|
||||
egc = "▌";
|
||||
}else{
|
||||
cell_set_fchannel(c, trilerp(tl, bl, br));
|
||||
cell_set_fchannel(c, trilerp(rgbbase_tl, rgbbase_bl, rgbbase_br));
|
||||
cell_set_blitquadrants(c, 1, 0, 1, 1);
|
||||
egc = "▙";
|
||||
}
|
||||
}else if(rgba_trans_q(rgbbase_bl, transcolor)){
|
||||
if(rgba_trans_q(rgbbase_br, transcolor)){ // entire bottom is transparent
|
||||
cell_set_fchannel(c, lerp(tl, tr));
|
||||
}else if(rgba_trans_p(rgbbase_bl, transcolor)){
|
||||
if(rgba_trans_p(rgbbase_br, transcolor)){ // entire bottom is transparent
|
||||
cell_set_fchannel(c, lerp(rgbbase_tl, rgbbase_tr));
|
||||
cell_set_blitquadrants(c, 1, 1, 0, 0);
|
||||
egc = "▀";
|
||||
}else{ // only bl is transparent
|
||||
cell_set_fchannel(c, trilerp(tl, tr, br));
|
||||
cell_set_fchannel(c, trilerp(rgbbase_tl, rgbbase_tr, rgbbase_br));
|
||||
cell_set_blitquadrants(c, 1, 1, 0, 1);
|
||||
egc = "▜";
|
||||
}
|
||||
}else if(rgba_trans_q(rgbbase_br, transcolor)){ // only br is transparent
|
||||
cell_set_fchannel(c, trilerp(tl, tr, bl));
|
||||
}else if(rgba_trans_p(rgbbase_br, transcolor)){ // only br is transparent
|
||||
cell_set_fchannel(c, trilerp(rgbbase_tl, rgbbase_tr, rgbbase_bl));
|
||||
cell_set_blitquadrants(c, 1, 1, 1, 0);
|
||||
egc = "▛";
|
||||
}else{
|
||||
@ -417,7 +413,7 @@ qtrans_check(nccell* c, unsigned blendcolors,
|
||||
}else if(blendcolors){
|
||||
nccell_set_fg_alpha(c, CELL_ALPHA_BLEND);
|
||||
}
|
||||
//fprintf(stderr, "QBQ: 0x%x\n", cell_blittedquadrants(c));
|
||||
fprintf(stderr, "QBQ: 0x%x EGC: %s\n", cell_blittedquadrants(c), egc);
|
||||
return egc;
|
||||
}
|
||||
|
||||
@ -426,13 +422,13 @@ qtrans_check(nccell* c, unsigned blendcolors,
|
||||
static inline int
|
||||
quadrant_blit(ncplane* nc, int linesize, const void* data,
|
||||
int leny, int lenx, const blitterargs* bargs){
|
||||
const int bpp = 32;
|
||||
#define Bpp 4
|
||||
const uint32_t* udat = data;
|
||||
int dimy, dimx, x, y;
|
||||
int total = 0; // number of cells written
|
||||
ncplane_dim_yx(nc, &dimy, &dimx);
|
||||
//fprintf(stderr, "quadblitter %dx%d -> %d/%d+%d/%d\n", leny, lenx, dimy, dimx, bargs->u.cell.placey, bargs->u.cell.placex);
|
||||
// FIXME not going to necessarily be safe on all architectures hrmmm
|
||||
const unsigned char* dat = data;
|
||||
int visy = bargs->begy;
|
||||
for(y = bargs->u.cell.placey ; visy < (bargs->begy + leny) && y < dimy ; ++y, visy += 2){
|
||||
if(y < 0){
|
||||
@ -446,30 +442,34 @@ quadrant_blit(ncplane* nc, int linesize, const void* data,
|
||||
if(x < 0){
|
||||
continue;
|
||||
}
|
||||
const unsigned char* rgbbase_tl = dat + (linesize * visy) + (visx * bpp / CHAR_BIT);
|
||||
const unsigned char* rgbbase_tr = zeroes;
|
||||
const unsigned char* rgbbase_bl = zeroes;
|
||||
const unsigned char* rgbbase_br = zeroes;
|
||||
uint32_t rgbbase_tl = udat[(linesize / Bpp * visy) + visx];
|
||||
uint32_t rgbbase_tr = 0;
|
||||
uint32_t rgbbase_bl = 0;
|
||||
uint32_t rgbbase_br = 0;
|
||||
if(visx < bargs->begx + lenx - 1){
|
||||
rgbbase_tr = dat + (linesize * visy) + ((visx + 1) * bpp / CHAR_BIT);
|
||||
rgbbase_tr = udat[(linesize / Bpp * visy) + (visx + 1)];
|
||||
if(visy < bargs->begy + leny - 1){
|
||||
rgbbase_br = dat + (linesize * (visy + 1)) + ((visx + 1) * bpp / CHAR_BIT);
|
||||
rgbbase_br = udat[(linesize / Bpp * (visy + 1)) + (visx + 1)];
|
||||
}
|
||||
}
|
||||
if(visy < bargs->begy + leny - 1){
|
||||
rgbbase_bl = dat + (linesize * (visy + 1)) + (visx * bpp / CHAR_BIT);
|
||||
rgbbase_bl = udat[(linesize / Bpp * (visy + 1)) + visx];
|
||||
}
|
||||
//fprintf(stderr, "[%04d/%04d] bpp: %d lsize: %d %02x %02x %02x %02x\n", y, x, bpp, linesize, rgbbase_tl[0], rgbbase_tr[1], rgbbase_bl[2], rgbbase_br[3]);
|
||||
//fprintf(stderr, "[%04d/%04d] bpp: %d lsize: %d\n", y, x, bpp, linesize);
|
||||
nccell* c = ncplane_cell_ref_yx(nc, y, x);
|
||||
c->channels = 0;
|
||||
c->stylemask = 0;
|
||||
const char* egc = qtrans_check(c, bargs->u.cell.blendcolors, rgbbase_tl, rgbbase_tr, rgbbase_bl, rgbbase_br, bargs->transcolor);
|
||||
const char* egc = qtrans_check(c, bargs->u.cell.blendcolors,
|
||||
rgbbase_tl, rgbbase_tr,
|
||||
rgbbase_bl, rgbbase_br,
|
||||
bargs->transcolor);
|
||||
fprintf(stderr, "POST-QTRANS: %016lx\n", c->channels);
|
||||
if(egc == NULL){
|
||||
uint32_t tl = 0, tr = 0, bl = 0, br = 0;
|
||||
ncchannel_set_rgb8(&tl, rgbbase_tl[0], rgbbase_tl[1], rgbbase_tl[2]);
|
||||
ncchannel_set_rgb8(&tr, rgbbase_tr[0], rgbbase_tr[1], rgbbase_tr[2]);
|
||||
ncchannel_set_rgb8(&bl, rgbbase_bl[0], rgbbase_bl[1], rgbbase_bl[2]);
|
||||
ncchannel_set_rgb8(&br, rgbbase_br[0], rgbbase_br[1], rgbbase_br[2]);
|
||||
ncchannel_set_rgb8(&tl, ncpixel_r(rgbbase_tl), ncpixel_g(rgbbase_tl), ncpixel_b(rgbbase_tl));
|
||||
ncchannel_set_rgb8(&tr, ncpixel_r(rgbbase_tr), ncpixel_g(rgbbase_tr), ncpixel_b(rgbbase_tr));
|
||||
ncchannel_set_rgb8(&bl, ncpixel_r(rgbbase_bl), ncpixel_g(rgbbase_bl), ncpixel_b(rgbbase_bl));
|
||||
ncchannel_set_rgb8(&br, ncpixel_r(rgbbase_br), ncpixel_g(rgbbase_br), ncpixel_b(rgbbase_br));
|
||||
uint32_t bg, fg;
|
||||
//fprintf(stderr, "qtrans check: %d/%d\n%08x %08x\n%08x %08x\n", y, x, *(const uint32_t*)rgbbase_tl, *(const uint32_t*)rgbbase_tr, *(const uint32_t*)rgbbase_bl, *(const uint32_t*)rgbbase_br);
|
||||
egc = quadrant_solver(tl, tr, bl, br, &fg, &bg);
|
||||
@ -483,6 +483,7 @@ quadrant_blit(ncplane* nc, int linesize, const void* data,
|
||||
}
|
||||
cell_set_blitquadrants(c, 1, 1, 1, 1);
|
||||
}
|
||||
fprintf(stderr, "POST-POST-QTRANS: %016lx\n", c->channels);
|
||||
if(*egc){
|
||||
if(pool_blit_direct(&nc->pool, c, egc, strlen(egc), 1) <= 0){
|
||||
return -1;
|
||||
|
@ -1526,6 +1526,7 @@ void ncvisual_printbanner(const notcurses* nc);
|
||||
// bits against each pixel's RGB value, and treat a match as transparent.
|
||||
static inline bool
|
||||
rgba_trans_p(uint32_t p, uint32_t transcolor){
|
||||
fprintf(stderr, "ALPHA CHECK: %08x %02x\n", p, ncpixel_a(p));
|
||||
if(ncpixel_a(p) < 192){
|
||||
return true;
|
||||
}
|
||||
|
@ -2712,14 +2712,15 @@ ncplane_as_rgba_internal(const ncplane* nc, ncblitter_e blit,
|
||||
for(int px = 0 ; px < bset->width ; ++px){
|
||||
uint32_t* p = &ret[(targy + py) * (lenx * bset->width) + (targx + px)];
|
||||
bool background = is_bg_p(idx, py, px, bset->width);
|
||||
fprintf(stderr, "FG: %02x %02x %02x BG: %02x %02x %02x %08x\n", fr, fg, fb, br, bg, bb, *p);
|
||||
if(background){
|
||||
if(ba){
|
||||
*p = 0;
|
||||
}else{
|
||||
ncpixel_set_a(p, 0xff);
|
||||
ncpixel_set_r(p, br);
|
||||
ncpixel_set_g(p, bb);
|
||||
ncpixel_set_b(p, bg);
|
||||
ncpixel_set_g(p, bg);
|
||||
ncpixel_set_b(p, bb);
|
||||
}
|
||||
}else{
|
||||
if(fa){
|
||||
@ -2727,10 +2728,11 @@ ncplane_as_rgba_internal(const ncplane* nc, ncblitter_e blit,
|
||||
}else{
|
||||
ncpixel_set_a(p, 0xff);
|
||||
ncpixel_set_r(p, fr);
|
||||
ncpixel_set_g(p, fb);
|
||||
ncpixel_set_b(p, fg);
|
||||
ncpixel_set_g(p, fg);
|
||||
ncpixel_set_b(p, fb);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "POST FG: %02x %02x %02x BG: %02x %02x %02x *P: %08x\n", fr, fg, fb, br, bg, bb, *p);
|
||||
}
|
||||
}
|
||||
free(c);
|
||||
|
Loading…
x
Reference in New Issue
Block a user