From 507e551ebdfb1642ddf507ecaf6399eaf1bf9fd3 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 15 Sep 2006 23:00:58 -0700 Subject: [PATCH] Actually do proper gamma-corrected alpha blending. It seems fast enough. --- com32/lib/Makefile | 6 ++++- com32/lib/sys/vesa/alphatbl.pl | 54 ++++++++++++++++++++++++++++++++++++++++++ com32/lib/sys/vesa/drawtxt.c | 16 +++++-------- com32/lib/sys/vesa/video.h | 3 ++- 4 files changed, 67 insertions(+), 12 deletions(-) create mode 100644 com32/lib/sys/vesa/alphatbl.pl diff --git a/com32/lib/Makefile b/com32/lib/Makefile index d20bc3b..e3cef23 100644 --- a/com32/lib/Makefile +++ b/com32/lib/Makefile @@ -42,6 +42,7 @@ LIBOBJS = \ \ sys/vesacon_write.o sys/vesaserial_write.o \ sys/vesa/initvesa.o sys/vesa/drawtxt.o sys/vesa/background.o \ + sys/vesa/alphatbl.o \ \ pci/cfgtype.o \ pci/readb.o pci/readw.o pci/readl.o pci/readbios.o \ @@ -77,7 +78,7 @@ libcom32.a : $(LIBOBJS) $(RANLIB) $@ tidy: - rm -f *.o .*.d */*.o */.*.d lib/sys/vesa/alphatbl.c + rm -f *.o .*.d */*.o */.*.d sys/vesa/alphatbl.c clean: tidy rm -f *.a @@ -95,6 +96,9 @@ install: all sys/vesa/drawtxt.o: sys/vesa/drawtxt.c $(CC) $(CFLAGS) -O3 -c -o $@ $< +sys/vesa/alphatbl.c: sys/vesa/alphatbl.pl + $(PERL) $< > $@ + jpeg/jidctflt.o: jpeg/jidctflt.c $(CC) $(CFLAGS) -O3 -c -o $@ $< diff --git a/com32/lib/sys/vesa/alphatbl.pl b/com32/lib/sys/vesa/alphatbl.pl new file mode 100644 index 0000000..dd71648 --- /dev/null +++ b/com32/lib/sys/vesa/alphatbl.pl @@ -0,0 +1,54 @@ +#!/usr/bin/perl +# +# Produce gamma-correction tables for alpha blending, assuming sRGB space. +# + +sub srgb_to_linear($) +{ + my($s) = @_; + + if ($s <= 10) { + return $s/(255*12.92); + } else { + return (($s+14.025)/269.025)**2.4; + } +} + +sub linear_to_srgb($) +{ + my($l) = @_; + my $s; + + if ($l <= 0.00304) { + $s = 12.92*$l; + } else { + $s = 1.055*$l**(1.0/2.4) - 0.055; + } + + return int($s*255+0.5); +} + +# Header +print "#include \n\n"; + +# +# Table 1: convert 8-bit sRGB values to 16-bit linear values +# + +print "const uint16_t __vesacon_srgb_to_linear[256] = {\n"; +for ($i = 0; $i <= 255; $i++) { + printf "\t%5d,\n", int(srgb_to_linear($i)*65535+0.5); +} +print "};\n\n"; + +# +# Table 2: convert linear values in the range [0, 65535*255], +# shifted right by 12 bits, to sRGB +# + +print "const uint8_t __vesacon_linear_to_srgb[4080] = {\n"; +for ($i = 0; $i <= 4079; $i++) { + printf "\t%3d,\n", linear_to_srgb(($i+0.5)/4079.937744); +} +print "};\n\n"; + diff --git a/com32/lib/sys/vesa/drawtxt.c b/com32/lib/sys/vesa/drawtxt.c index 794ebe0..f35e1b7 100644 --- a/com32/lib/sys/vesa/drawtxt.c +++ b/com32/lib/sys/vesa/drawtxt.c @@ -45,19 +45,15 @@ static inline void *copy_dword(void *dst, void *src, size_t dword_count) return dst; /* Updated destination pointer */ } -/* - * 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 __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; + unsigned int tmp; + + tmp = __vesacon_srgb_to_linear[fg] * alpha; + tmp += __vesacon_srgb_to_linear[bg] * (255-alpha); + + return __vesacon_linear_to_srgb[tmp >> 12]; } static uint32_t alpha_pixel(uint32_t fg, uint32_t bg) diff --git a/com32/lib/sys/vesa/video.h b/com32/lib/sys/vesa/video.h index 13449d8..5070f9e 100644 --- a/com32/lib/sys/vesa/video.h +++ b/com32/lib/sys/vesa/video.h @@ -69,7 +69,8 @@ extern uint8_t __vesacon_graphics_font[FONT_MAX_CHARS][FONT_MAX_HEIGHT]; extern uint32_t __vesacon_background[VIDEO_Y_SIZE][VIDEO_X_SIZE]; extern uint32_t __vesacon_shadowfb[VIDEO_Y_SIZE][VIDEO_X_SIZE]; -extern unsigned char __vesacon_alpha_tbl[256][4]; +extern const uint16_t __vesacon_srgb_to_linear[256]; +extern const uint8_t __vesacon_linear_to_srgb[4080]; int __vesacon_init_background(void); int vesacon_load_background(const char *); -- 2.7.4