2 FrameBufferBltLib - Library to perform blt operations on a frame buffer.
4 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include <Uefi/UefiBaseType.h>
10 #include <Protocol/GraphicsOutput.h>
12 #include <Library/BaseLib.h>
13 #include <Library/BaseMemoryLib.h>
14 #include <Library/DebugLib.h>
15 #include <Library/FrameBufferBltLib.h>
17 struct FRAME_BUFFER_CONFIGURE
{
18 UINT32 PixelsPerScanLine
;
23 EFI_GRAPHICS_PIXEL_FORMAT PixelFormat
;
24 EFI_PIXEL_BITMASK PixelMasks
;
25 INT8 PixelShl
[4]; // R-G-B-Rsvd
26 INT8 PixelShr
[4]; // R-G-B-Rsvd
30 CONST EFI_PIXEL_BITMASK mRgbPixelMasks
= {
31 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
34 CONST EFI_PIXEL_BITMASK mBgrPixelMasks
= {
35 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000
39 Initialize the bit mask in frame buffer configure.
41 @param BitMask The bit mask of pixel.
42 @param BytesPerPixel Size in bytes of pixel.
43 @param PixelShl Left shift array.
44 @param PixelShr Right shift array.
47 FrameBufferBltLibConfigurePixelFormat (
48 IN CONST EFI_PIXEL_BITMASK
*BitMask
,
49 OUT UINT32
*BytesPerPixel
,
58 ASSERT (BytesPerPixel
!= NULL
);
61 Masks
= (UINT32
*)BitMask
;
62 for (Index
= 0; Index
< 3; Index
++) {
63 ASSERT ((MergedMasks
& Masks
[Index
]) == 0);
65 PixelShl
[Index
] = (INT8
)HighBitSet32 (Masks
[Index
]) - 23 + (Index
* 8);
66 if (PixelShl
[Index
] < 0) {
67 PixelShr
[Index
] = -PixelShl
[Index
];
75 "%d: shl:%d shr:%d mask:%x\n",
82 MergedMasks
= (UINT32
)(MergedMasks
| Masks
[Index
]);
85 MergedMasks
= (UINT32
)(MergedMasks
| Masks
[3]);
87 ASSERT (MergedMasks
!= 0);
88 *BytesPerPixel
= (UINT32
)((HighBitSet32 (MergedMasks
) + 7) / 8);
89 DEBUG ((DEBUG_INFO
, "Bytes per pixel: %d\n", *BytesPerPixel
));
93 Create the configuration for a video frame buffer.
95 The configuration is returned in the caller provided buffer.
97 @param[in] FrameBuffer Pointer to the start of the frame buffer.
98 @param[in] FrameBufferInfo Describes the frame buffer characteristics.
99 @param[in,out] Configure The created configuration information.
100 @param[in,out] ConfigureSize Size of the configuration information.
102 @retval RETURN_SUCCESS The configuration was successful created.
103 @retval RETURN_BUFFER_TOO_SMALL The Configure is to too small. The required
104 size is returned in ConfigureSize.
105 @retval RETURN_UNSUPPORTED The requested mode is not supported by
111 FrameBufferBltConfigure (
112 IN VOID
*FrameBuffer
,
113 IN EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*FrameBufferInfo
,
114 IN OUT FRAME_BUFFER_CONFIGURE
*Configure
,
115 IN OUT UINTN
*ConfigureSize
118 CONST EFI_PIXEL_BITMASK
*BitMask
;
119 UINT32 BytesPerPixel
;
123 if (ConfigureSize
== NULL
) {
124 return RETURN_INVALID_PARAMETER
;
127 switch (FrameBufferInfo
->PixelFormat
) {
128 case PixelRedGreenBlueReserved8BitPerColor
:
129 BitMask
= &mRgbPixelMasks
;
132 case PixelBlueGreenRedReserved8BitPerColor
:
133 BitMask
= &mBgrPixelMasks
;
137 BitMask
= &FrameBufferInfo
->PixelInformation
;
141 ASSERT (FrameBufferInfo
->PixelFormat
!= PixelBltOnly
);
142 return RETURN_UNSUPPORTED
;
146 return RETURN_INVALID_PARAMETER
;
149 if (FrameBufferInfo
->PixelsPerScanLine
< FrameBufferInfo
->HorizontalResolution
) {
150 return RETURN_UNSUPPORTED
;
153 FrameBufferBltLibConfigurePixelFormat (BitMask
, &BytesPerPixel
, PixelShl
, PixelShr
);
155 if (*ConfigureSize
< sizeof (FRAME_BUFFER_CONFIGURE
)
156 + FrameBufferInfo
->HorizontalResolution
* BytesPerPixel
)
158 *ConfigureSize
= sizeof (FRAME_BUFFER_CONFIGURE
)
159 + FrameBufferInfo
->HorizontalResolution
* BytesPerPixel
;
160 return RETURN_BUFFER_TOO_SMALL
;
163 if (Configure
== NULL
) {
164 return RETURN_INVALID_PARAMETER
;
167 CopyMem (&Configure
->PixelMasks
, BitMask
, sizeof (*BitMask
));
168 CopyMem (Configure
->PixelShl
, PixelShl
, sizeof (PixelShl
));
169 CopyMem (Configure
->PixelShr
, PixelShr
, sizeof (PixelShr
));
170 Configure
->BytesPerPixel
= BytesPerPixel
;
171 Configure
->PixelFormat
= FrameBufferInfo
->PixelFormat
;
172 Configure
->FrameBuffer
= (UINT8
*)FrameBuffer
;
173 Configure
->Width
= FrameBufferInfo
->HorizontalResolution
;
174 Configure
->Height
= FrameBufferInfo
->VerticalResolution
;
175 Configure
->PixelsPerScanLine
= FrameBufferInfo
->PixelsPerScanLine
;
177 return RETURN_SUCCESS
;
181 Performs a UEFI Graphics Output Protocol Blt Video Fill.
183 @param[in] Configure Pointer to a configuration which was successfully
184 created by FrameBufferBltConfigure ().
185 @param[in] Color Color to fill the region with.
186 @param[in] DestinationX X location to start fill operation.
187 @param[in] DestinationY Y location to start fill operation.
188 @param[in] Width Width (in pixels) to fill.
189 @param[in] Height Height to fill.
191 @retval RETURN_INVALID_PARAMETER Invalid parameter was passed in.
192 @retval RETURN_SUCCESS The video was filled successfully.
196 FrameBufferBltLibVideoFill (
197 IN FRAME_BUFFER_CONFIGURE
*Configure
,
198 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Color
,
199 IN UINTN DestinationX
,
200 IN UINTN DestinationY
,
212 BOOLEAN LineBufferReady
;
218 // BltBuffer to Video: Source is BltBuffer, destination is Video
220 if (DestinationY
+ Height
> Configure
->Height
) {
221 DEBUG ((DEBUG_VERBOSE
, "VideoFill: Past screen (Y)\n"));
222 return RETURN_INVALID_PARAMETER
;
225 if (DestinationX
+ Width
> Configure
->Width
) {
226 DEBUG ((DEBUG_VERBOSE
, "VideoFill: Past screen (X)\n"));
227 return RETURN_INVALID_PARAMETER
;
230 if ((Width
== 0) || (Height
== 0)) {
231 DEBUG ((DEBUG_VERBOSE
, "VideoFill: Width or Height is 0\n"));
232 return RETURN_INVALID_PARAMETER
;
235 WidthInBytes
= Width
* Configure
->BytesPerPixel
;
237 Uint32
= *(UINT32
*)Color
;
240 (((Uint32
<< Configure
->PixelShl
[0]) >> Configure
->PixelShr
[0]) &
241 Configure
->PixelMasks
.RedMask
) |
242 (((Uint32
<< Configure
->PixelShl
[1]) >> Configure
->PixelShr
[1]) &
243 Configure
->PixelMasks
.GreenMask
) |
244 (((Uint32
<< Configure
->PixelShl
[2]) >> Configure
->PixelShr
[2]) &
245 Configure
->PixelMasks
.BlueMask
)
249 "VideoFill: color=0x%x, wide-fill=0x%x\n",
255 // If the size of the pixel data evenly divides the sizeof
256 // WideFill, then a wide fill operation can be used
259 if ((sizeof (WideFill
) % Configure
->BytesPerPixel
) == 0) {
260 for (IndexX
= Configure
->BytesPerPixel
; IndexX
< sizeof (WideFill
); IndexX
++) {
261 ((UINT8
*)&WideFill
)[IndexX
] = ((UINT8
*)&WideFill
)[IndexX
% Configure
->BytesPerPixel
];
265 // If all the bytes in the pixel are the same value, then use
266 // a wide fill operation.
269 IndexX
= 1, Uint8
= ((UINT8
*)&WideFill
)[0];
270 IndexX
< Configure
->BytesPerPixel
;
273 if (Uint8
!= ((UINT8
*)&WideFill
)[IndexX
]) {
280 SetMem (&WideFill
, sizeof (WideFill
), Uint8
);
284 if (UseWideFill
&& (DestinationX
== 0) && (Width
== Configure
->PixelsPerScanLine
)) {
285 DEBUG ((DEBUG_VERBOSE
, "VideoFill (wide, one-shot)\n"));
286 Offset
= DestinationY
* Configure
->PixelsPerScanLine
;
287 Offset
= Configure
->BytesPerPixel
* Offset
;
288 Destination
= Configure
->FrameBuffer
+ Offset
;
289 SizeInBytes
= WidthInBytes
* Height
;
290 if (SizeInBytes
>= 8) {
291 SetMem32 (Destination
, SizeInBytes
& ~3, (UINT32
)WideFill
);
292 Destination
+= SizeInBytes
& ~3;
296 if (SizeInBytes
> 0) {
297 SetMem (Destination
, SizeInBytes
, (UINT8
)(UINTN
)WideFill
);
300 LineBufferReady
= FALSE
;
301 for (IndexY
= DestinationY
; IndexY
< (Height
+ DestinationY
); IndexY
++) {
302 Offset
= (IndexY
* Configure
->PixelsPerScanLine
) + DestinationX
;
303 Offset
= Configure
->BytesPerPixel
* Offset
;
304 Destination
= Configure
->FrameBuffer
+ Offset
;
306 if (UseWideFill
&& (((UINTN
)Destination
& 7) == 0)) {
307 DEBUG ((DEBUG_VERBOSE
, "VideoFill (wide)\n"));
308 SizeInBytes
= WidthInBytes
;
309 if (SizeInBytes
>= 8) {
310 SetMem64 (Destination
, SizeInBytes
& ~7, WideFill
);
311 Destination
+= SizeInBytes
& ~7;
315 if (SizeInBytes
> 0) {
316 CopyMem (Destination
, &WideFill
, SizeInBytes
);
319 DEBUG ((DEBUG_VERBOSE
, "VideoFill (not wide)\n"));
320 if (!LineBufferReady
) {
321 CopyMem (Configure
->LineBuffer
, &WideFill
, Configure
->BytesPerPixel
);
322 for (IndexX
= 1; IndexX
< Width
; ) {
324 (Configure
->LineBuffer
+ (IndexX
* Configure
->BytesPerPixel
)),
325 Configure
->LineBuffer
,
326 MIN (IndexX
, Width
- IndexX
) * Configure
->BytesPerPixel
328 IndexX
+= MIN (IndexX
, Width
- IndexX
);
331 LineBufferReady
= TRUE
;
334 CopyMem (Destination
, Configure
->LineBuffer
, WidthInBytes
);
339 return RETURN_SUCCESS
;
343 Performs a UEFI Graphics Output Protocol Blt Video to Buffer operation
344 with extended parameters.
346 @param[in] Configure Pointer to a configuration which was successfully
347 created by FrameBufferBltConfigure ().
348 @param[out] BltBuffer Output buffer for pixel color data.
349 @param[in] SourceX X location within video.
350 @param[in] SourceY Y location within video.
351 @param[in] DestinationX X location within BltBuffer.
352 @param[in] DestinationY Y location within BltBuffer.
353 @param[in] Width Width (in pixels).
354 @param[in] Height Height.
355 @param[in] Delta Number of bytes in a row of BltBuffer.
357 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
358 @retval RETURN_SUCCESS The Blt operation was performed successfully.
361 FrameBufferBltLibVideoToBltBuffer (
362 IN FRAME_BUFFER_CONFIGURE
*Configure
,
363 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
,
366 IN UINTN DestinationX
,
367 IN UINTN DestinationY
,
375 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
384 // Video to BltBuffer: Source is Video, destination is BltBuffer
386 if (SourceY
+ Height
> Configure
->Height
) {
387 return RETURN_INVALID_PARAMETER
;
390 if (SourceX
+ Width
> Configure
->Width
) {
391 return RETURN_INVALID_PARAMETER
;
394 if ((Width
== 0) || (Height
== 0)) {
395 return RETURN_INVALID_PARAMETER
;
399 // If Delta is zero, then the entire BltBuffer is being used, so Delta is
400 // the number of bytes in each row of BltBuffer. Since BltBuffer is Width
401 // pixels size, the number of bytes in each row can be computed.
404 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
407 WidthInBytes
= Width
* Configure
->BytesPerPixel
;
410 // Video to BltBuffer: Source is Video, destination is BltBuffer
412 for (SrcY
= SourceY
, DstY
= DestinationY
;
413 DstY
< (Height
+ DestinationY
);
416 Offset
= (SrcY
* Configure
->PixelsPerScanLine
) + SourceX
;
417 Offset
= Configure
->BytesPerPixel
* Offset
;
418 Source
= Configure
->FrameBuffer
+ Offset
;
420 if (Configure
->PixelFormat
== PixelBlueGreenRedReserved8BitPerColor
) {
421 Destination
= (UINT8
*)BltBuffer
+ (DstY
* Delta
) + (DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
423 Destination
= Configure
->LineBuffer
;
426 CopyMem (Destination
, Source
, WidthInBytes
);
428 if (Configure
->PixelFormat
!= PixelBlueGreenRedReserved8BitPerColor
) {
429 for (IndexX
= 0; IndexX
< Width
; IndexX
++) {
430 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*)
431 ((UINT8
*)BltBuffer
+ (DstY
* Delta
) +
432 (DestinationX
+ IndexX
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
433 Uint32
= *(UINT32
*)(Configure
->LineBuffer
+ (IndexX
* Configure
->BytesPerPixel
));
436 (((Uint32
& Configure
->PixelMasks
.RedMask
) >>
437 Configure
->PixelShl
[0]) << Configure
->PixelShr
[0]) |
438 (((Uint32
& Configure
->PixelMasks
.GreenMask
) >>
439 Configure
->PixelShl
[1]) << Configure
->PixelShr
[1]) |
440 (((Uint32
& Configure
->PixelMasks
.BlueMask
) >>
441 Configure
->PixelShl
[2]) << Configure
->PixelShr
[2])
447 return RETURN_SUCCESS
;
451 Performs a UEFI Graphics Output Protocol Blt Buffer to Video operation
452 with extended parameters.
454 @param[in] Configure Pointer to a configuration which was successfully
455 created by FrameBufferBltConfigure ().
456 @param[in] BltBuffer Output buffer for pixel color data.
457 @param[in] SourceX X location within BltBuffer.
458 @param[in] SourceY Y location within BltBuffer.
459 @param[in] DestinationX X location within video.
460 @param[in] DestinationY Y location within video.
461 @param[in] Width Width (in pixels).
462 @param[in] Height Height.
463 @param[in] Delta Number of bytes in a row of BltBuffer.
465 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
466 @retval RETURN_SUCCESS The Blt operation was performed successfully.
469 FrameBufferBltLibBufferToVideo (
470 IN FRAME_BUFFER_CONFIGURE
*Configure
,
471 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
,
474 IN UINTN DestinationX
,
475 IN UINTN DestinationY
,
483 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
492 // BltBuffer to Video: Source is BltBuffer, destination is Video
494 if (DestinationY
+ Height
> Configure
->Height
) {
495 return RETURN_INVALID_PARAMETER
;
498 if (DestinationX
+ Width
> Configure
->Width
) {
499 return RETURN_INVALID_PARAMETER
;
502 if ((Width
== 0) || (Height
== 0)) {
503 return RETURN_INVALID_PARAMETER
;
507 // If Delta is zero, then the entire BltBuffer is being used, so Delta is
508 // the number of bytes in each row of BltBuffer. Since BltBuffer is Width
509 // pixels size, the number of bytes in each row can be computed.
512 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
515 WidthInBytes
= Width
* Configure
->BytesPerPixel
;
517 for (SrcY
= SourceY
, DstY
= DestinationY
;
518 SrcY
< (Height
+ SourceY
);
521 Offset
= (DstY
* Configure
->PixelsPerScanLine
) + DestinationX
;
522 Offset
= Configure
->BytesPerPixel
* Offset
;
523 Destination
= Configure
->FrameBuffer
+ Offset
;
525 if (Configure
->PixelFormat
== PixelBlueGreenRedReserved8BitPerColor
) {
526 Source
= (UINT8
*)BltBuffer
+ (SrcY
* Delta
) + SourceX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
528 for (IndexX
= 0; IndexX
< Width
; IndexX
++) {
530 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*)(
533 ((SourceX
+ IndexX
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
))
535 Uint32
= *(UINT32
*)Blt
;
536 *(UINT32
*)(Configure
->LineBuffer
+ (IndexX
* Configure
->BytesPerPixel
)) =
538 (((Uint32
<< Configure
->PixelShl
[0]) >> Configure
->PixelShr
[0]) &
539 Configure
->PixelMasks
.RedMask
) |
540 (((Uint32
<< Configure
->PixelShl
[1]) >> Configure
->PixelShr
[1]) &
541 Configure
->PixelMasks
.GreenMask
) |
542 (((Uint32
<< Configure
->PixelShl
[2]) >> Configure
->PixelShr
[2]) &
543 Configure
->PixelMasks
.BlueMask
)
547 Source
= Configure
->LineBuffer
;
550 CopyMem (Destination
, Source
, WidthInBytes
);
553 return RETURN_SUCCESS
;
557 Performs a UEFI Graphics Output Protocol Blt Video to Video operation
559 @param[in] Configure Pointer to a configuration which was successfully
560 created by FrameBufferBltConfigure ().
561 @param[in] SourceX X location within video.
562 @param[in] SourceY Y location within video.
563 @param[in] DestinationX X location within video.
564 @param[in] DestinationY Y location within video.
565 @param[in] Width Width (in pixels).
566 @param[in] Height Height.
568 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
569 @retval RETURN_SUCCESS The Blt operation was performed successfully.
572 FrameBufferBltLibVideoToVideo (
573 IN FRAME_BUFFER_CONFIGURE
*Configure
,
576 IN UINTN DestinationX
,
577 IN UINTN DestinationY
,
589 // Video to Video: Source is Video, destination is Video
591 if (SourceY
+ Height
> Configure
->Height
) {
592 return RETURN_INVALID_PARAMETER
;
595 if (SourceX
+ Width
> Configure
->Width
) {
596 return RETURN_INVALID_PARAMETER
;
599 if (DestinationY
+ Height
> Configure
->Height
) {
600 return RETURN_INVALID_PARAMETER
;
603 if (DestinationX
+ Width
> Configure
->Width
) {
604 return RETURN_INVALID_PARAMETER
;
607 if ((Width
== 0) || (Height
== 0)) {
608 return RETURN_INVALID_PARAMETER
;
611 WidthInBytes
= Width
* Configure
->BytesPerPixel
;
613 Offset
= (SourceY
* Configure
->PixelsPerScanLine
) + SourceX
;
614 Offset
= Configure
->BytesPerPixel
* Offset
;
615 Source
= Configure
->FrameBuffer
+ Offset
;
617 Offset
= (DestinationY
* Configure
->PixelsPerScanLine
) + DestinationX
;
618 Offset
= Configure
->BytesPerPixel
* Offset
;
619 Destination
= Configure
->FrameBuffer
+ Offset
;
621 LineStride
= Configure
->BytesPerPixel
* Configure
->PixelsPerScanLine
;
622 if (Destination
> Source
) {
624 // Copy from last line to avoid source is corrupted by copying
626 Source
+= Height
* LineStride
;
627 Destination
+= Height
* LineStride
;
628 LineStride
= -LineStride
;
631 while (Height
-- > 0) {
632 CopyMem (Destination
, Source
, WidthInBytes
);
634 Source
+= LineStride
;
635 Destination
+= LineStride
;
638 return RETURN_SUCCESS
;
642 Performs a UEFI Graphics Output Protocol Blt operation.
644 @param[in] Configure Pointer to a configuration which was successfully
645 created by FrameBufferBltConfigure ().
646 @param[in,out] BltBuffer The data to transfer to screen.
647 @param[in] BltOperation The operation to perform.
648 @param[in] SourceX The X coordinate of the source for BltOperation.
649 @param[in] SourceY The Y coordinate of the source for BltOperation.
650 @param[in] DestinationX The X coordinate of the destination for
652 @param[in] DestinationY The Y coordinate of the destination for
654 @param[in] Width The width of a rectangle in the blt rectangle
656 @param[in] Height The height of a rectangle in the blt rectangle
658 @param[in] Delta Not used for EfiBltVideoFill and
659 EfiBltVideoToVideo operation. If a Delta of 0
660 is used, the entire BltBuffer will be operated
661 on. If a subrectangle of the BltBuffer is
662 used, then Delta represents the number of
663 bytes in a row of the BltBuffer.
665 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
666 @retval RETURN_SUCCESS The Blt operation was performed successfully.
671 IN FRAME_BUFFER_CONFIGURE
*Configure
,
672 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer OPTIONAL
,
673 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
676 IN UINTN DestinationX
,
677 IN UINTN DestinationY
,
683 if (Configure
== NULL
) {
684 return RETURN_INVALID_PARAMETER
;
687 switch (BltOperation
) {
688 case EfiBltVideoToBltBuffer
:
689 return FrameBufferBltLibVideoToBltBuffer (
701 case EfiBltVideoToVideo
:
702 return FrameBufferBltLibVideoToVideo (
712 case EfiBltVideoFill
:
713 return FrameBufferBltLibVideoFill (
722 case EfiBltBufferToVideo
:
723 return FrameBufferBltLibBufferToVideo (
736 return RETURN_INVALID_PARAMETER
;