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
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.
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>
21 #include <Guid/GlobalVariable.h>
23 #include "LcdGraphicsOutputDxe.h"
25 extern BOOLEAN mDisplayInitialized
;
28 // Function Definitions
33 VideoCopyNoHorizontalOverlap (
34 IN UINTN BitsPerPixel
,
35 IN
volatile VOID
*FrameBufferBase
,
36 IN UINT32 HorizontalResolution
,
39 IN UINTN DestinationX
,
40 IN UINTN DestinationY
,
45 EFI_STATUS Status
= EFI_SUCCESS
;
47 UINTN DestinationLine
;
52 VOID
*DestinationAddr
;
54 if( DestinationY
<= SourceY
) {
55 // scrolling up (or horizontally but without overlap)
57 DestinationLine
= DestinationY
;
61 SourceLine
= SourceY
+ Height
;
62 DestinationLine
= DestinationY
+ Height
;
66 WidthInBytes
= Width
* 2;
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
);
73 // Copy the entire line Y from video ram to the temp buffer
74 CopyMem( DestinationAddr
, SourceAddr
, WidthInBytes
);
76 // Update the line numbers
78 DestinationLine
+= Step
;
86 VideoCopyHorizontalOverlap (
87 IN UINTN BitsPerPixel
,
88 IN
volatile VOID
*FrameBufferBase
,
89 UINT32 HorizontalResolution
,
92 IN UINTN DestinationX
,
93 IN UINTN DestinationY
,
98 EFI_STATUS Status
= EFI_SUCCESS
;
100 UINT16
*PixelBuffer16bit
;
101 UINT16
*SourcePixel16bit
;
102 UINT16
*DestinationPixel16bit
;
105 UINT32 DestinationPixelY
;
108 // Allocate a temporary buffer
109 PixelBuffer16bit
= (UINT16
*) AllocatePool((Height
* Width
) * sizeof(UINT16
));
111 if (PixelBuffer16bit
== NULL
) {
112 Status
= EFI_OUT_OF_RESOURCES
;
116 // Access each pixel inside the source area of the Video Memory and copy it to the temp buffer
118 SizeIn16Bits
= Width
* 2;
120 for (SourcePixelY
= SourceY
, DestinationPixel16bit
= PixelBuffer16bit
;
121 SourcePixelY
< SourceY
+ Height
;
122 SourcePixelY
++, DestinationPixel16bit
+= Width
)
124 // Calculate the source address:
125 SourcePixel16bit
= (UINT16
*)FrameBufferBase
+ SourcePixelY
* HorizontalResolution
+ SourceX
;
127 // Copy the entire line Y from Video to the temp buffer
128 CopyMem( (VOID
*)DestinationPixel16bit
, (CONST VOID
*)SourcePixel16bit
, SizeIn16Bits
);
131 // Copy from the temp buffer into the destination area of the Video Memory
133 for (DestinationPixelY
= DestinationY
, SourcePixel16bit
= PixelBuffer16bit
;
134 DestinationPixelY
< DestinationY
+ Height
;
135 DestinationPixelY
++, SourcePixel16bit
+= Width
)
137 // Calculate the target address:
138 DestinationPixel16bit
= (UINT16
*)FrameBufferBase
+ (DestinationPixelY
* HorizontalResolution
+ DestinationX
);
140 // Copy the entire line Y from the temp buffer to Video
141 CopyMem( (VOID
*)DestinationPixel16bit
, (CONST VOID
*)SourcePixel16bit
, SizeIn16Bits
);
144 // Free the allocated memory
145 FreePool((VOID
*) PixelBuffer16bit
);
155 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
156 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*EfiSourcePixel
, OPTIONAL
159 IN UINTN DestinationX
,
160 IN UINTN DestinationY
,
163 IN UINTN Delta OPTIONAL
// Number of BYTES in a row of the BltBuffer
166 EFI_PIXEL_BITMASK
* PixelInformation
;
168 UINT32 HorizontalResolution
;
169 VOID
*FrameBufferBase
;
170 UINT16
*DestinationPixel16bit
;
172 UINT32 DestinationPixelX
;
173 UINT32 DestinationLine
;
175 Status
= EFI_SUCCESS
;
176 PixelInformation
= &This
->Mode
->Info
->PixelInformation
;
177 FrameBufferBase
= (UINTN
*)((UINTN
)(This
->Mode
->FrameBufferBase
));
178 HorizontalResolution
= This
->Mode
->Info
->HorizontalResolution
;
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
)
187 // Copy the SourcePixel into every pixel inside the target rectangle
188 for (DestinationLine
= DestinationY
;
189 DestinationLine
< DestinationY
+ Height
;
192 for (DestinationPixelX
= DestinationX
;
193 DestinationPixelX
< DestinationX
+ Width
;
196 // Calculate the target address:
197 DestinationPixel16bit
= (UINT16
*)FrameBufferBase
+ DestinationLine
* HorizontalResolution
+ DestinationPixelX
;
199 // Copy the pixel into the new target
200 *DestinationPixel16bit
= Pixel16bit
;
210 BltVideoToBltBuffer (
211 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
212 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
215 IN UINTN DestinationX
,
216 IN UINTN DestinationY
,
219 IN UINTN Delta OPTIONAL
// Number of BYTES in a row of the BltBuffer
223 UINT32 HorizontalResolution
;
224 EFI_PIXEL_BITMASK
*PixelInformation
;
225 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*EfiDestinationPixel
;
226 VOID
*FrameBufferBase
;
227 UINT16
*SourcePixel16bit
;
231 UINT32 DestinationPixelX
;
232 UINT32 DestinationLine
;
233 UINT32 BltBufferHorizontalResolution
;
235 Status
= EFI_SUCCESS
;
236 PixelInformation
= &This
->Mode
->Info
->PixelInformation
;
237 HorizontalResolution
= This
->Mode
->Info
->HorizontalResolution
;
238 FrameBufferBase
= (UINTN
*)((UINTN
)(This
->Mode
->FrameBufferBase
));
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
));
245 BltBufferHorizontalResolution
= Width
;
248 // Access each pixel inside the Video Memory
249 for (SourceLine
= SourceY
, DestinationLine
= DestinationY
;
250 SourceLine
< SourceY
+ Height
;
251 SourceLine
++, DestinationLine
++)
253 for (SourcePixelX
= SourceX
, DestinationPixelX
= DestinationX
;
254 SourcePixelX
< SourceX
+ Width
;
255 SourcePixelX
++, DestinationPixelX
++)
257 // Calculate the source and target addresses:
258 SourcePixel16bit
= (UINT16
*)FrameBufferBase
+ SourceLine
* HorizontalResolution
+ SourcePixelX
;
259 EfiDestinationPixel
= BltBuffer
+ DestinationLine
* BltBufferHorizontalResolution
+ DestinationPixelX
;
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
;
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 );
278 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
279 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
282 IN UINTN DestinationX
,
283 IN UINTN DestinationY
,
286 IN UINTN Delta OPTIONAL
// Number of BYTES in a row of the BltBuffer
290 UINT32 HorizontalResolution
;
291 EFI_PIXEL_BITMASK
*PixelInformation
;
292 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*EfiSourcePixel
;
293 VOID
*FrameBufferBase
;
294 UINT16
*DestinationPixel16bit
;
297 UINT32 DestinationPixelX
;
298 UINT32 DestinationLine
;
299 UINT32 BltBufferHorizontalResolution
;
301 Status
= EFI_SUCCESS
;
302 PixelInformation
= &This
->Mode
->Info
->PixelInformation
;
303 HorizontalResolution
= This
->Mode
->Info
->HorizontalResolution
;
304 FrameBufferBase
= (UINTN
*)((UINTN
)(This
->Mode
->FrameBufferBase
));
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
));
311 BltBufferHorizontalResolution
= Width
;
314 // Access each pixel inside the BltBuffer Memory
315 for (SourceLine
= SourceY
, DestinationLine
= DestinationY
;
316 SourceLine
< SourceY
+ Height
;
317 SourceLine
++, DestinationLine
++) {
319 for (SourcePixelX
= SourceX
, DestinationPixelX
= DestinationX
;
320 SourcePixelX
< SourceX
+ Width
;
321 SourcePixelX
++, DestinationPixelX
++)
323 // Calculate the source and target addresses:
324 EfiSourcePixel
= BltBuffer
+ SourceLine
* BltBufferHorizontalResolution
+ SourcePixelX
;
325 DestinationPixel16bit
= (UINT16
*)FrameBufferBase
+ DestinationLine
* HorizontalResolution
+ DestinationPixelX
;
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
)
344 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
345 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
348 IN UINTN DestinationX
,
349 IN UINTN DestinationY
,
352 IN UINTN Delta OPTIONAL
// Number of BYTES in a row of the BltBuffer
356 UINT32 HorizontalResolution
;
358 VOID
*FrameBufferBase
;
362 HorizontalResolution
= This
->Mode
->Info
->HorizontalResolution
;
363 FrameBufferBase
= (UINTN
*)((UINTN
)(This
->Mode
->FrameBufferBase
));
366 // BltVideo to BltVideo:
368 // Source is the Video Memory,
369 // Destination is the Video Memory
371 FrameBufferBase
= (UINTN
*)((UINTN
)(This
->Mode
->FrameBufferBase
));
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
) {
380 Status
= EFI_SUCCESS
;
381 } else if( ((SourceX
>DestinationX
)?(SourceX
- DestinationX
):(DestinationX
- SourceX
)) < Width
) {
383 Status
= VideoCopyHorizontalOverlap (BitsPerPixel
, FrameBufferBase
, HorizontalResolution
, SourceX
, SourceY
, DestinationX
, DestinationY
, Width
, Height
);
386 Status
= VideoCopyNoHorizontalOverlap (BitsPerPixel
, FrameBufferBase
, HorizontalResolution
, SourceX
, SourceY
, DestinationX
, DestinationY
, Width
, Height
);
389 // Copying from different heights
390 Status
= VideoCopyNoHorizontalOverlap (BitsPerPixel
, FrameBufferBase
, HorizontalResolution
, SourceX
, SourceY
, DestinationX
, DestinationY
, Width
, Height
);
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
,
404 IN UINTN DestinationX
,
405 IN UINTN DestinationY
,
408 IN UINTN Delta OPTIONAL
// Number of BYTES in a row of the BltBuffer
412 LCD_INSTANCE
*Instance
;
414 Instance
= LCD_INSTANCE_FROM_GOP_THIS(This
);
416 if (!mDisplayInitialized
) {
417 InitializeDisplay (Instance
);
420 switch (BltOperation
) {
421 case EfiBltVideoFill
:
422 Status
= BltVideoFill (This
, BltBuffer
, SourceX
, SourceY
, DestinationX
, DestinationY
, Width
, Height
, Delta
);
425 case EfiBltVideoToBltBuffer
:
426 Status
= BltVideoToBltBuffer (This
, BltBuffer
, SourceX
, SourceY
, DestinationX
, DestinationY
, Width
, Height
, Delta
);
429 case EfiBltBufferToVideo
:
430 Status
= BltBufferToVideo (This
, BltBuffer
, SourceX
, SourceY
, DestinationX
, DestinationY
, Width
, Height
, Delta
);
433 case EfiBltVideoToVideo
:
434 Status
= BltVideoToVideo (This
, BltBuffer
, SourceX
, SourceY
, DestinationX
, DestinationY
, Width
, Height
, Delta
);
437 case EfiGraphicsOutputBltOperationMax
:
439 DEBUG((DEBUG_ERROR
, "LcdGraphicsBlt: Invalid Operation\n"));
440 Status
= EFI_INVALID_PARAMETER
;