Besides... this is just a bunch of mental masturbation. The JRE might "officially" have you modify data with BufferedImage.setRGB or MemoryImageSource. But for practical and performance purposes (in my limited testing), you might rather use int[] of a BufferedImage.

If public API returns a DataBuffer, and it turns out to be a DataBufferInt, we have a guarantee that it will behave like it says in the specification. If the JRE library developers want to change things behind the scenes that affects behaviour to the point that it no longer behaves like specified by DataBufferInt, they must use/create a different subtype of DataBuffer. The fallback will keep the application functional in this case, therefore the application won't be broken, like you suggested.

I don't understand your argument regarding the fallback. If you could explain that more I would appreciate it.

If the JRE developers want to change things behind the scenes, why should they be forced to keep a promise they never made so a bunch of improperly implemented code can still work?

If I promise to return A, and everyone assumes I return B because I do infact return B, it is then my fault when I return C at a later point in time, which is not B but is A?

If I promise to return A, and everyone assumes I return B because I do infact return B, it is then my fault when I return C at a later point in time, which is not B but is A?

I check whether you return an instance of B, if so, use it as B, and if not, I use the returned instance as an A (which may or may not be a C,D,etc). So, the moment you start returning C, my app still works, because I use C as A (which is a promise).

That, is a proper fallback.

Hi, appreciate more people! Σ ♥ = ¾Learn how to award medals... and work your way up the social rankings!

If I promise to return A, and everyone assumes I return B because I do infact return B, it is then my fault when I return C at a later point in time, which is not B but is A?

I check whether you return B, if so, use B, and if not, I use it as an A (which may or may not be a C). So, the moment you start returning C, my app still works, because I use C as A (which is a promise).

That, is a fallabck.

That makes sense. And I would argue that implementation makes complete sense. Still though, I do feel like you are accessing protected data - none the less I wouldn't mind this.

Golly, I almost feel as if I started this whole thing. I don't think this was started as a means to heatedly discuss hardware acceleration or what the most OOP way to access pixels.

I was actually trying to find a way to do fast perlpixel software effects. Not really OOP's way. I come from a C++ background where you could just declare an int pointer, point it to the image's data buffer and write directly so this is kind of new to me.

Though, I'm kinda lost halfway through the discussions because of my light java experience.

It being used internally makes no argument. Ask Microsoft how much undocumented functionality is in use under their Operating System. Most software frameworks do this, as I've already pointed out. The difference is you aren't maintaining your development platform and thus you shouldn't make assumptions because Oracle isn't going to contact you when they've refactored code.

But whatever, I yield. While it is not functionality that will likely change, it is definitely accessing protected data buffers (which was why my initial assumption was made)

Using instanceof is in essence against OOP practice. So is casting down to get functionality that was intentionally unexposed.

a) This isn't going to change because the Java2D team have been recommending this approach for over a decade. The DataBuffer is specified to be of TYPE_INT - to be nitpicky it might have been better if they had specified this meant DataBufferInt or subclass.

b) I've already posted a link earlier which shows how to build a BufferedImage from an int[], and therefore is the absolutely safe way to do this following the spec to the letter.

I was not aware that this was being encouraged by the Java2D team, I asked if it was earlier and no one responded, is this true? Internal usage != encouraged usage.

You shouldn't ever construct a buffered image (at least for your backbuffer) the way you describe if you plan on rendering it to a graphics object. It won't be guaranteed to be compatible with the device. Hence why the entire process is abstracted via createCompatibleImage of the corresponding GraphicsConfiguration.

Albeit, that point is moot anyway since I can't find anywhere in the doc that says anything that guarantees this isn't wrapped etc...

Anyway, I disagree with Riven's fallback in this case, as it requires writing an unnecessary code path that will not be required. If you want a clean way to do this without breaking encapsulation, then wrap the pixel array into an image as below. This way you don't access any 'protected' data and fully follow the spec. It also protects you from two other issues you'll never see in practice - data offset and scanline.

You shouldn't ever construct a buffered image (at least for your backbuffer) the way you describe if you plan on rendering it to a graphics object. It won't be guaranteed to be compatible with the device. Hence why the entire process is abstracted via createCompatibleImage of the corresponding GraphicsConfiguration.

Load of rubbish! createCompatibleImage() just means you have an image in the same color model as the screen, and so is (theoretically) faster to draw to the screen. If you're doing direct pixel manipulation you want a guaranteed color model to work with. Drawing to the screen is only a small part of the overhead, and there are optimized paths for converting default RGB color models.

Albeit, that point is moot anyway since I can't find anywhere in the doc that says anything that guarantees this isn't wrapped etc...

That's Java! It's pass-by-reference by default, which means if anything accepts a mutable object, it should respond to changes in that object. This is used all over the JRE - eg. passing models into Swing components. Anything that has pass-by-value semantics, which being Java means cloning or otherwise copying data, says so in the documentation.

I've been doing loads of stuff with direct pixel manipulation for over ten years - I'm glad you've popped up to tell me it doesn't work!

Load of rubbish! createCompatibleImage() just means you have an image in the same color model as the screen, and so is (theoretically) faster to draw to the screen. If you're doing direct pixel manipulation you want a guaranteed color model to work with. Drawing to the screen is only a small part of the overhead, and there are optimized paths for converting default RGB color models.

It does drastically increase performance (from my experience) but it depends on the environment. Creating a compatible image also allows it to be hardware accelerated where optimal - definitely something you want for your backbuffer (ofcourse doing software based per-pixel operations on your backbuffer throws that out the window anyways.)

That's Java! It's pass-by-reference by default, which means if anything accepts a mutable object, it should respond to changes in that object. This is used all over the JRE - eg. passing models into Swing components. Anything that has pass-by-value semantics, which being Java means cloning or otherwise copying data, says so in the documentation.

Fair point, and this does make sense. I haven't been programming in Java in particular long enough to know of the special points it makes regarding this in the javadoc.

Quote

I've been doing loads of stuff with direct pixel manipulation for over ten years - I'm glad you've popped up to tell me it doesn't work!

I'm not telling you that it doesn't work. My point consists of two arguments:- Software shaders are not practical for a real-time render loop in most games where rendering is already an expensive operation.- You are hacking your way into an object's hidden data.

The second argument was for an older code snippet, the code snippet you just presented I haven't got a problem with.

Creating a compatible image also allows it to be hardware accelerated where optimal - definitely something you want for your backbuffer

All BufferedImages can be "managed" - cached in video memory. You don't need to use createCompatibleImage for this.

Rendering into a BufferedImage is not hardware accelerated. You don't want to be using them for a back buffer! createCompatibleVolatileImage maybe. Or use a BufferStrategy which will do that under the hood.

All BufferedImages can be "managed" - cached in video memory. You don't need to use createCompatibleImage for this.

Rendering into a BufferedImage is not hardware accelerated. You don't want to be using them for a back buffer! createCompatibleVolatileImage maybe. Or use a BufferStrategy which will do that under the hood.

How else would you apply a post-processing software-shader effect to the data rendered on the backbuffer?

the old MediaTracker functionality thrown in for free). Images that you get from other key means, such as ImageIO-created images or any image created explicitly through calling new BufferedImage() are not managed, and thus will not benefit from under-the-hood acceleration possibilities. p

If your rendering is that expensive, you'd be a fool to be using Java2D to start with! They're perfectly "practical" for simple things and specific use cases, and also potentially as a learning tool.

It's the required abstraction in Java2D that makes doing things its not supposed to do slow, if you use Java2D properly and you don't need to travel down those optimization routes not offered by Java2D (i.e, hardware shader) then your code should in theory perform just as optimally if you did the same in OpenGl (in theory better because the JRE can make educated decisions based on the platform regarding which rendering APIs to use)

It's the required abstraction in Java2D that makes doing things its not supposed to do slow, if you use Java2D properly and you don't need to travel down those optimization routes not offered by Java2D (i.e, hardware shader) then your code should in theory perform just as optimally if you did the same in OpenGl (in theory better because the JRE can make educated decisions based on the platform regarding which rendering APIs to use)

Nice theory! In practice, that's not true. Java2D is a general purpose imaging API - it aims for compatibility across renderers that isn't compatible with fast rendering (ie. pixel accuracy). You also have no idea what will be accelerated and what will be punted to the software loops - and direct pixel manipulation in Java can often outperform those software loops!

It's the required abstraction in Java2D that makes doing things its not supposed to do slow, if you use Java2D properly and you don't need to travel down those optimization routes not offered by Java2D (i.e, hardware shader) then your code should in theory perform just as optimally if you did the same in OpenGl (in theory better because the JRE can make educated decisions based on the platform regarding which rendering APIs to use)

Nice theory! In practice, that's not true. Java2D is a general purpose imaging API - it aims for compatibility across renderers that isn't compatible with fast rendering (ie. pixel accuracy). You also have no idea what will be accelerated and what will be punted to the software loops - and direct pixel manipulation in Java can often outperform those software loops!

Which I hadn't before noticed - this seems to make your point regarding managed images. A further google search than I thought it would be though I may have just not been googling the proper keywords.

In terms of performance comparison with Java2D and OpenGL - I don't think it is ever fair to generalize the performance of an entire API to be slower than another. It really depends on what you are using it for. On Windows with poor OpenGL driver support (or none at all) you could experience incredibly poor frame rates using native OpenGL and higher framerates using D3D\DirectDraw via Java2D, and vise-versa. There are a lot of things you cannot do in Java2D that you can do in OpenGL, but if you need nothing more than Java2D there is no reason not to use it.

In terms of performance comparison with Java2D and OpenGL - I don't think it is ever fair to generalize the performance of an entire API to be slower than another. It really depends on what you are using it for.

In terms of performance comparison with Java2D and OpenGL - I don't think it is ever fair to generalize the performance of an entire API to be slower than another. It really depends on what you are using it for.

And what it's designed for!

People use Java because it abstracts them from hardware-level details - sure that isn't always possible when it comes to developing games, but where it is it should be taken advantage of, it is one of the core concepts of Java. Write Once, Run Anywhere. Sure, occasionally we need native dependencies, but if you can avoid them you should.

I do like Java2D for it's simplicity, and ease of use, little to no setup, etc.

Quote

if you need nothing more than Java2D there is no reason not to use it.

Indeed. And if you also need per-pixel manipulation, then use the databuffer method.

I just wrote a quick comparison between using drawLine() to a BufferedImage, then drawing it to screen (standard J2D), my int[] method, and, for fun, an interleaved byte[] method, to see if it's any faster. See for yourself:EDIT: Added setRGB() testQuick n' dirtyTM bench mark

Disclaimer: There may be many non-optimal things in that code, feel free to modify and show me. Also, this bench mark only tests writing to a backbuffer, not reading data back from it. That test would be even more embarrassing for J2D as that would compare array access to getRGB().

@BurntPizza - do you find your results a surprise? Can your code draw angled lines or an oval? You're comparing something designed for a specific purpose to a general purpose image library / rasterizer. Some things can be much faster using direct pixel manipulation because you can bypass a huge amount of indirection.

This is comparing rendering to a BufferedImage though, which is all software on the Graphics2D side as well. How about using a VolatileImage for the Graphics2D test? Still use BufferedImages for the others - that should might compare your pixel manipulation against the accelerated pipeline.

Interestingly, for game purposes, sprite blitting can be quite fast (as long as we're not talking transformation or scaling), even using blending. See these blendmodes for example.

@BurntPizza - do you find your results a surprise? Can your code draw angled lines or an oval? You're comparing something designed for a specific purpose to a general purpose image library / rasterizer. Some things can be much faster using direct pixel manipulation because you can bypass a huge amount of indirection.

I agree, and no, I don't find the result a surprise, it is what I expected.

A long time ago I wrote an ArrayGraphics class that had all the standard Graphics.drawXXX() and fillXXX() methods, based off Brensenham's, etc, and used the int[] method. Was still much faster than equivalent J2D operations. I'll see if I can find it and give it a reboot.

Indeed. And if you also need per-pixel manipulation, then use the databuffer method.

I think it's harder to make a generalization like that. It depends on what you are using the per-pixel manipulation for. If you're doing a bunch of different post-processing effects on a relatively large buffer in a real-time loop, it's hopeless (for now.)

Are you measuring just the time it takes to render over a buffered image? Or that and the time it takes to render the actual image to the given surface? drawLine etc are hardware accelerated so they won't force the JRE to give up accelerating the image, per pixel operations aren't.

@Jeremy - drawLine() on a BufferedImage is not hardware accelerated, and the image is only cached in video memory the second time it's drawn without being modified. Therefore it makes no difference to this test. This is why I suggested switching to VolatileImage where drawLine() may be accelerated.

@Jeremy - drawLine() on a BufferedImage is not hardware accelerated, and the image is only cached in video memory the second time it's drawn without being modified. Therefore it makes no difference to this test. This is why I suggested switching to VolatileImage where drawLine() may be accelerated.

Just tested using VolatileImage for the drawLine() test, still BufferedImage for others, results:

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org