OpenGL VM flag degrade performance on Java2D???

my situation was to have a game implemented without the flag for the OpenGL.
my framework (done in java2D) is completely based on the BufferedImageOp to draw on the fly effect!

how my frameworks works is this just create to any cycle the next immage and then the the drawable:


dbImage = JPanel.createImage(pWidth, pHeight); // create the double buffer immage
dbg = (Graphics2D) dbImage.getGraphics();

after that it is pass to the rendering that are 2D sprite based on the bufferedImmage
internalRenderGame(dbg);

any sprite before to be render on the dbg ( that i s the Graphics2D) is passed to a chain of effect that execute specific effect implemented as BufferedImageOp brightness, and transparence or affine trasfomration for scale and rotation


//filtersToApplyare all the filter ot use: can be any, one of this or all -->brightness, transparence,scale and rotation
BufferedImage filtered = EffectManager.getInstance().chain(filtersToApply,image, position, size, color);
dbg.drawImage(filtered, (int)(position.getPosX() - filtered.getWidth()/2), (int)(position.getPosY() - size.getHeigh()/2), null);

in the end finally draw the final immage with all the sprite and background painted over


g = (Graphics2D) gamePanel.getGraphics();
g.drawImage(doFinalEffect(dbImage), 0, 0,pWidth,pHeight, null);

but before is possible to pass the final image (that is the immage with the background and all the sprites) again to a chain of effect (that is implemented has before as BufferedImageOp brightness to make obscuration of all the immage)

ALL this story to explane that it is very easy nothing complex, and when i have activated the “OpenGL” VM flag -Dsun.java2d.opengl=True, my application is start to be very slow!!! it become a disaster, lost 30% of the frames!!!
i would like to understand why, or at list to understand how to analyze

Its likely the Direct3d backend is just faster on your pc (that is if you are on Windows).

Also “-Dsun.java2d.opengl=True” is a bit of a debug mode and will give you verbose console output, highly unlikely but “-Dsun.java2d.opengl=true” maybe a tiny bit faster.

btw which graphics card are you on?

the output in the console is almost nothing, so modifying it din’t recognize any effect

i’m working on my laptop and the graphics card is integrated on it:
Intel® HD Graphics Family

testing this card with the OpenGl Extensions viewer 3.0 i’m able to support with this card operation
openGL 2.2

Hi alesky!

I’ve been working a little bit with an intel HD3000 with Java2D in my laptop (JDK 7 and Windows 7) and:

I tried both flags: for using direct3D and openGL pipeline with:

System.setProperty(“sun.java2d.opengl”, “True”); or System.setProperty(“sun.java2d.d3d”, “True”);

And I get much better performance with direct3D pipeline.

Also, I have to say that, for some reason, the global performance of intelHD with java2D is quite bad, maybe is a driver issue. I have also a Nvidia GT520 in the laptop. In theory Nvidia GPU is not much better than the intel HD, but the performance in java2D is much better, maybe 5 times faster. Also, sometimes, the intel behaves weirdly. The performance suddently drops when I add some extra pictures.


About the code you show. Several months ago a did many microbenchs in order to get the best performance with java2D, but I don’t remember all the details.

You use a jPanel for drawing the stuff?. Did you tried to use a BufferStrategy over a canvas instead? As far I remember it gives better performance.

Ok, then you apply a set of affineTransforms, right?, so you create an intermediate BufferedImage called “filtered” with all the changes. Do you tried directly to draw the image to dbg without creating that “filtered” image?

something like this:

dbg.scale(scaleX,scaleY);
dbg.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,desired_alpha));
dbg.drawImage(image,brightness_operation,posX,posY);

also, are you creating a new image each cycle?

“dbImage = JPanel.createImage(pWidth, pHeight); // create the double buffer immage”

Why don’t you reuse it, I found that the command clearRect is really efficient for clearing an image, is even more efficient than fillRect.

//-----------------------------

I would not mind to take a look at your full code, I enjoy optimizing :stuck_out_tongue:

Cheers.

Personally I wouldn’t rely on that flag - some systems won’t support it, others will perform better, and some may even perform worse.

General consensus is: if you need reliable performance, Java2D is the wrong choice. :wink:

Oh, yes! davedes post remind me an important thing. Sometimes Java2D cannot recognize the hardware, so the direct3D pipeline cannot be activated. This happens for example in laptops with nvidia optimus.

You can solve this with the environment variable J2D_D3D_NO_HWCHECK=true, so you deactivate any hardware checking and pipeline can be enabled.

I would love to try java2D in more computers. But yes, it seems that if you go outside standard configurations, weird things can happen. That makes development more thrilling ;D

Setting flags like that always screams to me “I can determine what Java2D pipeline will run faster on this machine better than Java2D itself can.” Do you think the JVM is picking the wrong pipeline for some reason?

Next thanks to you
regarding the optimization i want to answer to all your idea just to share our knowledge

firs of all
The chose of the JPanel happen for one specific reason the method JPanel.createImage(pWidth, pHeight)
hire the official link to java doc http://docs.oracle.com/javase/6/docs/api/java/awt/Component.html#createImage(java.awt.image.ImageProducer)
this method must be called each time in the cycle, because it manage automatically for you the double buffering strategy
increasing the performance, so for this reason this object is used by double buffering i can not reuse the same object clearing the immage

never tried to do it by canvas, is there a specific method to do it automatically? the old AWT expose something to do it? if exsist let me know i want to try it

this part of the code is already optimized, the solution applied is this:
every image transformed in the chain of effect is stored in a repository keeping with it information of the kind of transformation performed over it, so every time that on a image is required to execute same effect, first of all I look in the repository if that image with that kind of transformation already exists in this case this image is get and reused, other ways a new image with effect is created and saved in the repository.
this make in my case a huge increasing of the performance and aloud to me to work on image modification on the fly
but the back side of this solution is the memory used to store images in the repository

instead regarding this fact (davedes please don’t take it personally, but i have to write this)

the fact that exist technologies that are better of the Java2D is something that also the kids know,
so if i use this specific section of the forum called Java2D, and not OpenGL Development may be ther is a reason what u think?
http://www.java-gaming.org/boards/java-2d/15/view.html

if i can get 1 euro for all the guys that write in this forum,

i will become one of the most reach person in the word (ok i will open a topic for this ;D)

regarding the real discussion of this topic,

me too!!!

i want to try to set the variable J2D_D3D_NO_HWCHECK=true and try to activate the direct3D. i will let to know how it works

alesky, I show you a skeleton of a canvas ready for drawing anything you want. I use a VolatileImage as a intermediate buffer. I set the same name you used. If you try it, it would be great some result comparison :smiley:

public class Zoom_canvas extends Canvas {
    
    
      

    protected BufferStrategy buffer;  //BufferStratrgy
    protected VolatileImage dbImage ; //VolatileImage as intermediate buffer
 
    

    public Zoom_canvas() {   //constructor
        this.setIgnoreRepaint(true); //we repaint manually
        this.setFocusable(false);

        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsConfiguration gc = ge.getDefaultScreenDevice().getDefaultConfiguration();
        dbImage = gc.createCompatibleVolatileImage(this.getWidth, this.getHeight, Transparency.TRANSLUCENT); //initialize the VolatileImage
    }

    public void dispose() {
        buffer.dispose();
    }

    public void Init() { //call this before starting game loop, it initializes the bufferStrategy
        createBufferStrategy(2);  //double buffering
        buffer = getBufferStrategy();
    }

    public void PerformDraw() {  //public drawing method, call this from your game loop for update image

        Graphics g;
        try {
            g = buffer.getDrawGraphics();
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
        this.paint((Graphics2D) g);
        g.dispose();

        if (!buffer.contentsLost()) {
            buffer.show();
        }
    }

    private void paint(Graphics2D g) { //real drawing method

        super.paint(g);

        Graphics2D ga = (Graphics2D) dbImage.getGraphics();
        ga.setBackground(new Color(0, 0, 0, 0));
        ga.clearRect(0, 0, dbImage.getWidth(), dbImage.getHeight()); // we clear the intermediate buffer

//===============================        
//... TO DO, ADD dome drawing here using "ga"!!!
//===============================
        ga.dispose();

        g.drawImage(dbImage, 0, 0, null);
        g.dispose();
    }
}