Optimize boot menu drawing to eliminate screen flickering
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 29s
Builds / ExectOS (i686, debug) (push) Successful in 28s
Builds / ExectOS (i686, release) (push) Successful in 32s
Builds / ExectOS (amd64, release) (push) Successful in 34s

This commit is contained in:
Aiken Harris 2025-08-25 17:56:40 +02:00
parent e99e563aff
commit 960e913222
Signed by: harraiken
GPG Key ID: C40F06CB7493C1F5

View File

@ -24,7 +24,8 @@ BlDisplayBootMenu()
XTBL_DIALOG_HANDLE Handle; XTBL_DIALOG_HANDLE Handle;
PXTBL_BOOTMENU_ITEM MenuEntries = NULL; PXTBL_BOOTMENU_ITEM MenuEntries = NULL;
ULONG Index; ULONG Index;
ULONG HighligtedEntryId, NumberOfEntries, TopVisibleEntry, VisibleEntries; ULONG HighligtedEntryId, OldHighligtedEntryId, NumberOfEntries, TopVisibleEntry, VisibleEntries;
BOOLEAN RedrawBootMenu, RedrawEntries;
UINT_PTR EventIndex; UINT_PTR EventIndex;
EFI_EVENT Events[2]; EFI_EVENT Events[2];
EFI_INPUT_KEY Key; EFI_INPUT_KEY Key;
@ -72,14 +73,23 @@ BlDisplayBootMenu()
} }
} }
/* Set redraw flags to not redraw the menu itself, but fill it with entries */
RedrawBootMenu = FALSE;
RedrawEntries = TRUE;
/* Infinite boot menu loop */ /* Infinite boot menu loop */
while(TRUE) while(TRUE)
{ {
/* Redraw boot menu */ /* Redraw boot menu frame if requested */
BlpDrawBootMenu(&Handle); if(RedrawBootMenu)
{
BlpDrawBootMenu(&Handle);
RedrawBootMenu = FALSE;
RedrawEntries = TRUE;
}
/* Sanity check to ensure we do not display more entries than possible */ /* Sanity check to ensure we do not display more entries than possible */
if (VisibleEntries > NumberOfEntries) if(VisibleEntries > NumberOfEntries)
{ {
VisibleEntries = NumberOfEntries; VisibleEntries = NumberOfEntries;
} }
@ -87,12 +97,17 @@ BlDisplayBootMenu()
/* Check if there is anything to show in the boot menu */ /* Check if there is anything to show in the boot menu */
if(NumberOfEntries > 0) if(NumberOfEntries > 0)
{ {
/* Iterate through all menu entries */ /* Check if we need to redraw boot menu entries */
for(Index = 0; Index < VisibleEntries; Index++) if(RedrawEntries)
{ {
/* Draw menu entry */ /* Iterate through all menu entries */
BlpDrawBootMenuEntry(&Handle, MenuEntries[TopVisibleEntry + Index].EntryName, for(Index = 0; Index < VisibleEntries; Index++)
Index, (TopVisibleEntry + Index) == HighligtedEntryId); {
/* Draw menu entry */
BlpDrawBootMenuEntry(&Handle, MenuEntries[TopVisibleEntry + Index].EntryName,
Index, (TopVisibleEntry + Index) == HighligtedEntryId);
}
RedrawEntries = FALSE;
} }
} }
else else
@ -126,6 +141,9 @@ BlDisplayBootMenu()
/* Flush keyboard buffer out of any keystrokes */ /* Flush keyboard buffer out of any keystrokes */
EfiSystemTable->ConIn->Reset(EfiSystemTable->ConIn, FALSE); EfiSystemTable->ConIn->Reset(EfiSystemTable->ConIn, FALSE);
/* Store old highlighted entry */
OldHighligtedEntryId = HighligtedEntryId;
/* Infinite boot menu event loop */ /* Infinite boot menu event loop */
while(TRUE) while(TRUE)
{ {
@ -168,6 +186,7 @@ BlDisplayBootMenu()
BlDebugPrint(L"ERROR: Failed to boot '%S' (Status Code: 0x%zX)\n", BlDebugPrint(L"ERROR: Failed to boot '%S' (Status Code: 0x%zX)\n",
MenuEntries[HighligtedEntryId].EntryName, Status); MenuEntries[HighligtedEntryId].EntryName, Status);
BlDisplayErrorDialog(L"XTLDR", L"Failed to startup the selected Operating System."); BlDisplayErrorDialog(L"XTLDR", L"Failed to startup the selected Operating System.");
RedrawBootMenu = TRUE;
} }
/* Break from boot menu event loop to redraw whole boot menu */ /* Break from boot menu event loop to redraw whole boot menu */
@ -176,14 +195,28 @@ BlDisplayBootMenu()
else if(Key.ScanCode == 0x01) else if(Key.ScanCode == 0x01)
{ {
/* UpArrow key pressed, go to previous entry if possible */ /* UpArrow key pressed, go to previous entry if possible */
if (HighligtedEntryId > 0) if(HighligtedEntryId > 0)
{ {
/* Highlight previous entry */
HighligtedEntryId--; HighligtedEntryId--;
if (HighligtedEntryId < TopVisibleEntry)
/* Check if we need to scroll the view */
if(HighligtedEntryId < TopVisibleEntry)
{ {
/* Scroll the view */
TopVisibleEntry = HighligtedEntryId; TopVisibleEntry = HighligtedEntryId;
RedrawEntries = TRUE;
break;
} }
break;
/* Redraw new highlighted entry and the old one */
BlpDrawBootMenuEntry(&Handle, MenuEntries[OldHighligtedEntryId].EntryName,
OldHighligtedEntryId - TopVisibleEntry, FALSE);
BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId].EntryName,
HighligtedEntryId - TopVisibleEntry, TRUE);
/* Update old highlighted entry */
OldHighligtedEntryId = HighligtedEntryId;
} }
} }
else if(Key.ScanCode == 0x02) else if(Key.ScanCode == 0x02)
@ -191,12 +224,26 @@ BlDisplayBootMenu()
/* DownArrow key pressed, go to next entry if possible */ /* DownArrow key pressed, go to next entry if possible */
if(HighligtedEntryId < NumberOfEntries - 1) if(HighligtedEntryId < NumberOfEntries - 1)
{ {
/* Highlight next entry */
HighligtedEntryId++; HighligtedEntryId++;
if (HighligtedEntryId >= TopVisibleEntry + VisibleEntries)
/* Check if we need to scroll the view */
if(HighligtedEntryId >= TopVisibleEntry + VisibleEntries)
{ {
/* Scroll the view */
TopVisibleEntry = HighligtedEntryId - VisibleEntries + 1; TopVisibleEntry = HighligtedEntryId - VisibleEntries + 1;
RedrawEntries = TRUE;
break;
} }
break;
/* Redraw new highlighted entry and the old one */
BlpDrawBootMenuEntry(&Handle, MenuEntries[OldHighligtedEntryId].EntryName,
OldHighligtedEntryId - TopVisibleEntry, FALSE);
BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId].EntryName,
HighligtedEntryId - TopVisibleEntry, TRUE);
/* Update old highlighted entry */
OldHighligtedEntryId = HighligtedEntryId;
} }
} }
else if(Key.ScanCode == 0x09) else if(Key.ScanCode == 0x09)
@ -207,6 +254,7 @@ BlDisplayBootMenu()
/* Highlight first entry */ /* Highlight first entry */
HighligtedEntryId = 0; HighligtedEntryId = 0;
TopVisibleEntry = 0; TopVisibleEntry = 0;
RedrawEntries = TRUE;
break; break;
} }
} }
@ -218,6 +266,7 @@ BlDisplayBootMenu()
/* Highlight last entry */ /* Highlight last entry */
HighligtedEntryId = NumberOfEntries - 1; HighligtedEntryId = NumberOfEntries - 1;
TopVisibleEntry = (NumberOfEntries > VisibleEntries) ? (NumberOfEntries - VisibleEntries) : 0; TopVisibleEntry = (NumberOfEntries > VisibleEntries) ? (NumberOfEntries - VisibleEntries) : 0;
RedrawEntries = TRUE;
break; break;
} }
} }
@ -241,6 +290,7 @@ BlDisplayBootMenu()
L"Visit https://exectos.eu.org/ for more information."); L"Visit https://exectos.eu.org/ for more information.");
/* Break from boot menu event loop to redraw whole boot menu */ /* Break from boot menu event loop to redraw whole boot menu */
RedrawBootMenu = TRUE;
break; break;
} }
else if(Key.ScanCode == 0x14) else if(Key.ScanCode == 0x14)
@ -248,6 +298,7 @@ BlDisplayBootMenu()
/* F10 key pressed, reboot into UEFI setup interface */ /* F10 key pressed, reboot into UEFI setup interface */
BlEnterFirmwareSetup(); BlEnterFirmwareSetup();
BlDisplayErrorDialog(L"XTLDR", L"Reboot into firmware setup interface not supported!"); BlDisplayErrorDialog(L"XTLDR", L"Reboot into firmware setup interface not supported!");
RedrawBootMenu = TRUE;
/* Break from boot menu event loop to redraw whole boot menu */ /* Break from boot menu event loop to redraw whole boot menu */
break; break;
@ -257,6 +308,7 @@ BlDisplayBootMenu()
/* F11 key pressed, reboot the machine */ /* F11 key pressed, reboot the machine */
BlRebootSystem(); BlRebootSystem();
BlDisplayErrorDialog(L"XTLDR", L"Failed to reboot the machine!"); BlDisplayErrorDialog(L"XTLDR", L"Failed to reboot the machine!");
RedrawBootMenu = TRUE;
/* Break from boot menu event loop to redraw whole boot menu */ /* Break from boot menu event loop to redraw whole boot menu */
break; break;
@ -266,6 +318,7 @@ BlDisplayBootMenu()
/* F12 key pressed, shutdown the machine */ /* F12 key pressed, shutdown the machine */
BlShutdownSystem(); BlShutdownSystem();
BlDisplayErrorDialog(L"XTLDR", L"Failed to shutdown the machine!"); BlDisplayErrorDialog(L"XTLDR", L"Failed to shutdown the machine!");
RedrawBootMenu = TRUE;
/* Break from boot menu event loop to redraw whole boot menu */ /* Break from boot menu event loop to redraw whole boot menu */
break; break;
@ -274,6 +327,7 @@ BlDisplayBootMenu()
{ {
/* 'e' key pressed, edit the highlighted entry */ /* 'e' key pressed, edit the highlighted entry */
BlDisplayErrorDialog(L"XTLDR", L"Editing boot menu entries is not implemented yet!"); BlDisplayErrorDialog(L"XTLDR", L"Editing boot menu entries is not implemented yet!");
RedrawBootMenu = TRUE;
/* Break from boot menu event loop to redraw whole boot menu */ /* Break from boot menu event loop to redraw whole boot menu */
break; break;
@ -316,6 +370,7 @@ BlDisplayBootMenu()
BlDebugPrint(L"ERROR: Failed to boot '%S' (Status Code: 0x%zX)\n", BlDebugPrint(L"ERROR: Failed to boot '%S' (Status Code: 0x%zX)\n",
MenuEntries[HighligtedEntryId].EntryName, Status); MenuEntries[HighligtedEntryId].EntryName, Status);
BlDisplayErrorDialog(L"XTLDR", L"Failed to startup the selected Operating System."); BlDisplayErrorDialog(L"XTLDR", L"Failed to startup the selected Operating System.");
RedrawBootMenu = TRUE;
} }
break; break;
} }