/** @file Copyright (c) 2011-2013, ARM Ltd. All rights reserved.<BR> SPDX-License-Identifier: BSD-2-Clause-Patent **/ #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; }