ReactOS 0.4.16-dev-2284-g3529151
vidfb.c
Go to the documentation of this file.
1/*
2 * PROJECT: FreeLoader
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Video support for linear framebuffers
5 * COPYRIGHT: Authors of uefivid.c and xboxvideo.c
6 * Copyright 2025-2026 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
7 */
8
9#include <freeldr.h>
10#include "vidfb.h"
11#include "vgafont.h"
12
13#include <debug.h>
15
16/* This is used to introduce artificial symmetric borders at the top and bottom */
17#define TOP_BOTTOM_LINES 0
18
19
20/* GLOBALS ********************************************************************/
21
22typedef struct _FRAMEBUFFER_INFO
23{
26
27 /* Horizontal and Vertical resolution in pixels */
30
31 /* Number of pixel elements per video memory line */
32 ULONG PixelsPerScanLine; // aka. "Pitch" or "ScreenStride", but Stride is in bytes or bits...
33 ULONG BitsPerPixel; // aka. "PixelStride".
34
35 /* Physical format of the pixel for BPP > 8, specified by bit-mask */
37
41 ULONG Delta; // aka. "Pitch": actual size in bytes of a scanline.
43
46
47
48/* FUNCTIONS ******************************************************************/
49
50#if DBG
51static VOID
52VidFbPrintFramebufferInfo(VOID)
53{
54 TRACE("Framebuffer format:\n");
55 TRACE(" BaseAddress : 0x%X\n", framebufInfo.BaseAddress);
56 TRACE(" BufferSize : %lu\n", framebufInfo.BufferSize);
57 TRACE(" ScreenWidth : %lu\n", framebufInfo.ScreenWidth);
58 TRACE(" ScreenHeight : %lu\n", framebufInfo.ScreenHeight);
59 TRACE(" PixelsPerScanLine : %lu\n", framebufInfo.PixelsPerScanLine);
60 TRACE(" BitsPerPixel : %lu\n", framebufInfo.BitsPerPixel);
61 TRACE(" BytesPerPixel : %lu\n", framebufInfo.BytesPerPixel);
62 TRACE(" Delta : %lu\n", framebufInfo.Delta);
63 TRACE(" ARGB masks: : %08x/%08x/%08x/%08x\n",
68}
69#endif
70
105 _In_ UINT32 PixelsPerScanLine,
106 _In_ UINT32 BitsPerPixel,
107 _In_opt_ PPIXEL_BITMASK PixelMasks)
108{
110
111 if (pFbData)
112 *pFbData = NULL;
113
115
116 /* Verify framebuffer dimensions */
117 if ((ScreenWidth < 1) || (ScreenHeight < 1))
118 {
119 ERR("Invalid framebuffer dimensions\n");
120 return FALSE;
121 }
122
127 framebufInfo.PixelsPerScanLine = PixelsPerScanLine;
128 framebufInfo.BitsPerPixel = BitsPerPixel;
129
130 framebufInfo.BytesPerPixel = (BitsPerPixel + 7) / 8; // Round up to nearest byte.
131 framebufInfo.Delta = (PixelsPerScanLine * framebufInfo.BytesPerPixel + 3) & ~3;
132
133 /* Verify that the framebuffer fits inside the video RAM */
135 {
136 ERR("Framebuffer doesn't fit inside the video RAM (FB size: %lu, VRAM size: %lu)\n",
138 return FALSE;
139 }
140
141 /* We currently only support 32bpp */
142 if (BitsPerPixel != 32)
143 {
144 /* Unsupported BPP */
145 ERR("Unsupported %lu bits per pixel format\n", BitsPerPixel);
146 return FALSE;
147 }
148
149 //ASSERT((BitsPerPixel <= 8 && !PixelMasks) || (BitsPerPixel > 8));
150 if (BitsPerPixel > 8)
151 {
152 if (!PixelMasks ||
153 (PixelMasks->RedMask == 0 &&
154 PixelMasks->GreenMask == 0 &&
155 PixelMasks->BlueMask == 0 /* &&
156 PixelMasks->ReservedMask == 0 */))
157 {
158 /* Determine pixel mask given color depth and color channel */
159 switch (BitsPerPixel)
160 {
161 case 32:
162 case 24: /* 8:8:8 */
163 BitMasks->RedMask = 0x00FF0000; // 0x00FF0000;
164 BitMasks->GreenMask = 0x0000FF00; // 0x00FF0000 >> 8;
165 BitMasks->BlueMask = 0x000000FF; // 0x00FF0000 >> 16;
166 BitMasks->ReservedMask = ((1 << (BitsPerPixel - 24)) - 1) << 24;
167 break;
168 case 16: /* 5:6:5 */
169 BitMasks->RedMask = 0xF800; // 0xF800;
170 BitMasks->GreenMask = 0x07E0; // (0xF800 >> 5) | 0x20;
171 BitMasks->BlueMask = 0x001F; // 0xF800 >> 11;
172 BitMasks->ReservedMask = 0;
173 break;
174 case 15: /* 5:5:5 */
175 BitMasks->RedMask = 0x7C00; // 0x7C00;
176 BitMasks->GreenMask = 0x03E0; // 0x7C00 >> 5;
177 BitMasks->BlueMask = 0x001F; // 0x7C00 >> 10;
178 BitMasks->ReservedMask = 0x8000;
179 break;
180 default:
181 /* Unsupported BPP */
183 RtlZeroMemory(BitMasks, sizeof(*BitMasks));
184 }
185 }
186 else
187 {
188 /* Copy the pixel masks */
189 RtlCopyMemory(BitMasks, PixelMasks, sizeof(*BitMasks));
190 }
191 }
192 else
193 {
194 /* Palettized modes don't use masks */
195 RtlZeroMemory(BitMasks, sizeof(*BitMasks));
196 }
197
198#if DBG
199 VidFbPrintFramebufferInfo();
200 {
201 ULONG BppFromMasks =
202 PixelBitmasksToBpp(BitMasks->RedMask,
203 BitMasks->GreenMask,
204 BitMasks->BlueMask,
205 BitMasks->ReservedMask);
206 TRACE("BitsPerPixel = %lu , BppFromMasks = %lu\n", BitsPerPixel, BppFromMasks);
207 //ASSERT(BitsPerPixel == BppFromMasks);
208 }
209#endif
210
211 /* Initialize the hardware device configuration data if specified */
212 if (pFbData)
213 {
219
222
223 *pFbData = &FrameBufferData;
224 }
225
226 return TRUE;
227}
228
229VOID
232 _In_ BOOLEAN FullScreen)
233{
234 ULONG Line, Col;
235 PUINT32 p;
236
237 for (Line = 0; Line < framebufInfo.ScreenHeight - (FullScreen ? 0 : 2 * TOP_BOTTOM_LINES); Line++)
238 {
240 for (Col = 0; Col < framebufInfo.ScreenWidth; Col++)
241 {
242 *p++ = Color;
243 }
244 }
245}
246
252VOID
254 _In_ UCHAR Char,
255 _In_ ULONG X,
256 _In_ ULONG Y,
257 _In_ UINT32 FgColor,
258 _In_ UINT32 BgColor)
259{
260 const UCHAR* FontPtr;
261 PUINT32 Pixel;
262 UCHAR Mask;
263 ULONG Line, Col;
264
265 /* Don't display outside of the screen, nor partial characters */
266 if ((X + CHAR_WIDTH - 1 >= framebufInfo.ScreenWidth) ||
268 {
269 return;
270 }
271
272 FontPtr = BitmapFont8x16 + Char * CHAR_HEIGHT;
274 (Y + TOP_BOTTOM_LINES) * framebufInfo.Delta + X * sizeof(UINT32));
275
276 for (Line = 0; Line < CHAR_HEIGHT; Line++)
277 {
278 Mask = 0x80;
279 for (Col = 0; Col < CHAR_WIDTH; Col++)
280 {
281 Pixel[Col] = (0 != (FontPtr[Line] & Mask) ? FgColor : BgColor);
282 Mask = Mask >> 1;
283 }
284 Pixel = (PUINT32)((PUCHAR)Pixel + framebufInfo.Delta);
285 }
286}
287
293VOID
298{
302}
303
309ULONG
311{
314}
315
316VOID
319 _In_ ULONG Scroll)
320{
324
325 while (PixelCount--)
326 *Dst++ = *Src++;
327
328 for (PixelCount = 0; PixelCount < framebufInfo.ScreenWidth * Scroll; PixelCount++)
329 *Dst++ = Color;
330}
331
332#if 0
333VOID
334VidFbSetTextCursorPosition(UCHAR X, UCHAR Y)
335{
336 /* We don't have a cursor yet */
337}
338
339VOID
340VidFbHideShowTextCursor(BOOLEAN Show)
341{
342 /* We don't have a cursor yet */
343}
344
346VidFbIsPaletteFixed(VOID)
347{
348 return FALSE;
349}
350
351VOID
352VidFbSetPaletteColor(
354 _In_ UCHAR Red, _In_ UCHAR Green, _In_ UCHAR Blue)
355{
356 /* Not supported */
357}
358
359VOID
360VidFbGetPaletteColor(
362 _Out_ PUCHAR Red, _Out_ PUCHAR Green, _Out_ PUCHAR Blue)
363{
364 /* Not supported */
365}
366#endif
367
368
369
370/*
371 * PROJECT: FreeLoader
372 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
373 * or MIT (https://spdx.org/licenses/MIT)
374 * PURPOSE: Linear framebuffer based console support
375 * COPYRIGHT: Copyright 2025-2026 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
376 */
377
378#define VGA_CHAR_SIZE 2
379
380#define FBCONS_WIDTH (framebufInfo.ScreenWidth / CHAR_WIDTH)
381#define FBCONS_HEIGHT ((framebufInfo.ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT)
382
383static inline
384UINT32
386 _In_ UCHAR Attr)
387{
389 Intensity = (0 == (Attr & 0x08) ? 127 : 255);
390
391 return 0xff000000 |
392 (0 == (Attr & 0x04) ? 0 : (Intensity << 16)) |
393 (0 == (Attr & 0x02) ? 0 : (Intensity << 8)) |
394 (0 == (Attr & 0x01) ? 0 : Intensity);
395}
396
402static VOID
404 _In_ UCHAR Attr,
405 _Out_ PUINT32 FgColor,
406 _Out_ PUINT32 BgColor)
407{
408 *FgColor = FbConsAttrToSingleColor(Attr & 0x0F);
409 *BgColor = FbConsAttrToSingleColor((Attr >> 4) & 0x0F);
410}
411
412VOID
414 _In_ UCHAR Attr)
415{
416 UINT32 FgColor, BgColor;
417 FbConsAttrToColors(Attr, &FgColor, &BgColor);
419}
420
426VOID
428 _In_ UCHAR Char,
429 _In_ ULONG Column,
430 _In_ ULONG Row,
431 _In_ UINT32 FgColor,
432 _In_ UINT32 BgColor)
433{
434 /* Don't display outside of the screen */
435 if ((Column >= FBCONS_WIDTH) || (Row >= FBCONS_HEIGHT))
436 return;
437 VidFbOutputChar(Char, Column * CHAR_WIDTH, Row * CHAR_HEIGHT, FgColor, BgColor);
438}
439
444VOID
446 _In_ UCHAR Char,
447 _In_ UCHAR Attr,
448 _In_ ULONG Column,
449 _In_ ULONG Row)
450{
451 UINT32 FgColor, BgColor;
452 FbConsAttrToColors(Attr, &FgColor, &BgColor);
453 FbConsOutputChar(Char, Column, Row, FgColor, BgColor);
454}
455
461VOID
466{
467 // VidFbGetDisplaySize(Width, Height, Depth);
468 // *Width /= CHAR_WIDTH;
469 // *Height /= CHAR_HEIGHT;
473}
474
480ULONG
482{
484}
485
490// TODO: Write a VidFb "BitBlt" equivalent.
491VOID
494{
495 PUCHAR OffScreenBuffer = (PUCHAR)Buffer;
496 ULONG Row, Col;
497
498 // ULONG Width, Height, Depth;
499 // FbConsGetDisplaySize(&Width, &Height, &Depth);
501
502 for (Row = 0; Row < Height; ++Row)
503 {
504 for (Col = 0; Col < Width; ++Col)
505 {
506 FbConsPutChar(OffScreenBuffer[0], OffScreenBuffer[1], Col, Row);
507 OffScreenBuffer += VGA_CHAR_SIZE;
508 }
509 }
510}
511
512VOID
514 _In_ UCHAR Attr)
515{
516 UINT32 BgColor, Dummy;
517 FbConsAttrToColors(Attr, &Dummy, &BgColor);
518 VidFbScrollUp(BgColor, CHAR_HEIGHT);
519}
unsigned char BOOLEAN
Definition: actypes.h:127
#define ERR(fmt,...)
Definition: precomp.h:57
unsigned int * PUINT32
Definition: basetsd.h:119
#define UNIMPLEMENTED
Definition: ntoskrnl.c:15
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
Definition: bufpool.h:45
#define BufferSize
Definition: mmc.h:75
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define Y(I)
unsigned int Mask
Definition: fpcontrol.c:82
GLfloat GLfloat p
Definition: glext.h:8902
#define Dst
Definition: mesh.h:153
static WORD Intensity(RGBQUAD clr)
Definition: msrle32.c:44
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
#define _Out_opt_
Definition: no_sal2.h:214
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
static ULONG ScreenWidth
Definition: pcvideo.c:116
static ULONG ScreenHeight
Definition: pcvideo.c:117
#define TRACE(s)
Definition: solgame.cpp:4
Definition: ncftp.h:79
Definition: ui.h:200
ReactOS Framebuffer-specific video device configuration data.
Definition: framebuf.h:35
struct _CM_FRAMEBUF_DEVICE_DATA::@3566 PixelMasks
ULONG BitsPerPixel
Pixel depth.
Definition: framebuf.h:51
ULONG PixelsPerScanLine
Pitch/stride in pixels.
Definition: framebuf.h:50
ULONG BufferSize
Definition: vidfb.c:25
ULONG_PTR BaseAddress
Definition: vidfb.c:24
ULONG PixelsPerScanLine
Definition: vidfb.c:32
ULONG ScreenHeight
Definition: vidfb.c:29
ULONG BitsPerPixel
Definition: vidfb.c:33
ULONG Delta
Definition: vidfb.c:41
PIXEL_BITMASK PixelMasks
Definition: vidfb.c:36
ULONG BytesPerPixel
Definition: vidfb.c:40
ULONG ScreenWidth
Definition: vidfb.c:28
Physical format of an RGB pixel, specified with per-component bit-masks. A bit being set defines thos...
Definition: vidfb.h:22
ULONG RedMask
Definition: vidfb.h:23
ULONG BlueMask
Definition: vidfb.h:25
ULONG GreenMask
Definition: vidfb.h:24
ULONG ReservedMask
Definition: vidfb.h:26
uint32_t * PULONG
Definition: typedefs.h:59
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t UINT32
Definition: typedefs.h:59
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
_In_ HFONT _Out_ PUINT _Out_ PUINT Width
Definition: font.h:89
_In_ HFONT _Out_ PUINT Height
Definition: font.h:88
const UCHAR BitmapFont8x16[256 *CHAR_HEIGHT]
Definition: vgafont.c:13
#define CHAR_WIDTH
Definition: vgafont.h:10
#define CHAR_HEIGHT
Definition: vgafont.h:11
VOID FbConsScrollUp(_In_ UCHAR Attr)
Definition: vidfb.c:513
VOID FbConsClearScreen(_In_ UCHAR Attr)
Definition: vidfb.c:413
#define FBCONS_WIDTH
Definition: vidfb.c:380
#define TOP_BOTTOM_LINES
Definition: vidfb.c:17
VOID FbConsGetDisplaySize(_Out_ PULONG Width, _Out_ PULONG Height, _Out_ PULONG Depth)
Returns the width and height in number of CGA characters/attributes, of a full text-mode CGA-style ch...
Definition: vidfb.c:462
#define VGA_CHAR_SIZE
Definition: vidfb.c:378
ULONG VidFbGetBufferSize(VOID)
Returns the size in bytes, of a full graphics pixel buffer rectangle that can fill the whole visible ...
Definition: vidfb.c:310
static FRAMEBUFFER_INFO framebufInfo
Definition: vidfb.c:44
VOID VidFbClearScreenColor(_In_ UINT32 Color, _In_ BOOLEAN FullScreen)
Definition: vidfb.c:230
#define FBCONS_HEIGHT
Definition: vidfb.c:381
VOID VidFbScrollUp(_In_ UINT32 Color, _In_ ULONG Scroll)
Definition: vidfb.c:317
ULONG FbConsGetBufferSize(VOID)
Returns the size in bytes, of a full text-mode CGA-style character buffer rectangle that can fill the...
Definition: vidfb.c:481
struct _FRAMEBUFFER_INFO FRAMEBUFFER_INFO
static VOID FbConsAttrToColors(_In_ UCHAR Attr, _Out_ PUINT32 FgColor, _Out_ PUINT32 BgColor)
Maps a text-mode CGA-style character attribute to separate foreground and background ARGB colors.
Definition: vidfb.c:403
static CM_FRAMEBUF_DEVICE_DATA FrameBufferData
Definition: vidfb.c:45
VOID FbConsPutChar(_In_ UCHAR Char, _In_ UCHAR Attr, _In_ ULONG Column, _In_ ULONG Row)
Displays a character with specific text attributes at a given position.
Definition: vidfb.c:445
static UINT32 FbConsAttrToSingleColor(_In_ UCHAR Attr)
Definition: vidfb.c:385
VOID FbConsOutputChar(_In_ UCHAR Char, _In_ ULONG Column, _In_ ULONG Row, _In_ UINT32 FgColor, _In_ UINT32 BgColor)
Displays a character at a given position with specific foreground and background colors.
Definition: vidfb.c:427
VOID VidFbOutputChar(_In_ UCHAR Char, _In_ ULONG X, _In_ ULONG Y, _In_ UINT32 FgColor, _In_ UINT32 BgColor)
Displays a character at a given pixel position with specific foreground and background colors.
Definition: vidfb.c:253
VOID VidFbGetDisplaySize(_Out_ PULONG Width, _Out_ PULONG Height, _Out_ PULONG Depth)
Returns the width and height in pixels, of the whole visible area of the graphics framebuffer.
Definition: vidfb.c:294
VOID FbConsCopyOffScreenBufferToVRAM(_In_ PVOID Buffer)
Copies a full text-mode CGA-style character buffer rectangle to the console.
Definition: vidfb.c:492
struct _FRAMEBUFFER_INFO * PFRAMEBUFFER_INFO
BOOLEAN VidFbInitializeVideo(_Out_opt_ PCM_FRAMEBUF_DEVICE_DATA *pFbData, _In_ ULONG_PTR BaseAddress, _In_ ULONG BufferSize, _In_ UINT32 ScreenWidth, _In_ UINT32 ScreenHeight, _In_ UINT32 PixelsPerScanLine, _In_ UINT32 BitsPerPixel, _In_opt_ PPIXEL_BITMASK PixelMasks)
Initializes internal framebuffer information based on the given parameters.
Definition: vidfb.c:99
FORCEINLINE ULONG PixelBitmasksToBpp(_In_ ULONG RedMask, _In_ ULONG GreenMask, _In_ ULONG BlueMask, _In_ ULONG ReservedMask)
Calculates the number of bits per pixel ("PixelDepth") for the given pixel format,...
Definition: vidfb.h:41
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
_In_opt_ PALLOCATE_FUNCTION _In_opt_ PFREE_FUNCTION _In_ ULONG _In_ SIZE_T _In_ ULONG _In_ USHORT Depth
Definition: exfuncs.h:819
unsigned char UCHAR
Definition: xmlstorage.h:181