mirror of
https://github.com/reactos/reactos.git
synced 2026-05-30 14:34:57 +08:00
[FREELDR:XBOX/UEFI] vidfb: stub-plement pixel bitmasks support (#8531)
This is the starting point where both support for generic framebuffer video driver support (in bootvid and win32k) for XBOX, UEFI etc., and in FreeLoader itself also for PC VESA, begins.
This commit is contained in:
@@ -134,7 +134,8 @@ XboxVideoInit(VOID)
|
||||
ScreenWidth,
|
||||
ScreenHeight,
|
||||
ScreenWidth, // PixelsPerScanLine
|
||||
BytesPerPixel * 8);
|
||||
BytesPerPixel * 8,
|
||||
NULL);
|
||||
|
||||
VidFbClearScreenColor(MAKE_COLOR(0, 0, 0), TRUE);
|
||||
}
|
||||
|
||||
39
boot/freeldr/freeldr/arch/twidbits.h
Normal file
39
boot/freeldr/freeldr/arch/twidbits.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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: Bit twiddling helpers
|
||||
* COPYRIGHT: Copyright 2025 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
|
||||
*
|
||||
* Based on http://www.graphics.stanford.edu/~seander/bithacks.html
|
||||
* and other sources.
|
||||
*/
|
||||
|
||||
// HAVE___BUILTIN_POPCOUNT
|
||||
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* @brief Return the number of bits set in a 32-bit integer.
|
||||
* @note Equivalent to __popcnt().
|
||||
**/
|
||||
FORCEINLINE
|
||||
ULONG
|
||||
CountNumberOfBits(
|
||||
_In_ UINT32 n)
|
||||
{
|
||||
#ifdef HAVE___BUILTIN_POPCOUNT
|
||||
return __popcnt(n);
|
||||
#else
|
||||
n -= ((n >> 1) & 0x55555555);
|
||||
n = (((n >> 2) & 0x33333333) + (n & 0x33333333));
|
||||
#if 0
|
||||
n = (((n >> 4) + n) & 0x0f0f0f0f);
|
||||
n += (n >> 8);
|
||||
n += (n >> 16);
|
||||
return (n & 0x3f);
|
||||
#else
|
||||
return (((n >> 4) + n) & 0x0f0f0f0f) * 0x01010101 >> 24;
|
||||
#endif
|
||||
#endif /* HAVE___BUILTIN_POPCOUNT */
|
||||
}
|
||||
@@ -21,10 +21,38 @@ EFI_GUID EfiGraphicsOutputProtocol = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
/* EFI 1.x */
|
||||
#ifdef EFI_UGA_DRAW_PROTOCOL_GUID
|
||||
|
||||
/* NOTE: EFI UGA does not support any other format than 32-bit xRGB, and
|
||||
* no direct access to the underlying hardware framebuffer is offered */
|
||||
C_ASSERT(sizeof(EFI_UGA_PIXEL) == sizeof(ULONG));
|
||||
|
||||
#endif /* EFI */
|
||||
|
||||
/* UEFI support, see efi/GraphicsOutput.h */
|
||||
#ifdef EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID // __GRAPHICS_OUTPUT_H__
|
||||
|
||||
C_ASSERT(sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) == sizeof(ULONG));
|
||||
|
||||
/**
|
||||
* @brief Maps UEFI GOP pixel format to pixel masks.
|
||||
* @see EFI_PIXEL_BITMASK
|
||||
**/
|
||||
static EFI_PIXEL_BITMASK EfiPixelMasks[] =
|
||||
{ /* Red, Green, Blue, Reserved */
|
||||
{0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000}, // PixelRedGreenBlueReserved8BitPerColor
|
||||
{0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000}, // PixelBlueGreenRedReserved8BitPerColor
|
||||
{0, 0, 0, 0} // PixelBitMask, PixelBltOnly, ...
|
||||
};
|
||||
|
||||
#endif /* UEFI */
|
||||
|
||||
EFI_STATUS
|
||||
UefiInitializeVideo(VOID)
|
||||
{
|
||||
EFI_GRAPHICS_PIXEL_FORMAT PixelFormat;
|
||||
EFI_PIXEL_BITMASK* pPixelBitmask;
|
||||
ULONG BitsPerPixel;
|
||||
|
||||
EFI_STATUS Status;
|
||||
@@ -47,15 +75,33 @@ UefiInitializeVideo(VOID)
|
||||
case PixelRedGreenBlueReserved8BitPerColor:
|
||||
case PixelBlueGreenRedReserved8BitPerColor:
|
||||
{
|
||||
pPixelBitmask = &EfiPixelMasks[PixelFormat];
|
||||
BitsPerPixel = RTL_BITS_OF(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
||||
break;
|
||||
}
|
||||
|
||||
case PixelBitMask:
|
||||
{
|
||||
/*
|
||||
* When the GOP pixel format is given by PixelBitMask, the pixel
|
||||
* element size _may be_ different from 4 bytes.
|
||||
* See UEFI Spec Rev.2.10 Section 12.9 "Graphics Output Protocol":
|
||||
* example code "GetPixelElementSize()" function.
|
||||
*/
|
||||
pPixelBitmask = &gop->Mode->Info->PixelInformation;
|
||||
BitsPerPixel =
|
||||
PixelBitmasksToBpp(pPixelBitmask->RedMask,
|
||||
pPixelBitmask->GreenMask,
|
||||
pPixelBitmask->BlueMask,
|
||||
pPixelBitmask->ReservedMask);
|
||||
break;
|
||||
}
|
||||
|
||||
case PixelBltOnly:
|
||||
default:
|
||||
{
|
||||
ERR("Unsupported UFEI GOP format %lu\n", PixelFormat);
|
||||
pPixelBitmask = NULL;
|
||||
BitsPerPixel = 0;
|
||||
break;
|
||||
}
|
||||
@@ -66,7 +112,8 @@ UefiInitializeVideo(VOID)
|
||||
gop->Mode->Info->HorizontalResolution,
|
||||
gop->Mode->Info->VerticalResolution,
|
||||
gop->Mode->Info->PixelsPerScanLine,
|
||||
BitsPerPixel);
|
||||
BitsPerPixel,
|
||||
(PPIXEL_BITMASK)pPixelBitmask);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,9 @@ typedef struct _FRAMEBUFFER_INFO
|
||||
ULONG PixelsPerScanLine; // aka. "Pitch" or "ScreenStride", but Stride is in bytes or bits...
|
||||
ULONG BitsPerPixel; // aka. "PixelStride".
|
||||
|
||||
/* Physical format of the pixel for BPP > 8, specified by bit-mask */
|
||||
PIXEL_BITMASK PixelMasks;
|
||||
|
||||
/** Calculated values */
|
||||
|
||||
ULONG BytesPerPixel;
|
||||
@@ -55,6 +58,11 @@ VidFbPrintFramebufferInfo(VOID)
|
||||
TRACE(" BitsPerPixel : %lu\n", framebufInfo.BitsPerPixel);
|
||||
TRACE(" BytesPerPixel : %lu\n", framebufInfo.BytesPerPixel);
|
||||
TRACE(" Delta : %lu\n", framebufInfo.Delta);
|
||||
TRACE(" ARGB masks: : %08x/%08x/%08x/%08x\n",
|
||||
framebufInfo.PixelMasks.ReservedMask,
|
||||
framebufInfo.PixelMasks.RedMask,
|
||||
framebufInfo.PixelMasks.GreenMask,
|
||||
framebufInfo.PixelMasks.BlueMask);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -78,6 +86,10 @@ VidFbPrintFramebufferInfo(VOID)
|
||||
* @param[in] BitsPerPixel
|
||||
* The number of usable bits (not counting the reserved ones) per pixel.
|
||||
*
|
||||
* @param[in] PixelMasks
|
||||
* Optional pointer to a PIXEL_BITMASK structure describing the pixel
|
||||
* format used by the framebuffer.
|
||||
*
|
||||
* @return
|
||||
* TRUE if initialization is successful; FALSE if not.
|
||||
**/
|
||||
@@ -88,8 +100,11 @@ VidFbInitializeVideo(
|
||||
_In_ UINT32 ScreenWidth,
|
||||
_In_ UINT32 ScreenHeight,
|
||||
_In_ UINT32 PixelsPerScanLine,
|
||||
_In_ UINT32 BitsPerPixel)
|
||||
_In_ UINT32 BitsPerPixel,
|
||||
_In_opt_ PPIXEL_BITMASK PixelMasks)
|
||||
{
|
||||
PPIXEL_BITMASK BitMasks = &framebufInfo.PixelMasks;
|
||||
|
||||
RtlZeroMemory(&framebufInfo, sizeof(framebufInfo));
|
||||
|
||||
framebufInfo.BaseAddress = BaseAddress;
|
||||
@@ -110,8 +125,66 @@ VidFbInitializeVideo(
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//ASSERT((BitsPerPixel <= 8 && !PixelMasks) || (BitsPerPixel > 8));
|
||||
if (BitsPerPixel > 8)
|
||||
{
|
||||
if (!PixelMasks ||
|
||||
(PixelMasks->RedMask == 0 &&
|
||||
PixelMasks->GreenMask == 0 &&
|
||||
PixelMasks->BlueMask == 0 /* &&
|
||||
PixelMasks->ReservedMask == 0 */))
|
||||
{
|
||||
/* Determine pixel mask given color depth and color channel */
|
||||
switch (BitsPerPixel)
|
||||
{
|
||||
case 32:
|
||||
case 24: /* 8:8:8 */
|
||||
BitMasks->RedMask = 0x00FF0000; // 0x00FF0000;
|
||||
BitMasks->GreenMask = 0x0000FF00; // 0x00FF0000 >> 8;
|
||||
BitMasks->BlueMask = 0x000000FF; // 0x00FF0000 >> 16;
|
||||
BitMasks->ReservedMask = ((1 << (BitsPerPixel - 24)) - 1) << 24;
|
||||
break;
|
||||
case 16: /* 5:6:5 */
|
||||
BitMasks->RedMask = 0xF800; // 0xF800;
|
||||
BitMasks->GreenMask = 0x07E0; // (0xF800 >> 5) | 0x20;
|
||||
BitMasks->BlueMask = 0x001F; // 0xF800 >> 11;
|
||||
BitMasks->ReservedMask = 0;
|
||||
break;
|
||||
case 15: /* 5:5:5 */
|
||||
BitMasks->RedMask = 0x7C00; // 0x7C00;
|
||||
BitMasks->GreenMask = 0x03E0; // 0x7C00 >> 5;
|
||||
BitMasks->BlueMask = 0x001F; // 0x7C00 >> 10;
|
||||
BitMasks->ReservedMask = 0x8000;
|
||||
break;
|
||||
default:
|
||||
/* Unsupported BPP */
|
||||
UNIMPLEMENTED;
|
||||
RtlZeroMemory(BitMasks, sizeof(*BitMasks));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Copy the pixel masks */
|
||||
RtlCopyMemory(BitMasks, PixelMasks, sizeof(*BitMasks));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Palettized modes don't use masks */
|
||||
RtlZeroMemory(BitMasks, sizeof(*BitMasks));
|
||||
}
|
||||
|
||||
#if DBG
|
||||
VidFbPrintFramebufferInfo();
|
||||
{
|
||||
ULONG BppFromMasks =
|
||||
PixelBitmasksToBpp(BitMasks->RedMask,
|
||||
BitMasks->GreenMask,
|
||||
BitMasks->BlueMask,
|
||||
BitMasks->ReservedMask);
|
||||
TRACE("BitsPerPixel = %lu , BppFromMasks = %lu\n", BitsPerPixel, BppFromMasks);
|
||||
//ASSERT(BitsPerPixel == BppFromMasks);
|
||||
}
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
|
||||
@@ -7,6 +7,49 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "twidbits.h"
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Physical format of an RGB pixel, specified with per-component bit-masks.
|
||||
* A bit being set defines those used for the given color component, such
|
||||
* as Red, Green, Blue, or Reserved.
|
||||
*
|
||||
* @note
|
||||
* Supports up to 32 bits-per-pixel deep pixels.
|
||||
**/
|
||||
typedef struct _PIXEL_BITMASK
|
||||
{
|
||||
ULONG RedMask;
|
||||
ULONG GreenMask;
|
||||
ULONG BlueMask;
|
||||
ULONG ReservedMask;
|
||||
} PIXEL_BITMASK, *PPIXEL_BITMASK;
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Calculates the number of bits per pixel ("PixelDepth") for
|
||||
* the given pixel format, given by the pixel color masks.
|
||||
*
|
||||
* @remark
|
||||
* See UEFI Spec Rev.2.10 Section 12.9 "Graphics Output Protocol":
|
||||
* example code "GetPixelElementSize()" function.
|
||||
**/
|
||||
FORCEINLINE
|
||||
ULONG
|
||||
PixelBitmasksToBpp(
|
||||
_In_ ULONG RedMask,
|
||||
_In_ ULONG GreenMask,
|
||||
_In_ ULONG BlueMask,
|
||||
_In_ ULONG ReservedMask)
|
||||
{
|
||||
ULONG CompoundMask = (RedMask | GreenMask | BlueMask | ReservedMask);
|
||||
/* Alternatively, the calculation could be done by finding the highest
|
||||
* bit set in the combined pixel color masks, if they are packed together. */
|
||||
return CountNumberOfBits(CompoundMask); // FindHighestSetBit(CompoundMask);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
VidFbInitializeVideo(
|
||||
_In_ ULONG_PTR BaseAddress,
|
||||
@@ -14,7 +57,8 @@ VidFbInitializeVideo(
|
||||
_In_ UINT32 ScreenWidth,
|
||||
_In_ UINT32 ScreenHeight,
|
||||
_In_ UINT32 PixelsPerScanLine,
|
||||
_In_ UINT32 BitsPerPixel);
|
||||
_In_ UINT32 BitsPerPixel,
|
||||
_In_opt_ PPIXEL_BITMASK PixelMasks);
|
||||
|
||||
VOID
|
||||
VidFbClearScreenColor(
|
||||
|
||||
Reference in New Issue
Block a user