From a54575d01e3ff8342e630b55529dddf5bdc8a883 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Wed, 9 Jan 2013 12:40:42 +0000 Subject: [PATCH] [BOOTVID] Rewrite DisplayCharacter. The new algorithm is much faster. It uses the VGA mask register to draws up to 8 pixels at once, completely getting rid of the inner loop. Pixel position / mask calculations and the check for opaque vs transparent background are moved out of the loops. The result is a single loop for the y coordinate containing an inlined __outbyte and memory write. A second loop in case of unaligned character writes. svn path=/trunk/; revision=58148 --- reactos/drivers/base/bootvid/i386/vga.c | 125 +++++++++++++++++------- 1 file changed, 91 insertions(+), 34 deletions(-) diff --git a/reactos/drivers/base/bootvid/i386/vga.c b/reactos/drivers/base/bootvid/i386/vga.c index 28a43cc9c56..4ec6ebe1aaf 100644 --- a/reactos/drivers/base/bootvid/i386/vga.c +++ b/reactos/drivers/base/bootvid/i386/vga.c @@ -114,19 +114,32 @@ SetPixel(IN ULONG Left, READ_REGISTER_UCHAR(PixelPosition) & Color); } +#ifdef CHAR_GEN_UPSIDE_DOWN +# define GetFontPtr(_Char) &FontData[_Char * BOOTCHAR_HEIGHT] + BOOTCHAR_HEIGHT - 1; +# define FONT_PTR_DELTA (-1) +#else +# define GetFontPtr(_Char) &FontData[_Char * BOOTCHAR_HEIGHT]; +# define FONT_PTR_DELTA (1) +#endif + +#define SET_PIXELS(_PixelPtr, _PixelMask, _TextColor) \ + /* Select the bitmask register and write the mask */ \ + __outpw(0x3CE, (_PixelMask << 8) | 8); \ +\ + /* Set the new color */ \ + WRITE_REGISTER_UCHAR(_PixelPtr, (UCHAR)_TextColor);\ + VOID NTAPI DisplayCharacter(CHAR Character, ULONG Left, ULONG Top, ULONG TextColor, - ULONG BackTextColor) + ULONG BackColor) { - PUCHAR FontChar; - ULONG i, j, XOffset; - - /* Get the font line for this character */ - FontChar = &FontData[Character * BOOTCHAR_HEIGHT]; + PUCHAR FontChar, PixelPtr; + ULONG Height; + UCHAR Shift; /* Switch to mode 10 */ ReadWriteMode(10); @@ -137,40 +150,84 @@ DisplayCharacter(CHAR Character, /* Select the color don't care register */ __outpw(0x3CE, 7); - /* Loop each pixel height */ - i = BOOTCHAR_HEIGHT; + /* Calculate shift */ + Shift = Left & 7; + + /* Get the font and pixel pointer */ + FontChar = GetFontPtr(Character); + PixelPtr = (PUCHAR)VgaBase + (Left >> 3) + (Top * 80); + + /* Loop all pixel rows */ + Height = BOOTCHAR_HEIGHT; do { - /* Loop each pixel width */ - j = 128; - XOffset = Left; + SET_PIXELS(PixelPtr, *FontChar >> Shift, TextColor); + PixelPtr += 80; + FontChar += FONT_PTR_DELTA; + } while (--Height); + + /* Check if we need to update neighbor bytes */ + if (Shift) + { + /* Calculate shift for 2nd byte */ + Shift = 8 - Shift; + + /* Get the font and pixel pointer (2nd byte) */ + FontChar = GetFontPtr(Character); + PixelPtr = (PUCHAR)VgaBase + (Left >> 3) + (Top * 80) + 1; + + /* Loop all pixel rows */ + Height = BOOTCHAR_HEIGHT; do { - /* Check if we should draw this pixel */ -#ifdef CHAR_GEN_UPSIDE_DOWN - if (FontChar[i] & (UCHAR)j) -#else - /* Normal character generator (top of char is first element) */ - if (FontChar[BOOTCHAR_HEIGHT - i] & (UCHAR)j) -#endif - { - /* We do, use the given Text Color */ - SetPixel(XOffset, Top, (UCHAR)TextColor); - } - else if (BackTextColor < 16) - { - /* This is a background pixel. */ - /* We're drawing it unless it's transparent. */ - SetPixel(XOffset, Top, (UCHAR)BackTextColor); - } + SET_PIXELS(PixelPtr, *FontChar << Shift, TextColor); + PixelPtr += 80; + FontChar++; + } while (--Height); + } - /* Increase X Offset */ - XOffset++; - } while (j >>= 1); + /* Check if the background color is transparent */ + if (BackColor >= 16) + { + /* We are done */ + return; + } - /* Move to the next Y ordinate */ - Top++; - } while (--i); + /* Calculate shift */ + Shift = Left & 7; + + /* Get the font and pixel pointer */ + FontChar = GetFontPtr(Character); + PixelPtr = (PUCHAR)VgaBase + (Left >> 3) + (Top * 80); + + /* Loop all pixel rows */ + Height = BOOTCHAR_HEIGHT; + do + { + SET_PIXELS(PixelPtr, ~*FontChar >> Shift, BackColor); + PixelPtr += 80; + FontChar++; + } while (--Height); + + /* Check if we need to update neighbor bytes */ + if (Shift) + { + /* Calculate shift for 2nd byte */ + Shift = 8 - Shift; + + /* Get the font and pixel pointer (2nd byte) */ + FontChar = GetFontPtr(Character); + PixelPtr = (PUCHAR)VgaBase + (Left >> 3) + (Top * 80) + 1; + + /* Loop all pixel rows */ + Height = BOOTCHAR_HEIGHT; + do + { + SET_PIXELS(PixelPtr, ~*FontChar << Shift, BackColor); + PixelPtr += 80; + FontChar++; + } while (--Height); + } } VOID