Home | History | Annotate | Download | only in FrameBufferBltLib
      1 /** @file
      2   FrameBufferBltLib - Library to perform blt operations on a frame buffer.
      3 
      4   Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include <Uefi/UefiBaseType.h>
     16 #include <Protocol/GraphicsOutput.h>
     17 
     18 #include <Library/BaseLib.h>
     19 #include <Library/BaseMemoryLib.h>
     20 #include <Library/DebugLib.h>
     21 #include <Library/FrameBufferBltLib.h>
     22 
     23 struct FRAME_BUFFER_CONFIGURE {
     24   UINTN                           ColorDepth;
     25   UINTN                           WidthInBytes;
     26   UINTN                           BytesPerPixel;
     27   UINTN                           WidthInPixels;
     28   UINTN                           Height;
     29   UINT8                           LineBuffer[SIZE_4KB * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)];
     30   UINT8                           *FrameBuffer;
     31   EFI_GRAPHICS_PIXEL_FORMAT       PixelFormat;
     32   EFI_PIXEL_BITMASK               PixelMasks;
     33   INTN                            PixelShl[4]; // R-G-B-Rsvd
     34   INTN                            PixelShr[4]; // R-G-B-Rsvd
     35 };
     36 
     37 CONST EFI_PIXEL_BITMASK mRgbPixelMasks = {
     38   0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
     39 };
     40 
     41 CONST EFI_PIXEL_BITMASK mBgrPixelMasks = {
     42   0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000
     43 };
     44 
     45 /**
     46   Initialize the bit mask in frame buffer configure.
     47 
     48   @param Configure  The frame buffer configure.
     49   @param BitMask    The bit mask of pixel.
     50 **/
     51 VOID
     52 ConfigurePixelBitMaskFormat (
     53   IN FRAME_BUFFER_CONFIGURE     *Configure,
     54   IN CONST EFI_PIXEL_BITMASK    *BitMask
     55   )
     56 {
     57   UINTN   Loop;
     58   UINT32  *Masks;
     59   UINT32  MergedMasks;
     60 
     61   MergedMasks = 0;
     62   Masks = (UINT32*) BitMask;
     63   for (Loop = 0; Loop < 3; Loop++) {
     64     ASSERT ((Loop == 3) || (Masks[Loop] != 0));
     65     ASSERT ((MergedMasks & Masks[Loop]) == 0);
     66     Configure->PixelShl[Loop] = HighBitSet32 (Masks[Loop]) - 23 + (Loop * 8);
     67     if (Configure->PixelShl[Loop] < 0) {
     68       Configure->PixelShr[Loop] = -Configure->PixelShl[Loop];
     69       Configure->PixelShl[Loop] = 0;
     70     } else {
     71       Configure->PixelShr[Loop] = 0;
     72     }
     73     MergedMasks = (UINT32) (MergedMasks | Masks[Loop]);
     74     DEBUG ((EFI_D_VERBOSE, "%d: shl:%d shr:%d mask:%x\n", Loop,
     75             Configure->PixelShl[Loop], Configure->PixelShr[Loop], Masks[Loop]));
     76   }
     77   MergedMasks = (UINT32) (MergedMasks | Masks[3]);
     78 
     79   ASSERT (MergedMasks != 0);
     80   Configure->BytesPerPixel = (UINTN) ((HighBitSet32 (MergedMasks) + 7) / 8);
     81 
     82   DEBUG ((EFI_D_VERBOSE, "Bytes per pixel: %d\n", Configure->BytesPerPixel));
     83 
     84   CopyMem (&Configure->PixelMasks, BitMask, sizeof (*BitMask));
     85 }
     86 
     87 /**
     88   Create the configuration for a video frame buffer.
     89 
     90   The configuration is returned in the caller provided buffer.
     91 
     92   @param[in] FrameBuffer       Pointer to the start of the frame buffer.
     93   @param[in] FrameBufferInfo   Describes the frame buffer characteristics.
     94   @param[in,out] Configure     The created configuration information.
     95   @param[in,out] ConfigureSize Size of the configuration information.
     96 
     97   @retval RETURN_SUCCESS            The configuration was successful created.
     98   @retval RETURN_BUFFER_TOO_SMALL   The Configure is to too small. The required
     99                                     size is returned in ConfigureSize.
    100   @retval RETURN_UNSUPPORTED        The requested mode is not supported by
    101                                     this implementaion.
    102 
    103 **/
    104 RETURN_STATUS
    105 EFIAPI
    106 FrameBufferBltConfigure (
    107   IN     VOID                                  *FrameBuffer,
    108   IN     EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *FrameBufferInfo,
    109   IN OUT FRAME_BUFFER_CONFIGURE                *Configure,
    110   IN OUT UINTN                                 *ConfigureSize
    111   )
    112 {
    113   if (ConfigureSize == NULL) {
    114     return RETURN_INVALID_PARAMETER;
    115   }
    116 
    117   if (*ConfigureSize < sizeof (FRAME_BUFFER_CONFIGURE)) {
    118     *ConfigureSize = sizeof (FRAME_BUFFER_CONFIGURE);
    119     return RETURN_BUFFER_TOO_SMALL;
    120   }
    121 
    122   if (Configure == NULL) {
    123     return RETURN_INVALID_PARAMETER;
    124   }
    125 
    126   switch (FrameBufferInfo->PixelFormat) {
    127   case PixelRedGreenBlueReserved8BitPerColor:
    128     ConfigurePixelBitMaskFormat (Configure, &mRgbPixelMasks);
    129     break;
    130 
    131   case PixelBlueGreenRedReserved8BitPerColor:
    132     ConfigurePixelBitMaskFormat (Configure, &mBgrPixelMasks);
    133     break;
    134 
    135   case PixelBitMask:
    136     ConfigurePixelBitMaskFormat (Configure, &(FrameBufferInfo->PixelInformation));
    137     break;
    138 
    139   case PixelBltOnly:
    140     ASSERT (FrameBufferInfo->PixelFormat != PixelBltOnly);
    141     return RETURN_UNSUPPORTED;
    142 
    143   default:
    144     ASSERT (FALSE);
    145     return RETURN_INVALID_PARAMETER;
    146   }
    147 
    148   Configure->PixelFormat   = FrameBufferInfo->PixelFormat;
    149   Configure->FrameBuffer   = (UINT8*) FrameBuffer;
    150   Configure->WidthInPixels = (UINTN) FrameBufferInfo->HorizontalResolution;
    151   Configure->Height        = (UINTN) FrameBufferInfo->VerticalResolution;
    152   Configure->WidthInBytes  = Configure->WidthInPixels * Configure->BytesPerPixel;
    153 
    154   ASSERT (Configure->WidthInBytes < sizeof (Configure->LineBuffer));
    155 
    156   return RETURN_SUCCESS;
    157 }
    158 
    159 /**
    160   Performs a UEFI Graphics Output Protocol Blt Video Fill.
    161 
    162   @param[in]  Configure     Pointer to a configuration which was successfully
    163                             created by FrameBufferBltConfigure ().
    164   @param[in]  Color         Color to fill the region with.
    165   @param[in]  DestinationX  X location to start fill operation.
    166   @param[in]  DestinationY  Y location to start fill operation.
    167   @param[in]  Width         Width (in pixels) to fill.
    168   @param[in]  Height        Height to fill.
    169 
    170   @retval  RETURN_INVALID_PARAMETER Invalid parameter was passed in.
    171   @retval  RETURN_SUCCESS           The video was filled successfully.
    172 
    173 **/
    174 EFI_STATUS
    175 FrameBufferBltLibVideoFill (
    176   IN  FRAME_BUFFER_CONFIGURE        *Configure,
    177   IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Color,
    178   IN  UINTN                         DestinationX,
    179   IN  UINTN                         DestinationY,
    180   IN  UINTN                         Width,
    181   IN  UINTN                         Height
    182   )
    183 {
    184   UINTN                             IndexX;
    185   UINTN                             IndexY;
    186   UINT8                             *Destination;
    187   UINT8                             Uint8;
    188   UINT32                            Uint32;
    189   UINT64                            WideFill;
    190   BOOLEAN                           UseWideFill;
    191   BOOLEAN                           LineBufferReady;
    192   UINTN                             Offset;
    193   UINTN                             WidthInBytes;
    194   UINTN                             SizeInBytes;
    195 
    196   //
    197   // BltBuffer to Video: Source is BltBuffer, destination is Video
    198   //
    199   if (DestinationY + Height > Configure->Height) {
    200     DEBUG ((EFI_D_VERBOSE, "VideoFill: Past screen (Y)\n"));
    201     return RETURN_INVALID_PARAMETER;
    202   }
    203 
    204   if (DestinationX + Width > Configure->WidthInPixels) {
    205     DEBUG ((EFI_D_VERBOSE, "VideoFill: Past screen (X)\n"));
    206     return RETURN_INVALID_PARAMETER;
    207   }
    208 
    209   if (Width == 0 || Height == 0) {
    210     DEBUG ((EFI_D_VERBOSE, "VideoFill: Width or Height is 0\n"));
    211     return RETURN_INVALID_PARAMETER;
    212   }
    213 
    214   WidthInBytes = Width * Configure->BytesPerPixel;
    215 
    216   Uint32 = *(UINT32*) Color;
    217   WideFill =
    218     (UINT32) (
    219     (((Uint32 << Configure->PixelShl[0]) >> Configure->PixelShr[0]) &
    220      Configure->PixelMasks.RedMask) |
    221      (((Uint32 << Configure->PixelShl[1]) >> Configure->PixelShr[1]) &
    222       Configure->PixelMasks.GreenMask) |
    223       (((Uint32 << Configure->PixelShl[2]) >> Configure->PixelShr[2]) &
    224        Configure->PixelMasks.BlueMask)
    225       );
    226   DEBUG ((EFI_D_VERBOSE, "VideoFill: color=0x%x, wide-fill=0x%x\n",
    227           Uint32, WideFill));
    228 
    229   //
    230   // If the size of the pixel data evenly divides the sizeof
    231   // WideFill, then a wide fill operation can be used
    232   //
    233   UseWideFill = TRUE;
    234   if ((sizeof (WideFill) % Configure->BytesPerPixel) == 0) {
    235     for (IndexX = Configure->BytesPerPixel; IndexX < sizeof (WideFill); IndexX++) {
    236       ((UINT8*) &WideFill)[IndexX] = ((UINT8*) &WideFill)[IndexX % Configure->BytesPerPixel];
    237     }
    238   } else {
    239     //
    240     // If all the bytes in the pixel are the same value, then use
    241     // a wide fill operation.
    242     //
    243     for (
    244       IndexX = 1, Uint8 = ((UINT8*) &WideFill)[0];
    245       IndexX < Configure->BytesPerPixel;
    246       IndexX++) {
    247       if (Uint8 != ((UINT8*) &WideFill)[IndexX]) {
    248         UseWideFill = FALSE;
    249         break;
    250       }
    251     }
    252     if (UseWideFill) {
    253       SetMem (&WideFill, sizeof (WideFill), Uint8);
    254     }
    255   }
    256 
    257   if (UseWideFill && (DestinationX == 0) && (Width == Configure->WidthInPixels)) {
    258     DEBUG ((EFI_D_VERBOSE, "VideoFill (wide, one-shot)\n"));
    259     Offset = DestinationY * Configure->WidthInPixels;
    260     Offset = Configure->BytesPerPixel * Offset;
    261     Destination = Configure->FrameBuffer + Offset;
    262     SizeInBytes = WidthInBytes * Height;
    263     if (SizeInBytes >= 8) {
    264       SetMem32 (Destination, SizeInBytes & ~3, (UINT32) WideFill);
    265       SizeInBytes &= 3;
    266     }
    267     if (SizeInBytes > 0) {
    268       SetMem (Destination, SizeInBytes, (UINT8) (UINTN) WideFill);
    269     }
    270   } else {
    271     LineBufferReady = FALSE;
    272     for (IndexY = DestinationY; IndexY < (Height + DestinationY); IndexY++) {
    273       Offset = (IndexY * Configure->WidthInPixels) + DestinationX;
    274       Offset = Configure->BytesPerPixel * Offset;
    275       Destination = Configure->FrameBuffer + Offset;
    276 
    277       if (UseWideFill && (((UINTN) Destination & 7) == 0)) {
    278         DEBUG ((EFI_D_VERBOSE, "VideoFill (wide)\n"));
    279         SizeInBytes = WidthInBytes;
    280         if (SizeInBytes >= 8) {
    281           SetMem64 (Destination, SizeInBytes & ~7, WideFill);
    282           SizeInBytes &= 7;
    283         }
    284         if (SizeInBytes > 0) {
    285           CopyMem (Destination, &WideFill, SizeInBytes);
    286         }
    287       } else {
    288         DEBUG ((EFI_D_VERBOSE, "VideoFill (not wide)\n"));
    289         if (!LineBufferReady) {
    290           CopyMem (Configure->LineBuffer, &WideFill, Configure->BytesPerPixel);
    291           for (IndexX = 1; IndexX < Width; ) {
    292             CopyMem (
    293               (Configure->LineBuffer + (IndexX * Configure->BytesPerPixel)),
    294               Configure->LineBuffer,
    295               MIN (IndexX, Width - IndexX) * Configure->BytesPerPixel
    296             );
    297             IndexX += MIN (IndexX, Width - IndexX);
    298           }
    299           LineBufferReady = TRUE;
    300         }
    301         CopyMem (Destination, Configure->LineBuffer, WidthInBytes);
    302       }
    303     }
    304   }
    305 
    306   return RETURN_SUCCESS;
    307 }
    308 
    309 /**
    310   Performs a UEFI Graphics Output Protocol Blt Video to Buffer operation
    311   with extended parameters.
    312 
    313   @param[in]  Configure     Pointer to a configuration which was successfully
    314                             created by FrameBufferBltConfigure ().
    315   @param[out] BltBuffer     Output buffer for pixel color data.
    316   @param[in]  SourceX       X location within video.
    317   @param[in]  SourceY       Y location within video.
    318   @param[in]  DestinationX  X location within BltBuffer.
    319   @param[in]  DestinationY  Y location within BltBuffer.
    320   @param[in]  Width         Width (in pixels).
    321   @param[in]  Height        Height.
    322   @param[in]  Delta         Number of bytes in a row of BltBuffer.
    323 
    324   @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
    325   @retval RETURN_SUCCESS           The Blt operation was performed successfully.
    326 **/
    327 RETURN_STATUS
    328 FrameBufferBltLibVideoToBltBuffer (
    329   IN     FRAME_BUFFER_CONFIGURE          *Configure,
    330      OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,
    331   IN     UINTN                           SourceX,
    332   IN     UINTN                           SourceY,
    333   IN     UINTN                           DestinationX,
    334   IN     UINTN                           DestinationY,
    335   IN     UINTN                           Width,
    336   IN     UINTN                           Height,
    337   IN     UINTN                           Delta
    338   )
    339 {
    340   UINTN                                  DstY;
    341   UINTN                                  SrcY;
    342   EFI_GRAPHICS_OUTPUT_BLT_PIXEL          *Blt;
    343   UINT8                                  *Source;
    344   UINT8                                  *Destination;
    345   UINTN                                  IndexX;
    346   UINT32                                 Uint32;
    347   UINTN                                  Offset;
    348   UINTN                                  WidthInBytes;
    349 
    350   //
    351   // Video to BltBuffer: Source is Video, destination is BltBuffer
    352   //
    353   if (SourceY + Height > Configure->Height) {
    354     return RETURN_INVALID_PARAMETER;
    355   }
    356 
    357   if (SourceX + Width > Configure->WidthInPixels) {
    358     return RETURN_INVALID_PARAMETER;
    359   }
    360 
    361   if (Width == 0 || Height == 0) {
    362     return RETURN_INVALID_PARAMETER;
    363   }
    364 
    365   //
    366   // If Delta is zero, then the entire BltBuffer is being used, so Delta is
    367   // the number of bytes in each row of BltBuffer. Since BltBuffer is Width
    368   // pixels size, the number of bytes in each row can be computed.
    369   //
    370   if (Delta == 0) {
    371     Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
    372   }
    373 
    374   WidthInBytes = Width * Configure->BytesPerPixel;
    375 
    376   //
    377   // Video to BltBuffer: Source is Video, destination is BltBuffer
    378   //
    379   for (SrcY = SourceY, DstY = DestinationY;
    380        DstY < (Height + DestinationY);
    381        SrcY++, DstY++) {
    382 
    383     Offset = (SrcY * Configure->WidthInPixels) + SourceX;
    384     Offset = Configure->BytesPerPixel * Offset;
    385     Source = Configure->FrameBuffer + Offset;
    386 
    387     if (Configure->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
    388       Destination = (UINT8 *) BltBuffer + (DstY * Delta) + (DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
    389     } else {
    390       Destination = Configure->LineBuffer;
    391     }
    392 
    393     CopyMem (Destination, Source, WidthInBytes);
    394 
    395     if (Configure->PixelFormat != PixelBlueGreenRedReserved8BitPerColor) {
    396       for (IndexX = 0; IndexX < Width; IndexX++) {
    397         Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)
    398           ((UINT8 *) BltBuffer + (DstY * Delta) +
    399           (DestinationX + IndexX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
    400         Uint32 = *(UINT32*) (Configure->LineBuffer + (IndexX * Configure->BytesPerPixel));
    401         *(UINT32*) Blt =
    402           (UINT32) (
    403           (((Uint32 & Configure->PixelMasks.RedMask) >>
    404             Configure->PixelShl[0]) << Configure->PixelShr[0]) |
    405             (((Uint32 & Configure->PixelMasks.GreenMask) >>
    406               Configure->PixelShl[1]) << Configure->PixelShr[1]) |
    407               (((Uint32 & Configure->PixelMasks.BlueMask) >>
    408                 Configure->PixelShl[2]) << Configure->PixelShr[2])
    409             );
    410       }
    411     }
    412   }
    413 
    414   return RETURN_SUCCESS;
    415 }
    416 
    417 /**
    418   Performs a UEFI Graphics Output Protocol Blt Buffer to Video operation
    419   with extended parameters.
    420 
    421   @param[in]  Configure     Pointer to a configuration which was successfully
    422                             created by FrameBufferBltConfigure ().
    423   @param[in]  BltBuffer     Output buffer for pixel color data.
    424   @param[in]  SourceX       X location within BltBuffer.
    425   @param[in]  SourceY       Y location within BltBuffer.
    426   @param[in]  DestinationX  X location within video.
    427   @param[in]  DestinationY  Y location within video.
    428   @param[in]  Width         Width (in pixels).
    429   @param[in]  Height        Height.
    430   @param[in]  Delta         Number of bytes in a row of BltBuffer.
    431 
    432   @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
    433   @retval RETURN_SUCCESS           The Blt operation was performed successfully.
    434 **/
    435 RETURN_STATUS
    436 FrameBufferBltLibBufferToVideo (
    437   IN  FRAME_BUFFER_CONFIGURE                *Configure,
    438   IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL         *BltBuffer,
    439   IN  UINTN                                 SourceX,
    440   IN  UINTN                                 SourceY,
    441   IN  UINTN                                 DestinationX,
    442   IN  UINTN                                 DestinationY,
    443   IN  UINTN                                 Width,
    444   IN  UINTN                                 Height,
    445   IN  UINTN                                 Delta
    446   )
    447 {
    448   UINTN                                    DstY;
    449   UINTN                                    SrcY;
    450   EFI_GRAPHICS_OUTPUT_BLT_PIXEL            *Blt;
    451   UINT8                                    *Source;
    452   UINT8                                    *Destination;
    453   UINTN                                    IndexX;
    454   UINT32                                   Uint32;
    455   UINTN                                    Offset;
    456   UINTN                                    WidthInBytes;
    457 
    458   //
    459   // BltBuffer to Video: Source is BltBuffer, destination is Video
    460   //
    461   if (DestinationY + Height > Configure->Height) {
    462     return RETURN_INVALID_PARAMETER;
    463   }
    464 
    465   if (DestinationX + Width > Configure->WidthInPixels) {
    466     return RETURN_INVALID_PARAMETER;
    467   }
    468 
    469   if (Width == 0 || Height == 0) {
    470     return RETURN_INVALID_PARAMETER;
    471   }
    472 
    473   //
    474   // If Delta is zero, then the entire BltBuffer is being used, so Delta is
    475   // the number of bytes in each row of BltBuffer. Since BltBuffer is Width
    476   // pixels size, the number of bytes in each row can be computed.
    477   //
    478   if (Delta == 0) {
    479     Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
    480   }
    481 
    482   WidthInBytes = Width * Configure->BytesPerPixel;
    483 
    484   for (SrcY = SourceY, DstY = DestinationY;
    485        SrcY < (Height + SourceY);
    486        SrcY++, DstY++) {
    487 
    488     Offset = (DstY * Configure->WidthInPixels) + DestinationX;
    489     Offset = Configure->BytesPerPixel * Offset;
    490     Destination = Configure->FrameBuffer + Offset;
    491 
    492     if (Configure->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
    493       Source = (UINT8 *) BltBuffer + (SrcY * Delta);
    494     } else {
    495       for (IndexX = 0; IndexX < Width; IndexX++) {
    496         Blt =
    497           (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (
    498               (UINT8 *) BltBuffer +
    499               (SrcY * Delta) +
    500               ((SourceX + IndexX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))
    501             );
    502         Uint32 = *(UINT32*) Blt;
    503         *(UINT32*) (Configure->LineBuffer + (IndexX * Configure->BytesPerPixel)) =
    504           (UINT32) (
    505               (((Uint32 << Configure->PixelShl[0]) >> Configure->PixelShr[0]) &
    506                Configure->PixelMasks.RedMask) |
    507               (((Uint32 << Configure->PixelShl[1]) >> Configure->PixelShr[1]) &
    508                Configure->PixelMasks.GreenMask) |
    509               (((Uint32 << Configure->PixelShl[2]) >> Configure->PixelShr[2]) &
    510                Configure->PixelMasks.BlueMask)
    511             );
    512       }
    513       Source = Configure->LineBuffer;
    514     }
    515 
    516     CopyMem (Destination, Source, WidthInBytes);
    517   }
    518 
    519   return RETURN_SUCCESS;
    520 }
    521 
    522 /**
    523   Performs a UEFI Graphics Output Protocol Blt Video to Video operation
    524 
    525   @param[in]  Configure     Pointer to a configuration which was successfully
    526                             created by FrameBufferBltConfigure ().
    527   @param[in]  SourceX       X location within video.
    528   @param[in]  SourceY       Y location within video.
    529   @param[in]  DestinationX  X location within video.
    530   @param[in]  DestinationY  Y location within video.
    531   @param[in]  Width         Width (in pixels).
    532   @param[in]  Height        Height.
    533 
    534   @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
    535   @retval RETURN_SUCCESS           The Blt operation was performed successfully.
    536 **/
    537 RETURN_STATUS
    538 FrameBufferBltLibVideoToVideo (
    539   IN  FRAME_BUFFER_CONFIGURE                *Configure,
    540   IN  UINTN                                 SourceX,
    541   IN  UINTN                                 SourceY,
    542   IN  UINTN                                 DestinationX,
    543   IN  UINTN                                 DestinationY,
    544   IN  UINTN                                 Width,
    545   IN  UINTN                                 Height
    546   )
    547 {
    548   UINT8                                     *Source;
    549   UINT8                                     *Destination;
    550   UINTN                                     Offset;
    551   UINTN                                     WidthInBytes;
    552   INTN                                      LineStride;
    553 
    554   //
    555   // Video to Video: Source is Video, destination is Video
    556   //
    557   if (SourceY + Height > Configure->Height) {
    558     return RETURN_INVALID_PARAMETER;
    559   }
    560 
    561   if (SourceX + Width > Configure->WidthInPixels) {
    562     return RETURN_INVALID_PARAMETER;
    563   }
    564 
    565   if (DestinationY + Height > Configure->Height) {
    566     return RETURN_INVALID_PARAMETER;
    567   }
    568 
    569   if (DestinationX + Width > Configure->WidthInPixels) {
    570     return RETURN_INVALID_PARAMETER;
    571   }
    572 
    573   if (Width == 0 || Height == 0) {
    574     return RETURN_INVALID_PARAMETER;
    575   }
    576 
    577   WidthInBytes = Width * Configure->BytesPerPixel;
    578 
    579   Offset = (SourceY * Configure->WidthInPixels) + SourceX;
    580   Offset = Configure->BytesPerPixel * Offset;
    581   Source = Configure->FrameBuffer + Offset;
    582 
    583   Offset = (DestinationY * Configure->WidthInPixels) + DestinationX;
    584   Offset = Configure->BytesPerPixel * Offset;
    585   Destination = Configure->FrameBuffer + Offset;
    586 
    587   LineStride = Configure->WidthInBytes;
    588   if (Destination > Source) {
    589     //
    590     // Copy from last line to avoid source is corrupted by copying
    591     //
    592     Source += Height * LineStride;
    593     Destination += Height * LineStride;
    594     LineStride = -LineStride;
    595   }
    596 
    597   while (Height-- > 0) {
    598     CopyMem (Destination, Source, WidthInBytes);
    599 
    600     Source += LineStride;
    601     Destination += LineStride;
    602   }
    603 
    604   return RETURN_SUCCESS;
    605 }
    606 
    607 /**
    608   Performs a UEFI Graphics Output Protocol Blt operation.
    609 
    610   @param[in]     Configure    Pointer to a configuration which was successfully
    611                               created by FrameBufferBltConfigure ().
    612   @param[in,out] BltBuffer    The data to transfer to screen.
    613   @param[in]     BltOperation The operation to perform.
    614   @param[in]     SourceX      The X coordinate of the source for BltOperation.
    615   @param[in]     SourceY      The Y coordinate of the source for BltOperation.
    616   @param[in]     DestinationX The X coordinate of the destination for
    617                               BltOperation.
    618   @param[in]     DestinationY The Y coordinate of the destination for
    619                               BltOperation.
    620   @param[in]     Width        The width of a rectangle in the blt rectangle
    621                               in pixels.
    622   @param[in]     Height       The height of a rectangle in the blt rectangle
    623                               in pixels.
    624   @param[in]     Delta        Not used for EfiBltVideoFill and
    625                               EfiBltVideoToVideo operation. If a Delta of 0
    626                               is used, the entire BltBuffer will be operated
    627                               on. If a subrectangle of the BltBuffer is
    628                               used, then Delta represents the number of
    629                               bytes in a row of the BltBuffer.
    630 
    631   @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
    632   @retval RETURN_SUCCESS           The Blt operation was performed successfully.
    633 **/
    634 RETURN_STATUS
    635 EFIAPI
    636 FrameBufferBlt (
    637   IN     FRAME_BUFFER_CONFIGURE                *Configure,
    638   IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL         *BltBuffer, OPTIONAL
    639   IN     EFI_GRAPHICS_OUTPUT_BLT_OPERATION     BltOperation,
    640   IN     UINTN                                 SourceX,
    641   IN     UINTN                                 SourceY,
    642   IN     UINTN                                 DestinationX,
    643   IN     UINTN                                 DestinationY,
    644   IN     UINTN                                 Width,
    645   IN     UINTN                                 Height,
    646   IN     UINTN                                 Delta
    647   )
    648 {
    649   if (Configure == NULL) {
    650     return RETURN_INVALID_PARAMETER;
    651   }
    652 
    653   switch (BltOperation) {
    654   case EfiBltVideoToBltBuffer:
    655     return FrameBufferBltLibVideoToBltBuffer (
    656              Configure,
    657              BltBuffer,
    658              SourceX,
    659              SourceY,
    660              DestinationX,
    661              DestinationY,
    662              Width,
    663              Height,
    664              Delta
    665              );
    666 
    667   case EfiBltVideoToVideo:
    668     return FrameBufferBltLibVideoToVideo (
    669              Configure,
    670              SourceX,
    671              SourceY,
    672              DestinationX,
    673              DestinationY,
    674              Width,
    675              Height
    676              );
    677 
    678   case EfiBltVideoFill:
    679     return FrameBufferBltLibVideoFill (
    680              Configure,
    681              BltBuffer,
    682              DestinationX,
    683              DestinationY,
    684              Width,
    685              Height
    686              );
    687 
    688   case EfiBltBufferToVideo:
    689     return FrameBufferBltLibBufferToVideo (
    690              Configure,
    691              BltBuffer,
    692              SourceX,
    693              SourceY,
    694              DestinationX,
    695              DestinationY,
    696              Width,
    697              Height,
    698              Delta
    699              );
    700 
    701   default:
    702     return RETURN_INVALID_PARAMETER;
    703   }
    704 }
    705