[PATCH libinput 06/16] filter: explain the acceleration function in detail
Jonas Ådahl
jadahl at gmail.com
Mon Aug 10 01:21:34 PDT 2015
On Wed, Aug 05, 2015 at 04:32:35PM +1000, Peter Hutterer wrote:
> And switch to a code-flow that's a bit more self-explanatory than the current
> min/max combinations.
>
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
Much much more easy to follow now. Most of the reviewing time of this
patch was trying to re-understand and confirm the f1 f2 min max code
did what the new description explains. The new code make that a lot more
obvious.
Reviewed-by: Jonas Ådahl <jadahl at gmail.com>
> ---
> src/filter.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------
> 1 file changed, 73 insertions(+), 10 deletions(-)
>
> diff --git a/src/filter.c b/src/filter.c
> index b42db35..4f0d8d5 100644
> --- a/src/filter.c
> +++ b/src/filter.c
> @@ -421,19 +421,26 @@ pointer_accel_profile_linear_low_dpi(struct motion_filter *filter,
> struct pointer_accelerator *accel_filter =
> (struct pointer_accelerator *)filter;
>
> - double f1, f2; /* unitless */
> double max_accel = accel_filter->accel; /* unitless factor */
> - const double threshold = accel_filter->threshold; /* units/us */
> + double threshold = accel_filter->threshold; /* units/us */
> const double incline = accel_filter->incline;
> double factor; /* unitless */
> double dpi_factor = accel_filter->dpi_factor;
>
> + /* dpi_factor is always < 1.0, increase max_accel, reduce
> + the threshold so it kicks in earlier */
> max_accel /= dpi_factor;
> + threshold *= dpi_factor;
>
> - f1 = min(1, 0.3 + v_us2ms(speed_in) * 10.0);
> - f2 = 1 + (v_us2ms(speed_in) - v_us2ms(threshold) * dpi_factor) * incline;
> + /* see pointer_accel_profile_linear for a long description */
> + if (v_us2ms(speed_in) < 0.07)
> + factor = 10 * v_us2ms(speed_in) + 0.3;
> + else if (speed_in < threshold)
> + factor = 1;
> + else
> + factor = incline * v_us2ms(speed_in - threshold) + 1;
>
> - factor = min(max_accel, f2 > 1 ? f2 : f1);
> + factor = min(max_accel, factor);
>
> return factor;
> }
> @@ -446,17 +453,67 @@ pointer_accel_profile_linear(struct motion_filter *filter,
> {
> struct pointer_accelerator *accel_filter =
> (struct pointer_accelerator *)filter;
> -
> - double f1, f2; /* unitless */
> const double max_accel = accel_filter->accel; /* unitless factor */
> const double threshold = accel_filter->threshold; /* units/us */
> const double incline = accel_filter->incline;
> double factor; /* unitless */
>
> - f1 = min(1, 0.3 + v_us2ms(speed_in) * 10);
> - f2 = 1 + (v_us2ms(speed_in) - v_us2ms(threshold)) * incline;
> + /*
> + Our acceleration function calculates a factor to accelerate input
> + deltas with. The function is a double incline with a plateau,
> + with a rough shape like this:
>
> - factor = min(max_accel, f2 > 1 ? f2 : f1);
> + accel
> + factor
> + ^
> + | /
> + | _____/
> + | /
> + |/
> + +-------------> speed in
> +
> + The two inclines are linear functions in the form
> + y = ax + b
> + where y is speed_out
> + x is speed_in
> + a is the incline of acceleration
> + b is minimum acceleration factor
> +
> + for speeds up to 0.07 u/ms, we decelerate, down to 30% of input
> + speed.
> + hence 1 = a * 0.07 + 0.3
> + 0.3 = a * 0.00 + 0.3 => a := 10
> + deceleration function is thus:
> + y = 10x + 0.3
> +
> + Note:
> + * 0.07u/ms as threshold is a result of trial-and-error and
> + has no other intrinsic meaning.
> + * 0.3 is chosen simply because it is above the Nyquist frequency
> + for subpixel motion within a pixel.
> + */
> + if (v_us2ms(speed_in) < 0.07) {
> + factor = 10 * v_us2ms(speed_in) + 0.3;
> + /* up to the threshold, we keep factor 1, i.e. 1:1 movement */
> + } else if (speed_in < threshold) {
> + factor = 1;
> +
> + } else {
> + /* Acceleration function above the threshold:
> + y = ax' + b
> + where T is threshold
> + x is speed_in
> + x' is speed
> + and
> + y(T) == 1
> + hence 1 = ax' + 1
> + => x' := (x - T)
> + */
> + factor = incline * v_us2ms(speed_in - threshold) + 1;
> + }
> +
> + /* Cap at the maximum acceleration factor */
> + factor = min(max_accel, factor);
>
> return factor;
> }
> @@ -509,6 +566,12 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter,
> TP_MAGIC_LOW_RES_FACTOR; /* units/us */
> const double incline = accel_filter->incline * TP_MAGIC_LOW_RES_FACTOR;
>
> + /* Note: the magic values in this function are obtained by
> + * trial-and-error. No other meaning should be interpreted.
> + * The calculation is a compressed form of
> + * pointer_accel_profile_linear(), look at the git history of that
> + * function for an explaination of what the min/max/etc. does.
> + */
> speed_in *= TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR;
>
> f1 = min(1, v_us2ms(speed_in) * 5);
> --
> 2.4.3
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
More information about the wayland-devel
mailing list