]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputBlt.c
ArmPlatformPkg: Fix Ecc error 5007 in LcdGraphicsOutputDxe
[mirror_edk2.git] / ArmPlatformPkg / Drivers / LcdGraphicsOutputDxe / LcdGraphicsOutputBlt.c
CommitLineData
1e57a462 1/** @file\r
2\r
eb97f138 3 Copyright (c) 2011 - 2020, Arm Limited. All rights reserved.<BR>\r
f4dfad05 4 SPDX-License-Identifier: BSD-2-Clause-Patent\r
1e57a462 5\r
6 **/\r
7\r
8#include <PiDxe.h>\r
9#include <Library/BaseMemoryLib.h>\r
10#include <Library/DevicePathLib.h>\r
11#include <Library/UefiBootServicesTableLib.h>\r
12#include <Library/UefiRuntimeServicesTableLib.h>\r
13#include <Library/MemoryAllocationLib.h>\r
14\r
15#include <Guid/GlobalVariable.h>\r
16\r
17#include "LcdGraphicsOutputDxe.h"\r
18\r
19extern BOOLEAN mDisplayInitialized;\r
20\r
21//\r
22// Function Definitions\r
23//\r
24\r
25STATIC\r
26EFI_STATUS\r
27VideoCopyNoHorizontalOverlap (\r
28 IN UINTN BitsPerPixel,\r
29 IN volatile VOID *FrameBufferBase,\r
30 IN UINT32 HorizontalResolution,\r
31 IN UINTN SourceX,\r
32 IN UINTN SourceY,\r
33 IN UINTN DestinationX,\r
34 IN UINTN DestinationY,\r
35 IN UINTN Width,\r
36 IN UINTN Height\r
37)\r
38{\r
eb97f138 39 EFI_STATUS Status;\r
1e57a462 40 UINTN SourceLine;\r
41 UINTN DestinationLine;\r
42 UINTN WidthInBytes;\r
43 UINTN LineCount;\r
44 INTN Step;\r
45 VOID *SourceAddr;\r
46 VOID *DestinationAddr;\r
47\r
eb97f138
PG
48 Status = EFI_SUCCESS;\r
49\r
1e57a462 50 if( DestinationY <= SourceY ) {\r
51 // scrolling up (or horizontally but without overlap)\r
52 SourceLine = SourceY;\r
53 DestinationLine = DestinationY;\r
54 Step = 1;\r
55 } else {\r
56 // scrolling down\r
57 SourceLine = SourceY + Height;\r
58 DestinationLine = DestinationY + Height;\r
59 Step = -1;\r
60 }\r
61\r
62 switch (BitsPerPixel) {\r
63\r
64 case LCD_BITS_PER_PIXEL_24:\r
65\r
66 WidthInBytes = Width * 4;\r
67\r
68 for( LineCount = 0; LineCount < Height; LineCount++ ) {\r
69 // Update the start addresses of source & destination using 32bit pointer arithmetic\r
70 SourceAddr = (VOID *)((UINT32 *)FrameBufferBase + SourceLine * HorizontalResolution + SourceX );\r
71 DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);\r
72\r
73 // Copy the entire line Y from video ram to the temp buffer\r
74 CopyMem( DestinationAddr, SourceAddr, WidthInBytes);\r
75\r
76 // Update the line numbers\r
77 SourceLine += Step;\r
78 DestinationLine += Step;\r
79 }\r
80 break;\r
81\r
82 case LCD_BITS_PER_PIXEL_16_555:\r
83 case LCD_BITS_PER_PIXEL_16_565:\r
84 case LCD_BITS_PER_PIXEL_12_444:\r
85\r
86 WidthInBytes = Width * 2;\r
87\r
88 for( LineCount = 0; LineCount < Height; LineCount++ ) {\r
89 // Update the start addresses of source & destination using 16bit pointer arithmetic\r
90 SourceAddr = (VOID *)((UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourceX );\r
91 DestinationAddr = (VOID *)((UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);\r
92\r
93 // Copy the entire line Y from video ram to the temp buffer\r
94 CopyMem( DestinationAddr, SourceAddr, WidthInBytes);\r
95\r
96 // Update the line numbers\r
97 SourceLine += Step;\r
98 DestinationLine += Step;\r
99 }\r
100 break;\r
101\r
102 case LCD_BITS_PER_PIXEL_8:\r
103 case LCD_BITS_PER_PIXEL_4:\r
104 case LCD_BITS_PER_PIXEL_2:\r
105 case LCD_BITS_PER_PIXEL_1:\r
106 default:\r
107 // Can't handle this case\r
108 DEBUG((DEBUG_ERROR, "ArmVeGraphics_Blt: EfiBltVideoToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));\r
109 Status = EFI_INVALID_PARAMETER;\r
110 goto EXIT;\r
111 // break;\r
112\r
113 }\r
114\r
115 EXIT:\r
116 return Status;\r
117}\r
118\r
119STATIC\r
120EFI_STATUS\r
121VideoCopyHorizontalOverlap (\r
122 IN UINTN BitsPerPixel,\r
123 IN volatile VOID *FrameBufferBase,\r
124 UINT32 HorizontalResolution,\r
125 IN UINTN SourceX,\r
126 IN UINTN SourceY,\r
127 IN UINTN DestinationX,\r
128 IN UINTN DestinationY,\r
129 IN UINTN Width,\r
130 IN UINTN Height\r
131)\r
132{\r
eb97f138 133 EFI_STATUS Status;\r
1e57a462 134\r
135 UINT32 *PixelBuffer32bit;\r
136 UINT32 *SourcePixel32bit;\r
137 UINT32 *DestinationPixel32bit;\r
138\r
139 UINT16 *PixelBuffer16bit;\r
140 UINT16 *SourcePixel16bit;\r
141 UINT16 *DestinationPixel16bit;\r
142\r
143 UINT32 SourcePixelY;\r
144 UINT32 DestinationPixelY;\r
145 UINTN SizeIn32Bits;\r
146 UINTN SizeIn16Bits;\r
147\r
eb97f138
PG
148 Status = EFI_SUCCESS;\r
149\r
1e57a462 150 switch (BitsPerPixel) {\r
151\r
152 case LCD_BITS_PER_PIXEL_24:\r
153 // Allocate a temporary buffer\r
154\r
155 PixelBuffer32bit = (UINT32 *) AllocatePool((Height * Width) * sizeof(UINT32));\r
156\r
157 if (PixelBuffer32bit == NULL) {\r
158 Status = EFI_OUT_OF_RESOURCES;\r
159 goto EXIT;\r
160 }\r
161\r
162 SizeIn32Bits = Width * 4;\r
163\r
164 // Copy from the video ram (source region) to a temp buffer\r
165 for (SourcePixelY = SourceY, DestinationPixel32bit = PixelBuffer32bit;\r
166 SourcePixelY < SourceY + Height;\r
167 SourcePixelY++, DestinationPixel32bit += Width)\r
168 {\r
169 // Update the start address of line Y (source)\r
170 SourcePixel32bit = (UINT32 *)FrameBufferBase + SourcePixelY * HorizontalResolution + SourceX;\r
171\r
172 // Copy the entire line Y from video ram to the temp buffer\r
173 CopyMem( (VOID *)DestinationPixel32bit, (CONST VOID *)SourcePixel32bit, SizeIn32Bits);\r
174 }\r
175\r
176 // Copy from the temp buffer to the video ram (destination region)\r
177 for (DestinationPixelY = DestinationY, SourcePixel32bit = PixelBuffer32bit;\r
178 DestinationPixelY < DestinationY + Height;\r
179 DestinationPixelY++, SourcePixel32bit += Width)\r
180 {\r
181 // Update the start address of line Y (target)\r
182 DestinationPixel32bit = (UINT32 *)FrameBufferBase + DestinationPixelY * HorizontalResolution + DestinationX;\r
183\r
184 // Copy the entire line Y from the temp buffer to video ram\r
185 CopyMem( (VOID *)DestinationPixel32bit, (CONST VOID *)SourcePixel32bit, SizeIn32Bits);\r
186 }\r
187\r
188 // Free up the allocated memory\r
189 FreePool((VOID *) PixelBuffer32bit);\r
190\r
191 break;\r
192\r
193\r
194 case LCD_BITS_PER_PIXEL_16_555:\r
195 case LCD_BITS_PER_PIXEL_16_565:\r
196 case LCD_BITS_PER_PIXEL_12_444:\r
197 // Allocate a temporary buffer\r
198 PixelBuffer16bit = (UINT16 *) AllocatePool((Height * Width) * sizeof(UINT16));\r
199\r
200 if (PixelBuffer16bit == NULL) {\r
201 Status = EFI_OUT_OF_RESOURCES;\r
202 goto EXIT;\r
203 }\r
204\r
205 // Access each pixel inside the source area of the Video Memory and copy it to the temp buffer\r
206\r
207 SizeIn16Bits = Width * 2;\r
208\r
209 for (SourcePixelY = SourceY, DestinationPixel16bit = PixelBuffer16bit;\r
210 SourcePixelY < SourceY + Height;\r
211 SourcePixelY++, DestinationPixel16bit += Width)\r
212 {\r
213 // Calculate the source address:\r
214 SourcePixel16bit = (UINT16 *)FrameBufferBase + SourcePixelY * HorizontalResolution + SourceX;\r
215\r
216 // Copy the entire line Y from Video to the temp buffer\r
217 CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits);\r
218 }\r
219\r
220 // Copy from the temp buffer into the destination area of the Video Memory\r
221\r
222 for (DestinationPixelY = DestinationY, SourcePixel16bit = PixelBuffer16bit;\r
223 DestinationPixelY < DestinationY + Height;\r
224 DestinationPixelY++, SourcePixel16bit += Width)\r
225 {\r
226 // Calculate the target address:\r
227 DestinationPixel16bit = (UINT16 *)FrameBufferBase + (DestinationPixelY * HorizontalResolution + DestinationX);\r
228\r
229 // Copy the entire line Y from the temp buffer to Video\r
230 CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits);\r
231 }\r
232\r
233 // Free the allocated memory\r
234 FreePool((VOID *) PixelBuffer16bit);\r
235\r
236 break;\r
237\r
238\r
239 case LCD_BITS_PER_PIXEL_8:\r
240 case LCD_BITS_PER_PIXEL_4:\r
241 case LCD_BITS_PER_PIXEL_2:\r
242 case LCD_BITS_PER_PIXEL_1:\r
243 default:\r
244 // Can't handle this case\r
245 DEBUG((DEBUG_ERROR, "ArmVeGraphics_Blt: EfiBltVideoToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));\r
246 Status = EFI_INVALID_PARAMETER;\r
247 goto EXIT;\r
248 // break;\r
249\r
250 }\r
251\r
252EXIT:\r
253 return Status;\r
254}\r
255\r
256STATIC\r
257EFI_STATUS\r
258BltVideoFill (\r
259 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
260 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiSourcePixel, OPTIONAL\r
261 IN UINTN SourceX,\r
262 IN UINTN SourceY,\r
263 IN UINTN DestinationX,\r
264 IN UINTN DestinationY,\r
265 IN UINTN Width,\r
266 IN UINTN Height,\r
267 IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer\r
268 )\r
269{\r
270 EFI_PIXEL_BITMASK* PixelInformation;\r
271 EFI_STATUS Status;\r
272 UINT32 HorizontalResolution;\r
273 LCD_BPP BitsPerPixel;\r
274 VOID *FrameBufferBase;\r
275 VOID *DestinationAddr;\r
276 UINT16 *DestinationPixel16bit;\r
277 UINT16 Pixel16bit;\r
278 UINT32 DestinationPixelX;\r
279 UINT32 DestinationLine;\r
280 UINTN WidthInBytes;\r
281\r
282 Status = EFI_SUCCESS;\r
283 PixelInformation = &This->Mode->Info->PixelInformation;\r
284 FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));\r
285 HorizontalResolution = This->Mode->Info->HorizontalResolution;\r
286\r
287 LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);\r
288\r
289 switch (BitsPerPixel) {\r
290 case LCD_BITS_PER_PIXEL_24:\r
291 WidthInBytes = Width * 4;\r
292\r
293 // Copy the SourcePixel into every pixel inside the target rectangle\r
294 for (DestinationLine = DestinationY;\r
295 DestinationLine < DestinationY + Height;\r
296 DestinationLine++)\r
297 {\r
298 // Calculate the target address using 32bit pointer arithmetic:\r
299 DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);\r
300\r
301 // Fill the entire line\r
64669aca 302 SetMem32 (DestinationAddr, WidthInBytes, *((UINT32 *)EfiSourcePixel));\r
1e57a462 303 }\r
304 break;\r
305\r
306 case LCD_BITS_PER_PIXEL_16_555:\r
307 // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel\r
308 Pixel16bit = (UINT16) (\r
309 ( (EfiSourcePixel->Red << 7) & PixelInformation->RedMask )\r
310 | ( (EfiSourcePixel->Green << 2) & PixelInformation->GreenMask )\r
311 | ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask )\r
312// | ( 0 & PixelInformation->ReservedMask )\r
313 );\r
314\r
315 // Copy the SourcePixel into every pixel inside the target rectangle\r
316 for (DestinationLine = DestinationY;\r
317 DestinationLine < DestinationY + Height;\r
318 DestinationLine++)\r
319 {\r
320 for (DestinationPixelX = DestinationX;\r
321 DestinationPixelX < DestinationX + Width;\r
322 DestinationPixelX++)\r
323 {\r
324 // Calculate the target address:\r
325 DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;\r
326\r
327 // Copy the pixel into the new target\r
328 *DestinationPixel16bit = Pixel16bit;\r
329 }\r
330 }\r
331 break;\r
332\r
333 case LCD_BITS_PER_PIXEL_16_565:\r
334 // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel\r
335 Pixel16bit = (UINT16) (\r
336 ( (EfiSourcePixel->Red << 8) & PixelInformation->RedMask )\r
337 | ( (EfiSourcePixel->Green << 3) & PixelInformation->GreenMask )\r
338 | ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask )\r
339 );\r
340\r
341 // Copy the SourcePixel into every pixel inside the target rectangle\r
342 for (DestinationLine = DestinationY;\r
343 DestinationLine < DestinationY + Height;\r
344 DestinationLine++)\r
345 {\r
346 for (DestinationPixelX = DestinationX;\r
347 DestinationPixelX < DestinationX + Width;\r
348 DestinationPixelX++)\r
349 {\r
350 // Calculate the target address:\r
351 DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;\r
352\r
353 // Copy the pixel into the new target\r
354 *DestinationPixel16bit = Pixel16bit;\r
355 }\r
356 }\r
357 break;\r
358\r
359 case LCD_BITS_PER_PIXEL_12_444:\r
360 // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel\r
361 Pixel16bit = (UINT16) (\r
362 ( (EfiSourcePixel->Red >> 4) & PixelInformation->RedMask )\r
363 | ( (EfiSourcePixel->Green ) & PixelInformation->GreenMask )\r
364 | ( (EfiSourcePixel->Blue << 4) & PixelInformation->BlueMask )\r
365 );\r
366\r
367 // Copy the SourcePixel into every pixel inside the target rectangle\r
368 for (DestinationLine = DestinationY;\r
369 DestinationLine < DestinationY + Height;\r
370 DestinationLine++)\r
371 {\r
372 for (DestinationPixelX = DestinationX;\r
373 DestinationPixelX < DestinationX + Width;\r
374 DestinationPixelX++)\r
375 {\r
376 // Calculate the target address:\r
377 DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;\r
378\r
379 // Copy the pixel into the new target\r
380 *DestinationPixel16bit = Pixel16bit;\r
381 }\r
382 }\r
383 break;\r
384\r
385 case LCD_BITS_PER_PIXEL_8:\r
386 case LCD_BITS_PER_PIXEL_4:\r
387 case LCD_BITS_PER_PIXEL_2:\r
388 case LCD_BITS_PER_PIXEL_1:\r
389 default:\r
390 // Can't handle this case\r
391 DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltVideoFill: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));\r
392 Status = EFI_INVALID_PARAMETER;\r
393 break;\r
394 }\r
395\r
396 return Status;\r
397}\r
398\r
399STATIC\r
400EFI_STATUS\r
401BltVideoToBltBuffer (\r
402 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
403 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
404 IN UINTN SourceX,\r
405 IN UINTN SourceY,\r
406 IN UINTN DestinationX,\r
407 IN UINTN DestinationY,\r
408 IN UINTN Width,\r
409 IN UINTN Height,\r
410 IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer\r
411 )\r
412{\r
413 EFI_STATUS Status;\r
414 UINT32 HorizontalResolution;\r
415 LCD_BPP BitsPerPixel;\r
416 EFI_PIXEL_BITMASK *PixelInformation;\r
417 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiDestinationPixel;\r
418 VOID *FrameBufferBase;\r
419 VOID *SourceAddr;\r
420 VOID *DestinationAddr;\r
421 UINT16 *SourcePixel16bit;\r
422 UINT16 Pixel16bit;\r
423 UINT32 SourcePixelX;\r
424 UINT32 SourceLine;\r
425 UINT32 DestinationPixelX;\r
426 UINT32 DestinationLine;\r
427 UINT32 BltBufferHorizontalResolution;\r
428 UINTN WidthInBytes;\r
429\r
430 Status = EFI_SUCCESS;\r
431 PixelInformation = &This->Mode->Info->PixelInformation;\r
432 HorizontalResolution = This->Mode->Info->HorizontalResolution;\r
433 FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));\r
434\r
435 if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {\r
436 // Delta is not zero and it is different from the width.\r
437 // Divide it by the size of a pixel to find out the buffer's horizontal resolution.\r
438 BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
439 } else {\r
440 BltBufferHorizontalResolution = Width;\r
441 }\r
442\r
443 LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);\r
444\r
445 switch (BitsPerPixel) {\r
446 case LCD_BITS_PER_PIXEL_24:\r
447 WidthInBytes = Width * 4;\r
448\r
449 // Access each line inside the Video Memory\r
450 for (SourceLine = SourceY, DestinationLine = DestinationY;\r
451 SourceLine < SourceY + Height;\r
452 SourceLine++, DestinationLine++)\r
453 {\r
454 // Calculate the source and target addresses using 32bit pointer arithmetic:\r
455 SourceAddr = (VOID *)((UINT32 *)FrameBufferBase + SourceLine * HorizontalResolution + SourceX );\r
456 DestinationAddr = (VOID *)((UINT32 *)BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationX);\r
457\r
458 // Copy the entire line\r
459 CopyMem( DestinationAddr, SourceAddr, WidthInBytes);\r
460 }\r
461 break;\r
462\r
463 case LCD_BITS_PER_PIXEL_16_555:\r
464 // Access each pixel inside the Video Memory\r
465 for (SourceLine = SourceY, DestinationLine = DestinationY;\r
466 SourceLine < SourceY + Height;\r
467 SourceLine++, DestinationLine++)\r
468 {\r
469 for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;\r
470 SourcePixelX < SourceX + Width;\r
471 SourcePixelX++, DestinationPixelX++)\r
472 {\r
473 // Calculate the source and target addresses:\r
474 SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;\r
475 EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;\r
476\r
477 // Snapshot the pixel from the video buffer once, to speed up the operation.\r
478 // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.\r
479 Pixel16bit = *SourcePixel16bit;\r
480\r
481 // Copy the pixel into the new target\r
482 EfiDestinationPixel->Red = (UINT8) ( (Pixel16bit & PixelInformation->RedMask ) >> 7 );\r
483 EfiDestinationPixel->Green = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask ) >> 2);\r
484 EfiDestinationPixel->Blue = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask ) << 3 );\r
485 // EfiDestinationPixel->Reserved = (UINT8) 0;\r
486 }\r
487 }\r
488 break;\r
489\r
490 case LCD_BITS_PER_PIXEL_16_565:\r
491 // Access each pixel inside the Video Memory\r
492 for (SourceLine = SourceY, DestinationLine = DestinationY;\r
493 SourceLine < SourceY + Height;\r
494 SourceLine++, DestinationLine++)\r
495 {\r
496 for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;\r
497 SourcePixelX < SourceX + Width;\r
498 SourcePixelX++, DestinationPixelX++)\r
499 {\r
500 // Calculate the source and target addresses:\r
501 SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;\r
502 EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;\r
503\r
504 // Snapshot the pixel from the video buffer once, to speed up the operation.\r
505 // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.\r
506 Pixel16bit = *SourcePixel16bit;\r
507\r
508 // Copy the pixel into the new target\r
509 // There is no info for the Reserved byte, so we set it to zero\r
510 EfiDestinationPixel->Red = (UINT8) ( (Pixel16bit & PixelInformation->RedMask ) >> 8 );\r
511 EfiDestinationPixel->Green = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask ) >> 3);\r
512 EfiDestinationPixel->Blue = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask ) << 3 );\r
513 // EfiDestinationPixel->Reserved = (UINT8) 0;\r
514 }\r
515 }\r
516 break;\r
517\r
518 case LCD_BITS_PER_PIXEL_12_444:\r
519 // Access each pixel inside the Video Memory\r
520 for (SourceLine = SourceY, DestinationLine = DestinationY;\r
521 SourceLine < SourceY + Height;\r
522 SourceLine++, DestinationLine++)\r
523 {\r
524 for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;\r
525 SourcePixelX < SourceX + Width;\r
526 SourcePixelX++, DestinationPixelX++)\r
527 {\r
528 // Calculate the source and target addresses:\r
529 SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;\r
530 EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;\r
531\r
532 // Snapshot the pixel from the video buffer once, to speed up the operation.\r
533 // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.\r
534 Pixel16bit = *SourcePixel16bit;\r
535\r
536 // Copy the pixel into the new target\r
537 EfiDestinationPixel->Red = (UINT8) ( (Pixel16bit & PixelInformation->RedMask ) >> 4 );\r
538 EfiDestinationPixel->Green = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask ) );\r
539 EfiDestinationPixel->Blue = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask ) << 4 );\r
540 // EfiDestinationPixel->Reserved = (UINT8) 0;\r
541 }\r
542 }\r
543 break;\r
544\r
545 case LCD_BITS_PER_PIXEL_8:\r
546 case LCD_BITS_PER_PIXEL_4:\r
547 case LCD_BITS_PER_PIXEL_2:\r
548 case LCD_BITS_PER_PIXEL_1:\r
549 default:\r
550 // Can't handle this case\r
551 DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltVideoToBltBuffer: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));\r
552 Status = EFI_INVALID_PARAMETER;\r
553 break;\r
554 }\r
555 return Status;\r
556}\r
557\r
558STATIC\r
559EFI_STATUS\r
560BltBufferToVideo (\r
561 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
562 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
563 IN UINTN SourceX,\r
564 IN UINTN SourceY,\r
565 IN UINTN DestinationX,\r
566 IN UINTN DestinationY,\r
567 IN UINTN Width,\r
568 IN UINTN Height,\r
569 IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer\r
570 )\r
571{\r
572 EFI_STATUS Status;\r
573 UINT32 HorizontalResolution;\r
574 LCD_BPP BitsPerPixel;\r
575 EFI_PIXEL_BITMASK *PixelInformation;\r
576 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiSourcePixel;\r
577 VOID *FrameBufferBase;\r
578 VOID *SourceAddr;\r
579 VOID *DestinationAddr;\r
580 UINT16 *DestinationPixel16bit;\r
581 UINT32 SourcePixelX;\r
582 UINT32 SourceLine;\r
583 UINT32 DestinationPixelX;\r
584 UINT32 DestinationLine;\r
585 UINT32 BltBufferHorizontalResolution;\r
586 UINTN WidthInBytes;\r
587\r
588 Status = EFI_SUCCESS;\r
589 PixelInformation = &This->Mode->Info->PixelInformation;\r
590 HorizontalResolution = This->Mode->Info->HorizontalResolution;\r
591 FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));\r
592\r
593 if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {\r
594 // Delta is not zero and it is different from the width.\r
595 // Divide it by the size of a pixel to find out the buffer's horizontal resolution.\r
596 BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
597 } else {\r
598 BltBufferHorizontalResolution = Width;\r
599 }\r
600\r
601 LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);\r
602\r
603 switch (BitsPerPixel) {\r
604 case LCD_BITS_PER_PIXEL_24:\r
605 WidthInBytes = Width * 4;\r
606\r
607 // Access each pixel inside the BltBuffer Memory\r
608 for (SourceLine = SourceY, DestinationLine = DestinationY;\r
609 SourceLine < SourceY + Height;\r
610 SourceLine++, DestinationLine++)\r
611 {\r
612 // Calculate the source and target addresses using 32bit pointer arithmetic:\r
613 SourceAddr = (VOID *)((UINT32 *)BltBuffer + SourceLine * BltBufferHorizontalResolution + SourceX );\r
614 DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);\r
615\r
616 // Copy the entire row Y\r
617 CopyMem( DestinationAddr, SourceAddr, WidthInBytes);\r
618 }\r
619 break;\r
620\r
621 case LCD_BITS_PER_PIXEL_16_555:\r
622 // Access each pixel inside the BltBuffer Memory\r
623 for (SourceLine = SourceY, DestinationLine = DestinationY;\r
624 SourceLine < SourceY + Height;\r
625 SourceLine++, DestinationLine++) {\r
626\r
627 for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;\r
628 SourcePixelX < SourceX + Width;\r
629 SourcePixelX++, DestinationPixelX++)\r
630 {\r
631 // Calculate the source and target addresses:\r
632 EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;\r
633 DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;\r
634\r
635 // Copy the pixel into the new target\r
636 // Only the most significant bits will be copied across:\r
637 // To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits\r
638 *DestinationPixel16bit = (UINT16) (\r
639 ( (EfiSourcePixel->Red << 7) & PixelInformation->RedMask )\r
640 | ( (EfiSourcePixel->Green << 2) & PixelInformation->GreenMask )\r
641 | ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask )\r
642 // | ( 0 & PixelInformation->ReservedMask )\r
643 );\r
644 }\r
645 }\r
646 break;\r
647\r
648 case LCD_BITS_PER_PIXEL_16_565:\r
649 // Access each pixel inside the BltBuffer Memory\r
650 for (SourceLine = SourceY, DestinationLine = DestinationY;\r
651 SourceLine < SourceY + Height;\r
652 SourceLine++, DestinationLine++) {\r
653\r
654 for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;\r
655 SourcePixelX < SourceX + Width;\r
656 SourcePixelX++, DestinationPixelX++)\r
657 {\r
658 // Calculate the source and target addresses:\r
659 EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;\r
660 DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;\r
661\r
662 // Copy the pixel into the new target\r
663 // Only the most significant bits will be copied across:\r
664 // To convert from 8 bits to 5 or 6 bits per pixel we throw away the 3 or 2 least significant bits\r
665 // There is no room for the Reserved byte so we ignore that completely\r
666 *DestinationPixel16bit = (UINT16) (\r
667 ( (EfiSourcePixel->Red << 8) & PixelInformation->RedMask )\r
668 | ( (EfiSourcePixel->Green << 3) & PixelInformation->GreenMask )\r
669 | ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask )\r
670 );\r
671 }\r
672 }\r
673 break;\r
674\r
675 case LCD_BITS_PER_PIXEL_12_444:\r
676 // Access each pixel inside the BltBuffer Memory\r
677 for (SourceLine = SourceY, DestinationLine = DestinationY;\r
678 SourceLine < SourceY + Height;\r
679 SourceLine++, DestinationLine++) {\r
680\r
681 for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;\r
682 SourcePixelX < SourceX + Width;\r
683 SourcePixelX++, DestinationPixelX++)\r
684 {\r
685 // Calculate the source and target addresses:\r
686 EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;\r
687 DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;\r
688\r
689 // Copy the pixel into the new target\r
690 // Only the most significant bits will be copied across:\r
691 // To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits\r
692 *DestinationPixel16bit = (UINT16) (\r
693 ( (EfiSourcePixel->Red << 4) & PixelInformation->RedMask )\r
694 | ( (EfiSourcePixel->Green ) & PixelInformation->GreenMask )\r
695 | ( (EfiSourcePixel->Blue >> 4) & PixelInformation->BlueMask )\r
696 // | ( 0 & PixelInformation->ReservedMask )\r
697 );\r
698 }\r
699 }\r
700 break;\r
701\r
702 case LCD_BITS_PER_PIXEL_8:\r
703 case LCD_BITS_PER_PIXEL_4:\r
704 case LCD_BITS_PER_PIXEL_2:\r
705 case LCD_BITS_PER_PIXEL_1:\r
706 default:\r
707 // Can't handle this case\r
708 DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltBufferToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));\r
709 Status = EFI_INVALID_PARAMETER;\r
710 break;\r
711 }\r
712 return Status;\r
713}\r
714\r
715STATIC\r
716EFI_STATUS\r
717BltVideoToVideo (\r
718 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
719 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
720 IN UINTN SourceX,\r
721 IN UINTN SourceY,\r
722 IN UINTN DestinationX,\r
723 IN UINTN DestinationY,\r
724 IN UINTN Width,\r
725 IN UINTN Height,\r
726 IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer\r
727 )\r
728{\r
729 EFI_STATUS Status;\r
730 UINT32 HorizontalResolution;\r
731 LCD_BPP BitsPerPixel;\r
732 VOID *FrameBufferBase;\r
733\r
734 HorizontalResolution = This->Mode->Info->HorizontalResolution;\r
735 FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));\r
736\r
737 //\r
738 // BltVideo to BltVideo:\r
739 //\r
740 // Source is the Video Memory,\r
741 // Destination is the Video Memory\r
742\r
743 LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);\r
744 FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));\r
745\r
746 // The UEFI spec currently states:\r
747 // "There is no limitation on the overlapping of the source and destination rectangles"\r
748 // Therefore, we must be careful to avoid overwriting the source data\r
749 if( SourceY == DestinationY ) {\r
750 // Copying within the same height, e.g. horizontal shift\r
751 if( SourceX == DestinationX ) {\r
752 // Nothing to do\r
753 Status = EFI_SUCCESS;\r
754 } else if( ((SourceX>DestinationX)?(SourceX - DestinationX):(DestinationX - SourceX)) < Width ) {\r
755 // There is overlap\r
756 Status = VideoCopyHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );\r
757 } else {\r
758 // No overlap\r
759 Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );\r
760 }\r
761 } else {\r
762 // Copying from different heights\r
763 Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );\r
764 }\r
765\r
766 return Status;\r
767}\r
768\r
769/***************************************\r
770 * GraphicsOutput Protocol function, mapping to\r
771 * EFI_GRAPHICS_OUTPUT_PROTOCOL.Blt\r
772 *\r
773 * PRESUMES: 1 pixel = 4 bytes (32bits)\r
774 * ***************************************/\r
775EFI_STATUS\r
776EFIAPI\r
777LcdGraphicsBlt (\r
778 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
91c38d4e
RC
779 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
780 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
781 IN UINTN SourceX,\r
782 IN UINTN SourceY,\r
783 IN UINTN DestinationX,\r
784 IN UINTN DestinationY,\r
785 IN UINTN Width,\r
786 IN UINTN Height,\r
787 IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer\r
1e57a462 788 )\r
789{\r
91c38d4e
RC
790 EFI_STATUS Status;\r
791 UINT32 HorizontalResolution;\r
1e57a462 792 UINT32 VerticalResolution;\r
91c38d4e 793 LCD_INSTANCE* Instance;\r
1e57a462 794\r
795 Instance = LCD_INSTANCE_FROM_GOP_THIS(This);\r
796\r
797 // Setup the hardware if not already done\r
798 if (!mDisplayInitialized) {\r
799 Status = InitializeDisplay (Instance);\r
800 if (EFI_ERROR(Status)) {\r
801 goto EXIT;\r
802 }\r
803 }\r
804\r
805 HorizontalResolution = This->Mode->Info->HorizontalResolution;\r
806 VerticalResolution = This->Mode->Info->VerticalResolution;\r
807\r
808 DEBUG((DEBUG_INFO, "LcdGraphicsBlt (BltOperation:%d,DestX:%d,DestY:%d,Width:%d,Height:%d) res(%d,%d)\n",\r
809 BltOperation,DestinationX,DestinationY,Width,Height,HorizontalResolution,VerticalResolution));\r
810\r
811 // Check we have reasonable parameters\r
91c38d4e 812 if (Width == 0 || Height == 0) {\r
1e57a462 813 DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: ERROR - Invalid dimension: Zero size area.\n" ));\r
91c38d4e
RC
814 Status = EFI_INVALID_PARAMETER;\r
815 goto EXIT;\r
816 }\r
817\r
818 if ((BltOperation == EfiBltVideoFill) || (BltOperation == EfiBltBufferToVideo) || (BltOperation == EfiBltVideoToBltBuffer)) {\r
819 ASSERT( BltBuffer != NULL);\r
820 }\r
821\r
822 /*if ((DestinationX >= HorizontalResolution) || (DestinationY >= VerticalResolution)) {\r
823 DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: ERROR - Invalid destination.\n" ));\r
824 Status = EFI_INVALID_PARAMETER;\r
825 goto EXIT;\r
826 }*/\r
827\r
828 // If we are reading data out of the video buffer, check that the source area is within the display limits\r
829 if ((BltOperation == EfiBltVideoToBltBuffer) || (BltOperation == EfiBltVideoToVideo)) {\r
1e57a462 830 if ((SourceY + Height > VerticalResolution) || (SourceX + Width > HorizontalResolution)) {\r
831 DEBUG((DEBUG_INFO, "LcdGraphicsBlt: ERROR - Invalid source resolution.\n" ));\r
832 DEBUG((DEBUG_INFO, " - SourceY=%d + Height=%d > VerticalResolution=%d.\n", SourceY, Height, VerticalResolution ));\r
833 DEBUG((DEBUG_INFO, " - SourceX=%d + Width=%d > HorizontalResolution=%d.\n", SourceX, Width, HorizontalResolution ));\r
834 Status = EFI_INVALID_PARAMETER;\r
835 goto EXIT;\r
836 }\r
91c38d4e 837 }\r
1e57a462 838\r
91c38d4e
RC
839 // If we are writing data into the video buffer, that the destination area is within the display limits\r
840 if ((BltOperation == EfiBltVideoFill) || (BltOperation == EfiBltBufferToVideo) || (BltOperation == EfiBltVideoToVideo)) {\r
1e57a462 841 if ((DestinationY + Height > VerticalResolution) || (DestinationX + Width > HorizontalResolution)) {\r
842 DEBUG((DEBUG_INFO, "LcdGraphicsBlt: ERROR - Invalid destination resolution.\n" ));\r
843 DEBUG((DEBUG_INFO, " - DestinationY=%d + Height=%d > VerticalResolution=%d.\n", DestinationY, Height, VerticalResolution ));\r
844 DEBUG((DEBUG_INFO, " - DestinationX=%d + Width=%d > HorizontalResolution=%d.\n", DestinationX, Width, HorizontalResolution ));\r
845 Status = EFI_INVALID_PARAMETER;\r
846 goto EXIT;\r
847 }\r
91c38d4e 848 }\r
1e57a462 849\r
850 //\r
851 // Perform the Block Transfer Operation\r
852 //\r
853\r
91c38d4e
RC
854 switch (BltOperation) {\r
855 case EfiBltVideoFill:\r
856 Status = BltVideoFill (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);\r
857 break;\r
1e57a462 858\r
91c38d4e
RC
859 case EfiBltVideoToBltBuffer:\r
860 Status = BltVideoToBltBuffer (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);\r
1e57a462 861 break;\r
862\r
863 case EfiBltBufferToVideo:\r
864 Status = BltBufferToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);\r
91c38d4e 865 break;\r
1e57a462 866\r
91c38d4e
RC
867 case EfiBltVideoToVideo:\r
868 Status = BltVideoToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);\r
869 break;\r
1e57a462 870\r
91c38d4e
RC
871 case EfiGraphicsOutputBltOperationMax:\r
872 default:\r
873 DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: Invalid Operation\n"));\r
874 Status = EFI_INVALID_PARAMETER;\r
875 break;\r
876 }\r
1e57a462 877\r
878EXIT:\r
91c38d4e 879 return Status;\r
1e57a462 880}\r