]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputBlt.c
ArmPlatformPkg: Fix Ecc error 8005
[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
64 case LcdBitsPerPixel_24:
65
66 WidthInBytes = Width * 4;
67
68 for( LineCount = 0; LineCount < Height; LineCount++ ) {
69 // Update the start addresses of source & destination using 32bit pointer arithmetic
70 SourceAddr = (VOID *)((UINT32 *)FrameBufferBase + SourceLine * HorizontalResolution + SourceX );
71 DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);
72
73 // Copy the entire line Y from video ram to the temp buffer
74 CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
75
76 // Update the line numbers
77 SourceLine += Step;
78 DestinationLine += Step;
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 break;
101
102 case LcdBitsPerPixel_8:
103 case LcdBitsPerPixel_4:
104 case LcdBitsPerPixel_2:
105 case LcdBitsPerPixel_1:
106 default:
107 // Can't handle this case
108 DEBUG((DEBUG_ERROR, "ArmVeGraphics_Blt: EfiBltVideoToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
109 Status = EFI_INVALID_PARAMETER;
110 goto EXIT;
111 // break;
112
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
152 case LcdBitsPerPixel_24:
153 // Allocate a temporary buffer
154
155 PixelBuffer32bit = (UINT32 *) AllocatePool((Height * Width) * sizeof(UINT32));
156
157 if (PixelBuffer32bit == NULL) {
158 Status = EFI_OUT_OF_RESOURCES;
159 goto EXIT;
160 }
161
162 SizeIn32Bits = Width * 4;
163
164 // Copy from the video ram (source region) to a temp buffer
165 for (SourcePixelY = SourceY, DestinationPixel32bit = PixelBuffer32bit;
166 SourcePixelY < SourceY + Height;
167 SourcePixelY++, DestinationPixel32bit += Width)
168 {
169 // Update the start address of line Y (source)
170 SourcePixel32bit = (UINT32 *)FrameBufferBase + SourcePixelY * HorizontalResolution + SourceX;
171
172 // Copy the entire line Y from video ram to the temp buffer
173 CopyMem( (VOID *)DestinationPixel32bit, (CONST VOID *)SourcePixel32bit, SizeIn32Bits);
174 }
175
176 // Copy from the temp buffer to the video ram (destination region)
177 for (DestinationPixelY = DestinationY, SourcePixel32bit = PixelBuffer32bit;
178 DestinationPixelY < DestinationY + Height;
179 DestinationPixelY++, SourcePixel32bit += Width)
180 {
181 // Update the start address of line Y (target)
182 DestinationPixel32bit = (UINT32 *)FrameBufferBase + DestinationPixelY * HorizontalResolution + DestinationX;
183
184 // Copy the entire line Y from the temp buffer to video ram
185 CopyMem( (VOID *)DestinationPixel32bit, (CONST VOID *)SourcePixel32bit, SizeIn32Bits);
186 }
187
188 // Free up the allocated memory
189 FreePool((VOID *) PixelBuffer32bit);
190
191 break;
192
193
194 case LcdBitsPerPixel_16_555:
195 case LcdBitsPerPixel_16_565:
196 case LcdBitsPerPixel_12_444:
197 // Allocate a temporary buffer
198 PixelBuffer16bit = (UINT16 *) AllocatePool((Height * Width) * sizeof(UINT16));
199
200 if (PixelBuffer16bit == NULL) {
201 Status = EFI_OUT_OF_RESOURCES;
202 goto EXIT;
203 }
204
205 // Access each pixel inside the source area of the Video Memory and copy it to the temp buffer
206
207 SizeIn16Bits = Width * 2;
208
209 for (SourcePixelY = SourceY, DestinationPixel16bit = PixelBuffer16bit;
210 SourcePixelY < SourceY + Height;
211 SourcePixelY++, DestinationPixel16bit += Width)
212 {
213 // Calculate the source address:
214 SourcePixel16bit = (UINT16 *)FrameBufferBase + SourcePixelY * HorizontalResolution + SourceX;
215
216 // Copy the entire line Y from Video to the temp buffer
217 CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits);
218 }
219
220 // Copy from the temp buffer into the destination area of the Video Memory
221
222 for (DestinationPixelY = DestinationY, SourcePixel16bit = PixelBuffer16bit;
223 DestinationPixelY < DestinationY + Height;
224 DestinationPixelY++, SourcePixel16bit += Width)
225 {
226 // Calculate the target address:
227 DestinationPixel16bit = (UINT16 *)FrameBufferBase + (DestinationPixelY * HorizontalResolution + DestinationX);
228
229 // Copy the entire line Y from the temp buffer to Video
230 CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits);
231 }
232
233 // Free the allocated memory
234 FreePool((VOID *) PixelBuffer16bit);
235
236 break;
237
238
239 case LcdBitsPerPixel_8:
240 case LcdBitsPerPixel_4:
241 case LcdBitsPerPixel_2:
242 case LcdBitsPerPixel_1:
243 default:
244 // Can't handle this case
245 DEBUG((DEBUG_ERROR, "ArmVeGraphics_Blt: EfiBltVideoToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
246 Status = EFI_INVALID_PARAMETER;
247 goto EXIT;
248 // break;
249
250 }
251
252 EXIT:
253 return Status;
254 }
255
256 STATIC
257 EFI_STATUS
258 BltVideoFill (
259 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
260 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiSourcePixel, OPTIONAL
261 IN UINTN SourceX,
262 IN UINTN SourceY,
263 IN UINTN DestinationX,
264 IN UINTN DestinationY,
265 IN UINTN Width,
266 IN UINTN Height,
267 IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer
268 )
269 {
270 EFI_PIXEL_BITMASK* PixelInformation;
271 EFI_STATUS Status;
272 UINT32 HorizontalResolution;
273 LCD_BPP BitsPerPixel;
274 VOID *FrameBufferBase;
275 VOID *DestinationAddr;
276 UINT16 *DestinationPixel16bit;
277 UINT16 Pixel16bit;
278 UINT32 DestinationPixelX;
279 UINT32 DestinationLine;
280 UINTN WidthInBytes;
281
282 Status = EFI_SUCCESS;
283 PixelInformation = &This->Mode->Info->PixelInformation;
284 FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
285 HorizontalResolution = This->Mode->Info->HorizontalResolution;
286
287 LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
288
289 switch (BitsPerPixel) {
290 case LcdBitsPerPixel_24:
291 WidthInBytes = Width * 4;
292
293 // Copy the SourcePixel into every pixel inside the target rectangle
294 for (DestinationLine = DestinationY;
295 DestinationLine < DestinationY + Height;
296 DestinationLine++)
297 {
298 // Calculate the target address using 32bit pointer arithmetic:
299 DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);
300
301 // Fill the entire line
302 SetMem32 (DestinationAddr, WidthInBytes, *((UINT32 *)EfiSourcePixel));
303 }
304 break;
305
306 case LcdBitsPerPixel_16_555:
307 // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
308 Pixel16bit = (UINT16) (
309 ( (EfiSourcePixel->Red << 7) & PixelInformation->RedMask )
310 | ( (EfiSourcePixel->Green << 2) & PixelInformation->GreenMask )
311 | ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask )
312 // | ( 0 & PixelInformation->ReservedMask )
313 );
314
315 // Copy the SourcePixel into every pixel inside the target rectangle
316 for (DestinationLine = DestinationY;
317 DestinationLine < DestinationY + Height;
318 DestinationLine++)
319 {
320 for (DestinationPixelX = DestinationX;
321 DestinationPixelX < DestinationX + Width;
322 DestinationPixelX++)
323 {
324 // Calculate the target address:
325 DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
326
327 // Copy the pixel into the new target
328 *DestinationPixel16bit = Pixel16bit;
329 }
330 }
331 break;
332
333 case LcdBitsPerPixel_16_565:
334 // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
335 Pixel16bit = (UINT16) (
336 ( (EfiSourcePixel->Red << 8) & PixelInformation->RedMask )
337 | ( (EfiSourcePixel->Green << 3) & PixelInformation->GreenMask )
338 | ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask )
339 );
340
341 // Copy the SourcePixel into every pixel inside the target rectangle
342 for (DestinationLine = DestinationY;
343 DestinationLine < DestinationY + Height;
344 DestinationLine++)
345 {
346 for (DestinationPixelX = DestinationX;
347 DestinationPixelX < DestinationX + Width;
348 DestinationPixelX++)
349 {
350 // Calculate the target address:
351 DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
352
353 // Copy the pixel into the new target
354 *DestinationPixel16bit = Pixel16bit;
355 }
356 }
357 break;
358
359 case LcdBitsPerPixel_12_444:
360 // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
361 Pixel16bit = (UINT16) (
362 ( (EfiSourcePixel->Red >> 4) & PixelInformation->RedMask )
363 | ( (EfiSourcePixel->Green ) & PixelInformation->GreenMask )
364 | ( (EfiSourcePixel->Blue << 4) & PixelInformation->BlueMask )
365 );
366
367 // Copy the SourcePixel into every pixel inside the target rectangle
368 for (DestinationLine = DestinationY;
369 DestinationLine < DestinationY + Height;
370 DestinationLine++)
371 {
372 for (DestinationPixelX = DestinationX;
373 DestinationPixelX < DestinationX + Width;
374 DestinationPixelX++)
375 {
376 // Calculate the target address:
377 DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
378
379 // Copy the pixel into the new target
380 *DestinationPixel16bit = Pixel16bit;
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 break;
462
463 case LcdBitsPerPixel_16_555:
464 // Access each pixel inside the Video Memory
465 for (SourceLine = SourceY, DestinationLine = DestinationY;
466 SourceLine < SourceY + Height;
467 SourceLine++, DestinationLine++)
468 {
469 for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
470 SourcePixelX < SourceX + Width;
471 SourcePixelX++, DestinationPixelX++)
472 {
473 // Calculate the source and target addresses:
474 SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;
475 EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;
476
477 // Snapshot the pixel from the video buffer once, to speed up the operation.
478 // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
479 Pixel16bit = *SourcePixel16bit;
480
481 // Copy the pixel into the new target
482 EfiDestinationPixel->Red = (UINT8) ( (Pixel16bit & PixelInformation->RedMask ) >> 7 );
483 EfiDestinationPixel->Green = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask ) >> 2);
484 EfiDestinationPixel->Blue = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask ) << 3 );
485 // EfiDestinationPixel->Reserved = (UINT8) 0;
486 }
487 }
488 break;
489
490 case LcdBitsPerPixel_16_565:
491 // Access each pixel inside the Video Memory
492 for (SourceLine = SourceY, DestinationLine = DestinationY;
493 SourceLine < SourceY + Height;
494 SourceLine++, DestinationLine++)
495 {
496 for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
497 SourcePixelX < SourceX + Width;
498 SourcePixelX++, DestinationPixelX++)
499 {
500 // Calculate the source and target addresses:
501 SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;
502 EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;
503
504 // Snapshot the pixel from the video buffer once, to speed up the operation.
505 // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
506 Pixel16bit = *SourcePixel16bit;
507
508 // Copy the pixel into the new target
509 // There is no info for the Reserved byte, so we set it to zero
510 EfiDestinationPixel->Red = (UINT8) ( (Pixel16bit & PixelInformation->RedMask ) >> 8 );
511 EfiDestinationPixel->Green = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask ) >> 3);
512 EfiDestinationPixel->Blue = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask ) << 3 );
513 // EfiDestinationPixel->Reserved = (UINT8) 0;
514 }
515 }
516 break;
517
518 case LcdBitsPerPixel_12_444:
519 // Access each pixel inside the Video Memory
520 for (SourceLine = SourceY, DestinationLine = DestinationY;
521 SourceLine < SourceY + Height;
522 SourceLine++, DestinationLine++)
523 {
524 for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
525 SourcePixelX < SourceX + Width;
526 SourcePixelX++, DestinationPixelX++)
527 {
528 // Calculate the source and target addresses:
529 SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;
530 EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;
531
532 // Snapshot the pixel from the video buffer once, to speed up the operation.
533 // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
534 Pixel16bit = *SourcePixel16bit;
535
536 // Copy the pixel into the new target
537 EfiDestinationPixel->Red = (UINT8) ( (Pixel16bit & PixelInformation->RedMask ) >> 4 );
538 EfiDestinationPixel->Green = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask ) );
539 EfiDestinationPixel->Blue = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask ) << 4 );
540 // EfiDestinationPixel->Reserved = (UINT8) 0;
541 }
542 }
543 break;
544
545 case LcdBitsPerPixel_8:
546 case LcdBitsPerPixel_4:
547 case LcdBitsPerPixel_2:
548 case LcdBitsPerPixel_1:
549 default:
550 // Can't handle this case
551 DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltVideoToBltBuffer: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
552 Status = EFI_INVALID_PARAMETER;
553 break;
554 }
555 return Status;
556 }
557
558 STATIC
559 EFI_STATUS
560 BltBufferToVideo (
561 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
562 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
563 IN UINTN SourceX,
564 IN UINTN SourceY,
565 IN UINTN DestinationX,
566 IN UINTN DestinationY,
567 IN UINTN Width,
568 IN UINTN Height,
569 IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer
570 )
571 {
572 EFI_STATUS Status;
573 UINT32 HorizontalResolution;
574 LCD_BPP BitsPerPixel;
575 EFI_PIXEL_BITMASK *PixelInformation;
576 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiSourcePixel;
577 VOID *FrameBufferBase;
578 VOID *SourceAddr;
579 VOID *DestinationAddr;
580 UINT16 *DestinationPixel16bit;
581 UINT32 SourcePixelX;
582 UINT32 SourceLine;
583 UINT32 DestinationPixelX;
584 UINT32 DestinationLine;
585 UINT32 BltBufferHorizontalResolution;
586 UINTN WidthInBytes;
587
588 Status = EFI_SUCCESS;
589 PixelInformation = &This->Mode->Info->PixelInformation;
590 HorizontalResolution = This->Mode->Info->HorizontalResolution;
591 FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
592
593 if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
594 // Delta is not zero and it is different from the width.
595 // Divide it by the size of a pixel to find out the buffer's horizontal resolution.
596 BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
597 } else {
598 BltBufferHorizontalResolution = Width;
599 }
600
601 LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
602
603 switch (BitsPerPixel) {
604 case LcdBitsPerPixel_24:
605 WidthInBytes = Width * 4;
606
607 // Access each pixel inside the BltBuffer Memory
608 for (SourceLine = SourceY, DestinationLine = DestinationY;
609 SourceLine < SourceY + Height;
610 SourceLine++, DestinationLine++)
611 {
612 // Calculate the source and target addresses using 32bit pointer arithmetic:
613 SourceAddr = (VOID *)((UINT32 *)BltBuffer + SourceLine * BltBufferHorizontalResolution + SourceX );
614 DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);
615
616 // Copy the entire row Y
617 CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
618 }
619 break;
620
621 case LcdBitsPerPixel_16_555:
622 // Access each pixel inside the BltBuffer Memory
623 for (SourceLine = SourceY, DestinationLine = DestinationY;
624 SourceLine < SourceY + Height;
625 SourceLine++, DestinationLine++) {
626
627 for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
628 SourcePixelX < SourceX + Width;
629 SourcePixelX++, DestinationPixelX++)
630 {
631 // Calculate the source and target addresses:
632 EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;
633 DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
634
635 // Copy the pixel into the new target
636 // Only the most significant bits will be copied across:
637 // To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits
638 *DestinationPixel16bit = (UINT16) (
639 ( (EfiSourcePixel->Red << 7) & PixelInformation->RedMask )
640 | ( (EfiSourcePixel->Green << 2) & PixelInformation->GreenMask )
641 | ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask )
642 // | ( 0 & PixelInformation->ReservedMask )
643 );
644 }
645 }
646 break;
647
648 case LcdBitsPerPixel_16_565:
649 // Access each pixel inside the BltBuffer Memory
650 for (SourceLine = SourceY, DestinationLine = DestinationY;
651 SourceLine < SourceY + Height;
652 SourceLine++, DestinationLine++) {
653
654 for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
655 SourcePixelX < SourceX + Width;
656 SourcePixelX++, DestinationPixelX++)
657 {
658 // Calculate the source and target addresses:
659 EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;
660 DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
661
662 // Copy the pixel into the new target
663 // Only the most significant bits will be copied across:
664 // To convert from 8 bits to 5 or 6 bits per pixel we throw away the 3 or 2 least significant bits
665 // There is no room for the Reserved byte so we ignore that completely
666 *DestinationPixel16bit = (UINT16) (
667 ( (EfiSourcePixel->Red << 8) & PixelInformation->RedMask )
668 | ( (EfiSourcePixel->Green << 3) & PixelInformation->GreenMask )
669 | ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask )
670 );
671 }
672 }
673 break;
674
675 case LcdBitsPerPixel_12_444:
676 // Access each pixel inside the BltBuffer Memory
677 for (SourceLine = SourceY, DestinationLine = DestinationY;
678 SourceLine < SourceY + Height;
679 SourceLine++, DestinationLine++) {
680
681 for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
682 SourcePixelX < SourceX + Width;
683 SourcePixelX++, DestinationPixelX++)
684 {
685 // Calculate the source and target addresses:
686 EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;
687 DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
688
689 // Copy the pixel into the new target
690 // Only the most significant bits will be copied across:
691 // To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits
692 *DestinationPixel16bit = (UINT16) (
693 ( (EfiSourcePixel->Red << 4) & PixelInformation->RedMask )
694 | ( (EfiSourcePixel->Green ) & PixelInformation->GreenMask )
695 | ( (EfiSourcePixel->Blue >> 4) & PixelInformation->BlueMask )
696 // | ( 0 & PixelInformation->ReservedMask )
697 );
698 }
699 }
700 break;
701
702 case LcdBitsPerPixel_8:
703 case LcdBitsPerPixel_4:
704 case LcdBitsPerPixel_2:
705 case LcdBitsPerPixel_1:
706 default:
707 // Can't handle this case
708 DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltBufferToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
709 Status = EFI_INVALID_PARAMETER;
710 break;
711 }
712 return Status;
713 }
714
715 STATIC
716 EFI_STATUS
717 BltVideoToVideo (
718 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
719 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
720 IN UINTN SourceX,
721 IN UINTN SourceY,
722 IN UINTN DestinationX,
723 IN UINTN DestinationY,
724 IN UINTN Width,
725 IN UINTN Height,
726 IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer
727 )
728 {
729 EFI_STATUS Status;
730 UINT32 HorizontalResolution;
731 LCD_BPP BitsPerPixel;
732 VOID *FrameBufferBase;
733
734 HorizontalResolution = This->Mode->Info->HorizontalResolution;
735 FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
736
737 //
738 // BltVideo to BltVideo:
739 //
740 // Source is the Video Memory,
741 // Destination is the Video Memory
742
743 LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
744 FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
745
746 // The UEFI spec currently states:
747 // "There is no limitation on the overlapping of the source and destination rectangles"
748 // Therefore, we must be careful to avoid overwriting the source data
749 if( SourceY == DestinationY ) {
750 // Copying within the same height, e.g. horizontal shift
751 if( SourceX == DestinationX ) {
752 // Nothing to do
753 Status = EFI_SUCCESS;
754 } else if( ((SourceX>DestinationX)?(SourceX - DestinationX):(DestinationX - SourceX)) < Width ) {
755 // There is overlap
756 Status = VideoCopyHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
757 } else {
758 // No overlap
759 Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
760 }
761 } else {
762 // Copying from different heights
763 Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
764 }
765
766 return Status;
767 }
768
769 /***************************************
770 * GraphicsOutput Protocol function, mapping to
771 * EFI_GRAPHICS_OUTPUT_PROTOCOL.Blt
772 *
773 * PRESUMES: 1 pixel = 4 bytes (32bits)
774 * ***************************************/
775 EFI_STATUS
776 EFIAPI
777 LcdGraphicsBlt (
778 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
779 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
780 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
781 IN UINTN SourceX,
782 IN UINTN SourceY,
783 IN UINTN DestinationX,
784 IN UINTN DestinationY,
785 IN UINTN Width,
786 IN UINTN Height,
787 IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer
788 )
789 {
790 EFI_STATUS Status;
791 UINT32 HorizontalResolution;
792 UINT32 VerticalResolution;
793 LCD_INSTANCE* Instance;
794
795 Instance = LCD_INSTANCE_FROM_GOP_THIS(This);
796
797 // Setup the hardware if not already done
798 if (!mDisplayInitialized) {
799 Status = InitializeDisplay (Instance);
800 if (EFI_ERROR(Status)) {
801 goto EXIT;
802 }
803 }
804
805 HorizontalResolution = This->Mode->Info->HorizontalResolution;
806 VerticalResolution = This->Mode->Info->VerticalResolution;
807
808 DEBUG((DEBUG_INFO, "LcdGraphicsBlt (BltOperation:%d,DestX:%d,DestY:%d,Width:%d,Height:%d) res(%d,%d)\n",
809 BltOperation,DestinationX,DestinationY,Width,Height,HorizontalResolution,VerticalResolution));
810
811 // Check we have reasonable parameters
812 if (Width == 0 || Height == 0) {
813 DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: ERROR - Invalid dimension: Zero size area.\n" ));
814 Status = EFI_INVALID_PARAMETER;
815 goto EXIT;
816 }
817
818 if ((BltOperation == EfiBltVideoFill) || (BltOperation == EfiBltBufferToVideo) || (BltOperation == EfiBltVideoToBltBuffer)) {
819 ASSERT( BltBuffer != NULL);
820 }
821
822 /*if ((DestinationX >= HorizontalResolution) || (DestinationY >= VerticalResolution)) {
823 DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: ERROR - Invalid destination.\n" ));
824 Status = EFI_INVALID_PARAMETER;
825 goto EXIT;
826 }*/
827
828 // If we are reading data out of the video buffer, check that the source area is within the display limits
829 if ((BltOperation == EfiBltVideoToBltBuffer) || (BltOperation == EfiBltVideoToVideo)) {
830 if ((SourceY + Height > VerticalResolution) || (SourceX + Width > HorizontalResolution)) {
831 DEBUG((DEBUG_INFO, "LcdGraphicsBlt: ERROR - Invalid source resolution.\n" ));
832 DEBUG((DEBUG_INFO, " - SourceY=%d + Height=%d > VerticalResolution=%d.\n", SourceY, Height, VerticalResolution ));
833 DEBUG((DEBUG_INFO, " - SourceX=%d + Width=%d > HorizontalResolution=%d.\n", SourceX, Width, HorizontalResolution ));
834 Status = EFI_INVALID_PARAMETER;
835 goto EXIT;
836 }
837 }
838
839 // If we are writing data into the video buffer, that the destination area is within the display limits
840 if ((BltOperation == EfiBltVideoFill) || (BltOperation == EfiBltBufferToVideo) || (BltOperation == EfiBltVideoToVideo)) {
841 if ((DestinationY + Height > VerticalResolution) || (DestinationX + Width > HorizontalResolution)) {
842 DEBUG((DEBUG_INFO, "LcdGraphicsBlt: ERROR - Invalid destination resolution.\n" ));
843 DEBUG((DEBUG_INFO, " - DestinationY=%d + Height=%d > VerticalResolution=%d.\n", DestinationY, Height, VerticalResolution ));
844 DEBUG((DEBUG_INFO, " - DestinationX=%d + Width=%d > HorizontalResolution=%d.\n", DestinationX, Width, HorizontalResolution ));
845 Status = EFI_INVALID_PARAMETER;
846 goto EXIT;
847 }
848 }
849
850 //
851 // Perform the Block Transfer Operation
852 //
853
854 switch (BltOperation) {
855 case EfiBltVideoFill:
856 Status = BltVideoFill (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
857 break;
858
859 case EfiBltVideoToBltBuffer:
860 Status = BltVideoToBltBuffer (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
861 break;
862
863 case EfiBltBufferToVideo:
864 Status = BltBufferToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
865 break;
866
867 case EfiBltVideoToVideo:
868 Status = BltVideoToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
869 break;
870
871 case EfiGraphicsOutputBltOperationMax:
872 default:
873 DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: Invalid Operation\n"));
874 Status = EFI_INVALID_PARAMETER;
875 break;
876 }
877
878 EXIT:
879 return Status;
880 }