Home | History | Annotate | Download | only in LcdGraphicsOutputDxe
      1 /** @file
      2 
      3  Copyright (c) 2011-2013, ARM Ltd. All rights reserved.<BR>
      4  This program and the accompanying materials
      5  are licensed and made available under the terms and conditions of the BSD License
      6  which accompanies this distribution.  The full text of the license may be found at
      7  http://opensource.org/licenses/bsd-license.php
      8 
      9  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12  **/
     13 
     14 #include <PiDxe.h>
     15 #include <Library/BaseMemoryLib.h>
     16 #include <Library/DevicePathLib.h>
     17 #include <Library/UefiBootServicesTableLib.h>
     18 #include <Library/UefiRuntimeServicesTableLib.h>
     19 #include <Library/MemoryAllocationLib.h>
     20 
     21 #include <Guid/GlobalVariable.h>
     22 
     23 #include "LcdGraphicsOutputDxe.h"
     24 
     25 extern BOOLEAN mDisplayInitialized;
     26 
     27 //
     28 // Function Definitions
     29 //
     30 
     31 STATIC
     32 EFI_STATUS
     33 VideoCopyNoHorizontalOverlap (
     34   IN UINTN          BitsPerPixel,
     35   IN volatile VOID  *FrameBufferBase,
     36   IN UINT32         HorizontalResolution,
     37   IN UINTN          SourceX,
     38   IN UINTN          SourceY,
     39   IN UINTN          DestinationX,
     40   IN UINTN          DestinationY,
     41   IN UINTN          Width,
     42   IN UINTN          Height
     43 )
     44 {
     45   EFI_STATUS    Status = EFI_SUCCESS;
     46   UINTN         SourceLine;
     47   UINTN         DestinationLine;
     48   UINTN         WidthInBytes;
     49   UINTN         LineCount;
     50   INTN          Step;
     51   VOID          *SourceAddr;
     52   VOID          *DestinationAddr;
     53 
     54   if( DestinationY <= SourceY ) {
     55     // scrolling up (or horizontally but without overlap)
     56     SourceLine       = SourceY;
     57     DestinationLine  = DestinationY;
     58     Step             = 1;
     59   } else {
     60     // scrolling down
     61     SourceLine       = SourceY + Height;
     62     DestinationLine  = DestinationY + Height;
     63     Step             = -1;
     64   }
     65 
     66   switch (BitsPerPixel) {
     67 
     68   case LCD_BITS_PER_PIXEL_24:
     69 
     70     WidthInBytes = Width * 4;
     71 
     72     for( LineCount = 0; LineCount < Height; LineCount++ ) {
     73       // Update the start addresses of source & destination using 32bit pointer arithmetic
     74       SourceAddr      = (VOID *)((UINT32 *)FrameBufferBase + SourceLine      * HorizontalResolution + SourceX     );
     75       DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);
     76 
     77       // Copy the entire line Y from video ram to the temp buffer
     78       CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
     79 
     80       // Update the line numbers
     81       SourceLine      += Step;
     82       DestinationLine += Step;
     83     }
     84     break;
     85 
     86   case LCD_BITS_PER_PIXEL_16_555:
     87   case LCD_BITS_PER_PIXEL_16_565:
     88   case LCD_BITS_PER_PIXEL_12_444:
     89 
     90     WidthInBytes = Width * 2;
     91 
     92     for( LineCount = 0; LineCount < Height; LineCount++ ) {
     93       // Update the start addresses of source & destination using 16bit pointer arithmetic
     94       SourceAddr      = (VOID *)((UINT16 *)FrameBufferBase + SourceLine      * HorizontalResolution + SourceX     );
     95       DestinationAddr = (VOID *)((UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);
     96 
     97       // Copy the entire line Y from video ram to the temp buffer
     98       CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
     99 
    100       // Update the line numbers
    101       SourceLine      += Step;
    102       DestinationLine += Step;
    103     }
    104     break;
    105 
    106   case LCD_BITS_PER_PIXEL_8:
    107   case LCD_BITS_PER_PIXEL_4:
    108   case LCD_BITS_PER_PIXEL_2:
    109   case LCD_BITS_PER_PIXEL_1:
    110   default:
    111     // Can't handle this case
    112     DEBUG((DEBUG_ERROR, "ArmVeGraphics_Blt: EfiBltVideoToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
    113     Status = EFI_INVALID_PARAMETER;
    114     goto EXIT;
    115     // break;
    116 
    117   }
    118 
    119   EXIT:
    120   return Status;
    121 }
    122 
    123 STATIC
    124 EFI_STATUS
    125 VideoCopyHorizontalOverlap (
    126   IN UINTN          BitsPerPixel,
    127   IN volatile VOID  *FrameBufferBase,
    128   UINT32            HorizontalResolution,
    129   IN UINTN          SourceX,
    130   IN UINTN          SourceY,
    131   IN UINTN          DestinationX,
    132   IN UINTN          DestinationY,
    133   IN UINTN          Width,
    134   IN UINTN          Height
    135 )
    136 {
    137   EFI_STATUS      Status = EFI_SUCCESS;
    138 
    139   UINT32 *PixelBuffer32bit;
    140   UINT32 *SourcePixel32bit;
    141   UINT32 *DestinationPixel32bit;
    142 
    143   UINT16 *PixelBuffer16bit;
    144   UINT16 *SourcePixel16bit;
    145   UINT16 *DestinationPixel16bit;
    146 
    147   UINT32          SourcePixelY;
    148   UINT32          DestinationPixelY;
    149   UINTN           SizeIn32Bits;
    150   UINTN           SizeIn16Bits;
    151 
    152   switch (BitsPerPixel) {
    153 
    154   case LCD_BITS_PER_PIXEL_24:
    155     // Allocate a temporary buffer
    156 
    157     PixelBuffer32bit = (UINT32 *) AllocatePool((Height * Width) * sizeof(UINT32));
    158 
    159     if (PixelBuffer32bit == NULL) {
    160       Status = EFI_OUT_OF_RESOURCES;
    161       goto EXIT;
    162     }
    163 
    164     SizeIn32Bits = Width * 4;
    165 
    166     // Copy from the video ram (source region) to a temp buffer
    167     for (SourcePixelY = SourceY, DestinationPixel32bit = PixelBuffer32bit;
    168          SourcePixelY < SourceY + Height;
    169          SourcePixelY++, DestinationPixel32bit += Width)
    170     {
    171       // Update the start address of line Y (source)
    172       SourcePixel32bit = (UINT32 *)FrameBufferBase + SourcePixelY * HorizontalResolution + SourceX;
    173 
    174       // Copy the entire line Y from video ram to the temp buffer
    175       CopyMem( (VOID *)DestinationPixel32bit, (CONST VOID *)SourcePixel32bit, SizeIn32Bits);
    176     }
    177 
    178     // Copy from the temp buffer to the video ram (destination region)
    179     for (DestinationPixelY = DestinationY, SourcePixel32bit = PixelBuffer32bit;
    180          DestinationPixelY < DestinationY + Height;
    181          DestinationPixelY++, SourcePixel32bit += Width)
    182     {
    183       // Update the start address of line Y (target)
    184       DestinationPixel32bit = (UINT32 *)FrameBufferBase + DestinationPixelY * HorizontalResolution + DestinationX;
    185 
    186       // Copy the entire line Y from the temp buffer to video ram
    187       CopyMem( (VOID *)DestinationPixel32bit, (CONST VOID *)SourcePixel32bit, SizeIn32Bits);
    188     }
    189 
    190     // Free up the allocated memory
    191     FreePool((VOID *) PixelBuffer32bit);
    192 
    193     break;
    194 
    195 
    196   case LCD_BITS_PER_PIXEL_16_555:
    197   case LCD_BITS_PER_PIXEL_16_565:
    198   case LCD_BITS_PER_PIXEL_12_444:
    199     // Allocate a temporary buffer
    200     PixelBuffer16bit = (UINT16 *) AllocatePool((Height * Width) * sizeof(UINT16));
    201 
    202     if (PixelBuffer16bit == NULL) {
    203       Status = EFI_OUT_OF_RESOURCES;
    204       goto EXIT;
    205     }
    206 
    207     // Access each pixel inside the source area of the Video Memory and copy it to the temp buffer
    208 
    209     SizeIn16Bits = Width * 2;
    210 
    211     for (SourcePixelY = SourceY, DestinationPixel16bit = PixelBuffer16bit;
    212          SourcePixelY < SourceY + Height;
    213          SourcePixelY++, DestinationPixel16bit += Width)
    214     {
    215       // Calculate the source address:
    216       SourcePixel16bit = (UINT16 *)FrameBufferBase + SourcePixelY * HorizontalResolution + SourceX;
    217 
    218       // Copy the entire line Y from Video to the temp buffer
    219       CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits);
    220     }
    221 
    222     // Copy from the temp buffer into the destination area of the Video Memory
    223 
    224     for (DestinationPixelY = DestinationY, SourcePixel16bit = PixelBuffer16bit;
    225          DestinationPixelY < DestinationY + Height;
    226          DestinationPixelY++, SourcePixel16bit += Width)
    227     {
    228       // Calculate the target address:
    229       DestinationPixel16bit = (UINT16 *)FrameBufferBase + (DestinationPixelY * HorizontalResolution + DestinationX);
    230 
    231       // Copy the entire line Y from the temp buffer to Video
    232       CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits);
    233     }
    234 
    235     // Free the allocated memory
    236     FreePool((VOID *) PixelBuffer16bit);
    237 
    238     break;
    239 
    240 
    241   case LCD_BITS_PER_PIXEL_8:
    242   case LCD_BITS_PER_PIXEL_4:
    243   case LCD_BITS_PER_PIXEL_2:
    244   case LCD_BITS_PER_PIXEL_1:
    245   default:
    246     // Can't handle this case
    247     DEBUG((DEBUG_ERROR, "ArmVeGraphics_Blt: EfiBltVideoToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
    248     Status = EFI_INVALID_PARAMETER;
    249     goto EXIT;
    250     // break;
    251 
    252   }
    253 
    254 EXIT:
    255   return Status;
    256 }
    257 
    258 STATIC
    259 EFI_STATUS
    260 BltVideoFill (
    261   IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
    262   IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *EfiSourcePixel,     OPTIONAL
    263   IN UINTN                               SourceX,
    264   IN UINTN                               SourceY,
    265   IN UINTN                               DestinationX,
    266   IN UINTN                               DestinationY,
    267   IN UINTN                               Width,
    268   IN UINTN                               Height,
    269   IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
    270   )
    271 {
    272   EFI_PIXEL_BITMASK*  PixelInformation;
    273   EFI_STATUS         Status;
    274   UINT32             HorizontalResolution;
    275   LCD_BPP            BitsPerPixel;
    276   VOID            *FrameBufferBase;
    277   VOID            *DestinationAddr;
    278   UINT16          *DestinationPixel16bit;
    279   UINT16          Pixel16bit;
    280   UINT32          DestinationPixelX;
    281   UINT32          DestinationLine;
    282   UINTN           WidthInBytes;
    283 
    284   Status           = EFI_SUCCESS;
    285   PixelInformation = &This->Mode->Info->PixelInformation;
    286   FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
    287   HorizontalResolution = This->Mode->Info->HorizontalResolution;
    288 
    289   LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
    290 
    291   switch (BitsPerPixel) {
    292   case LCD_BITS_PER_PIXEL_24:
    293     WidthInBytes = Width * 4;
    294 
    295     // Copy the SourcePixel into every pixel inside the target rectangle
    296     for (DestinationLine = DestinationY;
    297          DestinationLine < DestinationY + Height;
    298          DestinationLine++)
    299     {
    300       // Calculate the target address using 32bit pointer arithmetic:
    301       DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution  + DestinationX);
    302 
    303       // Fill the entire line
    304       SetMem32 (DestinationAddr, WidthInBytes, *((UINT32 *)EfiSourcePixel));
    305     }
    306     break;
    307 
    308   case LCD_BITS_PER_PIXEL_16_555:
    309     // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
    310     Pixel16bit = (UINT16) (
    311         ( (EfiSourcePixel->Red      <<  7) & PixelInformation->RedMask      )
    312       | ( (EfiSourcePixel->Green    <<  2) & PixelInformation->GreenMask    )
    313       | ( (EfiSourcePixel->Blue     >>  3) & PixelInformation->BlueMask     )
    314 //      | ( 0                           & PixelInformation->ReservedMask )
    315      );
    316 
    317     // Copy the SourcePixel into every pixel inside the target rectangle
    318     for (DestinationLine = DestinationY;
    319          DestinationLine < DestinationY + Height;
    320          DestinationLine++)
    321     {
    322       for (DestinationPixelX = DestinationX;
    323            DestinationPixelX < DestinationX + Width;
    324            DestinationPixelX++)
    325       {
    326         // Calculate the target address:
    327         DestinationPixel16bit =  (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
    328 
    329         // Copy the pixel into the new target
    330         *DestinationPixel16bit = Pixel16bit;
    331       }
    332     }
    333     break;
    334 
    335   case LCD_BITS_PER_PIXEL_16_565:
    336     // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
    337     Pixel16bit = (UINT16) (
    338         ( (EfiSourcePixel->Red      <<  8) & PixelInformation->RedMask      )
    339       | ( (EfiSourcePixel->Green    <<  3) & PixelInformation->GreenMask    )
    340       | ( (EfiSourcePixel->Blue     >>  3) & PixelInformation->BlueMask     )
    341      );
    342 
    343     // Copy the SourcePixel into every pixel inside the target rectangle
    344     for (DestinationLine = DestinationY;
    345          DestinationLine < DestinationY + Height;
    346          DestinationLine++)
    347     {
    348       for (DestinationPixelX = DestinationX;
    349            DestinationPixelX < DestinationX + Width;
    350            DestinationPixelX++)
    351       {
    352         // Calculate the target address:
    353         DestinationPixel16bit =  (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution  + DestinationPixelX;
    354 
    355         // Copy the pixel into the new target
    356         *DestinationPixel16bit = Pixel16bit;
    357       }
    358     }
    359     break;
    360 
    361   case LCD_BITS_PER_PIXEL_12_444:
    362     // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
    363     Pixel16bit = (UINT16) (
    364         ( (EfiSourcePixel->Red      >> 4) & PixelInformation->RedMask      )
    365       | ( (EfiSourcePixel->Green        ) & PixelInformation->GreenMask    )
    366       | ( (EfiSourcePixel->Blue     << 4) & PixelInformation->BlueMask     )
    367      );
    368 
    369     // Copy the SourcePixel into every pixel inside the target rectangle
    370     for (DestinationLine = DestinationY;
    371          DestinationLine < DestinationY + Height;
    372          DestinationLine++)
    373     {
    374       for (DestinationPixelX = DestinationX;
    375            DestinationPixelX < DestinationX + Width;
    376            DestinationPixelX++)
    377       {
    378         // Calculate the target address:
    379         DestinationPixel16bit =  (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution  + DestinationPixelX;
    380 
    381         // Copy the pixel into the new target
    382         *DestinationPixel16bit = Pixel16bit;
    383       }
    384     }
    385     break;
    386 
    387   case LCD_BITS_PER_PIXEL_8:
    388   case LCD_BITS_PER_PIXEL_4:
    389   case LCD_BITS_PER_PIXEL_2:
    390   case LCD_BITS_PER_PIXEL_1:
    391   default:
    392     // Can't handle this case
    393     DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltVideoFill: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
    394     Status = EFI_INVALID_PARAMETER;
    395     break;
    396   }
    397 
    398   return Status;
    399 }
    400 
    401 STATIC
    402 EFI_STATUS
    403 BltVideoToBltBuffer (
    404   IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
    405   IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,     OPTIONAL
    406   IN UINTN                               SourceX,
    407   IN UINTN                               SourceY,
    408   IN UINTN                               DestinationX,
    409   IN UINTN                               DestinationY,
    410   IN UINTN                               Width,
    411   IN UINTN                               Height,
    412   IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
    413   )
    414 {
    415   EFI_STATUS         Status;
    416   UINT32             HorizontalResolution;
    417   LCD_BPP            BitsPerPixel;
    418   EFI_PIXEL_BITMASK  *PixelInformation;
    419   EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiDestinationPixel;
    420   VOID   *FrameBufferBase;
    421   VOID            *SourceAddr;
    422   VOID            *DestinationAddr;
    423   UINT16 *SourcePixel16bit;
    424   UINT16          Pixel16bit;
    425   UINT32          SourcePixelX;
    426   UINT32          SourceLine;
    427   UINT32          DestinationPixelX;
    428   UINT32          DestinationLine;
    429   UINT32          BltBufferHorizontalResolution;
    430   UINTN           WidthInBytes;
    431 
    432   Status = EFI_SUCCESS;
    433   PixelInformation = &This->Mode->Info->PixelInformation;
    434   HorizontalResolution = This->Mode->Info->HorizontalResolution;
    435   FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
    436 
    437   if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
    438     // Delta is not zero and it is different from the width.
    439     // Divide it by the size of a pixel to find out the buffer's horizontal resolution.
    440     BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
    441   } else {
    442     BltBufferHorizontalResolution = Width;
    443   }
    444 
    445   LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
    446 
    447   switch (BitsPerPixel) {
    448   case LCD_BITS_PER_PIXEL_24:
    449     WidthInBytes = Width * 4;
    450 
    451     // Access each line inside the Video Memory
    452     for (SourceLine = SourceY, DestinationLine = DestinationY;
    453          SourceLine < SourceY + Height;
    454          SourceLine++, DestinationLine++)
    455     {
    456       // Calculate the source and target addresses using 32bit pointer arithmetic:
    457       SourceAddr      = (VOID *)((UINT32 *)FrameBufferBase + SourceLine      * HorizontalResolution          + SourceX     );
    458       DestinationAddr = (VOID *)((UINT32 *)BltBuffer       + DestinationLine * BltBufferHorizontalResolution + DestinationX);
    459 
    460       // Copy the entire line
    461       CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
    462     }
    463     break;
    464 
    465   case LCD_BITS_PER_PIXEL_16_555:
    466     // Access each pixel inside the Video Memory
    467     for (SourceLine = SourceY, DestinationLine = DestinationY;
    468          SourceLine < SourceY + Height;
    469          SourceLine++, DestinationLine++)
    470     {
    471       for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
    472            SourcePixelX < SourceX + Width;
    473            SourcePixelX++, DestinationPixelX++)
    474       {
    475         // Calculate the source and target addresses:
    476         SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;
    477         EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;
    478 
    479         // Snapshot the pixel from the video buffer once, to speed up the operation.
    480         // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
    481         Pixel16bit = *SourcePixel16bit;
    482 
    483         // Copy the pixel into the new target
    484         EfiDestinationPixel->Red      = (UINT8) ( (Pixel16bit & PixelInformation->RedMask     ) >>  7 );
    485         EfiDestinationPixel->Green    = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask   ) >>  2);
    486         EfiDestinationPixel->Blue     = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask    ) <<  3 );
    487         // EfiDestinationPixel->Reserved = (UINT8) 0;
    488       }
    489     }
    490     break;
    491 
    492   case LCD_BITS_PER_PIXEL_16_565:
    493     // Access each pixel inside the Video Memory
    494     for (SourceLine = SourceY, DestinationLine = DestinationY;
    495          SourceLine < SourceY + Height;
    496          SourceLine++, DestinationLine++)
    497     {
    498       for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
    499            SourcePixelX < SourceX + Width;
    500            SourcePixelX++, DestinationPixelX++)
    501       {
    502         // Calculate the source and target addresses:
    503         SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;
    504         EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;
    505 
    506         // Snapshot the pixel from the video buffer once, to speed up the operation.
    507         // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
    508         Pixel16bit = *SourcePixel16bit;
    509 
    510         // Copy the pixel into the new target
    511         // There is no info for the Reserved byte, so we set it to zero
    512         EfiDestinationPixel->Red      = (UINT8) ( (Pixel16bit & PixelInformation->RedMask     ) >> 8 );
    513         EfiDestinationPixel->Green    = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask   ) >> 3);
    514         EfiDestinationPixel->Blue     = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask    ) << 3 );
    515         // EfiDestinationPixel->Reserved = (UINT8) 0;
    516       }
    517     }
    518     break;
    519 
    520   case LCD_BITS_PER_PIXEL_12_444:
    521     // Access each pixel inside the Video Memory
    522     for (SourceLine = SourceY, DestinationLine = DestinationY;
    523          SourceLine < SourceY + Height;
    524          SourceLine++, DestinationLine++)
    525     {
    526       for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
    527            SourcePixelX < SourceX + Width;
    528            SourcePixelX++, DestinationPixelX++)
    529       {
    530         // Calculate the source and target addresses:
    531         SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;
    532         EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;
    533 
    534         // Snapshot the pixel from the video buffer once, to speed up the operation.
    535         // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
    536         Pixel16bit = *SourcePixel16bit;
    537 
    538         // Copy the pixel into the new target
    539         EfiDestinationPixel->Red      = (UINT8) ( (Pixel16bit & PixelInformation->RedMask     ) >> 4 );
    540         EfiDestinationPixel->Green    = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask   )     );
    541         EfiDestinationPixel->Blue     = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask    ) << 4 );
    542         // EfiDestinationPixel->Reserved = (UINT8) 0;
    543       }
    544     }
    545     break;
    546 
    547   case LCD_BITS_PER_PIXEL_8:
    548   case LCD_BITS_PER_PIXEL_4:
    549   case LCD_BITS_PER_PIXEL_2:
    550   case LCD_BITS_PER_PIXEL_1:
    551   default:
    552     // Can't handle this case
    553     DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltVideoToBltBuffer: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
    554     Status = EFI_INVALID_PARAMETER;
    555     break;
    556   }
    557   return Status;
    558 }
    559 
    560 STATIC
    561 EFI_STATUS
    562 BltBufferToVideo (
    563   IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
    564   IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,     OPTIONAL
    565   IN UINTN                               SourceX,
    566   IN UINTN                               SourceY,
    567   IN UINTN                               DestinationX,
    568   IN UINTN                               DestinationY,
    569   IN UINTN                               Width,
    570   IN UINTN                               Height,
    571   IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
    572   )
    573 {
    574   EFI_STATUS         Status;
    575   UINT32             HorizontalResolution;
    576   LCD_BPP            BitsPerPixel;
    577   EFI_PIXEL_BITMASK  *PixelInformation;
    578   EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiSourcePixel;
    579   VOID   *FrameBufferBase;
    580   VOID            *SourceAddr;
    581   VOID            *DestinationAddr;
    582   UINT16 *DestinationPixel16bit;
    583   UINT32          SourcePixelX;
    584   UINT32          SourceLine;
    585   UINT32          DestinationPixelX;
    586   UINT32          DestinationLine;
    587   UINT32          BltBufferHorizontalResolution;
    588   UINTN           WidthInBytes;
    589 
    590   Status = EFI_SUCCESS;
    591   PixelInformation = &This->Mode->Info->PixelInformation;
    592   HorizontalResolution = This->Mode->Info->HorizontalResolution;
    593   FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
    594 
    595   if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
    596     // Delta is not zero and it is different from the width.
    597     // Divide it by the size of a pixel to find out the buffer's horizontal resolution.
    598     BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
    599   } else {
    600     BltBufferHorizontalResolution = Width;
    601   }
    602 
    603   LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
    604 
    605   switch (BitsPerPixel) {
    606   case LCD_BITS_PER_PIXEL_24:
    607     WidthInBytes = Width * 4;
    608 
    609     // Access each pixel inside the BltBuffer Memory
    610     for (SourceLine = SourceY, DestinationLine = DestinationY;
    611        SourceLine < SourceY + Height;
    612        SourceLine++, DestinationLine++)
    613     {
    614       // Calculate the source and target addresses using 32bit pointer arithmetic:
    615       SourceAddr      = (VOID *)((UINT32 *)BltBuffer       + SourceLine      * BltBufferHorizontalResolution + SourceX     );
    616       DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution          + DestinationX);
    617 
    618       // Copy the entire row Y
    619       CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
    620     }
    621     break;
    622 
    623   case LCD_BITS_PER_PIXEL_16_555:
    624     // Access each pixel inside the BltBuffer Memory
    625     for (SourceLine = SourceY, DestinationLine = DestinationY;
    626        SourceLine < SourceY + Height;
    627        SourceLine++, DestinationLine++) {
    628 
    629       for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
    630            SourcePixelX < SourceX + Width;
    631            SourcePixelX++, DestinationPixelX++)
    632       {
    633         // Calculate the source and target addresses:
    634         EfiSourcePixel  = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;
    635         DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
    636 
    637         // Copy the pixel into the new target
    638         // Only the most significant bits will be copied across:
    639         // To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits
    640         *DestinationPixel16bit = (UINT16) (
    641               ( (EfiSourcePixel->Red      <<  7) & PixelInformation->RedMask      )
    642             | ( (EfiSourcePixel->Green    <<  2) & PixelInformation->GreenMask    )
    643             | ( (EfiSourcePixel->Blue     >>  3) & PixelInformation->BlueMask     )
    644       //            | ( 0                                & PixelInformation->ReservedMask )
    645             );
    646       }
    647     }
    648     break;
    649 
    650   case LCD_BITS_PER_PIXEL_16_565:
    651     // Access each pixel inside the BltBuffer Memory
    652     for (SourceLine = SourceY, DestinationLine = DestinationY;
    653          SourceLine < SourceY + Height;
    654          SourceLine++, DestinationLine++) {
    655 
    656       for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
    657            SourcePixelX < SourceX + Width;
    658            SourcePixelX++, DestinationPixelX++)
    659       {
    660         // Calculate the source and target addresses:
    661         EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;
    662         DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
    663 
    664         // Copy the pixel into the new target
    665         // Only the most significant bits will be copied across:
    666         // To convert from 8 bits to 5 or 6 bits per pixel we throw away the 3 or 2  least significant bits
    667         // There is no room for the Reserved byte so we ignore that completely
    668         *DestinationPixel16bit = (UINT16) (
    669               ( (EfiSourcePixel->Red      <<  8) & PixelInformation->RedMask      )
    670             | ( (EfiSourcePixel->Green    <<  3) & PixelInformation->GreenMask    )
    671             | ( (EfiSourcePixel->Blue     >>  3) & PixelInformation->BlueMask     )
    672            );
    673       }
    674     }
    675     break;
    676 
    677   case LCD_BITS_PER_PIXEL_12_444:
    678     // Access each pixel inside the BltBuffer Memory
    679     for (SourceLine = SourceY, DestinationLine = DestinationY;
    680          SourceLine < SourceY + Height;
    681          SourceLine++, DestinationLine++) {
    682 
    683       for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
    684            SourcePixelX < SourceX + Width;
    685            SourcePixelX++, DestinationPixelX++)
    686       {
    687         // Calculate the source and target addresses:
    688         EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;
    689         DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
    690 
    691         // Copy the pixel into the new target
    692         // Only the most significant bits will be copied across:
    693         // To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits
    694         *DestinationPixel16bit = (UINT16) (
    695               ( (EfiSourcePixel->Red      << 4) & PixelInformation->RedMask      )
    696             | ( (EfiSourcePixel->Green        ) & PixelInformation->GreenMask    )
    697             | ( (EfiSourcePixel->Blue     >> 4) & PixelInformation->BlueMask     )
    698   //            | ( 0                               & PixelInformation->ReservedMask )
    699            );
    700       }
    701     }
    702     break;
    703 
    704   case LCD_BITS_PER_PIXEL_8:
    705   case LCD_BITS_PER_PIXEL_4:
    706   case LCD_BITS_PER_PIXEL_2:
    707   case LCD_BITS_PER_PIXEL_1:
    708   default:
    709     // Can't handle this case
    710     DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltBufferToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
    711     Status = EFI_INVALID_PARAMETER;
    712     break;
    713   }
    714   return Status;
    715 }
    716 
    717 STATIC
    718 EFI_STATUS
    719 BltVideoToVideo (
    720   IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
    721   IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,     OPTIONAL
    722   IN UINTN                               SourceX,
    723   IN UINTN                               SourceY,
    724   IN UINTN                               DestinationX,
    725   IN UINTN                               DestinationY,
    726   IN UINTN                               Width,
    727   IN UINTN                               Height,
    728   IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
    729   )
    730 {
    731   EFI_STATUS         Status;
    732   UINT32             HorizontalResolution;
    733   LCD_BPP            BitsPerPixel;
    734   VOID   *FrameBufferBase;
    735 
    736   HorizontalResolution = This->Mode->Info->HorizontalResolution;
    737   FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
    738 
    739   //
    740   // BltVideo to BltVideo:
    741   //
    742   //  Source is the Video Memory,
    743   //  Destination is the Video Memory
    744 
    745   LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
    746   FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
    747 
    748   // The UEFI spec currently states:
    749   // "There is no limitation on the overlapping of the source and destination rectangles"
    750   // Therefore, we must be careful to avoid overwriting the source data
    751   if( SourceY == DestinationY ) {
    752     // Copying within the same height, e.g. horizontal shift
    753     if( SourceX == DestinationX ) {
    754       // Nothing to do
    755       Status = EFI_SUCCESS;
    756     } else if( ((SourceX>DestinationX)?(SourceX - DestinationX):(DestinationX - SourceX)) < Width ) {
    757       // There is overlap
    758       Status = VideoCopyHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
    759     } else {
    760       // No overlap
    761       Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
    762     }
    763   } else {
    764     // Copying from different heights
    765     Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
    766   }
    767 
    768   return Status;
    769 }
    770 
    771 /***************************************
    772  * GraphicsOutput Protocol function, mapping to
    773  * EFI_GRAPHICS_OUTPUT_PROTOCOL.Blt
    774  *
    775  * PRESUMES: 1 pixel = 4 bytes (32bits)
    776  *  ***************************************/
    777 EFI_STATUS
    778 EFIAPI
    779 LcdGraphicsBlt (
    780   IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
    781   IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,     OPTIONAL
    782   IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION   BltOperation,
    783   IN UINTN                               SourceX,
    784   IN UINTN                               SourceY,
    785   IN UINTN                               DestinationX,
    786   IN UINTN                               DestinationY,
    787   IN UINTN                               Width,
    788   IN UINTN                               Height,
    789   IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
    790   )
    791 {
    792   EFI_STATUS         Status;
    793   UINT32             HorizontalResolution;
    794   UINT32             VerticalResolution;
    795   LCD_INSTANCE*      Instance;
    796 
    797   Instance = LCD_INSTANCE_FROM_GOP_THIS(This);
    798 
    799   // Setup the hardware if not already done
    800   if (!mDisplayInitialized) {
    801     Status = InitializeDisplay (Instance);
    802     if (EFI_ERROR(Status)) {
    803       goto EXIT;
    804     }
    805   }
    806 
    807   HorizontalResolution = This->Mode->Info->HorizontalResolution;
    808   VerticalResolution   = This->Mode->Info->VerticalResolution;
    809 
    810   DEBUG((DEBUG_INFO, "LcdGraphicsBlt (BltOperation:%d,DestX:%d,DestY:%d,Width:%d,Height:%d) res(%d,%d)\n",
    811       BltOperation,DestinationX,DestinationY,Width,Height,HorizontalResolution,VerticalResolution));
    812 
    813   // Check we have reasonable parameters
    814   if (Width == 0 || Height == 0) {
    815     DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: ERROR - Invalid dimension: Zero size area.\n" ));
    816     Status = EFI_INVALID_PARAMETER;
    817     goto EXIT;
    818   }
    819 
    820   if ((BltOperation == EfiBltVideoFill) || (BltOperation == EfiBltBufferToVideo) || (BltOperation == EfiBltVideoToBltBuffer)) {
    821     ASSERT( BltBuffer != NULL);
    822   }
    823 
    824   /*if ((DestinationX >= HorizontalResolution) || (DestinationY >= VerticalResolution)) {
    825     DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: ERROR - Invalid destination.\n" ));
    826     Status = EFI_INVALID_PARAMETER;
    827     goto EXIT;
    828   }*/
    829 
    830   // If we are reading data out of the video buffer, check that the source area is within the display limits
    831   if ((BltOperation == EfiBltVideoToBltBuffer) || (BltOperation == EfiBltVideoToVideo)) {
    832     if ((SourceY + Height > VerticalResolution) || (SourceX + Width > HorizontalResolution)) {
    833       DEBUG((DEBUG_INFO, "LcdGraphicsBlt: ERROR - Invalid source resolution.\n" ));
    834       DEBUG((DEBUG_INFO, "                      - SourceY=%d + Height=%d > VerticalResolution=%d.\n", SourceY, Height, VerticalResolution ));
    835       DEBUG((DEBUG_INFO, "                      - SourceX=%d + Width=%d > HorizontalResolution=%d.\n", SourceX, Width, HorizontalResolution ));
    836       Status = EFI_INVALID_PARAMETER;
    837       goto EXIT;
    838     }
    839   }
    840 
    841   // If we are writing data into the video buffer, that the destination area is within the display limits
    842   if ((BltOperation == EfiBltVideoFill) || (BltOperation == EfiBltBufferToVideo) || (BltOperation == EfiBltVideoToVideo)) {
    843     if ((DestinationY + Height > VerticalResolution) || (DestinationX + Width > HorizontalResolution)) {
    844       DEBUG((DEBUG_INFO, "LcdGraphicsBlt: ERROR - Invalid destination resolution.\n" ));
    845       DEBUG((DEBUG_INFO, "                      - DestinationY=%d + Height=%d > VerticalResolution=%d.\n", DestinationY, Height, VerticalResolution ));
    846       DEBUG((DEBUG_INFO, "                      - DestinationX=%d + Width=%d > HorizontalResolution=%d.\n", DestinationX, Width, HorizontalResolution ));
    847       Status = EFI_INVALID_PARAMETER;
    848       goto EXIT;
    849     }
    850   }
    851 
    852   //
    853   // Perform the Block Transfer Operation
    854   //
    855 
    856   switch (BltOperation) {
    857   case EfiBltVideoFill:
    858     Status = BltVideoFill (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
    859     break;
    860 
    861   case EfiBltVideoToBltBuffer:
    862     Status = BltVideoToBltBuffer (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
    863     break;
    864 
    865   case EfiBltBufferToVideo:
    866     Status = BltBufferToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
    867     break;
    868 
    869   case EfiBltVideoToVideo:
    870     Status = BltVideoToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
    871     break;
    872 
    873   case EfiGraphicsOutputBltOperationMax:
    874   default:
    875     DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: Invalid Operation\n"));
    876     Status = EFI_INVALID_PARAMETER;
    877     break;
    878   }
    879 
    880 EXIT:
    881   return Status;
    882 }
    883