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