X-Git-Url: https://code.delx.au/refind/blobdiff_plain/8b9e6b44d9e996a65cc4b81a71e8e6fdc054ea27..480ba418c97ece5557ac0efc5dc189ff19fb8b8f:/refind/screen.c diff --git a/refind/screen.c b/refind/screen.c index a5628c0..a408430 100644 --- a/refind/screen.c +++ b/refind/screen.c @@ -1,5 +1,5 @@ /* - * refit/screen.c + * refind/screen.c * Screen handling functions * * Copyright (c) 2006 Christoph Pfisterer @@ -33,24 +33,43 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* + * Modifications copyright (c) 2012-2015 Roderick W. Smith + * + * Modifications distributed under the terms of the GNU General Public + * License (GPL) version 3 (GPLv3), or (at your option) any later version. + * + */ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #include "global.h" #include "screen.h" #include "config.h" #include "libegint.h" -#include "refit_call_wrapper.h" +#include "lib.h" +#include "menu.h" +#include "../include/refit_call_wrapper.h" -#include "egemb_refind_banner.h" +#include "../include/egemb_refind_banner.h" // Console defines and variables UINTN ConWidth; UINTN ConHeight; -CHAR16 *BlankLine; - -static VOID SwitchToText(IN BOOLEAN CursorEnabled); -static VOID SwitchToGraphics(VOID); -static VOID DrawScreenHeader(IN CHAR16 *Title); +CHAR16 *BlankLine = NULL; // UGA defines and variables @@ -60,6 +79,7 @@ BOOLEAN AllowGraphicsMode; EG_PIXEL StdBackgroundPixel = { 0xbf, 0xbf, 0xbf, 0 }; EG_PIXEL MenuBackgroundPixel = { 0xbf, 0xbf, 0xbf, 0 }; +EG_PIXEL DarkBackgroundPixel = { 0x0, 0x0, 0x0, 0 }; static BOOLEAN GraphicsScreenDirty; @@ -67,14 +87,23 @@ static BOOLEAN GraphicsScreenDirty; static BOOLEAN haveError = FALSE; +static VOID PrepareBlankLine(VOID) { + UINTN i; + + MyFreePool(BlankLine); + // make a buffer for a whole text line + BlankLine = AllocatePool((ConWidth + 1) * sizeof(CHAR16)); + for (i = 0; i < ConWidth; i++) + BlankLine[i] = ' '; + BlankLine[i] = 0; +} + // // Screen initialization and switching // VOID InitScreen(VOID) { - UINTN i; - // initialize libeg egInitScreen(); @@ -83,6 +112,7 @@ VOID InitScreen(VOID) AllowGraphicsMode = TRUE; } else { AllowGraphicsMode = FALSE; + egSetTextMode(GlobalConfig.RequestedTextMode); egSetGraphicsModeEnabled(FALSE); // just to be sure we are in text mode } GraphicsScreenDirty = TRUE; @@ -97,18 +127,49 @@ VOID InitScreen(VOID) ConHeight = 25; } - // make a buffer for a whole text line - BlankLine = AllocatePool((ConWidth + 1) * sizeof(CHAR16)); - for (i = 0; i < ConWidth; i++) - BlankLine[i] = ' '; - BlankLine[i] = 0; + PrepareBlankLine(); - // show the banner (even when in graphics mode) - DrawScreenHeader(L"Initializing..."); + // show the banner if in text mode + if (GlobalConfig.TextOnly && (GlobalConfig.ScreensaverTime != -1)) + DrawScreenHeader(L"Initializing..."); } +// Set the screen resolution and mode (text vs. graphics). VOID SetupScreen(VOID) { + UINTN NewWidth, NewHeight; + + // Convert mode number to horizontal & vertical resolution values + if ((GlobalConfig.RequestedScreenWidth > 0) && (GlobalConfig.RequestedScreenHeight == 0)) + egGetResFromMode(&(GlobalConfig.RequestedScreenWidth), &(GlobalConfig.RequestedScreenHeight)); + + // Set the believed-to-be current resolution to the LOWER of the current + // believed-to-be resolution and the requested resolution. This is done to + // enable setting a lower-than-default resolution. + if ((GlobalConfig.RequestedScreenWidth > 0) && (GlobalConfig.RequestedScreenHeight > 0)) { + UGAWidth = (UGAWidth < GlobalConfig.RequestedScreenWidth) ? UGAWidth : GlobalConfig.RequestedScreenWidth; + UGAHeight = (UGAHeight < GlobalConfig.RequestedScreenHeight) ? UGAHeight : GlobalConfig.RequestedScreenHeight; + } + + // Set text mode. If this requires increasing the size of the graphics mode, do so. + if (egSetTextMode(GlobalConfig.RequestedTextMode)) { + egGetScreenSize(&NewWidth, &NewHeight); + if ((NewWidth > UGAWidth) || (NewHeight > UGAHeight)) { + UGAWidth = NewWidth; + UGAHeight = NewHeight; + } + if ((UGAWidth > GlobalConfig.RequestedScreenWidth) || (UGAHeight > GlobalConfig.RequestedScreenHeight)) { + // Requested text mode forces us to use a bigger graphics mode + GlobalConfig.RequestedScreenWidth = UGAWidth; + GlobalConfig.RequestedScreenHeight = UGAHeight; + } // if + } + + if (GlobalConfig.RequestedScreenWidth > 0) { + egSetScreenSize(&(GlobalConfig.RequestedScreenWidth), &(GlobalConfig.RequestedScreenHeight)); + egGetScreenSize(&UGAWidth, &UGAHeight); + } // if user requested a particular screen resolution + if (GlobalConfig.TextOnly) { // switch to text mode if requested AllowGraphicsMode = FALSE; @@ -117,23 +178,29 @@ VOID SetupScreen(VOID) } else if (AllowGraphicsMode) { // clear screen and show banner // (now we know we'll stay in graphics mode) - if ((GlobalConfig.RequestedScreenWidth > 0) && (GlobalConfig.RequestedScreenHeight > 0) && - egSetScreenSize(GlobalConfig.RequestedScreenWidth, GlobalConfig.RequestedScreenHeight)) { - UGAWidth = GlobalConfig.RequestedScreenWidth; - UGAHeight = GlobalConfig.RequestedScreenHeight; - } // if user requested a particular screen resolution SwitchToGraphics(); - BltClearScreen(TRUE); + if (GlobalConfig.ScreensaverTime != -1) { + BltClearScreen(TRUE); + } else { // start with screen blanked + GraphicsScreenDirty = TRUE; + } } -} +} // VOID SetupScreen() -static VOID SwitchToText(IN BOOLEAN CursorEnabled) +VOID SwitchToText(IN BOOLEAN CursorEnabled) { egSetGraphicsModeEnabled(FALSE); refit_call2_wrapper(ST->ConOut->EnableCursor, ST->ConOut, CursorEnabled); + // get size of text console + if (refit_call4_wrapper(ST->ConOut->QueryMode, ST->ConOut, ST->ConOut->Mode->Mode, &ConWidth, &ConHeight) != EFI_SUCCESS) { + // use default values on error + ConWidth = 80; + ConHeight = 25; + } + PrepareBlankLine(); } -static VOID SwitchToGraphics(VOID) +VOID SwitchToGraphics(VOID) { if (AllowGraphicsMode && !egIsGraphicsModeEnabled()) { egSetGraphicsModeEnabled(TRUE); @@ -157,8 +224,8 @@ VOID BeginTextScreen(IN CHAR16 *Title) VOID FinishTextScreen(IN BOOLEAN WaitAlways) { if (haveError || WaitAlways) { - SwitchToText(FALSE); - PauseForKey(); + PauseForKey(); + SwitchToText(FALSE); } // reset error flag @@ -167,8 +234,6 @@ VOID FinishTextScreen(IN BOOLEAN WaitAlways) VOID BeginExternalScreen(IN BOOLEAN UseGraphicsMode, IN CHAR16 *Title) { - EG_PIXEL DarkBackgroundPixel = { 0x0, 0x0, 0x0, 0 }; - if (!AllowGraphicsMode) UseGraphicsMode = FALSE; @@ -176,14 +241,10 @@ VOID BeginExternalScreen(IN BOOLEAN UseGraphicsMode, IN CHAR16 *Title) SwitchToGraphics(); BltClearScreen(FALSE); } else { - egClearScreen(&DarkBackgroundPixel); - } // if/else - - // show the header - DrawScreenHeader(Title); - - if (!UseGraphicsMode) + egClearScreen(&DarkBackgroundPixel); + DrawScreenHeader(Title); SwitchToText(TRUE); + } // reset error flag haveError = FALSE; @@ -199,6 +260,9 @@ VOID FinishExternalScreen(VOID) PauseForKey(); } + // Reset the screen resolution, in case external program changed it.... + SetupScreen(); + // reset error flag haveError = FALSE; } @@ -208,18 +272,19 @@ VOID TerminateScreen(VOID) // clear text screen refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BASIC); refit_call1_wrapper(ST->ConOut->ClearScreen, ST->ConOut); - + // enable cursor refit_call2_wrapper(ST->ConOut->EnableCursor, ST->ConOut, TRUE); } -static VOID DrawScreenHeader(IN CHAR16 *Title) +VOID DrawScreenHeader(IN CHAR16 *Title) { UINTN y; // clear to black background + egClearScreen(&DarkBackgroundPixel); // first clear in graphics mode refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BASIC); - refit_call1_wrapper(ST->ConOut->ClearScreen, ST->ConOut); + refit_call1_wrapper(ST->ConOut->ClearScreen, ST->ConOut); // then clear in text mode // paint header background refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BANNER); @@ -241,7 +306,7 @@ static VOID DrawScreenHeader(IN CHAR16 *Title) // Keyboard input // -static BOOLEAN ReadAllKeyStrokes(VOID) +BOOLEAN ReadAllKeyStrokes(VOID) { BOOLEAN GotKeyStrokes; EFI_STATUS Status; @@ -262,9 +327,9 @@ static BOOLEAN ReadAllKeyStrokes(VOID) VOID PauseForKey(VOID) { UINTN index; - + Print(L"\n* Hit any key to continue *"); - + if (ReadAllKeyStrokes()) { // remove buffered key strokes refit_call1_wrapper(BS->Stall, 5000000); // 5 seconds delay ReadAllKeyStrokes(); // empty the buffer again @@ -276,6 +341,11 @@ VOID PauseForKey(VOID) Print(L"\n"); } +// Pause a specified number of seconds +VOID PauseSeconds(UINTN Seconds) { + refit_call1_wrapper(BS->Stall, 1000000 * Seconds); +} // VOID PauseSeconds() + #if REFIT_DEBUG > 0 VOID DebugPause(VOID) { @@ -302,6 +372,7 @@ VOID EndlessIdleLoop(VOID) // Error handling // +#ifdef __MAKEWITH_GNUEFI BOOLEAN CheckFatalError(IN EFI_STATUS Status, IN CHAR16 *where) { CHAR16 ErrorName[64]; @@ -335,6 +406,37 @@ BOOLEAN CheckError(IN EFI_STATUS Status, IN CHAR16 *where) return TRUE; } +#else +BOOLEAN CheckFatalError(IN EFI_STATUS Status, IN CHAR16 *where) +{ +// CHAR16 ErrorName[64]; + + if (!EFI_ERROR(Status)) + return FALSE; + + gST->ConOut->SetAttribute (gST->ConOut, ATTR_ERROR); + Print(L"Fatal Error: %r %s\n", Status, where); + gST->ConOut->SetAttribute (gST->ConOut, ATTR_BASIC); + haveError = TRUE; + + //gBS->Exit(ImageHandle, ExitStatus, ExitDataSize, ExitData); + + return TRUE; +} + +BOOLEAN CheckError(IN EFI_STATUS Status, IN CHAR16 *where) +{ + if (!EFI_ERROR(Status)) + return FALSE; + + gST->ConOut->SetAttribute (gST->ConOut, ATTR_ERROR); + Print(L"Error: %r %s\n", Status, where); + gST->ConOut->SetAttribute (gST->ConOut, ATTR_BASIC); + haveError = TRUE; + + return TRUE; +} +#endif // // Graphics functions @@ -347,34 +449,64 @@ VOID SwitchToGraphicsAndClear(VOID) BltClearScreen(TRUE); } -VOID BltClearScreen(IN BOOLEAN ShowBanner) +VOID BltClearScreen(BOOLEAN ShowBanner) { static EG_IMAGE *Banner = NULL; + EG_IMAGE *NewBanner = NULL; + INTN BannerPosX, BannerPosY; + EG_PIXEL Black = { 0x0, 0x0, 0x0, 0 }; if (ShowBanner && !(GlobalConfig.HideUIFlags & HIDEUI_FLAG_BANNER)) { // load banner on first call if (Banner == NULL) { - if (GlobalConfig.BannerFileName == NULL) - Banner = egPrepareEmbeddedImage(&egemb_refind_banner, FALSE); - else + if (GlobalConfig.BannerFileName) Banner = egLoadImage(SelfDir, GlobalConfig.BannerFileName, FALSE); - if (Banner != NULL) - MenuBackgroundPixel = Banner->PixelData[0]; + if (Banner == NULL) + Banner = egPrepareEmbeddedImage(&egemb_refind_banner, FALSE); } + if (Banner) { + if (GlobalConfig.BannerScale == BANNER_FILLSCREEN) { + if ((Banner->Height != UGAHeight) || (Banner->Width != UGAWidth)) { + NewBanner = egScaleImage(Banner, UGAWidth, UGAHeight); + } // if + } else if ((Banner->Width > UGAWidth) || (Banner->Height > UGAHeight)) { + NewBanner = egCropImage(Banner, 0, 0, (Banner->Width > UGAWidth) ? UGAWidth : Banner->Width, + (Banner->Height > UGAHeight) ? UGAHeight : Banner->Height); + } // if/elseif + if (NewBanner) { + MyFreePool(Banner); + Banner = NewBanner; + } + MenuBackgroundPixel = Banner->PixelData[0]; + } // if Banner exists + // clear and draw banner - egClearScreen(&MenuBackgroundPixel); - if (Banner != NULL) - BltImage(Banner, (UGAWidth - Banner->Width) >> 1, - ((UGAHeight - LAYOUT_TOTAL_HEIGHT) >> 1) + LAYOUT_BANNER_HEIGHT - Banner->Height); + if (GlobalConfig.ScreensaverTime != -1) + egClearScreen(&MenuBackgroundPixel); + else + egClearScreen(&Black); + + if (Banner != NULL) { + BannerPosX = (Banner->Width < UGAWidth) ? ((UGAWidth - Banner->Width) / 2) : 0; + BannerPosY = (INTN) (ComputeRow0PosY() / 2) - (INTN) Banner->Height; + if (BannerPosY < 0) + BannerPosY = 0; + GlobalConfig.BannerBottomEdge = BannerPosY + Banner->Height; + if (GlobalConfig.ScreensaverTime != -1) + BltImage(Banner, (UINTN) BannerPosX, (UINTN) BannerPosY); + } - } else { - // clear to standard background color - egClearScreen(&StdBackgroundPixel); + } else { // not showing banner + // clear to menu background color + egClearScreen(&MenuBackgroundPixel); } GraphicsScreenDirty = FALSE; -} + egFreeImage(GlobalConfig.ScreenBackground); + GlobalConfig.ScreenBackground = egCopyScreen(); +} // VOID BltClearScreen() + VOID BltImage(IN EG_IMAGE *Image, IN UINTN XPos, IN UINTN YPos) { @@ -385,11 +517,11 @@ VOID BltImage(IN EG_IMAGE *Image, IN UINTN XPos, IN UINTN YPos) VOID BltImageAlpha(IN EG_IMAGE *Image, IN UINTN XPos, IN UINTN YPos, IN EG_PIXEL *BackgroundPixel) { EG_IMAGE *CompImage; - + // compose on background CompImage = egCreateFilledImage(Image->Width, Image->Height, FALSE, BackgroundPixel); egComposeImage(CompImage, Image, 0, 0); - + // blit to screen and clean up egDrawImage(CompImage, XPos, YPos); egFreeImage(CompImage); @@ -416,7 +548,7 @@ VOID BltImageAlpha(IN EG_IMAGE *Image, IN UINTN XPos, IN UINTN YPos, IN EG_PIXEL // CompHeight = TotalHeight; // OffsetY = (TotalHeight - CompHeight) >> 1; // egComposeImage(CompImage, TopImage, OffsetX, OffsetY); -// +// // // blit to screen and clean up // egDrawImage(CompImage, XPos, YPos); // egFreeImage(CompImage); @@ -425,7 +557,7 @@ VOID BltImageAlpha(IN EG_IMAGE *Image, IN UINTN XPos, IN UINTN YPos, IN EG_PIXEL VOID BltImageCompositeBadge(IN EG_IMAGE *BaseImage, IN EG_IMAGE *TopImage, IN EG_IMAGE *BadgeImage, IN UINTN XPos, IN UINTN YPos) { - UINTN TotalWidth, TotalHeight, CompWidth = 0, CompHeight = 0, OffsetX = 0, OffsetY = 0; + UINTN TotalWidth = 0, TotalHeight = 0, CompWidth = 0, CompHeight = 0, OffsetX = 0, OffsetY = 0; EG_IMAGE *CompImage = NULL; // initialize buffer with base image @@ -447,7 +579,7 @@ VOID BltImageCompositeBadge(IN EG_IMAGE *BaseImage, IN EG_IMAGE *TopImage, IN EG OffsetY = (TotalHeight - CompHeight) >> 1; egComposeImage(CompImage, TopImage, OffsetX, OffsetY); } - + // place the badge image if (BadgeImage != NULL && CompImage != NULL && (BadgeImage->Width + 8) < CompWidth && (BadgeImage->Height + 8) < CompHeight) { OffsetX += CompWidth - 8 - BadgeImage->Width; @@ -456,7 +588,12 @@ VOID BltImageCompositeBadge(IN EG_IMAGE *BaseImage, IN EG_IMAGE *TopImage, IN EG } // blit to screen and clean up - egDrawImage(CompImage, XPos, YPos); - egFreeImage(CompImage); - GraphicsScreenDirty = TRUE; + if (CompImage != NULL) { + if (CompImage->HasAlpha) + egDrawImageWithTransparency(CompImage, NULL, XPos, YPos, CompImage->Width, CompImage->Height); + else + egDrawImage(CompImage, XPos, YPos); + egFreeImage(CompImage); + GraphicsScreenDirty = TRUE; + } }