• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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   WidthInBytes = Width * 2;
67 
68   for( LineCount = 0; LineCount < Height; LineCount++ ) {
69     // Update the start addresses of source & destination using 16bit pointer arithmetic
70     SourceAddr      = (VOID *)((UINT16 *)FrameBufferBase + SourceLine      * HorizontalResolution + SourceX     );
71     DestinationAddr = (VOID *)((UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);
72 
73     // Copy the entire line Y from video ram to the temp buffer
74     CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
75 
76     // Update the line numbers
77     SourceLine      += Step;
78     DestinationLine += Step;
79   }
80 
81   return Status;
82 }
83 
84 STATIC
85 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)86 VideoCopyHorizontalOverlap (
87   IN UINTN          BitsPerPixel,
88   IN volatile VOID  *FrameBufferBase,
89   UINT32            HorizontalResolution,
90   IN UINTN          SourceX,
91   IN UINTN          SourceY,
92   IN UINTN          DestinationX,
93   IN UINTN          DestinationY,
94   IN UINTN          Width,
95   IN UINTN          Height
96   )
97 {
98   EFI_STATUS      Status = EFI_SUCCESS;
99 
100   UINT16 *PixelBuffer16bit;
101   UINT16 *SourcePixel16bit;
102   UINT16 *DestinationPixel16bit;
103 
104   UINT32          SourcePixelY;
105   UINT32          DestinationPixelY;
106   UINTN           SizeIn16Bits;
107 
108   // Allocate a temporary buffer
109   PixelBuffer16bit = (UINT16 *) AllocatePool((Height * Width) * sizeof(UINT16));
110 
111   if (PixelBuffer16bit == NULL) {
112     Status = EFI_OUT_OF_RESOURCES;
113     goto EXIT;
114   }
115 
116   // Access each pixel inside the source area of the Video Memory and copy it to the temp buffer
117 
118   SizeIn16Bits = Width * 2;
119 
120   for (SourcePixelY = SourceY, DestinationPixel16bit = PixelBuffer16bit;
121        SourcePixelY < SourceY + Height;
122        SourcePixelY++, DestinationPixel16bit += Width)
123   {
124     // Calculate the source address:
125     SourcePixel16bit = (UINT16 *)FrameBufferBase + SourcePixelY * HorizontalResolution + SourceX;
126 
127     // Copy the entire line Y from Video to the temp buffer
128     CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits);
129   }
130 
131   // Copy from the temp buffer into the destination area of the Video Memory
132 
133   for (DestinationPixelY = DestinationY, SourcePixel16bit = PixelBuffer16bit;
134        DestinationPixelY < DestinationY + Height;
135        DestinationPixelY++, SourcePixel16bit += Width)
136   {
137     // Calculate the target address:
138     DestinationPixel16bit = (UINT16 *)FrameBufferBase + (DestinationPixelY * HorizontalResolution + DestinationX);
139 
140     // Copy the entire line Y from the temp buffer to Video
141     CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits);
142   }
143 
144   // Free the allocated memory
145   FreePool((VOID *) PixelBuffer16bit);
146 
147 
148 EXIT:
149   return Status;
150 }
151 
152 STATIC
153 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)154 BltVideoFill (
155   IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
156   IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *EfiSourcePixel,     OPTIONAL
157   IN UINTN                               SourceX,
158   IN UINTN                               SourceY,
159   IN UINTN                               DestinationX,
160   IN UINTN                               DestinationY,
161   IN UINTN                               Width,
162   IN UINTN                               Height,
163   IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
164   )
165 {
166   EFI_PIXEL_BITMASK*  PixelInformation;
167   EFI_STATUS          Status;
168   UINT32              HorizontalResolution;
169   VOID                *FrameBufferBase;
170   UINT16              *DestinationPixel16bit;
171   UINT16              Pixel16bit;
172   UINT32              DestinationPixelX;
173   UINT32              DestinationLine;
174 
175   Status           = EFI_SUCCESS;
176   PixelInformation = &This->Mode->Info->PixelInformation;
177   FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
178   HorizontalResolution = This->Mode->Info->HorizontalResolution;
179 
180   // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
181   Pixel16bit = (UINT16) (
182       ( (EfiSourcePixel->Red      <<  8) & PixelInformation->RedMask      )
183     | ( (EfiSourcePixel->Green    <<  3) & PixelInformation->GreenMask    )
184     | ( (EfiSourcePixel->Blue     >>  3) & PixelInformation->BlueMask     )
185    );
186 
187   // Copy the SourcePixel into every pixel inside the target rectangle
188   for (DestinationLine = DestinationY;
189        DestinationLine < DestinationY + Height;
190        DestinationLine++)
191   {
192     for (DestinationPixelX = DestinationX;
193          DestinationPixelX < DestinationX + Width;
194          DestinationPixelX++)
195     {
196       // Calculate the target address:
197       DestinationPixel16bit =  (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution  + DestinationPixelX;
198 
199       // Copy the pixel into the new target
200       *DestinationPixel16bit = Pixel16bit;
201     }
202   }
203 
204 
205   return Status;
206 }
207 
208 STATIC
209 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)210 BltVideoToBltBuffer (
211   IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
212   IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,     OPTIONAL
213   IN UINTN                               SourceX,
214   IN UINTN                               SourceY,
215   IN UINTN                               DestinationX,
216   IN UINTN                               DestinationY,
217   IN UINTN                               Width,
218   IN UINTN                               Height,
219   IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
220   )
221 {
222   EFI_STATUS         Status;
223   UINT32             HorizontalResolution;
224   EFI_PIXEL_BITMASK  *PixelInformation;
225   EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiDestinationPixel;
226   VOID               *FrameBufferBase;
227   UINT16             *SourcePixel16bit;
228   UINT16             Pixel16bit;
229   UINT32             SourcePixelX;
230   UINT32             SourceLine;
231   UINT32             DestinationPixelX;
232   UINT32             DestinationLine;
233   UINT32             BltBufferHorizontalResolution;
234 
235   Status = EFI_SUCCESS;
236   PixelInformation = &This->Mode->Info->PixelInformation;
237   HorizontalResolution = This->Mode->Info->HorizontalResolution;
238   FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
239 
240   if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
241     // Delta is not zero and it is different from the width.
242     // Divide it by the size of a pixel to find out the buffer's horizontal resolution.
243     BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
244   } else {
245     BltBufferHorizontalResolution = Width;
246   }
247 
248   // Access each pixel inside the Video Memory
249   for (SourceLine = SourceY, DestinationLine = DestinationY;
250        SourceLine < SourceY + Height;
251        SourceLine++, DestinationLine++)
252   {
253     for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
254          SourcePixelX < SourceX + Width;
255          SourcePixelX++, DestinationPixelX++)
256     {
257       // Calculate the source and target addresses:
258       SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;
259       EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;
260 
261       // Snapshot the pixel from the video buffer once, to speed up the operation.
262       // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
263       Pixel16bit = *SourcePixel16bit;
264 
265       // Copy the pixel into the new target
266       EfiDestinationPixel->Red      = (UINT8) ( (Pixel16bit & PixelInformation->RedMask     ) >>  8 );
267       EfiDestinationPixel->Green    = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask   ) >>  3 );
268       EfiDestinationPixel->Blue     = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask    ) <<  3 );
269     }
270   }
271 
272   return Status;
273 }
274 
275 STATIC
276 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)277 BltBufferToVideo (
278   IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
279   IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,     OPTIONAL
280   IN UINTN                               SourceX,
281   IN UINTN                               SourceY,
282   IN UINTN                               DestinationX,
283   IN UINTN                               DestinationY,
284   IN UINTN                               Width,
285   IN UINTN                               Height,
286   IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
287   )
288 {
289   EFI_STATUS         Status;
290   UINT32             HorizontalResolution;
291   EFI_PIXEL_BITMASK  *PixelInformation;
292   EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiSourcePixel;
293   VOID               *FrameBufferBase;
294   UINT16             *DestinationPixel16bit;
295   UINT32             SourcePixelX;
296   UINT32             SourceLine;
297   UINT32             DestinationPixelX;
298   UINT32             DestinationLine;
299   UINT32             BltBufferHorizontalResolution;
300 
301   Status = EFI_SUCCESS;
302   PixelInformation = &This->Mode->Info->PixelInformation;
303   HorizontalResolution = This->Mode->Info->HorizontalResolution;
304   FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
305 
306   if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
307     // Delta is not zero and it is different from the width.
308     // Divide it by the size of a pixel to find out the buffer's horizontal resolution.
309     BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
310   } else {
311     BltBufferHorizontalResolution = Width;
312   }
313 
314   // Access each pixel inside the BltBuffer Memory
315   for (SourceLine = SourceY, DestinationLine = DestinationY;
316        SourceLine < SourceY + Height;
317        SourceLine++, DestinationLine++) {
318 
319     for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
320          SourcePixelX < SourceX + Width;
321          SourcePixelX++, DestinationPixelX++)
322     {
323       // Calculate the source and target addresses:
324       EfiSourcePixel  = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;
325       DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
326 
327       // Copy the pixel into the new target
328       // Only the most significant bits will be copied across:
329       // To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits
330         *DestinationPixel16bit = (UINT16) (
331               ( (EfiSourcePixel->Red      <<  8) & PixelInformation->RedMask      )
332             | ( (EfiSourcePixel->Green    <<  3) & PixelInformation->GreenMask    )
333             | ( (EfiSourcePixel->Blue     >>  3) & PixelInformation->BlueMask     )
334             );
335       }
336     }
337 
338   return Status;
339 }
340 
341 STATIC
342 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)343 BltVideoToVideo (
344   IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
345   IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,     OPTIONAL
346   IN UINTN                               SourceX,
347   IN UINTN                               SourceY,
348   IN UINTN                               DestinationX,
349   IN UINTN                               DestinationY,
350   IN UINTN                               Width,
351   IN UINTN                               Height,
352   IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
353   )
354 {
355   EFI_STATUS         Status;
356   UINT32             HorizontalResolution;
357   UINTN              BitsPerPixel;
358   VOID               *FrameBufferBase;
359 
360   BitsPerPixel = 16;
361 
362   HorizontalResolution = This->Mode->Info->HorizontalResolution;
363   FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
364 
365   //
366   // BltVideo to BltVideo:
367   //
368   //  Source is the Video Memory,
369   //  Destination is the Video Memory
370 
371   FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
372 
373   // The UEFI spec currently states:
374   // "There is no limitation on the overlapping of the source and destination rectangles"
375   // Therefore, we must be careful to avoid overwriting the source data
376   if( SourceY == DestinationY ) {
377     // Copying within the same height, e.g. horizontal shift
378     if( SourceX == DestinationX ) {
379       // Nothing to do
380       Status = EFI_SUCCESS;
381     } else if( ((SourceX>DestinationX)?(SourceX - DestinationX):(DestinationX - SourceX)) < Width ) {
382       // There is overlap
383       Status = VideoCopyHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
384     } else {
385       // No overlap
386       Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
387     }
388   } else {
389     // Copying from different heights
390     Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
391   }
392 
393   return Status;
394 }
395 
396 EFI_STATUS
397 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)398 LcdGraphicsBlt (
399   IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
400   IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,     OPTIONAL
401   IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION   BltOperation,
402   IN UINTN                               SourceX,
403   IN UINTN                               SourceY,
404   IN UINTN                               DestinationX,
405   IN UINTN                               DestinationY,
406   IN UINTN                               Width,
407   IN UINTN                               Height,
408   IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
409   )
410 {
411   EFI_STATUS    Status;
412   LCD_INSTANCE  *Instance;
413 
414   Instance = LCD_INSTANCE_FROM_GOP_THIS(This);
415 
416   if (!mDisplayInitialized) {
417     InitializeDisplay (Instance);
418   }
419 
420   switch (BltOperation) {
421   case EfiBltVideoFill:
422     Status = BltVideoFill (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
423     break;
424 
425   case EfiBltVideoToBltBuffer:
426     Status = BltVideoToBltBuffer (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
427     break;
428 
429   case EfiBltBufferToVideo:
430     Status = BltBufferToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
431     break;
432 
433   case EfiBltVideoToVideo:
434     Status = BltVideoToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
435     break;
436 
437   case EfiGraphicsOutputBltOperationMax:
438   default:
439     DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: Invalid Operation\n"));
440     Status = EFI_INVALID_PARAMETER;
441     break;
442 }
443 
444   return Status;
445 }
446