mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 09:25:10 +00:00
462 lines
11 KiB
C
462 lines
11 KiB
C
/*
|
|
* COPYRIGHT: See COPYING.ARM in the top level directory
|
|
* PROJECT: ReactOS UEFI Boot Library
|
|
* FILE: boot/environ/lib/io/display/guicons.c
|
|
* PURPOSE: Boot Library GUI Console Routines
|
|
* PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
|
|
*/
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
#include "bl.h"
|
|
|
|
/* DATA VARIABLES ************************************************************/
|
|
|
|
BL_GRAPHICS_CONSOLE_VTABLE ConsoleGraphicalVtbl =
|
|
{
|
|
{
|
|
(PCONSOLE_DESTRUCT)ConsoleGraphicalDestruct,
|
|
(PCONSOLE_REINITIALIZE)ConsoleGraphicalReinitialize,
|
|
ConsoleTextBaseGetTextState,
|
|
(PCONSOLE_SET_TEXT_STATE)ConsoleGraphicalSetTextState,
|
|
NULL, // GetTextResolution
|
|
NULL, // SetTextResolution
|
|
(PCONSOLE_CLEAR_TEXT)ConsoleGraphicalClearText
|
|
},
|
|
ConsoleGraphicalIsEnabled,
|
|
ConsoleGraphicalEnable,
|
|
NULL,
|
|
ConsoleGraphicalGetGraphicalResolution,
|
|
ConsoleGraphicalGetOriginalResolution,
|
|
NULL,
|
|
};
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
NTSTATUS
|
|
ConsoleGraphicalSetTextState (
|
|
_In_ PBL_GRAPHICS_CONSOLE Console,
|
|
_In_ ULONG Mask,
|
|
_In_ PBL_DISPLAY_STATE TextState
|
|
)
|
|
{
|
|
/* Is the text console active? */
|
|
if (Console->TextConsole.Active)
|
|
{
|
|
/* Let it handle that */
|
|
return ConsoleFirmwareTextSetState(&Console->TextConsole,
|
|
Mask,
|
|
TextState);
|
|
}
|
|
|
|
/* Not yet */
|
|
EfiPrintf(L"FFX set not implemented\r\n");
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NTSTATUS
|
|
ConsoleGraphicalConstruct (
|
|
_In_ PBL_GRAPHICS_CONSOLE GraphicsConsole
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
/* Create a text console */
|
|
Status = ConsoleTextLocalConstruct(&GraphicsConsole->TextConsole, FALSE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
EfiPrintf(L"Text failed: %lx\r\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
/* But overwrite its callbacks with ours */
|
|
GraphicsConsole->TextConsole.Callbacks = &ConsoleGraphicalVtbl.Text;
|
|
|
|
/* Try to create a GOP console */
|
|
Status = ConsoleEfiGraphicalOpenProtocol(GraphicsConsole, BlGopConsole);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* That failed, try an older EFI 1.02 UGA console */
|
|
EfiPrintf(L"GOP open failed!\r\n", Status);
|
|
Status = ConsoleEfiGraphicalOpenProtocol(GraphicsConsole, BlUgaConsole);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* That failed too, give up */
|
|
EfiPrintf(L"UGA failed!\r\n", Status);
|
|
ConsoleTextLocalDestruct(&GraphicsConsole->TextConsole);
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
/* Enable the console */
|
|
Status = ConsoleFirmwareGraphicalEnable(GraphicsConsole);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* Failed to enable it, undo everything */
|
|
EfiPrintf(L"Enable failed\r\n");
|
|
ConsoleFirmwareGraphicalClose(GraphicsConsole);
|
|
ConsoleTextLocalDestruct(&GraphicsConsole->TextConsole);
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
/* Save the graphics text color from the text mode text color */
|
|
GraphicsConsole->FgColor = GraphicsConsole->TextConsole.State.FgColor;
|
|
GraphicsConsole->BgColor = GraphicsConsole->TextConsole.State.BgColor;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
ConsolepClearBuffer (
|
|
_In_ PUCHAR FrameBuffer,
|
|
_In_ ULONG Width,
|
|
_In_ PUCHAR FillColor,
|
|
_In_ ULONG Height,
|
|
_In_ ULONG ScanlineWidth,
|
|
_In_ ULONG PixelDepth
|
|
)
|
|
{
|
|
PUCHAR Scanline, Current, FrameBufferEnd, LineEnd;
|
|
ULONG LineBytes, WidthBytes, BytesPerPixel;
|
|
|
|
/* Get the BPP */
|
|
BytesPerPixel = PixelDepth / 8;
|
|
|
|
/* Using that, calculate the size of a scan line */
|
|
LineBytes = ScanlineWidth * BytesPerPixel;
|
|
|
|
/* And the size of line we'll have to clear */
|
|
WidthBytes = Width * BytesPerPixel;
|
|
|
|
/* Allocate a scanline */
|
|
Scanline = BlMmAllocateHeap(WidthBytes);
|
|
if (Scanline)
|
|
{
|
|
/* For each remaining pixel on the scanline */
|
|
Current = Scanline;
|
|
while (Width--)
|
|
{
|
|
/* Copy in the fill color */
|
|
RtlCopyMemory(Current, FillColor, BytesPerPixel);
|
|
Current += BytesPerPixel;
|
|
}
|
|
|
|
/* For each scanline in the frame buffer */
|
|
while (Height--)
|
|
{
|
|
/* Copy our constructed scanline */
|
|
RtlCopyMemory(FrameBuffer, Scanline, WidthBytes);
|
|
FrameBuffer += LineBytes;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FrameBufferEnd = FrameBuffer + Height * LineBytes;
|
|
ScanlineWidth = BytesPerPixel * (ScanlineWidth - Width);
|
|
while (FrameBuffer != FrameBufferEnd)
|
|
{
|
|
if (FrameBuffer != (FrameBuffer + WidthBytes))
|
|
{
|
|
LineEnd = FrameBuffer + WidthBytes;
|
|
do
|
|
{
|
|
RtlCopyMemory(FrameBuffer, FillColor, BytesPerPixel);
|
|
FrameBuffer += BytesPerPixel;
|
|
}
|
|
while (FrameBuffer != LineEnd);
|
|
}
|
|
|
|
FrameBuffer += ScanlineWidth;
|
|
}
|
|
}
|
|
}
|
|
|
|
NTSTATUS
|
|
ConsolepConvertColorToPixel (
|
|
_In_ BL_COLOR Color,
|
|
_Out_ PUCHAR Pixel
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
/* Assume success */
|
|
Status = STATUS_SUCCESS;
|
|
|
|
/* Convert the color to a pixel value */
|
|
switch (Color)
|
|
{
|
|
case Black:
|
|
Pixel[1] = 0;
|
|
Pixel[2] = 0;
|
|
Pixel[0] = 0;
|
|
break;
|
|
case Blue:
|
|
Pixel[1] = 0;
|
|
Pixel[2] = 0;
|
|
Pixel[0] = 0x7F;
|
|
break;
|
|
case Green:
|
|
Pixel[1] = 0x7F;
|
|
Pixel[2] = 0;
|
|
Pixel[0] = 0;
|
|
break;
|
|
case Cyan:
|
|
Pixel[1] = 0x7F;
|
|
Pixel[2] = 0;
|
|
Pixel[0] = 0x7F;
|
|
break;
|
|
case Red:
|
|
Pixel[1] = 0;
|
|
Pixel[2] = 0x7F;
|
|
Pixel[0] = 0x7F;
|
|
break;
|
|
case Magenta:
|
|
Pixel[1] = 0;
|
|
Pixel[2] = 0x7F;
|
|
Pixel[0] = 0x7F;
|
|
break;
|
|
case Brown:
|
|
Pixel[1] = 0x3F;
|
|
Pixel[2] = 0x7F;
|
|
Pixel[0] = 0;
|
|
break;
|
|
case LtGray:
|
|
Pixel[1] = 0xBFu;
|
|
Pixel[2] = 0xBFu;
|
|
*Pixel = 0xBFu;
|
|
break;
|
|
case Gray:
|
|
Pixel[1] = 0x7F;
|
|
Pixel[2] = 0x7F;
|
|
Pixel[0] = 0x7F;
|
|
break;
|
|
case LtBlue:
|
|
Pixel[1] = 0;
|
|
Pixel[2] = 0;
|
|
Pixel[0] = 0xFF;
|
|
break;
|
|
case LtGreen:
|
|
Pixel[1] = 0xFF;
|
|
Pixel[2] = 0;
|
|
Pixel[0] = 0;
|
|
break;
|
|
case LtCyan:
|
|
Pixel[1] = 0xFF;
|
|
Pixel[2] = 0;
|
|
Pixel[0] = 0xFF;
|
|
break;
|
|
case LtRed:
|
|
Pixel[1] = 0;
|
|
Pixel[2] = 0xFF;
|
|
Pixel[0] = 0;
|
|
break;
|
|
case LtMagenta:
|
|
Pixel[1] = 0;
|
|
Pixel[2] = 0xFF;
|
|
Pixel[0] = 0xFF;
|
|
break;
|
|
case Yellow:
|
|
Pixel[1] = 0xFF;
|
|
Pixel[2] = 0xFF;
|
|
Pixel[0] = 0;
|
|
break;
|
|
case White:
|
|
Pixel[1] = 0xFF;
|
|
Pixel[2] = 0xFF;
|
|
Pixel[0] = 0xFF;
|
|
break;
|
|
default:
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
ConsoleGraphicalClearPixels (
|
|
_In_ PBL_GRAPHICS_CONSOLE Console,
|
|
_In_ ULONG Color
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
/* Check if the text console is active */
|
|
if (Console->TextConsole.Active)
|
|
{
|
|
/* We shouldn't be here */
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
else
|
|
{
|
|
/* Clear it in graphics mode */
|
|
Status = ConsoleFirmwareGraphicalClear(Console, Color);
|
|
}
|
|
|
|
/* All good */
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
ConsoleGraphicalClearText (
|
|
_In_ PBL_GRAPHICS_CONSOLE Console,
|
|
_In_ BOOLEAN LineOnly
|
|
)
|
|
{
|
|
/* Is the text console active? */
|
|
if (Console->TextConsole.Active)
|
|
{
|
|
/* Let firmware clear do it */
|
|
return ConsoleFirmwareTextClear(&Console->TextConsole, LineOnly);
|
|
}
|
|
|
|
/* Are we clearing a line only? */
|
|
if (LineOnly)
|
|
{
|
|
return BfClearToEndOfLine(Console);
|
|
}
|
|
|
|
/* Nope -- the whole screen */
|
|
return BfClearScreen(Console);
|
|
}
|
|
|
|
BOOLEAN
|
|
ConsoleGraphicalIsEnabled (
|
|
_In_ PBL_GRAPHICS_CONSOLE Console
|
|
)
|
|
{
|
|
/* Is the text console active? If so, the graphics console isn't */
|
|
return !Console->TextConsole.Active;
|
|
}
|
|
|
|
VOID
|
|
ConsoleGraphicalDestruct (
|
|
_In_ PBL_GRAPHICS_CONSOLE Console
|
|
)
|
|
{
|
|
/* Is the text console active? */
|
|
if (Console->TextConsole.Active)
|
|
{
|
|
/* Disable it */
|
|
ConsoleFirmwareGraphicalDisable(Console);
|
|
}
|
|
|
|
/* Close the firmware protocols */
|
|
ConsoleFirmwareGraphicalClose(Console);
|
|
|
|
/* Destroy the console object */
|
|
ConsoleTextLocalDestruct(&Console->TextConsole);
|
|
}
|
|
|
|
NTSTATUS
|
|
ConsoleGraphicalReinitialize (
|
|
_In_ PBL_GRAPHICS_CONSOLE Console
|
|
)
|
|
{
|
|
/* Is the text console active? */
|
|
if (Console->TextConsole.Active)
|
|
{
|
|
/* Reinitialize it */
|
|
ConsoleTextLocalReinitialize(&Console->TextConsole);
|
|
}
|
|
|
|
/* Disable the graphics console */
|
|
ConsoleFirmwareGraphicalDisable(Console);
|
|
|
|
/* Then bring it back again */
|
|
return ConsoleFirmwareGraphicalEnable(Console);
|
|
}
|
|
|
|
NTSTATUS
|
|
ConsoleGraphicalEnable (
|
|
_In_ PBL_GRAPHICS_CONSOLE Console,
|
|
_In_ BOOLEAN Enable
|
|
)
|
|
{
|
|
BOOLEAN Active;
|
|
NTSTATUS Status;
|
|
|
|
/* The text mode console state should be the opposite of what we want to do */
|
|
Active = Console->TextConsole.Active;
|
|
if (Active == Enable)
|
|
{
|
|
/* Are we trying to enable graphics? */
|
|
if (Enable)
|
|
{
|
|
/* Enable the console */
|
|
Status = ConsoleFirmwareGraphicalEnable(Console);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
/* Is the text console active? */
|
|
if (Console->TextConsole.Active)
|
|
{
|
|
/* Turn it off */
|
|
ConsoleFirmwareTextClose(&Console->TextConsole);
|
|
Console->TextConsole.Active = FALSE;
|
|
}
|
|
|
|
/* Preserve the text colors */
|
|
Console->FgColor = Console->TextConsole.State.FgColor;
|
|
Console->BgColor = Console->TextConsole.State.BgColor;
|
|
}
|
|
else
|
|
{
|
|
/* We are turning off graphics -- is the text console active? */
|
|
if (Active != TRUE)
|
|
{
|
|
/* It isn't, so let's turn it on */
|
|
Status = ConsoleFirmwareTextOpen(&Console->TextConsole);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
/* Remember that it's on */
|
|
Console->TextConsole.Active = TRUE;
|
|
}
|
|
|
|
/* Disable the graphics console */
|
|
ConsoleFirmwareGraphicalDisable(Console);
|
|
}
|
|
}
|
|
|
|
/* All good */
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
ConsoleGraphicalGetGraphicalResolution (
|
|
_In_ PBL_GRAPHICS_CONSOLE Console,
|
|
_In_ PBL_DISPLAY_MODE DisplayMode
|
|
)
|
|
{
|
|
/* Is the text console active? */
|
|
if (Console->TextConsole.Active)
|
|
{
|
|
/* There's no graphics resolution then */
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
/* Return the current display mode */
|
|
*DisplayMode = Console->DisplayMode;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
ConsoleGraphicalGetOriginalResolution (
|
|
_In_ PBL_GRAPHICS_CONSOLE Console,
|
|
_In_ PBL_DISPLAY_MODE DisplayMode
|
|
)
|
|
{
|
|
/* Is the text console active? */
|
|
if (Console->TextConsole.Active)
|
|
{
|
|
/* There's no graphics resolution then */
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
/* Return the current display mode */
|
|
*DisplayMode = Console->OldDisplayMode;
|
|
return STATUS_SUCCESS;
|
|
}
|