]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.c
MdeModulePkg/FrameBufferBltLib: Fix copying of unaligned memory
[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
0e58b55a 283 Destination += SizeInBytes & ~3;\r
b1ca3860
RN
284 SizeInBytes &= 3;\r
285 }\r
286 if (SizeInBytes > 0) {\r
287 SetMem (Destination, SizeInBytes, (UINT8) (UINTN) WideFill);\r
288 }\r
289 } else {\r
290 LineBufferReady = FALSE;\r
291 for (IndexY = DestinationY; IndexY < (Height + DestinationY); IndexY++) {\r
5ae07233 292 Offset = (IndexY * Configure->PixelsPerScanLine) + DestinationX;\r
b1ca3860
RN
293 Offset = Configure->BytesPerPixel * Offset;\r
294 Destination = Configure->FrameBuffer + Offset;\r
295\r
296 if (UseWideFill && (((UINTN) Destination & 7) == 0)) {\r
297 DEBUG ((EFI_D_VERBOSE, "VideoFill (wide)\n"));\r
298 SizeInBytes = WidthInBytes;\r
299 if (SizeInBytes >= 8) {\r
300 SetMem64 (Destination, SizeInBytes & ~7, WideFill);\r
0e58b55a 301 Destination += SizeInBytes & ~7;\r
b1ca3860
RN
302 SizeInBytes &= 7;\r
303 }\r
304 if (SizeInBytes > 0) {\r
305 CopyMem (Destination, &WideFill, SizeInBytes);\r
306 }\r
307 } else {\r
308 DEBUG ((EFI_D_VERBOSE, "VideoFill (not wide)\n"));\r
309 if (!LineBufferReady) {\r
310 CopyMem (Configure->LineBuffer, &WideFill, Configure->BytesPerPixel);\r
311 for (IndexX = 1; IndexX < Width; ) {\r
312 CopyMem (\r
313 (Configure->LineBuffer + (IndexX * Configure->BytesPerPixel)),\r
314 Configure->LineBuffer,\r
315 MIN (IndexX, Width - IndexX) * Configure->BytesPerPixel\r
316 );\r
317 IndexX += MIN (IndexX, Width - IndexX);\r
318 }\r
319 LineBufferReady = TRUE;\r
320 }\r
321 CopyMem (Destination, Configure->LineBuffer, WidthInBytes);\r
322 }\r
323 }\r
324 }\r
325\r
326 return RETURN_SUCCESS;\r
327}\r
328\r
329/**\r
330 Performs a UEFI Graphics Output Protocol Blt Video to Buffer operation\r
331 with extended parameters.\r
332\r
333 @param[in] Configure Pointer to a configuration which was successfully\r
334 created by FrameBufferBltConfigure ().\r
335 @param[out] BltBuffer Output buffer for pixel color data.\r
336 @param[in] SourceX X location within video.\r
337 @param[in] SourceY Y location within video.\r
338 @param[in] DestinationX X location within BltBuffer.\r
339 @param[in] DestinationY Y location within BltBuffer.\r
340 @param[in] Width Width (in pixels).\r
341 @param[in] Height Height.\r
342 @param[in] Delta Number of bytes in a row of BltBuffer.\r
343\r
344 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.\r
345 @retval RETURN_SUCCESS The Blt operation was performed successfully.\r
346**/\r
347RETURN_STATUS\r
348FrameBufferBltLibVideoToBltBuffer (\r
349 IN FRAME_BUFFER_CONFIGURE *Configure,\r
350 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,\r
351 IN UINTN SourceX,\r
352 IN UINTN SourceY,\r
353 IN UINTN DestinationX,\r
354 IN UINTN DestinationY,\r
355 IN UINTN Width,\r
356 IN UINTN Height,\r
357 IN UINTN Delta\r
358 )\r
359{\r
360 UINTN DstY;\r
361 UINTN SrcY;\r
362 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
363 UINT8 *Source;\r
364 UINT8 *Destination;\r
365 UINTN IndexX;\r
366 UINT32 Uint32;\r
367 UINTN Offset;\r
368 UINTN WidthInBytes;\r
369\r
370 //\r
371 // Video to BltBuffer: Source is Video, destination is BltBuffer\r
372 //\r
373 if (SourceY + Height > Configure->Height) {\r
374 return RETURN_INVALID_PARAMETER;\r
375 }\r
376\r
5ae07233 377 if (SourceX + Width > Configure->Width) {\r
b1ca3860
RN
378 return RETURN_INVALID_PARAMETER;\r
379 }\r
380\r
381 if (Width == 0 || Height == 0) {\r
382 return RETURN_INVALID_PARAMETER;\r
383 }\r
384\r
385 //\r
386 // If Delta is zero, then the entire BltBuffer is being used, so Delta is\r
387 // the number of bytes in each row of BltBuffer. Since BltBuffer is Width\r
388 // pixels size, the number of bytes in each row can be computed.\r
389 //\r
390 if (Delta == 0) {\r
391 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
392 }\r
393\r
394 WidthInBytes = Width * Configure->BytesPerPixel;\r
395\r
396 //\r
397 // Video to BltBuffer: Source is Video, destination is BltBuffer\r
398 //\r
399 for (SrcY = SourceY, DstY = DestinationY;\r
400 DstY < (Height + DestinationY);\r
401 SrcY++, DstY++) {\r
402\r
5ae07233 403 Offset = (SrcY * Configure->PixelsPerScanLine) + SourceX;\r
b1ca3860
RN
404 Offset = Configure->BytesPerPixel * Offset;\r
405 Source = Configure->FrameBuffer + Offset;\r
406\r
407 if (Configure->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {\r
408 Destination = (UINT8 *) BltBuffer + (DstY * Delta) + (DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
409 } else {\r
410 Destination = Configure->LineBuffer;\r
411 }\r
412\r
413 CopyMem (Destination, Source, WidthInBytes);\r
414\r
415 if (Configure->PixelFormat != PixelBlueGreenRedReserved8BitPerColor) {\r
416 for (IndexX = 0; IndexX < Width; IndexX++) {\r
417 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)\r
418 ((UINT8 *) BltBuffer + (DstY * Delta) +\r
419 (DestinationX + IndexX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
420 Uint32 = *(UINT32*) (Configure->LineBuffer + (IndexX * Configure->BytesPerPixel));\r
421 *(UINT32*) Blt =\r
422 (UINT32) (\r
423 (((Uint32 & Configure->PixelMasks.RedMask) >>\r
424 Configure->PixelShl[0]) << Configure->PixelShr[0]) |\r
425 (((Uint32 & Configure->PixelMasks.GreenMask) >>\r
426 Configure->PixelShl[1]) << Configure->PixelShr[1]) |\r
427 (((Uint32 & Configure->PixelMasks.BlueMask) >>\r
428 Configure->PixelShl[2]) << Configure->PixelShr[2])\r
429 );\r
430 }\r
431 }\r
432 }\r
433\r
434 return RETURN_SUCCESS;\r
435}\r
436\r
437/**\r
438 Performs a UEFI Graphics Output Protocol Blt Buffer to Video operation\r
439 with extended parameters.\r
440\r
441 @param[in] Configure Pointer to a configuration which was successfully\r
442 created by FrameBufferBltConfigure ().\r
443 @param[in] BltBuffer Output buffer for pixel color data.\r
444 @param[in] SourceX X location within BltBuffer.\r
445 @param[in] SourceY Y location within BltBuffer.\r
446 @param[in] DestinationX X location within video.\r
447 @param[in] DestinationY Y location within video.\r
448 @param[in] Width Width (in pixels).\r
449 @param[in] Height Height.\r
450 @param[in] Delta Number of bytes in a row of BltBuffer.\r
451\r
452 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.\r
453 @retval RETURN_SUCCESS The Blt operation was performed successfully.\r
454**/\r
455RETURN_STATUS\r
456FrameBufferBltLibBufferToVideo (\r
457 IN FRAME_BUFFER_CONFIGURE *Configure,\r
458 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,\r
459 IN UINTN SourceX,\r
460 IN UINTN SourceY,\r
461 IN UINTN DestinationX,\r
462 IN UINTN DestinationY,\r
463 IN UINTN Width,\r
464 IN UINTN Height,\r
465 IN UINTN Delta\r
466 )\r
467{\r
468 UINTN DstY;\r
469 UINTN SrcY;\r
470 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
471 UINT8 *Source;\r
472 UINT8 *Destination;\r
473 UINTN IndexX;\r
474 UINT32 Uint32;\r
475 UINTN Offset;\r
476 UINTN WidthInBytes;\r
477\r
478 //\r
479 // BltBuffer to Video: Source is BltBuffer, destination is Video\r
480 //\r
481 if (DestinationY + Height > Configure->Height) {\r
482 return RETURN_INVALID_PARAMETER;\r
483 }\r
484\r
5ae07233 485 if (DestinationX + Width > Configure->Width) {\r
b1ca3860
RN
486 return RETURN_INVALID_PARAMETER;\r
487 }\r
488\r
489 if (Width == 0 || Height == 0) {\r
490 return RETURN_INVALID_PARAMETER;\r
491 }\r
492\r
493 //\r
494 // If Delta is zero, then the entire BltBuffer is being used, so Delta is\r
495 // the number of bytes in each row of BltBuffer. Since BltBuffer is Width\r
496 // pixels size, the number of bytes in each row can be computed.\r
497 //\r
498 if (Delta == 0) {\r
499 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
500 }\r
501\r
502 WidthInBytes = Width * Configure->BytesPerPixel;\r
503\r
504 for (SrcY = SourceY, DstY = DestinationY;\r
505 SrcY < (Height + SourceY);\r
506 SrcY++, DstY++) {\r
507\r
5ae07233 508 Offset = (DstY * Configure->PixelsPerScanLine) + DestinationX;\r
b1ca3860
RN
509 Offset = Configure->BytesPerPixel * Offset;\r
510 Destination = Configure->FrameBuffer + Offset;\r
511\r
512 if (Configure->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {\r
513 Source = (UINT8 *) BltBuffer + (SrcY * Delta);\r
514 } else {\r
515 for (IndexX = 0; IndexX < Width; IndexX++) {\r
516 Blt =\r
517 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (\r
518 (UINT8 *) BltBuffer +\r
519 (SrcY * Delta) +\r
520 ((SourceX + IndexX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))\r
521 );\r
522 Uint32 = *(UINT32*) Blt;\r
523 *(UINT32*) (Configure->LineBuffer + (IndexX * Configure->BytesPerPixel)) =\r
524 (UINT32) (\r
525 (((Uint32 << Configure->PixelShl[0]) >> Configure->PixelShr[0]) &\r
526 Configure->PixelMasks.RedMask) |\r
527 (((Uint32 << Configure->PixelShl[1]) >> Configure->PixelShr[1]) &\r
528 Configure->PixelMasks.GreenMask) |\r
529 (((Uint32 << Configure->PixelShl[2]) >> Configure->PixelShr[2]) &\r
530 Configure->PixelMasks.BlueMask)\r
531 );\r
532 }\r
533 Source = Configure->LineBuffer;\r
534 }\r
535\r
536 CopyMem (Destination, Source, WidthInBytes);\r
537 }\r
538\r
539 return RETURN_SUCCESS;\r
540}\r
541\r
542/**\r
543 Performs a UEFI Graphics Output Protocol Blt Video to Video operation\r
544\r
545 @param[in] Configure Pointer to a configuration which was successfully\r
546 created by FrameBufferBltConfigure ().\r
547 @param[in] SourceX X location within video.\r
548 @param[in] SourceY Y location within video.\r
549 @param[in] DestinationX X location within video.\r
550 @param[in] DestinationY Y location within video.\r
551 @param[in] Width Width (in pixels).\r
552 @param[in] Height Height.\r
553\r
554 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.\r
555 @retval RETURN_SUCCESS The Blt operation was performed successfully.\r
556**/\r
557RETURN_STATUS\r
558FrameBufferBltLibVideoToVideo (\r
559 IN FRAME_BUFFER_CONFIGURE *Configure,\r
560 IN UINTN SourceX,\r
561 IN UINTN SourceY,\r
562 IN UINTN DestinationX,\r
563 IN UINTN DestinationY,\r
564 IN UINTN Width,\r
565 IN UINTN Height\r
566 )\r
567{\r
568 UINT8 *Source;\r
569 UINT8 *Destination;\r
570 UINTN Offset;\r
571 UINTN WidthInBytes;\r
572 INTN LineStride;\r
573\r
574 //\r
575 // Video to Video: Source is Video, destination is Video\r
576 //\r
577 if (SourceY + Height > Configure->Height) {\r
578 return RETURN_INVALID_PARAMETER;\r
579 }\r
580\r
5ae07233 581 if (SourceX + Width > Configure->Width) {\r
b1ca3860
RN
582 return RETURN_INVALID_PARAMETER;\r
583 }\r
584\r
585 if (DestinationY + Height > Configure->Height) {\r
586 return RETURN_INVALID_PARAMETER;\r
587 }\r
588\r
5ae07233 589 if (DestinationX + Width > Configure->Width) {\r
b1ca3860
RN
590 return RETURN_INVALID_PARAMETER;\r
591 }\r
592\r
593 if (Width == 0 || Height == 0) {\r
594 return RETURN_INVALID_PARAMETER;\r
595 }\r
596\r
597 WidthInBytes = Width * Configure->BytesPerPixel;\r
598\r
5ae07233 599 Offset = (SourceY * Configure->PixelsPerScanLine) + SourceX;\r
b1ca3860
RN
600 Offset = Configure->BytesPerPixel * Offset;\r
601 Source = Configure->FrameBuffer + Offset;\r
602\r
5ae07233 603 Offset = (DestinationY * Configure->PixelsPerScanLine) + DestinationX;\r
b1ca3860
RN
604 Offset = Configure->BytesPerPixel * Offset;\r
605 Destination = Configure->FrameBuffer + Offset;\r
606\r
5ae07233 607 LineStride = Configure->BytesPerPixel * Configure->PixelsPerScanLine;\r
b1ca3860
RN
608 if (Destination > Source) {\r
609 //\r
610 // Copy from last line to avoid source is corrupted by copying\r
611 //\r
612 Source += Height * LineStride;\r
613 Destination += Height * LineStride;\r
614 LineStride = -LineStride;\r
615 }\r
616\r
617 while (Height-- > 0) {\r
618 CopyMem (Destination, Source, WidthInBytes);\r
619\r
620 Source += LineStride;\r
621 Destination += LineStride;\r
622 }\r
623\r
624 return RETURN_SUCCESS;\r
625}\r
626\r
627/**\r
628 Performs a UEFI Graphics Output Protocol Blt operation.\r
629\r
630 @param[in] Configure Pointer to a configuration which was successfully\r
631 created by FrameBufferBltConfigure ().\r
632 @param[in,out] BltBuffer The data to transfer to screen.\r
633 @param[in] BltOperation The operation to perform.\r
634 @param[in] SourceX The X coordinate of the source for BltOperation.\r
635 @param[in] SourceY The Y coordinate of the source for BltOperation.\r
636 @param[in] DestinationX The X coordinate of the destination for\r
637 BltOperation.\r
638 @param[in] DestinationY The Y coordinate of the destination for\r
639 BltOperation.\r
640 @param[in] Width The width of a rectangle in the blt rectangle\r
641 in pixels.\r
642 @param[in] Height The height of a rectangle in the blt rectangle\r
643 in pixels.\r
644 @param[in] Delta Not used for EfiBltVideoFill and\r
645 EfiBltVideoToVideo operation. If a Delta of 0\r
646 is used, the entire BltBuffer will be operated\r
647 on. If a subrectangle of the BltBuffer is\r
648 used, then Delta represents the number of\r
649 bytes in a row of the BltBuffer.\r
650\r
651 @retval RETURN_INVALID_PARAMETER Invalid parameter were passed in.\r
652 @retval RETURN_SUCCESS The Blt operation was performed successfully.\r
653**/\r
654RETURN_STATUS\r
655EFIAPI\r
656FrameBufferBlt (\r
657 IN FRAME_BUFFER_CONFIGURE *Configure,\r
658 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
659 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
660 IN UINTN SourceX,\r
661 IN UINTN SourceY,\r
662 IN UINTN DestinationX,\r
663 IN UINTN DestinationY,\r
664 IN UINTN Width,\r
665 IN UINTN Height,\r
666 IN UINTN Delta\r
667 )\r
668{\r
669 if (Configure == NULL) {\r
670 return RETURN_INVALID_PARAMETER;\r
671 }\r
672\r
673 switch (BltOperation) {\r
674 case EfiBltVideoToBltBuffer:\r
675 return FrameBufferBltLibVideoToBltBuffer (\r
676 Configure,\r
677 BltBuffer,\r
678 SourceX,\r
679 SourceY,\r
680 DestinationX,\r
681 DestinationY,\r
682 Width,\r
683 Height,\r
684 Delta\r
685 );\r
686\r
687 case EfiBltVideoToVideo:\r
688 return FrameBufferBltLibVideoToVideo (\r
689 Configure,\r
690 SourceX,\r
691 SourceY,\r
692 DestinationX,\r
693 DestinationY,\r
694 Width,\r
695 Height\r
696 );\r
697\r
698 case EfiBltVideoFill:\r
699 return FrameBufferBltLibVideoFill (\r
700 Configure,\r
701 BltBuffer,\r
702 DestinationX,\r
703 DestinationY,\r
704 Width,\r
705 Height\r
706 );\r
707\r
708 case EfiBltBufferToVideo:\r
709 return FrameBufferBltLibBufferToVideo (\r
710 Configure,\r
711 BltBuffer,\r
712 SourceX,\r
713 SourceY,\r
714 DestinationX,\r
715 DestinationY,\r
716 Width,\r
717 Height,\r
718 Delta\r
719 );\r
720\r
721 default:\r
722 return RETURN_INVALID_PARAMETER;\r
723 }\r
724}\r