/* uuterm, Copyright (C) 2006 Rich Felker; licensed under GNU GPL v2 only */ #include #include "uuterm.h" #include "dblbuf.h" static void blitline8(unsigned char *dest, unsigned char *src, unsigned long *colors, int w) { #define T(x) ~((x&8)*0xff>>3 | (x&4)*0xff<<6 | (x&2)*0xff<<15 | (x&1)*0xff<<24) static const uint32_t tab[16] = { T(0), T(1), T(2), T(3), T(4), T(5), T(6), T(7), T(8), T(9), T(10), T(11), T(12), T(13), T(14), T(15) }; #undef T uint32_t *dest4 = (uint32_t*)dest; for(; w--; dest4+=2, colors+=2) { int s = *src++; int t0 = tab[s>>4]; int t1 = tab[s&15]; dest4[0] = colors[0] ^ (colors[1] & t0); dest4[1] = colors[0] ^ (colors[1] & t1); } } static void blitline16(unsigned char *dest, unsigned char *src, unsigned long *colors, int w) { static const union { unsigned char b[4]; uint32_t w; } tab[4] = { { { 0xff, 0xff, 0xff, 0xff } }, { { 0xff, 0xff, 0x00, 0x00 } }, { { 0x00, 0x00, 0xff, 0xff } }, { { 0x00, 0x00, 0x00, 0x00 } } }; uint32_t *dest4 = (uint32_t*)dest; for(; w--; dest4+=4, colors+=2) { int s = *src++; uint32_t t0 = tab[s>>6].w; uint32_t t1 = tab[(s>>4)&3].w; uint32_t t2 = tab[(s>>2)&3].w; uint32_t t3 = tab[s&3].w; dest4[0] = colors[0] ^ (colors[1] & t0); dest4[1] = colors[0] ^ (colors[1] & t1); dest4[2] = colors[0] ^ (colors[1] & t2); dest4[3] = colors[0] ^ (colors[1] & t3); } } static void blit_slice(struct uudisp *d, int idx, int x1, int x2) { struct dblbuf *b = (void *)&d->priv; int cs = (d->cell_w+7)>>3; int y = b->slices[idx].y; int w = x2 - x1 + 1; int s = d->w * cs; int i; unsigned char *dest = b->vidmem + y*b->row_stride + x1*d->cell_w*b->bytes_per_pixel; unsigned char *src = b->slices[idx].bitmap + x1*cs; unsigned long *colors = b->slices[idx].colors + 2*x1; for (i=0; icell_h; i++) { if (b->bytes_per_pixel == 1) blitline8(dest, src, colors, w); else if (b->bytes_per_pixel == 2) blitline16(dest, src, colors, w); dest += b->line_stride; src += s; } } void clear_cells(struct uudisp *d, int idx, int x1, int x2) { struct dblbuf *b = (void *)&d->priv; int i; int cs = d->cell_w+7 >> 3; int cnt = (x2 - x1 + 1) * cs; int stride = d->w * cs; unsigned char *dest = b->slices[idx].bitmap + x1 * cs; memset(b->slices[idx].colors + 2*x1, 0, (x2-x1+1)*2*sizeof(long)); for (i=d->cell_h; i; i--, dest += stride) memset(dest, 0, cnt); } static unsigned long expand_color(struct uudisp *d, int color) { struct dblbuf *b = (void *)&d->priv; if (b->bytes_per_pixel > 1) { int R = color<<1 & 2; int G = color & 2; int B = color>>1 & 2; if (color>>3) { R++; G++; B++; } if (b->bytes_per_pixel == 2) return (R*0xa + (G*0x14<<5) + (B*0xa<<11)) * (unsigned long)0x0001000100010001; else if (b->bytes_per_pixel == 4) return (R*0x50 + (G*0x50<<8) + (B*0x50<<16)) * (unsigned long)0x0000000100000001; } return color * (unsigned long)0x0101010101010101; } void uudisp_predraw_cell(struct uudisp *d, int idx, int x, int color) { struct dblbuf *b = (void *)&d->priv; b->slices[idx].colors[2*x] = expand_color(d, color&15); b->slices[idx].colors[2*x+1] = expand_color(d, color>>4) ^ b->slices[idx].colors[2*x]; } void uudisp_draw_glyph(struct uudisp *d, int idx, int x, const void *glyph) { struct dblbuf *b = (void *)&d->priv; int i; int cs = d->cell_w+7 >> 3; int stride = d->w * cs; unsigned char *src = (void *)glyph; unsigned char *dest = b->slices[idx].bitmap + cs * x; for (i=d->cell_h; i; i--, dest += stride) *dest |= *src++; } void uudisp_refresh(struct uudisp *d, struct uuterm *t) { struct dblbuf *b = (void *)&d->priv; int h = t->h < d->h ? t->h : d->h; int x1, x2, idx, y; if (!b->active) return; if (b->repaint) { for (idx=0; idxslices[idx].y = -1; b->repaint = 0; } /* Clean up cursor first.. */ idx = t->rows[b->curs_y]->idx; if ((unsigned)b->slices[idx].y < d->h) blit_slice(d, idx, b->curs_x, b->curs_x); for (y=0; yrows[y]->x1; x2 = t->rows[y]->x2; idx = t->rows[y]->idx; if (x2 >= x1) { clear_cells(d, idx, x1, x2); uuterm_refresh_row(d, t->rows[y], x1, x2); t->rows[y]->x1 = t->w; t->rows[y]->x2 = -1; } if (b->slices[idx].y != y) { b->slices[idx].y = y; x1 = 0; x2 = d->w-1; } else if (x2 < x1) continue; blit_slice(d, idx, x1, x2); } if (d->blink & 1) { unsigned long rev = expand_color(d, 15); int idx = t->rows[t->y]->idx; b->slices[idx].colors[2*t->x] ^= rev; blit_slice(d, idx, t->x, t->x); b->slices[idx].colors[2*t->x] ^= rev; } b->curs_x = t->x; b->curs_y = t->y; } struct slice *dblbuf_setup_buf(int w, int h, int cs, int ch, unsigned char *mem) { struct slice *slices = (void *)mem; int i; mem += sizeof(slices[0]) * h; for (i=0; i