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