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 - 2011, 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 "PiDxe.h"
     16 #include <Library/BaseLib.h>
     17 #include <Library/BaseMemoryLib.h>
     18 #include <Library/BltLib.h>
     19 #include <Library/DebugLib.h>
     20 
     21 #if 0
     22 #define VDEBUG DEBUG
     23 #else
     24 #define VDEBUG(x)
     25 #endif
     26 
     27 #define MAX_LINE_BUFFER_SIZE (SIZE_4KB * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))
     28 
     29 UINTN                           mBltLibColorDepth;
     30 UINTN                           mBltLibWidthInBytes;
     31 UINTN                           mBltLibBytesPerPixel;
     32 UINTN                           mBltLibWidthInPixels;
     33 UINTN                           mBltLibHeight;
     34 UINT8                           mBltLibLineBuffer[MAX_LINE_BUFFER_SIZE];
     35 UINT8                           *mBltLibFrameBuffer;
     36 EFI_GRAPHICS_PIXEL_FORMAT       mPixelFormat;
     37 EFI_PIXEL_BITMASK               mPixelBitMasks;
     38 INTN                            mPixelShl[4]; // R-G-B-Rsvd
     39 INTN                            mPixelShr[4]; // R-G-B-Rsvd
     40 
     41 
     42 VOID
     43 ConfigurePixelBitMaskFormat (
     44   IN EFI_PIXEL_BITMASK          *BitMask
     45   )
     46 {
     47   UINTN   Loop;
     48   UINT32  *Masks;
     49   UINT32  MergedMasks;
     50 
     51   MergedMasks = 0;
     52   Masks = (UINT32*) BitMask;
     53   for (Loop = 0; Loop < 3; Loop++) {
     54     ASSERT ((Loop == 3) || (Masks[Loop] != 0));
     55     ASSERT ((MergedMasks & Masks[Loop]) == 0);
     56     mPixelShl[Loop] = HighBitSet32 (Masks[Loop]) - 23 + (Loop * 8);
     57     if (mPixelShl[Loop] < 0) {
     58       mPixelShr[Loop] = -mPixelShl[Loop];
     59       mPixelShl[Loop] = 0;
     60     } else {
     61       mPixelShr[Loop] = 0;
     62     }
     63     MergedMasks = (UINT32) (MergedMasks | Masks[Loop]);
     64     DEBUG ((EFI_D_INFO, "%d: shl:%d shr:%d mask:%x\n", Loop, mPixelShl[Loop], mPixelShr[Loop], Masks[Loop]));
     65   }
     66   MergedMasks = (UINT32) (MergedMasks | Masks[3]);
     67 
     68   ASSERT (MergedMasks != 0);
     69   mBltLibBytesPerPixel = (UINTN) ((HighBitSet32 (MergedMasks) + 7) / 8);
     70 
     71   DEBUG ((EFI_D_INFO, "Bytes per pixel: %d\n", mBltLibBytesPerPixel));
     72 
     73   CopyMem (&mPixelBitMasks, BitMask, sizeof (*BitMask));
     74 }
     75 
     76 
     77 /**
     78   Configure the FrameBufferLib instance
     79 
     80   @param[in] FrameBuffer      Pointer to the start of the frame buffer
     81   @param[in] FrameBufferInfo  Describes the frame buffer characteristics
     82 
     83   @retval  EFI_INVALID_PARAMETER - Invalid parameter
     84   @retval  EFI_UNSUPPORTED - The BltLib does not support this configuration
     85   @retval  EFI_SUCCESS - Blt operation success
     86 
     87 **/
     88 EFI_STATUS
     89 EFIAPI
     90 BltLibConfigure (
     91   IN  VOID                                 *FrameBuffer,
     92   IN  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *FrameBufferInfo
     93   )
     94 {
     95   STATIC EFI_PIXEL_BITMASK  RgbPixelMasks =
     96     { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 };
     97   STATIC EFI_PIXEL_BITMASK  BgrPixelMasks =
     98     { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 };
     99 
    100   switch (FrameBufferInfo->PixelFormat) {
    101   case PixelRedGreenBlueReserved8BitPerColor:
    102     ConfigurePixelBitMaskFormat (&RgbPixelMasks);
    103     break;
    104   case PixelBlueGreenRedReserved8BitPerColor:
    105     ConfigurePixelBitMaskFormat (&BgrPixelMasks);
    106     break;
    107   case PixelBitMask:
    108     ConfigurePixelBitMaskFormat (&(FrameBufferInfo->PixelInformation));
    109     break;
    110   case PixelBltOnly:
    111     ASSERT (FrameBufferInfo->PixelFormat != PixelBltOnly);
    112     return EFI_UNSUPPORTED;
    113   default:
    114     ASSERT (FALSE);
    115     return EFI_INVALID_PARAMETER;
    116   }
    117   mPixelFormat = FrameBufferInfo->PixelFormat;
    118 
    119   mBltLibFrameBuffer = (UINT8*) FrameBuffer;
    120   mBltLibWidthInPixels = (UINTN) FrameBufferInfo->HorizontalResolution;
    121   mBltLibHeight = (UINTN) FrameBufferInfo->VerticalResolution;
    122   mBltLibWidthInBytes = mBltLibWidthInPixels * mBltLibBytesPerPixel;
    123 
    124   ASSERT (mBltLibWidthInBytes < sizeof (mBltLibLineBuffer));
    125 
    126   return EFI_SUCCESS;
    127 }
    128 
    129 
    130 /**
    131   Performs a UEFI Graphics Output Protocol Blt operation.
    132 
    133   @param[in,out] BltBuffer     - The data to transfer to screen
    134   @param[in]     BltOperation  - The operation to perform
    135   @param[in]     SourceX       - The X coordinate of the source for BltOperation
    136   @param[in]     SourceY       - The Y coordinate of the source for BltOperation
    137   @param[in]     DestinationX  - The X coordinate of the destination for BltOperation
    138   @param[in]     DestinationY  - The Y coordinate of the destination for BltOperation
    139   @param[in]     Width         - The width of a rectangle in the blt rectangle in pixels
    140   @param[in]     Height        - The height of a rectangle in the blt rectangle in pixels
    141   @param[in]     Delta         - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
    142                                  If a Delta of 0 is used, the entire BltBuffer will be operated on.
    143                                  If a subrectangle of the BltBuffer is used, then Delta represents
    144                                  the number of bytes in a row of the BltBuffer.
    145 
    146   @retval  EFI_DEVICE_ERROR - A hardware error occured
    147   @retval  EFI_INVALID_PARAMETER - Invalid parameter passed in
    148   @retval  EFI_SUCCESS - Blt operation success
    149 
    150 **/
    151 EFI_STATUS
    152 EFIAPI
    153 BltLibGopBlt (
    154   IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL         *BltBuffer, OPTIONAL
    155   IN  EFI_GRAPHICS_OUTPUT_BLT_OPERATION     BltOperation,
    156   IN  UINTN                                 SourceX,
    157   IN  UINTN                                 SourceY,
    158   IN  UINTN                                 DestinationX,
    159   IN  UINTN                                 DestinationY,
    160   IN  UINTN                                 Width,
    161   IN  UINTN                                 Height,
    162   IN  UINTN                                 Delta
    163   )
    164 {
    165   switch (BltOperation) {
    166   case EfiBltVideoToBltBuffer:
    167     return BltLibVideoToBltBufferEx (
    168              BltBuffer,
    169              SourceX,
    170              SourceY,
    171              DestinationX,
    172              DestinationY,
    173              Width,
    174              Height,
    175              Delta
    176              );
    177 
    178   case EfiBltVideoToVideo:
    179     return BltLibVideoToVideo (
    180              SourceX,
    181              SourceY,
    182              DestinationX,
    183              DestinationY,
    184              Width,
    185              Height
    186              );
    187 
    188   case EfiBltVideoFill:
    189     return BltLibVideoFill (
    190              BltBuffer,
    191              DestinationX,
    192              DestinationY,
    193              Width,
    194              Height
    195              );
    196 
    197   case EfiBltBufferToVideo:
    198     return BltLibBufferToVideoEx (
    199              BltBuffer,
    200              SourceX,
    201              SourceY,
    202              DestinationX,
    203              DestinationY,
    204              Width,
    205              Height,
    206              Delta
    207              );
    208   default:
    209     return EFI_INVALID_PARAMETER;
    210   }
    211 }
    212 
    213 
    214 /**
    215   Performs a UEFI Graphics Output Protocol Blt Video Fill.
    216 
    217   @param[in]  Color         Color to fill the region with
    218   @param[in]  DestinationX  X location to start fill operation
    219   @param[in]  DestinationY  Y location to start fill operation
    220   @param[in]  Width         Width (in pixels) to fill
    221   @param[in]  Height        Height to fill
    222 
    223   @retval  EFI_DEVICE_ERROR - A hardware error occured
    224   @retval  EFI_INVALID_PARAMETER - Invalid parameter passed in
    225   @retval  EFI_SUCCESS - The sizes were returned
    226 
    227 **/
    228 EFI_STATUS
    229 EFIAPI
    230 BltLibVideoFill (
    231   IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL         *Color,
    232   IN  UINTN                                 DestinationX,
    233   IN  UINTN                                 DestinationY,
    234   IN  UINTN                                 Width,
    235   IN  UINTN                                 Height
    236   )
    237 {
    238   UINTN                           DstY;
    239   VOID                            *BltMemDst;
    240   UINTN                           X;
    241   UINT8                           Uint8;
    242   UINT32                          Uint32;
    243   UINT64                          WideFill;
    244   BOOLEAN                         UseWideFill;
    245   BOOLEAN                         LineBufferReady;
    246   UINTN                           Offset;
    247   UINTN                           WidthInBytes;
    248   UINTN                           SizeInBytes;
    249 
    250   //
    251   // BltBuffer to Video: Source is BltBuffer, destination is Video
    252   //
    253   if (DestinationY + Height > mBltLibHeight) {
    254     DEBUG ((EFI_D_INFO, "VideoFill: Past screen (Y)\n"));
    255     return EFI_INVALID_PARAMETER;
    256   }
    257 
    258   if (DestinationX + Width > mBltLibWidthInPixels) {
    259     DEBUG ((EFI_D_INFO, "VideoFill: Past screen (X)\n"));
    260     return EFI_INVALID_PARAMETER;
    261   }
    262 
    263   if (Width == 0 || Height == 0) {
    264     DEBUG ((EFI_D_INFO, "VideoFill: Width or Height is 0\n"));
    265     return EFI_INVALID_PARAMETER;
    266   }
    267 
    268   WidthInBytes = Width * mBltLibBytesPerPixel;
    269 
    270   Uint32 = *(UINT32*) Color;
    271   WideFill =
    272     (UINT32) (
    273         (((Uint32 << mPixelShl[0]) >> mPixelShr[0]) & mPixelBitMasks.RedMask) |
    274         (((Uint32 << mPixelShl[1]) >> mPixelShr[1]) & mPixelBitMasks.GreenMask) |
    275         (((Uint32 << mPixelShl[2]) >> mPixelShr[2]) & mPixelBitMasks.BlueMask)
    276       );
    277   VDEBUG ((EFI_D_INFO, "VideoFill: color=0x%x, wide-fill=0x%x\n", Uint32, WideFill));
    278 
    279   //
    280   // If the size of the pixel data evenly divides the sizeof
    281   // WideFill, then a wide fill operation can be used
    282   //
    283   UseWideFill = TRUE;
    284   if ((sizeof (WideFill) % mBltLibBytesPerPixel) == 0) {
    285     for (X = mBltLibBytesPerPixel; X < sizeof (WideFill); X++) {
    286       ((UINT8*)&WideFill)[X] = ((UINT8*)&WideFill)[X % mBltLibBytesPerPixel];
    287     }
    288   } else {
    289     //
    290     // If all the bytes in the pixel are the same value, then use
    291     // a wide fill operation.
    292     //
    293     for (
    294       X = 1, Uint8 = ((UINT8*)&WideFill)[0];
    295       X < mBltLibBytesPerPixel;
    296       X++) {
    297       if (Uint8 != ((UINT8*)&WideFill)[X]) {
    298         UseWideFill = FALSE;
    299         break;
    300       }
    301     }
    302     if (UseWideFill) {
    303       SetMem ((VOID*) &WideFill, sizeof (WideFill), Uint8);
    304     }
    305   }
    306 
    307   if (UseWideFill && (DestinationX == 0) && (Width == mBltLibWidthInPixels)) {
    308     VDEBUG ((EFI_D_INFO, "VideoFill (wide, one-shot)\n"));
    309     Offset = DestinationY * mBltLibWidthInPixels;
    310     Offset = mBltLibBytesPerPixel * Offset;
    311     BltMemDst = (VOID*) (mBltLibFrameBuffer + Offset);
    312     SizeInBytes = WidthInBytes * Height;
    313     if (SizeInBytes >= 8) {
    314       SetMem32 (BltMemDst, SizeInBytes & ~3, (UINT32) WideFill);
    315       SizeInBytes = SizeInBytes & 3;
    316     }
    317     if (SizeInBytes > 0) {
    318       SetMem (BltMemDst, SizeInBytes, (UINT8)(UINTN) WideFill);
    319     }
    320   } else {
    321     LineBufferReady = FALSE;
    322     for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) {
    323       Offset = (DstY * mBltLibWidthInPixels) + DestinationX;
    324       Offset = mBltLibBytesPerPixel * Offset;
    325       BltMemDst = (VOID*) (mBltLibFrameBuffer + Offset);
    326 
    327       if (UseWideFill && (((UINTN) BltMemDst & 7) == 0)) {
    328         VDEBUG ((EFI_D_INFO, "VideoFill (wide)\n"));
    329         SizeInBytes = WidthInBytes;
    330         if (SizeInBytes >= 8) {
    331           SetMem64 (BltMemDst, SizeInBytes & ~7, WideFill);
    332           SizeInBytes = SizeInBytes & 7;
    333         }
    334         if (SizeInBytes > 0) {
    335           CopyMem (BltMemDst, (VOID*) &WideFill, SizeInBytes);
    336         }
    337       } else {
    338         VDEBUG ((EFI_D_INFO, "VideoFill (not wide)\n"));
    339         if (!LineBufferReady) {
    340           CopyMem (mBltLibLineBuffer, &WideFill, mBltLibBytesPerPixel);
    341           for (X = 1; X < Width; ) {
    342             CopyMem(
    343               (mBltLibLineBuffer + (X * mBltLibBytesPerPixel)),
    344               mBltLibLineBuffer,
    345               MIN (X, Width - X) * mBltLibBytesPerPixel
    346               );
    347             X = X + MIN (X, Width - X);
    348           }
    349           LineBufferReady = TRUE;
    350         }
    351         CopyMem (BltMemDst, mBltLibLineBuffer, WidthInBytes);
    352       }
    353     }
    354   }
    355 
    356   return EFI_SUCCESS;
    357 }
    358 
    359 
    360 /**
    361   Performs a UEFI Graphics Output Protocol Blt Video to Buffer operation.
    362 
    363   @param[out] BltBuffer     Output buffer for pixel color data
    364   @param[in]  SourceX       X location within video
    365   @param[in]  SourceY       Y location within video
    366   @param[in]  Width         Width (in pixels)
    367   @param[in]  Height        Height
    368 
    369   @retval  EFI_DEVICE_ERROR - A hardware error occured
    370   @retval  EFI_INVALID_PARAMETER - Invalid parameter passed in
    371   @retval  EFI_SUCCESS - The sizes were returned
    372 
    373 **/
    374 EFI_STATUS
    375 EFIAPI
    376 BltLibVideoToBltBuffer (
    377   OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL         *BltBuffer,
    378   IN  UINTN                                 SourceX,
    379   IN  UINTN                                 SourceY,
    380   IN  UINTN                                 Width,
    381   IN  UINTN                                 Height
    382   )
    383 {
    384   return BltLibVideoToBltBufferEx (
    385            BltBuffer,
    386            SourceX,
    387            SourceY,
    388            0,
    389            0,
    390            Width,
    391            Height,
    392            0
    393            );
    394 }
    395 
    396 
    397 /**
    398   Performs a UEFI Graphics Output Protocol Blt Video to Buffer operation
    399   with extended parameters.
    400 
    401   @param[out] BltBuffer     Output buffer for pixel color data
    402   @param[in]  SourceX       X location within video
    403   @param[in]  SourceY       Y location within video
    404   @param[in]  DestinationX  X location within BltBuffer
    405   @param[in]  DestinationY  Y location within BltBuffer
    406   @param[in]  Width         Width (in pixels)
    407   @param[in]  Height        Height
    408   @param[in]  Delta         Number of bytes in a row of BltBuffer
    409 
    410   @retval  EFI_DEVICE_ERROR - A hardware error occured
    411   @retval  EFI_INVALID_PARAMETER - Invalid parameter passed in
    412   @retval  EFI_SUCCESS - The sizes were returned
    413 
    414 **/
    415 EFI_STATUS
    416 EFIAPI
    417 BltLibVideoToBltBufferEx (
    418   OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL         *BltBuffer,
    419   IN  UINTN                                 SourceX,
    420   IN  UINTN                                 SourceY,
    421   IN  UINTN                                 DestinationX,
    422   IN  UINTN                                 DestinationY,
    423   IN  UINTN                                 Width,
    424   IN  UINTN                                 Height,
    425   IN  UINTN                                 Delta
    426   )
    427 {
    428   UINTN                           DstY;
    429   UINTN                           SrcY;
    430   EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *Blt;
    431   VOID                            *BltMemSrc;
    432   VOID                            *BltMemDst;
    433   UINTN                           X;
    434   UINT32                          Uint32;
    435   UINTN                           Offset;
    436   UINTN                           WidthInBytes;
    437 
    438   //
    439   // Video to BltBuffer: Source is Video, destination is BltBuffer
    440   //
    441   if (SourceY + Height > mBltLibHeight) {
    442     return EFI_INVALID_PARAMETER;
    443   }
    444 
    445   if (SourceX + Width > mBltLibWidthInPixels) {
    446     return EFI_INVALID_PARAMETER;
    447   }
    448 
    449   if (Width == 0 || Height == 0) {
    450     return EFI_INVALID_PARAMETER;
    451   }
    452 
    453   //
    454   // If Delta is zero, then the entire BltBuffer is being used, so Delta
    455   // is the number of bytes in each row of BltBuffer.  Since BltBuffer is Width pixels size,
    456   // the number of bytes in each row can be computed.
    457   //
    458   if (Delta == 0) {
    459     Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
    460   }
    461 
    462   WidthInBytes = Width * mBltLibBytesPerPixel;
    463 
    464   //
    465   // Video to BltBuffer: Source is Video, destination is BltBuffer
    466   //
    467   for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {
    468 
    469     Offset = (SrcY * mBltLibWidthInPixels) + SourceX;
    470     Offset = mBltLibBytesPerPixel * Offset;
    471     BltMemSrc = (VOID *) (mBltLibFrameBuffer + Offset);
    472 
    473     if (mPixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
    474       BltMemDst =
    475         (VOID *) (
    476             (UINT8 *) BltBuffer +
    477             (DstY * Delta) +
    478             (DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))
    479           );
    480     } else {
    481       BltMemDst = (VOID *) mBltLibLineBuffer;
    482     }
    483 
    484     CopyMem (BltMemDst, BltMemSrc, WidthInBytes);
    485 
    486     if (mPixelFormat != PixelBlueGreenRedReserved8BitPerColor) {
    487       for (X = 0; X < Width; X++) {
    488         Blt         = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + (DstY * Delta) + (DestinationX + X) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
    489         Uint32 = *(UINT32*) (mBltLibLineBuffer + (X * mBltLibBytesPerPixel));
    490         *(UINT32*) Blt =
    491           (UINT32) (
    492               (((Uint32 & mPixelBitMasks.RedMask)   >> mPixelShl[0]) << mPixelShr[0]) |
    493               (((Uint32 & mPixelBitMasks.GreenMask) >> mPixelShl[1]) << mPixelShr[1]) |
    494               (((Uint32 & mPixelBitMasks.BlueMask)  >> mPixelShl[2]) << mPixelShr[2])
    495             );
    496       }
    497     }
    498   }
    499 
    500   return EFI_SUCCESS;
    501 }
    502 
    503 
    504 /**
    505   Performs a UEFI Graphics Output Protocol Blt Buffer to Video operation.
    506 
    507   @param[in]  BltBuffer     Output buffer for pixel color data
    508   @param[in]  DestinationX  X location within video
    509   @param[in]  DestinationY  Y location within video
    510   @param[in]  Width         Width (in pixels)
    511   @param[in]  Height        Height
    512 
    513   @retval  EFI_DEVICE_ERROR - A hardware error occured
    514   @retval  EFI_INVALID_PARAMETER - Invalid parameter passed in
    515   @retval  EFI_SUCCESS - The sizes were returned
    516 
    517 **/
    518 EFI_STATUS
    519 EFIAPI
    520 BltLibBufferToVideo (
    521   IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL         *BltBuffer,
    522   IN  UINTN                                 DestinationX,
    523   IN  UINTN                                 DestinationY,
    524   IN  UINTN                                 Width,
    525   IN  UINTN                                 Height
    526   )
    527 {
    528   return BltLibBufferToVideoEx (
    529            BltBuffer,
    530            0,
    531            0,
    532            DestinationX,
    533            DestinationY,
    534            Width,
    535            Height,
    536            0
    537            );
    538 }
    539 
    540 
    541 /**
    542   Performs a UEFI Graphics Output Protocol Blt Buffer to Video operation
    543   with extended parameters.
    544 
    545   @param[in]  BltBuffer     Output buffer for pixel color data
    546   @param[in]  SourceX       X location within BltBuffer
    547   @param[in]  SourceY       Y location within BltBuffer
    548   @param[in]  DestinationX  X location within video
    549   @param[in]  DestinationY  Y location within video
    550   @param[in]  Width         Width (in pixels)
    551   @param[in]  Height        Height
    552   @param[in]  Delta         Number of bytes in a row of BltBuffer
    553 
    554   @retval  EFI_DEVICE_ERROR - A hardware error occured
    555   @retval  EFI_INVALID_PARAMETER - Invalid parameter passed in
    556   @retval  EFI_SUCCESS - The sizes were returned
    557 
    558 **/
    559 EFI_STATUS
    560 EFIAPI
    561 BltLibBufferToVideoEx (
    562   IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL         *BltBuffer,
    563   IN  UINTN                                 SourceX,
    564   IN  UINTN                                 SourceY,
    565   IN  UINTN                                 DestinationX,
    566   IN  UINTN                                 DestinationY,
    567   IN  UINTN                                 Width,
    568   IN  UINTN                                 Height,
    569   IN  UINTN                                 Delta
    570   )
    571 {
    572   UINTN                           DstY;
    573   UINTN                           SrcY;
    574   EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *Blt;
    575   VOID                            *BltMemSrc;
    576   VOID                            *BltMemDst;
    577   UINTN                           X;
    578   UINT32                          Uint32;
    579   UINTN                           Offset;
    580   UINTN                           WidthInBytes;
    581 
    582   //
    583   // BltBuffer to Video: Source is BltBuffer, destination is Video
    584   //
    585   if (DestinationY + Height > mBltLibHeight) {
    586     return EFI_INVALID_PARAMETER;
    587   }
    588 
    589   if (DestinationX + Width > mBltLibWidthInPixels) {
    590     return EFI_INVALID_PARAMETER;
    591   }
    592 
    593   if (Width == 0 || Height == 0) {
    594     return EFI_INVALID_PARAMETER;
    595   }
    596 
    597   //
    598   // If Delta is zero, then the entire BltBuffer is being used, so Delta
    599   // is the number of bytes in each row of BltBuffer.  Since BltBuffer is Width pixels size,
    600   // the number of bytes in each row can be computed.
    601   //
    602   if (Delta == 0) {
    603     Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
    604   }
    605 
    606   WidthInBytes = Width * mBltLibBytesPerPixel;
    607 
    608   for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
    609 
    610     Offset = (DstY * mBltLibWidthInPixels) + DestinationX;
    611     Offset = mBltLibBytesPerPixel * Offset;
    612     BltMemDst = (VOID*) (mBltLibFrameBuffer + Offset);
    613 
    614     if (mPixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
    615       BltMemSrc = (VOID *) ((UINT8 *) BltBuffer + (SrcY * Delta));
    616     } else {
    617       for (X = 0; X < Width; X++) {
    618         Blt =
    619           (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (
    620               (UINT8 *) BltBuffer +
    621               (SrcY * Delta) +
    622               ((SourceX + X) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))
    623             );
    624         Uint32 = *(UINT32*) Blt;
    625         *(UINT32*) (mBltLibLineBuffer + (X * mBltLibBytesPerPixel)) =
    626           (UINT32) (
    627               (((Uint32 << mPixelShl[0]) >> mPixelShr[0]) & mPixelBitMasks.RedMask) |
    628               (((Uint32 << mPixelShl[1]) >> mPixelShr[1]) & mPixelBitMasks.GreenMask) |
    629               (((Uint32 << mPixelShl[2]) >> mPixelShr[2]) & mPixelBitMasks.BlueMask)
    630             );
    631       }
    632       BltMemSrc = (VOID *) mBltLibLineBuffer;
    633     }
    634 
    635     CopyMem (BltMemDst, BltMemSrc, WidthInBytes);
    636   }
    637 
    638   return EFI_SUCCESS;
    639 }
    640 
    641 
    642 /**
    643   Performs a UEFI Graphics Output Protocol Blt Video to Video operation
    644 
    645   @param[in]  SourceX       X location within video
    646   @param[in]  SourceY       Y location within video
    647   @param[in]  DestinationX  X location within video
    648   @param[in]  DestinationY  Y location within video
    649   @param[in]  Width         Width (in pixels)
    650   @param[in]  Height        Height
    651 
    652   @retval  EFI_DEVICE_ERROR - A hardware error occured
    653   @retval  EFI_INVALID_PARAMETER - Invalid parameter passed in
    654   @retval  EFI_SUCCESS - The sizes were returned
    655 
    656 **/
    657 EFI_STATUS
    658 EFIAPI
    659 BltLibVideoToVideo (
    660   IN  UINTN                                 SourceX,
    661   IN  UINTN                                 SourceY,
    662   IN  UINTN                                 DestinationX,
    663   IN  UINTN                                 DestinationY,
    664   IN  UINTN                                 Width,
    665   IN  UINTN                                 Height
    666   )
    667 {
    668   VOID                            *BltMemSrc;
    669   VOID                            *BltMemDst;
    670   UINTN                           Offset;
    671   UINTN                           WidthInBytes;
    672   INTN                            LineStride;
    673 
    674   //
    675   // Video to Video: Source is Video, destination is Video
    676   //
    677   if (SourceY + Height > mBltLibHeight) {
    678     return EFI_INVALID_PARAMETER;
    679   }
    680 
    681   if (SourceX + Width > mBltLibWidthInPixels) {
    682     return EFI_INVALID_PARAMETER;
    683   }
    684 
    685   if (DestinationY + Height > mBltLibHeight) {
    686     return EFI_INVALID_PARAMETER;
    687   }
    688 
    689   if (DestinationX + Width > mBltLibWidthInPixels) {
    690     return EFI_INVALID_PARAMETER;
    691   }
    692 
    693   if (Width == 0 || Height == 0) {
    694     return EFI_INVALID_PARAMETER;
    695   }
    696 
    697   WidthInBytes = Width * mBltLibBytesPerPixel;
    698 
    699   Offset = (SourceY * mBltLibWidthInPixels) + SourceX;
    700   Offset = mBltLibBytesPerPixel * Offset;
    701   BltMemSrc = (VOID *) (mBltLibFrameBuffer + Offset);
    702 
    703   Offset = (DestinationY * mBltLibWidthInPixels) + DestinationX;
    704   Offset = mBltLibBytesPerPixel * Offset;
    705   BltMemDst = (VOID *) (mBltLibFrameBuffer + Offset);
    706 
    707   LineStride = mBltLibWidthInBytes;
    708   if ((UINTN) BltMemDst > (UINTN) BltMemSrc) {
    709     LineStride = -LineStride;
    710   }
    711 
    712   while (Height > 0) {
    713     CopyMem (BltMemDst, BltMemSrc, WidthInBytes);
    714 
    715     BltMemSrc = (VOID*) ((UINT8*) BltMemSrc + LineStride);
    716     BltMemDst = (VOID*) ((UINT8*) BltMemDst + LineStride);
    717     Height--;
    718   }
    719 
    720   return EFI_SUCCESS;
    721 }
    722 
    723 
    724 /**
    725   Returns the sizes related to the video device
    726 
    727   @param[out]  Width   Width (in pixels)
    728   @param[out]  Height  Height (in pixels)
    729 
    730   @retval  EFI_INVALID_PARAMETER - Invalid parameter passed in
    731   @retval  EFI_SUCCESS - The sizes were returned
    732 
    733 **/
    734 EFI_STATUS
    735 EFIAPI
    736 BltLibGetSizes (
    737   OUT UINTN                                 *Width,  OPTIONAL
    738   OUT UINTN                                 *Height  OPTIONAL
    739   )
    740 {
    741   if (Width != NULL) {
    742     *Width = mBltLibWidthInPixels;
    743   }
    744   if (Height != NULL) {
    745     *Height = mBltLibHeight;
    746   }
    747 
    748   return EFI_SUCCESS;
    749 }
    750 
    751