2 FrameBufferBltLib - Library to perform blt operations on a frame buffer.
4 Copyright (c) 2007 - 2016, 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 UINT8 LineBuffer
[SIZE_4KB
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)];
31 EFI_GRAPHICS_PIXEL_FORMAT PixelFormat
;
32 EFI_PIXEL_BITMASK PixelMasks
;
33 INTN PixelShl
[4]; // R-G-B-Rsvd
34 INTN 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 Configure The frame buffer configure.
49 @param BitMask The bit mask of pixel.
52 ConfigurePixelBitMaskFormat (
53 IN FRAME_BUFFER_CONFIGURE
*Configure
,
54 IN CONST EFI_PIXEL_BITMASK
*BitMask
62 Masks
= (UINT32
*) BitMask
;
63 for (Loop
= 0; Loop
< 3; Loop
++) {
64 ASSERT ((Loop
== 3) || (Masks
[Loop
] != 0));
65 ASSERT ((MergedMasks
& Masks
[Loop
]) == 0);
66 Configure
->PixelShl
[Loop
] = HighBitSet32 (Masks
[Loop
]) - 23 + (Loop
* 8);
67 if (Configure
->PixelShl
[Loop
] < 0) {
68 Configure
->PixelShr
[Loop
] = -Configure
->PixelShl
[Loop
];
69 Configure
->PixelShl
[Loop
] = 0;
71 Configure
->PixelShr
[Loop
] = 0;
73 MergedMasks
= (UINT32
) (MergedMasks
| Masks
[Loop
]);
74 DEBUG ((EFI_D_VERBOSE
, "%d: shl:%d shr:%d mask:%x\n", Loop
,
75 Configure
->PixelShl
[Loop
], Configure
->PixelShr
[Loop
], Masks
[Loop
]));
77 MergedMasks
= (UINT32
) (MergedMasks
| Masks
[3]);
79 ASSERT (MergedMasks
!= 0);
80 Configure
->BytesPerPixel
= (UINTN
) ((HighBitSet32 (MergedMasks
) + 7) / 8);
82 DEBUG ((EFI_D_VERBOSE
, "Bytes per pixel: %d\n", Configure
->BytesPerPixel
));
84 CopyMem (&Configure
->PixelMasks
, BitMask
, sizeof (*BitMask
));
88 Create the configuration for a video frame buffer.
90 The configuration is returned in the caller provided buffer.
92 @param[in] FrameBuffer Pointer to the start of the frame buffer.
93 @param[in] FrameBufferInfo Describes the frame buffer characteristics.
94 @param[in,out] Configure The created configuration information.
95 @param[in,out] ConfigureSize Size of the configuration information.
97 @retval RETURN_SUCCESS The configuration was successful created.
98 @retval RETURN_BUFFER_TOO_SMALL The Configure is to too small. The required
99 size is returned in ConfigureSize.
100 @retval RETURN_UNSUPPORTED The requested mode is not supported by
106 FrameBufferBltConfigure (
107 IN VOID
*FrameBuffer
,
108 IN EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*FrameBufferInfo
,
109 IN OUT FRAME_BUFFER_CONFIGURE
*Configure
,
110 IN OUT UINTN
*ConfigureSize
113 if (ConfigureSize
== NULL
) {
114 return RETURN_INVALID_PARAMETER
;
117 if (*ConfigureSize
< sizeof (FRAME_BUFFER_CONFIGURE
)) {
118 *ConfigureSize
= sizeof (FRAME_BUFFER_CONFIGURE
);
119 return RETURN_BUFFER_TOO_SMALL
;
122 if (Configure
== NULL
) {
123 return RETURN_INVALID_PARAMETER
;
126 switch (FrameBufferInfo
->PixelFormat
) {
127 case PixelRedGreenBlueReserved8BitPerColor
:
128 ConfigurePixelBitMaskFormat (Configure
, &mRgbPixelMasks
);
131 case PixelBlueGreenRedReserved8BitPerColor
:
132 ConfigurePixelBitMaskFormat (Configure
, &mBgrPixelMasks
);
136 ConfigurePixelBitMaskFormat (Configure
, &(FrameBufferInfo
->PixelInformation
));
140 ASSERT (FrameBufferInfo
->PixelFormat
!= PixelBltOnly
);
141 return RETURN_UNSUPPORTED
;
145 return RETURN_INVALID_PARAMETER
;
148 Configure
->PixelFormat
= FrameBufferInfo
->PixelFormat
;
149 Configure
->FrameBuffer
= (UINT8
*) FrameBuffer
;
150 Configure
->WidthInPixels
= (UINTN
) FrameBufferInfo
->HorizontalResolution
;
151 Configure
->Height
= (UINTN
) FrameBufferInfo
->VerticalResolution
;
152 Configure
->WidthInBytes
= Configure
->WidthInPixels
* Configure
->BytesPerPixel
;
154 ASSERT (Configure
->WidthInBytes
< sizeof (Configure
->LineBuffer
));
156 return RETURN_SUCCESS
;
160 Performs a UEFI Graphics Output Protocol Blt Video Fill.
162 @param[in] Configure Pointer to a configuration which was successfully
163 created by FrameBufferBltConfigure ().
164 @param[in] Color Color to fill the region with.
165 @param[in] DestinationX X location to start fill operation.
166 @param[in] DestinationY Y location to start fill operation.
167 @param[in] Width Width (in pixels) to fill.
168 @param[in] Height Height to fill.
170 @retval RETURN_INVALID_PARAMETER Invalid parameter was passed in.
171 @retval RETURN_SUCCESS The video was filled successfully.
175 FrameBufferBltLibVideoFill (
176 IN FRAME_BUFFER_CONFIGURE
*Configure
,
177 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Color
,
178 IN UINTN DestinationX
,
179 IN UINTN DestinationY
,
191 BOOLEAN LineBufferReady
;
197 // BltBuffer to Video: Source is BltBuffer, destination is Video
199 if (DestinationY
+ Height
> Configure
->Height
) {
200 DEBUG ((EFI_D_VERBOSE
, "VideoFill: Past screen (Y)\n"));
201 return RETURN_INVALID_PARAMETER
;
204 if (DestinationX
+ Width
> Configure
->WidthInPixels
) {
205 DEBUG ((EFI_D_VERBOSE
, "VideoFill: Past screen (X)\n"));
206 return RETURN_INVALID_PARAMETER
;
209 if (Width
== 0 || Height
== 0) {
210 DEBUG ((EFI_D_VERBOSE
, "VideoFill: Width or Height is 0\n"));
211 return RETURN_INVALID_PARAMETER
;
214 WidthInBytes
= Width
* Configure
->BytesPerPixel
;
216 Uint32
= *(UINT32
*) Color
;
219 (((Uint32
<< Configure
->PixelShl
[0]) >> Configure
->PixelShr
[0]) &
220 Configure
->PixelMasks
.RedMask
) |
221 (((Uint32
<< Configure
->PixelShl
[1]) >> Configure
->PixelShr
[1]) &
222 Configure
->PixelMasks
.GreenMask
) |
223 (((Uint32
<< Configure
->PixelShl
[2]) >> Configure
->PixelShr
[2]) &
224 Configure
->PixelMasks
.BlueMask
)
226 DEBUG ((EFI_D_VERBOSE
, "VideoFill: color=0x%x, wide-fill=0x%x\n",
230 // If the size of the pixel data evenly divides the sizeof
231 // WideFill, then a wide fill operation can be used
234 if ((sizeof (WideFill
) % Configure
->BytesPerPixel
) == 0) {
235 for (IndexX
= Configure
->BytesPerPixel
; IndexX
< sizeof (WideFill
); IndexX
++) {
236 ((UINT8
*) &WideFill
)[IndexX
] = ((UINT8
*) &WideFill
)[IndexX
% Configure
->BytesPerPixel
];
240 // If all the bytes in the pixel are the same value, then use
241 // a wide fill operation.
244 IndexX
= 1, Uint8
= ((UINT8
*) &WideFill
)[0];
245 IndexX
< Configure
->BytesPerPixel
;
247 if (Uint8
!= ((UINT8
*) &WideFill
)[IndexX
]) {
253 SetMem (&WideFill
, sizeof (WideFill
), Uint8
);
257 if (UseWideFill
&& (DestinationX
== 0) && (Width
== Configure
->WidthInPixels
)) {
258 DEBUG ((EFI_D_VERBOSE
, "VideoFill (wide, one-shot)\n"));
259 Offset
= DestinationY
* Configure
->WidthInPixels
;
260 Offset
= Configure
->BytesPerPixel
* Offset
;
261 Destination
= Configure
->FrameBuffer
+ Offset
;
262 SizeInBytes
= WidthInBytes
* Height
;
263 if (SizeInBytes
>= 8) {
264 SetMem32 (Destination
, SizeInBytes
& ~3, (UINT32
) WideFill
);
267 if (SizeInBytes
> 0) {
268 SetMem (Destination
, SizeInBytes
, (UINT8
) (UINTN
) WideFill
);
271 LineBufferReady
= FALSE
;
272 for (IndexY
= DestinationY
; IndexY
< (Height
+ DestinationY
); IndexY
++) {
273 Offset
= (IndexY
* Configure
->WidthInPixels
) + DestinationX
;
274 Offset
= Configure
->BytesPerPixel
* Offset
;
275 Destination
= Configure
->FrameBuffer
+ Offset
;
277 if (UseWideFill
&& (((UINTN
) Destination
& 7) == 0)) {
278 DEBUG ((EFI_D_VERBOSE
, "VideoFill (wide)\n"));
279 SizeInBytes
= WidthInBytes
;
280 if (SizeInBytes
>= 8) {
281 SetMem64 (Destination
, SizeInBytes
& ~7, WideFill
);
284 if (SizeInBytes
> 0) {
285 CopyMem (Destination
, &WideFill
, SizeInBytes
);
288 DEBUG ((EFI_D_VERBOSE
, "VideoFill (not wide)\n"));
289 if (!LineBufferReady
) {
290 CopyMem (Configure
->LineBuffer
, &WideFill
, Configure
->BytesPerPixel
);
291 for (IndexX
= 1; IndexX
< Width
; ) {
293 (Configure
->LineBuffer
+ (IndexX
* Configure
->BytesPerPixel
)),
294 Configure
->LineBuffer
,
295 MIN (IndexX
, Width
- IndexX
) * Configure
->BytesPerPixel
297 IndexX
+= MIN (IndexX
, Width
- IndexX
);
299 LineBufferReady
= TRUE
;
301 CopyMem (Destination
, Configure
->LineBuffer
, WidthInBytes
);
306 return RETURN_SUCCESS
;
310 Performs a UEFI Graphics Output Protocol Blt Video to Buffer operation
311 with extended parameters.
313 @param[in] Configure Pointer to a configuration which was successfully
314 created by FrameBufferBltConfigure ().
315 @param[out] BltBuffer Output buffer for pixel color data.
316 @param[in] SourceX X location within video.
317 @param[in] SourceY Y location within video.
318 @param[in] DestinationX X location within BltBuffer.
319 @param[in] DestinationY Y location within BltBuffer.
320 @param[in] Width Width (in pixels).
321 @param[in] Height Height.
322 @param[in] Delta Number of bytes in a row of BltBuffer.
324 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
325 @retval RETURN_SUCCESS The Blt operation was performed successfully.
328 FrameBufferBltLibVideoToBltBuffer (
329 IN FRAME_BUFFER_CONFIGURE
*Configure
,
330 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
,
333 IN UINTN DestinationX
,
334 IN UINTN DestinationY
,
342 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
351 // Video to BltBuffer: Source is Video, destination is BltBuffer
353 if (SourceY
+ Height
> Configure
->Height
) {
354 return RETURN_INVALID_PARAMETER
;
357 if (SourceX
+ Width
> Configure
->WidthInPixels
) {
358 return RETURN_INVALID_PARAMETER
;
361 if (Width
== 0 || Height
== 0) {
362 return RETURN_INVALID_PARAMETER
;
366 // If Delta is zero, then the entire BltBuffer is being used, so Delta is
367 // the number of bytes in each row of BltBuffer. Since BltBuffer is Width
368 // pixels size, the number of bytes in each row can be computed.
371 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
374 WidthInBytes
= Width
* Configure
->BytesPerPixel
;
377 // Video to BltBuffer: Source is Video, destination is BltBuffer
379 for (SrcY
= SourceY
, DstY
= DestinationY
;
380 DstY
< (Height
+ DestinationY
);
383 Offset
= (SrcY
* Configure
->WidthInPixels
) + SourceX
;
384 Offset
= Configure
->BytesPerPixel
* Offset
;
385 Source
= Configure
->FrameBuffer
+ Offset
;
387 if (Configure
->PixelFormat
== PixelBlueGreenRedReserved8BitPerColor
) {
388 Destination
= (UINT8
*) BltBuffer
+ (DstY
* Delta
) + (DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
390 Destination
= Configure
->LineBuffer
;
393 CopyMem (Destination
, Source
, WidthInBytes
);
395 if (Configure
->PixelFormat
!= PixelBlueGreenRedReserved8BitPerColor
) {
396 for (IndexX
= 0; IndexX
< Width
; IndexX
++) {
397 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*)
398 ((UINT8
*) BltBuffer
+ (DstY
* Delta
) +
399 (DestinationX
+ IndexX
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
400 Uint32
= *(UINT32
*) (Configure
->LineBuffer
+ (IndexX
* Configure
->BytesPerPixel
));
403 (((Uint32
& Configure
->PixelMasks
.RedMask
) >>
404 Configure
->PixelShl
[0]) << Configure
->PixelShr
[0]) |
405 (((Uint32
& Configure
->PixelMasks
.GreenMask
) >>
406 Configure
->PixelShl
[1]) << Configure
->PixelShr
[1]) |
407 (((Uint32
& Configure
->PixelMasks
.BlueMask
) >>
408 Configure
->PixelShl
[2]) << Configure
->PixelShr
[2])
414 return RETURN_SUCCESS
;
418 Performs a UEFI Graphics Output Protocol Blt Buffer to Video operation
419 with extended parameters.
421 @param[in] Configure Pointer to a configuration which was successfully
422 created by FrameBufferBltConfigure ().
423 @param[in] BltBuffer Output buffer for pixel color data.
424 @param[in] SourceX X location within BltBuffer.
425 @param[in] SourceY Y location within BltBuffer.
426 @param[in] DestinationX X location within video.
427 @param[in] DestinationY Y location within video.
428 @param[in] Width Width (in pixels).
429 @param[in] Height Height.
430 @param[in] Delta Number of bytes in a row of BltBuffer.
432 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
433 @retval RETURN_SUCCESS The Blt operation was performed successfully.
436 FrameBufferBltLibBufferToVideo (
437 IN FRAME_BUFFER_CONFIGURE
*Configure
,
438 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
,
441 IN UINTN DestinationX
,
442 IN UINTN DestinationY
,
450 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
459 // BltBuffer to Video: Source is BltBuffer, destination is Video
461 if (DestinationY
+ Height
> Configure
->Height
) {
462 return RETURN_INVALID_PARAMETER
;
465 if (DestinationX
+ Width
> Configure
->WidthInPixels
) {
466 return RETURN_INVALID_PARAMETER
;
469 if (Width
== 0 || Height
== 0) {
470 return RETURN_INVALID_PARAMETER
;
474 // If Delta is zero, then the entire BltBuffer is being used, so Delta is
475 // the number of bytes in each row of BltBuffer. Since BltBuffer is Width
476 // pixels size, the number of bytes in each row can be computed.
479 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
482 WidthInBytes
= Width
* Configure
->BytesPerPixel
;
484 for (SrcY
= SourceY
, DstY
= DestinationY
;
485 SrcY
< (Height
+ SourceY
);
488 Offset
= (DstY
* Configure
->WidthInPixels
) + DestinationX
;
489 Offset
= Configure
->BytesPerPixel
* Offset
;
490 Destination
= Configure
->FrameBuffer
+ Offset
;
492 if (Configure
->PixelFormat
== PixelBlueGreenRedReserved8BitPerColor
) {
493 Source
= (UINT8
*) BltBuffer
+ (SrcY
* Delta
);
495 for (IndexX
= 0; IndexX
< Width
; IndexX
++) {
497 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (
498 (UINT8
*) BltBuffer
+
500 ((SourceX
+ IndexX
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
))
502 Uint32
= *(UINT32
*) Blt
;
503 *(UINT32
*) (Configure
->LineBuffer
+ (IndexX
* Configure
->BytesPerPixel
)) =
505 (((Uint32
<< Configure
->PixelShl
[0]) >> Configure
->PixelShr
[0]) &
506 Configure
->PixelMasks
.RedMask
) |
507 (((Uint32
<< Configure
->PixelShl
[1]) >> Configure
->PixelShr
[1]) &
508 Configure
->PixelMasks
.GreenMask
) |
509 (((Uint32
<< Configure
->PixelShl
[2]) >> Configure
->PixelShr
[2]) &
510 Configure
->PixelMasks
.BlueMask
)
513 Source
= Configure
->LineBuffer
;
516 CopyMem (Destination
, Source
, WidthInBytes
);
519 return RETURN_SUCCESS
;
523 Performs a UEFI Graphics Output Protocol Blt Video to Video operation
525 @param[in] Configure Pointer to a configuration which was successfully
526 created by FrameBufferBltConfigure ().
527 @param[in] SourceX X location within video.
528 @param[in] SourceY Y location within video.
529 @param[in] DestinationX X location within video.
530 @param[in] DestinationY Y location within video.
531 @param[in] Width Width (in pixels).
532 @param[in] Height Height.
534 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
535 @retval RETURN_SUCCESS The Blt operation was performed successfully.
538 FrameBufferBltLibVideoToVideo (
539 IN FRAME_BUFFER_CONFIGURE
*Configure
,
542 IN UINTN DestinationX
,
543 IN UINTN DestinationY
,
555 // Video to Video: Source is Video, destination is Video
557 if (SourceY
+ Height
> Configure
->Height
) {
558 return RETURN_INVALID_PARAMETER
;
561 if (SourceX
+ Width
> Configure
->WidthInPixels
) {
562 return RETURN_INVALID_PARAMETER
;
565 if (DestinationY
+ Height
> Configure
->Height
) {
566 return RETURN_INVALID_PARAMETER
;
569 if (DestinationX
+ Width
> Configure
->WidthInPixels
) {
570 return RETURN_INVALID_PARAMETER
;
573 if (Width
== 0 || Height
== 0) {
574 return RETURN_INVALID_PARAMETER
;
577 WidthInBytes
= Width
* Configure
->BytesPerPixel
;
579 Offset
= (SourceY
* Configure
->WidthInPixels
) + SourceX
;
580 Offset
= Configure
->BytesPerPixel
* Offset
;
581 Source
= Configure
->FrameBuffer
+ Offset
;
583 Offset
= (DestinationY
* Configure
->WidthInPixels
) + DestinationX
;
584 Offset
= Configure
->BytesPerPixel
* Offset
;
585 Destination
= Configure
->FrameBuffer
+ Offset
;
587 LineStride
= Configure
->WidthInBytes
;
588 if (Destination
> Source
) {
590 // Copy from last line to avoid source is corrupted by copying
592 Source
+= Height
* LineStride
;
593 Destination
+= Height
* LineStride
;
594 LineStride
= -LineStride
;
597 while (Height
-- > 0) {
598 CopyMem (Destination
, Source
, WidthInBytes
);
600 Source
+= LineStride
;
601 Destination
+= LineStride
;
604 return RETURN_SUCCESS
;
608 Performs a UEFI Graphics Output Protocol Blt operation.
610 @param[in] Configure Pointer to a configuration which was successfully
611 created by FrameBufferBltConfigure ().
612 @param[in,out] BltBuffer The data to transfer to screen.
613 @param[in] BltOperation The operation to perform.
614 @param[in] SourceX The X coordinate of the source for BltOperation.
615 @param[in] SourceY The Y coordinate of the source for BltOperation.
616 @param[in] DestinationX The X coordinate of the destination for
618 @param[in] DestinationY The Y coordinate of the destination for
620 @param[in] Width The width of a rectangle in the blt rectangle
622 @param[in] Height The height of a rectangle in the blt rectangle
624 @param[in] Delta Not used for EfiBltVideoFill and
625 EfiBltVideoToVideo operation. If a Delta of 0
626 is used, the entire BltBuffer will be operated
627 on. If a subrectangle of the BltBuffer is
628 used, then Delta represents the number of
629 bytes in a row of the BltBuffer.
631 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
632 @retval RETURN_SUCCESS The Blt operation was performed successfully.
637 IN FRAME_BUFFER_CONFIGURE
*Configure
,
638 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
639 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
642 IN UINTN DestinationX
,
643 IN UINTN DestinationY
,
649 if (Configure
== NULL
) {
650 return RETURN_INVALID_PARAMETER
;
653 switch (BltOperation
) {
654 case EfiBltVideoToBltBuffer
:
655 return FrameBufferBltLibVideoToBltBuffer (
667 case EfiBltVideoToVideo
:
668 return FrameBufferBltLibVideoToVideo (
678 case EfiBltVideoFill
:
679 return FrameBufferBltLibVideoFill (
688 case EfiBltBufferToVideo
:
689 return FrameBufferBltLibBufferToVideo (
702 return RETURN_INVALID_PARAMETER
;