Java-Gaming.org Hi !
Featured games (81)
games approved by the League of Dukes
Games in Showcase (513)
Games in Android Showcase (119)
games submitted by our members
Games in WIP (576)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: 1 [2] 3
  ignore  |  Print  
  Pixel manipulation with bufferstrategy.  (Read 6425 times)
0 Members and 2 Guests are viewing this topic.
Offline davedes
« Reply #30 - Posted 2013-08-15 20:55:52 »

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.

Offline Jeremy
« Reply #31 - Posted 2013-08-15 21:00:22 »

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?

JevaEngine, Latest Playthrough (This demo is networked with a centralized server model)

http://www.youtube.com/watch?v=rWA8bajpVXg
Online Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #32 - Posted 2013-08-15 21:02:55 »

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
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Jeremy
« Reply #33 - Posted 2013-08-15 21:05:38 »

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.

JevaEngine, Latest Playthrough (This demo is networked with a centralized server model)

http://www.youtube.com/watch?v=rWA8bajpVXg
Offline epicpunnum

Junior Newbie


Exp: 2 years


A man with a plan.


« Reply #34 - Posted 2013-08-15 22:37:25 »

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

Currently designing a puzzle-horror game called SLEEP in my free time.
I also draw and animate stuff on Youtube. Cheesy
Offline relminator
« Reply #35 - Posted 2013-08-15 23:05:59 »

Golly, I almost feel as if I started this whole thing.  Lips Sealed
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. Smiley

Though, I'm kinda lost halfway through the discussions because of my light java experience. Smiley
Offline BurntPizza
« Reply #36 - Posted 2013-08-15 23:30:13 »

I come from a C++ background where you could just declare an int pointer, point it to the image's data buffer

That's pretty much exactly what you get with the method I posted. Fast too.  Smiley
Offline relminator
« Reply #37 - Posted 2013-08-16 04:35:28 »

Thanks! will try it later today.
Offline relminator
« Reply #38 - Posted 2013-08-17 09:59:23 »

Yay! Got it to work! Thanks guys!



www.java-gaming.org/index.php?action=post;board=22.0
Offline nsigma
« Reply #39 - Posted 2013-08-17 11:05:28 »

Great stuff!  Your link to the other topic is broken though.  Wink

Glad you didn't get dissuaded by the arguments in this thread - if it's good enough for JavaFX ...   Grin

Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Jeremy
« Reply #40 - Posted 2013-08-17 11:27:00 »

Great stuff!  Your link to the other topic is broken though.  Wink

Glad you didn't get dissuaded by the arguments in this thread - if it's good enough for JavaFX ...   Grin

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.

JevaEngine, Latest Playthrough (This demo is networked with a centralized server model)

http://www.youtube.com/watch?v=rWA8bajpVXg
Offline nsigma
« Reply #41 - Posted 2013-08-17 11:49:47 »

@Jeremy - oh, you're back!  Tongue

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.

Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
Offline Jeremy
« Reply #42 - Posted 2013-08-17 12:21:02 »

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...

JevaEngine, Latest Playthrough (This demo is networked with a centralized server model)

http://www.youtube.com/watch?v=rWA8bajpVXg
Offline nsigma
« Reply #43 - Posted 2013-08-17 16:26:26 »

@Jeremy - you've changed your reply since I first read it!  Emo

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.

1  
2  
3  
4  
5  
6  
int[] pixels = new int[width * height];
DataBufferInt db = new DataBufferInt(pixels, pixels.length);
ColorModel cm = ColorModel.getRGBdefault();
WritableRaster raster = Raster.createPackedRaster(db, width, height, width, cm.getMasks(), null);
BufferedImage image = new BufferedImage(cm, raster, false, null);
// play with pixel array as you want


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!  Tongue

Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
Offline Jeremy
« Reply #44 - Posted 2013-08-17 17:11:07 »

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!  Tongue
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.

JevaEngine, Latest Playthrough (This demo is networked with a centralized server model)

http://www.youtube.com/watch?v=rWA8bajpVXg
Offline nsigma
« Reply #45 - Posted 2013-08-17 17:36:39 »

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.

- Software shaders are not practical for a real-time render loop in most games where rendering is already an expensive operation.

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

Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
Offline Jeremy
« Reply #46 - Posted 2013-08-17 17:45:38 »

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?

I am pretty sure that not 'every' bufferedimage is managed, you have to go through a particular process to acquire a managed buffered image, but correct me if I am mistaken:
https://weblogs.java.net/blog/chet/archive/2003/08/bufferedimage_a_1.html

Quote
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!  Wink  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)

JevaEngine, Latest Playthrough (This demo is networked with a centralized server model)

http://www.youtube.com/watch?v=rWA8bajpVXg
Offline BurntPizza
« Reply #47 - Posted 2013-08-17 17:52:28 »


Note that that post is from 2003. Things have changed, and my understanding is that BufferedImages are managed by default, until you do some illegal operation, usually involving their Rasters, etc.

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)

I think many will agree with me when I say that OpenGL is far faster for just about any operation in J2D, not mention the operations not in the J2D API.
Offline nsigma
« Reply #48 - Posted 2013-08-17 17:55:37 »

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

You wouldn't in this specific case, as you'd have to use the BufferedImage methodology above - you still don't need a compatible image for that though.

I am pretty sure that not 'every' bufferedimage is managed, you have to go through a particular process to acquire a managed buffered image, but correct me if I am mistaken:
https://weblogs.java.net/blog/chet/archive/2003/08/bufferedimage_a_1.html

Your information is about a decade too old!  Wink  This changed in Java 1.5.

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!

Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
Offline Jeremy
« Reply #49 - Posted 2013-08-17 18:11:46 »

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

You wouldn't in this specific case, as you'd have to use the BufferedImage methodology above - you still don't need a compatible image for that though.

I am pretty sure that not 'every' bufferedimage is managed, you have to go through a particular process to acquire a managed buffered image, but correct me if I am mistaken:
https://weblogs.java.net/blog/chet/archive/2003/08/bufferedimage_a_1.html

Your information is about a decade too old!  Wink  This changed in Java 1.5.

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!

Found this:
http://docs.oracle.com/javase/7/docs/technotes/guides/2d/new_features.html

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.

Anyways, it seems I've thrown us off topic.

JevaEngine, Latest Playthrough (This demo is networked with a centralized server model)

http://www.youtube.com/watch?v=rWA8bajpVXg
Offline nsigma
« Reply #50 - Posted 2013-08-17 18:20:36 »

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!

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

There are many, but I'm not going to argue that further - just try reading this forum!  Grin


Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
Offline Jeremy
« Reply #51 - Posted 2013-08-17 18:31:27 »

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.

JevaEngine, Latest Playthrough (This demo is networked with a centralized server model)

http://www.youtube.com/watch?v=rWA8bajpVXg
Offline BurntPizza
« Reply #52 - Posted 2013-08-17 19:21:38 »

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() test
Quick 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().

Post results! I'm curious!

Typical on my machine:

1  
2  
3  
4  
5  
Rendering Test: 200 frames...
Time for drawLine(): 10.34 s
Time for setRGB(): 2.74 s
Time for int[]: 1.53 s
And for fun, time for byte[]: 1.44 s
Offline nsigma
« Reply #53 - Posted 2013-08-17 20:01:45 »

@BurntPizza - do you find your results a surprise?  Can your code draw angled lines or an oval?  Wink  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.

Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
Offline BurntPizza
« Reply #54 - Posted 2013-08-17 20:10:29 »

@BurntPizza - do you find your results a surprise?  Can your code draw angled lines or an oval?  Wink  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.

Also, thanks for the link, looks quite useful!
Offline Several Kilo-Bytes

Senior Duke


Medals: 11



« Reply #55 - Posted 2013-08-17 20:18:28 »

Was still much faster than equivalent J2D operations. I'll see if I can find it and give it a reboot.

How much of the Graphics2D class did it support?
Offline BurntPizza
« Reply #56 - Posted 2013-08-17 20:24:12 »

Was still much faster than equivalent J2D operations. I'll see if I can find it and give it a reboot.

How much of the Graphics2D class did it support?

drawLine() (any brush size)
drawCircle() (filled or not)
drawRect() (filled or not)
drawPixel() (don't have to explain)

That's all I remember, only main thing I remember was missing was drawOval()
Offline Jeremy
« Reply #57 - Posted 2013-08-17 21:48:19 »

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.

JevaEngine, Latest Playthrough (This demo is networked with a centralized server model)

http://www.youtube.com/watch?v=rWA8bajpVXg
Offline nsigma
« Reply #58 - Posted 2013-08-17 22:00:00 »

@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.

Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
Offline BurntPizza
« Reply #59 - Posted 2013-08-17 22:16:41 »

@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:

1  
2  
3  
4  
5  
6  
Rendering Test: 200 frames...
Using VolatileImage for drawLine() test, BufferedImage for others:
Time for drawLine(): 10.58 s
Time for setRGB(): 2.65 s
Time for int[]: 1.54 s
And for fun, time for byte[]: 1.44 s


VolatileImage created with
GraphicsConfiguration.createCompatibleVolatileImage(w, h, new ImageCapabilities(true))
Pages: 1 [2] 3
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Longarmx (38 views)
2014-10-17 03:59:02

Norakomi (29 views)
2014-10-16 15:22:06

Norakomi (24 views)
2014-10-16 15:20:20

lcass (28 views)
2014-10-15 16:18:58

TehJavaDev (56 views)
2014-10-14 00:39:48

TehJavaDev (55 views)
2014-10-14 00:35:47

TehJavaDev (46 views)
2014-10-14 00:32:37

BurntPizza (64 views)
2014-10-11 23:24:42

BurntPizza (36 views)
2014-10-11 23:10:45

BurntPizza (78 views)
2014-10-11 22:30:10
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
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
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!