Java Hardware Acceleration

26,550

Solution 1

1) So far hardware acceleration is never enabled by default, and to my knowledge it has not changed yet. To activate rendering acceleration pass this arg (-Dsun.java2d.opengl=true) to the Java launcher at program start up, or set it before using any rendering libraries. System.setProperty("sun.java2d.opengl", "true"); It is an optional parameter.

2) Yes BufferedImage encapsulates some of the details of managing the Volatile Memory because, when the BufferdImage is accelerated a copy of it is stored in V-Ram as a VolatileImage.

The upside to a BufferedImage is as long as you are not messing with the pixels it contains, just copying them like a call to graphics.drawImage(), then the BufferedImage will be accelerated after a certain non specified number of copies and it will manage the VolatileImage for you.

The downside to a BufferedImage is if you are doing image editing, changing the pixels in the BufferedImage, in some cases it will give up trying to accelerate it, at that point if you are looking for performant rendering for your editing you need to consider managing your own VolatileImage. I do not know which operations make the BufferedImage give up on trying to accelerate rendering for you.

3) The advantage of using the createCompatibleImage()/createCompatibleVolatileImage() is that ImageIO.read() does not do any conversion to a default supported Image Data Model. So if you import a PNG it will represent it in the format built by the PNG reader. This means that every time it is rendered by a GraphicsDevice it must first be converted to a compatible Image Data Model.

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()

The above process will convert an image read in with the image io api to a BufferedImage that has a Image Data Model compatible with the default screen device so that conversion does not need to take place when ever it is rendered. The times when this is most advantageous is when you will be rendering the image very frequently.

4) You do not need to make an effort to batch your image rendering because for the most part Java will attempt to do this for you. There is no reason why you cant attempt to do this but in general it is better to profile your applications and confirm that there is a bottleneck at the image rendering code before you attempt to carry out a performance optimization such as this. The main disadvantage is that it my be implemented slightly differently in each JVM and then the enhancements might be worthless.

5) To the best of my knowledge the design you have outlined is one of the better strategies out there when doing Double Buffering manually and actively rendering an application. http://docs.oracle.com/javase/7/docs/api/java/awt/image/BufferStrategy.html At this link you will find a description of the BufferStrategy. In the description it shows a code snippet that is the recommended way to do active rendering with a BufferStrategy object. I use this particular technique for my active rendering code. The only major difference is that in my code. like you, I have created the BufferStrategy on an instance of a Canvas which I put on a JFrame.

Solution 2

Judging from some older documentation, you can tell on Sun JVMs whether hardware acceleration is on or not by checking the sun.java2d.opengl property.

Unfortunately, I do not know if this applies to the Apple JVM.

You can check if an individual image is hardware accelerated using Image's getCapabilities(GraphicsConfiguration).isAccelerated()

Having said all this, all the documentation I've seen (including this one) imply that BufferedImage is not hardware accelerated. Swing has also been changed to use VolatileImages for its double-buffering for this very reason.

Share:
26,550
Freezerburn
Author by

Freezerburn

Updated on December 01, 2020

Comments

  • Freezerburn
    Freezerburn over 3 years

    I have been spending some time looking into the hardware acceleration features of Java, and I am still a bit confused as none of the sites that I found online directly and clearly answered some of the questions I have. So here are the questions I have for hardware acceleration in Java:

    1) In Eclipse version 3.6.0, with the most recent Java update for Mac OS X (1.6u10 I think), is hardware acceleration enabled by default? I read somewhere that

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

    is supposed to give an indication of whether or not hardware acceleration is enabled, and my program reports back true when that is run on my main Canvas instance for drawing to. If my hardware acceleration is not enabled now, or by default, what would I have to do to enable it?

    2) I have seen a couple articles here and there about the difference between a BufferedImage and VolatileImage, mainly saying that VolatileImage is the hardware accelerated image and is stored in VRAM for fast copy-from operations. However, I have also found some instances where BufferedImage is said to be hardware accelerated as well. Is BufferedImage hardware accelerated as well in my environment? What would be the advantage of using a VolatileImage if both types are hardware accelerated? My main assumption for the advantage of having a VolatileImage in the case of both having acceleration is that VolatileImage is able to detect when its VRAM has been dumped. But if BufferedImage also support acceleration now, would it not have the same kind of detection built into it as well, just hidden from the user, in case that the memory is dumped?

    3) Is there any advantage to using

    someGraphicsConfiguration.getCompatibleImage/getCompatibleVolatileImage()
    

    as opposed to

    ImageIO.read()
    

    In a tutorial I have been reading for some general concepts about setting up the rendering window properly (tutorial) it uses the getCompatibleImage method, which I believe returns a BufferedImage, to get their "hardware accelerated" images for fast drawing, which ties into question 2 about if it is hardware accelerated.

    4) This is less hardware acceleration, but it is something I have been curious about: do I need to order which graphics get drawn? I know that when using OpenGL via C/C++ it is best to make sure that the same graphic is drawn in all the locations it needs to be drawn at once to reduce the number of times the current texture needs to be switch. From what I have read, it seems as if Java will take care of this for me and make sure things are drawn in the most optimal fashion, but again, nothing has ever said anything like this clearly.

    5) What AWT/Swing classes support hardware acceleration, and which ones should be used? I am currently using a class that extends JFrame to create a window, and adding a Canvas to it from which I create a BufferStrategy. Is this good practice, or is there some other type of way I should be implementing this?

    Thank you very much for your time, and I hope I provided clear questions and enough information for you to answer my several questions.

  • Freezerburn
    Freezerburn over 13 years
    Where would I find the sun.java2d.opengl property? I've seen it mentioned, but I never knew where to check it or put it to make sure it was enabled on Mac/Eclipse. Also: download.oracle.com/javase/1.5.0/docs/guide/2d/… says that BufferedImages are managed in 1.5.0 and are cached in video memory.
  • Powerlord
    Powerlord over 13 years
    Lets see... I think it's System.getProperty("sun.java2d.opengl") to get the value of the property. As for BufferedImage, it said it can be cached in video memory but says nothing about actually manipulating it beyond that.
  • Freezerburn
    Freezerburn over 13 years
    Printing the output of getProperty gives me "null" to the console. From what I understand about how the acceleration works in Java, would BufferedImage being in video memory allow for the fast copying that VolatileImage is supposed to have? I would assume that would be the case if it uses video-to-video copying.
  • Powerlord
    Powerlord over 13 years
    I don't know a lot about hardware acceleration in Java either (I'm a web guy), I just assumed that there's some benefit for VolatileImage to be OpenGL (on DirectDraw/Direct2D on Windows) accelerated.
  • Freezerburn
    Freezerburn over 13 years
    There probably is, and that's why I'm asking all those questions, heh. I appreciate the help though. Hopefully a Java guru will notice the questions and answer it at some point :)
  • Freezerburn
    Freezerburn over 11 years
    Is there any particular reason that most/all examples use a JFrame to store the Canvas? From what I understood, Swing is pretty much terrible. Why would you not use a Frame? I have code which does just that, and it seems to be no harder to create than a JFrame. Also how is hardware acceleration enabled if it is not by default?
  • Zixradoom
    Zixradoom over 11 years
    @FreezerBurn I do not know why most examples use JFrame vs Frame. I imagine it is done with a JFrame because that is what is most commonly known. This is only speculation but, I would guess that manually rendering in Java with only a Top Level Container (JFrame,Frame,etc) and a Canvas there is little difference between which one you choose. To activate rendering acceleration pass this arg (-Dsun.java2d.opengl=true) to the Java launcher at program start up, or to set it before using any rendering libraries. (System.setProperty("sun.java2d.opengl", "true");) It is an optional parameter.
  • chubbsondubs
    chubbsondubs over 11 years
    JFrame is Swing where Frame/Canvas is AWT. Swing is the newer component library and AWT is the old deprecated library. Swing uses light-weight components where AWT is native components. JFrame preferred to older AWT components.