Re: input_defuzz_abs_event considered harmful

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Mar 02, 2018 at 09:21:34PM +0300, Konstantin Kharlamov wrote:
> On 02.03.2018 03:20, Peter Hutterer wrote:
> > There, now I have your attention, right? :)
> > 
> > TLDR: input_defuzz_abs_event() produces pointer jumps at certain slow
> > movement speeds and I don't know what to do about it.
> > 
> > While dealing with pointer jitter issues in libinput I stumbled into an
> > issue with how the fuzz value in the kernel is handled during
> > input_defuzz_abs_event(). Specifically, the response is nonlinear and can
> > lead to jumpy pointer movement for deltas d = fuzz and d = fuzz * 2.
> > 
> > Note, this bug affects a moving pointer, not a stationary one. For that the
> > defuzzing works as intended. Let's assume that with a perceived-constant
> > finger motion speed, you'll get deltas in the range (fuzz * 2) ± 3.
> > 
> > input_defuzz_abs_event() returns:
> >    d = fuzz * 2 - 3 → value returned: fuzz - 1
> >    d = fuzz * 2 - 2 → value returned: fuzz - 1
> >    d = fuzz * 2     → value returned: fuzz * 2
> >    d = fuzz * 2 + 1 → value returned: fuzz * 2 + 1
> >    d = fuzz * 2 + 2 → value returned: fuzz * 2 + 2
> > 
> > There's another jump at the fuzz ± 2 range. In concrete numbers for a fuzz
> > of 8, input deltas result in values:
> > 
> >    d = 6 → value 1
> >    d = 7 → value 1
> >    d = 8 → value 4
> >    d = 9 → value 4
> >    ...
> >    d = 14 → value 7
> >    d = 15 → value 7
> >    d = 16 → value 16
> >    d = 17 → value 17
> >    d = 18 → value 18
> > 
> > i.e. at the fuzz and fuzz * 2 points we see a jump of approx size fuzz/2 and
> > fuzz, respectively. These are integer divisons, so some variance is expected.
> > Obviously the numbers change for higher fuzz values but 8 seems to be the
> > most common one.
> > 
> > A few more details and a python script to recreate this and play around with
> > it: https://bugs.freedesktop.org/show_bug.cgi?id=105303
> > 
> > In real terms, this means that a pointer moving at a percieved-constant
> > speed will provide deltas of [7, 7, 16, 7, 16, 16, 7, 16, 7]. And if we were
> > to rely on the fuzz in userspace as hint for our hysteresis, we'd end up
> > filtering the 7 values but letting the 16 values pass through. This gives us
> > pointer jumps.
> > 
> > Those jumps happen right at the slow speed where we're moving slow enough to
> > notice them. Ironically, slowing down to check what just happened will not
> > reproduce the problem. The defuzzed value is used as 'old' value for the
> > algorithm, so there's a feedback loop as well. So it's very hard to
> > reproduce consistently, you cannot really get a [7, 16, 7, 16] motion with
> > human input. But it's like bad kerning, once you see it you cannot unsee it
> > :)
> > 
> > I'm a bit out of ideas on how to deal with this:
> > 1) improve the algorithm in the kernel so the response is more linear
> > 2) figure out a way how to undo the kernel defuzz in userspace and
> >    do hysteresis based on the reconstructed raw value
> > 3) provide some way of disabling in-kernel hysteres while leaving fuzz set
> > 4) force the fuzz to 0, while remembering what it should be
> > 
> > Neither of them is ideal, but 4 seems the best, with caveats.
> > 
> > 1) can remove (some of) the jumps but since we already get processed
> >     coordinates, doing the correct thing in libinput is harder
> 
> Another contra to 1 would be: userspace is easier to debug.
> 
> > 2) possibly possible, but will be lossy or inaccurate
> > 3) would require some new ioctl and per-client behaviour. not ideal
> > 4) this one is both the easiest and messiest. The approach would be:
> >   * a udev rule extracts the fuzz value into a AXIS_FUZZ=$fuzz property
> >   * use EVIOCSABS to set the fuzz to 0 (thus disabling kernel defuzzing),
> >   * have libinput init the hysteresis based on AXIS_FUZZ
> >   * pray that no other input-handling clients relies on kernel fuzzing
> >     because we just changed the kernel device
> > 
> > Any suggestions on how to handle this would be appreciated.
> 
> I'm voting for the 4th option too. I'm wondering if there's a way to find
> default fuzz values after they have been set to zero, i.e. to use them after
> X11/compositor restart/crash.
> 
> Do I correctly understand though that the fuzz value is used by kernel to do
> some hysteresis algo on its own (i.e. the input_defuzz_abs_event())?

correct

> If it
> is, I think it'd be better to remove this algorithm from the kernel
> whatsoever — it'd allow to not even force fuzz values to zero (well, at
> least not for patched kernels).

as usual, removing something from the kernel is tricky and risky, who knows
if anything relies on that defuzzing :)

Preliminary patch set for 4) is available here:
https://lists.freedesktop.org/archives/wayland-devel/2018-March/037299.html

Cheers,
   Peter
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux