summaryrefslogtreecommitdiffstats
path: root/src/demos/xtrans/XTDesktopManager.java
diff options
context:
space:
mode:
authorKenneth Russel <[email protected]>2005-10-12 01:30:31 +0000
committerKenneth Russel <[email protected]>2005-10-12 01:30:31 +0000
commit82388fe004e7bc86100ad45377e69f771b45c977 (patch)
treef7d866cea1caca1f66a67ffc47f5b44b58ed3fdd /src/demos/xtrans/XTDesktopManager.java
parent55370bacd5640ea9be8f6c137ec03a76c6572651 (diff)
Added XTrans (Accelerated Transitions) demo, which uses the
Java2D/JOGL bridge in a completely different way than the GLJPanel. The OffscreenDesktopPane and associated classes are an attempt at a generalized mechanism for supporting off-screen rendering of Swing components within a JDesktopPane and later composition (by subclasses) of those components' contents on-screen. The XTDesktopPane is intended to be a drop-in replacement for the JDesktopPane which supports OpenGL-accelerated animated transitions for components added to and removed from it. The XTBasicTransitionManager and XTBasicTransition classes define the default implementation of animated transition effects, supporting a combination of fade, rotation and scroll effects. More, and arbitrary, transitions are certainly possible. More experimentation by the community is needed. This demo is intended as a first step toward a more generalized framework in which arbitrary Swing rendering can be performed via the Java2D/JOGL bridge. Bugs remain, such as needing to preserve portions of the OffscreenDesktopManager's back buffer after components have been made not visible (during the process of closing them) in order to properly animate their close effects. The XTrans demo works properly in most cases but the JRefract demo (which now accepts an -xt command line argument to install an XTDesktopPane instead of a JDesktopPane) does not. More work also remains to be done, in particular on the layout of components on the back buffer. A 2D bin-packing algorithm is needed. When the Java2D/JOGL bridge supports Java2D's use of the Frame Buffer Object extension (and, implicitly, render-to-texture on all platforms) the glCopyTexSubImage2D operation to copy the off-screen back buffer to a VolatileImage can disappear; this is the principal expensive operation when the contents change of components which have been added to the OffscreenDesktopPane. git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/../svn-server-sync/jogl-demos/branches/JSR-231@140 3298f667-5e0e-4b4a-8ed4-a3559d26a5f4
Diffstat (limited to 'src/demos/xtrans/XTDesktopManager.java')
-rwxr-xr-xsrc/demos/xtrans/XTDesktopManager.java166
1 files changed, 166 insertions, 0 deletions
diff --git a/src/demos/xtrans/XTDesktopManager.java b/src/demos/xtrans/XTDesktopManager.java
new file mode 100755
index 0000000..4b911ee
--- /dev/null
+++ b/src/demos/xtrans/XTDesktopManager.java
@@ -0,0 +1,166 @@
+package demos.xtrans;
+
+import java.awt.*;
+import java.awt.geom.*;
+import java.awt.image.*;
+import java.beans.*;
+import java.nio.*;
+import java.util.*;
+import javax.swing.*;
+import javax.media.opengl.*;
+import javax.media.opengl.glu.*;
+import com.sun.opengl.impl.*;
+
+import com.sun.opengl.impl.windows.*;
+
+/** A desktop manager implementation supporting accelerated
+ transitions of the components on the desktop via OpenGL. This
+ class does not need to be instantiated by end users; it is
+ installed automatically when an XTDesktopPane is constructed. */
+public class XTDesktopManager extends OffscreenDesktopManager {
+ private GLContext j2dContext;
+ private Object j2dContextSurfaceIdentifier;
+ private int oglTextureId;
+ private int prevBackBufferWidth;
+ private int prevBackBufferHeight;
+
+ private int textureTarget = GL.GL_TEXTURE_2D;
+
+ /** Returns the OpenGL texture object ID associated with the
+ off-screen back buffer for all of the components on the
+ desktop. */
+ public int getOpenGLTextureObject() {
+ return oglTextureId;
+ }
+
+ /** Returns a rectangle specifying the OpenGL texture coordinates of
+ the passed component in the texture object. The x and y
+ coordinates of the returned rectangle specify the lower left
+ corner of the component's image. */
+ public Rectangle2D getOpenGLTextureCoords(Component c) {
+ Rectangle rect = getBoundsOnBackBuffer(c);
+ if (rect == null) {
+ throw new RuntimeException("Unknown component " + c);
+ }
+ double offscreenWidth = getOffscreenBackBufferWidth();
+ double offscreenHeight = getOffscreenBackBufferHeight();
+ return new Rectangle2D.Double(rect.x / offscreenWidth,
+ (offscreenHeight - rect.y - rect.height) / offscreenHeight,
+ rect.width / offscreenWidth,
+ rect.height / offscreenHeight);
+ }
+
+ /** Updates the off-screen buffer of this desktop manager and makes
+ the rendering results available to OpenGL in the form of a
+ texture object. */
+ public void updateOffscreenBuffer(OffscreenDesktopPane parent) {
+ boolean needsCopy = needsCopyBack();
+ boolean hadPrevBackBuffer = false;
+ super.updateOffscreenBuffer(parent);
+ Image img = getOffscreenBackBuffer();
+ final boolean mustResizeOGLTexture = ((oglTextureId == 0) ||
+ (img == null) ||
+ (prevBackBufferWidth != img.getWidth(null)) ||
+ (prevBackBufferHeight != img.getHeight(null)));
+ if (needsCopy) {
+ final Graphics g = getOffscreenGraphics();
+ // Capture off-screen buffer contents into OpenGL texture
+ Java2D.invokeWithOGLContextCurrent(g, new Runnable() {
+ public void run() {
+ // Get valid Java2D context
+ if (j2dContext == null ||
+ j2dContextSurfaceIdentifier != Java2D.getOGLSurfaceIdentifier(g)) {
+ j2dContext = GLDrawableFactory.getFactory().createExternalGLContext();
+ j2dContext.setGL(new DebugGL(j2dContext.getGL()));
+ j2dContextSurfaceIdentifier = Java2D.getOGLSurfaceIdentifier(g);
+ }
+
+ j2dContext.makeCurrent(); // No-op
+ try {
+ GL gl = j2dContext.getGL();
+
+ if (oglTextureId == 0) {
+ // Set up and initialize texture
+ int[] tmp = new int[1];
+
+ gl.glGenTextures(1, tmp, 0);
+ oglTextureId = tmp[0];
+ if (oglTextureId == 0) {
+ throw new RuntimeException("Error generating OpenGL back buffer texture");
+ }
+ assert mustResizeOGLTexture : "Must know we need to resize";
+ }
+
+ gl.glBindTexture(textureTarget, oglTextureId);
+
+ int offscreenWidth = getOffscreenBackBufferWidth();
+ int offscreenHeight = getOffscreenBackBufferHeight();
+
+ if (mustResizeOGLTexture) {
+ prevBackBufferWidth = offscreenWidth;
+ prevBackBufferHeight = offscreenHeight;
+
+ gl.glTexImage2D(textureTarget,
+ 0,
+ GL.GL_RGBA8,
+ offscreenWidth,
+ offscreenHeight,
+ 0,
+ GL.GL_RGBA,
+ GL.GL_UNSIGNED_BYTE,
+ null);
+ }
+
+ // Copy texture from offscreen buffer
+ // NOTE: assumes read buffer is set up
+ // FIXME: could be more efficient by copying only bounding rectangle
+
+ gl.glPixelStorei(GL.GL_UNPACK_SWAP_BYTES, GL.GL_FALSE);
+ gl.glPixelStorei(GL.GL_PACK_SWAP_BYTES, GL.GL_FALSE);
+ gl.glPixelStorei(GL.GL_UNPACK_LSB_FIRST, GL.GL_FALSE);
+ gl.glPixelStorei(GL.GL_PACK_LSB_FIRST, GL.GL_FALSE);
+ gl.glPixelStorei(GL.GL_UNPACK_ROW_LENGTH, 0);
+ gl.glPixelStorei(GL.GL_PACK_ROW_LENGTH, 0);
+ gl.glPixelStorei(GL.GL_UNPACK_SKIP_ROWS, 0);
+ gl.glPixelStorei(GL.GL_PACK_SKIP_ROWS, 0);
+ gl.glPixelStorei(GL.GL_UNPACK_SKIP_PIXELS, 0);
+ gl.glPixelStorei(GL.GL_PACK_SKIP_PIXELS, 0);
+ gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1);
+ gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1);
+ gl.glPixelTransferf(GL.GL_RED_SCALE, 1);
+ gl.glPixelTransferf(GL.GL_GREEN_SCALE, 1);
+ gl.glPixelTransferf(GL.GL_BLUE_SCALE, 1);
+ gl.glPixelTransferf(GL.GL_ALPHA_SCALE, 1);
+ gl.glPixelTransferf(GL.GL_RED_BIAS, 0);
+ gl.glPixelTransferf(GL.GL_GREEN_BIAS, 0);
+ gl.glPixelTransferf(GL.GL_BLUE_BIAS, 0);
+ gl.glPixelTransferf(GL.GL_ALPHA_BIAS, 0);
+
+ // long start = System.currentTimeMillis();
+ gl.glCopyTexSubImage2D(textureTarget,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ offscreenWidth,
+ offscreenHeight);
+ // long end = System.currentTimeMillis();
+ // System.err.println("glCopyTexSubImage2D " + offscreenWidth + "x" + offscreenHeight + " took " + (end - start) + " ms");
+
+ } finally {
+ j2dContext.release();
+ }
+ }
+ });
+ }
+ }
+
+ // Ideally we would force a repaint only of the 2D bounds of the 3D
+ // component projected onto the desktop. However for expedience
+ // we'll currently just repaint the entire desktop to get correct
+ // results.
+ protected void repaintPortionOfDesktop(JDesktopPane desktop, Component comp) {
+ desktop.repaint();
+ }
+}