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