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