From 0a6e191eaebcc8edc2611dbedab6fd04a615fc2f Mon Sep 17 00:00:00 2001
From: Kenneth Russel
+
+
+
+Jogl is a Java programming language binding for the OpenGL 3D graphics
+API. It supports integration with the Java platform's AWT and Swing
+widget sets while providing a minimal and easy-to-use API that handles
+many of the issues associated with building multithreaded OpenGL
+applications. Jogl provides access to the latest OpenGL routines
+(OpenGL 1.4 with vendor extensions) as well as platform-independent
+access to hardware-accelerated offscreen rendering ("pbuffers"). Jogl
+also provides some of the most popular features introduced by other
+Java bindings for OpenGL like GL4Java, LWJGL and Magician, including a
+composable pipeline model which can provide faster debugging for
+Java-based OpenGL applications than the analogous C program.
+
+
+
+Jogl was designed for the most recent version of the Java platform and
+for this reason supports only J2SE 1.4 and later. It also only
+supports truecolor (15 bits per pixel and higher) rendering; it does
+not support color-indexed modes. Certain areas of the public APIs are
+more restrictive than in other bindings; for example, the GLCanvas and
+GLJPanel classes are final, unlike in GL4Java, and the GLContext class
+is no longer exposed in the public API. These changes have been made
+to keep the public API simple and because most of the programming
+errors that have been seen with earlier Java/OpenGL interfaces, in
+particular GL4Java, have been related to subclassing the OpenGL widget
+classes and performing manual OpenGL context management. Several
+complex and leading-edge OpenGL demonstrations have been successfully
+ported from C/C++ to Jogl without needing direct access to any of
+these APIs. However, all of these classes and concepts are accessible
+at the Java programming language level in implementation packages, and
+in fact the Jogl binding is itself written almost completely in the
+Java programming language. There are only about fifty lines of
+handwritten C code in the entire Jogl source base; the rest of the
+native code is autogenerated during the build process by a new tool
+called GlueGen, the source code of which is in the Jogl source
+tree. Documentation for GlueGen is forthcoming.
+
+
+
+Jogl provides two basic widgets into which OpenGL rendering can be
+performed. The GLCanvas is a heavyweight AWT widget which supports
+hardware acceleration and which is intended to be the primary widget
+used by applications. The GLJPanel is a fully Swing-compatible
+lightweight widget which currently does not support hardware
+acceleration but which is intended to provide 100% correct Swing
+integration in the rare circumstances where a GLCanvas can not be
+used. See this
+article on The
+Swing Connection for more information about mixing lightweight and
+heavyweight widgets.
+
+
+
+Both the GLCanvas and GLJPanel implement a common interface called
+GLDrawable so applications can switch between them with minimal code
+changes. The GLDrawable interface provides
+
+Jogl - User's Guide
+
+
+
+
+
+
+
+
+ Overview
+
+ Creating a GLDrawable
+
+
+
+
+
+display()
method for forcing OpenGL rendering to
+ be performed
+
+ setRenderingThread()
,
+ setNoAutoRedrawMode()
) for controlling the
+ multithreading behavior of the widget
+
+
+ +GLCanvas and GLJPanel instances are created using the factory methods +in GLDrawableFactory. These factory methods allow the user to request +a certain set of OpenGL parameters in the form of a GLCapabilities +object as well as optionally customize the format selection algorithm +by specifying a GLCapabilitiesChooser. + +
++ +A GLCapabilities object specifies the OpenGL parameters for a +newly-created widget, such as the color, alpha,, z-buffer and +accumulation buffer bit depths and whether the widget is +double-buffered. The default capabilities are loosely specified but +provide for truecolor RGB, a reasonably large depth buffer, +double-buffered, with no alpha, stencil, or accumulation buffers. + +
++ +An application can override the default pixel format selection +algorithm by providing a GLCapabilitiesChooser to the +GLDrawableFactory. The chooseCapabilities method will be called with +all of the available pixel formats as an array of GLCapabilities +objects; it should return an integer index into this array. The +DefaultGLCapabilitiesChooser attempts to provide a better +cross-platform selection algorithm than the WGL and GLX pixel format +selection algorithms. + +
+ ++ +Applications implement the GLEventListener interface to perform OpenGL +drawing. When the methods of the GLEventListener are called, the +underlying OpenGL context associated with the drawable is already +current. The listener fetches the GL object out of the GLDrawable and +begins to perform rendering. + +
+
+
+The init()
method is called once, upon context
+creation. (Hooks for context destruction, and support for context
+recreation, are not yet implemented.) The display()
+method is called to perform per-frame rendering. The
+reshape()
method is called when the drawable has been
+resized; the default implementation automatically resizes the OpenGL
+viewport so often it is not necessary to do any work in this method.
+The displayChanged()
method is designed to allow
+applications to support on-the-fly screen mode switching, but support
+for this is not yet implemented so the body of this method should
+remain empty.
+
+
+
+It is strongly recommended that applications always refetch the GL and
+GLU objects out of the GLDrawable upon each call to the
+init()
, display()
and reshape()
+methods and pass the GL object down on the stack to any drawing
+routines, as opposed to storing the GL in a field and referencing it
+from there. The reason is that multithreading issues inherent to the
+AWT toolkit make it difficult to reason about which threads certain
+operations are occurring on, and if the GL object is stored in a field
+it is unfortunately too easy to accidentally make OpenGL calls from a
+thread that does not have a current context. This will usually cause
+the application to crash. For more information please see the section
+on multithreading.
+
+
+
+Jogl supports the "composable pipeline" paradigm introduced by the
+Magician Java binding for OpenGL. The DebugGL pipeline calls
+glGetError
after each OpenGL call, reporting any errors
+found. It can greatly speed up development time because of its
+fine-grained error checking as opposed to the manual error checking
+usually required in OpenGL programs written in C. The TraceGL prints
+logging information upon each OpenGL call and is helpful when an
+application crash makes it difficult to see where the error occurred.
+
+
+
+To use these pipelines, call GLDrawable.setGL
at the
+beginning of the init
method in your GLEventListener. For
+example,
+
+
+class MyListener implements GLEventListener { + public void init(GLDrawable drawable) { + drawable.setGL(new DebugGL(drawable.getGL())); + // ... + } + + // ... +} ++ + + +
+ +Jogl was designed to interoperate with the AWT, an inherently +multithreaded GUI toolkit. OpenGL, in contrast, was originally +designed in single-threaded C programming environments. For this +reason Jogl provides a framework in which it is possible to write +correct multithreaded OpenGL applications using the GLEventListener +paradigm. + +
++ +If an application written using Jogl interacts in any way with the +mouse or keyboard, the AWT is processing these events and the +multithreaded aspects of the program must be considered. + +
+
+
+OpenGL applications usually behave in one of two ways: either they
+repaint only on demand, for example when mouse input comes in, or they
+repaint continually, regardless of whether user input is coming in. In
+the repaint-on-demand model, the application can merely call
+GLDrawable.display()
manually at the end of the mouse or
+keyboard listener to cause repainting to be done. Alternatively if the
+application knows the concrete type of the GLDrawable it can call
+repaint() to have the painting scheduled for a later time.
+
+
+
+In the continuous repaint model, the application typically has a main
+loop which is calling GLDrawable.display()
repeatedly, or
+is using the Animator class, which does this internally. In both of
+these cases the OpenGL rendering will be done on this thread rather
+than the internal AWT event queue thread which dispatches mouse and
+keyboard events.
+
+
+
+Both of these models (repaint-on-demand and repaint continually) still
+require the user to think about which thread keyboard and mouse events
+are coming in on, and which thread is performing the OpenGL rendering.
+OpenGL rendering may not occur directly inside the mouse or
+keyboard handlers, because the OpenGL context for the drawable is not
+current at this point (hence the warning about storing a GL object in
+a field, where it can be fetched and accidentally used by another
+thread). However, a mouse or keyboard listener may invoke
+GLDrawable.display()
.
+
+
+
+It is generally recommended that applications perform as little work
+as possible inside their mouse and keyboard handlers to keep the GUI
+responsive. However, since OpenGL commands can not be run from
+directly within the mouse or keyboard event listener, the best
+practice is to store off state when the listener is entered and
+retrieve this state during the next call to
+GLEventListener.display()
.
+
+
+
+Furthermore, it is recommended that if there are long computational
+sequences in the GLEventListener's display
method which
+reference variables which may be being simultaneously modified by the
+AWT thread (mouse and keyboard listeners) that copies of these
+variables be made upon entry to display
and these copies
+be referenced throughout display() and the methods it calls. This will
+prevent the values from changing while the OpenGL rendering is being
+performed. Errors of this kind show up in many ways, including certain
+kinds of flickering of the rendered image as certain pieces of objects
+are rendered in one place and other pieces are rendered elsewhere in
+the scene. Restructuring the display() method as described has solved
+all instances of this kind of error that have been seen with Jogl to
+date.
+
+
+ +In addition to correctness issues, there are also performance issues +to consider with multithreaded OpenGL applications. The OpenGL context +associated with a particular drawable can only be current on one +thread at a time. If multiple threads may be making the context +current then this implies that the context must be made current and +freed during each render; the overhead of these context operations may +be significant depending on the application. For this reason Jogl has +a built-in mechanism for optimizing the OpenGL context handling to the +efficiency of an analogous C application. + +
+
+
+GLDrawable.setRenderingThread
informs the Jogl library
+that rendering to a particular drawable will only occur from the
+specified thread. The intent is that the OpenGL context can be made
+current and remain current on that thread until
+setRenderingThread(null) is called. Unfortunately, due to
+quality-of-implementation bugs in the X11 JAWT, this optimization had
+to be made advisory; in other words, it was not possible to guarantee
+that setRenderingThread would yield any faster OpenGL context handling
+on these platforms.
+
+
+
+In some situations, typically when an application is using pbuffers to
+compute intermediate results, it is required that automatic redraws be
+suspended for a particular drawable so that the application can
+completely control when and where the display() method is called. For
+this reason the GLDrawable.setNoAutoRedrawMode()
method
+was added; it is used not only by the Jogl implementation but also by
+utility libraries such as gleem (included in the jogl-demos
+distribution). We consider it unfortunate that it was necessary to
+expose two APIs to express basically the same idea and hope that if
+the JAWT implementation in the 1.5 platform has better locking
+behavior that GLDrawable.setNoAutoRedrawMode()
may be
+able to be removed.
+
+
+ +Jogl exposes hardware-accelerated offscreen rendering (pbuffers) with +a minimal and platform-agnostic API. Several recent demos have been +successfully ported from C/C++ to Java using Jogl's pbuffer APIs. +However, the pbuffer support in Jogl remains one of the more +experimental aspects of the package and the APIs may need to change in +the future. + +
+
+
+To create a pbuffer, create a GLCanvas and (assuming it reports that
+it can create an offscreen drawable) make a pbuffer using the
+createOffscreenDrawable
API. Because of the multithreaded
+nature of the AWT, the pbuffer is actually created lazily. For this
+reason the application's main loop typically needs to detect when the
+init() methods of all of the GLEventListeners for all of the offscreen
+surfaces have been called. See the demonstrations such as the
+ProceduralTexturePhysics demo for an example of this.
+
+
+ +Additionally, pbuffers are only created when the parent GLCanvas's +display(), init(), or reshape() methods are called; in other words, it +may be necessary to manually "prime" the GLCanvas by calling display() +on it until it creates all of its requested pbuffers. Again, please +see the demonstrations for concrete examples of this. We hope that it +may be possible to hide many of these details in the future. + +
++ +A pbuffer is used by calling its display() method. Rendering, as +always, occurs while the pbuffer's OpenGL context is current. There +are render-to-texture options that can be specified in the +GLCapabilities for the pbuffer which can make it easier to operate +upon the resulting pixels. These APIs are however extremely +experimental and not yet implemented on all platforms. + +
+ ++ +The following issues, among others, are outstanding on all platforms: + +
+ ++ +No outstanding issues at this time. + +
+ ++ +The Mac OS X port of Jogl, in particular the GL interface and its +implementation, can be used either with the provided GLCanvas widget +or with the Cocoa NSOpenGLView. In order to use it with Cocoa the +following steps should be taken: + +
net.java.games.jogl.impl.macosx.MacOSXGLImpl
using the
+public constructor taking no arguments.
+
+MacOSXGLImpl.resetGLFunctionAvailability()
.
+
++ +The following issues remain with the Mac OS X port: + +