| /** @file | |
| FrameBufferBltLib - Library to perform blt operations on a frame buffer. | |
| Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #include <Uefi/UefiBaseType.h> | |
| #include <Protocol/GraphicsOutput.h> | |
| #include <Library/BaseLib.h> | |
| #include <Library/BaseMemoryLib.h> | |
| #include <Library/DebugLib.h> | |
| #include <Library/FrameBufferBltLib.h> | |
| struct FRAME_BUFFER_CONFIGURE { | |
| UINT32 PixelsPerScanLine; | |
| UINT32 BytesPerPixel; | |
| UINT32 Width; | |
| UINT32 Height; | |
| UINT8 *FrameBuffer; | |
| EFI_GRAPHICS_PIXEL_FORMAT PixelFormat; | |
| EFI_PIXEL_BITMASK PixelMasks; | |
| INT8 PixelShl[4]; // R-G-B-Rsvd | |
| INT8 PixelShr[4]; // R-G-B-Rsvd | |
| UINT8 LineBuffer[0]; | |
| }; | |
| CONST EFI_PIXEL_BITMASK mRgbPixelMasks = { | |
| 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 | |
| }; | |
| CONST EFI_PIXEL_BITMASK mBgrPixelMasks = { | |
| 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 | |
| }; | |
| /** | |
| Initialize the bit mask in frame buffer configure. | |
| @param BitMask The bit mask of pixel. | |
| @param BytesPerPixel Size in bytes of pixel. | |
| @param PixelShl Left shift array. | |
| @param PixelShr Right shift array. | |
| **/ | |
| VOID | |
| FrameBufferBltLibConfigurePixelFormat ( | |
| IN CONST EFI_PIXEL_BITMASK *BitMask, | |
| OUT UINT32 *BytesPerPixel, | |
| OUT INT8 *PixelShl, | |
| OUT INT8 *PixelShr | |
| ) | |
| { | |
| UINT8 Index; | |
| UINT32 *Masks; | |
| UINT32 MergedMasks; | |
| ASSERT (BytesPerPixel != NULL); | |
| MergedMasks = 0; | |
| Masks = (UINT32 *)BitMask; | |
| for (Index = 0; Index < 3; Index++) { | |
| ASSERT ((MergedMasks & Masks[Index]) == 0); | |
| PixelShl[Index] = (INT8)HighBitSet32 (Masks[Index]) - 23 + (Index * 8); | |
| if (PixelShl[Index] < 0) { | |
| PixelShr[Index] = -PixelShl[Index]; | |
| PixelShl[Index] = 0; | |
| } else { | |
| PixelShr[Index] = 0; | |
| } | |
| DEBUG (( | |
| DEBUG_INFO, | |
| "%d: shl:%d shr:%d mask:%x\n", | |
| Index, | |
| PixelShl[Index], | |
| PixelShr[Index], | |
| Masks[Index] | |
| )); | |
| MergedMasks = (UINT32)(MergedMasks | Masks[Index]); | |
| } | |
| MergedMasks = (UINT32)(MergedMasks | Masks[3]); | |
| ASSERT (MergedMasks != 0); | |
| *BytesPerPixel = (UINT32)((HighBitSet32 (MergedMasks) + 7) / 8); | |
| DEBUG ((DEBUG_INFO, "Bytes per pixel: %d\n", *BytesPerPixel)); | |
| } | |
| /** | |
| Create the configuration for a video frame buffer. | |
| The configuration is returned in the caller provided buffer. | |
| @param[in] FrameBuffer Pointer to the start of the frame buffer. | |
| @param[in] FrameBufferInfo Describes the frame buffer characteristics. | |
| @param[in,out] Configure The created configuration information. | |
| @param[in,out] ConfigureSize Size of the configuration information. | |
| @retval RETURN_SUCCESS The configuration was successful created. | |
| @retval RETURN_BUFFER_TOO_SMALL The Configure is to too small. The required | |
| size is returned in ConfigureSize. | |
| @retval RETURN_UNSUPPORTED The requested mode is not supported by | |
| this implementaion. | |
| **/ | |
| RETURN_STATUS | |
| EFIAPI | |
| FrameBufferBltConfigure ( | |
| IN VOID *FrameBuffer, | |
| IN EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *FrameBufferInfo, | |
| IN OUT FRAME_BUFFER_CONFIGURE *Configure, | |
| IN OUT UINTN *ConfigureSize | |
| ) | |
| { | |
| CONST EFI_PIXEL_BITMASK *BitMask; | |
| UINT32 BytesPerPixel; | |
| INT8 PixelShl[4]; | |
| INT8 PixelShr[4]; | |
| if (ConfigureSize == NULL) { | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| switch (FrameBufferInfo->PixelFormat) { | |
| case PixelRedGreenBlueReserved8BitPerColor: | |
| BitMask = &mRgbPixelMasks; | |
| break; | |
| case PixelBlueGreenRedReserved8BitPerColor: | |
| BitMask = &mBgrPixelMasks; | |
| break; | |
| case PixelBitMask: | |
| BitMask = &FrameBufferInfo->PixelInformation; | |
| break; | |
| case PixelBltOnly: | |
| ASSERT (FrameBufferInfo->PixelFormat != PixelBltOnly); | |
| return RETURN_UNSUPPORTED; | |
| default: | |
| ASSERT (FALSE); | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| if (FrameBufferInfo->PixelsPerScanLine < FrameBufferInfo->HorizontalResolution) { | |
| return RETURN_UNSUPPORTED; | |
| } | |
| FrameBufferBltLibConfigurePixelFormat (BitMask, &BytesPerPixel, PixelShl, PixelShr); | |
| if (*ConfigureSize < sizeof (FRAME_BUFFER_CONFIGURE) | |
| + FrameBufferInfo->HorizontalResolution * BytesPerPixel) | |
| { | |
| *ConfigureSize = sizeof (FRAME_BUFFER_CONFIGURE) | |
| + FrameBufferInfo->HorizontalResolution * BytesPerPixel; | |
| return RETURN_BUFFER_TOO_SMALL; | |
| } | |
| if (Configure == NULL) { | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| CopyMem (&Configure->PixelMasks, BitMask, sizeof (*BitMask)); | |
| CopyMem (Configure->PixelShl, PixelShl, sizeof (PixelShl)); | |
| CopyMem (Configure->PixelShr, PixelShr, sizeof (PixelShr)); | |
| Configure->BytesPerPixel = BytesPerPixel; | |
| Configure->PixelFormat = FrameBufferInfo->PixelFormat; | |
| Configure->FrameBuffer = (UINT8 *)FrameBuffer; | |
| Configure->Width = FrameBufferInfo->HorizontalResolution; | |
| Configure->Height = FrameBufferInfo->VerticalResolution; | |
| Configure->PixelsPerScanLine = FrameBufferInfo->PixelsPerScanLine; | |
| return RETURN_SUCCESS; | |
| } | |
| /** | |
| Performs a UEFI Graphics Output Protocol Blt Video Fill. | |
| @param[in] Configure Pointer to a configuration which was successfully | |
| created by FrameBufferBltConfigure (). | |
| @param[in] Color Color to fill the region with. | |
| @param[in] DestinationX X location to start fill operation. | |
| @param[in] DestinationY Y location to start fill operation. | |
| @param[in] Width Width (in pixels) to fill. | |
| @param[in] Height Height to fill. | |
| @retval RETURN_INVALID_PARAMETER Invalid parameter was passed in. | |
| @retval RETURN_SUCCESS The video was filled successfully. | |
| **/ | |
| EFI_STATUS | |
| FrameBufferBltLibVideoFill ( | |
| IN FRAME_BUFFER_CONFIGURE *Configure, | |
| IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Color, | |
| IN UINTN DestinationX, | |
| IN UINTN DestinationY, | |
| IN UINTN Width, | |
| IN UINTN Height | |
| ) | |
| { | |
| UINTN IndexX; | |
| UINTN IndexY; | |
| UINT8 *Destination; | |
| UINT8 Uint8; | |
| UINT32 Uint32; | |
| UINT64 WideFill; | |
| BOOLEAN UseWideFill; | |
| BOOLEAN LineBufferReady; | |
| UINTN Offset; | |
| UINTN WidthInBytes; | |
| UINTN SizeInBytes; | |
| // | |
| // BltBuffer to Video: Source is BltBuffer, destination is Video | |
| // | |
| if (DestinationY + Height > Configure->Height) { | |
| DEBUG ((DEBUG_VERBOSE, "VideoFill: Past screen (Y)\n")); | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| if (DestinationX + Width > Configure->Width) { | |
| DEBUG ((DEBUG_VERBOSE, "VideoFill: Past screen (X)\n")); | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| if ((Width == 0) || (Height == 0)) { | |
| DEBUG ((DEBUG_VERBOSE, "VideoFill: Width or Height is 0\n")); | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| WidthInBytes = Width * Configure->BytesPerPixel; | |
| Uint32 = *(UINT32 *)Color; | |
| WideFill = | |
| (UINT32)( | |
| (((Uint32 << Configure->PixelShl[0]) >> Configure->PixelShr[0]) & | |
| Configure->PixelMasks.RedMask) | | |
| (((Uint32 << Configure->PixelShl[1]) >> Configure->PixelShr[1]) & | |
| Configure->PixelMasks.GreenMask) | | |
| (((Uint32 << Configure->PixelShl[2]) >> Configure->PixelShr[2]) & | |
| Configure->PixelMasks.BlueMask) | |
| ); | |
| DEBUG (( | |
| DEBUG_VERBOSE, | |
| "VideoFill: color=0x%x, wide-fill=0x%x\n", | |
| Uint32, | |
| WideFill | |
| )); | |
| // | |
| // If the size of the pixel data evenly divides the sizeof | |
| // WideFill, then a wide fill operation can be used | |
| // | |
| UseWideFill = TRUE; | |
| if ((sizeof (WideFill) % Configure->BytesPerPixel) == 0) { | |
| for (IndexX = Configure->BytesPerPixel; IndexX < sizeof (WideFill); IndexX++) { | |
| ((UINT8 *)&WideFill)[IndexX] = ((UINT8 *)&WideFill)[IndexX % Configure->BytesPerPixel]; | |
| } | |
| } else { | |
| // | |
| // If all the bytes in the pixel are the same value, then use | |
| // a wide fill operation. | |
| // | |
| for ( | |
| IndexX = 1, Uint8 = ((UINT8 *)&WideFill)[0]; | |
| IndexX < Configure->BytesPerPixel; | |
| IndexX++) | |
| { | |
| if (Uint8 != ((UINT8 *)&WideFill)[IndexX]) { | |
| UseWideFill = FALSE; | |
| break; | |
| } | |
| } | |
| if (UseWideFill) { | |
| SetMem (&WideFill, sizeof (WideFill), Uint8); | |
| } | |
| } | |
| if (UseWideFill && (DestinationX == 0) && (Width == Configure->PixelsPerScanLine)) { | |
| DEBUG ((DEBUG_VERBOSE, "VideoFill (wide, one-shot)\n")); | |
| Offset = DestinationY * Configure->PixelsPerScanLine; | |
| Offset = Configure->BytesPerPixel * Offset; | |
| Destination = Configure->FrameBuffer + Offset; | |
| SizeInBytes = WidthInBytes * Height; | |
| if (SizeInBytes >= 8) { | |
| SetMem32 (Destination, SizeInBytes & ~3, (UINT32)WideFill); | |
| Destination += SizeInBytes & ~3; | |
| SizeInBytes &= 3; | |
| } | |
| if (SizeInBytes > 0) { | |
| SetMem (Destination, SizeInBytes, (UINT8)(UINTN)WideFill); | |
| } | |
| } else { | |
| LineBufferReady = FALSE; | |
| for (IndexY = DestinationY; IndexY < (Height + DestinationY); IndexY++) { | |
| Offset = (IndexY * Configure->PixelsPerScanLine) + DestinationX; | |
| Offset = Configure->BytesPerPixel * Offset; | |
| Destination = Configure->FrameBuffer + Offset; | |
| if (UseWideFill && (((UINTN)Destination & 7) == 0)) { | |
| DEBUG ((DEBUG_VERBOSE, "VideoFill (wide)\n")); | |
| SizeInBytes = WidthInBytes; | |
| if (SizeInBytes >= 8) { | |
| SetMem64 (Destination, SizeInBytes & ~7, WideFill); | |
| Destination += SizeInBytes & ~7; | |
| SizeInBytes &= 7; | |
| } | |
| if (SizeInBytes > 0) { | |
| CopyMem (Destination, &WideFill, SizeInBytes); | |
| } | |
| } else { | |
| DEBUG ((DEBUG_VERBOSE, "VideoFill (not wide)\n")); | |
| if (!LineBufferReady) { | |
| CopyMem (Configure->LineBuffer, &WideFill, Configure->BytesPerPixel); | |
| for (IndexX = 1; IndexX < Width; ) { | |
| CopyMem ( | |
| (Configure->LineBuffer + (IndexX * Configure->BytesPerPixel)), | |
| Configure->LineBuffer, | |
| MIN (IndexX, Width - IndexX) * Configure->BytesPerPixel | |
| ); | |
| IndexX += MIN (IndexX, Width - IndexX); | |
| } | |
| LineBufferReady = TRUE; | |
| } | |
| CopyMem (Destination, Configure->LineBuffer, WidthInBytes); | |
| } | |
| } | |
| } | |
| return RETURN_SUCCESS; | |
| } | |
| /** | |
| Performs a UEFI Graphics Output Protocol Blt Video to Buffer operation | |
| with extended parameters. | |
| @param[in] Configure Pointer to a configuration which was successfully | |
| created by FrameBufferBltConfigure (). | |
| @param[out] BltBuffer Output buffer for pixel color data. | |
| @param[in] SourceX X location within video. | |
| @param[in] SourceY Y location within video. | |
| @param[in] DestinationX X location within BltBuffer. | |
| @param[in] DestinationY Y location within BltBuffer. | |
| @param[in] Width Width (in pixels). | |
| @param[in] Height Height. | |
| @param[in] Delta Number of bytes in a row of BltBuffer. | |
| @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in. | |
| @retval RETURN_SUCCESS The Blt operation was performed successfully. | |
| **/ | |
| RETURN_STATUS | |
| FrameBufferBltLibVideoToBltBuffer ( | |
| IN FRAME_BUFFER_CONFIGURE *Configure, | |
| OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, | |
| IN UINTN SourceX, | |
| IN UINTN SourceY, | |
| IN UINTN DestinationX, | |
| IN UINTN DestinationY, | |
| IN UINTN Width, | |
| IN UINTN Height, | |
| IN UINTN Delta | |
| ) | |
| { | |
| UINTN DstY; | |
| UINTN SrcY; | |
| EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt; | |
| UINT8 *Source; | |
| UINT8 *Destination; | |
| UINTN IndexX; | |
| UINT32 Uint32; | |
| UINTN Offset; | |
| UINTN WidthInBytes; | |
| // | |
| // Video to BltBuffer: Source is Video, destination is BltBuffer | |
| // | |
| if (SourceY + Height > Configure->Height) { | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| if (SourceX + Width > Configure->Width) { | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| if ((Width == 0) || (Height == 0)) { | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| // | |
| // If Delta is zero, then the entire BltBuffer is being used, so Delta is | |
| // the number of bytes in each row of BltBuffer. Since BltBuffer is Width | |
| // pixels size, the number of bytes in each row can be computed. | |
| // | |
| if (Delta == 0) { | |
| Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); | |
| } | |
| WidthInBytes = Width * Configure->BytesPerPixel; | |
| // | |
| // Video to BltBuffer: Source is Video, destination is BltBuffer | |
| // | |
| for (SrcY = SourceY, DstY = DestinationY; | |
| DstY < (Height + DestinationY); | |
| SrcY++, DstY++) | |
| { | |
| Offset = (SrcY * Configure->PixelsPerScanLine) + SourceX; | |
| Offset = Configure->BytesPerPixel * Offset; | |
| Source = Configure->FrameBuffer + Offset; | |
| if (Configure->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) { | |
| Destination = (UINT8 *)BltBuffer + (DstY * Delta) + (DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); | |
| } else { | |
| Destination = Configure->LineBuffer; | |
| } | |
| CopyMem (Destination, Source, WidthInBytes); | |
| if (Configure->PixelFormat != PixelBlueGreenRedReserved8BitPerColor) { | |
| for (IndexX = 0; IndexX < Width; IndexX++) { | |
| Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) | |
| ((UINT8 *)BltBuffer + (DstY * Delta) + | |
| (DestinationX + IndexX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); | |
| Uint32 = *(UINT32 *)(Configure->LineBuffer + (IndexX * Configure->BytesPerPixel)); | |
| *(UINT32 *)Blt = | |
| (UINT32)( | |
| (((Uint32 & Configure->PixelMasks.RedMask) >> | |
| Configure->PixelShl[0]) << Configure->PixelShr[0]) | | |
| (((Uint32 & Configure->PixelMasks.GreenMask) >> | |
| Configure->PixelShl[1]) << Configure->PixelShr[1]) | | |
| (((Uint32 & Configure->PixelMasks.BlueMask) >> | |
| Configure->PixelShl[2]) << Configure->PixelShr[2]) | |
| ); | |
| } | |
| } | |
| } | |
| return RETURN_SUCCESS; | |
| } | |
| /** | |
| Performs a UEFI Graphics Output Protocol Blt Buffer to Video operation | |
| with extended parameters. | |
| @param[in] Configure Pointer to a configuration which was successfully | |
| created by FrameBufferBltConfigure (). | |
| @param[in] BltBuffer Output buffer for pixel color data. | |
| @param[in] SourceX X location within BltBuffer. | |
| @param[in] SourceY Y location within BltBuffer. | |
| @param[in] DestinationX X location within video. | |
| @param[in] DestinationY Y location within video. | |
| @param[in] Width Width (in pixels). | |
| @param[in] Height Height. | |
| @param[in] Delta Number of bytes in a row of BltBuffer. | |
| @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in. | |
| @retval RETURN_SUCCESS The Blt operation was performed successfully. | |
| **/ | |
| RETURN_STATUS | |
| FrameBufferBltLibBufferToVideo ( | |
| IN FRAME_BUFFER_CONFIGURE *Configure, | |
| IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, | |
| IN UINTN SourceX, | |
| IN UINTN SourceY, | |
| IN UINTN DestinationX, | |
| IN UINTN DestinationY, | |
| IN UINTN Width, | |
| IN UINTN Height, | |
| IN UINTN Delta | |
| ) | |
| { | |
| UINTN DstY; | |
| UINTN SrcY; | |
| EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt; | |
| UINT8 *Source; | |
| UINT8 *Destination; | |
| UINTN IndexX; | |
| UINT32 Uint32; | |
| UINTN Offset; | |
| UINTN WidthInBytes; | |
| // | |
| // BltBuffer to Video: Source is BltBuffer, destination is Video | |
| // | |
| if (DestinationY + Height > Configure->Height) { | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| if (DestinationX + Width > Configure->Width) { | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| if ((Width == 0) || (Height == 0)) { | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| // | |
| // If Delta is zero, then the entire BltBuffer is being used, so Delta is | |
| // the number of bytes in each row of BltBuffer. Since BltBuffer is Width | |
| // pixels size, the number of bytes in each row can be computed. | |
| // | |
| if (Delta == 0) { | |
| Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); | |
| } | |
| WidthInBytes = Width * Configure->BytesPerPixel; | |
| for (SrcY = SourceY, DstY = DestinationY; | |
| SrcY < (Height + SourceY); | |
| SrcY++, DstY++) | |
| { | |
| Offset = (DstY * Configure->PixelsPerScanLine) + DestinationX; | |
| Offset = Configure->BytesPerPixel * Offset; | |
| Destination = Configure->FrameBuffer + Offset; | |
| if (Configure->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) { | |
| Source = (UINT8 *)BltBuffer + (SrcY * Delta) + SourceX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); | |
| } else { | |
| for (IndexX = 0; IndexX < Width; IndexX++) { | |
| Blt = | |
| (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)( | |
| (UINT8 *)BltBuffer + | |
| (SrcY * Delta) + | |
| ((SourceX + IndexX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) | |
| ); | |
| Uint32 = *(UINT32 *)Blt; | |
| *(UINT32 *)(Configure->LineBuffer + (IndexX * Configure->BytesPerPixel)) = | |
| (UINT32)( | |
| (((Uint32 << Configure->PixelShl[0]) >> Configure->PixelShr[0]) & | |
| Configure->PixelMasks.RedMask) | | |
| (((Uint32 << Configure->PixelShl[1]) >> Configure->PixelShr[1]) & | |
| Configure->PixelMasks.GreenMask) | | |
| (((Uint32 << Configure->PixelShl[2]) >> Configure->PixelShr[2]) & | |
| Configure->PixelMasks.BlueMask) | |
| ); | |
| } | |
| Source = Configure->LineBuffer; | |
| } | |
| CopyMem (Destination, Source, WidthInBytes); | |
| } | |
| return RETURN_SUCCESS; | |
| } | |
| /** | |
| Performs a UEFI Graphics Output Protocol Blt Video to Video operation | |
| @param[in] Configure Pointer to a configuration which was successfully | |
| created by FrameBufferBltConfigure (). | |
| @param[in] SourceX X location within video. | |
| @param[in] SourceY Y location within video. | |
| @param[in] DestinationX X location within video. | |
| @param[in] DestinationY Y location within video. | |
| @param[in] Width Width (in pixels). | |
| @param[in] Height Height. | |
| @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in. | |
| @retval RETURN_SUCCESS The Blt operation was performed successfully. | |
| **/ | |
| RETURN_STATUS | |
| FrameBufferBltLibVideoToVideo ( | |
| IN FRAME_BUFFER_CONFIGURE *Configure, | |
| IN UINTN SourceX, | |
| IN UINTN SourceY, | |
| IN UINTN DestinationX, | |
| IN UINTN DestinationY, | |
| IN UINTN Width, | |
| IN UINTN Height | |
| ) | |
| { | |
| UINT8 *Source; | |
| UINT8 *Destination; | |
| UINTN Offset; | |
| UINTN WidthInBytes; | |
| INTN LineStride; | |
| // | |
| // Video to Video: Source is Video, destination is Video | |
| // | |
| if (SourceY + Height > Configure->Height) { | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| if (SourceX + Width > Configure->Width) { | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| if (DestinationY + Height > Configure->Height) { | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| if (DestinationX + Width > Configure->Width) { | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| if ((Width == 0) || (Height == 0)) { | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| WidthInBytes = Width * Configure->BytesPerPixel; | |
| Offset = (SourceY * Configure->PixelsPerScanLine) + SourceX; | |
| Offset = Configure->BytesPerPixel * Offset; | |
| Source = Configure->FrameBuffer + Offset; | |
| Offset = (DestinationY * Configure->PixelsPerScanLine) + DestinationX; | |
| Offset = Configure->BytesPerPixel * Offset; | |
| Destination = Configure->FrameBuffer + Offset; | |
| LineStride = Configure->BytesPerPixel * Configure->PixelsPerScanLine; | |
| if (Destination > Source) { | |
| // | |
| // Copy from last line to avoid source is corrupted by copying | |
| // | |
| Source += Height * LineStride; | |
| Destination += Height * LineStride; | |
| LineStride = -LineStride; | |
| } | |
| while (Height-- > 0) { | |
| CopyMem (Destination, Source, WidthInBytes); | |
| Source += LineStride; | |
| Destination += LineStride; | |
| } | |
| return RETURN_SUCCESS; | |
| } | |
| /** | |
| Performs a UEFI Graphics Output Protocol Blt operation. | |
| @param[in] Configure Pointer to a configuration which was successfully | |
| created by FrameBufferBltConfigure (). | |
| @param[in,out] BltBuffer The data to transfer to screen. | |
| @param[in] BltOperation The operation to perform. | |
| @param[in] SourceX The X coordinate of the source for BltOperation. | |
| @param[in] SourceY The Y coordinate of the source for BltOperation. | |
| @param[in] DestinationX The X coordinate of the destination for | |
| BltOperation. | |
| @param[in] DestinationY The Y coordinate of the destination for | |
| BltOperation. | |
| @param[in] Width The width of a rectangle in the blt rectangle | |
| in pixels. | |
| @param[in] Height The height of a rectangle in the blt rectangle | |
| in pixels. | |
| @param[in] Delta Not used for EfiBltVideoFill and | |
| EfiBltVideoToVideo operation. If a Delta of 0 | |
| is used, the entire BltBuffer will be operated | |
| on. If a subrectangle of the BltBuffer is | |
| used, then Delta represents the number of | |
| bytes in a row of the BltBuffer. | |
| @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in. | |
| @retval RETURN_SUCCESS The Blt operation was performed successfully. | |
| **/ | |
| RETURN_STATUS | |
| EFIAPI | |
| FrameBufferBlt ( | |
| IN FRAME_BUFFER_CONFIGURE *Configure, | |
| IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL, | |
| IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, | |
| IN UINTN SourceX, | |
| IN UINTN SourceY, | |
| IN UINTN DestinationX, | |
| IN UINTN DestinationY, | |
| IN UINTN Width, | |
| IN UINTN Height, | |
| IN UINTN Delta | |
| ) | |
| { | |
| if (Configure == NULL) { | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| switch (BltOperation) { | |
| case EfiBltVideoToBltBuffer: | |
| return FrameBufferBltLibVideoToBltBuffer ( | |
| Configure, | |
| BltBuffer, | |
| SourceX, | |
| SourceY, | |
| DestinationX, | |
| DestinationY, | |
| Width, | |
| Height, | |
| Delta | |
| ); | |
| case EfiBltVideoToVideo: | |
| return FrameBufferBltLibVideoToVideo ( | |
| Configure, | |
| SourceX, | |
| SourceY, | |
| DestinationX, | |
| DestinationY, | |
| Width, | |
| Height | |
| ); | |
| case EfiBltVideoFill: | |
| return FrameBufferBltLibVideoFill ( | |
| Configure, | |
| BltBuffer, | |
| DestinationX, | |
| DestinationY, | |
| Width, | |
| Height | |
| ); | |
| case EfiBltBufferToVideo: | |
| return FrameBufferBltLibBufferToVideo ( | |
| Configure, | |
| BltBuffer, | |
| SourceX, | |
| SourceY, | |
| DestinationX, | |
| DestinationY, | |
| Width, | |
| Height, | |
| Delta | |
| ); | |
| default: | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| } |