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
];
72 DEBUG ((DEBUG_INFO
, "%d: shl:%d shr:%d mask:%x\n", Index
,
73 PixelShl
[Index
], PixelShr
[Index
], Masks
[Index
]));
75 MergedMasks
= (UINT32
) (MergedMasks
| Masks
[Index
]);
77 MergedMasks
= (UINT32
) (MergedMasks
| Masks
[3]);
79 ASSERT (MergedMasks
!= 0);
80 *BytesPerPixel
= (UINT32
) ((HighBitSet32 (MergedMasks
) + 7) / 8);
81 DEBUG ((DEBUG_INFO
, "Bytes per pixel: %d\n", *BytesPerPixel
));
85 Create the configuration for a video frame buffer.
87 The configuration is returned in the caller provided buffer.
89 @param[in] FrameBuffer Pointer to the start of the frame buffer.
90 @param[in] FrameBufferInfo Describes the frame buffer characteristics.
91 @param[in,out] Configure The created configuration information.
92 @param[in,out] ConfigureSize Size of the configuration information.
94 @retval RETURN_SUCCESS The configuration was successful created.
95 @retval RETURN_BUFFER_TOO_SMALL The Configure is to too small. The required
96 size is returned in ConfigureSize.
97 @retval RETURN_UNSUPPORTED The requested mode is not supported by
103 FrameBufferBltConfigure (
104 IN VOID
*FrameBuffer
,
105 IN EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*FrameBufferInfo
,
106 IN OUT FRAME_BUFFER_CONFIGURE
*Configure
,
107 IN OUT UINTN
*ConfigureSize
110 CONST EFI_PIXEL_BITMASK
*BitMask
;
111 UINT32 BytesPerPixel
;
115 if (ConfigureSize
== NULL
) {
116 return RETURN_INVALID_PARAMETER
;
119 switch (FrameBufferInfo
->PixelFormat
) {
120 case PixelRedGreenBlueReserved8BitPerColor
:
121 BitMask
= &mRgbPixelMasks
;
124 case PixelBlueGreenRedReserved8BitPerColor
:
125 BitMask
= &mBgrPixelMasks
;
129 BitMask
= &FrameBufferInfo
->PixelInformation
;
133 ASSERT (FrameBufferInfo
->PixelFormat
!= PixelBltOnly
);
134 return RETURN_UNSUPPORTED
;
138 return RETURN_INVALID_PARAMETER
;
141 if (FrameBufferInfo
->PixelsPerScanLine
< FrameBufferInfo
->HorizontalResolution
) {
142 return RETURN_UNSUPPORTED
;
145 FrameBufferBltLibConfigurePixelFormat (BitMask
, &BytesPerPixel
, PixelShl
, PixelShr
);
147 if (*ConfigureSize
< sizeof (FRAME_BUFFER_CONFIGURE
)
148 + FrameBufferInfo
->HorizontalResolution
* BytesPerPixel
) {
149 *ConfigureSize
= sizeof (FRAME_BUFFER_CONFIGURE
)
150 + FrameBufferInfo
->HorizontalResolution
* BytesPerPixel
;
151 return RETURN_BUFFER_TOO_SMALL
;
154 if (Configure
== NULL
) {
155 return RETURN_INVALID_PARAMETER
;
158 CopyMem (&Configure
->PixelMasks
, BitMask
, sizeof (*BitMask
));
159 CopyMem (Configure
->PixelShl
, PixelShl
, sizeof (PixelShl
));
160 CopyMem (Configure
->PixelShr
, PixelShr
, sizeof (PixelShr
));
161 Configure
->BytesPerPixel
= BytesPerPixel
;
162 Configure
->PixelFormat
= FrameBufferInfo
->PixelFormat
;
163 Configure
->FrameBuffer
= (UINT8
*) FrameBuffer
;
164 Configure
->Width
= FrameBufferInfo
->HorizontalResolution
;
165 Configure
->Height
= FrameBufferInfo
->VerticalResolution
;
166 Configure
->PixelsPerScanLine
= FrameBufferInfo
->PixelsPerScanLine
;
168 return RETURN_SUCCESS
;
172 Performs a UEFI Graphics Output Protocol Blt Video Fill.
174 @param[in] Configure Pointer to a configuration which was successfully
175 created by FrameBufferBltConfigure ().
176 @param[in] Color Color to fill the region with.
177 @param[in] DestinationX X location to start fill operation.
178 @param[in] DestinationY Y location to start fill operation.
179 @param[in] Width Width (in pixels) to fill.
180 @param[in] Height Height to fill.
182 @retval RETURN_INVALID_PARAMETER Invalid parameter was passed in.
183 @retval RETURN_SUCCESS The video was filled successfully.
187 FrameBufferBltLibVideoFill (
188 IN FRAME_BUFFER_CONFIGURE
*Configure
,
189 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Color
,
190 IN UINTN DestinationX
,
191 IN UINTN DestinationY
,
203 BOOLEAN LineBufferReady
;
209 // BltBuffer to Video: Source is BltBuffer, destination is Video
211 if (DestinationY
+ Height
> Configure
->Height
) {
212 DEBUG ((EFI_D_VERBOSE
, "VideoFill: Past screen (Y)\n"));
213 return RETURN_INVALID_PARAMETER
;
216 if (DestinationX
+ Width
> Configure
->Width
) {
217 DEBUG ((EFI_D_VERBOSE
, "VideoFill: Past screen (X)\n"));
218 return RETURN_INVALID_PARAMETER
;
221 if (Width
== 0 || Height
== 0) {
222 DEBUG ((EFI_D_VERBOSE
, "VideoFill: Width or Height is 0\n"));
223 return RETURN_INVALID_PARAMETER
;
226 WidthInBytes
= Width
* Configure
->BytesPerPixel
;
228 Uint32
= *(UINT32
*) Color
;
231 (((Uint32
<< Configure
->PixelShl
[0]) >> Configure
->PixelShr
[0]) &
232 Configure
->PixelMasks
.RedMask
) |
233 (((Uint32
<< Configure
->PixelShl
[1]) >> Configure
->PixelShr
[1]) &
234 Configure
->PixelMasks
.GreenMask
) |
235 (((Uint32
<< Configure
->PixelShl
[2]) >> Configure
->PixelShr
[2]) &
236 Configure
->PixelMasks
.BlueMask
)
238 DEBUG ((EFI_D_VERBOSE
, "VideoFill: color=0x%x, wide-fill=0x%x\n",
242 // If the size of the pixel data evenly divides the sizeof
243 // WideFill, then a wide fill operation can be used
246 if ((sizeof (WideFill
) % Configure
->BytesPerPixel
) == 0) {
247 for (IndexX
= Configure
->BytesPerPixel
; IndexX
< sizeof (WideFill
); IndexX
++) {
248 ((UINT8
*) &WideFill
)[IndexX
] = ((UINT8
*) &WideFill
)[IndexX
% Configure
->BytesPerPixel
];
252 // If all the bytes in the pixel are the same value, then use
253 // a wide fill operation.
256 IndexX
= 1, Uint8
= ((UINT8
*) &WideFill
)[0];
257 IndexX
< Configure
->BytesPerPixel
;
259 if (Uint8
!= ((UINT8
*) &WideFill
)[IndexX
]) {
265 SetMem (&WideFill
, sizeof (WideFill
), Uint8
);
269 if (UseWideFill
&& (DestinationX
== 0) && (Width
== Configure
->PixelsPerScanLine
)) {
270 DEBUG ((EFI_D_VERBOSE
, "VideoFill (wide, one-shot)\n"));
271 Offset
= DestinationY
* Configure
->PixelsPerScanLine
;
272 Offset
= Configure
->BytesPerPixel
* Offset
;
273 Destination
= Configure
->FrameBuffer
+ Offset
;
274 SizeInBytes
= WidthInBytes
* Height
;
275 if (SizeInBytes
>= 8) {
276 SetMem32 (Destination
, SizeInBytes
& ~3, (UINT32
) WideFill
);
277 Destination
+= SizeInBytes
& ~3;
280 if (SizeInBytes
> 0) {
281 SetMem (Destination
, SizeInBytes
, (UINT8
) (UINTN
) WideFill
);
284 LineBufferReady
= FALSE
;
285 for (IndexY
= DestinationY
; IndexY
< (Height
+ DestinationY
); IndexY
++) {
286 Offset
= (IndexY
* Configure
->PixelsPerScanLine
) + DestinationX
;
287 Offset
= Configure
->BytesPerPixel
* Offset
;
288 Destination
= Configure
->FrameBuffer
+ Offset
;
290 if (UseWideFill
&& (((UINTN
) Destination
& 7) == 0)) {
291 DEBUG ((EFI_D_VERBOSE
, "VideoFill (wide)\n"));
292 SizeInBytes
= WidthInBytes
;
293 if (SizeInBytes
>= 8) {
294 SetMem64 (Destination
, SizeInBytes
& ~7, WideFill
);
295 Destination
+= SizeInBytes
& ~7;
298 if (SizeInBytes
> 0) {
299 CopyMem (Destination
, &WideFill
, SizeInBytes
);
302 DEBUG ((EFI_D_VERBOSE
, "VideoFill (not wide)\n"));
303 if (!LineBufferReady
) {
304 CopyMem (Configure
->LineBuffer
, &WideFill
, Configure
->BytesPerPixel
);
305 for (IndexX
= 1; IndexX
< Width
; ) {
307 (Configure
->LineBuffer
+ (IndexX
* Configure
->BytesPerPixel
)),
308 Configure
->LineBuffer
,
309 MIN (IndexX
, Width
- IndexX
) * Configure
->BytesPerPixel
311 IndexX
+= MIN (IndexX
, Width
- IndexX
);
313 LineBufferReady
= TRUE
;
315 CopyMem (Destination
, Configure
->LineBuffer
, WidthInBytes
);
320 return RETURN_SUCCESS
;
324 Performs a UEFI Graphics Output Protocol Blt Video to Buffer operation
325 with extended parameters.
327 @param[in] Configure Pointer to a configuration which was successfully
328 created by FrameBufferBltConfigure ().
329 @param[out] BltBuffer Output buffer for pixel color data.
330 @param[in] SourceX X location within video.
331 @param[in] SourceY Y location within video.
332 @param[in] DestinationX X location within BltBuffer.
333 @param[in] DestinationY Y location within BltBuffer.
334 @param[in] Width Width (in pixels).
335 @param[in] Height Height.
336 @param[in] Delta Number of bytes in a row of BltBuffer.
338 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
339 @retval RETURN_SUCCESS The Blt operation was performed successfully.
342 FrameBufferBltLibVideoToBltBuffer (
343 IN FRAME_BUFFER_CONFIGURE
*Configure
,
344 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
,
347 IN UINTN DestinationX
,
348 IN UINTN DestinationY
,
356 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
365 // Video to BltBuffer: Source is Video, destination is BltBuffer
367 if (SourceY
+ Height
> Configure
->Height
) {
368 return RETURN_INVALID_PARAMETER
;
371 if (SourceX
+ Width
> Configure
->Width
) {
372 return RETURN_INVALID_PARAMETER
;
375 if (Width
== 0 || Height
== 0) {
376 return RETURN_INVALID_PARAMETER
;
380 // If Delta is zero, then the entire BltBuffer is being used, so Delta is
381 // the number of bytes in each row of BltBuffer. Since BltBuffer is Width
382 // pixels size, the number of bytes in each row can be computed.
385 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
388 WidthInBytes
= Width
* Configure
->BytesPerPixel
;
391 // Video to BltBuffer: Source is Video, destination is BltBuffer
393 for (SrcY
= SourceY
, DstY
= DestinationY
;
394 DstY
< (Height
+ DestinationY
);
397 Offset
= (SrcY
* Configure
->PixelsPerScanLine
) + SourceX
;
398 Offset
= Configure
->BytesPerPixel
* Offset
;
399 Source
= Configure
->FrameBuffer
+ Offset
;
401 if (Configure
->PixelFormat
== PixelBlueGreenRedReserved8BitPerColor
) {
402 Destination
= (UINT8
*) BltBuffer
+ (DstY
* Delta
) + (DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
404 Destination
= Configure
->LineBuffer
;
407 CopyMem (Destination
, Source
, WidthInBytes
);
409 if (Configure
->PixelFormat
!= PixelBlueGreenRedReserved8BitPerColor
) {
410 for (IndexX
= 0; IndexX
< Width
; IndexX
++) {
411 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*)
412 ((UINT8
*) BltBuffer
+ (DstY
* Delta
) +
413 (DestinationX
+ IndexX
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
414 Uint32
= *(UINT32
*) (Configure
->LineBuffer
+ (IndexX
* Configure
->BytesPerPixel
));
417 (((Uint32
& Configure
->PixelMasks
.RedMask
) >>
418 Configure
->PixelShl
[0]) << Configure
->PixelShr
[0]) |
419 (((Uint32
& Configure
->PixelMasks
.GreenMask
) >>
420 Configure
->PixelShl
[1]) << Configure
->PixelShr
[1]) |
421 (((Uint32
& Configure
->PixelMasks
.BlueMask
) >>
422 Configure
->PixelShl
[2]) << Configure
->PixelShr
[2])
428 return RETURN_SUCCESS
;
432 Performs a UEFI Graphics Output Protocol Blt Buffer to Video operation
433 with extended parameters.
435 @param[in] Configure Pointer to a configuration which was successfully
436 created by FrameBufferBltConfigure ().
437 @param[in] BltBuffer Output buffer for pixel color data.
438 @param[in] SourceX X location within BltBuffer.
439 @param[in] SourceY Y location within BltBuffer.
440 @param[in] DestinationX X location within video.
441 @param[in] DestinationY Y location within video.
442 @param[in] Width Width (in pixels).
443 @param[in] Height Height.
444 @param[in] Delta Number of bytes in a row of BltBuffer.
446 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
447 @retval RETURN_SUCCESS The Blt operation was performed successfully.
450 FrameBufferBltLibBufferToVideo (
451 IN FRAME_BUFFER_CONFIGURE
*Configure
,
452 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
,
455 IN UINTN DestinationX
,
456 IN UINTN DestinationY
,
464 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
473 // BltBuffer to Video: Source is BltBuffer, destination is Video
475 if (DestinationY
+ Height
> Configure
->Height
) {
476 return RETURN_INVALID_PARAMETER
;
479 if (DestinationX
+ Width
> Configure
->Width
) {
480 return RETURN_INVALID_PARAMETER
;
483 if (Width
== 0 || Height
== 0) {
484 return RETURN_INVALID_PARAMETER
;
488 // If Delta is zero, then the entire BltBuffer is being used, so Delta is
489 // the number of bytes in each row of BltBuffer. Since BltBuffer is Width
490 // pixels size, the number of bytes in each row can be computed.
493 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
496 WidthInBytes
= Width
* Configure
->BytesPerPixel
;
498 for (SrcY
= SourceY
, DstY
= DestinationY
;
499 SrcY
< (Height
+ SourceY
);
502 Offset
= (DstY
* Configure
->PixelsPerScanLine
) + DestinationX
;
503 Offset
= Configure
->BytesPerPixel
* Offset
;
504 Destination
= Configure
->FrameBuffer
+ Offset
;
506 if (Configure
->PixelFormat
== PixelBlueGreenRedReserved8BitPerColor
) {
507 Source
= (UINT8
*) BltBuffer
+ (SrcY
* Delta
);
509 for (IndexX
= 0; IndexX
< Width
; IndexX
++) {
511 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (
512 (UINT8
*) BltBuffer
+
514 ((SourceX
+ IndexX
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
))
516 Uint32
= *(UINT32
*) Blt
;
517 *(UINT32
*) (Configure
->LineBuffer
+ (IndexX
* Configure
->BytesPerPixel
)) =
519 (((Uint32
<< Configure
->PixelShl
[0]) >> Configure
->PixelShr
[0]) &
520 Configure
->PixelMasks
.RedMask
) |
521 (((Uint32
<< Configure
->PixelShl
[1]) >> Configure
->PixelShr
[1]) &
522 Configure
->PixelMasks
.GreenMask
) |
523 (((Uint32
<< Configure
->PixelShl
[2]) >> Configure
->PixelShr
[2]) &
524 Configure
->PixelMasks
.BlueMask
)
527 Source
= Configure
->LineBuffer
;
530 CopyMem (Destination
, Source
, WidthInBytes
);
533 return RETURN_SUCCESS
;
537 Performs a UEFI Graphics Output Protocol Blt Video to Video operation
539 @param[in] Configure Pointer to a configuration which was successfully
540 created by FrameBufferBltConfigure ().
541 @param[in] SourceX X location within video.
542 @param[in] SourceY Y location within video.
543 @param[in] DestinationX X location within video.
544 @param[in] DestinationY Y location within video.
545 @param[in] Width Width (in pixels).
546 @param[in] Height Height.
548 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
549 @retval RETURN_SUCCESS The Blt operation was performed successfully.
552 FrameBufferBltLibVideoToVideo (
553 IN FRAME_BUFFER_CONFIGURE
*Configure
,
556 IN UINTN DestinationX
,
557 IN UINTN DestinationY
,
569 // Video to Video: Source is Video, destination is Video
571 if (SourceY
+ Height
> Configure
->Height
) {
572 return RETURN_INVALID_PARAMETER
;
575 if (SourceX
+ Width
> Configure
->Width
) {
576 return RETURN_INVALID_PARAMETER
;
579 if (DestinationY
+ Height
> Configure
->Height
) {
580 return RETURN_INVALID_PARAMETER
;
583 if (DestinationX
+ Width
> Configure
->Width
) {
584 return RETURN_INVALID_PARAMETER
;
587 if (Width
== 0 || Height
== 0) {
588 return RETURN_INVALID_PARAMETER
;
591 WidthInBytes
= Width
* Configure
->BytesPerPixel
;
593 Offset
= (SourceY
* Configure
->PixelsPerScanLine
) + SourceX
;
594 Offset
= Configure
->BytesPerPixel
* Offset
;
595 Source
= Configure
->FrameBuffer
+ Offset
;
597 Offset
= (DestinationY
* Configure
->PixelsPerScanLine
) + DestinationX
;
598 Offset
= Configure
->BytesPerPixel
* Offset
;
599 Destination
= Configure
->FrameBuffer
+ Offset
;
601 LineStride
= Configure
->BytesPerPixel
* Configure
->PixelsPerScanLine
;
602 if (Destination
> Source
) {
604 // Copy from last line to avoid source is corrupted by copying
606 Source
+= Height
* LineStride
;
607 Destination
+= Height
* LineStride
;
608 LineStride
= -LineStride
;
611 while (Height
-- > 0) {
612 CopyMem (Destination
, Source
, WidthInBytes
);
614 Source
+= LineStride
;
615 Destination
+= LineStride
;
618 return RETURN_SUCCESS
;
622 Performs a UEFI Graphics Output Protocol Blt operation.
624 @param[in] Configure Pointer to a configuration which was successfully
625 created by FrameBufferBltConfigure ().
626 @param[in,out] BltBuffer The data to transfer to screen.
627 @param[in] BltOperation The operation to perform.
628 @param[in] SourceX The X coordinate of the source for BltOperation.
629 @param[in] SourceY The Y coordinate of the source for BltOperation.
630 @param[in] DestinationX The X coordinate of the destination for
632 @param[in] DestinationY The Y coordinate of the destination for
634 @param[in] Width The width of a rectangle in the blt rectangle
636 @param[in] Height The height of a rectangle in the blt rectangle
638 @param[in] Delta Not used for EfiBltVideoFill and
639 EfiBltVideoToVideo operation. If a Delta of 0
640 is used, the entire BltBuffer will be operated
641 on. If a subrectangle of the BltBuffer is
642 used, then Delta represents the number of
643 bytes in a row of the BltBuffer.
645 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
646 @retval RETURN_SUCCESS The Blt operation was performed successfully.
651 IN FRAME_BUFFER_CONFIGURE
*Configure
,
652 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
653 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
656 IN UINTN DestinationX
,
657 IN UINTN DestinationY
,
663 if (Configure
== NULL
) {
664 return RETURN_INVALID_PARAMETER
;
667 switch (BltOperation
) {
668 case EfiBltVideoToBltBuffer
:
669 return FrameBufferBltLibVideoToBltBuffer (
681 case EfiBltVideoToVideo
:
682 return FrameBufferBltLibVideoToVideo (
692 case EfiBltVideoFill
:
693 return FrameBufferBltLibVideoFill (
702 case EfiBltBufferToVideo
:
703 return FrameBufferBltLibBufferToVideo (
716 return RETURN_INVALID_PARAMETER
;