]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/VirtioGpuDxe/Gop.c
OvmfPkg/VirtioGpuDxe: query native display resolution from host
[mirror_edk2.git] / OvmfPkg / VirtioGpuDxe / Gop.c
index 2c15d542e3b1e0c7aedd2564918b1576d39e9522..70a81c10c8b536c8598005569e4f43d40567da20 100644 (file)
@@ -9,6 +9,7 @@
 **/\r
 \r
 #include <Library/MemoryAllocationLib.h>\r
+#include <Library/PcdLib.h>\r
 \r
 #include "VirtioGpu.h"\r
 \r
@@ -192,6 +193,106 @@ STATIC CONST GOP_RESOLUTION  mGopResolutions[] = {
 #define VGPU_GOP_FROM_GOP(GopPointer) \\r
           CR (GopPointer, VGPU_GOP, Gop, VGPU_GOP_SIG)\r
 \r
+STATIC\r
+VOID\r
+EFIAPI\r
+GopNativeResolution (\r
+  IN  VGPU_GOP  *VgpuGop,\r
+  OUT UINT32    *XRes,\r
+  OUT UINT32    *YRes\r
+  )\r
+{\r
+  volatile VIRTIO_GPU_RESP_DISPLAY_INFO  DisplayInfo;\r
+  EFI_STATUS                             Status;\r
+  UINTN                                  Index;\r
+\r
+  Status = VirtioGpuGetDisplayInfo (VgpuGop->ParentBus, &DisplayInfo);\r
+  if (Status != EFI_SUCCESS) {\r
+    return;\r
+  }\r
+\r
+  for (Index = 0; Index < VIRTIO_GPU_MAX_SCANOUTS; Index++) {\r
+    if (!DisplayInfo.Pmodes[Index].Enabled ||\r
+        !DisplayInfo.Pmodes[Index].Rectangle.Width ||\r
+        !DisplayInfo.Pmodes[Index].Rectangle.Height)\r
+    {\r
+      continue;\r
+    }\r
+\r
+    DEBUG ((\r
+      DEBUG_INFO,\r
+      "%a: #%d: %dx%d\n",\r
+      __FUNCTION__,\r
+      Index,\r
+      DisplayInfo.Pmodes[Index].Rectangle.Width,\r
+      DisplayInfo.Pmodes[Index].Rectangle.Height\r
+      ));\r
+    if ((*XRes == 0) || (*YRes == 0)) {\r
+      *XRes = DisplayInfo.Pmodes[Index].Rectangle.Width;\r
+      *YRes = DisplayInfo.Pmodes[Index].Rectangle.Height;\r
+    }\r
+  }\r
+}\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+GopInitialize (\r
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL  *This\r
+  )\r
+{\r
+  VGPU_GOP    *VgpuGop;\r
+  EFI_STATUS  Status;\r
+  UINT32      XRes = 0, YRes = 0, Index;\r
+\r
+  VgpuGop = VGPU_GOP_FROM_GOP (This);\r
+\r
+  //\r
+  // Set up the Gop -> GopMode -> GopModeInfo pointer chain, and the other\r
+  // (nonzero) constant fields.\r
+  //\r
+  // No direct framebuffer access is supported, only Blt() is.\r
+  //\r
+  VgpuGop->Gop.Mode = &VgpuGop->GopMode;\r
+\r
+  VgpuGop->GopMode.MaxMode    = (UINT32)(ARRAY_SIZE (mGopResolutions));\r
+  VgpuGop->GopMode.Info       = &VgpuGop->GopModeInfo;\r
+  VgpuGop->GopMode.SizeOfInfo = sizeof VgpuGop->GopModeInfo;\r
+\r
+  VgpuGop->GopModeInfo.PixelFormat = PixelBltOnly;\r
+\r
+  //\r
+  // query host for display resolution\r
+  //\r
+  GopNativeResolution (VgpuGop, &XRes, &YRes);\r
+  if ((XRes == 0) || (YRes == 0)) {\r
+    return;\r
+  }\r
+\r
+  if (PcdGet8 (PcdVideoResolutionSource) == 0) {\r
+    Status = PcdSet32S (PcdVideoHorizontalResolution, XRes);\r
+    ASSERT_RETURN_ERROR (Status);\r
+    Status = PcdSet32S (PcdVideoVerticalResolution, YRes);\r
+    ASSERT_RETURN_ERROR (Status);\r
+    Status = PcdSet8S (PcdVideoResolutionSource, 2);\r
+    ASSERT_RETURN_ERROR (Status);\r
+  }\r
+\r
+  VgpuGop->NativeXRes = XRes;\r
+  VgpuGop->NativeYRes = YRes;\r
+  for (Index = 0; Index < ARRAY_SIZE (mGopResolutions); Index++) {\r
+    if ((mGopResolutions[Index].Width == XRes) &&\r
+        (mGopResolutions[Index].Height == YRes))\r
+    {\r
+      // native resolution already is in mode list\r
+      return;\r
+    }\r
+  }\r
+\r
+  // add to mode list\r
+  VgpuGop->GopMode.MaxMode++;\r
+}\r
+\r
 //\r
 // EFI_GRAPHICS_OUTPUT_PROTOCOL member functions.\r
 //\r
@@ -207,7 +308,7 @@ GopQueryMode (
 {\r
   EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *GopModeInfo;\r
 \r
-  if (ModeNumber >= ARRAY_SIZE (mGopResolutions)) {\r
+  if (ModeNumber >= This->Mode->MaxMode) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -216,10 +317,17 @@ GopQueryMode (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  GopModeInfo->HorizontalResolution = mGopResolutions[ModeNumber].Width;\r
-  GopModeInfo->VerticalResolution   = mGopResolutions[ModeNumber].Height;\r
-  GopModeInfo->PixelFormat          = PixelBltOnly;\r
-  GopModeInfo->PixelsPerScanLine    = mGopResolutions[ModeNumber].Width;\r
+  if (ModeNumber < ARRAY_SIZE (mGopResolutions)) {\r
+    GopModeInfo->HorizontalResolution = mGopResolutions[ModeNumber].Width;\r
+    GopModeInfo->VerticalResolution   = mGopResolutions[ModeNumber].Height;\r
+  } else {\r
+    VGPU_GOP  *VgpuGop = VGPU_GOP_FROM_GOP (This);\r
+    GopModeInfo->HorizontalResolution = VgpuGop->NativeXRes;\r
+    GopModeInfo->VerticalResolution   = VgpuGop->NativeYRes;\r
+  }\r
+\r
+  GopModeInfo->PixelFormat       = PixelBltOnly;\r
+  GopModeInfo->PixelsPerScanLine = GopModeInfo->HorizontalResolution;\r
 \r
   *SizeOfInfo = sizeof *GopModeInfo;\r
   *Info       = GopModeInfo;\r
@@ -234,19 +342,27 @@ GopSetMode (
   IN  UINT32                        ModeNumber\r
   )\r
 {\r
-  VGPU_GOP              *VgpuGop;\r
-  UINT32                NewResourceId;\r
-  UINTN                 NewNumberOfBytes;\r
-  UINTN                 NewNumberOfPages;\r
-  VOID                  *NewBackingStore;\r
-  EFI_PHYSICAL_ADDRESS  NewBackingStoreDeviceAddress;\r
-  VOID                  *NewBackingStoreMap;\r
+  VGPU_GOP                              *VgpuGop;\r
+  UINT32                                NewResourceId;\r
+  UINTN                                 NewNumberOfBytes;\r
+  UINTN                                 NewNumberOfPages;\r
+  VOID                                  *NewBackingStore;\r
+  EFI_PHYSICAL_ADDRESS                  NewBackingStoreDeviceAddress;\r
+  VOID                                  *NewBackingStoreMap;\r
+  UINTN                                 SizeOfInfo;\r
+  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *GopModeInfo;\r
 \r
   EFI_STATUS  Status;\r
   EFI_STATUS  Status2;\r
 \r
-  if (ModeNumber >= ARRAY_SIZE (mGopResolutions)) {\r
-    return EFI_UNSUPPORTED;\r
+  if (!This->Mode) {\r
+    // SetMode() call in InitVgpuGop() triggers this.\r
+    GopInitialize (This);\r
+  }\r
+\r
+  Status = GopQueryMode (This, ModeNumber, &SizeOfInfo, &GopModeInfo);\r
+  if (Status != EFI_SUCCESS) {\r
+    return Status;\r
   }\r
 \r
   VgpuGop = VGPU_GOP_FROM_GOP (This);\r
@@ -256,20 +372,6 @@ GopSetMode (
   // calls.\r
   //\r
   if (VgpuGop->ResourceId == 0) {\r
-    //\r
-    // Set up the Gop -> GopMode -> GopModeInfo pointer chain, and the other\r
-    // (nonzero) constant fields.\r
-    //\r
-    // No direct framebuffer access is supported, only Blt() is.\r
-    //\r
-    VgpuGop->Gop.Mode = &VgpuGop->GopMode;\r
-\r
-    VgpuGop->GopMode.MaxMode    = (UINT32)(ARRAY_SIZE (mGopResolutions));\r
-    VgpuGop->GopMode.Info       = &VgpuGop->GopModeInfo;\r
-    VgpuGop->GopMode.SizeOfInfo = sizeof VgpuGop->GopModeInfo;\r
-\r
-    VgpuGop->GopModeInfo.PixelFormat = PixelBltOnly;\r
-\r
     //\r
     // This is the first time we create a host side resource.\r
     //\r
@@ -292,8 +394,8 @@ GopSetMode (
              VgpuGop->ParentBus,                // VgpuDev\r
              NewResourceId,                     // ResourceId\r
              VirtioGpuFormatB8G8R8X8Unorm,      // Format\r
-             mGopResolutions[ModeNumber].Width, // Width\r
-             mGopResolutions[ModeNumber].Height // Height\r
+             GopModeInfo->HorizontalResolution, // Width\r
+             GopModeInfo->VerticalResolution    // Height\r
              );\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
@@ -303,8 +405,8 @@ GopSetMode (
   // Allocate, zero and map guest backing store, for bus master common buffer\r
   // operation.\r
   //\r
-  NewNumberOfBytes = mGopResolutions[ModeNumber].Width *\r
-                     mGopResolutions[ModeNumber].Height * sizeof (UINT32);\r
+  NewNumberOfBytes = GopModeInfo->HorizontalResolution *\r
+                     GopModeInfo->VerticalResolution * sizeof (UINT32);\r
   NewNumberOfPages = EFI_SIZE_TO_PAGES (NewNumberOfBytes);\r
   Status           = VirtioGpuAllocateZeroAndMapBackingStore (\r
                        VgpuGop->ParentBus,            // VgpuDev\r
@@ -337,8 +439,8 @@ GopSetMode (
              VgpuGop->ParentBus,                 // VgpuDev\r
              0,                                  // X\r
              0,                                  // Y\r
-             mGopResolutions[ModeNumber].Width,  // Width\r
-             mGopResolutions[ModeNumber].Height, // Height\r
+             GopModeInfo->HorizontalResolution,  // Width\r
+             GopModeInfo->VerticalResolution,    // Height\r
              0,                                  // ScanoutId\r
              NewResourceId                       // ResourceId\r
              );\r
@@ -356,8 +458,8 @@ GopSetMode (
                VgpuGop->ParentBus,                 // VgpuDev\r
                0,                                  // X\r
                0,                                  // Y\r
-               mGopResolutions[ModeNumber].Width,  // Width\r
-               mGopResolutions[ModeNumber].Height, // Height\r
+               GopModeInfo->HorizontalResolution,  // Width\r
+               GopModeInfo->VerticalResolution,    // Height\r
                NewResourceId                       // ResourceId\r
                );\r
     if (EFI_ERROR (Status)) {\r
@@ -367,13 +469,13 @@ GopSetMode (
       // therefore non-recoverable.\r
       //\r
       Status2 = VirtioGpuSetScanout (\r
-                  VgpuGop->ParentBus,                       // VgpuDev\r
-                  0,                                        // X\r
-                  0,                                        // Y\r
-                  mGopResolutions[This->Mode->Mode].Width,  // Width\r
-                  mGopResolutions[This->Mode->Mode].Height, // Height\r
-                  0,                                        // ScanoutId\r
-                  VgpuGop->ResourceId                       // ResourceId\r
+                  VgpuGop->ParentBus,                        // VgpuDev\r
+                  0,                                         // X\r
+                  0,                                         // Y\r
+                  VgpuGop->GopModeInfo.HorizontalResolution, // Width\r
+                  VgpuGop->GopModeInfo.VerticalResolution,   // Height\r
+                  0,                                         // ScanoutId\r
+                  VgpuGop->ResourceId                        // ResourceId\r
                   );\r
       ASSERT_EFI_ERROR (Status2);\r
       if (EFI_ERROR (Status2)) {\r
@@ -406,11 +508,9 @@ GopSetMode (
   //\r
   // Populate Mode and ModeInfo (mutable fields only).\r
   //\r
-  VgpuGop->GopMode.Mode                     = ModeNumber;\r
-  VgpuGop->GopModeInfo.HorizontalResolution =\r
-    mGopResolutions[ModeNumber].Width;\r
-  VgpuGop->GopModeInfo.VerticalResolution = mGopResolutions[ModeNumber].Height;\r
-  VgpuGop->GopModeInfo.PixelsPerScanLine  = mGopResolutions[ModeNumber].Width;\r
+  VgpuGop->GopMode.Mode = ModeNumber;\r
+  VgpuGop->GopModeInfo  = *GopModeInfo;\r
+  FreePool (GopModeInfo);\r
   return EFI_SUCCESS;\r
 \r
 DetachBackingStore:\r
@@ -435,6 +535,7 @@ DestroyHostResource:
     CpuDeadLoop ();\r
   }\r
 \r
+  FreePool (GopModeInfo);\r
   return Status;\r
 }\r
 \r