raspberrypi / linux

Kernel source tree for Raspberry Pi-provided kernel builds. Issues unrelated to the linux kernel should be posted on the community forum at https://forums.raspberrypi.com/
Other
11.07k stars 4.97k forks source link

Asymmetric overscan prevents mouse from reaching the desktop edge #4447

Open Botspot opened 3 years ago

Botspot commented 3 years ago

Is this the right place for my bug report? Yes, either here or firmware. Jamesh suggested I try opening an issue here first.

Describe the bug If left overscan and right overscan are not equal to one another, the mouse pointer will not be able to cover the entire desktop area.

To reproduce

overscan_left=190
#overscan_right=16
#overscan_top=16
#overscan_bottom=16

Expected behaviour Mouse pointer can move freely across the entire screen.

Actual behaviour Mouse pointer cannot approach the right side of the screen. The closest it can get to the edge is 190px away.

System

Botspot commented 3 years ago

Curious onlookers can review my forum post as well.

6by9 commented 3 years ago

As a quick test can you try altering /boot/config.txt so that you have dtoverlay=vc4-kms-v3d instead of vc4-fkms-v3d, reboot, and see if that has the same issue? That'll allow us to narrow it down between fkms/firmware and kernel framework.

6by9 commented 3 years ago

Can you also give us the output from cat /proc/cmdline?

6by9 commented 3 years ago

To answer my own questions, /proc/cmdline is correct for me in having

 video=HDMI-A-1:3840x2160M@30,margin_left=170,margin_right=0,margin_top=0,margin_bottom=0

And vc4-kms-v3d behaves the same - it clips the X offset to too low a value. X is still moving the mouse pointer off beyond the limit, as if there is something that changes when you hover over it, you see that happen even if it's in the bit the pointer can't get to. Also true in the Y direction if you set overscan_top.

Looking at the code I do see the obvious error https://github.com/raspberrypi/linux/blob/rpi-5.10.y/drivers/gpu/drm/vc4/vc4_plane.c#L313

    vc4_pstate->crtc_x += left;
    if (vc4_pstate->crtc_x > crtc_state->mode.hdisplay - left)
        vc4_pstate->crtc_x = crtc_state->mode.hdisplay - left;

That's wrong and I believe should be simply checking crtc_x against hdisplay without subtracting left. Same for the check on crtc_y a few lines later.

The only check that may be valid is to clip the bits of the image that then fall off the screen, but I think the display list generation does that anyway.

vc4_firmware_kms margins support was copied from vc4_planes, which explains why they both have the same issue.

JamesH65 commented 3 years ago

Same error on line 320 in the vertical coordinates.

6by9 commented 3 years ago

I'll correct myself before someone else does it for me.

if (vc4_pstate->crtc_x > crtc_state->mode.hdisplay - right)
        vc4_pstate->crtc_x = crtc_state->mode.hdisplay - right;

Mentally running through the combinations, I think there is still an issue if we take the example of a 1280x720 display, overscan defined as 100 off the right or bottom, and the application tries to push the image off the right/bottom edge. The source rectangle isn't being cropped, therefore part of the image will be visible in the overscan border.

JamesH65 commented 3 years ago

Reading that function it all seems a bit weird to me.

6by9 commented 3 years ago

Same error on line 320 in the vertical coordinates.

Wasn't that covered by:

That's wrong and I believe should be simply checking crtc_x against hdisplay without subtracting left. Same for the check on crtc_y a few lines later

JamesH65 commented 3 years ago

Yes, sorry, missed that bit.

6by9 commented 3 years ago

Reading that function it all seems a bit weird to me.

Margins in DRM are all a little icky in that they scale the image, but that's the way mainline chose to solve the problem :-/ Getting the maths right to clip every thing correctly is non-trivial, and mistakes are easy to make. This one has been in there since December 2018 and no one has noticed until now!

6by9 commented 3 years ago

I've confirmed via modetest that I can display an image in the overscan region with FKMS (almost certainly applies to KMS too), so that ought to be fixed.

6by9 commented 3 years ago

PR up for the basic issue in #4451

Botspot commented 3 years ago

Can you also give us the output from cat /proc/cmdline?

coherent_pool=1M 8250.nr_uarts=0 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1 video=HDMI-A-1:640x480M@60,margin_left=180,margin_right=180,margin_top=0,margin_bottom=0 smsc95xx.macaddr=DC:A6:32:B2:F2:2B vc_mem.mem_base=0x3eb00000 vc_mem.mem_size=0x3ff00000  usb-storage.quirks=174c:1153:u console=ttyS0,115200 console=tty1 root=PARTUUID=4b002859-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
pelwell commented 3 years ago

The PR that fixes this problem has been merged - future kernel builds should allow you to reach all corners of the desktop.

Botspot commented 3 years ago

The PR that fixes this problem has been merged - future kernel builds should allow you to reach all corners of the desktop.

Thank you guys so much! Before I close this issue, I was wondering if the X server could be changed so that it was not being squished by overscan. Right now, all "circles" on my screen appear like ovals, some rectangles look like squares, and everything is blurry compared to before applying overscan. Would it be possible to tell my X server to subtract the overscan values from it's own dimensions so that everything stays crisp and square?

6by9 commented 3 years ago

Sorry, that's inherent in the way mainline Linux has implemented overscan.

The original framebuffer driver implementation reduced the frame buffer size to compensate for overscan, and kept the pixel mapping at 1:1. eg 1920x1080 with 48 pixel on each side ended up with a 1824x984 frame buffer.

The mainline Linux implementation keeps the display as being at the native resolution, and then scales and offsets all planes to the appropriate margins. It would have been nice to have tweaked all the modes advertised to userspace to be cropped as before, but doing that now is going to be tricky.

Botspot commented 3 years ago

Sorry, that's inherent in the way mainline Linux has implemented overscan.

The original framebuffer driver implementation reduced the frame buffer size to compensate for overscan, and kept the pixel mapping at 1:1. eg 1920x1080 with 48 pixel on each side ended up with a 1824x984 frame buffer.

The mainline Linux implementation keeps the display as being at the native resolution, and then scales and offsets all planes to the appropriate margins. It would have been nice to have tweaked all the modes advertised to userspace to be cropped as before, but doing that now is going to be tricky.

Can you think of any messy workarounds? To me it seems like many people would appreciate the pixel mapping being kept at 1:1 for clarity.

Botspot commented 3 years ago

Would it be possible to manually override the x server/framebuffer dimensions?