Rendering Performance Issues

The pixel data you get is nothing more but a 2Darray inside a 1D array. A 1D array can just as easily represent 2D dimensions.

For every “row” you simply increment the position by the width of the image.



http://processing.org/learning/2darray/

So micro optimizations that you can use when everything else is corrected.
You are calling pri.getHeight() six times in inner loop? It’s static and can be asked one time before both loops. Don’t compare against method call value in loop. Instead call against constant value. When somethin is changed you calculate this cx*pri.getHeight() + cy three times and when not two times. Pre calcualte it.
Make simple code that compiler and JIT can understand more easily and optimize it further. But before you do any of these work with higher level optimizations that are allready told.

And when you ask some about your code make it ready for the reviews. It’s lame excuse to say that there are some old copy paste buggers. Make it easy to other readers spot the right problem and fix everything that you know allready so time is not wasted.

A couple of corrections to things said earlier. There are some general misconceptions with managed images around here! :slight_smile:

There are two methods called setRGB, and I’ve only ever seen the issue with images becoming unmanaged mentioned with regard to the other one (that takes an array). I’m not sure it’s still the case there either. It’s still the slower way to do this though.

If the OP is updating the image every frame (and only drawing it once) then there is absolutely no point in worrying about whether the image is managed or not. Drawing into a BufferedImage, even with Graphics2D, happens in software. The image is only synced to video memory when it’s been drawn a couple of times without modification.

If you need to update the pixel array of an image every frame, just grab the pixels array from the raster and stop worrying about whether it’s managed or not (unless you have to draw it lots of times, or rotated / scaled, in which case copying to a VolatileImage first may help).

If you ever need to update an image every frame with Graphics2D, then use a VolatileImage and you have a chance your drawing to (as well as rendering from) the image will be accelerated.

But see… I still need that code…

This is the current setup. I’m trying to create a subimage based on the intersection of the image and the master image but it’s still throwing RasterFormatExceptions.

Perhaps I’m doing it wrong?

(Note: I will update OP with this new code)

The first answer here is useful for copying an image:

I’m not using that method anymore, but you’re right that it’s useful. Thanks for finding it! I will keep it in mind if I ever use it some other time.

What is your point?

This draws a pixel-array onto another pixel-array. I get around 2200 fps on an i5

	public void draw(ArrayImage a, int xp, int yp) { //Draw a normal tile
		for (int y = 0; y < a.height; y++) {
			int yPixel = y + yp;
			if (yPixel < 0 || yPixel >= height) continue;

			for (int x = 0; x < a.width; x++) {
				int xPixel = x + xp;
				if (xPixel < 0 || xPixel >= width) continue;	

				int srcPixel = a.pixels[x + y * a.width];
				if (srcPixel < 0 /*if <0 srcPixel is meant to be transparent*/) pixels[xPixel + yPixel * width] = srcPixel;													
			}
		}
	}

Without knowning the dimensions of those pixel-arrays, it’s a meaningless statistic :slight_smile:

Yeah pardon, i forgot it reaches 2200 fps with nothing on the screen, just filling it with zeros every iteration :stuck_out_tongue:

Also its 640x500

I think I might scrap this whole thing and just invoke drawImage on the Graphics2D created by the BufferStrategy.

Does anyone know why BufferStrategy.drawImage is SO much faster than BufferedImage.drawImage?

Why not just use System.arraycopy to copy a region of your image?

	/**
	 * Quickly copies the specified pixels from the source image to the destination image.
	 * @param src the source image
	 * @param dst the destination image
	 * @param srcX the x position of the source image to start copying
	 * @param srcY the y position of the source image to start copying
	 * @param srcW the width of the section to copy from source
	 * @param srcH the height of the section to copy from source
	 * @param dstX the x position to place the copied pixels at on the destination image
	 * @param dstY the y position to place the copied pixels at on the destination image
	 */
	public void copyPixels(BufferedImage src, BufferedImage dst, int srcX, int srcY, int srcW, int srcH, int dstX, int dstY) {
		int[] srcbuf = ((DataBufferInt)src.getRaster().getDataBuffer()).getData();
		int[] dstbuf = ((DataBufferInt)dst.getRaster().getDataBuffer()).getData();
		int srcOff = srcX + srcY * src.getWidth();
		int dstOff = dstX + dstY * dst.getWidth();
		for (int y=0; y<srcH; y++) { //copy every row of src starting at offset
			System.arraycopy(srcbuf, srcOff, dstbuf, dstOff, srcW);
			srcOff += src.getWidth();
			dstOff += dst.getWidth();
		}
	}

EDIT: If you’re loading images with ImageIO, they may not be TYPE_INT_ARGB. You can convert them easily like so:

		if (image.getType()!=BufferedImage.TYPE_INT_ARGB) {
			BufferedImage convertedImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
			convertedImage.createGraphics().drawRenderedImage(image, null);
			image = convertedImage;
		}

Is that faster than just doing BufferStrategy.drawImage?

Not to mention it has nothing to do with drawing performance, that’s just looping through arrays and setting their values.

It’s like measuring how long a for loop takes.

int[] array = new array[1920*1080];

for (int i = 0; i < array.length; i++) {
array[i] = (int) System.currentTimeMillis();
}

Doing this loop 60 times takes about ~0.07 seconds. looping through 600 times ~0.6 seconds. looping through 1200 times ~1.2seconds.

The statistic is meaningless because it doesn’t really have anything to do with frames per second or drawing. Am I wrong?

[EDIT]
Also, I made a super awesome illustrative image of what happens to an image when you turn it into an array of ints! (Row major order)

Before: BufferedImage = new BufferedImage(width, height);

After: int[] array = new int[width*height];

In the end, rendering is nothing more or less than moving data around.

I would guess yes… Unless you’re copying huge sections, in which case drawImage might take advantage of OpenGL acceleration (assuming it’s enabled).

If this kind of performance is necessary, just benchmark it yourself.

Well my point is that if it takes less than a second to loop and alter 2 073 600 000 pixels ( 1000 * 1920 * 1080 ), performance is a non issue. :o