4

For quite a long time, 1-2 months, I have been trying to find an answer to this particular problem:

I can't get my image hardware accelerated!

I've been searching on the net, created my own methods, hit my head with the keyboard (still feel the pain) but no success.

Although I hate libraries other than Java SDK, I tried LWJGL and JOGL but for some stupid reason they dont work on my computer.

I tried using System.setProperty("Dsun.java2d.opengl", "True"), I used VolatileImage but I can't draw individual pixels to it.(I tried using drawLine(x,y,x,y) but it's slow)

Now I am so desperate. I will do anything to fix this! So please, if you know the solution (I know some of you do) tell me so I can get rid of this.

My code:

   public static void render(int x, int y, int w, int h, ) {

            int a[] = new int[3]; // The array that contains RGB values for every pixel
            BufferedImage bImg = Launcher.contObj.getGraphicsConfiguration().createCompatibleImage(800, 600, Transparency.TRANSLUCENT); // Creates an image compatible to my JPanel (Runs at 20-24 FPS on 800x600 resolution)
            int[] wr = ((DataBufferInt) bImg.getRaster().getDataBuffer()).getData(); // Contains the image data, used for drawing pixels
            for (int i = 0; i < bImg.getWidth(); i++) {
                for (int j = 0; j < bImg.getHeight(); j++) {
                    a[0] = i % 256;
                    a[2] = j % 256;
                    a[1] = i * j % 256;
                    wr[i + j * bImg.getWidth()] = new Color(a[0], a[1], a[2]).getRGB(); // Sets the pixels from a[]
                }
            }
            bImg.flush();
            g.drawImage(bImg, x, y, w, h, null); // Draws the image on the JPanel
            g.dispose();
            System.out.println(bImg.getCapabilities(Launcher.contObj.getGraphicsConfiguration()).isAccelerated()); // Prints out whether I was successful and made the image accelerated or failed and made everything worse
        }

I hope you understand the code. Please modify it in any way to help me find the solution to my problems.

Note: Please don't post anything about external libraries unless you are absolutely sure that I can't get this working without them.

Also, could it be that my graphics card doesn't support acceleration? (because I saw posts where hardware accel works for other people but not for me) Btw, it's a GeForce 430 GT.

THANKS IN ADVANCE!

  • What kind of performance gain do you expect from moving to the GPU an image buffer that you keep painting pixels onto? You know, it's faster to write to a memory many times and then dump the whole thing to the GPU at once than to make many individual calls to the GPU. – John Dvorak Oct 17 '13 at 14:56
  • check this: http://stackoverflow.com/questions/14635377/java-hardware-acceleration-not-working-with-intel-integrated-graphics – nullptr Oct 17 '13 at 15:58
  • Did you tried example I posted! – nullptr Oct 17 '13 at 16:37

1 Answers1

4

Source copied from : Java Hardware Acceleration not working with Intel Integrated Graphics

Try this:

package graphicstest;

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferStrategy;

public class GraphicsTest extends JFrame {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new GraphicsTest();
            }
        });
    }

    GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
    BufferCapabilities bufferCapabilities;
    BufferStrategy bufferStrategy;

    int y = 0;
    int delta = 1;

    public GraphicsTest() {

        setTitle("Hardware Acceleration Test");
        setSize(500, 300);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        setVisible(true);

        createBufferStrategy(2);
        bufferStrategy = getBufferStrategy();

        bufferCapabilities = gc.getBufferCapabilities();

        new AnimationThread().start();
    }

    class AnimationThread extends Thread {
        @Override
        public void run() {

            while(true) {
                Graphics2D g2 = null;
                try {
                    g2 = (Graphics2D) bufferStrategy.getDrawGraphics();
                    draw(g2);
                } finally {
                    if(g2 != null) g2.dispose();
                }
                bufferStrategy.show();

                try {
                    // CHANGE HERE, DONT SLEEP
                    //Thread.sleep(16);
                } catch(Exception err) {
                    err.printStackTrace();
                }
            }
        }
    }

    public void draw(Graphics2D g2) {
        if(!bufferCapabilities.isPageFlipping() || bufferCapabilities.isFullScreenRequired()) {
            g2.setColor(Color.black);
            g2.fillRect(0, 0, getWidth(), getHeight());
            g2.setColor(Color.red);
            g2.drawString("Hardware Acceleration is not supported...", 100, 100);
            g2.setColor(Color.white);
            g2.drawString("Page Flipping: " + (bufferCapabilities.isPageFlipping() ? "Available" : "Not Supported"), 100, 130);
            g2.drawString("Full Screen Required: " + (bufferCapabilities.isFullScreenRequired() ? "Required" : "Not Required"), 100, 160);
            g2.drawString("Multiple Buffer Capable: " + (bufferCapabilities.isMultiBufferAvailable() ? "Yes" : "No"), 100, 190);
        } else {
            g2.setColor(Color.black);
            g2.fillRect(0, 0, getWidth(), getHeight());
            g2.setColor(Color.white);
            g2.drawString("Hardware Acceleration is Working...", 100, 100);
            g2.drawString("Page Flipping: " + (bufferCapabilities.isPageFlipping() ? "Available" : "Not Supported"), 100, 130);
            g2.drawString("Full Screen Required: " + (bufferCapabilities.isFullScreenRequired() ? "Required" : "Not Required"), 100, 160);
            g2.drawString("Multiple Buffer Capable: " + (bufferCapabilities.isMultiBufferAvailable() ? "Yes" : "No"), 100, 190);
        }

        y += delta;
        if((y + 50) > getHeight() || y < 0) {
            delta *= -1;
        }

        g2.setColor(Color.blue);
        g2.fillRect(getWidth()-50, y, 50, 50);
    }
}

Output I got hardware accelaration not available. java.exe was taking 12% CPU. 700 FPS

Then I added System variable:

Variable name: J2D_D3D_NO_HWCHECK
         Variable value: true

then restarted IDE, and ran program:

I got amazing result. I got hardware acceleration available. java.exe was taking 5% CPU. 1700 FPS. Animation was great!

Above things are to check whether hardware acceleration works in your system.

Now to your question:

AFAIK: You can't get real hardware acceleration with BufferedImage. You should work with VolatileImage to get hardware acceleration. But with VolatileImage, you can't get pixel data buffer to modify pixels. And rendering pixel by pixel using hardware doesn't make sense.

What I suggest:

1) Design your logic, which can render pixels using Graphics and Graphics2D of volatile image. But don't go to make hack like drawing lines of 1 pixel.

2) Use buffer strategies, double / triple buffering.

3) If you want to stick with BufferedImage for setting each pixel, use BufferedImage as data model, while rendering draw buffered image on volatile image. This will help a lot if you are scaling image.

4) Cache the images frequently being rendered.

5) Write code better, like:

int wi = bImg.getWidth();
int he = bImg.getHeight();
for (int i = 0; i < wi; i++) {
    for (int j = 0; j < he; j++) {
        wr[i + j * wi] = ((i % 256) << 16) | ((i * j % 256) << 8) | (j % 256);
    }
}

6) For time consuming math operation like sqrt(), sin(), cos(), cache results of these operations and create lookup tables.

Community
  • 1
  • 1
nullptr
  • 3,320
  • 7
  • 35
  • 68
  • This is accelerated sure but the OP has the problem of acceleration turning off when he edits a pixel. – arynaq Oct 17 '13 at 16:06
  • Actually I was also looking for answer of this question since long ago, I got this answer from other post, and got excited, couldn't resist myself from helping other. – nullptr Oct 17 '13 at 16:13
  • Actually this will help OP to get to know whether hardware acceleration works on system or not! – nullptr Oct 17 '13 at 16:39
  • Sorry for my late reply. The environment variable added like 5 FPS (at least I think it's because of that) but it still isn't accelerated. About using VolatileImage... What's the point in having 200 FPS if I can't change pixels? At least the rendering algorithm I had in mind must be able to modify individual pixels in order to work. Btw, I don't know exactly what you mean by 'cacheing images'. Anyway, thanks for the effort, and sorry for the trouble. – Sonjo Falce Oct 18 '13 at 16:36
  • I have another question. How does the JRE System Library graphics drawRect or fillRect or drawImage? I can't think of another way than modifying pixels. How come their drawing is accelerated? What method does the 'fillRect()' use to draw pixels and why is that method not available for us? (My computer has available hardware accel) – Sonjo Falce Oct 18 '13 at 16:41
  • See, setting pixels using hardware acceleration does not make sense, because if you need to modify pixels for say 800x600 image, will you calling hardware 800x600x200 times for drawing complete picture with 200 FPS? – nullptr Oct 18 '13 at 17:26
  • Calling hardware for such things has overhead, but if you are telling hardware to render 800*600 image in one call, overall overhead is less. – nullptr Oct 18 '13 at 17:30
  • AFAIK, calling drawRect fillRect or drawImage gets converted to call to hardware for such things, and hardware will process that complete call. Overhead is less, as you are telling so many pixels to change in one call. – nullptr Oct 18 '13 at 17:33
  • 1
    Think like, you told hardware to draw 100x100 rectangle (more efficient). Another way, you told 100x100 times hardware to draw each pixel of rectangle (Very less efficient). – nullptr Oct 18 '13 at 17:35