libretro / RetroArch

Cross-platform, sophisticated frontend for the libretro API. Licensed GPLv3.
http://www.libretro.com
GNU General Public License v3.0
10.34k stars 1.84k forks source link

[Linux] No absolute positioning for udev pointer devices #13227

Open SeongGino opened 3 years ago

SeongGino commented 3 years ago

Description

When playing Lightgun games on RetroArch with various cores (Flycast, FBNeo, MAME '03, etc.), the cursor device with the udev general input driver always uses the full screen spanning width for aiming an emulated gun device in content that's rendered at non-full aspect ratios - i.e. 4:3 content on 16:9 monitor.

Expected behavior

The pointer cursor should be oriented with relation to the rendered content's screen area after scaling. This would provide line-of-sight aiming when using aspect ratios other than stretch/fullscreen, and aiming outside of the visible window should be considered an offscreen shot. This is the behavior in Linux's x input driver, as well as Windows' rawinput driver.

Actual behavior

The pointer cursor ends up behaving in a manner where it is relative to the content as if it was spanning across the entire width/height of the screen, ignoring the absolute positioning on the monitor. This is behavior similar to standalone MAME.

Steps to reproduce the bug

  1. This requires building RetroArch from master that includes 1ae36ee
  2. Use udev as the general input driver
  3. Set the mouse device index to the device correlating to a lightgun pointer (under Input -> Port 1 Controls), and ensure the video aspect ratio (under Video -> Scaling) is set to anything other than Full.
  4. Launch a lightgun-compatible content - issue observed with Flycast (Dreamcast) and FBNeo (Arcade) cores.
  5. Observe how the device needs to be aimed to the very edge of the monitor to aim similarly to the end-most edges of the emulated content, even when said content is not spanning the full real estate of the display.

Bisect Results

This has not been observed in anything but 9e55654, due to currently unpublishhed improvements enabling my lightgun device to be used.

Version/Commit

Environment information

ghost commented 3 years ago

Looked at the driver does seem to be using the view port not sure what the official stance on this is though.

Edit: this looks like it removed the x11 behavior you required. https://github.com/libretro/RetroArch/commit/f8b42898116fdbf5986fc90596a3447e3071ea65#diff-4e937f8626442bad3c2c482cb46e4b932f5af084c76819bc5ceef4a94db21d83

SeongGino commented 3 years ago

ATM I'm not even able to get the X11 driver to work with the lightgun since the cursor goes flying for no discernable reason, so I've no clue what the commit you're referring to does.

Regardless of which is preferred, it would be nice if there was a choice in the matter. Considering how Windows' rawinput works in Retroarch, I'm more inclined to think this situation is an oversight rather than an intentional design choice - why would they be inconsistent between OSes if the whole point of RetroArch is to unify the experience as best as possible?

Rant aside, I don't enjoy the way it works now, as I'd rather my games be int'd scaled than stretched. And if display-agnostic line-of-sight works on one system, why not the other?

ghost commented 3 years ago

This is the udev driver not the x11 driver that's a separate issue I think unless I've miss read it.

ghost commented 2 years ago

From my perspective udev has this right then again its down to interpretation I guess screen space need to be clarified is the physical space of the device abs coord at device level which is how I interpret it or its it as suggested in the first post in this post.

https://github.com/libretro/libretro-common/blob/b686a5759ed0935da73c58ea8c5a5daaefb10048/include/libretro.h#L129-L137

no where here does it mention scaling to the aspect ratio or the the first posts interpretation of the off screen. Any way would be fine to be honest but having all ports singing the same song would go a far way to help to put this issue to sleep.

arpruss commented 2 years ago

I think there are at two or three reasons why the absolute mouse coordinates should be mapped to the whole screen as requested by this report. First, the current behavior just does not allow line of sight aiming with lightguns that do support line of sight. This seems to me to be primary functionality of light gun code and the best for accurate replication of the original game experience. (I myself use a Wiimote with a custom four LED array around the screen and a python script that emulates an absolute mouse using quadrilateral perspective mapping.) Second, with a real absolute mouse, the present behavior of remapping the full screen coordinates of the mouse to the viewport means vertical and horizontal movements of the mouse are unequally translated to the screen. Typically content has black bars on both sides, and then horizontal mouse movements get squashed. The result is that a 45 degree movement of the mouse results in a different angle on the screen. Finally, I doubt that the present udev behavior works with udev touch screen devices correctly, since it will squish touches within the black bars to be within the content area. But I don't have any udev touchscreen device to test.

ghost commented 2 years ago

Well touchpads and such need the edges to be the analog value. I dont have any touchscreen to test either. Im not sure of how to handle this properly the guys that deal with the api documentation should clear it up to be sure. Another issue is when you speaking relative im assuing you mean relative to the display rather than actual relative mouse movement support for device mouse when the devices is abs

arpruss commented 2 years ago

As I read the udev code (without an actual touchscreen to test), it registers touches in the wrong place. Suppose you have a 16:9 screen and are running 4:3 content in it with black bars. If you touch the left side of the screen, then the current code will report an x value around -32767, which cores will interpret as the left side of the content viewport. And if you touch the left side of the content area, then the current code will report about -24500, which the core will interpret as 25% into the content, i.e., not the place you touch. What we need is that the cores get -32767 when you touch the left edge of the content area, not the left edge of the screen.

ghost commented 2 years ago

I need to double check these view port values im assuming x and y is the mouse

unsigned width = emulation display width; unsigned height = emulation display width; unsigned full_width = full screen width; unsigned full_height = full screen height;

Also the behavior defined above is probably valid for the pointer device the pointer and lightgun might need separated.

https://github.com/libretro/libretro-common/blob/b686a5759ed0935da73c58ea8c5a5daaefb10048/include/libretro.h#L149

arpruss commented 2 years ago

My understanding based on extensive experiments trying to get my lightgun to work is:

vp.full_width / vp.full_height = pixel dimensions of full screen vp.x / vp.y = coordinates of the top left (or maybe bottom left, I didn't check) corner of the emulation viewport vp.width / vp.height = emulation viewport pixel size.

Note that vp.x / vp.y / vp.width / vp.height are in screen coordinates, not emulation coordinates. E.g., for 4/3 content playing in the middle of a 1080P screen, vp.width should be around 1440 regardless of the emulator core, while vp.full_width should be 1920.

Then the udev driver converts the abs mouse coordinates to a -32767 to 32767 range, which cores interpret as ranging over the content area.

ghost commented 2 years ago

With that logic the code looks good to me. I only have a dolphin bar though can test your code and get back to you if you like is there any particular core and games you would like tested?