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