文档

Java™教程
隐藏目录
双缓冲和页面翻转
路径:奖励
课程:全屏独占模式API

双缓冲和页面翻转

假设你必须逐像素或逐行在屏幕上绘制整个图像。如果你直接在屏幕上绘制这样的图像(使用,比如,Graphics.drawLine),你可能会很失望地发现它需要一点时间。你甚至可能会注意到图像绘制的可见痕迹。大多数程序员使用一种称为双缓冲的技术,而不是以这种方式和速度观看绘制过程。

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

屏幕表面通常被称为主表面,用于双缓冲的离屏图像通常被称为后备缓冲区。从一个表面复制内容到另一个表面的行为通常被称为块线传输,或blitting(blt通常发音为"blit",不应与BLT三明治混淆)。

双缓冲

通常通过任何显示组件的图形对象来操作主表面;在全屏模式下,使用全屏窗口的图形进行的任何操作都是直接操作屏幕内存。因此,你可以利用全屏独占模式中可能由于窗口系统的开销而无法使用的其他功能。全屏独占模式中仅可用的一种技术是一种称为翻页的双缓冲形式。

翻页

许多显卡都有一个称为视频指针的概念,它只是视频内存中的一个地址。该指针告诉显卡在下一次刷新周期中在哪里查找要显示的视频内容。在某些显卡和某些操作系统中,甚至可以以编程方式操作该指针。假设你创建了一个后备缓冲区(在视频内存中),其宽度、高度和位深度与屏幕相同,然后以与双缓冲相同的方式绘制到该缓冲区中。现在想象一下,如果不像双缓冲那样将图像复制到屏幕上,而是简单地将视频指针切换到你的后备缓冲区,那么在下一次刷新时,显卡将使用你的图像来显示。这种切换称为翻页,与基于blt的双缓冲相比,性能提升在于只需要在内存中移动单个指针,而不是将整个内容从一个缓冲区复制到另一个缓冲区。

当页面翻转发生时,指向旧后备缓冲区的指针现在指向主表面,而指向旧主表面的指针现在指向后备缓冲区内存。这将自动为下一次绘制操作做好准备。

页面翻转

有时候,在翻转链中设置多个后备缓冲区是有优势的。当绘制所花费的时间大于监视器的刷新率时,这是特别有用的。翻转链只是两个或更多个后备缓冲区(有时称为中间缓冲区)加上主表面(有时称为三重缓冲、四重缓冲等)。在翻转链中,下一个可用的后备缓冲区变为主表面,以此类推,一直到用于绘制的最后一个后备缓冲区。

双缓冲和页面翻转的好处

如果你的性能指标仅仅是双缓冲或页面翻转的速度与直接渲染相比,你可能会感到失望。你可能会发现,直接渲染的数字远远超过双缓冲的数字,而这些数字远远超过页面翻转的数字。这些技术都是用于提高感知性能,在图形应用程序中,这比数值性能更重要。

双缓冲主要用于消除可见的绘制,这可以使应用程序看起来业余、迟缓或闪烁。页面翻转主要用于消除撕裂,即当绘制到屏幕上的速度快于监视器的刷新率时会发生的分割效果。更平滑的绘制意味着更好的感知性能和更好的用户体验。


上一页: 被动渲染与主动渲染
下一页: BufferStrategy和BufferCapabilities