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