mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-31 03:03:46 +01:00 
			
		
		
		
	This library provides interfaces to perform UEFI Graphics Output Protocol Video BLT operations. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Reviewed-by: Feng Tian <feng.tian@intel.com> Cc: Justen Jordan <jordan.l.justen@intel.com> Tested-by: Laszlo Ersek <lersek at redhat.com>
		
			
				
	
	
		
			705 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			705 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   FrameBufferBltLib - Library to perform blt operations on a frame buffer.
 | |
| 
 | |
|   Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
 | |
|   This program and the accompanying materials
 | |
|   are licensed and made available under the terms and conditions of the BSD License
 | |
|   which accompanies this distribution.  The full text of the license may be found at
 | |
|   http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #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 {
 | |
|   UINTN                           ColorDepth;
 | |
|   UINTN                           WidthInBytes;
 | |
|   UINTN                           BytesPerPixel;
 | |
|   UINTN                           WidthInPixels;
 | |
|   UINTN                           Height;
 | |
|   UINT8                           LineBuffer[SIZE_4KB * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)];
 | |
|   UINT8                           *FrameBuffer;
 | |
|   EFI_GRAPHICS_PIXEL_FORMAT       PixelFormat;
 | |
|   EFI_PIXEL_BITMASK               PixelMasks;
 | |
|   INTN                            PixelShl[4]; // R-G-B-Rsvd
 | |
|   INTN                            PixelShr[4]; // R-G-B-Rsvd
 | |
| };
 | |
| 
 | |
| 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 Configure  The frame buffer configure.
 | |
|   @param BitMask    The bit mask of pixel.
 | |
| **/
 | |
| VOID
 | |
| ConfigurePixelBitMaskFormat (
 | |
|   IN FRAME_BUFFER_CONFIGURE     *Configure,
 | |
|   IN CONST EFI_PIXEL_BITMASK    *BitMask
 | |
|   )
 | |
| {
 | |
|   UINTN   Loop;
 | |
|   UINT32  *Masks;
 | |
|   UINT32  MergedMasks;
 | |
| 
 | |
|   MergedMasks = 0;
 | |
|   Masks = (UINT32*) BitMask;
 | |
|   for (Loop = 0; Loop < 3; Loop++) {
 | |
|     ASSERT ((Loop == 3) || (Masks[Loop] != 0));
 | |
|     ASSERT ((MergedMasks & Masks[Loop]) == 0);
 | |
|     Configure->PixelShl[Loop] = HighBitSet32 (Masks[Loop]) - 23 + (Loop * 8);
 | |
|     if (Configure->PixelShl[Loop] < 0) {
 | |
|       Configure->PixelShr[Loop] = -Configure->PixelShl[Loop];
 | |
|       Configure->PixelShl[Loop] = 0;
 | |
|     } else {
 | |
|       Configure->PixelShr[Loop] = 0;
 | |
|     }
 | |
|     MergedMasks = (UINT32) (MergedMasks | Masks[Loop]);
 | |
|     DEBUG ((EFI_D_VERBOSE, "%d: shl:%d shr:%d mask:%x\n", Loop,
 | |
|             Configure->PixelShl[Loop], Configure->PixelShr[Loop], Masks[Loop]));
 | |
|   }
 | |
|   MergedMasks = (UINT32) (MergedMasks | Masks[3]);
 | |
| 
 | |
|   ASSERT (MergedMasks != 0);
 | |
|   Configure->BytesPerPixel = (UINTN) ((HighBitSet32 (MergedMasks) + 7) / 8);
 | |
| 
 | |
|   DEBUG ((EFI_D_VERBOSE, "Bytes per pixel: %d\n", Configure->BytesPerPixel));
 | |
| 
 | |
|   CopyMem (&Configure->PixelMasks, BitMask, sizeof (*BitMask));
 | |
| }
 | |
| 
 | |
| /**
 | |
|   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
 | |
|   )
 | |
| {
 | |
|   if (ConfigureSize == NULL) {
 | |
|     return RETURN_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (*ConfigureSize < sizeof (FRAME_BUFFER_CONFIGURE)) {
 | |
|     *ConfigureSize = sizeof (FRAME_BUFFER_CONFIGURE);
 | |
|     return RETURN_BUFFER_TOO_SMALL;
 | |
|   }
 | |
| 
 | |
|   if (Configure == NULL) {
 | |
|     return RETURN_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   switch (FrameBufferInfo->PixelFormat) {
 | |
|   case PixelRedGreenBlueReserved8BitPerColor:
 | |
|     ConfigurePixelBitMaskFormat (Configure, &mRgbPixelMasks);
 | |
|     break;
 | |
| 
 | |
|   case PixelBlueGreenRedReserved8BitPerColor:
 | |
|     ConfigurePixelBitMaskFormat (Configure, &mBgrPixelMasks);
 | |
|     break;
 | |
| 
 | |
|   case PixelBitMask:
 | |
|     ConfigurePixelBitMaskFormat (Configure, &(FrameBufferInfo->PixelInformation));
 | |
|     break;
 | |
| 
 | |
|   case PixelBltOnly:
 | |
|     ASSERT (FrameBufferInfo->PixelFormat != PixelBltOnly);
 | |
|     return RETURN_UNSUPPORTED;
 | |
| 
 | |
|   default:
 | |
|     ASSERT (FALSE);
 | |
|     return RETURN_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Configure->PixelFormat   = FrameBufferInfo->PixelFormat;
 | |
|   Configure->FrameBuffer   = (UINT8*) FrameBuffer;
 | |
|   Configure->WidthInPixels = (UINTN) FrameBufferInfo->HorizontalResolution;
 | |
|   Configure->Height        = (UINTN) FrameBufferInfo->VerticalResolution;
 | |
|   Configure->WidthInBytes  = Configure->WidthInPixels * Configure->BytesPerPixel;
 | |
| 
 | |
|   ASSERT (Configure->WidthInBytes < sizeof (Configure->LineBuffer));
 | |
| 
 | |
|   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 ((EFI_D_VERBOSE, "VideoFill: Past screen (Y)\n"));
 | |
|     return RETURN_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (DestinationX + Width > Configure->WidthInPixels) {
 | |
|     DEBUG ((EFI_D_VERBOSE, "VideoFill: Past screen (X)\n"));
 | |
|     return RETURN_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (Width == 0 || Height == 0) {
 | |
|     DEBUG ((EFI_D_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 ((EFI_D_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->WidthInPixels)) {
 | |
|     DEBUG ((EFI_D_VERBOSE, "VideoFill (wide, one-shot)\n"));
 | |
|     Offset = DestinationY * Configure->WidthInPixels;
 | |
|     Offset = Configure->BytesPerPixel * Offset;
 | |
|     Destination = Configure->FrameBuffer + Offset;
 | |
|     SizeInBytes = WidthInBytes * Height;
 | |
|     if (SizeInBytes >= 8) {
 | |
|       SetMem32 (Destination, SizeInBytes & ~3, (UINT32) WideFill);
 | |
|       SizeInBytes &= 3;
 | |
|     }
 | |
|     if (SizeInBytes > 0) {
 | |
|       SetMem (Destination, SizeInBytes, (UINT8) (UINTN) WideFill);
 | |
|     }
 | |
|   } else {
 | |
|     LineBufferReady = FALSE;
 | |
|     for (IndexY = DestinationY; IndexY < (Height + DestinationY); IndexY++) {
 | |
|       Offset = (IndexY * Configure->WidthInPixels) + DestinationX;
 | |
|       Offset = Configure->BytesPerPixel * Offset;
 | |
|       Destination = Configure->FrameBuffer + Offset;
 | |
| 
 | |
|       if (UseWideFill && (((UINTN) Destination & 7) == 0)) {
 | |
|         DEBUG ((EFI_D_VERBOSE, "VideoFill (wide)\n"));
 | |
|         SizeInBytes = WidthInBytes;
 | |
|         if (SizeInBytes >= 8) {
 | |
|           SetMem64 (Destination, SizeInBytes & ~7, WideFill);
 | |
|           SizeInBytes &= 7;
 | |
|         }
 | |
|         if (SizeInBytes > 0) {
 | |
|           CopyMem (Destination, &WideFill, SizeInBytes);
 | |
|         }
 | |
|       } else {
 | |
|         DEBUG ((EFI_D_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->WidthInPixels) {
 | |
|     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->WidthInPixels) + 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->WidthInPixels) {
 | |
|     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->WidthInPixels) + DestinationX;
 | |
|     Offset = Configure->BytesPerPixel * Offset;
 | |
|     Destination = Configure->FrameBuffer + Offset;
 | |
| 
 | |
|     if (Configure->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
 | |
|       Source = (UINT8 *) BltBuffer + (SrcY * Delta);
 | |
|     } 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->WidthInPixels) {
 | |
|     return RETURN_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (DestinationY + Height > Configure->Height) {
 | |
|     return RETURN_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (DestinationX + Width > Configure->WidthInPixels) {
 | |
|     return RETURN_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (Width == 0 || Height == 0) {
 | |
|     return RETURN_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   WidthInBytes = Width * Configure->BytesPerPixel;
 | |
| 
 | |
|   Offset = (SourceY * Configure->WidthInPixels) + SourceX;
 | |
|   Offset = Configure->BytesPerPixel * Offset;
 | |
|   Source = Configure->FrameBuffer + Offset;
 | |
| 
 | |
|   Offset = (DestinationY * Configure->WidthInPixels) + DestinationX;
 | |
|   Offset = Configure->BytesPerPixel * Offset;
 | |
|   Destination = Configure->FrameBuffer + Offset;
 | |
| 
 | |
|   LineStride = Configure->WidthInBytes;
 | |
|   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;
 | |
|   }
 | |
| }
 |