2 FrameBufferBltLib - Library to perform blt operations on a frame buffer.
4 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include <Uefi/UefiBaseType.h>
16 #include <Protocol/GraphicsOutput.h>
18 #include <Library/BaseLib.h>
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/FrameBufferBltLib.h>
23 struct FRAME_BUFFER_CONFIGURE
{
24 UINT32 PixelsPerScanLine
;
29 EFI_GRAPHICS_PIXEL_FORMAT PixelFormat
;
30 EFI_PIXEL_BITMASK PixelMasks
;
31 INT8 PixelShl
[4]; // R-G-B-Rsvd
32 INT8 PixelShr
[4]; // R-G-B-Rsvd
36 CONST EFI_PIXEL_BITMASK mRgbPixelMasks
= {
37 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
40 CONST EFI_PIXEL_BITMASK mBgrPixelMasks
= {
41 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000
45 Initialize the bit mask in frame buffer configure.
47 @param BitMask The bit mask of pixel.
48 @param BytesPerPixel Size in bytes of pixel.
49 @param PixelShl Left shift array.
50 @param PixelShr Right shift array.
53 FrameBufferBltLibConfigurePixelFormat (
54 IN CONST EFI_PIXEL_BITMASK
*BitMask
,
55 OUT UINT32
*BytesPerPixel
,
64 ASSERT (BytesPerPixel
!= NULL
);
67 Masks
= (UINT32
*) BitMask
;
68 for (Index
= 0; Index
< 3; Index
++) {
69 ASSERT ((MergedMasks
& Masks
[Index
]) == 0);
71 PixelShl
[Index
] = (INT8
) HighBitSet32 (Masks
[Index
]) - 23 + (Index
* 8);
72 if (PixelShl
[Index
] < 0) {
73 PixelShr
[Index
] = -PixelShl
[Index
];
78 DEBUG ((DEBUG_INFO
, "%d: shl:%d shr:%d mask:%x\n", Index
,
79 PixelShl
[Index
], PixelShr
[Index
], Masks
[Index
]));
81 MergedMasks
= (UINT32
) (MergedMasks
| Masks
[Index
]);
83 MergedMasks
= (UINT32
) (MergedMasks
| Masks
[3]);
85 ASSERT (MergedMasks
!= 0);
86 *BytesPerPixel
= (UINT32
) ((HighBitSet32 (MergedMasks
) + 7) / 8);
87 DEBUG ((DEBUG_INFO
, "Bytes per pixel: %d\n", *BytesPerPixel
));
91 Create the configuration for a video frame buffer.
93 The configuration is returned in the caller provided buffer.
95 @param[in] FrameBuffer Pointer to the start of the frame buffer.
96 @param[in] FrameBufferInfo Describes the frame buffer characteristics.
97 @param[in,out] Configure The created configuration information.
98 @param[in,out] ConfigureSize Size of the configuration information.
100 @retval RETURN_SUCCESS The configuration was successful created.
101 @retval RETURN_BUFFER_TOO_SMALL The Configure is to too small. The required
102 size is returned in ConfigureSize.
103 @retval RETURN_UNSUPPORTED The requested mode is not supported by
109 FrameBufferBltConfigure (
110 IN VOID
*FrameBuffer
,
111 IN EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*FrameBufferInfo
,
112 IN OUT FRAME_BUFFER_CONFIGURE
*Configure
,
113 IN OUT UINTN
*ConfigureSize
116 CONST EFI_PIXEL_BITMASK
*BitMask
;
117 UINT32 BytesPerPixel
;
121 if (ConfigureSize
== NULL
) {
122 return RETURN_INVALID_PARAMETER
;
125 switch (FrameBufferInfo
->PixelFormat
) {
126 case PixelRedGreenBlueReserved8BitPerColor
:
127 BitMask
= &mRgbPixelMasks
;
130 case PixelBlueGreenRedReserved8BitPerColor
:
131 BitMask
= &mBgrPixelMasks
;
135 BitMask
= &FrameBufferInfo
->PixelInformation
;
139 ASSERT (FrameBufferInfo
->PixelFormat
!= PixelBltOnly
);
140 return RETURN_UNSUPPORTED
;
144 return RETURN_INVALID_PARAMETER
;
147 if (FrameBufferInfo
->PixelsPerScanLine
< FrameBufferInfo
->HorizontalResolution
) {
148 return RETURN_UNSUPPORTED
;
151 FrameBufferBltLibConfigurePixelFormat (BitMask
, &BytesPerPixel
, PixelShl
, PixelShr
);
153 if (*ConfigureSize
< sizeof (FRAME_BUFFER_CONFIGURE
)
154 + FrameBufferInfo
->HorizontalResolution
* BytesPerPixel
) {
155 *ConfigureSize
= sizeof (FRAME_BUFFER_CONFIGURE
)
156 + FrameBufferInfo
->HorizontalResolution
* BytesPerPixel
;
157 return RETURN_BUFFER_TOO_SMALL
;
160 if (Configure
== NULL
) {
161 return RETURN_INVALID_PARAMETER
;
164 CopyMem (&Configure
->PixelMasks
, BitMask
, sizeof (*BitMask
));
165 CopyMem (Configure
->PixelShl
, PixelShl
, sizeof (PixelShl
));
166 CopyMem (Configure
->PixelShr
, PixelShr
, sizeof (PixelShr
));
167 Configure
->BytesPerPixel
= BytesPerPixel
;
168 Configure
->PixelFormat
= FrameBufferInfo
->PixelFormat
;
169 Configure
->FrameBuffer
= (UINT8
*) FrameBuffer
;
170 Configure
->Width
= FrameBufferInfo
->HorizontalResolution
;
171 Configure
->Height
= FrameBufferInfo
->VerticalResolution
;
172 Configure
->PixelsPerScanLine
= FrameBufferInfo
->PixelsPerScanLine
;
174 return RETURN_SUCCESS
;
178 Performs a UEFI Graphics Output Protocol Blt Video Fill.
180 @param[in] Configure Pointer to a configuration which was successfully
181 created by FrameBufferBltConfigure ().
182 @param[in] Color Color to fill the region with.
183 @param[in] DestinationX X location to start fill operation.
184 @param[in] DestinationY Y location to start fill operation.
185 @param[in] Width Width (in pixels) to fill.
186 @param[in] Height Height to fill.
188 @retval RETURN_INVALID_PARAMETER Invalid parameter was passed in.
189 @retval RETURN_SUCCESS The video was filled successfully.
193 FrameBufferBltLibVideoFill (
194 IN FRAME_BUFFER_CONFIGURE
*Configure
,
195 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Color
,
196 IN UINTN DestinationX
,
197 IN UINTN DestinationY
,
209 BOOLEAN LineBufferReady
;
215 // BltBuffer to Video: Source is BltBuffer, destination is Video
217 if (DestinationY
+ Height
> Configure
->Height
) {
218 DEBUG ((EFI_D_VERBOSE
, "VideoFill: Past screen (Y)\n"));
219 return RETURN_INVALID_PARAMETER
;
222 if (DestinationX
+ Width
> Configure
->Width
) {
223 DEBUG ((EFI_D_VERBOSE
, "VideoFill: Past screen (X)\n"));
224 return RETURN_INVALID_PARAMETER
;
227 if (Width
== 0 || Height
== 0) {
228 DEBUG ((EFI_D_VERBOSE
, "VideoFill: Width or Height is 0\n"));
229 return RETURN_INVALID_PARAMETER
;
232 WidthInBytes
= Width
* Configure
->BytesPerPixel
;
234 Uint32
= *(UINT32
*) Color
;
237 (((Uint32
<< Configure
->PixelShl
[0]) >> Configure
->PixelShr
[0]) &
238 Configure
->PixelMasks
.RedMask
) |
239 (((Uint32
<< Configure
->PixelShl
[1]) >> Configure
->PixelShr
[1]) &
240 Configure
->PixelMasks
.GreenMask
) |
241 (((Uint32
<< Configure
->PixelShl
[2]) >> Configure
->PixelShr
[2]) &
242 Configure
->PixelMasks
.BlueMask
)
244 DEBUG ((EFI_D_VERBOSE
, "VideoFill: color=0x%x, wide-fill=0x%x\n",
248 // If the size of the pixel data evenly divides the sizeof
249 // WideFill, then a wide fill operation can be used
252 if ((sizeof (WideFill
) % Configure
->BytesPerPixel
) == 0) {
253 for (IndexX
= Configure
->BytesPerPixel
; IndexX
< sizeof (WideFill
); IndexX
++) {
254 ((UINT8
*) &WideFill
)[IndexX
] = ((UINT8
*) &WideFill
)[IndexX
% Configure
->BytesPerPixel
];
258 // If all the bytes in the pixel are the same value, then use
259 // a wide fill operation.
262 IndexX
= 1, Uint8
= ((UINT8
*) &WideFill
)[0];
263 IndexX
< Configure
->BytesPerPixel
;
265 if (Uint8
!= ((UINT8
*) &WideFill
)[IndexX
]) {
271 SetMem (&WideFill
, sizeof (WideFill
), Uint8
);
275 if (UseWideFill
&& (DestinationX
== 0) && (Width
== Configure
->PixelsPerScanLine
)) {
276 DEBUG ((EFI_D_VERBOSE
, "VideoFill (wide, one-shot)\n"));
277 Offset
= DestinationY
* Configure
->PixelsPerScanLine
;
278 Offset
= Configure
->BytesPerPixel
* Offset
;
279 Destination
= Configure
->FrameBuffer
+ Offset
;
280 SizeInBytes
= WidthInBytes
* Height
;
281 if (SizeInBytes
>= 8) {
282 SetMem32 (Destination
, SizeInBytes
& ~3, (UINT32
) WideFill
);
283 Destination
+= SizeInBytes
& ~3;
286 if (SizeInBytes
> 0) {
287 SetMem (Destination
, SizeInBytes
, (UINT8
) (UINTN
) WideFill
);
290 LineBufferReady
= FALSE
;
291 for (IndexY
= DestinationY
; IndexY
< (Height
+ DestinationY
); IndexY
++) {
292 Offset
= (IndexY
* Configure
->PixelsPerScanLine
) + DestinationX
;
293 Offset
= Configure
->BytesPerPixel
* Offset
;
294 Destination
= Configure
->FrameBuffer
+ Offset
;
296 if (UseWideFill
&& (((UINTN
) Destination
& 7) == 0)) {
297 DEBUG ((EFI_D_VERBOSE
, "VideoFill (wide)\n"));
298 SizeInBytes
= WidthInBytes
;
299 if (SizeInBytes
>= 8) {
300 SetMem64 (Destination
, SizeInBytes
& ~7, WideFill
);
301 Destination
+= SizeInBytes
& ~7;
304 if (SizeInBytes
> 0) {
305 CopyMem (Destination
, &WideFill
, SizeInBytes
);
308 DEBUG ((EFI_D_VERBOSE
, "VideoFill (not wide)\n"));
309 if (!LineBufferReady
) {
310 CopyMem (Configure
->LineBuffer
, &WideFill
, Configure
->BytesPerPixel
);
311 for (IndexX
= 1; IndexX
< Width
; ) {
313 (Configure
->LineBuffer
+ (IndexX
* Configure
->BytesPerPixel
)),
314 Configure
->LineBuffer
,
315 MIN (IndexX
, Width
- IndexX
) * Configure
->BytesPerPixel
317 IndexX
+= MIN (IndexX
, Width
- IndexX
);
319 LineBufferReady
= TRUE
;
321 CopyMem (Destination
, Configure
->LineBuffer
, WidthInBytes
);
326 return RETURN_SUCCESS
;
330 Performs a UEFI Graphics Output Protocol Blt Video to Buffer operation
331 with extended parameters.
333 @param[in] Configure Pointer to a configuration which was successfully
334 created by FrameBufferBltConfigure ().
335 @param[out] BltBuffer Output buffer for pixel color data.
336 @param[in] SourceX X location within video.
337 @param[in] SourceY Y location within video.
338 @param[in] DestinationX X location within BltBuffer.
339 @param[in] DestinationY Y location within BltBuffer.
340 @param[in] Width Width (in pixels).
341 @param[in] Height Height.
342 @param[in] Delta Number of bytes in a row of BltBuffer.
344 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
345 @retval RETURN_SUCCESS The Blt operation was performed successfully.
348 FrameBufferBltLibVideoToBltBuffer (
349 IN FRAME_BUFFER_CONFIGURE
*Configure
,
350 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
,
353 IN UINTN DestinationX
,
354 IN UINTN DestinationY
,
362 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
371 // Video to BltBuffer: Source is Video, destination is BltBuffer
373 if (SourceY
+ Height
> Configure
->Height
) {
374 return RETURN_INVALID_PARAMETER
;
377 if (SourceX
+ Width
> Configure
->Width
) {
378 return RETURN_INVALID_PARAMETER
;
381 if (Width
== 0 || Height
== 0) {
382 return RETURN_INVALID_PARAMETER
;
386 // If Delta is zero, then the entire BltBuffer is being used, so Delta is
387 // the number of bytes in each row of BltBuffer. Since BltBuffer is Width
388 // pixels size, the number of bytes in each row can be computed.
391 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
394 WidthInBytes
= Width
* Configure
->BytesPerPixel
;
397 // Video to BltBuffer: Source is Video, destination is BltBuffer
399 for (SrcY
= SourceY
, DstY
= DestinationY
;
400 DstY
< (Height
+ DestinationY
);
403 Offset
= (SrcY
* Configure
->PixelsPerScanLine
) + SourceX
;
404 Offset
= Configure
->BytesPerPixel
* Offset
;
405 Source
= Configure
->FrameBuffer
+ Offset
;
407 if (Configure
->PixelFormat
== PixelBlueGreenRedReserved8BitPerColor
) {
408 Destination
= (UINT8
*) BltBuffer
+ (DstY
* Delta
) + (DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
410 Destination
= Configure
->LineBuffer
;
413 CopyMem (Destination
, Source
, WidthInBytes
);
415 if (Configure
->PixelFormat
!= PixelBlueGreenRedReserved8BitPerColor
) {
416 for (IndexX
= 0; IndexX
< Width
; IndexX
++) {
417 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*)
418 ((UINT8
*) BltBuffer
+ (DstY
* Delta
) +
419 (DestinationX
+ IndexX
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
420 Uint32
= *(UINT32
*) (Configure
->LineBuffer
+ (IndexX
* Configure
->BytesPerPixel
));
423 (((Uint32
& Configure
->PixelMasks
.RedMask
) >>
424 Configure
->PixelShl
[0]) << Configure
->PixelShr
[0]) |
425 (((Uint32
& Configure
->PixelMasks
.GreenMask
) >>
426 Configure
->PixelShl
[1]) << Configure
->PixelShr
[1]) |
427 (((Uint32
& Configure
->PixelMasks
.BlueMask
) >>
428 Configure
->PixelShl
[2]) << Configure
->PixelShr
[2])
434 return RETURN_SUCCESS
;
438 Performs a UEFI Graphics Output Protocol Blt Buffer to Video operation
439 with extended parameters.
441 @param[in] Configure Pointer to a configuration which was successfully
442 created by FrameBufferBltConfigure ().
443 @param[in] BltBuffer Output buffer for pixel color data.
444 @param[in] SourceX X location within BltBuffer.
445 @param[in] SourceY Y location within BltBuffer.
446 @param[in] DestinationX X location within video.
447 @param[in] DestinationY Y location within video.
448 @param[in] Width Width (in pixels).
449 @param[in] Height Height.
450 @param[in] Delta Number of bytes in a row of BltBuffer.
452 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
453 @retval RETURN_SUCCESS The Blt operation was performed successfully.
456 FrameBufferBltLibBufferToVideo (
457 IN FRAME_BUFFER_CONFIGURE
*Configure
,
458 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
,
461 IN UINTN DestinationX
,
462 IN UINTN DestinationY
,
470 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
479 // BltBuffer to Video: Source is BltBuffer, destination is Video
481 if (DestinationY
+ Height
> Configure
->Height
) {
482 return RETURN_INVALID_PARAMETER
;
485 if (DestinationX
+ Width
> Configure
->Width
) {
486 return RETURN_INVALID_PARAMETER
;
489 if (Width
== 0 || Height
== 0) {
490 return RETURN_INVALID_PARAMETER
;
494 // If Delta is zero, then the entire BltBuffer is being used, so Delta is
495 // the number of bytes in each row of BltBuffer. Since BltBuffer is Width
496 // pixels size, the number of bytes in each row can be computed.
499 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
502 WidthInBytes
= Width
* Configure
->BytesPerPixel
;
504 for (SrcY
= SourceY
, DstY
= DestinationY
;
505 SrcY
< (Height
+ SourceY
);
508 Offset
= (DstY
* Configure
->PixelsPerScanLine
) + DestinationX
;
509 Offset
= Configure
->BytesPerPixel
* Offset
;
510 Destination
= Configure
->FrameBuffer
+ Offset
;
512 if (Configure
->PixelFormat
== PixelBlueGreenRedReserved8BitPerColor
) {
513 Source
= (UINT8
*) BltBuffer
+ (SrcY
* Delta
);
515 for (IndexX
= 0; IndexX
< Width
; IndexX
++) {
517 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (
518 (UINT8
*) BltBuffer
+
520 ((SourceX
+ IndexX
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
))
522 Uint32
= *(UINT32
*) Blt
;
523 *(UINT32
*) (Configure
->LineBuffer
+ (IndexX
* Configure
->BytesPerPixel
)) =
525 (((Uint32
<< Configure
->PixelShl
[0]) >> Configure
->PixelShr
[0]) &
526 Configure
->PixelMasks
.RedMask
) |
527 (((Uint32
<< Configure
->PixelShl
[1]) >> Configure
->PixelShr
[1]) &
528 Configure
->PixelMasks
.GreenMask
) |
529 (((Uint32
<< Configure
->PixelShl
[2]) >> Configure
->PixelShr
[2]) &
530 Configure
->PixelMasks
.BlueMask
)
533 Source
= Configure
->LineBuffer
;
536 CopyMem (Destination
, Source
, WidthInBytes
);
539 return RETURN_SUCCESS
;
543 Performs a UEFI Graphics Output Protocol Blt Video to Video operation
545 @param[in] Configure Pointer to a configuration which was successfully
546 created by FrameBufferBltConfigure ().
547 @param[in] SourceX X location within video.
548 @param[in] SourceY Y location within video.
549 @param[in] DestinationX X location within video.
550 @param[in] DestinationY Y location within video.
551 @param[in] Width Width (in pixels).
552 @param[in] Height Height.
554 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
555 @retval RETURN_SUCCESS The Blt operation was performed successfully.
558 FrameBufferBltLibVideoToVideo (
559 IN FRAME_BUFFER_CONFIGURE
*Configure
,
562 IN UINTN DestinationX
,
563 IN UINTN DestinationY
,
575 // Video to Video: Source is Video, destination is Video
577 if (SourceY
+ Height
> Configure
->Height
) {
578 return RETURN_INVALID_PARAMETER
;
581 if (SourceX
+ Width
> Configure
->Width
) {
582 return RETURN_INVALID_PARAMETER
;
585 if (DestinationY
+ Height
> Configure
->Height
) {
586 return RETURN_INVALID_PARAMETER
;
589 if (DestinationX
+ Width
> Configure
->Width
) {
590 return RETURN_INVALID_PARAMETER
;
593 if (Width
== 0 || Height
== 0) {
594 return RETURN_INVALID_PARAMETER
;
597 WidthInBytes
= Width
* Configure
->BytesPerPixel
;
599 Offset
= (SourceY
* Configure
->PixelsPerScanLine
) + SourceX
;
600 Offset
= Configure
->BytesPerPixel
* Offset
;
601 Source
= Configure
->FrameBuffer
+ Offset
;
603 Offset
= (DestinationY
* Configure
->PixelsPerScanLine
) + DestinationX
;
604 Offset
= Configure
->BytesPerPixel
* Offset
;
605 Destination
= Configure
->FrameBuffer
+ Offset
;
607 LineStride
= Configure
->BytesPerPixel
* Configure
->PixelsPerScanLine
;
608 if (Destination
> Source
) {
610 // Copy from last line to avoid source is corrupted by copying
612 Source
+= Height
* LineStride
;
613 Destination
+= Height
* LineStride
;
614 LineStride
= -LineStride
;
617 while (Height
-- > 0) {
618 CopyMem (Destination
, Source
, WidthInBytes
);
620 Source
+= LineStride
;
621 Destination
+= LineStride
;
624 return RETURN_SUCCESS
;
628 Performs a UEFI Graphics Output Protocol Blt operation.
630 @param[in] Configure Pointer to a configuration which was successfully
631 created by FrameBufferBltConfigure ().
632 @param[in,out] BltBuffer The data to transfer to screen.
633 @param[in] BltOperation The operation to perform.
634 @param[in] SourceX The X coordinate of the source for BltOperation.
635 @param[in] SourceY The Y coordinate of the source for BltOperation.
636 @param[in] DestinationX The X coordinate of the destination for
638 @param[in] DestinationY The Y coordinate of the destination for
640 @param[in] Width The width of a rectangle in the blt rectangle
642 @param[in] Height The height of a rectangle in the blt rectangle
644 @param[in] Delta Not used for EfiBltVideoFill and
645 EfiBltVideoToVideo operation. If a Delta of 0
646 is used, the entire BltBuffer will be operated
647 on. If a subrectangle of the BltBuffer is
648 used, then Delta represents the number of
649 bytes in a row of the BltBuffer.
651 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
652 @retval RETURN_SUCCESS The Blt operation was performed successfully.
657 IN FRAME_BUFFER_CONFIGURE
*Configure
,
658 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
659 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
662 IN UINTN DestinationX
,
663 IN UINTN DestinationY
,
669 if (Configure
== NULL
) {
670 return RETURN_INVALID_PARAMETER
;
673 switch (BltOperation
) {
674 case EfiBltVideoToBltBuffer
:
675 return FrameBufferBltLibVideoToBltBuffer (
687 case EfiBltVideoToVideo
:
688 return FrameBufferBltLibVideoToVideo (
698 case EfiBltVideoFill
:
699 return FrameBufferBltLibVideoFill (
708 case EfiBltBufferToVideo
:
709 return FrameBufferBltLibBufferToVideo (
722 return RETURN_INVALID_PARAMETER
;