[FREELDR:XBOX/UEFI] Separate framebuffer functions with those pertaining to emulated text console (#8530)

- Framebuffer routines that output characters with text-like attributes,
  or return screen sizes in character units (columns/rows), pertain to a
  "framebuffer console" (FbCons) layer.
  Their interface may be extended a bit in the future.

- Add Doxygen documentation for some of them.

- The Xbox/UefiVideo* functions that are similarly character-oriented,
  invoke these framebuffer console routines.
This commit is contained in:
Hermès Bélusca-Maïto
2025-12-21 21:44:57 +01:00
parent 9f69e8cfab
commit 379eb14596
6 changed files with 249 additions and 107 deletions

View File

@@ -36,7 +36,7 @@ XboxConsPutChar(int c)
NeedScroll = (CurrentCursorY >= Height);
if (NeedScroll)
{
VidFbScrollUp(CurrentAttr);
FbConsScrollUp(CurrentAttr);
--CurrentCursorY;
}

View File

@@ -36,13 +36,13 @@ extern multiboot_info_t * MultibootInfoPtr;
VOID
XboxVideoClearScreen(UCHAR Attr)
{
VidFbClearScreen(Attr);
FbConsClearScreen(Attr);
}
VOID
XboxVideoPutChar(int Ch, UCHAR Attr, unsigned X, unsigned Y)
{
VidFbPutChar(Ch, Attr, X, Y);
FbConsPutChar(Ch, Attr, X, Y);
}
static UCHAR
@@ -149,13 +149,13 @@ XboxVideoSetDisplayMode(PCSTR DisplayMode, BOOLEAN Init)
VOID
XboxVideoGetDisplaySize(PULONG Width, PULONG Height, PULONG Depth)
{
VidFbGetDisplaySize(Width, Height, Depth);
FbConsGetDisplaySize(Width, Height, Depth);
}
ULONG
XboxVideoGetBufferSize(VOID)
{
return VidFbGetBufferSize();
return FbConsGetBufferSize();
}
VOID
@@ -179,7 +179,7 @@ XboxVideoHideShowTextCursor(BOOLEAN Show)
VOID
XboxVideoCopyOffScreenBufferToVRAM(PVOID Buffer)
{
VidFbCopyOffScreenBufferToVRAM(Buffer);
FbConsCopyOffScreenBufferToVRAM(Buffer);
}
BOOLEAN

View File

@@ -34,7 +34,7 @@ UefiConsPutChar(int c)
NeedScroll = (CurrentCursorY >= Height);
if (NeedScroll)
{
VidFbScrollUp(CurrentAttr);
FbConsScrollUp(CurrentAttr);
--CurrentCursorY;
}
if (c == '\r')

View File

@@ -73,19 +73,19 @@ UefiInitializeVideo(VOID)
VOID
UefiVideoClearScreen(UCHAR Attr)
{
VidFbClearScreen(Attr);
FbConsClearScreen(Attr);
}
VOID
UefiVideoPutChar(int Ch, UCHAR Attr, unsigned X, unsigned Y)
{
VidFbPutChar(Ch, Attr, X, Y);
FbConsPutChar(Ch, Attr, X, Y);
}
VOID
UefiVideoGetDisplaySize(PULONG Width, PULONG Height, PULONG Depth)
{
VidFbGetDisplaySize(Width, Height, Depth);
FbConsGetDisplaySize(Width, Height, Depth);
}
VIDEODISPLAYMODE
@@ -98,13 +98,13 @@ UefiVideoSetDisplayMode(PCSTR DisplayMode, BOOLEAN Init)
ULONG
UefiVideoGetBufferSize(VOID)
{
return VidFbGetBufferSize();
return FbConsGetBufferSize();
}
VOID
UefiVideoCopyOffScreenBufferToVRAM(PVOID Buffer)
{
VidFbCopyOffScreenBufferToVRAM(Buffer);
FbConsCopyOffScreenBufferToVRAM(Buffer);
}
VOID

View File

@@ -13,8 +13,6 @@
#include <debug.h>
DBG_DEFAULT_CHANNEL(UI);
#define VGA_CHAR_SIZE 2
/* This is used to introduce artificial symmetric borders at the top and bottom */
#define TOP_BOTTOM_LINES 0
@@ -62,7 +60,7 @@ VidFbPrintFramebufferInfo(VOID)
/**
* @brief
* Initializes internal framebuffer data based on the given parameters.
* Initializes internal framebuffer information based on the given parameters.
*
* @param[in] BaseAddress
* The framebuffer physical base address.
@@ -119,30 +117,6 @@ VidFbInitializeVideo(
return TRUE;
}
static inline
UINT32
VidFbAttrToSingleColor(
_In_ UCHAR Attr)
{
UCHAR Intensity;
Intensity = (0 == (Attr & 0x08) ? 127 : 255);
return 0xff000000 |
(0 == (Attr & 0x04) ? 0 : (Intensity << 16)) |
(0 == (Attr & 0x02) ? 0 : (Intensity << 8)) |
(0 == (Attr & 0x01) ? 0 : Intensity);
}
static VOID
VidFbAttrToColors(
_In_ UCHAR Attr,
_Out_ PUINT32 FgColor,
_Out_ PUINT32 BgColor)
{
*FgColor = VidFbAttrToSingleColor(Attr & 0x0F);
*BgColor = VidFbAttrToSingleColor((Attr >> 4) & 0x0F);
}
VOID
VidFbClearScreenColor(
_In_ UINT32 Color,
@@ -161,15 +135,11 @@ VidFbClearScreenColor(
}
}
VOID
VidFbClearScreen(
_In_ UCHAR Attr)
{
UINT32 FgColor, BgColor;
VidFbAttrToColors(Attr, &FgColor, &BgColor);
VidFbClearScreenColor(BgColor, FALSE);
}
/**
* @brief
* Displays a character at a given pixel position with specific foreground
* and background colors.
**/
VOID
VidFbOutputChar(
_In_ UCHAR Char,
@@ -183,9 +153,16 @@ VidFbOutputChar(
UCHAR Mask;
ULONG Line, Col;
/* Don't display outside of the screen, nor partial characters */
if ((X + CHAR_WIDTH >= framebufInfo.ScreenWidth) ||
(Y + CHAR_HEIGHT >= (framebufInfo.ScreenHeight - 2 * TOP_BOTTOM_LINES)))
{
return;
}
FontPtr = BitmapFont8x16 + Char * CHAR_HEIGHT;
Pixel = (PUINT32)((PUCHAR)framebufInfo.BaseAddress +
(Y * CHAR_HEIGHT + TOP_BOTTOM_LINES) * framebufInfo.Delta + X * CHAR_WIDTH * 4);
(Y + TOP_BOTTOM_LINES) * framebufInfo.Delta + X * sizeof(UINT32));
for (Line = 0; Line < CHAR_HEIGHT; Line++)
{
@@ -199,70 +176,48 @@ VidFbOutputChar(
}
}
VOID
VidFbPutChar(
_In_ UCHAR Char,
_In_ UCHAR Attr,
_In_ ULONG X,
_In_ ULONG Y)
{
UINT32 FgColor, BgColor;
VidFbAttrToColors(Attr, &FgColor, &BgColor);
VidFbOutputChar(Char, X, Y, FgColor, BgColor);
}
/**
* @brief
* Returns the width and height in pixels, of the whole visible area
* of the graphics framebuffer.
**/
VOID
VidFbGetDisplaySize(
_Out_ PULONG Width,
_Out_ PULONG Height,
_Out_ PULONG Depth)
{
*Width = framebufInfo.ScreenWidth / CHAR_WIDTH;
*Height = (framebufInfo.ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT;
*Width = framebufInfo.ScreenWidth;
*Height = framebufInfo.ScreenHeight - 2 * TOP_BOTTOM_LINES;
*Depth = framebufInfo.BitsPerPixel;
}
/**
* @brief
* Returns the size in bytes, of a full graphics pixel buffer rectangle
* that can fill the whole visible area of the graphics framebuffer.
**/
ULONG
VidFbGetBufferSize(VOID)
{
return ((framebufInfo.ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT *
(framebufInfo.ScreenWidth / CHAR_WIDTH) * VGA_CHAR_SIZE);
}
VOID
VidFbCopyOffScreenBufferToVRAM(
_In_ PVOID Buffer)
{
PUCHAR OffScreenBuffer = (PUCHAR)Buffer;
ULONG Line, Col;
for (Line = 0; Line < (framebufInfo.ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT; Line++)
{
for (Col = 0; Col < framebufInfo.ScreenWidth / CHAR_WIDTH; Col++)
{
VidFbPutChar(OffScreenBuffer[0], OffScreenBuffer[1], Col, Line);
OffScreenBuffer += VGA_CHAR_SIZE;
}
}
return ((framebufInfo.ScreenHeight - 2 * TOP_BOTTOM_LINES) *
framebufInfo.ScreenWidth * framebufInfo.BytesPerPixel);
}
VOID
VidFbScrollUp(
_In_ UCHAR Attr)
_In_ UINT32 Color,
_In_ ULONG Scroll)
{
UINT32 BgColor, Dummy;
ULONG PixelCount = framebufInfo.ScreenWidth * CHAR_HEIGHT *
(((framebufInfo.ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT) - 1);
PUINT32 Src = (PUINT32)((PUCHAR)framebufInfo.BaseAddress + (CHAR_HEIGHT + TOP_BOTTOM_LINES) * framebufInfo.Delta);
PUINT32 Dst = (PUINT32)((PUCHAR)framebufInfo.BaseAddress + TOP_BOTTOM_LINES * framebufInfo.Delta);
VidFbAttrToColors(Attr, &Dummy, &BgColor);
PUINT32 Src = (PUINT32)((PUCHAR)framebufInfo.BaseAddress + (TOP_BOTTOM_LINES + Scroll) * framebufInfo.Delta);
ULONG PixelCount = framebufInfo.ScreenWidth * ((framebufInfo.ScreenHeight - 2 * TOP_BOTTOM_LINES) - Scroll);
while (PixelCount--)
*Dst++ = *Src++;
for (PixelCount = 0; PixelCount < framebufInfo.ScreenWidth * CHAR_HEIGHT; PixelCount++)
*Dst++ = BgColor;
for (PixelCount = 0; PixelCount < framebufInfo.ScreenWidth * Scroll; PixelCount++)
*Dst++ = Color;
}
#if 0
@@ -300,3 +255,156 @@ VidFbGetPaletteColor(
/* Not supported */
}
#endif
/*
* PROJECT: FreeLoader
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* or MIT (https://spdx.org/licenses/MIT)
* PURPOSE: Linear framebuffer based console support
* COPYRIGHT: Copyright 2025 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
*/
#define VGA_CHAR_SIZE 2
#define FBCONS_WIDTH (framebufInfo.ScreenWidth / CHAR_WIDTH)
#define FBCONS_HEIGHT ((framebufInfo.ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT)
static inline
UINT32
FbConsAttrToSingleColor(
_In_ UCHAR Attr)
{
UCHAR Intensity;
Intensity = (0 == (Attr & 0x08) ? 127 : 255);
return 0xff000000 |
(0 == (Attr & 0x04) ? 0 : (Intensity << 16)) |
(0 == (Attr & 0x02) ? 0 : (Intensity << 8)) |
(0 == (Attr & 0x01) ? 0 : Intensity);
}
/**
* @brief
* Maps a text-mode CGA-style character attribute to separate
* foreground and background ARGB colors.
**/
static VOID
FbConsAttrToColors(
_In_ UCHAR Attr,
_Out_ PUINT32 FgColor,
_Out_ PUINT32 BgColor)
{
*FgColor = FbConsAttrToSingleColor(Attr & 0x0F);
*BgColor = FbConsAttrToSingleColor((Attr >> 4) & 0x0F);
}
VOID
FbConsClearScreen(
_In_ UCHAR Attr)
{
UINT32 FgColor, BgColor;
FbConsAttrToColors(Attr, &FgColor, &BgColor);
VidFbClearScreenColor(BgColor, FALSE);
}
/**
* @brief
* Displays a character at a given position with specific foreground
* and background colors.
**/
VOID
FbConsOutputChar(
_In_ UCHAR Char,
_In_ ULONG Column,
_In_ ULONG Row,
_In_ UINT32 FgColor,
_In_ UINT32 BgColor)
{
/* Don't display outside of the screen */
if ((Column >= FBCONS_WIDTH) || (Row >= FBCONS_HEIGHT))
return;
VidFbOutputChar(Char, Column * CHAR_WIDTH, Row * CHAR_HEIGHT, FgColor, BgColor);
}
/**
* @brief
* Displays a character with specific text attributes at a given position.
**/
VOID
FbConsPutChar(
_In_ UCHAR Char,
_In_ UCHAR Attr,
_In_ ULONG Column,
_In_ ULONG Row)
{
UINT32 FgColor, BgColor;
FbConsAttrToColors(Attr, &FgColor, &BgColor);
FbConsOutputChar(Char, Column, Row, FgColor, BgColor);
}
/**
* @brief
* Returns the width and height in number of CGA characters/attributes, of a
* full text-mode CGA-style character buffer rectangle that can fill the whole console.
**/
VOID
FbConsGetDisplaySize(
_Out_ PULONG Width,
_Out_ PULONG Height,
_Out_ PULONG Depth)
{
// VidFbGetDisplaySize(Width, Height, Depth);
// *Width /= CHAR_WIDTH;
// *Height /= CHAR_HEIGHT;
*Width = FBCONS_WIDTH;
*Height = FBCONS_HEIGHT;
*Depth = framebufInfo.BitsPerPixel;
}
/**
* @brief
* Returns the size in bytes, of a full text-mode CGA-style
* character buffer rectangle that can fill the whole console.
**/
ULONG
FbConsGetBufferSize(VOID)
{
return (FBCONS_HEIGHT * FBCONS_WIDTH * VGA_CHAR_SIZE);
}
/**
* @brief
* Copies a full text-mode CGA-style character buffer rectangle to the console.
**/
// TODO: Write a VidFb "BitBlt" equivalent.
VOID
FbConsCopyOffScreenBufferToVRAM(
_In_ PVOID Buffer)
{
PUCHAR OffScreenBuffer = (PUCHAR)Buffer;
ULONG Row, Col;
// ULONG Width, Height, Depth;
// FbConsGetDisplaySize(&Width, &Height, &Depth);
ULONG Width = FBCONS_WIDTH, Height = FBCONS_HEIGHT;
for (Row = 0; Row < Height; ++Row)
{
for (Col = 0; Col < Width; ++Col)
{
FbConsPutChar(OffScreenBuffer[0], OffScreenBuffer[1], Col, Row);
OffScreenBuffer += VGA_CHAR_SIZE;
}
}
}
VOID
FbConsScrollUp(
_In_ UCHAR Attr)
{
UINT32 BgColor, Dummy;
FbConsAttrToColors(Attr, &Dummy, &BgColor);
VidFbScrollUp(BgColor, CHAR_HEIGHT);
}

View File

@@ -21,10 +21,6 @@ VidFbClearScreenColor(
_In_ UINT32 Color,
_In_ BOOLEAN FullScreen);
VOID
VidFbClearScreen(
_In_ UCHAR Attr);
VOID
VidFbOutputChar(
_In_ UCHAR Char,
@@ -33,13 +29,6 @@ VidFbOutputChar(
_In_ UINT32 FgColor,
_In_ UINT32 BgColor);
VOID
VidFbPutChar(
_In_ UCHAR Char,
_In_ UCHAR Attr,
_In_ ULONG X,
_In_ ULONG Y);
VOID
VidFbGetDisplaySize(
_Out_ PULONG Width,
@@ -49,13 +38,10 @@ VidFbGetDisplaySize(
ULONG
VidFbGetBufferSize(VOID);
VOID
VidFbCopyOffScreenBufferToVRAM(
_In_ PVOID Buffer);
VOID
VidFbScrollUp(
_In_ UCHAR Attr);
_In_ UINT32 Color,
_In_ ULONG Scroll);
#if 0
VOID
@@ -77,3 +63,51 @@ VidFbGetPaletteColor(
_In_ UCHAR Color,
_Out_ PUCHAR Red, _Out_ PUCHAR Green, _Out_ PUCHAR Blue);
#endif
/*
* PROJECT: FreeLoader
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* or MIT (https://spdx.org/licenses/MIT)
* PURPOSE: Linear framebuffer based console support
* COPYRIGHT: Copyright 2025 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
*/
#pragma once
VOID
FbConsClearScreen(
_In_ UCHAR Attr);
VOID
FbConsOutputChar(
_In_ UCHAR Char,
_In_ ULONG Column,
_In_ ULONG Row,
_In_ UINT32 FgColor,
_In_ UINT32 BgColor);
VOID
FbConsPutChar(
_In_ UCHAR Char,
_In_ UCHAR Attr,
_In_ ULONG Column,
_In_ ULONG Row);
VOID
FbConsGetDisplaySize(
_Out_ PULONG Width,
_Out_ PULONG Height,
_Out_ PULONG Depth);
ULONG
FbConsGetBufferSize(VOID);
VOID
FbConsCopyOffScreenBufferToVRAM(
_In_ PVOID Buffer);
VOID
FbConsScrollUp(
_In_ UCHAR Attr);