]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputBlt.c
ArmPlatformPkg: Change OPTIONAL keyword usage style
[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
e5908945 64 case LcdBitsPerPixel_24:\r
1e57a462 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
e5908945
PG
82 case LcdBitsPerPixel_16_555:\r
83 case LcdBitsPerPixel_16_565:\r
84 case LcdBitsPerPixel_12_444:\r
1e57a462 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
e5908945
PG
102 case LcdBitsPerPixel_8:\r
103 case LcdBitsPerPixel_4:\r
104 case LcdBitsPerPixel_2:\r
105 case LcdBitsPerPixel_1:\r
1e57a462 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
e5908945 152 case LcdBitsPerPixel_24:\r
1e57a462 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
e5908945
PG
194 case LcdBitsPerPixel_16_555:\r
195 case LcdBitsPerPixel_16_565:\r
196 case LcdBitsPerPixel_12_444:\r
1e57a462 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
e5908945
PG
239 case LcdBitsPerPixel_8:\r
240 case LcdBitsPerPixel_4:\r
241 case LcdBitsPerPixel_2:\r
242 case LcdBitsPerPixel_1:\r
1e57a462 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
2863ba97 260 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiSourcePixel OPTIONAL,\r
1e57a462 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
e5908945 290 case LcdBitsPerPixel_24:\r
1e57a462 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
e5908945 306 case LcdBitsPerPixel_16_555:\r
1e57a462 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
e5908945 333 case LcdBitsPerPixel_16_565:\r
1e57a462 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
e5908945 359 case LcdBitsPerPixel_12_444:\r
1e57a462 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
e5908945
PG
385 case LcdBitsPerPixel_8:\r
386 case LcdBitsPerPixel_4:\r
387 case LcdBitsPerPixel_2:\r
388 case LcdBitsPerPixel_1:\r
1e57a462 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
2863ba97 403 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,\r
1e57a462 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
e5908945 446 case LcdBitsPerPixel_24:\r
1e57a462 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
e5908945 463 case LcdBitsPerPixel_16_555:\r
1e57a462 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
e5908945 490 case LcdBitsPerPixel_16_565:\r
1e57a462 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
e5908945 518 case LcdBitsPerPixel_12_444:\r
1e57a462 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
e5908945
PG
545 case LcdBitsPerPixel_8:\r
546 case LcdBitsPerPixel_4:\r
547 case LcdBitsPerPixel_2:\r
548 case LcdBitsPerPixel_1:\r
1e57a462 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
2863ba97 562 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,\r
1e57a462 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
e5908945 604 case LcdBitsPerPixel_24:\r
1e57a462 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
e5908945 621 case LcdBitsPerPixel_16_555:\r
1e57a462 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
e5908945 648 case LcdBitsPerPixel_16_565:\r
1e57a462 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
e5908945 675 case LcdBitsPerPixel_12_444:\r
1e57a462 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
e5908945
PG
702 case LcdBitsPerPixel_8:\r
703 case LcdBitsPerPixel_4:\r
704 case LcdBitsPerPixel_2:\r
705 case LcdBitsPerPixel_1:\r
1e57a462 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
2863ba97 719 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,\r
1e57a462 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
2863ba97 779 IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,\r
91c38d4e
RC
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