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