[PATCH 1/3] dinput: Stop sending WM_WINE_NOTIFY_ACTIVITY on every input.

Rémi Bernon rbernon at codeweavers.com
Mon Jun 8 02:47:07 CDT 2020


This message triggers screensaver notification in the user drivers, but
it is not useful to send it on every input message, and it even hurts
performance when high polling mouse is used.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=33643
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46976
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---

Notes:
    This only partially solves the mentionned bugs. Performance can be
    improved even more by using rawinput API instead of low-level hooks,
    but it requires the wineserver side to be implemented first.
    
    Because wiggling the mouse is a bit unpredictable, I've used evemu to
    create a fake evdev mouse device. And I've then injected events using
    this python / evemu-play script:
    
        python -u - <<EOF | stdbuf -oL evemu-play /dev/input/eventX
        for i in range(0, 1000*10000):
            print('E: {:.06f} 0002 0001 +001  # EV_REL / REL_Y'
                  '                +1'.format(i / 1000.))
            print('E: {:.06f} 0000 0000 0000  # ------------ '
                  'SYN_REPORT (0) ---------- +1ms'.format(i / 1000.))
        EOF
    
    Event injection time is not 100% reliable, but it is consistent and the
    event frequency is approximately 1kHz, similar to a high polling rate
    mouse.
    
    I've used Sekiro as a test case, with graphics settings set to lowest
    possible. The game runs at ~60fps without mouse input. The fps is not
    completely stable, and I believe it may be because the game is doing
    things at the same time. So I've measured the average fps of the first
    game scene after letting the injection run for a long time.
    
    Only positive REL_Y events are used so that the game camera gets down
    quickly and stops moving, to smooth variation that could be caused by
    the draw calls.
    
    With Wine 5.10, the fps drop to about ~40fps while input is injected,
    and PATCH #1 makes it go up to ~50fps.
    
    The other two patches have smaller effect and not easily measurable,
    but I believe they are still helpful -- perf indicates a lot of cache
    misses around the list iterations -- and they are also preparing ground
    for the rawinput patches.

 dlls/dinput/device.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index 8c5aa318837..51ae349f34e 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -931,13 +931,19 @@ HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, L
 
 void queue_event(LPDIRECTINPUTDEVICE8A iface, int inst_id, DWORD data, DWORD time, DWORD seq)
 {
+    static ULONGLONG notify_ms = 0;
     IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
     int next_pos, ofs = id_to_offset(&This->data_format, inst_id);
+    ULONGLONG time_ms = GetTickCount64();
 
     /* Event is being set regardless of the queue state */
     if (This->hEvent) SetEvent(This->hEvent);
 
-    PostMessageW(GetDesktopWindow(), WM_WINE_NOTIFY_ACTIVITY, 0, 0);
+    if (time_ms - notify_ms > 1000)
+    {
+        PostMessageW(GetDesktopWindow(), WM_WINE_NOTIFY_ACTIVITY, 0, 0);
+        notify_ms = time_ms;
+    }
 
     if (!This->queue_len || This->overflow || ofs < 0) return;
 
-- 
2.27.0




More information about the wine-devel mailing list