Abstract libwacom database initialization into a single place

No real changes for the non-tablet code, but for tablets we now keep the
libwacom datbase around. The primary motivating factor here is response time
during tests - initializing the database under valgrind took longer than the
proximity timeouts and caused random test case failures when a proximity out
was triggered before we even got to process the first event.

This is unfortunately a burden on the runtime now since we keep libwacom
around whenever a tablet is connected. Not much of an impact though, I
suspect, chances are you're running a web browser and everything pales against
that anyway.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer 2019-05-27 18:21:09 +10:00
parent 9b414faea2
commit ee1bc318d5
8 changed files with 91 additions and 38 deletions

View file

@ -215,7 +215,7 @@ src_libinput_util = [
] ]
libinput_util = static_library('libinput-util', libinput_util = static_library('libinput-util',
src_libinput_util, src_libinput_util,
dependencies : [dep_udev, dep_libevdev], dependencies : [dep_udev, dep_libevdev, dep_libwacom],
include_directories : includes_include) include_directories : includes_include)
dep_libinput_util = declare_dependency(link_with : libinput_util) dep_libinput_util = declare_dependency(link_with : libinput_util)
@ -233,7 +233,7 @@ src_libfilter = [
'src/filter-private.h' 'src/filter-private.h'
] ]
libfilter = static_library('filter', src_libfilter, libfilter = static_library('filter', src_libfilter,
dependencies : dep_udev, dependencies : [dep_udev, dep_libwacom],
include_directories : includes_include) include_directories : includes_include)
dep_libfilter = declare_dependency(link_with : libfilter) dep_libfilter = declare_dependency(link_with : libfilter)
@ -290,7 +290,7 @@ src_libquirks = [
'src/builddir.h', 'src/builddir.h',
] ]
deps_libquirks = [dep_udev, dep_libinput_util] deps_libquirks = [dep_udev, dep_libwacom, dep_libinput_util]
libquirks = static_library('quirks', src_libquirks, libquirks = static_library('quirks', src_libquirks,
dependencies : deps_libquirks, dependencies : deps_libquirks,
include_directories : includes_include) include_directories : includes_include)

View file

@ -3851,6 +3851,7 @@ tp_requires_rotation(struct tp_dispatch *tp, struct evdev_device *device)
{ {
bool rotate = false; bool rotate = false;
#if HAVE_LIBWACOM #if HAVE_LIBWACOM
struct libinput *li = tp_libinput_context(tp);
WacomDeviceDatabase *db = NULL; WacomDeviceDatabase *db = NULL;
WacomDevice **devices = NULL, WacomDevice **devices = NULL,
**d; **d;
@ -3861,12 +3862,9 @@ tp_requires_rotation(struct tp_dispatch *tp, struct evdev_device *device)
if ((device->tags & EVDEV_TAG_TABLET_TOUCHPAD) == 0) if ((device->tags & EVDEV_TAG_TABLET_TOUCHPAD) == 0)
goto out; goto out;
db = libwacom_database_new(); db = libinput_libwacom_ref(li);
if (!db) { if (!db)
evdev_log_info(device,
"Failed to initialize libwacom context.\n");
goto out; goto out;
}
/* Check if we have a device with the same vid/pid. If not, /* Check if we have a device with the same vid/pid. If not,
we need to loop through all devices and check their paired we need to loop through all devices and check their paired
@ -3896,9 +3894,12 @@ tp_requires_rotation(struct tp_dispatch *tp, struct evdev_device *device)
} }
free(devices); free(devices);
out: out:
/* We don't need to keep it around for the touchpad, we're done with
* it until the device dies. */
if (db) if (db)
libwacom_database_destroy(db); libinput_libwacom_unref(li);
#endif #endif
return rotate; return rotate;

View file

@ -490,16 +490,14 @@ static int
pad_init_leds_from_libwacom(struct pad_dispatch *pad, pad_init_leds_from_libwacom(struct pad_dispatch *pad,
struct evdev_device *device) struct evdev_device *device)
{ {
struct libinput *li = pad_libinput_context(pad);
WacomDeviceDatabase *db = NULL; WacomDeviceDatabase *db = NULL;
WacomDevice *wacom = NULL; WacomDevice *wacom = NULL;
int rc = 1; int rc = 1;
db = libwacom_database_new(); db = libinput_libwacom_ref(li);
if (!db) { if (!db)
evdev_log_info(device,
"Failed to initialize libwacom context.\n");
goto out; goto out;
}
wacom = libwacom_new_from_path(db, wacom = libwacom_new_from_path(db,
udev_device_get_devnode(device->udev_device), udev_device_get_devnode(device->udev_device),
@ -522,7 +520,7 @@ out:
if (wacom) if (wacom)
libwacom_destroy(wacom); libwacom_destroy(wacom);
if (db) if (db)
libwacom_database_destroy(db); libinput_libwacom_unref(li);
if (rc != 0) if (rc != 0)
pad_destroy_leds(pad); pad_destroy_leds(pad);

View file

@ -529,17 +529,15 @@ pad_init_buttons_from_libwacom(struct pad_dispatch *pad,
{ {
bool rc = false; bool rc = false;
#if HAVE_LIBWACOM_GET_BUTTON_EVDEV_CODE #if HAVE_LIBWACOM_GET_BUTTON_EVDEV_CODE
struct libinput *li = pad_libinput_context(pad);
WacomDeviceDatabase *db = NULL; WacomDeviceDatabase *db = NULL;
WacomDevice *tablet = NULL; WacomDevice *tablet = NULL;
int num_buttons; int num_buttons;
int map = 0; int map = 0;
db = libwacom_database_new(); db = libinput_libwacom_ref(li);
if (!db) { if (!db)
evdev_log_info(device,
"Failed to initialize libwacom context.\n");
goto out; goto out;
}
tablet = libwacom_new_from_usbid(db, tablet = libwacom_new_from_usbid(db,
evdev_device_get_id_vendor(device), evdev_device_get_id_vendor(device),
@ -566,7 +564,7 @@ out:
if (tablet) if (tablet)
libwacom_destroy(tablet); libwacom_destroy(tablet);
if (db) if (db)
libwacom_database_destroy(db); libinput_libwacom_unref(li);
#endif #endif
return rc; return rc;
} }

View file

@ -913,15 +913,13 @@ tool_set_bits_from_libwacom(const struct tablet_dispatch *tablet,
WacomStylusType type; WacomStylusType type;
WacomAxisTypeFlags axes; WacomAxisTypeFlags axes;
db = libwacom_database_new(); db = tablet_libinput_context(tablet)->libwacom.db;
if (!db) { if (!db)
evdev_log_info(tablet->device, return rc;
"Failed to initialize libwacom context.\n");
goto out;
}
s = libwacom_stylus_get_for_id(db, tool->tool_id); s = libwacom_stylus_get_for_id(db, tool->tool_id);
if (!s) if (!s)
goto out; return rc;
type = libwacom_stylus_get_type(s); type = libwacom_stylus_get_type(s);
if (type == WSTYLUS_PUCK) { if (type == WSTYLUS_PUCK) {
@ -965,9 +963,6 @@ tool_set_bits_from_libwacom(const struct tablet_dispatch *tablet,
copy_axis_cap(tablet, tool, LIBINPUT_TABLET_TOOL_AXIS_PRESSURE); copy_axis_cap(tablet, tool, LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
rc = 0; rc = 0;
out:
if (db)
libwacom_database_destroy(db);
#endif #endif
return rc; return rc;
} }
@ -1990,6 +1985,7 @@ tablet_destroy(struct evdev_dispatch *dispatch)
{ {
struct tablet_dispatch *tablet = tablet_dispatch(dispatch); struct tablet_dispatch *tablet = tablet_dispatch(dispatch);
struct libinput_tablet_tool *tool, *tmp; struct libinput_tablet_tool *tool, *tmp;
struct libinput *li = tablet_libinput_context(tablet);
libinput_timer_cancel(&tablet->quirks.prox_out_timer); libinput_timer_cancel(&tablet->quirks.prox_out_timer);
libinput_timer_destroy(&tablet->quirks.prox_out_timer); libinput_timer_destroy(&tablet->quirks.prox_out_timer);
@ -1998,6 +1994,8 @@ tablet_destroy(struct evdev_dispatch *dispatch)
libinput_tablet_tool_unref(tool); libinput_tablet_tool_unref(tool);
} }
libinput_libwacom_unref(li);
free(tablet); free(tablet);
} }
@ -2317,6 +2315,9 @@ struct evdev_dispatch *
evdev_tablet_create(struct evdev_device *device) evdev_tablet_create(struct evdev_device *device)
{ {
struct tablet_dispatch *tablet; struct tablet_dispatch *tablet;
struct libinput *li = evdev_libinput_context(device);
libinput_libwacom_ref(li);
/* Stop false positives caused by the forced proximity code */ /* Stop false positives caused by the forced proximity code */
if (getenv("LIBINPUT_RUNNING_TEST_SUITE")) if (getenv("LIBINPUT_RUNNING_TEST_SUITE"))

View file

@ -2700,17 +2700,15 @@ evdev_tablet_has_left_handed(struct evdev_device *device)
{ {
bool has_left_handed = false; bool has_left_handed = false;
#if HAVE_LIBWACOM #if HAVE_LIBWACOM
WacomDeviceDatabase *db; struct libinput *li = evdev_libinput_context(device);
WacomDeviceDatabase *db = NULL;
WacomDevice *d = NULL; WacomDevice *d = NULL;
WacomError *error; WacomError *error;
const char *devnode; const char *devnode;
db = libwacom_database_new(); db = libinput_libwacom_ref(li);
if (!db) { if (!db)
evdev_log_info(device,
"failed to initialize libwacom context.\n");
goto out; goto out;
}
error = libwacom_error_new(); error = libwacom_error_new();
devnode = udev_device_get_devnode(device->udev_device); devnode = udev_device_get_devnode(device->udev_device);
@ -2737,7 +2735,8 @@ evdev_tablet_has_left_handed(struct evdev_device *device)
libwacom_error_free(&error); libwacom_error_free(&error);
if (d) if (d)
libwacom_destroy(d); libwacom_destroy(d);
libwacom_database_destroy(db); if (db)
libinput_libwacom_unref(li);
out: out:
#endif #endif

View file

@ -31,6 +31,10 @@
#include <math.h> #include <math.h>
#include <stdarg.h> #include <stdarg.h>
#if HAVE_LIBWACOM
#include <libwacom/libwacom.h>
#endif
#include "linux/input.h" #include "linux/input.h"
#include "libinput.h" #include "libinput.h"
@ -155,6 +159,13 @@ struct libinput {
bool quirks_initialized; bool quirks_initialized;
struct quirks_context *quirks; struct quirks_context *quirks;
#if HAVE_LIBWACOM
struct {
WacomDeviceDatabase *db;
size_t refcount;
} libwacom;
#endif
}; };
typedef void (*libinput_seat_destroy_func) (struct libinput_seat *seat); typedef void (*libinput_seat_destroy_func) (struct libinput_seat *seat);
@ -837,4 +848,15 @@ point_in_rect(const struct device_coords *point,
point->y < rect->y + rect->h); point->y < rect->y + rect->h);
} }
#if HAVE_LIBWACOM
WacomDeviceDatabase *
libinput_libwacom_ref(struct libinput *li);
void
libinput_libwacom_unref(struct libinput *li);
#else
static inline void *libinput_libwacom_ref(struct libinput *li) { return NULL; }
static inline void libinput_libwacom_unref(struct libinput *li) {}
#endif
#endif /* LIBINPUT_PRIVATE_H */ #endif /* LIBINPUT_PRIVATE_H */

View file

@ -4164,3 +4164,37 @@ libinput_device_config_rotation_get_default_angle(struct libinput_device *device
return device->config.rotation->get_default_angle(device); return device->config.rotation->get_default_angle(device);
} }
#if HAVE_LIBWACOM
WacomDeviceDatabase *
libinput_libwacom_ref(struct libinput *li)
{
WacomDeviceDatabase *db = NULL;
if (!li->libwacom.db) {
db = libwacom_database_new();
if (!db) {
log_error(li,
"Failed to initialize libwacom context\n");
return NULL;
}
li->libwacom.db = db;
li->libwacom.refcount = 0;
}
li->libwacom.refcount++;
db = li->libwacom.db;
return db;
}
void
libinput_libwacom_unref(struct libinput *li)
{
assert(li->libwacom.refcount >= 1);
if (--li->libwacom.refcount == 0) {
libwacom_database_destroy(li->libwacom.db);
li->libwacom.db = NULL;
}
}
#endif