Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392/* * PROJECT: ReactOS Boot Video Driver * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * PURPOSE: Platform-independent common helpers and defines * COPYRIGHT: Copyright 2010 Gregor Schneider <gregor.schneider@reactos.org> * Copyright 2011 Rafal Harabien <rafalh@reactos.org> * Copyright 2020 Stanislav Motylkov <x86corez@gmail.com> */
#include "precomp.h"
/* GLOBALS ********************************************************************/
/* * Boot video driver default palette is similar to the standard 16-color * CGA palette, but it has Red and Blue channels swapped, and also dark * and light gray colors swapped. */const RGBQUAD VidpDefaultPalette[BV_MAX_COLORS] ={ RGB( 0, 0, 0), /* Black */ RGB(128, 0, 0), /* Red */ RGB( 0, 128, 0), /* Green */ RGB(128, 128, 0), /* Brown */ RGB( 0, 0, 128), /* Blue */ RGB(128, 0, 128), /* Magenta */ RGB( 0, 128, 128), /* Cyan */ RGB(128, 128, 128), /* Dark Gray */ RGB(192, 192, 192), /* Light Gray */ RGB(255, 0, 0), /* Light Red */ RGB( 0, 255, 0), /* Light Green */ RGB(255, 255, 0), /* Yellow */ RGB( 0, 0, 255), /* Light Blue */ RGB(255, 0, 255), /* Light Magenta */ RGB( 0, 255, 255), /* Light Cyan */ RGB(255, 255, 255), /* White */};
/* PRIVATE FUNCTIONS **********************************************************/
static VOIDBitBlt( _In_ ULONG Left, _In_ ULONG Top, _In_ ULONG Width, _In_ ULONG Height, _In_reads_bytes_(Delta * Height) PUCHAR Buffer, _In_ ULONG BitsPerPixel, _In_ ULONG Delta){ ULONG X, Y, Pixel; UCHAR Colors; PUCHAR InputBuffer; const ULONG Bottom = Top + Height; const ULONG Right = Left + Width;
/* Check if the buffer isn't 4bpp */ if (BitsPerPixel != 4) { /* FIXME: TODO */ DbgPrint("Unhandled BitBlt\n" "%lux%lu @ (%lu|%lu)\n" "Bits Per Pixel %lu\n" "Buffer: %p. Delta: %lu\n", Width, Height, Left, Top, BitsPerPixel, Buffer, Delta); return; }
PrepareForSetPixel();
/* 4bpp blitting */ for (Y = Top; Y < Bottom; ++Y) { InputBuffer = Buffer;
for (X = Left, Pixel = 0; X < Right; ++X, ++Pixel) { if (Pixel % 2 == 0) { /* Extract colors at every two pixels */ Colors = *InputBuffer++;
SetPixel(X, Y, Colors >> 4); } else { SetPixel(X, Y, Colors & 0x0F); } }
Buffer += Delta; }}
static VOIDRleBitBlt( _In_ ULONG Left, _In_ ULONG Top, _In_ ULONG Width, _In_ ULONG Height, _In_ PUCHAR Buffer){ ULONG YDelta; ULONG x; ULONG RleValue, NewRleValue; ULONG Color, Color2; ULONG i, j; ULONG Code;
PrepareForSetPixel();
/* Set Y height and current X value and start loop */ YDelta = Top + Height - 1; x = Left; for (;;) { /* Get the current value and advance in the buffer */ RleValue = *Buffer; Buffer++; if (RleValue) { /* Check if we've gone past the edge */ if ((x + RleValue) > (Width + Left)) { /* Fixup the pixel value */ RleValue = Left - x + Width; }
/* Get the new value */ NewRleValue = *Buffer;
/* Get the two colors */ Color = NewRleValue >> 4; Color2 = NewRleValue & 0xF;
/* Increase buffer position */ Buffer++;
/* Check if we need to do a fill */ if (Color == Color2) { /* Do a fill and continue the loop */ RleValue += x; VidSolidColorFill(x, YDelta, RleValue - 1, YDelta, (UCHAR)Color); x = RleValue; continue; }
/* Check if the pixel value is 1 or below */ if (RleValue > 1) { /* Set loop variables */ for (i = (RleValue - 2) / 2 + 1; i > 0; --i) { /* Set the pixels */ SetPixel(x, YDelta, (UCHAR)Color); x++; SetPixel(x, YDelta, (UCHAR)Color2); x++;
/* Decrease pixel value */ RleValue -= 2; } }
/* Check if there is any value at all */ if (RleValue) { /* Set the pixel and increase position */ SetPixel(x, YDelta, (UCHAR)Color); x++; }
/* Start over */ continue; }
/* Get the current pixel value */ RleValue = *Buffer; Code = RleValue; switch (Code) { /* Case 0 */ case 0: { /* Set new x value, decrease distance and restart */ x = Left; YDelta--; Buffer++; continue; }
/* Case 1 */ case 1: { /* Done */ return; }
/* Case 2 */ case 2: { /* Set new x value, decrease distance and restart */ Buffer++; x += *Buffer; Buffer++; YDelta -= *Buffer; Buffer++; continue; }
/* Other values */ default: { Buffer++; break; } }
/* Check if we've gone past the edge */ if ((x + RleValue) > (Width + Left)) { /* Set fixed up loop count */ i = RleValue - Left - Width + x;
/* Fixup pixel value */ RleValue -= i; } else { /* Clear loop count */ i = 0; }
/* Check the value now */ if (RleValue > 1) { /* Set loop variables */ for (j = (RleValue - 2) / 2 + 1; j > 0; --j) { /* Get the new value */ NewRleValue = *Buffer;
/* Get the two colors */ Color = NewRleValue >> 4; Color2 = NewRleValue & 0xF;
/* Increase buffer position */ Buffer++;
/* Set the pixels */ SetPixel(x, YDelta, (UCHAR)Color); x++; SetPixel(x, YDelta, (UCHAR)Color2); x++;
/* Decrease pixel value */ RleValue -= 2; } }
/* Check if there is any value at all */ if (RleValue) { /* Set the pixel and increase position */ Color = *Buffer >> 4; Buffer++; SetPixel(x, YDelta, (UCHAR)Color); x++; i--; }
/* Check loop count now */ if ((LONG)i > 0) { /* Decrease it */ i--;
/* Set new position */ Buffer = Buffer + (i / 2) + 1; }
/* Check if we need to increase the buffer */ if ((ULONG_PTR)Buffer & 1) Buffer++; }}
/* PUBLIC FUNCTIONS ***********************************************************/
VOIDNTAPIVidBufferToScreenBlt( _In_reads_bytes_(Delta * Height) PUCHAR Buffer, _In_ ULONG Left, _In_ ULONG Top, _In_ ULONG Width, _In_ ULONG Height, _In_ ULONG Delta){ /* Make sure we have a width and height */ if (!Width || !Height) return;
/* Call the helper function */ BitBlt(Left, Top, Width, Height, Buffer, 4, Delta);}
VOIDNTAPIVidBitBlt( _In_ PUCHAR Buffer, _In_ ULONG Left, _In_ ULONG Top){ PBITMAPINFOHEADER BitmapInfoHeader; LONG Delta; PUCHAR BitmapOffset; ULONG PaletteCount;
/* Get the Bitmap Header */ BitmapInfoHeader = (PBITMAPINFOHEADER)Buffer;
/* Initialize the palette */ PaletteCount = BitmapInfoHeader->biClrUsed ? BitmapInfoHeader->biClrUsed : BV_MAX_COLORS; InitPaletteWithTable((PULONG)(Buffer + BitmapInfoHeader->biSize), PaletteCount);
/* Make sure we can support this bitmap */ ASSERT((BitmapInfoHeader->biBitCount * BitmapInfoHeader->biPlanes) <= 4);
/* * Calculate the delta and align it on 32-bytes, then calculate * the actual start of the bitmap data. */ Delta = (BitmapInfoHeader->biBitCount * BitmapInfoHeader->biWidth) + 31; Delta >>= 3; Delta &= ~3; BitmapOffset = Buffer + sizeof(BITMAPINFOHEADER) + PaletteCount * sizeof(ULONG);
/* Check the compression of the bitmap */ if (BitmapInfoHeader->biCompression == BI_RLE4) { /* Make sure we have a width and a height */ if ((BitmapInfoHeader->biWidth) && (BitmapInfoHeader->biHeight)) { /* We can use RLE Bit Blt */ RleBitBlt(Left, Top, BitmapInfoHeader->biWidth, BitmapInfoHeader->biHeight, BitmapOffset); } } else { /* Check if the height is negative */ if (BitmapInfoHeader->biHeight < 0) { /* Make it positive in the header */ BitmapInfoHeader->biHeight *= -1; } else { /* Update buffer offset */ BitmapOffset += ((BitmapInfoHeader->biHeight - 1) * Delta); Delta *= -1; }
/* Make sure we have a width and a height */ if ((BitmapInfoHeader->biWidth) && (BitmapInfoHeader->biHeight)) { /* Do the BitBlt */ BitBlt(Left, Top, BitmapInfoHeader->biWidth, BitmapInfoHeader->biHeight, BitmapOffset, BitmapInfoHeader->biBitCount, Delta); } }}