3 Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
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>
15 #include <Guid/GlobalVariable.h>
17 #include "LcdGraphicsOutputDxe.h"
19 extern BOOLEAN mDisplayInitialized
;
22 // Function Definitions
27 VideoCopyNoHorizontalOverlap (
28 IN UINTN BitsPerPixel
,
29 IN
volatile VOID
*FrameBufferBase
,
30 IN UINT32 HorizontalResolution
,
33 IN UINTN DestinationX
,
34 IN UINTN DestinationY
,
39 EFI_STATUS Status
= EFI_SUCCESS
;
41 UINTN DestinationLine
;
46 VOID
*DestinationAddr
;
48 if( DestinationY
<= SourceY
) {
49 // scrolling up (or horizontally but without overlap)
51 DestinationLine
= DestinationY
;
55 SourceLine
= SourceY
+ Height
;
56 DestinationLine
= DestinationY
+ Height
;
60 WidthInBytes
= Width
* 2;
62 for( LineCount
= 0; LineCount
< Height
; LineCount
++ ) {
63 // Update the start addresses of source & destination using 16bit pointer arithmetic
64 SourceAddr
= (VOID
*)((UINT16
*)FrameBufferBase
+ SourceLine
* HorizontalResolution
+ SourceX
);
65 DestinationAddr
= (VOID
*)((UINT16
*)FrameBufferBase
+ DestinationLine
* HorizontalResolution
+ DestinationX
);
67 // Copy the entire line Y from video ram to the temp buffer
68 CopyMem( DestinationAddr
, SourceAddr
, WidthInBytes
);
70 // Update the line numbers
72 DestinationLine
+= Step
;
80 VideoCopyHorizontalOverlap (
81 IN UINTN BitsPerPixel
,
82 IN
volatile VOID
*FrameBufferBase
,
83 UINT32 HorizontalResolution
,
86 IN UINTN DestinationX
,
87 IN UINTN DestinationY
,
92 EFI_STATUS Status
= EFI_SUCCESS
;
94 UINT16
*PixelBuffer16bit
;
95 UINT16
*SourcePixel16bit
;
96 UINT16
*DestinationPixel16bit
;
99 UINT32 DestinationPixelY
;
102 // Allocate a temporary buffer
103 PixelBuffer16bit
= (UINT16
*) AllocatePool((Height
* Width
) * sizeof(UINT16
));
105 if (PixelBuffer16bit
== NULL
) {
106 Status
= EFI_OUT_OF_RESOURCES
;
110 // Access each pixel inside the source area of the Video Memory and copy it to the temp buffer
112 SizeIn16Bits
= Width
* 2;
114 for (SourcePixelY
= SourceY
, DestinationPixel16bit
= PixelBuffer16bit
;
115 SourcePixelY
< SourceY
+ Height
;
116 SourcePixelY
++, DestinationPixel16bit
+= Width
)
118 // Calculate the source address:
119 SourcePixel16bit
= (UINT16
*)FrameBufferBase
+ SourcePixelY
* HorizontalResolution
+ SourceX
;
121 // Copy the entire line Y from Video to the temp buffer
122 CopyMem( (VOID
*)DestinationPixel16bit
, (CONST VOID
*)SourcePixel16bit
, SizeIn16Bits
);
125 // Copy from the temp buffer into the destination area of the Video Memory
127 for (DestinationPixelY
= DestinationY
, SourcePixel16bit
= PixelBuffer16bit
;
128 DestinationPixelY
< DestinationY
+ Height
;
129 DestinationPixelY
++, SourcePixel16bit
+= Width
)
131 // Calculate the target address:
132 DestinationPixel16bit
= (UINT16
*)FrameBufferBase
+ (DestinationPixelY
* HorizontalResolution
+ DestinationX
);
134 // Copy the entire line Y from the temp buffer to Video
135 CopyMem( (VOID
*)DestinationPixel16bit
, (CONST VOID
*)SourcePixel16bit
, SizeIn16Bits
);
138 // Free the allocated memory
139 FreePool((VOID
*) PixelBuffer16bit
);
149 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
150 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*EfiSourcePixel
, OPTIONAL
153 IN UINTN DestinationX
,
154 IN UINTN DestinationY
,
157 IN UINTN Delta OPTIONAL
// Number of BYTES in a row of the BltBuffer
160 EFI_PIXEL_BITMASK
* PixelInformation
;
162 UINT32 HorizontalResolution
;
163 VOID
*FrameBufferBase
;
164 UINT16
*DestinationPixel16bit
;
166 UINT32 DestinationPixelX
;
167 UINT32 DestinationLine
;
169 Status
= EFI_SUCCESS
;
170 PixelInformation
= &This
->Mode
->Info
->PixelInformation
;
171 FrameBufferBase
= (UINTN
*)((UINTN
)(This
->Mode
->FrameBufferBase
));
172 HorizontalResolution
= This
->Mode
->Info
->HorizontalResolution
;
174 // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
175 Pixel16bit
= (UINT16
) (
176 ( (EfiSourcePixel
->Red
<< 8) & PixelInformation
->RedMask
)
177 | ( (EfiSourcePixel
->Green
<< 3) & PixelInformation
->GreenMask
)
178 | ( (EfiSourcePixel
->Blue
>> 3) & PixelInformation
->BlueMask
)
181 // Copy the SourcePixel into every pixel inside the target rectangle
182 for (DestinationLine
= DestinationY
;
183 DestinationLine
< DestinationY
+ Height
;
186 for (DestinationPixelX
= DestinationX
;
187 DestinationPixelX
< DestinationX
+ Width
;
190 // Calculate the target address:
191 DestinationPixel16bit
= (UINT16
*)FrameBufferBase
+ DestinationLine
* HorizontalResolution
+ DestinationPixelX
;
193 // Copy the pixel into the new target
194 *DestinationPixel16bit
= Pixel16bit
;
204 BltVideoToBltBuffer (
205 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
206 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
209 IN UINTN DestinationX
,
210 IN UINTN DestinationY
,
213 IN UINTN Delta OPTIONAL
// Number of BYTES in a row of the BltBuffer
217 UINT32 HorizontalResolution
;
218 EFI_PIXEL_BITMASK
*PixelInformation
;
219 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*EfiDestinationPixel
;
220 VOID
*FrameBufferBase
;
221 UINT16
*SourcePixel16bit
;
225 UINT32 DestinationPixelX
;
226 UINT32 DestinationLine
;
227 UINT32 BltBufferHorizontalResolution
;
229 Status
= EFI_SUCCESS
;
230 PixelInformation
= &This
->Mode
->Info
->PixelInformation
;
231 HorizontalResolution
= This
->Mode
->Info
->HorizontalResolution
;
232 FrameBufferBase
= (UINTN
*)((UINTN
)(This
->Mode
->FrameBufferBase
));
234 if(( Delta
!= 0 ) && ( Delta
!= Width
* sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL
))) {
235 // Delta is not zero and it is different from the width.
236 // Divide it by the size of a pixel to find out the buffer's horizontal resolution.
237 BltBufferHorizontalResolution
= (UINT32
) (Delta
/ sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
239 BltBufferHorizontalResolution
= Width
;
242 // Access each pixel inside the Video Memory
243 for (SourceLine
= SourceY
, DestinationLine
= DestinationY
;
244 SourceLine
< SourceY
+ Height
;
245 SourceLine
++, DestinationLine
++)
247 for (SourcePixelX
= SourceX
, DestinationPixelX
= DestinationX
;
248 SourcePixelX
< SourceX
+ Width
;
249 SourcePixelX
++, DestinationPixelX
++)
251 // Calculate the source and target addresses:
252 SourcePixel16bit
= (UINT16
*)FrameBufferBase
+ SourceLine
* HorizontalResolution
+ SourcePixelX
;
253 EfiDestinationPixel
= BltBuffer
+ DestinationLine
* BltBufferHorizontalResolution
+ DestinationPixelX
;
255 // Snapshot the pixel from the video buffer once, to speed up the operation.
256 // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
257 Pixel16bit
= *SourcePixel16bit
;
259 // Copy the pixel into the new target
260 EfiDestinationPixel
->Red
= (UINT8
) ( (Pixel16bit
& PixelInformation
->RedMask
) >> 8 );
261 EfiDestinationPixel
->Green
= (UINT8
) ( (Pixel16bit
& PixelInformation
->GreenMask
) >> 3 );
262 EfiDestinationPixel
->Blue
= (UINT8
) ( (Pixel16bit
& PixelInformation
->BlueMask
) << 3 );
272 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
273 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
276 IN UINTN DestinationX
,
277 IN UINTN DestinationY
,
280 IN UINTN Delta OPTIONAL
// Number of BYTES in a row of the BltBuffer
284 UINT32 HorizontalResolution
;
285 EFI_PIXEL_BITMASK
*PixelInformation
;
286 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*EfiSourcePixel
;
287 VOID
*FrameBufferBase
;
288 UINT16
*DestinationPixel16bit
;
291 UINT32 DestinationPixelX
;
292 UINT32 DestinationLine
;
293 UINT32 BltBufferHorizontalResolution
;
295 Status
= EFI_SUCCESS
;
296 PixelInformation
= &This
->Mode
->Info
->PixelInformation
;
297 HorizontalResolution
= This
->Mode
->Info
->HorizontalResolution
;
298 FrameBufferBase
= (UINTN
*)((UINTN
)(This
->Mode
->FrameBufferBase
));
300 if(( Delta
!= 0 ) && ( Delta
!= Width
* sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL
))) {
301 // Delta is not zero and it is different from the width.
302 // Divide it by the size of a pixel to find out the buffer's horizontal resolution.
303 BltBufferHorizontalResolution
= (UINT32
) (Delta
/ sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
305 BltBufferHorizontalResolution
= Width
;
308 // Access each pixel inside the BltBuffer Memory
309 for (SourceLine
= SourceY
, DestinationLine
= DestinationY
;
310 SourceLine
< SourceY
+ Height
;
311 SourceLine
++, DestinationLine
++) {
313 for (SourcePixelX
= SourceX
, DestinationPixelX
= DestinationX
;
314 SourcePixelX
< SourceX
+ Width
;
315 SourcePixelX
++, DestinationPixelX
++)
317 // Calculate the source and target addresses:
318 EfiSourcePixel
= BltBuffer
+ SourceLine
* BltBufferHorizontalResolution
+ SourcePixelX
;
319 DestinationPixel16bit
= (UINT16
*)FrameBufferBase
+ DestinationLine
* HorizontalResolution
+ DestinationPixelX
;
321 // Copy the pixel into the new target
322 // Only the most significant bits will be copied across:
323 // To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits
324 *DestinationPixel16bit
= (UINT16
) (
325 ( (EfiSourcePixel
->Red
<< 8) & PixelInformation
->RedMask
)
326 | ( (EfiSourcePixel
->Green
<< 3) & PixelInformation
->GreenMask
)
327 | ( (EfiSourcePixel
->Blue
>> 3) & PixelInformation
->BlueMask
)
338 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
339 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
342 IN UINTN DestinationX
,
343 IN UINTN DestinationY
,
346 IN UINTN Delta OPTIONAL
// Number of BYTES in a row of the BltBuffer
350 UINT32 HorizontalResolution
;
352 VOID
*FrameBufferBase
;
356 HorizontalResolution
= This
->Mode
->Info
->HorizontalResolution
;
357 FrameBufferBase
= (UINTN
*)((UINTN
)(This
->Mode
->FrameBufferBase
));
360 // BltVideo to BltVideo:
362 // Source is the Video Memory,
363 // Destination is the Video Memory
365 FrameBufferBase
= (UINTN
*)((UINTN
)(This
->Mode
->FrameBufferBase
));
367 // The UEFI spec currently states:
368 // "There is no limitation on the overlapping of the source and destination rectangles"
369 // Therefore, we must be careful to avoid overwriting the source data
370 if( SourceY
== DestinationY
) {
371 // Copying within the same height, e.g. horizontal shift
372 if( SourceX
== DestinationX
) {
374 Status
= EFI_SUCCESS
;
375 } else if( ((SourceX
>DestinationX
)?(SourceX
- DestinationX
):(DestinationX
- SourceX
)) < Width
) {
377 Status
= VideoCopyHorizontalOverlap (BitsPerPixel
, FrameBufferBase
, HorizontalResolution
, SourceX
, SourceY
, DestinationX
, DestinationY
, Width
, Height
);
380 Status
= VideoCopyNoHorizontalOverlap (BitsPerPixel
, FrameBufferBase
, HorizontalResolution
, SourceX
, SourceY
, DestinationX
, DestinationY
, Width
, Height
);
383 // Copying from different heights
384 Status
= VideoCopyNoHorizontalOverlap (BitsPerPixel
, FrameBufferBase
, HorizontalResolution
, SourceX
, SourceY
, DestinationX
, DestinationY
, Width
, Height
);
393 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
394 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
395 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
398 IN UINTN DestinationX
,
399 IN UINTN DestinationY
,
402 IN UINTN Delta OPTIONAL
// Number of BYTES in a row of the BltBuffer
406 LCD_INSTANCE
*Instance
;
408 Instance
= LCD_INSTANCE_FROM_GOP_THIS(This
);
410 if (!mDisplayInitialized
) {
411 InitializeDisplay (Instance
);
414 switch (BltOperation
) {
415 case EfiBltVideoFill
:
416 Status
= BltVideoFill (This
, BltBuffer
, SourceX
, SourceY
, DestinationX
, DestinationY
, Width
, Height
, Delta
);
419 case EfiBltVideoToBltBuffer
:
420 Status
= BltVideoToBltBuffer (This
, BltBuffer
, SourceX
, SourceY
, DestinationX
, DestinationY
, Width
, Height
, Delta
);
423 case EfiBltBufferToVideo
:
424 Status
= BltBufferToVideo (This
, BltBuffer
, SourceX
, SourceY
, DestinationX
, DestinationY
, Width
, Height
, Delta
);
427 case EfiBltVideoToVideo
:
428 Status
= BltVideoToVideo (This
, BltBuffer
, SourceX
, SourceY
, DestinationX
, DestinationY
, Width
, Height
, Delta
);
431 case EfiGraphicsOutputBltOperationMax
:
433 DEBUG((DEBUG_ERROR
, "LcdGraphicsBlt: Invalid Operation\n"));
434 Status
= EFI_INVALID_PARAMETER
;