1
0
Fork 0

backends/native: Use a pre-sampled bezier pressure curve

Based on the pressure curve control points sample a bezier curve and
then look up the pressure at that point of the curve.

We sample 256 points and do linear interpolation in between, this
strikes a balance between having to calculate the point for all
8K pressure points a modern pen supports while still giving us
reasonable detailed curves.

Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3158
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3399>
This commit is contained in:
Peter Hutterer 2023-12-15 10:10:52 +10:00 committed by Marge Bot
parent 4d6add290e
commit e7ba16689d
2 changed files with 39 additions and 30 deletions

View file

@ -31,6 +31,7 @@ meta_input_device_tool_native_finalize (GObject *object)
g_hash_table_unref (tool->button_map);
libinput_tablet_tool_unref (tool->tool);
meta_bezier_free (tool->bezier);
G_OBJECT_CLASS (meta_input_device_tool_native_parent_class)->finalize (object);
}
@ -49,6 +50,20 @@ meta_input_device_tool_native_init (MetaInputDeviceToolNative *tool)
tool->button_map = g_hash_table_new (NULL, NULL);
}
static void
init_pressurecurve (MetaInputDeviceToolNative *tool)
{
MetaBezier *bezier = meta_bezier_new (N_PRESSURECURVE_POINTS);
g_clear_pointer (&tool->bezier, meta_bezier_free);
meta_bezier_init (bezier,
tool->pressure_curve[0].x,
tool->pressure_curve[0].y,
tool->pressure_curve[1].x,
tool->pressure_curve[1].y);
tool->bezier = bezier;
}
static ClutterInputAxisFlags
translate_axes (struct libinput_tablet_tool *tool)
{
@ -86,6 +101,8 @@ meta_input_device_tool_native_new (struct libinput_tablet_tool *tool,
evdev_tool->tool = libinput_tablet_tool_ref (tool);
init_pressurecurve (evdev_tool);
return CLUTTER_INPUT_DEVICE_TOOL (evdev_tool);
}
@ -94,6 +111,7 @@ meta_input_device_tool_native_set_pressure_curve_in_impl (ClutterInputDeviceTool
double curve[4])
{
MetaInputDeviceToolNative *evdev_tool;
graphene_point_t p1, p2;
g_return_if_fail (META_IS_INPUT_DEVICE_TOOL_NATIVE (tool));
g_return_if_fail (curve[0] >= 0 && curve[0] <= 1 &&
@ -101,11 +119,19 @@ meta_input_device_tool_native_set_pressure_curve_in_impl (ClutterInputDeviceTool
curve[2] >= 0 && curve[2] <= 1 &&
curve[3] >= 0 && curve[3] <= 1);
p1.x = curve[0];
p1.y = curve[1];
p2.x = curve[2];
p2.y = curve[3];
evdev_tool = META_INPUT_DEVICE_TOOL_NATIVE (tool);
evdev_tool->pressure_curve[0].x = curve[0];
evdev_tool->pressure_curve[0].y = curve[1];
evdev_tool->pressure_curve[1].x = curve[2];
evdev_tool->pressure_curve[1].y = curve[3];
if (!graphene_point_equal (&p1, &evdev_tool->pressure_curve[0]) ||
!graphene_point_equal (&p2, &evdev_tool->pressure_curve[1]))
{
evdev_tool->pressure_curve[0] = p1;
evdev_tool->pressure_curve[1] = p2;
init_pressurecurve (evdev_tool);
}
}
void
@ -130,42 +156,21 @@ meta_input_device_tool_native_set_button_code_in_impl (ClutterInputDeviceTool *t
}
}
static double
calculate_bezier_position (double pos,
double x1,
double y1,
double x2,
double y2)
{
double int1_y, int2_y;
pos = CLAMP (pos, 0, 1);
/* Intersection between 0,0 and x1,y1 */
int1_y = pos * y1;
/* Intersection between x2,y2 and 1,1 */
int2_y = (pos * (1 - y2)) + y2;
/* Find the new position in the line traced by the previous points */
return (pos * (int2_y - int1_y)) + int1_y;
}
double
meta_input_device_tool_native_translate_pressure_in_impl (ClutterInputDeviceTool *tool,
double pressure)
{
MetaInputDeviceToolNative *evdev_tool;
double factor;
g_return_val_if_fail (META_IS_INPUT_DEVICE_TOOL_NATIVE (tool), pressure);
evdev_tool = META_INPUT_DEVICE_TOOL_NATIVE (tool);
return calculate_bezier_position (CLAMP (pressure, 0, 1),
evdev_tool->pressure_curve[0].x,
evdev_tool->pressure_curve[0].y,
evdev_tool->pressure_curve[1].x,
evdev_tool->pressure_curve[1].y);
pressure = CLAMP (pressure, 0.0, 1.0);
factor = meta_bezier_lookup (evdev_tool->bezier, pressure);
return pressure * factor;
}
uint32_t

View file

@ -26,6 +26,7 @@
#include <graphene.h>
#include <libinput.h>
#include "backends/native/meta-bezier.h"
#include "clutter/clutter.h"
G_BEGIN_DECLS
@ -55,12 +56,15 @@ G_BEGIN_DECLS
typedef struct _MetaInputDeviceToolNative MetaInputDeviceToolNative;
typedef struct _MetaInputDeviceToolNativeClass MetaInputDeviceToolNativeClass;
#define N_PRESSURECURVE_POINTS 256
struct _MetaInputDeviceToolNative
{
ClutterInputDeviceTool parent_instance;
struct libinput_tablet_tool *tool;
GHashTable *button_map;
graphene_point_t pressure_curve[2];
MetaBezier *bezier;
};
struct _MetaInputDeviceToolNativeClass