Double 重缓冲和页面翻转

假设您必须在屏幕上逐像素或逐行绘制整个图片。如果要直接在屏幕上绘制这样的东西(例如使用Graphics\.drawLine),您可能会非常失望地注意到它花费了一些时间。您甚至可能会注意到有关图片绘制方式的可见伪像。大多数程序员不是看着以这种方式并以此速度绘制事物,而是使用一种称为 Double 缓冲的技术。

Java 应用程序中传统的 Double 缓冲概念非常简单:创建一个离屏图像,使用该图像的图形对象绘制到该图像,然后一步一步,使用目标窗口的图形对象和离屏图像调用drawImage。您可能已经注意到,Swing 在其许多组件中都使用了此技术,通常使用setDoubleBuffered方法在默认情况下启用了该技术。

屏幕表面通常称为主表面,用于 Double 重缓冲的屏幕外图像通常称为后缓冲。将内容物从一个表面复制到另一个表面的动作通常被称为分块线转移或刮擦(blt 通常发音为“ blit”,不应与 BLT 三明治混淆)。

Double Buffering

通常通过任何显示组件的图形对象来操纵主表面。在全屏 Pattern 下,使用全屏窗口图形的任何操作都是对屏幕内存的直接操作。因此,您可以利用全屏独占 Pattern 下的其他功能,否则,由于开窗系统的开销,这些功能可能不可用。仅在全屏独占 Pattern 下可用的一种这样的技术是称为页翻转的 Double 缓冲形式。

Page Flipping

许多图形卡都有视频指针的概念,这只是视频内存中的地址。该指针告诉图形卡在哪里寻找下一个刷新周期中要显示的视频内容。在某些图形卡和某些 os 中,甚至可以以编程方式操纵此指针。假设您创建了一个在屏幕上具有确切宽度,高度和位深度的后缓冲区(在视频内存中),然后以与使用 Double 缓冲区相同的方式将其拖到该缓冲区。现在想象一下,如果您只是将视频指针更改为后缓冲区,而不是像 Double 缓冲那样将图像拖到屏幕上,将会发生什么情况。在下一次刷新期间,图形卡现在将使用您的图像进行显示。此switch称为页面翻转,与基于 blt 的 Double 缓冲相比,性能提高是,只需将单个指针移入内存,而不是将整个内容从一个缓冲区复制到另一个缓冲区。

当发生页面翻转时,指向旧的后缓冲区的指针现在指向主表面,指向旧的主面的指针现在指向后缓冲存储器。这将自动设置您进行下一个绘制操作。

Page Flipping

有时在翻转链中设置多个反向缓冲区是有利的。当绘制所花费的时间大于监视器的刷新率时,此功能特别有用。一条翻转链仅是两个或多个后缓冲区(有时称为中间缓冲区)加上主表面(有时称为三重缓冲,四重缓冲等)。在翻转链中,下一个可用的后缓冲区将成为主曲面等,一直到用于绘制的最后面的后缓冲区。

Double 缓冲和翻页的好处

如果您的性能 Metrics 仅仅是 Double 缓冲或页面翻转相对于直接渲染的速度,那么您可能会感到失望。您可能会发现直接渲染的数字远远超过了 Double 缓冲的数字,而这些数字远远超过了页面翻转的数字。这些技术中的每一种都用于改善感知性能,这在图形应用程序中比数字性能更为重要。

Double 缓冲主要用于消除可见的绘制,这些绘制可以使应用程序看起来不熟练,缓慢或出现闪烁。页面翻转主要用于消除撕裂,这种撕裂现象是在绘制到屏幕上时发生的,其发生速度快于监视器的刷新率。平滑的绘制意味着更好的感知性能和更好的用户体验。