Browse Source

OvmfPkg/VirtioGpuDxe: query native display resolution from host

Try query native display resolution from the host.  When successful,
setup PcdVideoHorizontalResolution and PcdVideoVerticalResolution
accordingly and add the video mode to the GOP mode list if needed.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Gerd Hoffmann 2 years ago
parent
commit
916f90baa5
3 changed files with 99 additions and 5 deletions
  1. 87 5
      OvmfPkg/VirtioGpuDxe/Gop.c
  2. 6 0
      OvmfPkg/VirtioGpuDxe/VirtioGpu.h
  3. 6 0
      OvmfPkg/VirtioGpuDxe/VirtioGpu.inf

+ 87 - 5
OvmfPkg/VirtioGpuDxe/Gop.c

@@ -9,6 +9,7 @@
 **/
 
 #include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
 
 #include "VirtioGpu.h"
 
@@ -192,6 +193,47 @@ STATIC CONST GOP_RESOLUTION  mGopResolutions[] = {
 #define VGPU_GOP_FROM_GOP(GopPointer) \
           CR (GopPointer, VGPU_GOP, Gop, VGPU_GOP_SIG)
 
+STATIC
+VOID
+EFIAPI
+GopNativeResolution (
+  IN  VGPU_GOP  *VgpuGop,
+  OUT UINT32    *XRes,
+  OUT UINT32    *YRes
+  )
+{
+  volatile VIRTIO_GPU_RESP_DISPLAY_INFO  DisplayInfo;
+  EFI_STATUS                             Status;
+  UINTN                                  Index;
+
+  Status = VirtioGpuGetDisplayInfo (VgpuGop->ParentBus, &DisplayInfo);
+  if (Status != EFI_SUCCESS) {
+    return;
+  }
+
+  for (Index = 0; Index < VIRTIO_GPU_MAX_SCANOUTS; Index++) {
+    if (!DisplayInfo.Pmodes[Index].Enabled ||
+        !DisplayInfo.Pmodes[Index].Rectangle.Width ||
+        !DisplayInfo.Pmodes[Index].Rectangle.Height)
+    {
+      continue;
+    }
+
+    DEBUG ((
+      DEBUG_INFO,
+      "%a: #%d: %dx%d\n",
+      __FUNCTION__,
+      Index,
+      DisplayInfo.Pmodes[Index].Rectangle.Width,
+      DisplayInfo.Pmodes[Index].Rectangle.Height
+      ));
+    if ((*XRes == 0) || (*YRes == 0)) {
+      *XRes = DisplayInfo.Pmodes[Index].Rectangle.Width;
+      *YRes = DisplayInfo.Pmodes[Index].Rectangle.Height;
+    }
+  }
+}
+
 STATIC
 VOID
 EFIAPI
@@ -199,7 +241,9 @@ GopInitialize (
   IN  EFI_GRAPHICS_OUTPUT_PROTOCOL  *This
   )
 {
-  VGPU_GOP  *VgpuGop;
+  VGPU_GOP    *VgpuGop;
+  EFI_STATUS  Status;
+  UINT32      XRes = 0, YRes = 0, Index;
 
   VgpuGop = VGPU_GOP_FROM_GOP (This);
 
@@ -216,6 +260,37 @@ GopInitialize (
   VgpuGop->GopMode.SizeOfInfo = sizeof VgpuGop->GopModeInfo;
 
   VgpuGop->GopModeInfo.PixelFormat = PixelBltOnly;
+
+  //
+  // query host for display resolution
+  //
+  GopNativeResolution (VgpuGop, &XRes, &YRes);
+  if ((XRes == 0) || (YRes == 0)) {
+    return;
+  }
+
+  if (PcdGet8 (PcdVideoResolutionSource) == 0) {
+    Status = PcdSet32S (PcdVideoHorizontalResolution, XRes);
+    ASSERT_RETURN_ERROR (Status);
+    Status = PcdSet32S (PcdVideoVerticalResolution, YRes);
+    ASSERT_RETURN_ERROR (Status);
+    Status = PcdSet8S (PcdVideoResolutionSource, 2);
+    ASSERT_RETURN_ERROR (Status);
+  }
+
+  VgpuGop->NativeXRes = XRes;
+  VgpuGop->NativeYRes = YRes;
+  for (Index = 0; Index < ARRAY_SIZE (mGopResolutions); Index++) {
+    if ((mGopResolutions[Index].Width == XRes) &&
+        (mGopResolutions[Index].Height == YRes))
+    {
+      // native resolution already is in mode list
+      return;
+    }
+  }
+
+  // add to mode list
+  VgpuGop->GopMode.MaxMode++;
 }
 
 //
@@ -242,10 +317,17 @@ GopQueryMode (
     return EFI_OUT_OF_RESOURCES;
   }
 
-  GopModeInfo->HorizontalResolution = mGopResolutions[ModeNumber].Width;
-  GopModeInfo->VerticalResolution   = mGopResolutions[ModeNumber].Height;
-  GopModeInfo->PixelFormat          = PixelBltOnly;
-  GopModeInfo->PixelsPerScanLine    = mGopResolutions[ModeNumber].Width;
+  if (ModeNumber < ARRAY_SIZE (mGopResolutions)) {
+    GopModeInfo->HorizontalResolution = mGopResolutions[ModeNumber].Width;
+    GopModeInfo->VerticalResolution   = mGopResolutions[ModeNumber].Height;
+  } else {
+    VGPU_GOP  *VgpuGop = VGPU_GOP_FROM_GOP (This);
+    GopModeInfo->HorizontalResolution = VgpuGop->NativeXRes;
+    GopModeInfo->VerticalResolution   = VgpuGop->NativeYRes;
+  }
+
+  GopModeInfo->PixelFormat       = PixelBltOnly;
+  GopModeInfo->PixelsPerScanLine = GopModeInfo->HorizontalResolution;
 
   *SizeOfInfo = sizeof *GopModeInfo;
   *Info       = GopModeInfo;

+ 6 - 0
OvmfPkg/VirtioGpuDxe/VirtioGpu.h

@@ -151,6 +151,12 @@ struct VGPU_GOP_STRUCT {
   // BackingStore is non-NULL.
   //
   VOID                                    *BackingStoreMap;
+
+  //
+  // native display resolution
+  //
+  UINT32                                  NativeXRes;
+  UINT32                                  NativeYRes;
 };
 
 //

+ 6 - 0
OvmfPkg/VirtioGpuDxe/VirtioGpu.inf

@@ -25,6 +25,7 @@
 
 [Packages]
   MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
   OvmfPkg/OvmfPkg.dec
 
 [LibraryClasses]
@@ -43,3 +44,8 @@
   gEfiGraphicsOutputProtocolGuid ## BY_START
   gEfiPciIoProtocolGuid          ## TO_START
   gVirtioDeviceProtocolGuid      ## TO_START
+
+[Pcd]
+  gUefiOvmfPkgTokenSpaceGuid.PcdVideoResolutionSource
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution