diff --git a/Changelog.md b/Changelog.md index 79c2b8214f862117c5775a79e7c879c64d37d99b..eb55bb3889c08a147e7e0600dc08fa247a442602 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,7 @@ OpenCore Changelog - Increased OpenCanopy rendering performance - Reduced OpenCanopy mouse pointer input lag - Fixed that cursor bounds could be different from OpenCanopy's +- Improved builtin picker rendering performance #### v0.6.7 - Fixed ocvalidate return code to be non-zero when issues are found diff --git a/Library/OcBootManagementLib/OcBootManagementLib.c b/Library/OcBootManagementLib/OcBootManagementLib.c index d57fea914004d8eca8021363444dde52d9289356..0581eab9474f65e10b13f322563d2fa1acef470e 100644 --- a/Library/OcBootManagementLib/OcBootManagementLib.c +++ b/Library/OcBootManagementLib/OcBootManagementLib.c @@ -1,5 +1,5 @@ /** @file - Copyright (C) 2019, vit9696. All rights reserved. + Copyright (C) 2019-2021, vit9696 and contributors. All rights reserved. All rights reserved. @@ -105,6 +105,26 @@ RunShowMenu ( return Status; } +STATIC +CHAR16 +GetPickerEntryCursor ( + IN OC_BOOT_CONTEXT *BootContext, + IN UINT32 TimeOutSeconds, + IN INTN ChosenEntry, + IN UINTN Index + ) +{ + if (TimeOutSeconds > 0 && BootContext->DefaultEntry->EntryIndex - 1 == Index) { + return L'*'; + } + + if (ChosenEntry >= 0 && (UINTN) ChosenEntry == Index) { + return L'>'; + } + + return L' '; +} + EFI_STATUS EFIAPI OcShowSimpleBootMenu ( @@ -118,6 +138,12 @@ OcShowSimpleBootMenu ( UINTN Length; INTN KeyIndex; INTN ChosenEntry; + INTN OldChosenEntry; + INT32 FirstIndexRow; + INT32 StatusRow; + INT32 StatusColumn; + CHAR16 EntryCursor; + CHAR16 OldEntryCursor; CHAR16 Code[2]; UINT32 TimeOutSeconds; UINT32 Count; @@ -129,7 +155,9 @@ OcShowSimpleBootMenu ( TimeOutSeconds = BootContext->PickerContext->TimeoutSeconds; ASSERT (BootContext->DefaultEntry != NULL); - ChosenEntry = (INTN) (BootContext->DefaultEntry->EntryIndex - 1); + ChosenEntry = (INTN) (BootContext->DefaultEntry->EntryIndex - 1); + OldChosenEntry = ChosenEntry; + FirstIndexRow = -1; PlayedOnce = FALSE; PlayChosen = FALSE; @@ -160,42 +188,73 @@ OcShowSimpleBootMenu ( gST->ConOut->TestString (gST->ConOut, OC_CONSOLE_MARK_CONTROLLED); while (TRUE) { - gST->ConOut->ClearScreen (gST->ConOut); - gST->ConOut->OutputString (gST->ConOut, OC_MENU_BOOT_MENU); - - if (BootContext->PickerContext->TitleSuffix != NULL) { - Length = AsciiStrLen (BootContext->PickerContext->TitleSuffix); - gST->ConOut->OutputString (gST->ConOut, L" ("); - for (Index = 0; Index < Length; ++Index) { - Code[0] = BootContext->PickerContext->TitleSuffix[Index]; - gST->ConOut->OutputString (gST->ConOut, Code); + if (FirstIndexRow != -1) { + // + // Incrementally update menu + // + if (OldChosenEntry >= 0 && OldChosenEntry != ChosenEntry) { + gST->ConOut->SetCursorPosition (gST->ConOut, 0, FirstIndexRow + OldChosenEntry); + gST->ConOut->OutputString (gST->ConOut, L" "); } - gST->ConOut->OutputString (gST->ConOut, L")"); - } + + if (OldChosenEntry != ChosenEntry || OldEntryCursor != EntryCursor) { + if (ChosenEntry >= 0) { + OldEntryCursor = EntryCursor; - gST->ConOut->OutputString (gST->ConOut, L"\r\n\r\n"); + EntryCursor = GetPickerEntryCursor(BootContext, TimeOutSeconds, ChosenEntry, ChosenEntry); - for (Index = 0; Index < MIN (Count, OC_INPUT_MAX); ++Index) { - if (TimeOutSeconds > 0 && BootContext->DefaultEntry->EntryIndex - 1 == Index) { - gST->ConOut->OutputString (gST->ConOut, L"* "); - } else if (ChosenEntry >= 0 && (UINTN) ChosenEntry == Index) { - gST->ConOut->OutputString (gST->ConOut, L"> "); - } else { - gST->ConOut->OutputString (gST->ConOut, L" "); + gST->ConOut->SetCursorPosition (gST->ConOut, 0, FirstIndexRow + ChosenEntry); + Code[0] = EntryCursor; + gST->ConOut->OutputString (gST->ConOut, Code); + } + + OldChosenEntry = ChosenEntry; + + gST->ConOut->SetCursorPosition (gST->ConOut, StatusColumn, StatusRow); } + } else { + // + // Render initial menu + // + gST->ConOut->ClearScreen (gST->ConOut); + gST->ConOut->OutputString (gST->ConOut, OC_MENU_BOOT_MENU); + + if (BootContext->PickerContext->TitleSuffix != NULL) { + Length = AsciiStrLen (BootContext->PickerContext->TitleSuffix); + gST->ConOut->OutputString (gST->ConOut, L" ("); + for (Index = 0; Index < Length; ++Index) { + Code[0] = BootContext->PickerContext->TitleSuffix[Index]; + gST->ConOut->OutputString (gST->ConOut, Code); + } + gST->ConOut->OutputString (gST->ConOut, L")"); + } + + gST->ConOut->OutputString (gST->ConOut, L"\r\n\r\n"); + + FirstIndexRow = gST->ConOut->Mode->CursorRow; - Code[0] = OC_INPUT_STR[Index]; - gST->ConOut->OutputString (gST->ConOut, Code); - gST->ConOut->OutputString (gST->ConOut, L". "); - gST->ConOut->OutputString (gST->ConOut, BootEntries[Index]->Name); - if (BootEntries[Index]->IsExternal) { - gST->ConOut->OutputString (gST->ConOut, OC_MENU_EXTERNAL); + for (Index = 0; Index < MIN (Count, OC_INPUT_MAX); ++Index) { + EntryCursor = GetPickerEntryCursor(BootContext, TimeOutSeconds, ChosenEntry, Index); + Code[0] = EntryCursor; + gST->ConOut->OutputString (gST->ConOut, Code); + gST->ConOut->OutputString (gST->ConOut, L" "); + + Code[0] = OC_INPUT_STR[Index]; + gST->ConOut->OutputString (gST->ConOut, Code); + gST->ConOut->OutputString (gST->ConOut, L". "); + gST->ConOut->OutputString (gST->ConOut, BootEntries[Index]->Name); + if (BootEntries[Index]->IsExternal) { + gST->ConOut->OutputString (gST->ConOut, OC_MENU_EXTERNAL); + } + gST->ConOut->OutputString (gST->ConOut, L"\r\n"); } + gST->ConOut->OutputString (gST->ConOut, L"\r\n"); - } + gST->ConOut->OutputString (gST->ConOut, OC_MENU_CHOOSE_OS); - gST->ConOut->OutputString (gST->ConOut, L"\r\n"); - gST->ConOut->OutputString (gST->ConOut, OC_MENU_CHOOSE_OS); + StatusRow = gST->ConOut->Mode->CursorRow; + StatusColumn = gST->ConOut->Mode->CursorColumn; + } if (!PlayedOnce && BootContext->PickerContext->PickerAudioAssist) { OcPlayAudioFile (BootContext->PickerContext, OcVoiceOverAudioFileChooseOS, FALSE);