More sophisticated alpha blending; comment out background call ATM
authorH. Peter Anvin <hpa@zytor.com>
Wed, 30 Aug 2006 23:03:24 +0000 (16:03 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Wed, 30 Aug 2006 23:03:24 +0000 (16:03 -0700)
com32/lib/MCONFIG
com32/lib/Makefile
com32/lib/sys/vesa/background.c
com32/lib/sys/vesa/drawtxt.c

index 1263b51..b542196 100644 (file)
@@ -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) \
index 5b6e057..05b2279 100644 (file)
@@ -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
index 5a34ef8..c40b138 100644 (file)
@@ -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;
 }
index 94634b0..c4e32c5 100644 (file)
 #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.
  * 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;