为什么终端仿真器绘制基于文本的应用程序时仍然存在视觉伪影?这在最近的电脑,渲染3D游戏和GUI窗口,包括反别名矢量字体,没有工件。
我经常看到以下工件,它们显示屏幕更新过程的中间步骤:
这些工件只在亚秒间隔内被看到,而不是在大多数屏幕更新过程中,但是在没有闪烁的GUI上长大后,我仍然想知道如何避免它们。上面所有的工件(滚动除外)都可以在下面的ASCIInema视频中看到,当它开始绘制更复杂的屏幕时:MapSCII -在你的控制台里的整个世界!
我也没有特别提到缓慢的更新。如果更新总是即时的,那就太好了,但由于网络和处理延迟,这并不总是可能的。我在这里的意思是,部分绘制的屏幕通常在短时间内是可见的。在大多数现代GUI中,只有完全完成的屏幕才会显示给用户,部分绘图的工件非常罕见。
我的印象是,终端模拟管道是这样的:
curses或其他库将字符单元格转换为ANSI转义代码,这些代码将在终端上呈现一个等效的屏幕。以上哪几个步骤可以减慢进程,使终端模拟器向我们显示中间呈现步骤,而不是只显示最终结果?
tcsetattr()的变化而改变,但我从多个来源读取到,波特率设置对终端模拟器使用的伪终端(pty)设备没有影响。这是否意味着Unix内核不刻意限制pty通信?write()?最近有一些努力使新的终端仿真器呈现得更快(例如,将字体预渲染到视频内存中的OpenGL纹理中)。但是,这些努力似乎只会加速字符单元格的渲染到屏幕位图上,一旦计算出网格。
似乎还有别的事情在发生,甚至在一台非常快的电脑上,也会使这些东西从根本上慢下来。想想看:如果终端模拟器在将任何内容呈现到屏幕位图之前处理所有ANSI代码以获得字符单元格网格,那么字符网格到位图呈现例程的速度有多慢并不重要--不应该有闪烁(至少不应该出现明显对应于硬件终端上光标移动的那种闪烁,这是我们经常看到的)。即使终端模拟器花了整整一秒钟在屏幕上绘制任何给定的字符单元格,我们也只能得到一秒的不活动,而不是一秒的闪烁。
一个类似的问题是,Unix、clear和reset命令所做的工作非常慢(从GUI用户的角度来看,它们不会做比重绘位图更复杂的事情)。也许是因为相关的原因。
发布于 2018-11-24 01:54:01
我希望听到更多的细节,如何准确地触发这样突出的闪烁,因为我没有注意到在使用我的系统。
在我的系统中,VTE ( GNOME终端后面的引擎)可以处理大约10 MB/s的传入数据。其他仿真器的性能也离此不远,在两个方向上可能在3或5的因子范围内。这很多,应该足够闪烁-更少的更新。
不过,请记住,全屏终端可能包含数万个字符单元格。UTF-8字符由多个字节组成.切换到不同的属性(颜色、大胆等)需要转义序列,可以从3-4到简单的10-20字节(特别是256颜色和真彩色扩展)。因此,真正复杂的布局可能需要100 kB,甚至更大的流量。这肯定不能在一个步骤中通过tty行。我甚至不确定某些应用程序(或屏幕绘图库)是否愿意在一步内缓冲整个输出。也许他们只是使用printf(),然后让stdio在大约8 kB之后刷新它们。这可能是他们行动迟缓的另一个原因。
我不太熟悉内核的调度行为,例如,它是否需要在两个进程以及用户/内核模式之间来回切换,或者它们是否可以在多线程CPU上同时运行。不过,我真的希望它们能在多核CPU上同时运行,而现在大多数CPU都是这样。
故事中没有故意节流。不过,当模拟器决定是否继续读取数据或更新其屏幕时,可能会有猜测。例如,如果终端仿真器处理输入的速度比应用程序发出的要快,那么它会在处理第一个块后看到输入延迟,因此可能会合理地决定更新其UI。
光标可能是最突出的闪烁,因为光标沿屏幕移动,因为内容正在被更新。它不能停留在同一个地方。如果模拟器在接收输入数据时只更新其屏幕一次,并且光标最终保持在相同的位置,则此闪烁极有可能变得可见。
您可能对这个原子更新建议 (在这里讨论)感兴趣,如果终端仿真器以及运行在其中的应用程序都支持它,它将主要解决这个问题。
您可能还感兴趣的是,由于键盘重复频率和监视器刷新速率之间的干扰,使用键盘的滚动体验是必干,这本身不是闪烁,而是会导致不愉快的体验。
https://unix.stackexchange.com/questions/483777
复制相似问题