]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.c
MdeModulePkg/FrameBufferBltLib: Fix a bug causing display corrupted
[mirror_edk2.git] / MdeModulePkg / Library / FrameBufferBltLib / FrameBufferBltLib.c
1 /** @file
2 FrameBufferBltLib - Library to perform blt operations on a frame buffer.
3
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
9
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.
12
13 **/
14
15 #include <Uefi/UefiBaseType.h>
16 #include <Protocol/GraphicsOutput.h>
17
18 #include <Library/BaseLib.h>
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/FrameBufferBltLib.h>
22
23 struct FRAME_BUFFER_CONFIGURE {
24 UINT32 PixelsPerScanLine;
25 UINT32 BytesPerPixel;
26 UINT32 Width;
27 UINT32 Height;
28 UINT8 *FrameBuffer;
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
33 UINT8 LineBuffer[0];
34 };
35
36 CONST EFI_PIXEL_BITMASK mRgbPixelMasks = {
37 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
38 };
39
40 CONST EFI_PIXEL_BITMASK mBgrPixelMasks = {
41 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000
42 };
43
44 /**
45 Initialize the bit mask in frame buffer configure.
46
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.
51 **/
52 VOID
53 FrameBufferBltLibConfigurePixelFormat (
54 IN CONST EFI_PIXEL_BITMASK *BitMask,
55 OUT UINT32 *BytesPerPixel,
56 OUT INT8 *PixelShl,
57 OUT INT8 *PixelShr
58 )
59 {
60 UINT8 Index;
61 UINT32 *Masks;
62 UINT32 MergedMasks;
63
64 ASSERT (BytesPerPixel != NULL);
65
66 MergedMasks = 0;
67 Masks = (UINT32*) BitMask;
68 for (Index = 0; Index < 3; Index++) {
69 ASSERT ((MergedMasks & Masks[Index]) == 0);
70
71 PixelShl[Index] = (INT8) HighBitSet32 (Masks[Index]) - 23 + (Index * 8);
72 if (PixelShl[Index] < 0) {
73 PixelShr[Index] = -PixelShl[Index];
74 PixelShl[Index] = 0;
75 } else {
76 PixelShr[Index] = 0;
77 }
78 DEBUG ((DEBUG_INFO, "%d: shl:%d shr:%d mask:%x\n", Index,
79 PixelShl[Index], PixelShr[Index], Masks[Index]));
80
81 MergedMasks = (UINT32) (MergedMasks | Masks[Index]);
82 }
83 MergedMasks = (UINT32) (MergedMasks | Masks[3]);
84
85 ASSERT (MergedMasks != 0);
86 *BytesPerPixel = (UINT32) ((HighBitSet32 (MergedMasks) + 7) / 8);
87 DEBUG ((DEBUG_INFO, "Bytes per pixel: %d\n", *BytesPerPixel));
88 }
89
90 /**
91 Create the configuration for a video frame buffer.
92
93 The configuration is returned in the caller provided buffer.
94
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.
99
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
104 this implementaion.
105
106 **/
107 RETURN_STATUS
108 EFIAPI
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
114 )
115 {
116 CONST EFI_PIXEL_BITMASK *BitMask;
117 UINT32 BytesPerPixel;
118 INT8 PixelShl[4];
119 INT8 PixelShr[4];
120
121 if (ConfigureSize == NULL) {
122 return RETURN_INVALID_PARAMETER;
123 }
124
125 switch (FrameBufferInfo->PixelFormat) {
126 case PixelRedGreenBlueReserved8BitPerColor:
127 BitMask = &mRgbPixelMasks;
128 break;
129
130 case PixelBlueGreenRedReserved8BitPerColor:
131 BitMask = &mBgrPixelMasks;
132 break;
133
134 case PixelBitMask:
135 BitMask = &FrameBufferInfo->PixelInformation;
136 break;
137
138 case PixelBltOnly:
139 ASSERT (FrameBufferInfo->PixelFormat != PixelBltOnly);
140 return RETURN_UNSUPPORTED;
141
142 default:
143 ASSERT (FALSE);
144 return RETURN_INVALID_PARAMETER;
145 }
146
147 if (FrameBufferInfo->PixelsPerScanLine < FrameBufferInfo->HorizontalResolution) {
148 return RETURN_UNSUPPORTED;
149 }
150
151 FrameBufferBltLibConfigurePixelFormat (BitMask, &BytesPerPixel, PixelShl, PixelShr);
152
153 if (*ConfigureSize < sizeof (FRAME_BUFFER_CONFIGURE)
154 + FrameBufferInfo->HorizontalResolution * BytesPerPixel) {
155 *ConfigureSize = sizeof (FRAME_BUFFER_CONFIGURE)
156 + FrameBufferInfo->HorizontalResolution * BytesPerPixel;
157 return RETURN_BUFFER_TOO_SMALL;
158 }
159
160 if (Configure == NULL) {
161 return RETURN_INVALID_PARAMETER;
162 }
163
164 CopyMem (&Configure->PixelMasks, BitMask, sizeof (*BitMask));
165 CopyMem (Configure->PixelShl, PixelShl, sizeof (PixelShl));
166 CopyMem (Configure->PixelShr, PixelShr, sizeof (PixelShr));
167 Configure->BytesPerPixel = BytesPerPixel;
168 Configure->PixelFormat = FrameBufferInfo->PixelFormat;
169 Configure->FrameBuffer = (UINT8*) FrameBuffer;
170 Configure->Width = FrameBufferInfo->HorizontalResolution;
171 Configure->Height = FrameBufferInfo->VerticalResolution;
172 Configure->PixelsPerScanLine = FrameBufferInfo->PixelsPerScanLine;
173
174 return RETURN_SUCCESS;
175 }
176
177 /**
178 Performs a UEFI Graphics Output Protocol Blt Video Fill.
179
180 @param[in] Configure Pointer to a configuration which was successfully
181 created by FrameBufferBltConfigure ().
182 @param[in] Color Color to fill the region with.
183 @param[in] DestinationX X location to start fill operation.
184 @param[in] DestinationY Y location to start fill operation.
185 @param[in] Width Width (in pixels) to fill.
186 @param[in] Height Height to fill.
187
188 @retval RETURN_INVALID_PARAMETER Invalid parameter was passed in.
189 @retval RETURN_SUCCESS The video was filled successfully.
190
191 **/
192 EFI_STATUS
193 FrameBufferBltLibVideoFill (
194 IN FRAME_BUFFER_CONFIGURE *Configure,
195 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Color,
196 IN UINTN DestinationX,
197 IN UINTN DestinationY,
198 IN UINTN Width,
199 IN UINTN Height
200 )
201 {
202 UINTN IndexX;
203 UINTN IndexY;
204 UINT8 *Destination;
205 UINT8 Uint8;
206 UINT32 Uint32;
207 UINT64 WideFill;
208 BOOLEAN UseWideFill;
209 BOOLEAN LineBufferReady;
210 UINTN Offset;
211 UINTN WidthInBytes;
212 UINTN SizeInBytes;
213
214 //
215 // BltBuffer to Video: Source is BltBuffer, destination is Video
216 //
217 if (DestinationY + Height > Configure->Height) {
218 DEBUG ((EFI_D_VERBOSE, "VideoFill: Past screen (Y)\n"));
219 return RETURN_INVALID_PARAMETER;
220 }
221
222 if (DestinationX + Width > Configure->Width) {
223 DEBUG ((EFI_D_VERBOSE, "VideoFill: Past screen (X)\n"));
224 return RETURN_INVALID_PARAMETER;
225 }
226
227 if (Width == 0 || Height == 0) {
228 DEBUG ((EFI_D_VERBOSE, "VideoFill: Width or Height is 0\n"));
229 return RETURN_INVALID_PARAMETER;
230 }
231
232 WidthInBytes = Width * Configure->BytesPerPixel;
233
234 Uint32 = *(UINT32*) Color;
235 WideFill =
236 (UINT32) (
237 (((Uint32 << Configure->PixelShl[0]) >> Configure->PixelShr[0]) &
238 Configure->PixelMasks.RedMask) |
239 (((Uint32 << Configure->PixelShl[1]) >> Configure->PixelShr[1]) &
240 Configure->PixelMasks.GreenMask) |
241 (((Uint32 << Configure->PixelShl[2]) >> Configure->PixelShr[2]) &
242 Configure->PixelMasks.BlueMask)
243 );
244 DEBUG ((EFI_D_VERBOSE, "VideoFill: color=0x%x, wide-fill=0x%x\n",
245 Uint32, WideFill));
246
247 //
248 // If the size of the pixel data evenly divides the sizeof
249 // WideFill, then a wide fill operation can be used
250 //
251 UseWideFill = TRUE;
252 if ((sizeof (WideFill) % Configure->BytesPerPixel) == 0) {
253 for (IndexX = Configure->BytesPerPixel; IndexX < sizeof (WideFill); IndexX++) {
254 ((UINT8*) &WideFill)[IndexX] = ((UINT8*) &WideFill)[IndexX % Configure->BytesPerPixel];
255 }
256 } else {
257 //
258 // If all the bytes in the pixel are the same value, then use
259 // a wide fill operation.
260 //
261 for (
262 IndexX = 1, Uint8 = ((UINT8*) &WideFill)[0];
263 IndexX < Configure->BytesPerPixel;
264 IndexX++) {
265 if (Uint8 != ((UINT8*) &WideFill)[IndexX]) {
266 UseWideFill = FALSE;
267 break;
268 }
269 }
270 if (UseWideFill) {
271 SetMem (&WideFill, sizeof (WideFill), Uint8);
272 }
273 }
274
275 if (UseWideFill && (DestinationX == 0) && (Width == Configure->PixelsPerScanLine)) {
276 DEBUG ((EFI_D_VERBOSE, "VideoFill (wide, one-shot)\n"));
277 Offset = DestinationY * Configure->PixelsPerScanLine;
278 Offset = Configure->BytesPerPixel * Offset;
279 Destination = Configure->FrameBuffer + Offset;
280 SizeInBytes = WidthInBytes * Height;
281 if (SizeInBytes >= 8) {
282 SetMem32 (Destination, SizeInBytes & ~3, (UINT32) WideFill);
283 SizeInBytes &= 3;
284 }
285 if (SizeInBytes > 0) {
286 SetMem (Destination, SizeInBytes, (UINT8) (UINTN) WideFill);
287 }
288 } else {
289 LineBufferReady = FALSE;
290 for (IndexY = DestinationY; IndexY < (Height + DestinationY); IndexY++) {
291 Offset = (IndexY * Configure->PixelsPerScanLine) + DestinationX;
292 Offset = Configure->BytesPerPixel * Offset;
293 Destination = Configure->FrameBuffer + Offset;
294
295 if (UseWideFill && (((UINTN) Destination & 7) == 0)) {
296 DEBUG ((EFI_D_VERBOSE, "VideoFill (wide)\n"));
297 SizeInBytes = WidthInBytes;
298 if (SizeInBytes >= 8) {
299 SetMem64 (Destination, SizeInBytes & ~7, WideFill);
300 SizeInBytes &= 7;
301 }
302 if (SizeInBytes > 0) {
303 CopyMem (Destination, &WideFill, SizeInBytes);
304 }
305 } else {
306 DEBUG ((EFI_D_VERBOSE, "VideoFill (not wide)\n"));
307 if (!LineBufferReady) {
308 CopyMem (Configure->LineBuffer, &WideFill, Configure->BytesPerPixel);
309 for (IndexX = 1; IndexX < Width; ) {
310 CopyMem (
311 (Configure->LineBuffer + (IndexX * Configure->BytesPerPixel)),
312 Configure->LineBuffer,
313 MIN (IndexX, Width - IndexX) * Configure->BytesPerPixel
314 );
315 IndexX += MIN (IndexX, Width - IndexX);
316 }
317 LineBufferReady = TRUE;
318 }
319 CopyMem (Destination, Configure->LineBuffer, WidthInBytes);
320 }
321 }
322 }
323
324 return RETURN_SUCCESS;
325 }
326
327 /**
328 Performs a UEFI Graphics Output Protocol Blt Video to Buffer operation
329 with extended parameters.
330
331 @param[in] Configure Pointer to a configuration which was successfully
332 created by FrameBufferBltConfigure ().
333 @param[out] BltBuffer Output buffer for pixel color data.
334 @param[in] SourceX X location within video.
335 @param[in] SourceY Y location within video.
336 @param[in] DestinationX X location within BltBuffer.
337 @param[in] DestinationY Y location within BltBuffer.
338 @param[in] Width Width (in pixels).
339 @param[in] Height Height.
340 @param[in] Delta Number of bytes in a row of BltBuffer.
341
342 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
343 @retval RETURN_SUCCESS The Blt operation was performed successfully.
344 **/
345 RETURN_STATUS
346 FrameBufferBltLibVideoToBltBuffer (
347 IN FRAME_BUFFER_CONFIGURE *Configure,
348 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
349 IN UINTN SourceX,
350 IN UINTN SourceY,
351 IN UINTN DestinationX,
352 IN UINTN DestinationY,
353 IN UINTN Width,
354 IN UINTN Height,
355 IN UINTN Delta
356 )
357 {
358 UINTN DstY;
359 UINTN SrcY;
360 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
361 UINT8 *Source;
362 UINT8 *Destination;
363 UINTN IndexX;
364 UINT32 Uint32;
365 UINTN Offset;
366 UINTN WidthInBytes;
367
368 //
369 // Video to BltBuffer: Source is Video, destination is BltBuffer
370 //
371 if (SourceY + Height > Configure->Height) {
372 return RETURN_INVALID_PARAMETER;
373 }
374
375 if (SourceX + Width > Configure->Width) {
376 return RETURN_INVALID_PARAMETER;
377 }
378
379 if (Width == 0 || Height == 0) {
380 return RETURN_INVALID_PARAMETER;
381 }
382
383 //
384 // If Delta is zero, then the entire BltBuffer is being used, so Delta is
385 // the number of bytes in each row of BltBuffer. Since BltBuffer is Width
386 // pixels size, the number of bytes in each row can be computed.
387 //
388 if (Delta == 0) {
389 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
390 }
391
392 WidthInBytes = Width * Configure->BytesPerPixel;
393
394 //
395 // Video to BltBuffer: Source is Video, destination is BltBuffer
396 //
397 for (SrcY = SourceY, DstY = DestinationY;
398 DstY < (Height + DestinationY);
399 SrcY++, DstY++) {
400
401 Offset = (SrcY * Configure->PixelsPerScanLine) + SourceX;
402 Offset = Configure->BytesPerPixel * Offset;
403 Source = Configure->FrameBuffer + Offset;
404
405 if (Configure->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
406 Destination = (UINT8 *) BltBuffer + (DstY * Delta) + (DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
407 } else {
408 Destination = Configure->LineBuffer;
409 }
410
411 CopyMem (Destination, Source, WidthInBytes);
412
413 if (Configure->PixelFormat != PixelBlueGreenRedReserved8BitPerColor) {
414 for (IndexX = 0; IndexX < Width; IndexX++) {
415 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)
416 ((UINT8 *) BltBuffer + (DstY * Delta) +
417 (DestinationX + IndexX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
418 Uint32 = *(UINT32*) (Configure->LineBuffer + (IndexX * Configure->BytesPerPixel));
419 *(UINT32*) Blt =
420 (UINT32) (
421 (((Uint32 & Configure->PixelMasks.RedMask) >>
422 Configure->PixelShl[0]) << Configure->PixelShr[0]) |
423 (((Uint32 & Configure->PixelMasks.GreenMask) >>
424 Configure->PixelShl[1]) << Configure->PixelShr[1]) |
425 (((Uint32 & Configure->PixelMasks.BlueMask) >>
426 Configure->PixelShl[2]) << Configure->PixelShr[2])
427 );
428 }
429 }
430 }
431
432 return RETURN_SUCCESS;
433 }
434
435 /**
436 Performs a UEFI Graphics Output Protocol Blt Buffer to Video operation
437 with extended parameters.
438
439 @param[in] Configure Pointer to a configuration which was successfully
440 created by FrameBufferBltConfigure ().
441 @param[in] BltBuffer Output buffer for pixel color data.
442 @param[in] SourceX X location within BltBuffer.
443 @param[in] SourceY Y location within BltBuffer.
444 @param[in] DestinationX X location within video.
445 @param[in] DestinationY Y location within video.
446 @param[in] Width Width (in pixels).
447 @param[in] Height Height.
448 @param[in] Delta Number of bytes in a row of BltBuffer.
449
450 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
451 @retval RETURN_SUCCESS The Blt operation was performed successfully.
452 **/
453 RETURN_STATUS
454 FrameBufferBltLibBufferToVideo (
455 IN FRAME_BUFFER_CONFIGURE *Configure,
456 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
457 IN UINTN SourceX,
458 IN UINTN SourceY,
459 IN UINTN DestinationX,
460 IN UINTN DestinationY,
461 IN UINTN Width,
462 IN UINTN Height,
463 IN UINTN Delta
464 )
465 {
466 UINTN DstY;
467 UINTN SrcY;
468 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
469 UINT8 *Source;
470 UINT8 *Destination;
471 UINTN IndexX;
472 UINT32 Uint32;
473 UINTN Offset;
474 UINTN WidthInBytes;
475
476 //
477 // BltBuffer to Video: Source is BltBuffer, destination is Video
478 //
479 if (DestinationY + Height > Configure->Height) {
480 return RETURN_INVALID_PARAMETER;
481 }
482
483 if (DestinationX + Width > Configure->Width) {
484 return RETURN_INVALID_PARAMETER;
485 }
486
487 if (Width == 0 || Height == 0) {
488 return RETURN_INVALID_PARAMETER;
489 }
490
491 //
492 // If Delta is zero, then the entire BltBuffer is being used, so Delta is
493 // the number of bytes in each row of BltBuffer. Since BltBuffer is Width
494 // pixels size, the number of bytes in each row can be computed.
495 //
496 if (Delta == 0) {
497 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
498 }
499
500 WidthInBytes = Width * Configure->BytesPerPixel;
501
502 for (SrcY = SourceY, DstY = DestinationY;
503 SrcY < (Height + SourceY);
504 SrcY++, DstY++) {
505
506 Offset = (DstY * Configure->PixelsPerScanLine) + DestinationX;
507 Offset = Configure->BytesPerPixel * Offset;
508 Destination = Configure->FrameBuffer + Offset;
509
510 if (Configure->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
511 Source = (UINT8 *) BltBuffer + (SrcY * Delta);
512 } else {
513 for (IndexX = 0; IndexX < Width; IndexX++) {
514 Blt =
515 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (
516 (UINT8 *) BltBuffer +
517 (SrcY * Delta) +
518 ((SourceX + IndexX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))
519 );
520 Uint32 = *(UINT32*) Blt;
521 *(UINT32*) (Configure->LineBuffer + (IndexX * Configure->BytesPerPixel)) =
522 (UINT32) (
523 (((Uint32 << Configure->PixelShl[0]) >> Configure->PixelShr[0]) &
524 Configure->PixelMasks.RedMask) |
525 (((Uint32 << Configure->PixelShl[1]) >> Configure->PixelShr[1]) &
526 Configure->PixelMasks.GreenMask) |
527 (((Uint32 << Configure->PixelShl[2]) >> Configure->PixelShr[2]) &
528 Configure->PixelMasks.BlueMask)
529 );
530 }
531 Source = Configure->LineBuffer;
532 }
533
534 CopyMem (Destination, Source, WidthInBytes);
535 }
536
537 return RETURN_SUCCESS;
538 }
539
540 /**
541 Performs a UEFI Graphics Output Protocol Blt Video to Video operation
542
543 @param[in] Configure Pointer to a configuration which was successfully
544 created by FrameBufferBltConfigure ().
545 @param[in] SourceX X location within video.
546 @param[in] SourceY Y location within video.
547 @param[in] DestinationX X location within video.
548 @param[in] DestinationY Y location within video.
549 @param[in] Width Width (in pixels).
550 @param[in] Height Height.
551
552 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
553 @retval RETURN_SUCCESS The Blt operation was performed successfully.
554 **/
555 RETURN_STATUS
556 FrameBufferBltLibVideoToVideo (
557 IN FRAME_BUFFER_CONFIGURE *Configure,
558 IN UINTN SourceX,
559 IN UINTN SourceY,
560 IN UINTN DestinationX,
561 IN UINTN DestinationY,
562 IN UINTN Width,
563 IN UINTN Height
564 )
565 {
566 UINT8 *Source;
567 UINT8 *Destination;
568 UINTN Offset;
569 UINTN WidthInBytes;
570 INTN LineStride;
571
572 //
573 // Video to Video: Source is Video, destination is Video
574 //
575 if (SourceY + Height > Configure->Height) {
576 return RETURN_INVALID_PARAMETER;
577 }
578
579 if (SourceX + Width > Configure->Width) {
580 return RETURN_INVALID_PARAMETER;
581 }
582
583 if (DestinationY + Height > Configure->Height) {
584 return RETURN_INVALID_PARAMETER;
585 }
586
587 if (DestinationX + Width > Configure->Width) {
588 return RETURN_INVALID_PARAMETER;
589 }
590
591 if (Width == 0 || Height == 0) {
592 return RETURN_INVALID_PARAMETER;
593 }
594
595 WidthInBytes = Width * Configure->BytesPerPixel;
596
597 Offset = (SourceY * Configure->PixelsPerScanLine) + SourceX;
598 Offset = Configure->BytesPerPixel * Offset;
599 Source = Configure->FrameBuffer + Offset;
600
601 Offset = (DestinationY * Configure->PixelsPerScanLine) + DestinationX;
602 Offset = Configure->BytesPerPixel * Offset;
603 Destination = Configure->FrameBuffer + Offset;
604
605 LineStride = Configure->BytesPerPixel * Configure->PixelsPerScanLine;
606 if (Destination > Source) {
607 //
608 // Copy from last line to avoid source is corrupted by copying
609 //
610 Source += Height * LineStride;
611 Destination += Height * LineStride;
612 LineStride = -LineStride;
613 }
614
615 while (Height-- > 0) {
616 CopyMem (Destination, Source, WidthInBytes);
617
618 Source += LineStride;
619 Destination += LineStride;
620 }
621
622 return RETURN_SUCCESS;
623 }
624
625 /**
626 Performs a UEFI Graphics Output Protocol Blt operation.
627
628 @param[in] Configure Pointer to a configuration which was successfully
629 created by FrameBufferBltConfigure ().
630 @param[in,out] BltBuffer The data to transfer to screen.
631 @param[in] BltOperation The operation to perform.
632 @param[in] SourceX The X coordinate of the source for BltOperation.
633 @param[in] SourceY The Y coordinate of the source for BltOperation.
634 @param[in] DestinationX The X coordinate of the destination for
635 BltOperation.
636 @param[in] DestinationY The Y coordinate of the destination for
637 BltOperation.
638 @param[in] Width The width of a rectangle in the blt rectangle
639 in pixels.
640 @param[in] Height The height of a rectangle in the blt rectangle
641 in pixels.
642 @param[in] Delta Not used for EfiBltVideoFill and
643 EfiBltVideoToVideo operation. If a Delta of 0
644 is used, the entire BltBuffer will be operated
645 on. If a subrectangle of the BltBuffer is
646 used, then Delta represents the number of
647 bytes in a row of the BltBuffer.
648
649 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.
650 @retval RETURN_SUCCESS The Blt operation was performed successfully.
651 **/
652 RETURN_STATUS
653 EFIAPI
654 FrameBufferBlt (
655 IN FRAME_BUFFER_CONFIGURE *Configure,
656 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
657 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
658 IN UINTN SourceX,
659 IN UINTN SourceY,
660 IN UINTN DestinationX,
661 IN UINTN DestinationY,
662 IN UINTN Width,
663 IN UINTN Height,
664 IN UINTN Delta
665 )
666 {
667 if (Configure == NULL) {
668 return RETURN_INVALID_PARAMETER;
669 }
670
671 switch (BltOperation) {
672 case EfiBltVideoToBltBuffer:
673 return FrameBufferBltLibVideoToBltBuffer (
674 Configure,
675 BltBuffer,
676 SourceX,
677 SourceY,
678 DestinationX,
679 DestinationY,
680 Width,
681 Height,
682 Delta
683 );
684
685 case EfiBltVideoToVideo:
686 return FrameBufferBltLibVideoToVideo (
687 Configure,
688 SourceX,
689 SourceY,
690 DestinationX,
691 DestinationY,
692 Width,
693 Height
694 );
695
696 case EfiBltVideoFill:
697 return FrameBufferBltLibVideoFill (
698 Configure,
699 BltBuffer,
700 DestinationX,
701 DestinationY,
702 Width,
703 Height
704 );
705
706 case EfiBltBufferToVideo:
707 return FrameBufferBltLibBufferToVideo (
708 Configure,
709 BltBuffer,
710 SourceX,
711 SourceY,
712 DestinationX,
713 DestinationY,
714 Width,
715 Height,
716 Delta
717 );
718
719 default:
720 return RETURN_INVALID_PARAMETER;
721 }
722 }