Author: tkreuzer Date: Wed Jan 9 12:40:42 2013 New Revision: 58148
URL: http://svn.reactos.org/svn/reactos?rev=58148&view=rev Log: [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.
Modified: trunk/reactos/drivers/base/bootvid/i386/vga.c
Modified: trunk/reactos/drivers/base/bootvid/i386/vga.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/base/bootvid/i386/v... ============================================================================== --- trunk/reactos/drivers/base/bootvid/i386/vga.c [iso-8859-1] (original) +++ trunk/reactos/drivers/base/bootvid/i386/vga.c [iso-8859-1] Wed Jan 9 12:40:42 2013 @@ -114,19 +114,32 @@ 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) -{ - PUCHAR FontChar; - ULONG i, j, XOffset; - - /* Get the font line for this character */ - FontChar = &FontData[Character * BOOTCHAR_HEIGHT]; + ULONG BackColor) +{ + PUCHAR FontChar, PixelPtr; + ULONG Height; + UCHAR Shift;
/* Switch to mode 10 */ ReadWriteMode(10); @@ -137,40 +150,84 @@ /* 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); - } - - /* Increase X Offset */ - XOffset++; - } while (j >>= 1); - - /* Move to the next Y ordinate */ - Top++; - } while (--i); + SET_PIXELS(PixelPtr, *FontChar << Shift, TextColor); + PixelPtr += 80; + FontChar++; + } while (--Height); + } + + /* Check if the background color is transparent */ + if (BackColor >= 16) + { + /* We are done */ + return; + } + + /* 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