@@ -406,6 +406,11 @@ static mut PCI_3D_CMD_BUF: Pci3dCmdBuffer = Pci3dCmdBuffer { data: [0; 16384] };
406406// 1728x1080 matches the QEMU resolution for consistent performance comparison.
407407const DEFAULT_FB_WIDTH : u32 = 1728 ;
408408const DEFAULT_FB_HEIGHT : u32 = 1080 ;
409+ // Minimum resolution floor — ensures the VM window is large enough on Retina Macs.
410+ // With --high-resolution off, 1 guest pixel = 1 Mac screen point, so 1280x960
411+ // gives a ~74% screen-width window on a 1728-point-wide display.
412+ const MIN_FB_WIDTH : u32 = 1280 ;
413+ const MIN_FB_HEIGHT : u32 = 960 ;
409414// Max supported resolution: 2560x1600 @ 32bpp = ~16.4MB
410415const FB_MAX_WIDTH : u32 = 2560 ;
411416const FB_MAX_HEIGHT : u32 = 1600 ;
@@ -1085,28 +1090,31 @@ pub fn init() -> Result<(), &'static str> {
10851090 Err ( e) => crate :: serial_println!( "[virtio-gpu-pci] GET_DISPLAY_INFO failed: {}" , e) ,
10861091 }
10871092
1088- // Use the display-reported resolution. Linux always matches its resources
1089- // to the display mode — gl_display.c uses drmModeGetConnector to get the
1090- // native mode and creates all resources at that resolution. SET_SCANOUT
1091- // with dimensions exceeding the display mode is silently ignored by Parallels.
1092- // DIAG: Force GOP resolution to test if resolution mismatch causes corruption.
1093- // GOP reports 1024x768, GET_DISPLAY_INFO reports 1728x1080. If 2D resource
1094- // must match the GOP physical display mode, using 1728x1080 would cause
1095- // stride mismatch in the hypervisor's display pipeline.
1096- // Use GOP resolution for the 2D resource + BAR0 display path.
1097- // VirGL will use its own resolution (from GET_DISPLAY_INFO) for 3D resources.
1093+ // Pick the largest resolution from: GET_DISPLAY_INFO, GOP, or the minimum.
1094+ // On Retina Macs with --high-resolution off, Parallels maps 1 guest pixel to
1095+ // 1 Mac screen point. GET_DISPLAY_INFO may report only 1024x768 in this mode,
1096+ // but SET_SCANOUT at a larger resolution works fine (Linux does arbitrary mode
1097+ // changes via drmModeSetCrtc → SET_SCANOUT). We enforce a 1280x960 minimum
1098+ // so the VM window is reasonably large on modern displays.
10981099 let gop_w = crate :: platform_config:: fb_width ( ) ;
10991100 let gop_h = crate :: platform_config:: fb_height ( ) ;
1100- let ( use_width, use_height) = if gop_w > 0 && gop_h > 0 {
1101- crate :: serial_println!( "[virtio-gpu-pci] Using GOP resolution {}x{} (display reported {:?})" ,
1102- gop_w, gop_h, display_dims) ;
1103- ( gop_w, gop_h)
1104- } else {
1105- match display_dims {
1106- Ok ( ( dw, dh) ) if dw > 0 && dh > 0 && dw <= FB_MAX_WIDTH && dh <= FB_MAX_HEIGHT => ( dw, dh) ,
1107- _ => ( DEFAULT_FB_WIDTH , DEFAULT_FB_HEIGHT ) ,
1108- }
1109- } ;
1101+ let ( disp_w, disp_h) = display_dims. unwrap_or ( ( 0 , 0 ) ) ;
1102+ // Pick the widest valid resolution, with 1280x960 as floor
1103+ let candidates: [ ( u32 , u32 ) ; 3 ] = [
1104+ ( disp_w, disp_h) ,
1105+ ( gop_w, gop_h) ,
1106+ ( MIN_FB_WIDTH , MIN_FB_HEIGHT ) ,
1107+ ] ;
1108+ let ( use_width, use_height) = candidates
1109+ . iter ( )
1110+ . filter ( |& & ( w, h) | w >= MIN_FB_WIDTH && h > 0 && w <= FB_MAX_WIDTH && h <= FB_MAX_HEIGHT )
1111+ . max_by_key ( |& & ( w, _) | w)
1112+ . copied ( )
1113+ . unwrap_or ( ( MIN_FB_WIDTH , MIN_FB_HEIGHT ) ) ;
1114+ crate :: serial_println!(
1115+ "[virtio-gpu-pci] Resolution: {}x{} (display={}x{}, GOP={}x{}, min={}x{})" ,
1116+ use_width, use_height, disp_w, disp_h, gop_w, gop_h, MIN_FB_WIDTH , MIN_FB_HEIGHT
1117+ ) ;
11101118
11111119 // Update state with actual dimensions
11121120 unsafe {
0 commit comments