| /** @file | |
| Copyright (c) 2011-2013, ARM Ltd. All rights reserved.<BR> | |
| This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| **/ | |
| #include <PiDxe.h> | |
| #include <Library/BaseMemoryLib.h> | |
| #include <Library/DevicePathLib.h> | |
| #include <Library/UefiBootServicesTableLib.h> | |
| #include <Library/UefiRuntimeServicesTableLib.h> | |
| #include <Library/MemoryAllocationLib.h> | |
| #include <Guid/GlobalVariable.h> | |
| #include "LcdGraphicsOutputDxe.h" | |
| extern BOOLEAN mDisplayInitialized; | |
| // | |
| // Function Definitions | |
| // | |
| STATIC | |
| EFI_STATUS | |
| VideoCopyNoHorizontalOverlap ( | |
| IN UINTN BitsPerPixel, | |
| IN volatile VOID *FrameBufferBase, | |
| IN UINT32 HorizontalResolution, | |
| IN UINTN SourceX, | |
| IN UINTN SourceY, | |
| IN UINTN DestinationX, | |
| IN UINTN DestinationY, | |
| IN UINTN Width, | |
| IN UINTN Height | |
| ) | |
| { | |
| EFI_STATUS Status = EFI_SUCCESS; | |
| UINTN SourceLine; | |
| UINTN DestinationLine; | |
| UINTN WidthInBytes; | |
| UINTN LineCount; | |
| INTN Step; | |
| VOID *SourceAddr; | |
| VOID *DestinationAddr; | |
| if( DestinationY <= SourceY ) { | |
| // scrolling up (or horizontally but without overlap) | |
| SourceLine = SourceY; | |
| DestinationLine = DestinationY; | |
| Step = 1; | |
| } else { | |
| // scrolling down | |
| SourceLine = SourceY + Height; | |
| DestinationLine = DestinationY + Height; | |
| Step = -1; | |
| } | |
| switch (BitsPerPixel) { | |
| case LCD_BITS_PER_PIXEL_24: | |
| WidthInBytes = Width * 4; | |
| for( LineCount = 0; LineCount < Height; LineCount++ ) { | |
| // Update the start addresses of source & destination using 32bit pointer arithmetic | |
| SourceAddr = (VOID *)((UINT32 *)FrameBufferBase + SourceLine * HorizontalResolution + SourceX ); | |
| DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX); | |
| // Copy the entire line Y from video ram to the temp buffer | |
| CopyMem( DestinationAddr, SourceAddr, WidthInBytes); | |
| // Update the line numbers | |
| SourceLine += Step; | |
| DestinationLine += Step; | |
| } | |
| break; | |
| case LCD_BITS_PER_PIXEL_16_555: | |
| case LCD_BITS_PER_PIXEL_16_565: | |
| case LCD_BITS_PER_PIXEL_12_444: | |
| WidthInBytes = Width * 2; | |
| for( LineCount = 0; LineCount < Height; LineCount++ ) { | |
| // Update the start addresses of source & destination using 16bit pointer arithmetic | |
| SourceAddr = (VOID *)((UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourceX ); | |
| DestinationAddr = (VOID *)((UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX); | |
| // Copy the entire line Y from video ram to the temp buffer | |
| CopyMem( DestinationAddr, SourceAddr, WidthInBytes); | |
| // Update the line numbers | |
| SourceLine += Step; | |
| DestinationLine += Step; | |
| } | |
| break; | |
| case LCD_BITS_PER_PIXEL_8: | |
| case LCD_BITS_PER_PIXEL_4: | |
| case LCD_BITS_PER_PIXEL_2: | |
| case LCD_BITS_PER_PIXEL_1: | |
| default: | |
| // Can't handle this case | |
| DEBUG((DEBUG_ERROR, "ArmVeGraphics_Blt: EfiBltVideoToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel)); | |
| Status = EFI_INVALID_PARAMETER; | |
| goto EXIT; | |
| // break; | |
| } | |
| EXIT: | |
| return Status; | |
| } | |
| STATIC | |
| EFI_STATUS | |
| VideoCopyHorizontalOverlap ( | |
| IN UINTN BitsPerPixel, | |
| IN volatile VOID *FrameBufferBase, | |
| UINT32 HorizontalResolution, | |
| IN UINTN SourceX, | |
| IN UINTN SourceY, | |
| IN UINTN DestinationX, | |
| IN UINTN DestinationY, | |
| IN UINTN Width, | |
| IN UINTN Height | |
| ) | |
| { | |
| EFI_STATUS Status = EFI_SUCCESS; | |
| UINT32 *PixelBuffer32bit; | |
| UINT32 *SourcePixel32bit; | |
| UINT32 *DestinationPixel32bit; | |
| UINT16 *PixelBuffer16bit; | |
| UINT16 *SourcePixel16bit; | |
| UINT16 *DestinationPixel16bit; | |
| UINT32 SourcePixelY; | |
| UINT32 DestinationPixelY; | |
| UINTN SizeIn32Bits; | |
| UINTN SizeIn16Bits; | |
| switch (BitsPerPixel) { | |
| case LCD_BITS_PER_PIXEL_24: | |
| // Allocate a temporary buffer | |
| PixelBuffer32bit = (UINT32 *) AllocatePool((Height * Width) * sizeof(UINT32)); | |
| if (PixelBuffer32bit == NULL) { | |
| Status = EFI_OUT_OF_RESOURCES; | |
| goto EXIT; | |
| } | |
| SizeIn32Bits = Width * 4; | |
| // Copy from the video ram (source region) to a temp buffer | |
| for (SourcePixelY = SourceY, DestinationPixel32bit = PixelBuffer32bit; | |
| SourcePixelY < SourceY + Height; | |
| SourcePixelY++, DestinationPixel32bit += Width) | |
| { | |
| // Update the start address of line Y (source) | |
| SourcePixel32bit = (UINT32 *)FrameBufferBase + SourcePixelY * HorizontalResolution + SourceX; | |
| // Copy the entire line Y from video ram to the temp buffer | |
| CopyMem( (VOID *)DestinationPixel32bit, (CONST VOID *)SourcePixel32bit, SizeIn32Bits); | |
| } | |
| // Copy from the temp buffer to the video ram (destination region) | |
| for (DestinationPixelY = DestinationY, SourcePixel32bit = PixelBuffer32bit; | |
| DestinationPixelY < DestinationY + Height; | |
| DestinationPixelY++, SourcePixel32bit += Width) | |
| { | |
| // Update the start address of line Y (target) | |
| DestinationPixel32bit = (UINT32 *)FrameBufferBase + DestinationPixelY * HorizontalResolution + DestinationX; | |
| // Copy the entire line Y from the temp buffer to video ram | |
| CopyMem( (VOID *)DestinationPixel32bit, (CONST VOID *)SourcePixel32bit, SizeIn32Bits); | |
| } | |
| // Free up the allocated memory | |
| FreePool((VOID *) PixelBuffer32bit); | |
| break; | |
| case LCD_BITS_PER_PIXEL_16_555: | |
| case LCD_BITS_PER_PIXEL_16_565: | |
| case LCD_BITS_PER_PIXEL_12_444: | |
| // Allocate a temporary buffer | |
| PixelBuffer16bit = (UINT16 *) AllocatePool((Height * Width) * sizeof(UINT16)); | |
| if (PixelBuffer16bit == NULL) { | |
| Status = EFI_OUT_OF_RESOURCES; | |
| goto EXIT; | |
| } | |
| // Access each pixel inside the source area of the Video Memory and copy it to the temp buffer | |
| SizeIn16Bits = Width * 2; | |
| for (SourcePixelY = SourceY, DestinationPixel16bit = PixelBuffer16bit; | |
| SourcePixelY < SourceY + Height; | |
| SourcePixelY++, DestinationPixel16bit += Width) | |
| { | |
| // Calculate the source address: | |
| SourcePixel16bit = (UINT16 *)FrameBufferBase + SourcePixelY * HorizontalResolution + SourceX; | |
| // Copy the entire line Y from Video to the temp buffer | |
| CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits); | |
| } | |
| // Copy from the temp buffer into the destination area of the Video Memory | |
| for (DestinationPixelY = DestinationY, SourcePixel16bit = PixelBuffer16bit; | |
| DestinationPixelY < DestinationY + Height; | |
| DestinationPixelY++, SourcePixel16bit += Width) | |
| { | |
| // Calculate the target address: | |
| DestinationPixel16bit = (UINT16 *)FrameBufferBase + (DestinationPixelY * HorizontalResolution + DestinationX); | |
| // Copy the entire line Y from the temp buffer to Video | |
| CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits); | |
| } | |
| // Free the allocated memory | |
| FreePool((VOID *) PixelBuffer16bit); | |
| break; | |
| case LCD_BITS_PER_PIXEL_8: | |
| case LCD_BITS_PER_PIXEL_4: | |
| case LCD_BITS_PER_PIXEL_2: | |
| case LCD_BITS_PER_PIXEL_1: | |
| default: | |
| // Can't handle this case | |
| DEBUG((DEBUG_ERROR, "ArmVeGraphics_Blt: EfiBltVideoToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel)); | |
| Status = EFI_INVALID_PARAMETER; | |
| goto EXIT; | |
| // break; | |
| } | |
| EXIT: | |
| return Status; | |
| } | |
| STATIC | |
| EFI_STATUS | |
| BltVideoFill ( | |
| IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, | |
| IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiSourcePixel, OPTIONAL | |
| IN UINTN SourceX, | |
| IN UINTN SourceY, | |
| IN UINTN DestinationX, | |
| IN UINTN DestinationY, | |
| IN UINTN Width, | |
| IN UINTN Height, | |
| IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer | |
| ) | |
| { | |
| EFI_PIXEL_BITMASK* PixelInformation; | |
| EFI_STATUS Status; | |
| UINT32 HorizontalResolution; | |
| LCD_BPP BitsPerPixel; | |
| VOID *FrameBufferBase; | |
| VOID *DestinationAddr; | |
| UINT16 *DestinationPixel16bit; | |
| UINT16 Pixel16bit; | |
| UINT32 DestinationPixelX; | |
| UINT32 DestinationLine; | |
| UINTN WidthInBytes; | |
| Status = EFI_SUCCESS; | |
| PixelInformation = &This->Mode->Info->PixelInformation; | |
| FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase)); | |
| HorizontalResolution = This->Mode->Info->HorizontalResolution; | |
| LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel); | |
| switch (BitsPerPixel) { | |
| case LCD_BITS_PER_PIXEL_24: | |
| WidthInBytes = Width * 4; | |
| // Copy the SourcePixel into every pixel inside the target rectangle | |
| for (DestinationLine = DestinationY; | |
| DestinationLine < DestinationY + Height; | |
| DestinationLine++) | |
| { | |
| // Calculate the target address using 32bit pointer arithmetic: | |
| DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX); | |
| // Fill the entire line | |
| SetMem32 (DestinationAddr, WidthInBytes, *((UINT32 *)EfiSourcePixel)); | |
| } | |
| break; | |
| case LCD_BITS_PER_PIXEL_16_555: | |
| // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel | |
| Pixel16bit = (UINT16) ( | |
| ( (EfiSourcePixel->Red << 7) & PixelInformation->RedMask ) | |
| | ( (EfiSourcePixel->Green << 2) & PixelInformation->GreenMask ) | |
| | ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask ) | |
| // | ( 0 & PixelInformation->ReservedMask ) | |
| ); | |
| // Copy the SourcePixel into every pixel inside the target rectangle | |
| for (DestinationLine = DestinationY; | |
| DestinationLine < DestinationY + Height; | |
| DestinationLine++) | |
| { | |
| for (DestinationPixelX = DestinationX; | |
| DestinationPixelX < DestinationX + Width; | |
| DestinationPixelX++) | |
| { | |
| // Calculate the target address: | |
| DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX; | |
| // Copy the pixel into the new target | |
| *DestinationPixel16bit = Pixel16bit; | |
| } | |
| } | |
| break; | |
| case LCD_BITS_PER_PIXEL_16_565: | |
| // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel | |
| Pixel16bit = (UINT16) ( | |
| ( (EfiSourcePixel->Red << 8) & PixelInformation->RedMask ) | |
| | ( (EfiSourcePixel->Green << 3) & PixelInformation->GreenMask ) | |
| | ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask ) | |
| ); | |
| // Copy the SourcePixel into every pixel inside the target rectangle | |
| for (DestinationLine = DestinationY; | |
| DestinationLine < DestinationY + Height; | |
| DestinationLine++) | |
| { | |
| for (DestinationPixelX = DestinationX; | |
| DestinationPixelX < DestinationX + Width; | |
| DestinationPixelX++) | |
| { | |
| // Calculate the target address: | |
| DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX; | |
| // Copy the pixel into the new target | |
| *DestinationPixel16bit = Pixel16bit; | |
| } | |
| } | |
| break; | |
| case LCD_BITS_PER_PIXEL_12_444: | |
| // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel | |
| Pixel16bit = (UINT16) ( | |
| ( (EfiSourcePixel->Red >> 4) & PixelInformation->RedMask ) | |
| | ( (EfiSourcePixel->Green ) & PixelInformation->GreenMask ) | |
| | ( (EfiSourcePixel->Blue << 4) & PixelInformation->BlueMask ) | |
| ); | |
| // Copy the SourcePixel into every pixel inside the target rectangle | |
| for (DestinationLine = DestinationY; | |
| DestinationLine < DestinationY + Height; | |
| DestinationLine++) | |
| { | |
| for (DestinationPixelX = DestinationX; | |
| DestinationPixelX < DestinationX + Width; | |
| DestinationPixelX++) | |
| { | |
| // Calculate the target address: | |
| DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX; | |
| // Copy the pixel into the new target | |
| *DestinationPixel16bit = Pixel16bit; | |
| } | |
| } | |
| break; | |
| case LCD_BITS_PER_PIXEL_8: | |
| case LCD_BITS_PER_PIXEL_4: | |
| case LCD_BITS_PER_PIXEL_2: | |
| case LCD_BITS_PER_PIXEL_1: | |
| default: | |
| // Can't handle this case | |
| DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltVideoFill: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel)); | |
| Status = EFI_INVALID_PARAMETER; | |
| break; | |
| } | |
| return Status; | |
| } | |
| STATIC | |
| EFI_STATUS | |
| BltVideoToBltBuffer ( | |
| IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, | |
| IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL | |
| IN UINTN SourceX, | |
| IN UINTN SourceY, | |
| IN UINTN DestinationX, | |
| IN UINTN DestinationY, | |
| IN UINTN Width, | |
| IN UINTN Height, | |
| IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| UINT32 HorizontalResolution; | |
| LCD_BPP BitsPerPixel; | |
| EFI_PIXEL_BITMASK *PixelInformation; | |
| EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiDestinationPixel; | |
| VOID *FrameBufferBase; | |
| VOID *SourceAddr; | |
| VOID *DestinationAddr; | |
| UINT16 *SourcePixel16bit; | |
| UINT16 Pixel16bit; | |
| UINT32 SourcePixelX; | |
| UINT32 SourceLine; | |
| UINT32 DestinationPixelX; | |
| UINT32 DestinationLine; | |
| UINT32 BltBufferHorizontalResolution; | |
| UINTN WidthInBytes; | |
| Status = EFI_SUCCESS; | |
| PixelInformation = &This->Mode->Info->PixelInformation; | |
| HorizontalResolution = This->Mode->Info->HorizontalResolution; | |
| FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase)); | |
| if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) { | |
| // Delta is not zero and it is different from the width. | |
| // Divide it by the size of a pixel to find out the buffer's horizontal resolution. | |
| BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); | |
| } else { | |
| BltBufferHorizontalResolution = Width; | |
| } | |
| LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel); | |
| switch (BitsPerPixel) { | |
| case LCD_BITS_PER_PIXEL_24: | |
| WidthInBytes = Width * 4; | |
| // Access each line inside the Video Memory | |
| for (SourceLine = SourceY, DestinationLine = DestinationY; | |
| SourceLine < SourceY + Height; | |
| SourceLine++, DestinationLine++) | |
| { | |
| // Calculate the source and target addresses using 32bit pointer arithmetic: | |
| SourceAddr = (VOID *)((UINT32 *)FrameBufferBase + SourceLine * HorizontalResolution + SourceX ); | |
| DestinationAddr = (VOID *)((UINT32 *)BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationX); | |
| // Copy the entire line | |
| CopyMem( DestinationAddr, SourceAddr, WidthInBytes); | |
| } | |
| break; | |
| case LCD_BITS_PER_PIXEL_16_555: | |
| // Access each pixel inside the Video Memory | |
| for (SourceLine = SourceY, DestinationLine = DestinationY; | |
| SourceLine < SourceY + Height; | |
| SourceLine++, DestinationLine++) | |
| { | |
| for (SourcePixelX = SourceX, DestinationPixelX = DestinationX; | |
| SourcePixelX < SourceX + Width; | |
| SourcePixelX++, DestinationPixelX++) | |
| { | |
| // Calculate the source and target addresses: | |
| SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX; | |
| EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX; | |
| // Snapshot the pixel from the video buffer once, to speed up the operation. | |
| // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations. | |
| Pixel16bit = *SourcePixel16bit; | |
| // Copy the pixel into the new target | |
| EfiDestinationPixel->Red = (UINT8) ( (Pixel16bit & PixelInformation->RedMask ) >> 7 ); | |
| EfiDestinationPixel->Green = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask ) >> 2); | |
| EfiDestinationPixel->Blue = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask ) << 3 ); | |
| // EfiDestinationPixel->Reserved = (UINT8) 0; | |
| } | |
| } | |
| break; | |
| case LCD_BITS_PER_PIXEL_16_565: | |
| // Access each pixel inside the Video Memory | |
| for (SourceLine = SourceY, DestinationLine = DestinationY; | |
| SourceLine < SourceY + Height; | |
| SourceLine++, DestinationLine++) | |
| { | |
| for (SourcePixelX = SourceX, DestinationPixelX = DestinationX; | |
| SourcePixelX < SourceX + Width; | |
| SourcePixelX++, DestinationPixelX++) | |
| { | |
| // Calculate the source and target addresses: | |
| SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX; | |
| EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX; | |
| // Snapshot the pixel from the video buffer once, to speed up the operation. | |
| // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations. | |
| Pixel16bit = *SourcePixel16bit; | |
| // Copy the pixel into the new target | |
| // There is no info for the Reserved byte, so we set it to zero | |
| EfiDestinationPixel->Red = (UINT8) ( (Pixel16bit & PixelInformation->RedMask ) >> 8 ); | |
| EfiDestinationPixel->Green = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask ) >> 3); | |
| EfiDestinationPixel->Blue = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask ) << 3 ); | |
| // EfiDestinationPixel->Reserved = (UINT8) 0; | |
| } | |
| } | |
| break; | |
| case LCD_BITS_PER_PIXEL_12_444: | |
| // Access each pixel inside the Video Memory | |
| for (SourceLine = SourceY, DestinationLine = DestinationY; | |
| SourceLine < SourceY + Height; | |
| SourceLine++, DestinationLine++) | |
| { | |
| for (SourcePixelX = SourceX, DestinationPixelX = DestinationX; | |
| SourcePixelX < SourceX + Width; | |
| SourcePixelX++, DestinationPixelX++) | |
| { | |
| // Calculate the source and target addresses: | |
| SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX; | |
| EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX; | |
| // Snapshot the pixel from the video buffer once, to speed up the operation. | |
| // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations. | |
| Pixel16bit = *SourcePixel16bit; | |
| // Copy the pixel into the new target | |
| EfiDestinationPixel->Red = (UINT8) ( (Pixel16bit & PixelInformation->RedMask ) >> 4 ); | |
| EfiDestinationPixel->Green = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask ) ); | |
| EfiDestinationPixel->Blue = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask ) << 4 ); | |
| // EfiDestinationPixel->Reserved = (UINT8) 0; | |
| } | |
| } | |
| break; | |
| case LCD_BITS_PER_PIXEL_8: | |
| case LCD_BITS_PER_PIXEL_4: | |
| case LCD_BITS_PER_PIXEL_2: | |
| case LCD_BITS_PER_PIXEL_1: | |
| default: | |
| // Can't handle this case | |
| DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltVideoToBltBuffer: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel)); | |
| Status = EFI_INVALID_PARAMETER; | |
| break; | |
| } | |
| return Status; | |
| } | |
| STATIC | |
| EFI_STATUS | |
| BltBufferToVideo ( | |
| IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, | |
| IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL | |
| IN UINTN SourceX, | |
| IN UINTN SourceY, | |
| IN UINTN DestinationX, | |
| IN UINTN DestinationY, | |
| IN UINTN Width, | |
| IN UINTN Height, | |
| IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| UINT32 HorizontalResolution; | |
| LCD_BPP BitsPerPixel; | |
| EFI_PIXEL_BITMASK *PixelInformation; | |
| EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiSourcePixel; | |
| VOID *FrameBufferBase; | |
| VOID *SourceAddr; | |
| VOID *DestinationAddr; | |
| UINT16 *DestinationPixel16bit; | |
| UINT32 SourcePixelX; | |
| UINT32 SourceLine; | |
| UINT32 DestinationPixelX; | |
| UINT32 DestinationLine; | |
| UINT32 BltBufferHorizontalResolution; | |
| UINTN WidthInBytes; | |
| Status = EFI_SUCCESS; | |
| PixelInformation = &This->Mode->Info->PixelInformation; | |
| HorizontalResolution = This->Mode->Info->HorizontalResolution; | |
| FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase)); | |
| if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) { | |
| // Delta is not zero and it is different from the width. | |
| // Divide it by the size of a pixel to find out the buffer's horizontal resolution. | |
| BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); | |
| } else { | |
| BltBufferHorizontalResolution = Width; | |
| } | |
| LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel); | |
| switch (BitsPerPixel) { | |
| case LCD_BITS_PER_PIXEL_24: | |
| WidthInBytes = Width * 4; | |
| // Access each pixel inside the BltBuffer Memory | |
| for (SourceLine = SourceY, DestinationLine = DestinationY; | |
| SourceLine < SourceY + Height; | |
| SourceLine++, DestinationLine++) | |
| { | |
| // Calculate the source and target addresses using 32bit pointer arithmetic: | |
| SourceAddr = (VOID *)((UINT32 *)BltBuffer + SourceLine * BltBufferHorizontalResolution + SourceX ); | |
| DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX); | |
| // Copy the entire row Y | |
| CopyMem( DestinationAddr, SourceAddr, WidthInBytes); | |
| } | |
| break; | |
| case LCD_BITS_PER_PIXEL_16_555: | |
| // Access each pixel inside the BltBuffer Memory | |
| for (SourceLine = SourceY, DestinationLine = DestinationY; | |
| SourceLine < SourceY + Height; | |
| SourceLine++, DestinationLine++) { | |
| for (SourcePixelX = SourceX, DestinationPixelX = DestinationX; | |
| SourcePixelX < SourceX + Width; | |
| SourcePixelX++, DestinationPixelX++) | |
| { | |
| // Calculate the source and target addresses: | |
| EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX; | |
| DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX; | |
| // Copy the pixel into the new target | |
| // Only the most significant bits will be copied across: | |
| // To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits | |
| *DestinationPixel16bit = (UINT16) ( | |
| ( (EfiSourcePixel->Red << 7) & PixelInformation->RedMask ) | |
| | ( (EfiSourcePixel->Green << 2) & PixelInformation->GreenMask ) | |
| | ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask ) | |
| // | ( 0 & PixelInformation->ReservedMask ) | |
| ); | |
| } | |
| } | |
| break; | |
| case LCD_BITS_PER_PIXEL_16_565: | |
| // Access each pixel inside the BltBuffer Memory | |
| for (SourceLine = SourceY, DestinationLine = DestinationY; | |
| SourceLine < SourceY + Height; | |
| SourceLine++, DestinationLine++) { | |
| for (SourcePixelX = SourceX, DestinationPixelX = DestinationX; | |
| SourcePixelX < SourceX + Width; | |
| SourcePixelX++, DestinationPixelX++) | |
| { | |
| // Calculate the source and target addresses: | |
| EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX; | |
| DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX; | |
| // Copy the pixel into the new target | |
| // Only the most significant bits will be copied across: | |
| // To convert from 8 bits to 5 or 6 bits per pixel we throw away the 3 or 2 least significant bits | |
| // There is no room for the Reserved byte so we ignore that completely | |
| *DestinationPixel16bit = (UINT16) ( | |
| ( (EfiSourcePixel->Red << 8) & PixelInformation->RedMask ) | |
| | ( (EfiSourcePixel->Green << 3) & PixelInformation->GreenMask ) | |
| | ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask ) | |
| ); | |
| } | |
| } | |
| break; | |
| case LCD_BITS_PER_PIXEL_12_444: | |
| // Access each pixel inside the BltBuffer Memory | |
| for (SourceLine = SourceY, DestinationLine = DestinationY; | |
| SourceLine < SourceY + Height; | |
| SourceLine++, DestinationLine++) { | |
| for (SourcePixelX = SourceX, DestinationPixelX = DestinationX; | |
| SourcePixelX < SourceX + Width; | |
| SourcePixelX++, DestinationPixelX++) | |
| { | |
| // Calculate the source and target addresses: | |
| EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX; | |
| DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX; | |
| // Copy the pixel into the new target | |
| // Only the most significant bits will be copied across: | |
| // To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits | |
| *DestinationPixel16bit = (UINT16) ( | |
| ( (EfiSourcePixel->Red << 4) & PixelInformation->RedMask ) | |
| | ( (EfiSourcePixel->Green ) & PixelInformation->GreenMask ) | |
| | ( (EfiSourcePixel->Blue >> 4) & PixelInformation->BlueMask ) | |
| // | ( 0 & PixelInformation->ReservedMask ) | |
| ); | |
| } | |
| } | |
| break; | |
| case LCD_BITS_PER_PIXEL_8: | |
| case LCD_BITS_PER_PIXEL_4: | |
| case LCD_BITS_PER_PIXEL_2: | |
| case LCD_BITS_PER_PIXEL_1: | |
| default: | |
| // Can't handle this case | |
| DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltBufferToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel)); | |
| Status = EFI_INVALID_PARAMETER; | |
| break; | |
| } | |
| return Status; | |
| } | |
| STATIC | |
| EFI_STATUS | |
| BltVideoToVideo ( | |
| IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, | |
| IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL | |
| IN UINTN SourceX, | |
| IN UINTN SourceY, | |
| IN UINTN DestinationX, | |
| IN UINTN DestinationY, | |
| IN UINTN Width, | |
| IN UINTN Height, | |
| IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| UINT32 HorizontalResolution; | |
| LCD_BPP BitsPerPixel; | |
| VOID *FrameBufferBase; | |
| HorizontalResolution = This->Mode->Info->HorizontalResolution; | |
| FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase)); | |
| // | |
| // BltVideo to BltVideo: | |
| // | |
| // Source is the Video Memory, | |
| // Destination is the Video Memory | |
| LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel); | |
| FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase)); | |
| // The UEFI spec currently states: | |
| // "There is no limitation on the overlapping of the source and destination rectangles" | |
| // Therefore, we must be careful to avoid overwriting the source data | |
| if( SourceY == DestinationY ) { | |
| // Copying within the same height, e.g. horizontal shift | |
| if( SourceX == DestinationX ) { | |
| // Nothing to do | |
| Status = EFI_SUCCESS; | |
| } else if( ((SourceX>DestinationX)?(SourceX - DestinationX):(DestinationX - SourceX)) < Width ) { | |
| // There is overlap | |
| Status = VideoCopyHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height ); | |
| } else { | |
| // No overlap | |
| Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height ); | |
| } | |
| } else { | |
| // Copying from different heights | |
| Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height ); | |
| } | |
| return Status; | |
| } | |
| /*************************************** | |
| * GraphicsOutput Protocol function, mapping to | |
| * EFI_GRAPHICS_OUTPUT_PROTOCOL.Blt | |
| * | |
| * PRESUMES: 1 pixel = 4 bytes (32bits) | |
| * ***************************************/ | |
| EFI_STATUS | |
| EFIAPI | |
| LcdGraphicsBlt ( | |
| IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, | |
| IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL | |
| IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, | |
| IN UINTN SourceX, | |
| IN UINTN SourceY, | |
| IN UINTN DestinationX, | |
| IN UINTN DestinationY, | |
| IN UINTN Width, | |
| IN UINTN Height, | |
| IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| UINT32 HorizontalResolution; | |
| UINT32 VerticalResolution; | |
| LCD_INSTANCE* Instance; | |
| Instance = LCD_INSTANCE_FROM_GOP_THIS(This); | |
| // Setup the hardware if not already done | |
| if (!mDisplayInitialized) { | |
| Status = InitializeDisplay (Instance); | |
| if (EFI_ERROR(Status)) { | |
| goto EXIT; | |
| } | |
| } | |
| HorizontalResolution = This->Mode->Info->HorizontalResolution; | |
| VerticalResolution = This->Mode->Info->VerticalResolution; | |
| DEBUG((DEBUG_INFO, "LcdGraphicsBlt (BltOperation:%d,DestX:%d,DestY:%d,Width:%d,Height:%d) res(%d,%d)\n", | |
| BltOperation,DestinationX,DestinationY,Width,Height,HorizontalResolution,VerticalResolution)); | |
| // Check we have reasonable parameters | |
| if (Width == 0 || Height == 0) { | |
| DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: ERROR - Invalid dimension: Zero size area.\n" )); | |
| Status = EFI_INVALID_PARAMETER; | |
| goto EXIT; | |
| } | |
| if ((BltOperation == EfiBltVideoFill) || (BltOperation == EfiBltBufferToVideo) || (BltOperation == EfiBltVideoToBltBuffer)) { | |
| ASSERT( BltBuffer != NULL); | |
| } | |
| /*if ((DestinationX >= HorizontalResolution) || (DestinationY >= VerticalResolution)) { | |
| DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: ERROR - Invalid destination.\n" )); | |
| Status = EFI_INVALID_PARAMETER; | |
| goto EXIT; | |
| }*/ | |
| // If we are reading data out of the video buffer, check that the source area is within the display limits | |
| if ((BltOperation == EfiBltVideoToBltBuffer) || (BltOperation == EfiBltVideoToVideo)) { | |
| if ((SourceY + Height > VerticalResolution) || (SourceX + Width > HorizontalResolution)) { | |
| DEBUG((DEBUG_INFO, "LcdGraphicsBlt: ERROR - Invalid source resolution.\n" )); | |
| DEBUG((DEBUG_INFO, " - SourceY=%d + Height=%d > VerticalResolution=%d.\n", SourceY, Height, VerticalResolution )); | |
| DEBUG((DEBUG_INFO, " - SourceX=%d + Width=%d > HorizontalResolution=%d.\n", SourceX, Width, HorizontalResolution )); | |
| Status = EFI_INVALID_PARAMETER; | |
| goto EXIT; | |
| } | |
| } | |
| // If we are writing data into the video buffer, that the destination area is within the display limits | |
| if ((BltOperation == EfiBltVideoFill) || (BltOperation == EfiBltBufferToVideo) || (BltOperation == EfiBltVideoToVideo)) { | |
| if ((DestinationY + Height > VerticalResolution) || (DestinationX + Width > HorizontalResolution)) { | |
| DEBUG((DEBUG_INFO, "LcdGraphicsBlt: ERROR - Invalid destination resolution.\n" )); | |
| DEBUG((DEBUG_INFO, " - DestinationY=%d + Height=%d > VerticalResolution=%d.\n", DestinationY, Height, VerticalResolution )); | |
| DEBUG((DEBUG_INFO, " - DestinationX=%d + Width=%d > HorizontalResolution=%d.\n", DestinationX, Width, HorizontalResolution )); | |
| Status = EFI_INVALID_PARAMETER; | |
| goto EXIT; | |
| } | |
| } | |
| // | |
| // Perform the Block Transfer Operation | |
| // | |
| switch (BltOperation) { | |
| case EfiBltVideoFill: | |
| Status = BltVideoFill (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta); | |
| break; | |
| case EfiBltVideoToBltBuffer: | |
| Status = BltVideoToBltBuffer (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta); | |
| break; | |
| case EfiBltBufferToVideo: | |
| Status = BltBufferToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta); | |
| break; | |
| case EfiBltVideoToVideo: | |
| Status = BltVideoToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta); | |
| break; | |
| case EfiGraphicsOutputBltOperationMax: | |
| default: | |
| DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: Invalid Operation\n")); | |
| Status = EFI_INVALID_PARAMETER; | |
| break; | |
| } | |
| EXIT: | |
| return Status; | |
| } |