297chrisc / playn

Automatically exported from code.google.com/p/playn
0 stars 0 forks source link

Java backend immediate drawing is incredibly slow #228

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Painting something like the Box2D debug view in an immediate manner will cause 
the Java backend drawing to become incredibly slow.

This is caused by playn.java.JavaGLContext#convertImageData (see the TODO 
comment in sources), which converts the BufferedImage used internally to the 
GL_RGBA color space and constructs a texture from it on every drawing 
iteration. For an 1024x768 sized image it takes about 100ms for a single 
drawing operation (profiled with netbeans, high end hardware, win 64bit). Thus, 
running at about 10 fps. This makes it quite difficult to debug the application 
using the Java backend.

There might be these solutions:
1. Implement INT_ARGB data buffers to be used on the lwjgl side. Unsure.
2. Use a BYTE_RGBA buffer right inside playn (maybe some lwjgl canvas to render 
immediate drawing directly to video memory instead of binding textures).
3. Implement playn.core.DebugDrawBox2D inside the gwtbox2d package using 
layers, but this would not solve the root problem regarding immediate drawing.

Actually, I guess the BufferedImage implementation is something left from the 
previous Java2D API just because it makes it easy to draw arcs etc. even if it 
does not play well with lwjgl. In an ideal world (of playn), this should be 
replaced with something lwjgl (Slick2D?) imho.

Original issue reported on code.google.com by dc...@dcode.io on 31 Jan 2013 at 1:43

GoogleCodeExporter commented 9 years ago
The image is only converted to the appropriate format for texture upload when 
it changes. Are you saying this debug view changes the images on every frame?

Original comment by m...@samskivert.com on 31 Jan 2013 at 6:02

GoogleCodeExporter commented 9 years ago
Yes, the debug view draws edges, shapes, bounding boxes, joints and stuff like 
that to a canvas image to display what's going on within the physics engine.

Example: http://gwtbox2d.appspot.com/ (all using DebugView)

So yes, the canvas' contents changes on every frame when using it. It does not 
matter how many of those operations are required, just "that" (for the Java 
backend) because of the conversion step. This is fine for the GWT backend for 
example (I assume also for Android etc.) since it draws directly to a 
compatible image (hence not conversion) but not for the Java backend as it has 
to convert the incompatible BufferedImage data to build a GL texture on every 
frame.

Unfortunately, this does not happen with the Box2D debug view only, but with 
pretty much every immediate drawing operation like when using ImmediateLayers 
or doing something inside of Game#paint (e.g. rendering some effects on the 
fly).

Finally the problem comes down to the use of INT_ARGB internally 
(BufferedImage) against BYTE_RGBA (lwjgl), which is an unusual thing for the 
Java backend, afaik, since it does no longer use Java2D for which 
BufferedImages are meant for.

Original comment by dc...@dcode.io on 31 Jan 2013 at 6:48

GoogleCodeExporter commented 9 years ago
If you render into a Canvas, you're using Java2D. There's no avoiding that.

We may be able to tell Java to use a raster format that is compatible with 
LWJGL which will speed things up a little bit, but rendering to a 2D image 
using the CPU and then uploading that image to the GPU every frame will never 
be super high performance.

That said, we should be able to at least make it as fast as the HTML backend. 
I'll look into it.

Original comment by m...@samskivert.com on 31 Jan 2013 at 6:52

GoogleCodeExporter commented 9 years ago
If you render into a Canvas, you're using Java2D. There's no avoiding that.

We may be able to tell Java to use a raster format that is compatible with 
LWJGL which will speed things up a little bit, but rendering to a 2D image 
using the CPU and then uploading that image to the GPU every frame will never 
be super high performance.

That said, we should be able to at least make it as fast as the HTML backend. 
I'll look into it.

Original comment by m...@samskivert.com on 31 Jan 2013 at 6:52

GoogleCodeExporter commented 9 years ago
I am not sure that this will be possible while still using Java2D for canvas 
rendering. Currently Java2D and LWJGL are mixed somehow in PlayN, so it's 
actually not even a real LWJGL backend. The ideal option would be to stop using 
Java2D for the one and LWJGL for the other task and implement canvas solely on 
top of LWJGL.

This is how Slick2D does it:

https://bitbucket.org/kevglass/slick/src/c0e4b96798d1c5b1969a26cb62eb7489d701ca6
f/trunk/Slick/src/org/newdawn/slick/Graphics.java?at=default

https://bitbucket.org/kevglass/slick/src/c0e4b96798d1c5b1969a26cb62eb7489d701ca6
f/trunk/Slick/src/org/newdawn/slick/geom/ShapeRenderer.java?at=default

This way around the Java backend would also become production-quality for those 
who'd like to publish a game on desktop also. Currently it's just the small 
amount of textures and/or not drawing anything in an immediate manner in most 
games that make it "somehow" work with the Java backend. It's quite a hack. As 
soon as there are more textures or any immediate painting, using a mixture of 
those two technologies will always cause the Java backend to fail.

Original comment by dc...@dcode.io on 31 Jan 2013 at 7:16

GoogleCodeExporter commented 9 years ago

Original comment by m...@samskivert.com on 31 Jan 2013 at 7:26