Java 硬件加速

我花了一些时间研究Java的硬件加速功能,我仍然有点困惑,因为我在网上找到的任何网站都没有直接清楚地回答我的一些问题。因此,以下是我对Java中硬件加速的问题:

1)在Eclipse版本3.6.0中,使用Mac OS X的最新Java更新(我认为是1.6u10),默认情况下是否启用硬件加速?我在某处读到

someCanvas.getGraphicsConfiguration().getBufferCapabilities().isPageFlipping()

应该指示是否启用了硬件加速,并且我的程序在我的主Canvas实例上运行以进行绘制时会报告为true。如果现在或默认情况下未启用硬件加速,我需要执行哪些操作才能启用它?

2)我在这里和那里看到了几篇关于BufferedImage和Vol volatileImage之间区别的文章,主要是说VolvocationImage是硬件加速图像,存储在VRAM中以进行快速复制操作。但是,我也发现了一些实例,其中BufferedImage也被称为硬件加速。BufferedImage 硬件是否也在我的环境中加速?如果两种类型都是硬件加速的,那么使用Vol volatileImage有什么好处?我对在两者都具有加速度的情况下具有VolquilImage的优势的主要假设是,VolatileImage能够检测到其VRAM何时被转储。但是,如果BufferedImage现在也支持加速,那么它是否也内置了相同类型的检测,只是对用户隐藏,以防内存被转储?

3)使用有什么好处吗

someGraphicsConfiguration.getCompatibleImage/getCompatibleVolatileImage()

ImageIO.read()

在我一直在阅读的教程中,关于正确设置渲染窗口的一些一般概念(教程),它使用getCompatibleImage方法,我相信它返回一个BufferedImage,以获得他们的“硬件加速”图像以进行快速绘制,这与问题2有关它是否是硬件加速的。

4)这是较少的硬件加速,但这是我一直好奇的事情:我需要订购绘制哪些图形吗?我知道,当通过C / C++使用OpenGL时,最好确保在需要同时绘制的所有位置绘制相同的图形,以减少需要切换当前纹理的次数。从我所读到的内容来看,似乎Java会为我处理这个问题,并确保以最佳方式绘制内容,但同样,从来没有人清楚地说过这样的话。

5) 哪些 AWT/Swing 类支持硬件加速,应该使用哪些类?我目前正在使用一个扩展JFrame的类来创建一个窗口,并向其添加一个Canvas,从中创建一个BufferStrategy。这是很好的做法,还是我应该实现这种方式的其他类型的方法?

非常感谢您抽出宝贵时间,我希望我提供了明确的问题和足够的信息,以便您回答我的几个问题。


答案 1

1)到目前为止,默认情况下从未启用硬件加速,据我所知,它尚未更改。要激活渲染加速,请在程序启动时将此参数 (-Dsun.java2d.opengl=true) 传递给 Java 启动器,或在使用任何渲染库之前进行设置。 它是一个可选参数。System.setProperty("sun.java2d.opengl", "true");

2) Yes 封装了管理易失性存储器的一些细节,因为当 加速时,它的副本将作为 .BufferedImageBufferdImageVolatileImage

a的好处是,只要您不弄乱它所包含的像素,只需像调用一样复制它们,那么在一定非指定数量的副本后,它将加速,它将为您管理。BufferedImagegraphics.drawImage()BufferedImageVolatileImage

a的缺点是,如果您正在进行图像编辑,更改中的像素,在某些情况下,它将放弃尝试加速它,此时如果您正在寻找用于编辑的高性能渲染,则需要考虑管理自己的 。我不知道哪些操作使您放弃尝试加速渲染。BufferedImageBufferedImageVolatileImageBufferedImage

3) 使用 的优点是不会对默认支持的图像数据模型进行任何转换。因此,如果您导入PNG,它将以PNG阅读器构建的格式表示它。这意味着每次由 它渲染时,必须首先将其转换为兼容的图像数据模型。createCompatibleImage()/createCompatibleVolatileImage()ImageIO.read()GraphicsDevice

BufferedImage image = ImageIO.read ( url );
BufferedImage convertedImage = null;
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment ();
GraphicsDevice gd = ge.getDefaultScreenDevice ();
GraphicsConfiguration gc = gd.getDefaultConfiguration ();
convertedImage = gc.createCompatibleImage (image.getWidth (), 
                                           image.getHeight (), 
                                           image.getTransparency () );
Graphics2D g2d = convertedImage.createGraphics ();
g2d.drawImage ( image, 0, 0, image.getWidth (), image.getHeight (), null );
g2d.dispose()

上述过程将使用图像 io API 读取的图像转换为具有与默认屏幕设备兼容的图像数据模型的 BufferedImage,以便在呈现图像时无需进行转换。这是最有利的时间是您将非常频繁地渲染图像的时间。

4)您不需要努力对图像渲染进行批处理,因为在大多数情况下,Java会尝试为您执行此操作。没有理由不能尝试这样做,但一般来说,在尝试执行此类性能优化之前,最好分析应用程序并确认图像呈现代码存在瓶颈。主要缺点是,在每个JVM中实现方式略有不同,然后增强功能可能毫无价值。

5)据我所知,您概述的设计是手动执行双缓冲并主动渲染应用程序时更好的策略之一。http://docs.oracle.com/javase/7/docs/api/java/awt/image/BufferStrategy.html在此链接中,您将找到 .在说明中,它显示了一个代码片段,这是对对象进行主动呈现的推荐方法。我将这种特殊技术用于我的活动呈现代码。唯一的主要区别是在我的代码中。像你一样,我已经创建了一个实例,我把它放在一个.BufferStrategyBufferStrategyBufferStrategyCanvasJFrame


答案 2

从一些较旧的文档来看,您可以通过检查属性在 Sun JVM 上判断硬件加速是否打开。sun.java2d.opengl

不幸的是,我不知道这是否适用于Apple JVM。

您可以使用 的 getCapabilities(GraphicsConfiguration).isAccelerated() 来检查单个图像是否经过硬件加速Image

话虽如此,我看到的所有文档(包括这个)都暗示这不是硬件加速。由于这个原因,Swing也被更改为使用s进行双缓冲。BufferedImageVolatileImage


推荐