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