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