Java 硬件加速

标签 java swing graphics hardware-acceleration

我一直在研究 Java 的硬件加速特性,但我仍然有点困惑,因为我在网上找到的网站都没有直接明确回答我的一些问题。下面是我对 Java 硬件加速的疑问:

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

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

应该指示是否启用了硬件加速,并且当在我的主 Canvas 实例上运行以进行绘图时,我的程序会返回 true。如果我的硬件加速现在没有启用,或者默认情况下没有启用,我需要做什么来启用它?

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

3) 使用有什么好处

someGraphicsConfiguration.getCompatibleImage/getCompatibleVolatileImage()

相对

ImageIO.read()

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

4) 这不是硬件加速,但我一直很好奇:我是否需要订购要绘制的图形?我知道,当通过 C/C++ 使用 OpenGL 时,最好确保在需要一次绘制的所有位置都绘制相同的图形,以减少当前纹理需要切换的次数。从我读到的内容来看,Java 似乎会为我解决这个问题,并确保以最优化的方式绘制内容,但同样,从来没有人这么清楚地表达过。

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

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

最佳答案

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

2) 是的,BufferedImage 封装了一些管理 volatile 内存的细节,因为当 BufferdImage 被加速时,它的副本作为 VolatileImage< 存储在 V-Ram 中

BufferedImage 的好处是只要你不弄乱它包含的像素,只需像调用 graphics.drawImage() 一样复制它们,然后BufferedImage 将在一定数量的非指定副本后加速,并为您管理 VolatileImage

BufferedImage 的缺点是,如果您在进行图像编辑,更改 BufferedImage 中的像素,在某些情况下它会放弃尝试加速它,在如果您正在为您的编辑寻找高性能渲染,那么您需要考虑管理您自己的 VolatileImage。不知道是哪些操作让BufferedImage放弃了为你加速渲染的尝试。

3) 使用 createCompatibleImage()/createCompatibleVolatileImage() 的优势 是 ImageIO.read() 不会对默认支持的图像数据模型进行任何转换。 因此,如果您导入 PNG,它将以 PNG 阅读器构建的格式表示。这意味着每次由 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 中的实现略有不同,然后增强可能毫无值(value)。

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

关于Java 硬件加速,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4627320/

相关文章:

java - Java 中的drawImage() "null"

Java Camel 大小写撇号问题

java - 在另一台设备上使用 EasyCrypt 库完成密码时出错

java - 如何在 Java 中将线从光栅转换为 vector ?

java - 关闭 JFrame 窗口

java - 从 JFrame 的标题栏中获取图标图像

python - 非线性函数的 numpy 爱因斯坦求和

java - 如何将程序调用转移到正在运行的实例

java - XMLEventWriter : how can I tell it to write empty elements?

java - 读取微调器输入