2 FrameBufferBltLib - Library to perform blt operations on a frame buffer.
4 Copyright (c) 2007 - 2017, 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
{
30 EFI_GRAPHICS_PIXEL_FORMAT PixelFormat
;
31 EFI_PIXEL_BITMASK PixelMasks
;
32 INT8 PixelShl
[4]; // R-G-B-Rsvd
33 INT8 PixelShr
[4]; // R-G-B-Rsvd
37 CONST EFI_PIXEL_BITMASK mRgbPixelMasks
= {
38 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
41 CONST EFI_PIXEL_BITMASK mBgrPixelMasks
= {
42 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000
46 Initialize the bit mask in frame buffer configure.
48 @param BitMask The bit mask of pixel.
49 @param BytesPerPixel Size in bytes of pixel.
50 @param PixelShl Left shift array.
51 @param PixelShr Right shift array.
54 FrameBufferBltLibConfigurePixelFormat (
55 IN CONST EFI_PIXEL_BITMASK
*BitMask
,
56 OUT UINTN
*BytesPerPixel
,
65 ASSERT (BytesPerPixel
!= NULL
);
68 Masks
= (UINT32
*) BitMask
;
69 for (Index
= 0; Index
< 3; Index
++) {
70 ASSERT ((MergedMasks
& Masks
[Index
]) == 0);
72 PixelShl
[Index
] = (INT8
) HighBitSet32 (Masks
[Index
]) - 23 + (Index
* 8);
73 if (PixelShl
[Index
] < 0) {
74 PixelShr
[Index
] = -PixelShl
[Index
];
79 DEBUG ((DEBUG_INFO
, "%d: shl:%d shr:%d mask:%x\n", Index
,
80 PixelShl
[Index
], PixelShr
[Index
], Masks
[Index
]));
82 MergedMasks
= (UINT32
) (MergedMasks
| Masks
[Index
]);
84 MergedMasks
= (UINT32
) (MergedMasks
| Masks
[3]);
86 ASSERT (MergedMasks
!= 0);
87 *BytesPerPixel
= (UINTN
) ((HighBitSet32 (MergedMasks
) + 7) / 8);
88 DEBUG ((DEBUG_INFO
, "Bytes per pixel: %d\n", *BytesPerPixel
));
92 Create the configuration for a video frame buffer.
94 The configuration is returned in the caller provided buffer.
96 @param[in] FrameBuffer Pointer to the start of the frame buffer.
97 @param[in] FrameBufferInfo Describes the frame buffer characteristics.
98 @param[in,out] Configure The created configuration information.
99 @param[in,out] ConfigureSize Size of the configuration information.
101 @retval RETURN_SUCCESS The configuration was successful created.
102 @retval RETURN_BUFFER_TOO_SMALL The Configure is to too small. The required
103 size is returned in ConfigureSize.
104 @retval RETURN_UNSUPPORTED The requested mode is not supported by
110 FrameBufferBltConfigure (
111 IN VOID
*FrameBuffer
,
112 IN EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*FrameBufferInfo
,
113 IN OUT FRAME_BUFFER_CONFIGURE
*Configure
,
114 IN OUT UINTN
*ConfigureSize
117 CONST EFI_PIXEL_BITMASK
*BitMask
;
122 if (ConfigureSize
== NULL
) {
123 return RETURN_INVALID_PARAMETER
;
126 switch (FrameBufferInfo
->PixelFormat
) {
127 case PixelRedGreenBlueReserved8BitPerColor
:
128 BitMask
= &mRgbPixelMasks
;
131 case PixelBlueGreenRedReserved8BitPerColor
:
132 BitMask
= &mBgrPixelMasks
;
136 BitMask
= &FrameBufferInfo
->PixelInformation
;
140 ASSERT (FrameBufferInfo
->PixelFormat
!= PixelBltOnly
);
141 return RETURN_UNSUPPORTED
;
145 return RETURN_INVALID_PARAMETER
;
148 FrameBufferBltLibConfigurePixelFormat (BitMask
, &BytesPerPixel
, PixelShl
, PixelShr
);
150 if (*ConfigureSize
< sizeof (FRAME_BUFFER_CONFIGURE
)
151 + FrameBufferInfo
->HorizontalResolution
* BytesPerPixel
) {
152 *ConfigureSize
= sizeof (FRAME_BUFFER_CONFIGURE
)
153 + FrameBufferInfo
->HorizontalResolution
* BytesPerPixel
;
154 return RETURN_BUFFER_TOO_SMALL
;
157 if (Configure
== NULL
) {
158 return RETURN_INVALID_PARAMETER
;
161 CopyMem (&Configure
->PixelMasks
, BitMask
, sizeof (*BitMask
));
162 CopyMem (Configure
->PixelShl
, PixelShl
, sizeof (PixelShl
));
163 CopyMem (Configure
->PixelShr
, PixelShr
, sizeof (PixelShr
));
164 Configure
->BytesPerPixel
= BytesPerPixel
;
165 Configure
->PixelFormat
= FrameBufferInfo
->PixelFormat
;
166 Configure
->FrameBuffer
= (UINT8
*) FrameBuffer
;
167 Configure
->WidthInPixels
= (UINTN
) FrameBufferInfo
->HorizontalResolution
;
168 Configure
->Height
= (UINTN
) FrameBufferInfo
->VerticalResolution
;
169 Configure
->WidthInBytes
= Configure
->WidthInPixels
* Configure
->BytesPerPixel
;
171 return RETURN_SUCCESS
;
175 Performs a UEFI Graphics Output Protocol Blt Video Fill.
177 @param[in] Configure Pointer to a configuration which was successfully
178 created by FrameBufferBltConfigure ().
179 @param[in] Color Color to fill the region with.
180 @param[in] DestinationX X location to start fill operation.
181 @param[in] DestinationY Y location to start fill operation.
182 @param[in] Width Width (in pixels) to fill.
183 @param[in] Height Height to fill.
185 @retval RETURN_INVALID_PARAMETER Invalid parameter was passed in.
186 @retval RETURN_SUCCESS The video was filled successfully.
190 FrameBufferBltLibVideoFill (
191 IN FRAME_BUFFER_CONFIGURE
*Configure
,
192 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Color
,
193 IN UINTN DestinationX
,
194 IN UINTN DestinationY
,
206 BOOLEAN LineBufferReady
;
212 // BltBuffer to Video: Source is BltBuffer, destination is Video
214 if (DestinationY
+ Height
> Configure
->Height
) {
215 DEBUG ((EFI_D_VERBOSE
, "VideoFill: Past screen (Y)\n"));
216 return RETURN_INVALID_PARAMETER
;
219 if (DestinationX
+ Width
> Configure
->WidthInPixels
) {
220 DEBUG ((EFI_D_VERBOSE
, "VideoFill: Past screen (X)\n"));
221 return RETURN_INVALID_PARAMETER
;
224 if (Width
== 0 || Height
== 0) {
225 DEBUG ((EFI_D_VERBOSE
, "VideoFill: Width or Height is 0\n"));
226 return RETURN_INVALID_PARAMETER
;
229 WidthInBytes
= Width
* Configure
->BytesPerPixel
;
231 Uint32
= *(UINT32
*) Color
;
234 (((Uint32
<< Configure
->PixelShl
[0]) >> Configure
->PixelShr
[0]) &
235 Configure
->PixelMasks
.RedMask
) |
236 (((Uint32
<< Configure
->PixelShl
[1]) >> Configure
->PixelShr
[1]) &
237 Configure
->PixelMasks
.GreenMask
) |
238 (((Uint32
<< Configure
->PixelShl
[2]) >> Configure
->PixelShr
[2]) &
239 Configure
->PixelMasks
.BlueMask
)
241 DEBUG ((EFI_D_VERBOSE
, "VideoFill: color=0x%x, wide-fill=0x%x\n",
245 // If the size of the pixel data evenly divides the sizeof
246 // WideFill, then a wide fill operation can be used
249 if ((sizeof (WideFill
) % Configure
->BytesPerPixel
) == 0) {
250 for (IndexX
= Configure
->BytesPerPixel
; IndexX
< sizeof (WideFill
); IndexX
++) {
251 ((UINT8
*) &WideFill
)[IndexX
] = ((UINT8
*) &WideFill
)[IndexX
% Configure
->BytesPerPixel
];
255 // If all the bytes in the pixel are the same value, then use
256 // a wide fill operation.
259 IndexX
= 1, Uint8
= ((UINT8
*) &WideFill
)[0];
260 IndexX
< Configure
->BytesPerPixel
;
262 if (Uint8
!= ((UINT8
*) &WideFill
)[IndexX
]) {
268 SetMem (&WideFill
, sizeof (WideFill
), Uint8
);
272 if (UseWideFill
&& (DestinationX
== 0) && (Width
== Configure
->WidthInPixels
)) {
273 DEBUG ((EFI_D_VERBOSE
, "VideoFill (wide, one-shot)\n"));
274 Offset
= DestinationY
* Configure
->WidthInPixels
;
275 Offset
= Configure
->BytesPerPixel
* Offset
;
276 Destination
= Configure
->FrameBuffer
+ Offset
;
277 SizeInBytes
= WidthInBytes
* Height
;
278 if (SizeInBytes
>= 8) {
279 SetMem32 (Destination
, SizeInBytes
& ~3, (UINT32
) WideFill
);
282 if (SizeInBytes
> 0) {
283 SetMem (Destination
, SizeInBytes
, (UINT8
) (UINTN
) WideFill
);
286 LineBufferReady
= FALSE
;
287 for (IndexY
= DestinationY
; IndexY
< (Height
+ DestinationY
); IndexY
++) {
288 Offset
= (IndexY
* Configure
->WidthInPixels
) + DestinationX
;
289 Offset
= Configure
->BytesPerPixel
* Offset
;
290 Destination
= Configure
->FrameBuffer
+ Offset
;
292 if (UseWideFill
&& (((UINTN
) Destination
& 7) == 0)) {
293 DEBUG ((EFI_D_VERBOSE
, "VideoFill (wide)\n"));
294 SizeInBytes
= WidthInBytes
;
295 if (SizeInBytes
>= 8) {
296 SetMem64 (Destination
, SizeInBytes
& ~7, WideFill
);
299 if (SizeInBytes
> 0) {
300 CopyMem (Destination
, &WideFill
, SizeInBytes
);
303 DEBUG ((EFI_D_VERBOSE
, "VideoFill (not wide)\n"));
304 if (!LineBufferReady
) {
305 CopyMem (Configure
->LineBuffer
, &WideFill
, Configure
->BytesPerPixel
);
306 for (IndexX
= 1; IndexX
< Width
; ) {
308 (Configure
->LineBuffer
+ (IndexX
* Configure
->BytesPerPixel
)),
309 Configure
->LineBuffer
,
310 MIN (IndexX
, Width
- IndexX
) * Configure
->BytesPerPixel
312 IndexX
+= MIN (IndexX
, Width
- IndexX
);
314 LineBufferReady
= TRUE
;
316 CopyMem (Destination
, Configure
->LineBuffer
, WidthInBytes
);
321 return RETURN_SUCCESS
;
325 Performs a UEFI Graphics Output Protocol Blt Video to Buffer operation
326 with extended parameters.
328 @param[in] Configure Pointer to a configuration which was successfully
329 created by FrameBufferBltConfigure ().
330 @param[out] BltBuffer Output buffer for pixel color data.
331 @param[in] SourceX X location within video.
332 @param[in] SourceY Y location within video.
333 @param[in] DestinationX X location within BltBuffer.
334 @param[in] DestinationY Y location within BltBuffer.
335 @param[in] Width Width (in pixels).
336 @param[in] Height Height.
337 @param[in] Delta Number of bytes in a row of BltBuffer.
339 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
340 @retval RETURN_SUCCESS The Blt operation was performed successfully.
343 FrameBufferBltLibVideoToBltBuffer (
344 IN FRAME_BUFFER_CONFIGURE
*Configure
,
345 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
,
348 IN UINTN DestinationX
,
349 IN UINTN DestinationY
,
357 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
366 // Video to BltBuffer: Source is Video, destination is BltBuffer
368 if (SourceY
+ Height
> Configure
->Height
) {
369 return RETURN_INVALID_PARAMETER
;
372 if (SourceX
+ Width
> Configure
->WidthInPixels
) {
373 return RETURN_INVALID_PARAMETER
;
376 if (Width
== 0 || Height
== 0) {
377 return RETURN_INVALID_PARAMETER
;
381 // If Delta is zero, then the entire BltBuffer is being used, so Delta is
382 // the number of bytes in each row of BltBuffer. Since BltBuffer is Width
383 // pixels size, the number of bytes in each row can be computed.
386 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
389 WidthInBytes
= Width
* Configure
->BytesPerPixel
;
392 // Video to BltBuffer: Source is Video, destination is BltBuffer
394 for (SrcY
= SourceY
, DstY
= DestinationY
;
395 DstY
< (Height
+ DestinationY
);
398 Offset
= (SrcY
* Configure
->WidthInPixels
) + SourceX
;
399 Offset
= Configure
->BytesPerPixel
* Offset
;
400 Source
= Configure
->FrameBuffer
+ Offset
;
402 if (Configure
->PixelFormat
== PixelBlueGreenRedReserved8BitPerColor
) {
403 Destination
= (UINT8
*) BltBuffer
+ (DstY
* Delta
) + (DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
405 Destination
= Configure
->LineBuffer
;
408 CopyMem (Destination
, Source
, WidthInBytes
);
410 if (Configure
->PixelFormat
!= PixelBlueGreenRedReserved8BitPerColor
) {
411 for (IndexX
= 0; IndexX
< Width
; IndexX
++) {
412 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*)
413 ((UINT8
*) BltBuffer
+ (DstY
* Delta
) +
414 (DestinationX
+ IndexX
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
415 Uint32
= *(UINT32
*) (Configure
->LineBuffer
+ (IndexX
* Configure
->BytesPerPixel
));
418 (((Uint32
& Configure
->PixelMasks
.RedMask
) >>
419 Configure
->PixelShl
[0]) << Configure
->PixelShr
[0]) |
420 (((Uint32
& Configure
->PixelMasks
.GreenMask
) >>
421 Configure
->PixelShl
[1]) << Configure
->PixelShr
[1]) |
422 (((Uint32
& Configure
->PixelMasks
.BlueMask
) >>
423 Configure
->PixelShl
[2]) << Configure
->PixelShr
[2])
429 return RETURN_SUCCESS
;
433 Performs a UEFI Graphics Output Protocol Blt Buffer to Video operation
434 with extended parameters.
436 @param[in] Configure Pointer to a configuration which was successfully
437 created by FrameBufferBltConfigure ().
438 @param[in] BltBuffer Output buffer for pixel color data.
439 @param[in] SourceX X location within BltBuffer.
440 @param[in] SourceY Y location within BltBuffer.
441 @param[in] DestinationX X location within video.
442 @param[in] DestinationY Y location within video.
443 @param[in] Width Width (in pixels).
444 @param[in] Height Height.
445 @param[in] Delta Number of bytes in a row of BltBuffer.
447 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
448 @retval RETURN_SUCCESS The Blt operation was performed successfully.
451 FrameBufferBltLibBufferToVideo (
452 IN FRAME_BUFFER_CONFIGURE
*Configure
,
453 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
,
456 IN UINTN DestinationX
,
457 IN UINTN DestinationY
,
465 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
474 // BltBuffer to Video: Source is BltBuffer, destination is Video
476 if (DestinationY
+ Height
> Configure
->Height
) {
477 return RETURN_INVALID_PARAMETER
;
480 if (DestinationX
+ Width
> Configure
->WidthInPixels
) {
481 return RETURN_INVALID_PARAMETER
;
484 if (Width
== 0 || Height
== 0) {
485 return RETURN_INVALID_PARAMETER
;
489 // If Delta is zero, then the entire BltBuffer is being used, so Delta is
490 // the number of bytes in each row of BltBuffer. Since BltBuffer is Width
491 // pixels size, the number of bytes in each row can be computed.
494 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
497 WidthInBytes
= Width
* Configure
->BytesPerPixel
;
499 for (SrcY
= SourceY
, DstY
= DestinationY
;
500 SrcY
< (Height
+ SourceY
);
503 Offset
= (DstY
* Configure
->WidthInPixels
) + DestinationX
;
504 Offset
= Configure
->BytesPerPixel
* Offset
;
505 Destination
= Configure
->FrameBuffer
+ Offset
;
507 if (Configure
->PixelFormat
== PixelBlueGreenRedReserved8BitPerColor
) {
508 Source
= (UINT8
*) BltBuffer
+ (SrcY
* Delta
);
510 for (IndexX
= 0; IndexX
< Width
; IndexX
++) {
512 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (
513 (UINT8
*) BltBuffer
+
515 ((SourceX
+ IndexX
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
))
517 Uint32
= *(UINT32
*) Blt
;
518 *(UINT32
*) (Configure
->LineBuffer
+ (IndexX
* Configure
->BytesPerPixel
)) =
520 (((Uint32
<< Configure
->PixelShl
[0]) >> Configure
->PixelShr
[0]) &
521 Configure
->PixelMasks
.RedMask
) |
522 (((Uint32
<< Configure
->PixelShl
[1]) >> Configure
->PixelShr
[1]) &
523 Configure
->PixelMasks
.GreenMask
) |
524 (((Uint32
<< Configure
->PixelShl
[2]) >> Configure
->PixelShr
[2]) &
525 Configure
->PixelMasks
.BlueMask
)
528 Source
= Configure
->LineBuffer
;
531 CopyMem (Destination
, Source
, WidthInBytes
);
534 return RETURN_SUCCESS
;
538 Performs a UEFI Graphics Output Protocol Blt Video to Video operation
540 @param[in] Configure Pointer to a configuration which was successfully
541 created by FrameBufferBltConfigure ().
542 @param[in] SourceX X location within video.
543 @param[in] SourceY Y location within video.
544 @param[in] DestinationX X location within video.
545 @param[in] DestinationY Y location within video.
546 @param[in] Width Width (in pixels).
547 @param[in] Height Height.
549 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
550 @retval RETURN_SUCCESS The Blt operation was performed successfully.
553 FrameBufferBltLibVideoToVideo (
554 IN FRAME_BUFFER_CONFIGURE
*Configure
,
557 IN UINTN DestinationX
,
558 IN UINTN DestinationY
,
570 // Video to Video: Source is Video, destination is Video
572 if (SourceY
+ Height
> Configure
->Height
) {
573 return RETURN_INVALID_PARAMETER
;
576 if (SourceX
+ Width
> Configure
->WidthInPixels
) {
577 return RETURN_INVALID_PARAMETER
;
580 if (DestinationY
+ Height
> Configure
->Height
) {
581 return RETURN_INVALID_PARAMETER
;
584 if (DestinationX
+ Width
> Configure
->WidthInPixels
) {
585 return RETURN_INVALID_PARAMETER
;
588 if (Width
== 0 || Height
== 0) {
589 return RETURN_INVALID_PARAMETER
;
592 WidthInBytes
= Width
* Configure
->BytesPerPixel
;
594 Offset
= (SourceY
* Configure
->WidthInPixels
) + SourceX
;
595 Offset
= Configure
->BytesPerPixel
* Offset
;
596 Source
= Configure
->FrameBuffer
+ Offset
;
598 Offset
= (DestinationY
* Configure
->WidthInPixels
) + DestinationX
;
599 Offset
= Configure
->BytesPerPixel
* Offset
;
600 Destination
= Configure
->FrameBuffer
+ Offset
;
602 LineStride
= Configure
->WidthInBytes
;
603 if (Destination
> Source
) {
605 // Copy from last line to avoid source is corrupted by copying
607 Source
+= Height
* LineStride
;
608 Destination
+= Height
* LineStride
;
609 LineStride
= -LineStride
;
612 while (Height
-- > 0) {
613 CopyMem (Destination
, Source
, WidthInBytes
);
615 Source
+= LineStride
;
616 Destination
+= LineStride
;
619 return RETURN_SUCCESS
;
623 Performs a UEFI Graphics Output Protocol Blt operation.
625 @param[in] Configure Pointer to a configuration which was successfully
626 created by FrameBufferBltConfigure ().
627 @param[in,out] BltBuffer The data to transfer to screen.
628 @param[in] BltOperation The operation to perform.
629 @param[in] SourceX The X coordinate of the source for BltOperation.
630 @param[in] SourceY The Y coordinate of the source for BltOperation.
631 @param[in] DestinationX The X coordinate of the destination for
633 @param[in] DestinationY The Y coordinate of the destination for
635 @param[in] Width The width of a rectangle in the blt rectangle
637 @param[in] Height The height of a rectangle in the blt rectangle
639 @param[in] Delta Not used for EfiBltVideoFill and
640 EfiBltVideoToVideo operation. If a Delta of 0
641 is used, the entire BltBuffer will be operated
642 on. If a subrectangle of the BltBuffer is
643 used, then Delta represents the number of
644 bytes in a row of the BltBuffer.
646 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
647 @retval RETURN_SUCCESS The Blt operation was performed successfully.
652 IN FRAME_BUFFER_CONFIGURE
*Configure
,
653 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
654 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
657 IN UINTN DestinationX
,
658 IN UINTN DestinationY
,
664 if (Configure
== NULL
) {
665 return RETURN_INVALID_PARAMETER
;
668 switch (BltOperation
) {
669 case EfiBltVideoToBltBuffer
:
670 return FrameBufferBltLibVideoToBltBuffer (
682 case EfiBltVideoToVideo
:
683 return FrameBufferBltLibVideoToVideo (
693 case EfiBltVideoFill
:
694 return FrameBufferBltLibVideoFill (
703 case EfiBltBufferToVideo
:
704 return FrameBufferBltLibBufferToVideo (
717 return RETURN_INVALID_PARAMETER
;