Page MenuHome

Generic Tablet on Linux - Erratic strokes with pressure sensitivity enabled
Closed, ResolvedPublic

Description

System Information
Kubuntu Linux 14.04 64 bits (Kernel 4.2.0-7-generic)
GTX 960
Genius EasyPen i405 (UC-Logic WP5540U)

Blender Version
Broken: 2.73a,nuildbot 9c916b0, master

Short description of error
Hello.
I've noticed this problem when I tried the new feature curve draw from master. But the problem also happen with texture paint. I have not been able to verify whether this also occurs with grease pencil. Having pressure sensitivity enabled, the stroke is erratic (it is choppy, dotted lines appear). The problem is most evident when you draw slow strokes. If you draw fast strokes, the problem is less frequent. In the file that I share I tested with texture paint, curve draw and grease pencil. To your left are the strokes drawn slowly. To the right, fast strokes.
The graphic tablet is a Genius EasyPen i405 (UC-Logic WP5540U) using evdev through this generic driver:
https://digimend.github.io/tablets/UC-Logic_WP5540U/

The problem does not occur in Windows with Blender.
GIMP on linux apparently works well with pressure sensitivity enabled .

Exact steps for others to reproduce the error
Draw with my graphics tablet in linux with pressure sensitivity enabled :)

Event Timeline

YAFU (YAFU) raised the priority of this task from to 90.
YAFU (YAFU) updated the task description. (Show Details)
YAFU (YAFU) added a project: BF Blender.
YAFU (YAFU) edited a custom field.
YAFU (YAFU) added a subscriber: YAFU (YAFU).

This looks like there is noise/jitter in the tablet's input values (+/- a pixel).
Possibly the gimp 'filters' the input so it doesn't show up as a problem.

Could you try drawing a single pixel line with a simple paint application (pinta) for example, to see if the noise is visible in this case?

YAFU (YAFU) added a comment.EditedApr 20 2016, 4:31 PM

Hello, here the test with pinta on Linux and Windows:

On the left without antialiasing, right with antialiasing.
Zooming the images, it seems that in the line Linux is a bit more dotted?

Anyway I do not know if pinta allows pressure sensitivity, I did not find the option.

This is what I get from "evtest" drawing a curved line along the verticlal:

You do not consider the first and last values of the list, where the pen tip was not touching the tablet. In the middle of the list are spaces/jumps where (ABS_PRESSURE) is not present. Do you think that might be the problem? Could someone try on Linux and evtest with a tablet where there is no problem, and compare with my values?

Using this script, converted the events to an OBJ and they don't seem all that jittery

# tablet_WP5540U_evtest.txt
event_text = """
...
"""

evt = [None, None]
ls = []
for l in event_text.split("\n"):
    if   "(ABS_X)" in l: evt[0] = int(l.split()[-1])
    elif "(ABS_Y)" in l: evt[1] = int(l.split()[-1])
    if None not in evt:
        ls.append(evt)
        evt = [None, None]

# write OBJ
print("v 0 0 0")
for evt in ls:
    print("v %d %d 0" % tuple(evt))
    print("f -1 -2")

Hello. The previous evtest was obtained by drawing the curve "on the air" over the desktop. Just in case, this evtest was obtained by drawing the curve in Blender:

Many tests on Linux: KDE, Xfce. Kubuntu 14.04, 15.04, 16.04. GIMP, Krita, MyPaint. Empty blender config folder. I only noticed the problem in Blender in Linux. In this video you can see that this is most noticeable in vertical strokes than in horizontal lines:
https://www.dropbox.com/s/ib4iahznz9rpd4f/texture%20paint%20tablet.mp4

I asked in DIGImend mailing list to see if they can give me a clue.
Thanks.

Hi. No, I do not notice changes in curve draw or texture paint. This is still broken. Compiled from master (hash: b1f6cd5)
By the way, I've contacted by mail to a person who has a similar tablet:
https://github.com/wavewave/hoodle/issues/40

which I have explained how to do the test with texture paint .blend file into "tablet_WP5540U_evtest.zip". He has confirmed to me that he has the same problem with Blender on Linux. I know that this does not provide much to this report, but this helps me to know that this is not only a problem with my hardware.
DIGImend people have not yet responded.

Would have tried that here, used to have an UC-LOGIC Tablet WP5540U (Genius G-Pen 450), but that piece of crap is dying on me now it seems… Will see if i can get it work again, does not sounds very promising.

Note that our Blender code is still using old XInput API, while at least gimp (and probably other qt/gtk apps too) are now on XInput2, might explain the difference. I already fixed some issues with that hardware, which were related to how xinput/evdev changed the 'tablet messages' (see rB0d5ebabe437, rBe63594a6e5d), so could be similar issue again.

Thing is, without a dev able to test with that kind of hardware, this is going to be *very* hard to nail down…

Bastien Montagne (mont29) lowered the priority of this task from 90 to Normal.May 2 2016, 12:24 PM
YAFU (YAFU) added a comment.EditedMay 4 2016, 12:14 AM

Thanks Bestien. I know it is difficult for developers if they do not have one of these graphics tablets.

I have contacted Dmitry Kazakov who has helped to get support for evdev graphics tablets on Krita. He is on the #krita IRC channel (nick: dmirtyK|log). He allowed me to share his answer here in the report, just in case this be something useful for you::

I don't know how to use Blender, so I cannot check the files attached, but I can judge basing on the video [0] and events log [1] attached.

Genius tablet's driver (at least in XInput1 implementation) has a weird property. It sends tablet events for partial changes, that is the application can get separate events for changes in each valuator supported by the tablet. That is, you can get the following events:

1) Pointer changed X coordinate by N pixels
2) Pointer changed Y coordinate by N pixels
3) Pointer changed its pressure by some amount.

If the application parses all these events as separate events and initiates painting on all of them, then the line will become dizzy and not-smooth. We first tried to add some smoothing to that, but found out that it breaks normal tablets like Wacom. So now we propagate all the events further to Krita [2]. This makes the events flow a bit dizzy, but it looks like smoothing capabilities of our brushes solve most of the problems. At least havind the spacing option allows us to paint not on every event, but basing on the spacing between daps.

Another possibility might be that Blender reads the coordinate values from X11 fixed point position fields of the X11 packets instead of reading valuators values directly. It should never do it, because these values differ form the ones passed via valuators. Early versions of Qt5 had this problem, but it is solved now (I guess).

[0] - https://www.dropbox.com/s/ib4iahznz9rpd4f/texture%20paint%20tablet.mp4
[1] - https://dev-files.blender.org/file/data/5n6wy2bvbypznsplop6m/PHID-FILE-tpa3cbf4ydqs3dvsriv5/tablet_WP5540U_evtest.txt

[2] - https://phabricator.kde.org/diffusion/CALLIGRA/browse/master/krita/ui/input/wintab/kis_tablet_support_x11.cpp;b9ec4f9b786d03a0e661d51310eb72838a33d734$668

Yes, I’m aware some drivers only give partial data in events, had to fix this about two years ago for pressure, but at that time at least x/y coords were OK. Looking at your video, this is no more the case.

To understand why horizontal lines are OK-ish, while vertical ones are not, you have to understand how that subset of info is handled at xinput level - we get a set of axes, first one being X coordinates, second one Y, third is pressure, next two ones are x and Y tilt (if supported). When only a subset of those is available, we get a 'start' and 'end' indices, so e.g. a start of '2' and end of '3' means only pressure changed.

So if only Y changes, it means there'll be no valid X value, while the reverse is not so common (since there is also often some pressure changes). That explains why vertical lines are dashed (retrieved X value is often invalid - probably zero - since it mostly varies along Y axis), while horizontal ones are OK-ish.

Proposed fix in rBc444bc670e42 is to do the same as what we already do for pressure etc. - to cache X/Y coord and use cached values when an event does not contain them. Here is a link to a build of that fix attempt for linux, please try it and report if it works or not (at least, it looks like it does not break wacom tablets ;) ).

Thank you Bastien. But unfortunately I do not notice any change in the behavior of my tablet with this build when pressure sensitivity is enabled. I still have the same problem.

Are you able to build blender yourself? Otherwise, trying to debug this by distance making testbuilds is going to be horribly long… :/

Yes, I can compile from master. But give me some instructions or text to read if I have to enable any debug option because I have not much idea about that.

OK, so created a temp branch to help us, here are the steps to use it:

git pull
git checkout temp-xinput-tablet
git pull

Then you can build as usual (you can switch back to master branch with just git checkout master, etc.).

Head of this temp-xinput-tablet branch has raw printing of tablet event contents in the console, so please just run blender with it, make a short tablet stroke (one vertically, one horizontally), and attach here the whole messages from the console.

You let me know if I followed well the steps:

Yep, you did good.

Interesting parts of this log are those like that one:

handling tablet event: 0: 809;  1: 384;  2: 237;  
Resulting tablet data: 0: 809;  1: 384;  2: 0.231672;  3: 0.000000;  4: 0.000000

handling tablet event: 0: 809;  1: 385;  
Resulting tablet data: 0: 809;  1: 385;  2: 0.231672;  3: 0.000000;  4: 0.000000

handling tablet event: 1: 386;  2: 0;  
Resulting tablet data: 0: 809;  1: 386;  2: 0.000000;  3: 0.000000;  4: 0.000000

handling tablet event: 0: 810;  1: 386;  
Resulting tablet data: 0: 810;  1: 386;  2: 0.000000;  3: 0.000000;  4: 0.000000

handling tablet event: 0: 810;  1: 387;  
Resulting tablet data: 0: 810;  1: 387;  2: 0.000000;  3: 0.000000;  4: 0.000000

handling tablet event: 1: 388;  
Resulting tablet data: 0: 810;  1: 388;  2: 0.000000;  3: 0.000000;  4: 0.000000

handling tablet event: 0: 810;  1: 388;  2: 240;  
Resulting tablet data: 0: 810;  1: 388;  2: 0.234604;  3: 0.000000;  4: 0.000000

handling tablet event: 1: 389;  2: 0;  
Resulting tablet data: 0: 810;  1: 389;  2: 0.000000;  3: 0.000000;  4: 0.000000

handling tablet event: 0: 810;  1: 390;  2: 244;  
Resulting tablet data: 0: 810;  1: 390;  2: 0.238514;  3: 0.000000;  4: 0.000000

handling tablet event: 1: 391;  
Resulting tablet data: 0: 810;  1: 391;  2: 0.238514;  3: 0.000000;  4: 0.000000

handling tablet event: 1: 391;  2: 0;  
Resulting tablet data: 0: 810;  1: 391;  2: 0.000000;  3: 0.000000;  4: 0.000000

handling tablet event: 1: 392;  2: 0;  
Resulting tablet data: 0: 810;  1: 392;  2: 0.000000;  3: 0.000000;  4: 0.000000

handling tablet event: 1: 393;  
Resulting tablet data: 0: 810;  1: 393;  2: 0.000000;  3: 0.000000;  4: 0.000000

Where 0 is X, 1 is Y, and 2 is pressure. As you can see, we have a lot of events reporting they have pressure data, and yet the value set is actually invalid 0 one. So it indeeds end up as an invalid pressure again - but this time I totally think this is a driver (or xinput) bug. In events like handling tablet event: 1: 391; 2: 0;, we should only get Y (1) value imho. Which means XDeviceMotionEvent.axes_count is not set correctly.

I do not really see what we can do more here, we are just getting bad data afaikt (that, or your tablet is broken and reports flickering pressure values - but would rule that out, since you said other apps are OK, and another user could confirm same behavior…).

That's right, I have not noticed weird behavior in other programs on Linux when pressure sensitivity is enabled. Also, texture paint and curve draw are working really well on Windows 7 with the same hardware. So I discard hardware problems.
I'll see if I can report somewhere issues related to the driver on Linux.
Thank you.

YAFU (YAFU) added a comment.EditedMay 11 2016, 1:10 AM

Hello.
I have contacted Nikolai Kondrashov, DIGImend founder and main developer. I shared with him the next file showing Evtest, Xinput and Blender output while drawing on Blender:

You can read what he wrote here on the mailing list:
https://sourceforge.net/p/digimend/mailman/digimend-devel/?viewmonth=201605

Please you read from the beginning of the messages in May. He has written one of the messages:

""The missing coordinates are perfectly valid according to the xinput protocol,
although e.g. the xf86-input-wacom driver never does them, while
x86-input-evdev always does, and the latter is handling most of the non-Wacom
tablets""

Yeah, I know missing coordinates is perfectly valid, the problem is not there. The problem is that, when only Y coordinate change, the event reports two available valuators, starting from valuator 1 (that is, it reports Y data and pressure data, even though there is no pressure data and valuator is set to zero).

Note that we do not use tablet's valuator data for x/y coordinates, we use 'standard' MotionNotify event for that, with coordinates already scaled and offset in root window.

Here is (reduced from unrelevant stuff) the code we use to get tablet pressure:

if (xe->type == m_xtablet.MotionEvent ||
    xe->type == m_xtablet.MotionEventEraser ||
    xe->type == m_xtablet.PressEvent ||
    xe->type == m_xtablet.PressEventEraser)
{
	XDeviceMotionEvent *data = (XDeviceMotionEvent *)xe;
	const unsigned char axis_first = data->first_axis;
	const unsigned char axes_end = axis_first + data->axes_count;  /* after the last */
	int axis_value;

#define AXIS_VALUE_GET(axis, val)  ((axis_first <= axis && axes_end > axis) && ((void)(val = data->axis_data[axis]), true))

	if (AXIS_VALUE_GET(2, axis_value)) {
		window->GetTabletData()->Pressure = axis_value / ((float)m_xtablet.PressureLevels);
	}
}

Again, our issue is that data->axes_count here has wrong value (2 instead of 1) quite often when only Y valuator actually changed.

Hi.
I opened a report bugs.freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=95459

I appreciate if you can discuss there in that report directly between developers, because I do not know nothing of coding or technical issues and basically all I can do is to testing with my hardware.
Thank you.

So, looks like it was indeed blender reading badly those valuators stuff in the end - at least not the same as xinput --test code does it. ;)

Was actually able to confirm the issue (and the fix) with own wacom tablet in the end, by forcing it to use evdev driver instead of wacom one (though much more hard to spot with that kind of HD device, which nearly always moves on both axes :P ).

Compiled from Master, it is working well now!

Thank you very much Bastien, Campbell and all developers (Blender and non Blender).