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