summaryrefslogtreecommitdiff
path: root/dblbuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'dblbuf.c')
-rw-r--r--dblbuf.c220
1 files changed, 220 insertions, 0 deletions
diff --git a/dblbuf.c b/dblbuf.c
new file mode 100644
index 0000000..ad70576
--- /dev/null
+++ b/dblbuf.c
@@ -0,0 +1,220 @@
+/* uuterm, Copyright (C) 2006 Rich Felker; licensed under GNU GPL v2 only */
+
+#include "uuterm.h"
+#include "dblbuf.h"
+
+#if 0
+static void blitline8_crap(unsigned char *dest, unsigned char *src, unsigned char *colors, int w, int cw)
+{
+ int cs = (cw+7)>>3;
+ int skip = (-cw)&7;
+ int x, i, j;
+ signed char b;
+ for (x=0; x<w; x++) {
+ j=skip;
+ b=*src++<<skip;
+ for (i=0; ; i++) {
+ for (; j<8; j++, b<<=1)
+ //*dest++ = 7 & (b>>7);
+ *dest++ = (*colors&15&(b>>7)) | (*colors>>4&~(b>>7));
+ if (i >= cs) break;
+ b=*src++;
+ j=0;
+ }
+ colors++;
+ }
+}
+
+static void blitline8_2(unsigned char *dest, unsigned char *src, unsigned char *colors, int w, int cw)
+{
+ int cs = (cw+7)>>3;
+ int skip = (-cw)&7;
+ int x, i, j;
+ signed char b;
+ unsigned char fg, bg;
+
+ for (x=0; x<w; x++) {
+ j=skip;
+ b=*src++<<skip;
+ fg = *colors & 15;
+ bg = *colors++ >> 4;
+ for (i=0; ; i++) {
+ for (; j<8; j++, b<<=1)
+ *dest++ = (fg&(b>>7)) | (bg&~(b>>7));
+ if (i >= cs) break;
+ b=*src++;
+ j=0;
+ }
+ }
+}
+#endif
+
+#ifdef HAVE_I386_ASM
+
+#define BLIT_PIXEL_8 \
+ "add %%al,%%al \n\t" \
+ "sbb %%dl,%%dl \n\t" \
+ "and %%bh,%%dl \n\t" \
+ "mov %%bl,%%dh \n\t" \
+ "add %%dl,%%dh \n\t" \
+ "mov %%dh,(%%edi) \n\t" \
+ "inc %%edi \n\t" \
+
+static void blitline8(unsigned char *dest, unsigned char *src, unsigned char *colors, int w, int cw)
+{
+ __asm__ __volatile__(
+ "push %%ebp \n\t"
+ "mov %%ebx, %%ebp \n\t"
+ "\n1: \n\t"
+ "mov (%%esi), %%al \n\t"
+ "inc %%esi \n\t"
+ "mov (%%ecx), %%bl \n\t"
+ "inc %%ecx \n\t"
+ "mov %%bl, %%bh \n\t"
+ "shr $4, %%bl \n\t"
+ "and $15, %%bh \n\t"
+ "sub %%bl, %%bh \n\t"
+ BLIT_PIXEL_8
+ BLIT_PIXEL_8
+ BLIT_PIXEL_8
+ BLIT_PIXEL_8
+ BLIT_PIXEL_8
+ BLIT_PIXEL_8
+ BLIT_PIXEL_8
+ BLIT_PIXEL_8
+ "dec %%ebp \n\t"
+ "jnz 1b \n\t"
+ "pop %%ebp \n\t"
+ : "=S"(src), "=D"(dest), "=c"(colors), "=b"(w)
+ : "S"(src), "D"(dest), "c"(colors), "b"(w)
+ : "memory" );
+}
+#else
+static void blitline8(unsigned char *dest, unsigned char *src, unsigned char *colors, int w, int cw)
+{
+ int x;
+ unsigned char b;
+ unsigned char c[2];
+
+ for (x=0; x<w; x++) {
+ b=*src++;
+ c[1] = *colors & 15;
+ c[0] = *colors++ >> 4;
+ dest[0] = c[b>>7]; b<<=1;
+ dest[1] = c[b>>7]; b<<=1;
+ dest[2] = c[b>>7]; b<<=1;
+ dest[3] = c[b>>7]; b<<=1;
+ dest[4] = c[b>>7]; b<<=1;
+ dest[5] = c[b>>7]; b<<=1;
+ dest[6] = c[b>>7]; b<<=1;
+ dest[7] = c[b>>7]; b<<=1;
+ dest += 8;
+ }
+}
+#endif
+
+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 char *colors = b->slices[idx].colors + x1;
+
+ for (i=0; i<d->cell_h; i++) {
+ blitline8(dest, src, colors, w, d->cell_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 + x1, 0, x2-x1+1);
+ for (i=d->cell_h; i; i--, dest += stride)
+ memset(dest, 0, cnt);
+}
+
+void uudisp_draw_glyph(struct uudisp *d, int idx, int x, const void *glyph, int color)
+{
+ 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;
+
+ b->slices[idx].colors[x] = color;
+ 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 y;
+
+ /* Clean up cursor first.. */
+ blit_slice(d, t->rows[b->curs_y]->idx, b->curs_x, b->curs_x);
+ //printf("--- %d\r\n", b->slices[t->rows[b->curs_y]->idx].y);
+
+ for (y=0; y<h; y++) {
+ int idx = t->rows[y]->idx;
+ int x1 = t->rows[y]->x1;
+ int x2 = t->rows[y]->x2;
+ 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) {
+ int idx = t->rows[t->y]->idx;
+ b->slices[idx].colors[t->x] ^= 0xff;
+ blit_slice(d, idx, t->x, t->x);
+ b->slices[idx].colors[t->x] ^= 0xff;
+ }
+ b->curs_x = t->x;
+ b->curs_y = t->y;
+ //printf("+++ %d\r\n", b->slices[t->rows[b->curs_y]->idx].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<h; i++, mem += w) {
+ slices[i].y = -1;
+ slices[i].colors = mem;
+ }
+ w *= cs * ch;
+ for (i=0; i<h; i++, mem += w)
+ slices[i].bitmap = mem;
+
+ return slices;
+}