android中输入触摸/显示滞后的原因是什么? [英] What are the cause(s) of input touch/display lag in android?

查看:151
本文介绍了android中输入触摸/显示滞后的原因是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个非常简单的应用程序,它使用opengl渲染正方形,GLSurfaceView读取输入触摸,并使用volatile变量与渲染线程交换最后一个位置.

I have a very simple app that render a square with opengl, input touch are read by the GLSurfaceView and last position is exchanged with the rendering thread using a volatile variable.

我观察到的内容( https://www.mail-archive.com/android-developers@googlegroups.com/msg235325.html )是触摸位置和显示之间存在延迟(滞后).

What I observe (and as been also very well described in https://www.mail-archive.com/android-developers@googlegroups.com/msg235325.html) is that there is a delay (a lag) between the touch position and the display.

当激活开发人员选项以显示触摸位置时,我发现在快速移动时:

When activating the developer option to show touch position, I see that when moving rapidly:

  • 与我的手指位置相比,跟踪系统显示的触摸位置的圆圈延迟了1 cm.我认为这是系统/硬件相关的,无法由应用程序更正.

  • the circle tracking the touch position shown by the system is 1 cm delayed compared to my finger position. I assume that this is system / hardware dependent and cannot be corrected by application.

,但是在我的应用程序中渲染的运动也延迟了调试圈1厘米. 因此,在实践中,延迟是可能的两倍.

but the movement rendered in my application is delayed also 1 cm after the debug circle. So in practice the delay is twice what it could be.

当手指的移动速度变慢时,图形的最终位置将停止并且当前触摸位置将同步.完全如本视频所示(在上面的讨论中找到链接) http://www.youtube.com/观看?v = fWZGshsXDhM

When the finger movement slow down, the final position of the drawing stops and current touch position is synchronized. Exactly as shown in this video (link found on discussion above) http://www.youtube.com/watch?v=fWZGshsXDhM

我仍然对导致第二次延迟的原因一无所知,我已经确定了从onTouchEvent到渲染线程的位置交换时间,它只有几毫秒. 渲染的频率为18ms.

Still I am clueless on what is causing the second delay, I have timed the exchange of the position from the onTouchEvent to the rendering thread and it is only a few ms. Rendering happens with a frequency of 18ms.

我尝试通过速度来预测延迟18ms的位置,从而缩短延迟的出现时间,但是它并没有改变任何延迟感知.

I have try to use velocity to shorten the appearance of the delay by predicting the position 18ms latter but it didn't change any delay perception.

有人对这种延迟有解释吗? 它是由系统层引起的,然后才能在onTouchEvent中对其进行访问吗?在其中 情况下,我看不到任何纠正方法.

Has someone an explanation for this kind of delay ? Is it caused by system layers before geting access to in it in onTouchEvent ? In which case I would see no way to correct it.

Google网上论坛没有具体答案.同样令我困扰的是,在线程中提到使用Canva而不是OpenGL可以消除延迟.这就提出了更多的问题,它可以回答.

There was no specific answer on the google group. Also what bother me is that in the thread it is mentionned that the delay disappear by using a canva instead of OpenGL. Which raise more question that it answers.

推荐答案

我最近一直在研究同一件事.这里对Android图形堆栈的内部有很好的解释:

I've been looking into the same thing recently. There's a good explanation of the Android graphics stack internals here:

https://source.android.com/devices/graphics/architecture.html

基本上,Android上的SurfaceViews代表缓冲区队列的生产者端.这些缓冲区的使用者是SurfaceFlinger,它处理更新在下一个vsync上显示的表面.关键是这是一个队列.实际上,除非队列已满,否则执行eglSwapBuffers不会阻止.这意味着,如果您的渲染很简单,则GLSurfaceView可以非常快地渲染前几帧,填充缓冲区队列,然后稳定到每16ms渲染一次"的稳定状态.

Essentially SurfaceViews on android represent the producer end of a buffer queue. The consumer of those buffers is SurfaceFlinger which handles updating the surfaces being displayed on the next vsync. The key thing is that this is a queue. Doing eglSwapBuffers in fact doesn't block unless the queue is full. That means if your rendering is simple, GLSurfaceView renders the first couple of frames very quickly, filling the buffer queue, and then settles down into the "render every 16ms" steady state.

您可以使用systrace查看队列中已填充的缓冲区数.您会注意到,GLSurfaceView通常在队列中以1帧开始一个vsync周期,当您的渲染函数完成时,它上升到2,这意味着您需要等待2个vsync才能显示(实际上,我认为3,因为SurfaceFlinger添加了另一个合成元素,但每个人都是相同的.

You can see the number of filled buffers in the queue with systrace. You'll notice the GLSurfaceView typically starts a vsync period with 1 frame in the queue, when your render function finishes this goes up to 2, meaning you will need to wait for 2 vsyncs before it displays (in fact 3, I think, because SurfaceFlinger adds another for composition, but that's the same for everyone).

画布是按需绘制而不是连续绘制,并且绘制通常比显示更新率低得多,因此该窗口的BufferQueue通常为空,因此SurfaceFlinger会在下一个vsync立即使用新内容.

Canvas is drawn on demand rather than continuously, and as that drawing typically happens at much less than the display update rate the BufferQueue for that window is typically empty so new content is consumed immediately by SurfaceFlinger on the next vsync.

您可以在vsync上注册回调,因此呈现的刷新率绝不会超过显示刷新率.这样可以避免GLSurfaceView连续渲染的尽可能快地填充队列"效果.但是,由于SurfaceFlinger可能会跳过节拍,因此无论如何都会导致队列增加,因此我不确定队列是否会填满.我在这里有一个问题:

You can register for callbacks on vsync so you never render more than the display refresh rate. That avoids the "fill the queue as fast as possible" effect of GLSurfaceView's continuous rendering. However I'm not sure that guarantees the queue will not fill up as it is possible that SurfaceFlinger will skip a beat, causing your queue to grow anyway. I've got a question on that here:

最小化Android GLSurfaceView延迟

我已经完成了在vsync上渲染的测试,但是每隔几百跳几帧以确保队列正确清空.在那种情况下,GL渲染的对象确实会与指针轨迹"叠加十字准线一起锁定移动. 调试圈"似乎仍在前面-我认为这是在SurfaceFlinger绘制表面的合成过程中作为简单的图层重定位来实现的,这将使其在其他渲染之前额外增加一帧.

I've done a test where I render on vsync, but skip a few frames every few hundred to guarantee the queue empties properly. In that case the GL-rendered objects do move in lock-step with the "pointer trail" overlay crosshair. The "debug circle" appears to still be slightly ahead - I think that is implemented as a simple layer reposition during SurfaceFlinger's composition of the drawn surfaces which would put it an additional frame ahead of the other rendering.

这篇关于android中输入触摸/显示滞后的原因是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆