TianoCore EDK2 master
Loading...
Searching...
No Matches
FrameBufferBltLib.c
Go to the documentation of this file.
1
9#include <Uefi/UefiBaseType.h>
11
12#include <Library/BaseLib.h>
14#include <Library/DebugLib.h>
16
18 UINT32 PixelsPerScanLine;
19 UINT32 BytesPerPixel;
20 UINT32 Width;
21 UINT32 Height;
22 UINT8 *FrameBuffer;
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
27 UINT8 LineBuffer[0];
28};
29
30CONST EFI_PIXEL_BITMASK mRgbPixelMasks = {
31 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
32};
33
34CONST EFI_PIXEL_BITMASK mBgrPixelMasks = {
35 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000
36};
37
46VOID
48 IN CONST EFI_PIXEL_BITMASK *BitMask,
49 OUT UINT32 *BytesPerPixel,
50 OUT INT8 *PixelShl,
51 OUT INT8 *PixelShr
52 )
53{
54 UINT8 Index;
55 UINT32 *Masks;
56 UINT32 MergedMasks;
57
58 ASSERT (BytesPerPixel != NULL);
59
60 MergedMasks = 0;
61 Masks = (UINT32 *)BitMask;
62 for (Index = 0; Index < 3; Index++) {
63 ASSERT ((MergedMasks & Masks[Index]) == 0);
64
65 PixelShl[Index] = (INT8)HighBitSet32 (Masks[Index]) - 23 + (Index * 8);
66 if (PixelShl[Index] < 0) {
67 PixelShr[Index] = -PixelShl[Index];
68 PixelShl[Index] = 0;
69 } else {
70 PixelShr[Index] = 0;
71 }
72
73 DEBUG ((
74 DEBUG_INFO,
75 "%d: shl:%d shr:%d mask:%x\n",
76 Index,
77 PixelShl[Index],
78 PixelShr[Index],
79 Masks[Index]
80 ));
81
82 MergedMasks = (UINT32)(MergedMasks | Masks[Index]);
83 }
84
85 MergedMasks = (UINT32)(MergedMasks | Masks[3]);
86
87 ASSERT (MergedMasks != 0);
88 *BytesPerPixel = (UINT32)((HighBitSet32 (MergedMasks) + 7) / 8);
89 DEBUG ((DEBUG_INFO, "Bytes per pixel: %d\n", *BytesPerPixel));
90}
91
109RETURN_STATUS
110EFIAPI
112 IN VOID *FrameBuffer,
114 IN OUT FRAME_BUFFER_CONFIGURE *Configure,
115 IN OUT UINTN *ConfigureSize
116 )
117{
118 CONST EFI_PIXEL_BITMASK *BitMask;
119 UINT32 BytesPerPixel;
120 INT8 PixelShl[4];
121 INT8 PixelShr[4];
122
123 if (ConfigureSize == NULL) {
125 }
126
127 switch (FrameBufferInfo->PixelFormat) {
129 BitMask = &mRgbPixelMasks;
130 break;
131
133 BitMask = &mBgrPixelMasks;
134 break;
135
136 case PixelBitMask:
137 BitMask = &FrameBufferInfo->PixelInformation;
138 break;
139
140 case PixelBltOnly:
141 ASSERT (FrameBufferInfo->PixelFormat != PixelBltOnly);
142 return RETURN_UNSUPPORTED;
143
144 default:
145 ASSERT (FALSE);
147 }
148
149 if (FrameBufferInfo->PixelsPerScanLine < FrameBufferInfo->HorizontalResolution) {
150 return RETURN_UNSUPPORTED;
151 }
152
153 FrameBufferBltLibConfigurePixelFormat (BitMask, &BytesPerPixel, PixelShl, PixelShr);
154
155 if (*ConfigureSize < sizeof (FRAME_BUFFER_CONFIGURE)
156 + FrameBufferInfo->HorizontalResolution * BytesPerPixel)
157 {
158 *ConfigureSize = sizeof (FRAME_BUFFER_CONFIGURE)
159 + FrameBufferInfo->HorizontalResolution * BytesPerPixel;
161 }
162
163 if (Configure == NULL) {
165 }
166
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;
176
177 return RETURN_SUCCESS;
178}
179
197 IN FRAME_BUFFER_CONFIGURE *Configure,
199 IN UINTN DestinationX,
200 IN UINTN DestinationY,
201 IN UINTN Width,
202 IN UINTN Height
203 )
204{
205 UINTN IndexX;
206 UINTN IndexY;
207 UINT8 *Destination;
208 UINT8 Uint8;
209 UINT32 Uint32;
210 UINT64 WideFill;
211 BOOLEAN UseWideFill;
212 BOOLEAN LineBufferReady;
213 UINTN Offset;
214 UINTN WidthInBytes;
215 UINTN SizeInBytes;
216
217 //
218 // BltBuffer to Video: Source is BltBuffer, destination is Video
219 //
220 if (DestinationY + Height > Configure->Height) {
221 DEBUG ((DEBUG_VERBOSE, "VideoFill: Past screen (Y)\n"));
223 }
224
225 if (DestinationX + Width > Configure->Width) {
226 DEBUG ((DEBUG_VERBOSE, "VideoFill: Past screen (X)\n"));
228 }
229
230 if ((Width == 0) || (Height == 0)) {
231 DEBUG ((DEBUG_VERBOSE, "VideoFill: Width or Height is 0\n"));
233 }
234
235 WidthInBytes = Width * Configure->BytesPerPixel;
236
237 Uint32 = *(UINT32 *)Color;
238 WideFill =
239 (UINT32)(
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)
246 );
247 DEBUG ((
248 DEBUG_VERBOSE,
249 "VideoFill: color=0x%x, wide-fill=0x%x\n",
250 Uint32,
251 WideFill
252 ));
253
254 //
255 // If the size of the pixel data evenly divides the sizeof
256 // WideFill, then a wide fill operation can be used
257 //
258 UseWideFill = TRUE;
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];
262 }
263 } else {
264 //
265 // If all the bytes in the pixel are the same value, then use
266 // a wide fill operation.
267 //
268 for (
269 IndexX = 1, Uint8 = ((UINT8 *)&WideFill)[0];
270 IndexX < Configure->BytesPerPixel;
271 IndexX++)
272 {
273 if (Uint8 != ((UINT8 *)&WideFill)[IndexX]) {
274 UseWideFill = FALSE;
275 break;
276 }
277 }
278
279 if (UseWideFill) {
280 SetMem (&WideFill, sizeof (WideFill), Uint8);
281 }
282 }
283
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;
293 SizeInBytes &= 3;
294 }
295
296 if (SizeInBytes > 0) {
297 SetMem (Destination, SizeInBytes, (UINT8)(UINTN)WideFill);
298 }
299 } else {
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;
305
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;
312 SizeInBytes &= 7;
313 }
314
315 if (SizeInBytes > 0) {
316 CopyMem (Destination, &WideFill, SizeInBytes);
317 }
318 } else {
319 DEBUG ((DEBUG_VERBOSE, "VideoFill (not wide)\n"));
320 if (!LineBufferReady) {
321 CopyMem (Configure->LineBuffer, &WideFill, Configure->BytesPerPixel);
322 for (IndexX = 1; IndexX < Width; ) {
323 CopyMem (
324 (Configure->LineBuffer + (IndexX * Configure->BytesPerPixel)),
325 Configure->LineBuffer,
326 MIN (IndexX, Width - IndexX) * Configure->BytesPerPixel
327 );
328 IndexX += MIN (IndexX, Width - IndexX);
329 }
330
331 LineBufferReady = TRUE;
332 }
333
334 CopyMem (Destination, Configure->LineBuffer, WidthInBytes);
335 }
336 }
337 }
338
339 return RETURN_SUCCESS;
340}
341
360RETURN_STATUS
362 IN FRAME_BUFFER_CONFIGURE *Configure,
364 IN UINTN SourceX,
365 IN UINTN SourceY,
366 IN UINTN DestinationX,
367 IN UINTN DestinationY,
368 IN UINTN Width,
369 IN UINTN Height,
370 IN UINTN Delta
371 )
372{
373 UINTN DstY;
374 UINTN SrcY;
376 UINT8 *Source;
377 UINT8 *Destination;
378 UINTN IndexX;
379 UINT32 Uint32;
380 UINTN Offset;
381 UINTN WidthInBytes;
382
383 //
384 // Video to BltBuffer: Source is Video, destination is BltBuffer
385 //
386 if (SourceY + Height > Configure->Height) {
388 }
389
390 if (SourceX + Width > Configure->Width) {
392 }
393
394 if ((Width == 0) || (Height == 0)) {
396 }
397
398 //
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.
402 //
403 if (Delta == 0) {
404 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
405 }
406
407 WidthInBytes = Width * Configure->BytesPerPixel;
408
409 //
410 // Video to BltBuffer: Source is Video, destination is BltBuffer
411 //
412 for (SrcY = SourceY, DstY = DestinationY;
413 DstY < (Height + DestinationY);
414 SrcY++, DstY++)
415 {
416 Offset = (SrcY * Configure->PixelsPerScanLine) + SourceX;
417 Offset = Configure->BytesPerPixel * Offset;
418 Source = Configure->FrameBuffer + Offset;
419
420 if (Configure->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
421 Destination = (UINT8 *)BltBuffer + (DstY * Delta) + (DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
422 } else {
423 Destination = Configure->LineBuffer;
424 }
425
426 CopyMem (Destination, Source, WidthInBytes);
427
428 if (Configure->PixelFormat != PixelBlueGreenRedReserved8BitPerColor) {
429 for (IndexX = 0; IndexX < Width; IndexX++) {
431 ((UINT8 *)BltBuffer + (DstY * Delta) +
432 (DestinationX + IndexX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
433 Uint32 = *(UINT32 *)(Configure->LineBuffer + (IndexX * Configure->BytesPerPixel));
434 *(UINT32 *)Blt =
435 (UINT32)(
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])
442 );
443 }
444 }
445 }
446
447 return RETURN_SUCCESS;
448}
449
468RETURN_STATUS
470 IN FRAME_BUFFER_CONFIGURE *Configure,
472 IN UINTN SourceX,
473 IN UINTN SourceY,
474 IN UINTN DestinationX,
475 IN UINTN DestinationY,
476 IN UINTN Width,
477 IN UINTN Height,
478 IN UINTN Delta
479 )
480{
481 UINTN DstY;
482 UINTN SrcY;
484 UINT8 *Source;
485 UINT8 *Destination;
486 UINTN IndexX;
487 UINT32 Uint32;
488 UINTN Offset;
489 UINTN WidthInBytes;
490
491 //
492 // BltBuffer to Video: Source is BltBuffer, destination is Video
493 //
494 if (DestinationY + Height > Configure->Height) {
496 }
497
498 if (DestinationX + Width > Configure->Width) {
500 }
501
502 if ((Width == 0) || (Height == 0)) {
504 }
505
506 //
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.
510 //
511 if (Delta == 0) {
512 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
513 }
514
515 WidthInBytes = Width * Configure->BytesPerPixel;
516
517 for (SrcY = SourceY, DstY = DestinationY;
518 SrcY < (Height + SourceY);
519 SrcY++, DstY++)
520 {
521 Offset = (DstY * Configure->PixelsPerScanLine) + DestinationX;
522 Offset = Configure->BytesPerPixel * Offset;
523 Destination = Configure->FrameBuffer + Offset;
524
525 if (Configure->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
526 Source = (UINT8 *)BltBuffer + (SrcY * Delta) + SourceX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
527 } else {
528 for (IndexX = 0; IndexX < Width; IndexX++) {
529 Blt =
531 (UINT8 *)BltBuffer +
532 (SrcY * Delta) +
533 ((SourceX + IndexX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))
534 );
535 Uint32 = *(UINT32 *)Blt;
536 *(UINT32 *)(Configure->LineBuffer + (IndexX * Configure->BytesPerPixel)) =
537 (UINT32)(
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)
544 );
545 }
546
547 Source = Configure->LineBuffer;
548 }
549
550 CopyMem (Destination, Source, WidthInBytes);
551 }
552
553 return RETURN_SUCCESS;
554}
555
571RETURN_STATUS
573 IN FRAME_BUFFER_CONFIGURE *Configure,
574 IN UINTN SourceX,
575 IN UINTN SourceY,
576 IN UINTN DestinationX,
577 IN UINTN DestinationY,
578 IN UINTN Width,
579 IN UINTN Height
580 )
581{
582 UINT8 *Source;
583 UINT8 *Destination;
584 UINTN Offset;
585 UINTN WidthInBytes;
586 INTN LineStride;
587
588 //
589 // Video to Video: Source is Video, destination is Video
590 //
591 if (SourceY + Height > Configure->Height) {
593 }
594
595 if (SourceX + Width > Configure->Width) {
597 }
598
599 if (DestinationY + Height > Configure->Height) {
601 }
602
603 if (DestinationX + Width > Configure->Width) {
605 }
606
607 if ((Width == 0) || (Height == 0)) {
609 }
610
611 WidthInBytes = Width * Configure->BytesPerPixel;
612
613 Offset = (SourceY * Configure->PixelsPerScanLine) + SourceX;
614 Offset = Configure->BytesPerPixel * Offset;
615 Source = Configure->FrameBuffer + Offset;
616
617 Offset = (DestinationY * Configure->PixelsPerScanLine) + DestinationX;
618 Offset = Configure->BytesPerPixel * Offset;
619 Destination = Configure->FrameBuffer + Offset;
620
621 LineStride = Configure->BytesPerPixel * Configure->PixelsPerScanLine;
622 if (Destination > Source) {
623 //
624 // Copy from last line to avoid source is corrupted by copying
625 //
626 Source += Height * LineStride;
627 Destination += Height * LineStride;
628 LineStride = -LineStride;
629 }
630
631 while (Height-- > 0) {
632 CopyMem (Destination, Source, WidthInBytes);
633
634 Source += LineStride;
635 Destination += LineStride;
636 }
637
638 return RETURN_SUCCESS;
639}
640
668RETURN_STATUS
669EFIAPI
671 IN FRAME_BUFFER_CONFIGURE *Configure,
672 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,
674 IN UINTN SourceX,
675 IN UINTN SourceY,
676 IN UINTN DestinationX,
677 IN UINTN DestinationY,
678 IN UINTN Width,
679 IN UINTN Height,
680 IN UINTN Delta
681 )
682{
683 if (Configure == NULL) {
685 }
686
687 switch (BltOperation) {
690 Configure,
691 BltBuffer,
692 SourceX,
693 SourceY,
694 DestinationX,
695 DestinationY,
696 Width,
697 Height,
698 Delta
699 );
700
703 Configure,
704 SourceX,
705 SourceY,
706 DestinationX,
707 DestinationY,
708 Width,
709 Height
710 );
711
712 case EfiBltVideoFill:
714 Configure,
715 BltBuffer,
716 DestinationX,
717 DestinationY,
718 Width,
719 Height
720 );
721
724 Configure,
725 BltBuffer,
726 SourceX,
727 SourceY,
728 DestinationX,
729 DestinationY,
730 Width,
731 Height,
732 Delta
733 );
734
735 default:
737 }
738}
UINT64 UINTN
INT64 INTN
INTN EFIAPI HighBitSet32(IN UINT32 Operand)
Definition: HighBitSet32.c:27
VOID *EFIAPI SetMem64(OUT VOID *Buffer, IN UINTN Length, IN UINT64 Value)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
Definition: SetMemWrapper.c:38
VOID *EFIAPI SetMem32(OUT VOID *Buffer, IN UINTN Length, IN UINT32 Value)
RETURN_STATUS FrameBufferBltLibVideoToBltBuffer(IN FRAME_BUFFER_CONFIGURE *Configure, OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, IN UINTN SourceX, IN UINTN SourceY, IN UINTN DestinationX, IN UINTN DestinationY, IN UINTN Width, IN UINTN Height, IN UINTN Delta)
RETURN_STATUS FrameBufferBltLibBufferToVideo(IN FRAME_BUFFER_CONFIGURE *Configure, IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, IN UINTN SourceX, IN UINTN SourceY, IN UINTN DestinationX, IN UINTN DestinationY, IN UINTN Width, IN UINTN Height, IN UINTN Delta)
RETURN_STATUS FrameBufferBltLibVideoToVideo(IN FRAME_BUFFER_CONFIGURE *Configure, IN UINTN SourceX, IN UINTN SourceY, IN UINTN DestinationX, IN UINTN DestinationY, IN UINTN Width, IN UINTN Height)
RETURN_STATUS EFIAPI FrameBufferBlt(IN FRAME_BUFFER_CONFIGURE *Configure, IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL, IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, IN UINTN SourceX, IN UINTN SourceY, IN UINTN DestinationX, IN UINTN DestinationY, IN UINTN Width, IN UINTN Height, IN UINTN Delta)
VOID FrameBufferBltLibConfigurePixelFormat(IN CONST EFI_PIXEL_BITMASK *BitMask, OUT UINT32 *BytesPerPixel, OUT INT8 *PixelShl, OUT INT8 *PixelShr)
RETURN_STATUS EFIAPI FrameBufferBltConfigure(IN VOID *FrameBuffer, IN EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *FrameBufferInfo, IN OUT FRAME_BUFFER_CONFIGURE *Configure, IN OUT UINTN *ConfigureSize)
EFI_STATUS FrameBufferBltLibVideoFill(IN FRAME_BUFFER_CONFIGURE *Configure, IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Color, IN UINTN DestinationX, IN UINTN DestinationY, IN UINTN Width, IN UINTN Height)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define RETURN_BUFFER_TOO_SMALL
Definition: Base.h:1093
#define MIN(a, b)
Definition: Base.h:1007
#define RETURN_UNSUPPORTED
Definition: Base.h:1081
#define RETURN_SUCCESS
Definition: Base.h:1066
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define RETURN_INVALID_PARAMETER
Definition: Base.h:1076
#define DEBUG(Expression)
Definition: DebugLib.h:434
EFI_GRAPHICS_OUTPUT_BLT_OPERATION
@ EfiBltVideoToBltBuffer
@ EfiBltBufferToVideo
@ EfiBltVideoFill
@ EfiBltVideoToVideo
EFI_GRAPHICS_PIXEL_FORMAT
@ PixelBitMask
@ PixelRedGreenBlueReserved8BitPerColor
@ PixelBlueGreenRedReserved8BitPerColor
@ PixelBltOnly
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29