JDK-6219284 : OGL: render on a single thread for improved reliability and performance
  • Type: Enhancement
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 5.0
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic,solaris_9
  • CPU: generic
  • Submitted: 2005-01-20
  • Updated: 2008-02-06
  • Resolved: 2005-03-07
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availabitlity Release.

To download the current JDK release, click here.
6 betaFixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
The OGL-based pipeline added in 5.0 is not as reliable as it could be.  A
typical (native) OpenGL app has one and only one rendering thread, so all
OGL commands are issued on that single thread.  The OGL-based Java 2D pipeline
doesn't have it so easy because rendering requests can come from any number of
threads (the EDT, a user thread, etc) even though we try to teach developers
to avoid doing heavy rendering to hardware surfaces from many threads.  It is
possible to write an OpenGL app that renders from multiple threads, but you
have to take many precautions to make that app reasonably robust, such as:
  - ensure only one thread is calling OGL methods at any given time
  - use FBConfigs and contexts only from the thread on which they were created

We went through great lengths in 5.0 to adhere to these restrictions, but in
the end we can only be as robust as the OGL drivers underneath us, and in
many cases those drivers are not very reliable when many rendering threads
are in use at the same time.  There is also a performance issue here because
for any given rendering operation, we need to first fetch the appropriate
context from thread-local storage (this is usually pretty fast, but it would
be nice if we could avoid it altogether).

We could make the OGL pipeline much more reliable if we played nice like
those typical native apps that only render from one thread.  One solution
would involve enqueuing rendering operations (or any operation that talks
to OpenGL) on a buffer, and then having a single separate thread that is only
responsible for flushing that buffer periodically.  This would allow any
number of Java-level threads to issue rendering requests, but in the end only
the single queue flushing thread would be calling OpenGL methods.
###@###.### 2005-1-20 00:16:06 GMT

EVALUATION The implementation of this feature has been in progress for a couple months now and is nearly complete. Rendering operations are enqueued by adding opcode tokens and parameters to a NIO ByteBuffer, and then a separate daemon thread processes the operations on that buffer on a periodic basis. In addition to simplifying the code in a number of places and making things more robust overall, this has actually had an impressive (positive) impact on runtime performance when the OGL pipeline is enabled. This is mostly due to the fact that we no longer have to go down through JNI for every single rendering operation. Instead, a number of operations are essentially batched up on the ByteBuffer, and then we only take the JNI hit once we flush the buffer. (JNI downcalls account for a significant part of the overhead of the OGL pipeline.) I'll save the detailed performance numbers for another day, but here are some quick numbers (these are from microbenchmarks, so take with a grain of salt): - SwingMark is ~16% faster on Linux - drawString() is ~250% faster (according to J2DBench2) - fillRect() and drawLine() are up to 2500% faster (according to J2DBench2) - with the FireStarter demo, we can render about 2500 transformed/blended rocks at 30 fps (as opposed to only 1600 rocks before STR) ###@###.### 2005-1-20 01:02:58 GMT