quadblitter: move to uint32_t throughout #1714

dankamongmen/rationalize-rgba
nick black 3 years ago
parent f77c008e88
commit 0c6dfceb7b
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC

@ -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;
ncpixel_r(uint32_t pixel){
return (htole(pixel) & 0x000000fful);
}
// Extract the 8-bit red component from an ABGR pixel
static inline unsigned
ncpixel_r(uint32_t pixel){
return (htole(pixel) & 0x000000fful);
ncpixel_a(uint32_t pixel){
return (htole(pixel) & 0xff000000ul) >> 24u;
}
// Extract the 8-bit green component from an ABGR pixel
static inline unsigned
ncpixel_g(uint32_t pixel){
return (htole(pixel) & 0x0000ff00ul) >> 8u;
ncpixel_b(uint32_t pixel){
return (htole(pixel) & 0x00ff0000ul) >> 16u;
}
// Extract the 8-bit blue component from an ABGR pixel
static inline unsigned
ncpixel_b(uint32_t pixel){
return (htole(pixel) & 0x00ff0000ul) >> 16u;
ncpixel_g(uint32_t pixel){
return (htole(pixel) & 0x0000ff00ul) >> 8u;
}
// 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

@ -4,30 +4,30 @@
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);
(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);
(g0 + g1 + g2 + 2) / 3,
(b0 + b1 + b2 + 2) / 3);
return ret;
}
@ -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…
Cancel
Save