diff --git a/Configuration/UTMQemuConfigurationDisplay.swift b/Configuration/UTMQemuConfigurationDisplay.swift index 822c354d6b..894e97ae0c 100644 --- a/Configuration/UTMQemuConfigurationDisplay.swift +++ b/Configuration/UTMQemuConfigurationDisplay.swift @@ -28,7 +28,12 @@ struct UTMQemuConfigurationDisplay: Codable, Identifiable { var isDynamicResolution: Bool = true /// Filter to use when upscaling. - var upscalingFilter: QEMUScaler = .nearest + /// + /// Nearest neighbour is only a good fit for low-resolution guests, where it keeps the image + /// sharp instead of washing it out (#3371); the wizard selects it for those. For a modern + /// guest the upscale is rarely an integer ratio, so nearest duplicates source pixels + /// unevenly and looks blocky rather than sharp. + var upscalingFilter: QEMUScaler = .linear /// Filter to use when downscaling. var downscalingFilter: QEMUScaler = .linear diff --git a/Platform/Shared/VMWizardState.swift b/Platform/Shared/VMWizardState.swift index 53f96f2ec4..f4547a9ace 100644 --- a/Platform/Shared/VMWizardState.swift +++ b/Platform/Shared/VMWizardState.swift @@ -475,6 +475,17 @@ struct AlertMessage: Identifiable { config.displays[0].hardware = AnyQEMUConstant(rawValue: newCard)! } } + // Low-resolution guests upscale better with nearest neighbour: linear washes out + // their already-chunky text (#3371). Legacy hardware is checked on its own rather + // than folded into the Windows case so that picking a legacy machine opts in under + // any OS, and because the summary page can enable it after the Windows page has + // latched isWindows10OrHigher. Modern guests keep the linear default, where the + // upscale is a non-integer ratio and nearest looks blocky instead of sharp. + if operatingSystem == .ClassicMacOS || legacyHardware || (operatingSystem == .Windows && !isWindows10OrHigher) { + for i in config.displays.indices { + config.displays[i].upscalingFilter = .nearest + } + } if operatingSystem == .Linux && !isDisplayEnabled { config.displays = [] let newSerial = UTMQemuConfigurationSerial(forArchitecture: systemArchitecture, target: systemTarget)!