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