Fixed the bug when set mode value is less than the Max mode value.
[people/mcb30/edk2.git] / edk2 / MdeModulePkg / Universal / Console / ConSplitterDxe / ConSplitterGraphics.c
index c3e15d4..d13d540 100644 (file)
@@ -147,14 +147,16 @@ ConSpliterConsoleControlSetMode (
     //\r
     if ((Mode == EfiConsoleControlScreenGraphics) &&((TextAndGop->GraphicsOutput != NULL) || (TextAndGop->UgaDraw != NULL))) {\r
       TextAndGop->TextOutEnabled = FALSE;\r
-      DevNullGopSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);\r
+      if (FeaturePcdGet (PcdConOutGopSupport)) {\r
+        DevNullGopSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);\r
+      } else if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
+        DevNullUgaSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);\r
+      }\r
     }\r
   }\r
-\r
   if (Mode == EfiConsoleControlScreenText) {\r
     DevNullSyncGopStdOut (Private);\r
   }\r
-\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -287,11 +289,6 @@ Routine Description:
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  if (!Private->HardwareNeedsStarting) {\r
-    if (Private->ConsoleOutputMode != EfiConsoleControlScreenGraphics) {\r
-      return EFI_UNSUPPORTED;\r
-    }\r
-  }\r
   //\r
   // return the worst status met\r
   //\r
@@ -319,17 +316,19 @@ Routine Description:
       }\r
     }\r
 \r
-    UgaDraw = Private->TextOutList[Index].UgaDraw;\r
-    if (UgaDraw != NULL) {\r
-      Status = UgaDraw->SetMode (\r
-                          UgaDraw,\r
-                          Mode->HorizontalResolution,\r
-                          Mode->VerticalResolution,\r
-                          32,\r
-                          60\r
-                          );\r
-      if (EFI_ERROR (Status)) {\r
-        ReturnStatus = Status;\r
+    if (EFI_ERROR (ReturnStatus)) {\r
+      UgaDraw = Private->TextOutList[Index].UgaDraw;\r
+      if (UgaDraw != NULL) {\r
+        Status = UgaDraw->SetMode (\r
+                            UgaDraw,\r
+                            Mode->HorizontalResolution,\r
+                            Mode->VerticalResolution,\r
+                            32,\r
+                            60\r
+                            );\r
+        if (EFI_ERROR (Status)) {\r
+          ReturnStatus = Status;\r
+        }\r
       }\r
     }\r
   }\r
@@ -653,6 +652,467 @@ DevNullGopSync (
   }\r
 }\r
 \r
+EFI_STATUS\r
+EFIAPI\r
+ConSpliterUgaDrawGetMode (\r
+  IN  EFI_UGA_DRAW_PROTOCOL           *This,\r
+  OUT UINT32                          *HorizontalResolution,\r
+  OUT UINT32                          *VerticalResolution,\r
+  OUT UINT32                          *ColorDepth,\r
+  OUT UINT32                          *RefreshRate\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Return the current video mode information.\r
+\r
+  Arguments:\r
+    This                  - Protocol instance pointer.\r
+    HorizontalResolution  - Current video horizontal resolution in pixels\r
+    VerticalResolution    - Current video vertical resolution in pixels\r
+    ColorDepth            - Current video color depth in bits per pixel\r
+    RefreshRate           - Current video refresh rate in Hz.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - Mode information returned.\r
+    EFI_NOT_STARTED       - Video display is not initialized. Call SetMode ()\r
+    EFI_INVALID_PARAMETER - One of the input args was NULL.\r
+\r
+--*/\r
+{\r
+  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;\r
+\r
+  if (!(HorizontalResolution && VerticalResolution && RefreshRate && ColorDepth)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // retrieve private data\r
+  //\r
+  Private               = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  *HorizontalResolution = Private->UgaHorizontalResolution;\r
+  *VerticalResolution   = Private->UgaVerticalResolution;\r
+  *ColorDepth           = Private->UgaColorDepth;\r
+  *RefreshRate          = Private->UgaRefreshRate;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSpliterUgaDrawSetMode (\r
+  IN  EFI_UGA_DRAW_PROTOCOL           *This,\r
+  IN UINT32                           HorizontalResolution,\r
+  IN UINT32                           VerticalResolution,\r
+  IN UINT32                           ColorDepth,\r
+  IN UINT32                           RefreshRate\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Return the current video mode information.\r
+\r
+  Arguments:\r
+    This                  - Protocol instance pointer.\r
+    HorizontalResolution  - Current video horizontal resolution in pixels\r
+    VerticalResolution    - Current video vertical resolution in pixels\r
+    ColorDepth            - Current video color depth in bits per pixel\r
+    RefreshRate           - Current video refresh rate in Hz.\r
+\r
+  Returns:\r
+    EFI_SUCCESS     - Mode information returned.\r
+    EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()\r
+    EFI_OUT_OF_RESOURCES - Out of resources.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                             Status;\r
+  TEXT_OUT_SPLITTER_PRIVATE_DATA         *Private;\r
+  UINTN                                  Index;\r
+  EFI_STATUS                             ReturnStatus;\r
+  UINTN                                  Size;\r
+  EFI_GRAPHICS_OUTPUT_PROTOCOL           *GraphicsOutput;\r
+  UINTN                                  NumberIndex;\r
+  UINTN                                  SizeOfInfo;\r
+  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION   *Info;\r
+  EFI_UGA_DRAW_PROTOCOL                  *UgaDraw;\r
+\r
+  Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  //\r
+  // UgaDevNullSetMode ()\r
+  //\r
+  ReturnStatus = EFI_SUCCESS;\r
+\r
+  //\r
+  // Free the old version\r
+  //\r
+  if (Private->UgaBlt != NULL) {\r
+    FreePool (Private->UgaBlt);\r
+  }\r
+\r
+  //\r
+  // Allocate the virtual Blt buffer\r
+  //\r
+  Size            = HorizontalResolution * VerticalResolution * sizeof (EFI_UGA_PIXEL);\r
+  Private->UgaBlt = AllocateZeroPool (Size);\r
+  if (Private->UgaBlt == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Update the Mode data\r
+  //\r
+  Private->UgaHorizontalResolution  = HorizontalResolution;\r
+  Private->UgaVerticalResolution    = VerticalResolution;\r
+  Private->UgaColorDepth            = ColorDepth;\r
+  Private->UgaRefreshRate           = RefreshRate;\r
+\r
+  if (Private->ConsoleOutputMode != EfiConsoleControlScreenGraphics) {\r
+    return ReturnStatus;\r
+  }\r
+  //\r
+  // return the worst status met\r
+  //\r
+  for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
+    UgaDraw = Private->TextOutList[Index].UgaDraw;\r
+    if (UgaDraw != NULL) {\r
+      Status = UgaDraw->SetMode (\r
+                          UgaDraw,\r
+                          HorizontalResolution,\r
+                          VerticalResolution,\r
+                          ColorDepth,\r
+                          RefreshRate\r
+                          );\r
+      if (EFI_ERROR (Status)) {\r
+        ReturnStatus = Status;\r
+      }\r
+    }\r
+\r
+    if (EFI_ERROR (ReturnStatus)) {\r
+      GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;\r
+      if (GraphicsOutput != NULL) {\r
+        //\r
+        // Find corresponding ModeNumber of this GraphicsOutput instance\r
+        //\r
+        for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex ++) {\r
+          Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);\r
+          if (EFI_ERROR (Status)) {\r
+            return Status;\r
+          }\r
+          if ((Info->HorizontalResolution == HorizontalResolution) && (Info->VerticalResolution == VerticalResolution)) {\r
+            FreePool (Info);\r
+            break;\r
+          }\r
+          FreePool (Info);\r
+        }\r
+\r
+        Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32) NumberIndex);\r
+        if (EFI_ERROR (Status)) {\r
+          ReturnStatus = Status;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  return ReturnStatus;\r
+}\r
+\r
+EFI_STATUS\r
+DevNullUgaBlt (\r
+  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA                *Private,\r
+  IN  EFI_UGA_PIXEL                                 *BltBuffer, OPTIONAL\r
+  IN  EFI_UGA_BLT_OPERATION                         BltOperation,\r
+  IN  UINTN                                         SourceX,\r
+  IN  UINTN                                         SourceY,\r
+  IN  UINTN                                         DestinationX,\r
+  IN  UINTN                                         DestinationY,\r
+  IN  UINTN                                         Width,\r
+  IN  UINTN                                         Height,\r
+  IN  UINTN                                         Delta         OPTIONAL\r
+  )\r
+{\r
+  UINTN         SrcY;\r
+  BOOLEAN       Forward;\r
+  UINTN         Index;\r
+  EFI_UGA_PIXEL *BltPtr;\r
+  EFI_UGA_PIXEL *ScreenPtr;\r
+  UINT32        HorizontalResolution;\r
+  UINT32        VerticalResolution;\r
+\r
+  if ((BltOperation < 0) || (BltOperation >= EfiUgaBltMax)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Width == 0 || Height == 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Delta == 0) {\r
+    Delta = Width * sizeof (EFI_UGA_PIXEL);\r
+  }\r
+\r
+  HorizontalResolution  = Private->UgaHorizontalResolution;\r
+  VerticalResolution    = Private->UgaVerticalResolution;\r
+\r
+  //\r
+  // We need to fill the Virtual Screen buffer with the blt data.\r
+  //\r
+  if (BltOperation == EfiUgaVideoToBltBuffer) {\r
+    //\r
+    // Video to BltBuffer: Source is Video, destination is BltBuffer\r
+    //\r
+    if ((SourceY + Height) > VerticalResolution) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    if ((SourceX + Width) > HorizontalResolution) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    BltPtr    = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + DestinationY * Delta + DestinationX * sizeof (EFI_UGA_PIXEL));\r
+    ScreenPtr = &Private->UgaBlt[SourceY * HorizontalResolution + SourceX];\r
+    while (Height) {\r
+      CopyMem (BltPtr, ScreenPtr, Width * sizeof (EFI_UGA_PIXEL));\r
+      BltPtr = (EFI_UGA_PIXEL *) ((UINT8 *) BltPtr + Delta);\r
+      ScreenPtr += HorizontalResolution;\r
+      Height--;\r
+    }\r
+  } else {\r
+    //\r
+    // BltBuffer to Video: Source is BltBuffer, destination is Video\r
+    //\r
+    if (DestinationY + Height > VerticalResolution) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    if (DestinationX + Width > HorizontalResolution) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    if ((BltOperation == EfiUgaVideoToVideo) && (DestinationY > SourceY)) {\r
+      //\r
+      // Copy backwards, only care the Video to Video Blt\r
+      //\r
+      ScreenPtr = &Private->UgaBlt[(DestinationY + Height - 1) * HorizontalResolution + DestinationX];\r
+      SrcY      = SourceY + Height - 1;\r
+      Forward   = FALSE;\r
+    } else {\r
+      //\r
+      // Copy forwards, for other cases\r
+      //\r
+      ScreenPtr = &Private->UgaBlt[DestinationY * HorizontalResolution + DestinationX];\r
+      SrcY      = SourceY;\r
+      Forward   = TRUE;\r
+    }\r
+\r
+    while (Height != 0) {\r
+      if (BltOperation == EfiUgaVideoFill) {\r
+        for (Index = 0; Index < Width; Index++) {\r
+          ScreenPtr[Index] = *BltBuffer;\r
+        }\r
+      } else {\r
+        if (BltOperation == EfiUgaBltBufferToVideo) {\r
+          BltPtr = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + SrcY * Delta + SourceX * sizeof (EFI_UGA_PIXEL));\r
+        } else {\r
+          BltPtr = &Private->UgaBlt[SrcY * HorizontalResolution + SourceX];\r
+        }\r
+\r
+        CopyMem (ScreenPtr, BltPtr, Width * sizeof (EFI_UGA_PIXEL));\r
+      }\r
+\r
+      if (Forward) {\r
+        ScreenPtr += HorizontalResolution;\r
+        SrcY ++;\r
+      } else {\r
+        ScreenPtr -= HorizontalResolution;\r
+        SrcY --;\r
+      }\r
+      Height--;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSpliterUgaDrawBlt (\r
+  IN  EFI_UGA_DRAW_PROTOCOL                         *This,\r
+  IN  EFI_UGA_PIXEL                                 *BltBuffer, OPTIONAL\r
+  IN  EFI_UGA_BLT_OPERATION                         BltOperation,\r
+  IN  UINTN                                         SourceX,\r
+  IN  UINTN                                         SourceY,\r
+  IN  UINTN                                         DestinationX,\r
+  IN  UINTN                                         DestinationY,\r
+  IN  UINTN                                         Width,\r
+  IN  UINTN                                         Height,\r
+  IN  UINTN                                         Delta         OPTIONAL\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    The following table defines actions for BltOperations:\r
+    EfiUgaVideoFill - Write data from the  BltBuffer pixel (SourceX, SourceY)\r
+      directly to every pixel of the video display rectangle\r
+      (DestinationX, DestinationY)\r
+      (DestinationX + Width, DestinationY + Height).\r
+      Only one pixel will be used from the BltBuffer. Delta is NOT used.\r
+    EfiUgaVideoToBltBuffer - Read data from the video display rectangle\r
+      (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in\r
+      the BltBuffer rectangle (DestinationX, DestinationY )\r
+      (DestinationX + Width, DestinationY + Height). If DestinationX or\r
+      DestinationY is not zero then Delta must be set to the length in bytes\r
+      of a row in the BltBuffer.\r
+    EfiUgaBltBufferToVideo - Write data from the  BltBuffer rectangle\r
+      (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the\r
+      video display rectangle (DestinationX, DestinationY)\r
+      (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is\r
+      not zero then Delta must be set to the length in bytes of a row in the\r
+      BltBuffer.\r
+    EfiUgaVideoToVideo - Copy from the video display rectangle\r
+      (SourceX, SourceY) (SourceX + Width, SourceY + Height) .\r
+      to the video display rectangle (DestinationX, DestinationY)\r
+      (DestinationX + Width, DestinationY + Height).\r
+     The BltBuffer and Delta  are not used in this mode.\r
+\r
+  Arguments:\r
+    This          - Protocol instance pointer.\r
+    BltBuffer     - Buffer containing data to blit into video buffer. This\r
+                    buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL)\r
+    BltOperation  - Operation to perform on BlitBuffer and video memory\r
+    SourceX       - X coordinate of source for the BltBuffer.\r
+    SourceY       - Y coordinate of source for the BltBuffer.\r
+    DestinationX  - X coordinate of destination for the BltBuffer.\r
+    DestinationY  - Y coordinate of destination for the BltBuffer.\r
+    Width         - Width of rectangle in BltBuffer in pixels.\r
+    Height        - Hight of rectangle in BltBuffer in pixels.\r
+    Delta         -\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The Blt operation completed.\r
+    EFI_INVALID_PARAMETER - BltOperation is not valid.\r
+    EFI_DEVICE_ERROR      - A hardware error occured writting to the video\r
+                             buffer.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                      Status;\r
+  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;\r
+  UINTN                           Index;\r
+  EFI_STATUS                      ReturnStatus;\r
+  EFI_GRAPHICS_OUTPUT_PROTOCOL    *GraphicsOutput;\r
+\r
+  Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  //\r
+  // Sync up DevNull UGA device\r
+  //\r
+  ReturnStatus = DevNullUgaBlt (\r
+                  Private,\r
+                  BltBuffer,\r
+                  BltOperation,\r
+                  SourceX,\r
+                  SourceY,\r
+                  DestinationX,\r
+                  DestinationY,\r
+                  Width,\r
+                  Height,\r
+                  Delta\r
+                  );\r
+  if (Private->ConsoleOutputMode != EfiConsoleControlScreenGraphics) {\r
+    return ReturnStatus;\r
+  }\r
+  //\r
+  // return the worst status met\r
+  //\r
+  for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
+    GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;\r
+    if (GraphicsOutput != NULL) {\r
+      Status = GraphicsOutput->Blt (\r
+                              GraphicsOutput,\r
+                              (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltBuffer,\r
+                              (EFI_GRAPHICS_OUTPUT_BLT_OPERATION) BltOperation,\r
+                              SourceX,\r
+                              SourceY,\r
+                              DestinationX,\r
+                              DestinationY,\r
+                              Width,\r
+                              Height,\r
+                              Delta\r
+                              );\r
+      if (EFI_ERROR (Status)) {\r
+        ReturnStatus = Status;\r
+      } else if (BltOperation == EfiBltVideoToBltBuffer) {\r
+        //\r
+        // Only need to read the data into buffer one time\r
+        //\r
+        return EFI_SUCCESS;\r
+      }\r
+    }\r
+\r
+    if (Private->TextOutList[Index].UgaDraw != NULL) {\r
+      Status = Private->TextOutList[Index].UgaDraw->Blt (\r
+                                                      Private->TextOutList[Index].UgaDraw,\r
+                                                      BltBuffer,\r
+                                                      BltOperation,\r
+                                                      SourceX,\r
+                                                      SourceY,\r
+                                                      DestinationX,\r
+                                                      DestinationY,\r
+                                                      Width,\r
+                                                      Height,\r
+                                                      Delta\r
+                                                      );\r
+      if (EFI_ERROR (Status)) {\r
+        ReturnStatus = Status;\r
+      } else if (BltOperation == EfiUgaVideoToBltBuffer) {\r
+        //\r
+        // Only need to read the data into buffer one time\r
+        //\r
+        return EFI_SUCCESS;\r
+      }\r
+    }\r
+  }\r
+\r
+  return ReturnStatus;\r
+}\r
+\r
+EFI_STATUS\r
+DevNullUgaSync (\r
+  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private,\r
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL    *GraphicsOutput,\r
+  IN  EFI_UGA_DRAW_PROTOCOL           *UgaDraw\r
+  )\r
+{\r
+  if (UgaDraw != NULL) {\r
+    return UgaDraw->Blt (\r
+                      UgaDraw,\r
+                      Private->UgaBlt,\r
+                      EfiUgaBltBufferToVideo,\r
+                      0,\r
+                      0,\r
+                      0,\r
+                      0,\r
+                      Private->UgaHorizontalResolution,\r
+                      Private->UgaVerticalResolution,\r
+                      Private->UgaHorizontalResolution * sizeof (EFI_UGA_PIXEL)\r
+                      );\r
+  } else {\r
+    return GraphicsOutput->Blt (\r
+                      GraphicsOutput,\r
+                      (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) Private->UgaBlt,\r
+                      EfiBltBufferToVideo,\r
+                      0,\r
+                      0,\r
+                      0,\r
+                      0,\r
+                      Private->UgaHorizontalResolution,\r
+                      Private->UgaVerticalResolution,\r
+                      0\r
+                      );\r
+  }\r
+}\r
 \r
 EFI_STATUS\r
 DevNullTextOutOutputString (\r
@@ -1130,6 +1590,9 @@ DevNullSyncGopStdOut (
   MaxColumn     = Private->DevNullColumns;\r
 \r
   Buffer        = AllocateZeroPool ((MaxColumn + 1) * sizeof (CHAR16));\r
+  if (Buffer == NULL) {\r
+    return ReturnStatus;\r
+  }\r
 \r
   for (Row = 0; Row < Private->DevNullRows; Row++, Screen += (MaxColumn + 1), Attributes += MaxColumn) {\r
 \r