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
{
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 FrameBufferBltLibConfigurePixelFormat (BitMask
, &BytesPerPixel
, PixelShl
, PixelShr
);
149 if (*ConfigureSize
< sizeof (FRAME_BUFFER_CONFIGURE
)
150 + FrameBufferInfo
->HorizontalResolution
* BytesPerPixel
) {
151 *ConfigureSize
= sizeof (FRAME_BUFFER_CONFIGURE
)
152 + FrameBufferInfo
->HorizontalResolution
* BytesPerPixel
;
153 return RETURN_BUFFER_TOO_SMALL
;
156 if (Configure
== NULL
) {
157 return RETURN_INVALID_PARAMETER
;
160 CopyMem (&Configure
->PixelMasks
, BitMask
, sizeof (*BitMask
));
161 CopyMem (Configure
->PixelShl
, PixelShl
, sizeof (PixelShl
));
162 CopyMem (Configure
->PixelShr
, PixelShr
, sizeof (PixelShr
));
163 Configure
->BytesPerPixel
= BytesPerPixel
;
164 Configure
->PixelFormat
= FrameBufferInfo
->PixelFormat
;
165 Configure
->FrameBuffer
= (UINT8
*) FrameBuffer
;
166 Configure
->WidthInPixels
= FrameBufferInfo
->HorizontalResolution
;
167 Configure
->Height
= FrameBufferInfo
->VerticalResolution
;
168 Configure
->WidthInBytes
= Configure
->WidthInPixels
* Configure
->BytesPerPixel
;
170 return RETURN_SUCCESS
;
174 Performs a UEFI Graphics Output Protocol Blt Video Fill.
176 @param[in] Configure Pointer to a configuration which was successfully
177 created by FrameBufferBltConfigure ().
178 @param[in] Color Color to fill the region with.
179 @param[in] DestinationX X location to start fill operation.
180 @param[in] DestinationY Y location to start fill operation.
181 @param[in] Width Width (in pixels) to fill.
182 @param[in] Height Height to fill.
184 @retval RETURN_INVALID_PARAMETER Invalid parameter was passed in.
185 @retval RETURN_SUCCESS The video was filled successfully.
189 FrameBufferBltLibVideoFill (
190 IN FRAME_BUFFER_CONFIGURE
*Configure
,
191 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Color
,
192 IN UINTN DestinationX
,
193 IN UINTN DestinationY
,
205 BOOLEAN LineBufferReady
;
211 // BltBuffer to Video: Source is BltBuffer, destination is Video
213 if (DestinationY
+ Height
> Configure
->Height
) {
214 DEBUG ((EFI_D_VERBOSE
, "VideoFill: Past screen (Y)\n"));
215 return RETURN_INVALID_PARAMETER
;
218 if (DestinationX
+ Width
> Configure
->WidthInPixels
) {
219 DEBUG ((EFI_D_VERBOSE
, "VideoFill: Past screen (X)\n"));
220 return RETURN_INVALID_PARAMETER
;
223 if (Width
== 0 || Height
== 0) {
224 DEBUG ((EFI_D_VERBOSE
, "VideoFill: Width or Height is 0\n"));
225 return RETURN_INVALID_PARAMETER
;
228 WidthInBytes
= Width
* Configure
->BytesPerPixel
;
230 Uint32
= *(UINT32
*) Color
;
233 (((Uint32
<< Configure
->PixelShl
[0]) >> Configure
->PixelShr
[0]) &
234 Configure
->PixelMasks
.RedMask
) |
235 (((Uint32
<< Configure
->PixelShl
[1]) >> Configure
->PixelShr
[1]) &
236 Configure
->PixelMasks
.GreenMask
) |
237 (((Uint32
<< Configure
->PixelShl
[2]) >> Configure
->PixelShr
[2]) &
238 Configure
->PixelMasks
.BlueMask
)
240 DEBUG ((EFI_D_VERBOSE
, "VideoFill: color=0x%x, wide-fill=0x%x\n",
244 // If the size of the pixel data evenly divides the sizeof
245 // WideFill, then a wide fill operation can be used
248 if ((sizeof (WideFill
) % Configure
->BytesPerPixel
) == 0) {
249 for (IndexX
= Configure
->BytesPerPixel
; IndexX
< sizeof (WideFill
); IndexX
++) {
250 ((UINT8
*) &WideFill
)[IndexX
] = ((UINT8
*) &WideFill
)[IndexX
% Configure
->BytesPerPixel
];
254 // If all the bytes in the pixel are the same value, then use
255 // a wide fill operation.
258 IndexX
= 1, Uint8
= ((UINT8
*) &WideFill
)[0];
259 IndexX
< Configure
->BytesPerPixel
;
261 if (Uint8
!= ((UINT8
*) &WideFill
)[IndexX
]) {
267 SetMem (&WideFill
, sizeof (WideFill
), Uint8
);
271 if (UseWideFill
&& (DestinationX
== 0) && (Width
== Configure
->WidthInPixels
)) {
272 DEBUG ((EFI_D_VERBOSE
, "VideoFill (wide, one-shot)\n"));
273 Offset
= DestinationY
* Configure
->WidthInPixels
;
274 Offset
= Configure
->BytesPerPixel
* Offset
;
275 Destination
= Configure
->FrameBuffer
+ Offset
;
276 SizeInBytes
= WidthInBytes
* Height
;
277 if (SizeInBytes
>= 8) {
278 SetMem32 (Destination
, SizeInBytes
& ~3, (UINT32
) WideFill
);
281 if (SizeInBytes
> 0) {
282 SetMem (Destination
, SizeInBytes
, (UINT8
) (UINTN
) WideFill
);
285 LineBufferReady
= FALSE
;
286 for (IndexY
= DestinationY
; IndexY
< (Height
+ DestinationY
); IndexY
++) {
287 Offset
= (IndexY
* Configure
->WidthInPixels
) + DestinationX
;
288 Offset
= Configure
->BytesPerPixel
* Offset
;
289 Destination
= Configure
->FrameBuffer
+ Offset
;
291 if (UseWideFill
&& (((UINTN
) Destination
& 7) == 0)) {
292 DEBUG ((EFI_D_VERBOSE
, "VideoFill (wide)\n"));
293 SizeInBytes
= WidthInBytes
;
294 if (SizeInBytes
>= 8) {
295 SetMem64 (Destination
, SizeInBytes
& ~7, WideFill
);
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
->WidthInPixels
) {
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
->WidthInPixels
) + 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
->WidthInPixels
) {
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
->WidthInPixels
) + 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
->WidthInPixels
) {
576 return RETURN_INVALID_PARAMETER
;
579 if (DestinationY
+ Height
> Configure
->Height
) {
580 return RETURN_INVALID_PARAMETER
;
583 if (DestinationX
+ Width
> Configure
->WidthInPixels
) {
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
->WidthInPixels
) + SourceX
;
594 Offset
= Configure
->BytesPerPixel
* Offset
;
595 Source
= Configure
->FrameBuffer
+ Offset
;
597 Offset
= (DestinationY
* Configure
->WidthInPixels
) + DestinationX
;
598 Offset
= Configure
->BytesPerPixel
* Offset
;
599 Destination
= Configure
->FrameBuffer
+ Offset
;
601 LineStride
= Configure
->WidthInBytes
;
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
;