.NET 白板书写延迟-触摸屏报点率

触摸书写延迟,是触摸屏很核心的参数。从用户在触摸屏上进行触控操作到设备作出响应之间的时间差,这个延迟高低会影响快速反应的应用场景使用如白板书写、玩游戏。

而触摸延迟主要影响因素有:触摸框报点率、软件框架延时(用于触摸数据接收、线程切换)、软件业务逻辑处理

我们这里介绍下触摸框报点率 Touch Report Rate,触摸屏每秒报告触控数据的次数(Hz),会根据设备类型不同而变化

触摸操作TouchMove(StylusMove)是定时上报一次,一次会上报1-N个点。

1     private void MainWindow_OnStylusMove(object sender, StylusEventArgs e)
2     {
3         var currentPointsCount = e.GetStylusPoints(this).Count;
4     }

不同屏幕定时触摸上报时间不同,我们可以通过Stylus事件收集看看

 1     private void MainWindow_OnStylusDown(object sender, StylusDownEventArgs e)
 2     {
 3         _stylusDown = true;
 4         _startTick = Environment.TickCount;
 5         _stylusEntryCount++;
 6         _distinctPoints.AddRange(e.GetStylusPoints(this).Distinct());
 7     }
 8 
 9     private void MainWindow_OnStylusMove(object sender, StylusEventArgs e)
10     {
11         if (!_stylusDown)
12         {
13             return;
14         }
15         _stylusEntryCount++;
16         _distinctPoints.AddRange(e.GetStylusPoints(this).Distinct());
17     }

输入平均间隔:var stylusEntryTime = (Environment.TickCount - _startTick) / (double)_stylusEntryCount

Dell触摸屏

我日常用于开发联调触摸相关功能的触摸屏,戴尔触摸屏Dell-P2418HT 1080P的触摸数据

1. WPF应用StylusMove输入,拿到的间隔是33ms,即30帧

2. 一次输入包含1-7个点 

3. 再算个点平均间隔16.7ms -- 这个数据也是有意义的,可以用于评估类似书写预测1个点可以提升的性能

使用BusHold,我们看下真实点输入间隔:

BusHold第4列数据,01是指Down/Move事件,00是指Up操作结束。我们看到Move操作输入间隔基本在16-17ms,说明触摸框真实报点间隔17ms左右,即60帧。

上面WPF监听Stylus事件,拿到的触摸操作输入间隔是33ms。为何应用层拿到的触摸数据帧率比触摸框低呢?

我们试试StylusPlugin(StylusPlugin方案可以在WPF路由事件之前拿到触摸数据,可以用于触摸书写加速方案)拿触摸线程的触摸数据,以及WPF路由触摸事件数据对比下:

获取StylusPlugin插件事件,代码比较简单。但需要注意的事,事件需要过滤掉主线程,过滤后才是触摸工作线程的触摸数据:

 1     public partial class MainWindow : Window
 2     {
 3         public MainWindow()
 4         {
 5             InitializeComponent();
 6             StylusPlugIns.Add(new TestStylusPlugIn(Thread.CurrentThread.ManagedThreadId));
 7         }
 8     }
 9     class TestStylusPlugIn : StylusPlugIn
10     {
11         private readonly int _uiThreadId;
12 
13         public TestStylusPlugIn(int uiThreadId)
14         {
15             _uiThreadId = uiThreadId;
16         }
17 
18         protected override void OnStylusMove(RawStylusInput rawStylusInput)
19         {
20             if (Thread.CurrentThread.ManagedThreadId == _uiThreadId)
21             {
22                 return;
23             }
24             Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss.fff")}:StylusPluginOnStylusMove {rawStylusInput.GetStylusPoints().Count}个点");
25             base.OnStylusMove(rawStylusInput);
26         }
27     }

与BusHold同样是7个点,

触摸线程事件,只不过2个点合并到一次触摸输入事件里了。所以这2个点合并操作不是路由事件内处理的,也不是WPF路由,减少了传递给应用程序的事件数量。我估计是InputManager协调输入并派发事件这块做了合并操作。我们可以再来一组测试数据,这里我们看到这之间的输入间隔不稳定:

但到StylusPlugin帧率减少的并不多,和小伙伴德熙沟通,有历史点合并但并不多。重要的是,以2个点周期输入间隔原来的16ms变大到33ms:

UI路由事件,我们看上面控制台输出,移动事件间隔30ms左右报个一次输入事件,最后一个Move事件里有4个点。这里的4个点输入,合并了1+2+1上面触摸线程事件的3次输入,所以WPF路由事件管理也有触摸消息的队列,会合并触摸点

那有没有可能减少触摸数据的合并,与触摸框保持一致的帧率呢?答案是有的,可以在WPF开启如UWP的Point消息:

1     public partial class App : Application
2     {
3         public App()
4         {
5             AppContext.SetSwitch("Switch.System.Windows.Input.Stylus.EnablePointerSupport", true);
6         }
7     }

添加EnablePointerSupport后,我们监听TouchMove事件:

触摸移动事件触发间隔就减少到16-17ms了,到与触摸框报点率相同帧率,good!

开启Pointer相关内容也可以看德熙MVP的博客 WPF dotnet core 如何开启 Pointer 消息的支持 (lindexi.com),但开启Pointer也有很多坑WPF 开启Pointer消息存在的坑 (lindexi.com),大家使用时多了解下已知缺陷

触摸大屏

再看看目前市面上交互触摸大屏所使用的富创通、华欣主流触摸框产品路由触摸数据:

输入间隔为15.6ms左右,触摸点之间平均间隔为7ms左右,即触摸框报点140帧以上,应用层触摸数据60帧。

最近有一款改良的富创通触摸G框版本,我们也由应用端收集下数据:

输入间隔没变也是15.6ms左右,触摸点之间平均间隔为4.5ms,即触摸框报点220帧左右,应用层触摸数据依然是60帧。说明这款触摸框提升了本身的报点率,但应用层根据硬件条件限制了60帧触摸报点。

至于这三个触摸屏的触摸数据帧数限制,

  • Dell触摸屏通过BusHold抓到原始触摸数据是60帧,但WPF处理后得到30帧
  • 大屏触摸框通过BusHold抓到原始触摸数据140帧,但WPF处理后得到60帧
  • 大屏触摸框升级版通过BusHold抓到原始触摸数据220帧,但WPF处理后也是得到60帧

是显示屏什么属性限制WPF内触摸数据帧率的呢?和小伙伴沟通盲猜WPF内可能卡30-60帧选项、根据触摸原始帧数去选30或者60,WPF在Dell触摸屏内最终得到30帧可能是触摸帧数60帧及以下被分配30帧?。。。我还没搞懂,有知道的朋友可以解惑下,期待你的指导

总结下,

1. 上面我们也介绍了开启pointer,WPF输出的触摸输入间隔与达到触摸框原始帧率。所以开启Pointer书写延迟能降低很大一部分

2. 触摸框原始帧率提升后,也能降低触摸输入间隔,即使不开启Pointer也能减少与上一次触摸间隔减少。所以可以与触摸框厂商沟通提升报点率,降低书写延迟

了解触摸报点率,才能真正去把书写性能以及书写平滑这块做好。

上面Demo见:kybs00/StylusPointRateDemo: 大屏触摸报点率检测Demo (github.com)kybs00/StylusPluginEventDemo: 触摸屏触笔插件StylusPlugin事件获取 (github.com)

posted @ 2024-10-10 14:06  唐宋元明清2188  阅读(612)  评论(12编辑  收藏  举报