Sync with trunk revision 64099.
[reactos.git] / ntoskrnl / inbv / inbv.c
index 280e918..5526b07 100644 (file)
 KSPIN_LOCK BootDriverLock;
 KIRQL InbvOldIrql;
 INBV_DISPLAY_STATE InbvDisplayState;
-BOOLEAN InbvBootDriverInstalled;
-BOOLEAN InbvDisplayDebugStrings;
+BOOLEAN InbvBootDriverInstalled = FALSE;
+BOOLEAN InbvDisplayDebugStrings = FALSE;
 INBV_DISPLAY_STRING_FILTER InbvDisplayFilter;
 ULONG ProgressBarLeft, ProgressBarTop;
-BOOLEAN ShowProgressBar;
+BOOLEAN ShowProgressBar = FALSE;
 INBV_PROGRESS_STATE InbvProgressState;
 INBV_RESET_DISPLAY_PARAMETERS InbvResetDisplayParameters;
 ULONG ResourceCount;
 PUCHAR ResourceList[64];
-BOOLEAN SysThreadCreated;
+BOOLEAN SysThreadCreated = FALSE;
 ROT_BAR_TYPE RotBarSelection;
 ULONG PltRotBarStatus;
 BT_PROGRESS_INDICATOR InbvProgressIndicator = {0, 25, 0};
 
+/* FADING FUNCTION ***********************************************************/
+
+/** From include/psdk/wingdi.h **/
+typedef struct tagRGBQUAD
+{
+    UCHAR    rgbBlue;
+    UCHAR    rgbGreen;
+    UCHAR    rgbRed;
+    UCHAR    rgbReserved;
+} RGBQUAD,*LPRGBQUAD;
+/*******************************/
+
+static RGBQUAD _MainPalette[16];
+
+#define PALETTE_FADE_STEPS  15
+#define PALETTE_FADE_TIME   20 * 1000 /* 20ms */
+
+/** From bootvid/precomp.h **/
+//
+// Bitmap Header
+//
+typedef struct tagBITMAPINFOHEADER
+{
+    ULONG biSize;
+    LONG biWidth;
+    LONG biHeight;
+    USHORT biPlanes;
+    USHORT biBitCount;
+    ULONG biCompression;
+    ULONG biSizeImage;
+    LONG biXPelsPerMeter;
+    LONG biYPelsPerMeter;
+    ULONG biClrUsed;
+    ULONG biClrImportant;
+} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
+/****************************/
+
+//
+// Needed prototypes
+//
+VOID NTAPI InbvAcquireLock(VOID);
+VOID NTAPI InbvReleaseLock(VOID);
+
+static VOID
+NTAPI
+BootImageFadeIn(VOID)
+{
+    UCHAR PaletteBitmapBuffer[sizeof(BITMAPINFOHEADER) + sizeof(_MainPalette)];
+    PBITMAPINFOHEADER PaletteBitmap = (PBITMAPINFOHEADER)PaletteBitmapBuffer;
+    LPRGBQUAD Palette = (LPRGBQUAD)(PaletteBitmapBuffer + sizeof(BITMAPINFOHEADER));
+
+    ULONG Iteration, Index, ClrUsed;
+
+    /* Check if we're installed and we own it */
+    if ((InbvBootDriverInstalled) &&
+        (InbvDisplayState == INBV_DISPLAY_STATE_OWNED))
+    {
+        /* Acquire the lock */
+        InbvAcquireLock();
+
+        /*
+         * Build a bitmap containing the fade in palette. The palette entries
+         * are then processed in a loop and set using VidBitBlt function.
+         */
+        ClrUsed = sizeof(_MainPalette) / sizeof(_MainPalette[0]);
+        RtlZeroMemory(PaletteBitmap, sizeof(BITMAPINFOHEADER));
+        PaletteBitmap->biSize = sizeof(BITMAPINFOHEADER);
+        PaletteBitmap->biBitCount = 4;
+        PaletteBitmap->biClrUsed = ClrUsed;
+
+        /*
+         * Main animation loop.
+         */
+        for (Iteration = 0; Iteration <= PALETTE_FADE_STEPS; ++Iteration)
+        {
+            for (Index = 0; Index < ClrUsed; Index++)
+            {
+                Palette[Index].rgbRed = (UCHAR)
+                    (_MainPalette[Index].rgbRed * Iteration / PALETTE_FADE_STEPS);
+                Palette[Index].rgbGreen = (UCHAR)
+                    (_MainPalette[Index].rgbGreen * Iteration / PALETTE_FADE_STEPS);
+                Palette[Index].rgbBlue = (UCHAR)
+                    (_MainPalette[Index].rgbBlue * Iteration / PALETTE_FADE_STEPS);
+            }
+
+            VidBitBlt(PaletteBitmapBuffer, 0, 0);
+
+            /* Wait for a bit. */
+            KeStallExecutionProcessor(PALETTE_FADE_TIME);
+        }
+
+        /* Release the lock */
+        InbvReleaseLock();
+
+        /* Wait for a bit. */
+        KeStallExecutionProcessor(PALETTE_FADE_TIME);
+    }
+}
+
 /* FUNCTIONS *****************************************************************/
 
 PVOID
 NTAPI
+INIT_FUNCTION
 FindBitmapResource(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
                    IN ULONG ResourceId)
 {
@@ -92,6 +192,7 @@ FindBitmapResource(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
 
 BOOLEAN
 NTAPI
+INIT_FUNCTION
 InbvDriverInitialize(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
                      IN ULONG Count)
 {
@@ -117,7 +218,7 @@ InbvDriverInitialize(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
     {
         /* Now reset the display, but only if there's a custom boot logo */
         VidResetDisplay(CustomLogo);
-        
+
         /* Find bitmap resources in the kernel */
         ResourceCount = min(IDB_CLUSTER_SERVER, Count);
         for (i = 1; i <= Count; i++)
@@ -174,6 +275,7 @@ InbvReleaseLock(VOID)
 
 VOID
 NTAPI
+INIT_FUNCTION
 InbvEnableBootDriver(IN BOOLEAN Enable)
 {
     /* Check if we're installed */
@@ -261,15 +363,14 @@ InbvDisplayString(IN PCHAR String)
         InbvAcquireLock();
 
         /* Make sure we're installed and display the string */
-        if (InbvBootDriverInstalled) VidDisplayString((PUCHAR) String);
+        if (InbvBootDriverInstalled) VidDisplayString((PUCHAR)String);
 
         /* Print the string on the EMS port */
-               HeadlessDispatch(
-                       HeadlessCmdPutString,
-                       String,
-                       strlen(String) + sizeof(ANSI_NULL),
-                       NULL,
-                       NULL);
+        HeadlessDispatch(HeadlessCmdPutString,
+                         String,
+                         strlen(String) + sizeof(ANSI_NULL),
+                         NULL,
+                         NULL);
 
         /* Release the lock */
         InbvReleaseLock();
@@ -361,11 +462,11 @@ VOID
 NTAPI
 InbvSetScrollRegion(IN ULONG Left,
                     IN ULONG Top,
-                    IN ULONG Width,
-                    IN ULONG Height)
+                    IN ULONG Right,
+                    IN ULONG Bottom)
 {
     /* Just call bootvid */
-    VidSetScrollRegion(Left, Top, Width, Height);
+    VidSetScrollRegion(Left, Top, Right, Bottom);
 }
 
 VOID
@@ -382,8 +483,8 @@ VOID
 NTAPI
 InbvSolidColorFill(IN ULONG Left,
                    IN ULONG Top,
-                   IN ULONG Width,
-                   IN ULONG Height,
+                   IN ULONG Right,
+                   IN ULONG Bottom,
                    IN ULONG Color)
 {
     /* Make sure we own it */
@@ -396,7 +497,7 @@ InbvSolidColorFill(IN ULONG Left,
         if (InbvBootDriverInstalled)
         {
             /* Call bootvid */
-            VidSolidColorFill(Left, Top, Width, Height, (UCHAR)Color);
+            VidSolidColorFill(Left, Top, Right, Bottom, (UCHAR)Color);
         }
 
         /* FIXME: Headless */
@@ -408,6 +509,7 @@ InbvSolidColorFill(IN ULONG Left,
 
 VOID
 NTAPI
+INIT_FUNCTION
 InbvUpdateProgressBar(IN ULONG Progress)
 {
     ULONG FillCount, BoundedProgress;
@@ -523,6 +625,7 @@ InbvSetProgressBarSubset(IN ULONG Floor,
 
 VOID
 NTAPI
+INIT_FUNCTION
 InbvIndicateProgress(VOID)
 {
     ULONG Percentage;
@@ -570,12 +673,19 @@ NtDisplayString(IN PUNICODE_STRING DisplayString)
 
 VOID
 NTAPI
-DisplayBootBitmap(IN BOOLEAN SosMode)
+INIT_FUNCTION
+DisplayBootBitmap(IN BOOLEAN TextMode)
 {
+    PBITMAPINFOHEADER BitmapInfoHeader;
+    LPRGBQUAD Palette;
+
     PVOID Header, Band, Text, Screen;
     ROT_BAR_TYPE TempRotBarSelection = RB_UNSPECIFIED;
+
+#ifdef CORE_6781_resolved
     UCHAR Buffer[64];
-    
+#endif
+
     /* Check if the system thread has already been created */
     if (SysThreadCreated)
     {
@@ -585,9 +695,9 @@ DisplayBootBitmap(IN BOOLEAN SosMode)
         InbvReleaseLock();
     }
 
-    /* Check if this is SOS mode */
+    /* Check if this is text mode */
     ShowProgressBar = FALSE;
-    if (SosMode)
+    if (TextMode)
     {
         /* Check if this is a server OS */
         if (SharedUserData->NtProductType == NtProductWinNt)
@@ -596,7 +706,7 @@ DisplayBootBitmap(IN BOOLEAN SosMode)
             InbvSetTextColor(15);
             InbvSolidColorFill(0, 0, 639, 479, 7);
             InbvSolidColorFill(0, 421, 639, 479, 1);
-            
+
             /* Get resources */
             Header = InbvGetResourceAddress(IDB_LOGO_HEADER);
             Band = InbvGetResourceAddress(IDB_LOGO_BAND);
@@ -655,23 +765,36 @@ DisplayBootBitmap(IN BOOLEAN SosMode)
                 /* Normal edition */
                 Text = InbvGetResourceAddress(IDB_SERVER_LOGO);
             }
-            
+
             /* Server product, display appropriate status bar color */
             InbvGetResourceAddress(IDB_BAR_SERVER);
         }
-        
+
         /* Make sure we had a logo */
         if (Screen)
         {
             /* Choose progress bar */
             TempRotBarSelection = RB_SQUARE_CELLS;
 
+            /*
+             * Save the main image palette and replace it with black palette, so
+             * we can do fade in effect later.
+             */
+            BitmapInfoHeader = (PBITMAPINFOHEADER)Screen;
+            Palette = (LPRGBQUAD)((PUCHAR)Screen + BitmapInfoHeader->biSize);
+            RtlCopyMemory(_MainPalette, Palette, sizeof(_MainPalette));
+            RtlZeroMemory(Palette, sizeof(_MainPalette));
+
             /* Blit the background */
             InbvBitBlt(Screen, 0, 0);
 
             /* Set progress bar coordinates and display it */
             InbvSetProgressBarCoordinates(257, 352);
-            
+
+            /* Display the boot logo and fade it in */
+            BootImageFadeIn();
+
+#ifdef CORE_6781_resolved
             /* Check for non-workstation products */
             if (SharedUserData->NtProductType != NtProductWinNt)
             {
@@ -679,17 +802,25 @@ DisplayBootBitmap(IN BOOLEAN SosMode)
                 InbvScreenToBufferBlt(Buffer, 413, 237, 7, 7, 8);
                 InbvSolidColorFill(418, 230, 454, 256, 0);
                 InbvBufferToScreenBlt(Buffer, 413, 237, 7, 7, 8);
-                
+
                 /* In setup mode, you haven't selected a SKU yet */
                 if (ExpInTextModeSetup) Text = NULL;
             }
-          }
-          
-          /* Draw the SKU text if it exits */
-          if (Text) InbvBitBlt(Text, 180, 121);
-          
-          /* Draw the progress bar bit */
-//          if (Bar) InbvBitBlt(Bar, 0, 0);
+#endif
+        }
+
+#ifdef CORE_6781_resolved
+        /* Draw the SKU text if it exits */
+        if (Text) InbvBitBlt(Text, 180, 121);
+#else
+        DBG_UNREFERENCED_LOCAL_VARIABLE(Text);
+#endif
+
+        /* Draw the progress bar bit */
+//      if (Bar) InbvBitBlt(Bar, 0, 0);
+
+        /* Set filter which will draw text display if needed */
+        InbvInstallDisplayStringFilter(DisplayFilter);
     }
 
     /* Do we have a system thread? */
@@ -705,6 +836,31 @@ DisplayBootBitmap(IN BOOLEAN SosMode)
 
 VOID
 NTAPI
+INIT_FUNCTION
+DisplayFilter(PCHAR *String)
+{
+    /* Windows hack to skip first dots */
+    static BOOLEAN DotHack = TRUE;
+
+    /* If "." is given set *String to empty string */
+    if(DotHack && strcmp(*String, ".") == 0)
+        *String = "";
+
+    if(**String)
+    {
+        /* Remove the filter */
+        InbvInstallDisplayStringFilter(NULL);
+
+        DotHack = FALSE;
+
+        /* Draw text screen */
+        DisplayBootBitmap(TRUE);
+    }
+}
+
+VOID
+NTAPI
+INIT_FUNCTION
 FinalizeBootLogo(VOID)
 {
     /* Acquire lock and check the display state */