Speeding up PBuffer-operations

Hi there,
is there a possibility to speed up screenshots with alpha channel from PBuffers? I had some operations made on a GLJPanel, but due to changes in the programm, I now have to use a pBuffer and draw the rendering with alpha channel to a normal JPanel. But the screenshot is a really slow operation if alpha channel has to be taken too. Speed is okay if no alpha information is taken. Does the alpha channel really slows down the operation this much or can it be optimized ???

Greetings FatFire

You could try to use a FBO instead of a pBuffer for this.

Sorry for warming up this again, but how exactly would I use a frame buffer object to render into a buffered image (or a volatile image, only holding the data on the gfx card would be damn fast, or not) ? I found several tutorials about rendering to texture, but I am not really sure how to use this for my problem. Maybe someone got a little code snippet which shows just how to enable fbo and how to get a buffered (volatile) image out of it?

Greetings FatFire :slight_smile:

Could’nt anyone give me a hint? Or maybe a link with further information? Maybe an idea how to speed up this operation? It’s really hard, because Screenshot and painting with alpha channel takes about 1.5s, without just 0.1s!

Are you sure the problem lies within the screenshot or could it be that painting with enabled alpha-channel is slow? 1,5s seems way too much either way, so what resolution are you sceenshooting and what are you using to take the screenshot. Also try a profiler to find the most costly part of the operation.

Never used before a profiler…I’ll see, if I can try that, to find out, what takes so much time. But a fast check with timestamps showed, that only taking the screenshot takes about 1.2s (90ms without Alphachannel, yeah, I know, drawing speed also goes down very hard).

Screenshot-Resolution is 986 x 725, but it wouldn’t make sense to reduce that. Maybe there is another solution to render big scene offscreen and to put the result into a bufferedimage?

Edit: Sorry, I am taking screenshot and paint like this:

BufferedImage tmpImage = Screenshot.readToBufferedImage(currentExtentInPixel.width,
          currentExtentInPixel.height, true);
g2.drawImage(tmpImage, null, 0, 0);

Hmm so maybe the screenshoot utility has a bug or there is a driver issue with alpha reads. Getting comfortable with a profiler will be handy in a lot of situations. There was a thread about profilers some time ago: http://www.java-gaming.org/forums/index.php?topic=14155

It looks like glReadPixels with a GL_ABGR_EXT readback type might be slow on your setup. What kind of graphics card do you have? Do you have a test case for the slowdown? I can think of a fairly straightforward change to the Screenshot code that I can check in for you to try, but I need to see why our nightly builds are still failing.

System:
Microsoft Windows 2000
5.00.2195
Service Pack 4

Computer:
AMD Athlon XP 2100+
512 MB Ram
Club3D ATI Radeon 9600 Non-pro 256 MB (Driver-version: 6.14.10.6599)

Little Test Case:

import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLPbuffer;

import com.sun.opengl.util.Screenshot;


public class AlphaSlowTestCase implements GLEventListener{

	private static final long serialVersionUID = 1L;
	private int width, height;
	
	public AlphaSlowTestCase(){
		GLCapabilities glcaps = new GLCapabilities();
		for(height = 48 ; height <= 1536 ; height *= 2){
			width = (int)((double)height / 0.75);
			GLPbuffer pBuffer = GLDrawableFactory.getFactory().createGLPbuffer(glcaps,
					null, width, height, null);
			pBuffer.addGLEventListener(this);
			pBuffer.display();
			try {Thread.sleep(2000);} catch (InterruptedException e) {}
		}
	}

	public static void main(String[] args) {
		new AlphaSlowTestCase();
	}

	public void display(GLAutoDrawable arg0) {
		long timestamp1, timestamp2, differenceAlpha, differenceNoAlpha;
		timestamp1 = System.nanoTime();
		Screenshot.readToBufferedImage(width, height, false);
		timestamp2 = System.nanoTime();
		differenceNoAlpha = (timestamp2 - timestamp1) / 1000000;
		timestamp1 = System.nanoTime();
		Screenshot.readToBufferedImage(width, height, true);
		timestamp2 = System.nanoTime();
		differenceAlpha = (timestamp2 - timestamp1) / 1000000;
		System.out.println("Screenshot with resolution " + width + "x" + height + "\n");
		System.out.println("Without Alphachannel\tWith Alphachannel");
		System.out.println(differenceNoAlpha + "ms\t\t\t" + differenceAlpha + "ms\n");
	}

	public void displayChanged(GLAutoDrawable arg0, boolean arg1, boolean arg2) {}

	public void init(GLAutoDrawable arg0) {}

	public void reshape(GLAutoDrawable arg0, int arg1, int arg2, int arg3, int arg4) {}

}

Test results:

[i]Screenshot with resolution 64x48

Without Alphachannel With Alphachannel
57ms 6ms

Screenshot with resolution 128x96

Without Alphachannel With Alphachannel
7ms 24ms

Screenshot with resolution 256x192

Without Alphachannel With Alphachannel
12ms 90ms

Screenshot with resolution 512x384

Without Alphachannel With Alphachannel
30ms 369ms

Screenshot with resolution 1024x768

Without Alphachannel With Alphachannel
118ms 1566ms

Screenshot with resolution 2048x1536

Without Alphachannel With Alphachannel
582ms 5916ms[/i]

I think 10 times slower isn’t normal at all ???

Hum, really seems to be a problem with my gfx card / computer…test results from another computer with NVidia Geforce 6600GT:

[i]Screenshot with resolution 64x48

Without Alphachannel With Alphachannel
15ms 2ms

Screenshot with resolution 128x96

Without Alphachannel With Alphachannel
2ms 1ms

Screenshot with resolution 256x192

Without Alphachannel With Alphachannel
3ms 3ms

Screenshot with resolution 512x384

Without Alphachannel With Alphachannel
9ms 9ms

Screenshot with resolution 1024x768

Without Alphachannel With Alphachannel
30ms 69ms

Screenshot with resolution 2048x1536

Without Alphachannel With Alphachannel
147ms 177ms[/i]

Looks like I have to tighten my requirements…beyond my configuration.

Edit: If my gfx card doesn’t support the GL_ABGR_EXT-Extension, is there a faster way than the Screenshot-class to take Screenshot with Alpha channel? I can’t really believe that changing the byteorder from RGBA to ABGR is so slow.

You can try allocating a TYPE_INT_ARGB BufferedImage (note that it will contain a DataBufferInt, not a DataBufferByte) and using the GL_BGRA pixel format with the GL_UNSIGNED_INT_8_8_8_8_REV pixel type. This is the workaround I discussed above which I’m planning to add.

Hooray, Ken, you are a genius ;D

Before: 1669ms
After: 68ms

Now my old Radeon is sprinting through this disciplin as well as the NVidia.

Thank you very much :slight_smile:

Greetings FatFire

Edit: Hum, but if I use this with the NVidia card, the alpha informations seem to get lost? ::slight_smile: I think I hate hardware near programming.

Did you explicitly request an alpha channel in your GLCapabilities (caps.setAlphaBits(8))? If not then you may just be getting lucky with getting one on the ATI card.

Yes, that was the problem. Shame on me, read it every day and then I do the same mistake ::slight_smile: I think I deleted the wrong code when I had a subversion conflict in that area :o
But it’s really disgusting if it’s working on one gfx card and another behaves totally different.

Thanks again

Greetings
FatFire