From 23795d290ed8026150c5634dd31db030771ac53a Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 30 Aug 2006 16:03:24 -0700 Subject: [PATCH] More sophisticated alpha blending; comment out background call ATM --- com32/lib/MCONFIG | 2 +- com32/lib/Makefile | 4 ++ com32/lib/sys/vesa/background.c | 3 ++ com32/lib/sys/vesa/drawtxt.c | 86 ++++++++++++++++++++++++++++------------- 4 files changed, 67 insertions(+), 28 deletions(-) diff --git a/com32/lib/MCONFIG b/com32/lib/MCONFIG index 1263b51..b542196 100644 --- a/com32/lib/MCONFIG +++ b/com32/lib/MCONFIG @@ -23,7 +23,7 @@ LIBFLAGS = -DDYNAMIC_CRC_TABLE -DPNG_NO_CONSOLE_IO \ REQFLAGS = -g -m32 -mregparm=3 -DREGPARM=3 -D__COM32__ -I. -I./sys -I../include OPTFLAGS = -Os -march=i386 -falign-functions=0 -falign-jumps=0 \ - -falign-labels=0 -ffast-math + -falign-labels=0 -ffast-math -fomit-frame-pointer WARNFLAGS = -W -Wall -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Winline CFLAGS = -Wp,-MT,$@,-MD,$(dir $@).$(notdir $@).d $(OPTFLAGS) \ diff --git a/com32/lib/Makefile b/com32/lib/Makefile index 5b6e057..05b2279 100644 --- a/com32/lib/Makefile +++ b/com32/lib/Makefile @@ -85,4 +85,8 @@ sys/vesa/alphatbl.o: sys/vesa/alphatbl.c sys/vesa/alphatbl.c: sys/vesa/alphatbl.pl $(PERL) $< > $@ || ( rm -f $@ ; exit 1 ) +# This code is performance critical, and doesn't compile well with -Os +sys/vesa/drawtxt.o: sys/vesa/drawtxt.c + $(CC) $(CFLAGS) -O3 -c -o $@ $< + -include .*.d */.*.d diff --git a/com32/lib/sys/vesa/background.c b/com32/lib/sys/vesa/background.c index 5a34ef8..c40b138 100644 --- a/com32/lib/sys/vesa/background.c +++ b/com32/lib/sys/vesa/background.c @@ -126,12 +126,14 @@ int vesacon_load_background(const char *filename) else if (info_ptr->bit_depth < 8) png_set_packing(png_ptr); +#if 0 if (png_get_bKGD(png_ptr, info_ptr, &image_background)) png_set_background(png_ptr, image_background, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); else png_set_background(png_ptr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); +#endif /* Whew! Now we should get the stuff we want... */ for (i = 0; i < info_ptr->height; i++) @@ -160,4 +162,5 @@ int __vesacon_init_background(void) memset(__vesacon_background, 0, sizeof __vesacon_background); /* The VESA BIOS has already cleared the screen */ + return 0; } diff --git a/com32/lib/sys/vesa/drawtxt.c b/com32/lib/sys/vesa/drawtxt.c index 94634b0..c4e32c5 100644 --- a/com32/lib/sys/vesa/drawtxt.c +++ b/com32/lib/sys/vesa/drawtxt.c @@ -30,6 +30,29 @@ #include "video.h" /* + * Color map (ARGB) for the 16 PC colors. This can be overridden by the + * application, and do not have to match the traditional colors. + */ +uint32_t vesacon_color_map[16] = { + 0x00000000, /* black */ + 0x400000ff, /* dark blue */ + 0x4000ff00, /* dark green */ + 0x4000ffff, /* dark cyan */ + 0x40ff0000, /* dark red */ + 0x40ff00ff, /* dark purple */ + 0x80ff8000, /* brown */ + 0xc0ffffff, /* light grey */ + 0x40ffffff, /* dark grey */ + 0xc00000ff, /* bright blue */ + 0xc000ff00, /* bright green */ + 0xc000ffff, /* bright cyan */ + 0xc0ff0000, /* bright red */ + 0xc0ff00ff, /* bright purple */ + 0xffffff00, /* yellow */ + 0xffffffff, /* white */ +}; + +/* * Linear alpha blending. Useless for anything that's actually * depends on color accuracy (because of gamma), but it's fine for * what we want. @@ -37,20 +60,35 @@ * This algorithm is exactly equivalent to (alpha*fg+(255-alpha)*bg)/255 * for all 8-bit values, but is substantially faster. */ -static inline uint8_t alpha(uint8_t fg, uint8_t bg, uint8_t alpha) +static inline __attribute__((always_inline)) + uint8_t alpha_val(uint8_t fg, uint8_t bg, uint8_t alpha) { unsigned int tmp = 1 + alpha*fg + (255-alpha)*bg; return (tmp + (tmp >> 8)) >> 8; } +static uint32_t alpha_pixel(uint32_t fg, uint32_t bg) +{ + uint8_t alpha = fg >> 24; + uint8_t fg_r = fg >> 16; + uint8_t fg_g = fg >> 8; + uint8_t fg_b = fg; + uint8_t bg_r = bg >> 16; + uint8_t bg_g = bg >> 8; + uint8_t bg_b = bg; + + return + (alpha_val(fg_r, bg_r, alpha) << 16)| + (alpha_val(fg_g, bg_g, alpha) << 8)| + (alpha_val(fg_b, bg_b, alpha)); +} + static void vesacon_update_characters(int row, int col, int nrows, int ncols) { const int height = __vesacon_font_height; const int width = FONT_WIDTH; - uint32_t *bgrowptr, *bgptr, *fbrowptr, *fbptr, bgval, bgxval; - int fr = 0, fg = 0, fb = 0; - int br = 0, bg = 0, bb = 0; - uint8_t r, g, b; + uint32_t *bgrowptr, *bgptr, *fbrowptr, *fbptr, bgval, fgval; + uint32_t fgcolor = 0, bgcolor = 0, color; uint8_t chbits = 0, chxbits = 0, chsbits = 0; int i, j, pixrow, pixsrow; struct vesa_char *rowptr, *rowsptr, *cptr, *csptr; @@ -89,12 +127,8 @@ static void vesacon_update_characters(int row, int col, int nrows, int ncols) chxbits = chbits; chxbits &= (cptr->sha & 0x02) ? 0xff : 0x00; chxbits ^= (cptr->sha & 0x01) ? 0xff : 0x00; - fr = ((cptr->attr & 4) >> 1) + ((cptr->attr & 8) >> 3); - fg = ((cptr->attr & 2)) + ((cptr->attr & 8) >> 3); - fb = ((cptr->attr & 1) << 1) + ((cptr->attr & 8) >> 3); - br = ((cptr->attr & 0x40) >> 5) + ((cptr->attr & 0x80) >> 7); - bg = ((cptr->attr & 0x20) >> 4) + ((cptr->attr & 0x80) >> 7); - bb = ((cptr->attr & 0x10) >> 3) + ((cptr->attr & 0x80) >> 7); + fgcolor = vesacon_color_map[cptr->sha & 0x0f]; + bgcolor = vesacon_color_map[cptr->sha >> 4]; cptr++; break; case FONT_WIDTH-1: @@ -107,25 +141,23 @@ static void vesacon_update_characters(int row, int col, int nrows, int ncols) break; } - bgval = *bgptr; - bgxval = bgptr[VIDEO_X_SIZE+1]; + /* If this pixel is raised, use the offsetted value */ + bgval = (chxbits & 0x80) ? bgptr[VIDEO_X_SIZE+1] : *bgptr; bgptr++; - - if (chbits & 0x80) { - r = __vesacon_alpha_tbl[(uint8_t)(bgxval >> 16)][fr]; - g = __vesacon_alpha_tbl[(uint8_t)(bgxval >> 8)][fg]; - b = __vesacon_alpha_tbl[(uint8_t)bgxval][fb]; - } else if ((chsbits & ~chxbits) & 0x80) { - r = __vesacon_alpha_tbl[(uint8_t)(bgval >> 16)][br] >> 2; - g = __vesacon_alpha_tbl[(uint8_t)(bgval >> 8)][bg] >> 2; - b = __vesacon_alpha_tbl[(uint8_t)bgval][bb] >> 2; - } else { - r = __vesacon_alpha_tbl[(uint8_t)(bgval >> 16)][br]; - g = __vesacon_alpha_tbl[(uint8_t)(bgval >> 8)][bg]; - b = __vesacon_alpha_tbl[(uint8_t)bgval][bb]; + + /* If this pixel is set, use the fg color, else the bg color */ + fgval = (chbits & 0x80) ? fgcolor : bgcolor; + + /* Produce the combined color pixel value */ + color = alpha_pixel(fgval, bgval); + + /* Apply the shadow (75% shadow) */ + if ((chsbits & ~chxbits) & 0x80) { + color >>= 2; + color &= 0x3f3f3f; } - *fbptr++ = (r << 16)|(g << 8)|b; + *fbptr++ = color; } bgrowptr += VIDEO_X_SIZE; -- 2.7.4