summaryrefslogtreecommitdiffstats
path: root/src/demos/xtrans/XTDesktopManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/demos/xtrans/XTDesktopManager.java')
-rwxr-xr-xsrc/demos/xtrans/XTDesktopManager.java214
1 files changed, 214 insertions, 0 deletions
diff --git a/src/demos/xtrans/XTDesktopManager.java b/src/demos/xtrans/XTDesktopManager.java
new file mode 100755
index 0000000..0081b5c
--- /dev/null
+++ b/src/demos/xtrans/XTDesktopManager.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package demos.xtrans;
+
+import com.sun.opengl.impl.awt.Java2D;
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Rectangle;
+import java.awt.geom.Rectangle2D;
+import javax.media.opengl.DebugGL2;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES1;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLProfile;
+import javax.swing.JDesktopPane;
+
+
+/** 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.
+ *
+ * @author Kenneth Russell
+ */
+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)) {
+ GLProfile glp = GLProfile.getDefault();
+ j2dContext = GLDrawableFactory.getFactory(glp).createExternalGLContext();
+ j2dContext.setGL(new DebugGL2(j2dContext.getGL().getGL2()));
+ j2dContextSurfaceIdentifier = Java2D.getOGLSurfaceIdentifier(g);
+ }
+
+ j2dContext.makeCurrent(); // No-op
+ try {
+ GL2 gl = j2dContext.getGL().getGL2();
+
+ 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(GL2.GL_UNPACK_SWAP_BYTES, GL.GL_FALSE);
+ gl.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, GL.GL_FALSE);
+ gl.glPixelStorei(GL2.GL_UNPACK_LSB_FIRST, GL.GL_FALSE);
+ gl.glPixelStorei(GL2.GL_PACK_LSB_FIRST, GL.GL_FALSE);
+ gl.glPixelStorei(GL2.GL_UNPACK_ROW_LENGTH, 0);
+ gl.glPixelStorei(GL2.GL_PACK_ROW_LENGTH, 0);
+ gl.glPixelStorei(GL2.GL_UNPACK_SKIP_ROWS, 0);
+ gl.glPixelStorei(GL2.GL_PACK_SKIP_ROWS, 0);
+ gl.glPixelStorei(GL2.GL_UNPACK_SKIP_PIXELS, 0);
+ gl.glPixelStorei(GL2.GL_PACK_SKIP_PIXELS, 0);
+ gl.glPixelStorei(GL2.GL_UNPACK_ALIGNMENT, 1);
+ gl.glPixelStorei(GL2.GL_PACK_ALIGNMENT, 1);
+ gl.glPixelTransferf(GL2.GL_RED_SCALE, 1);
+ gl.glPixelTransferf(GL2.GL_GREEN_SCALE, 1);
+ gl.glPixelTransferf(GL2.GL_BLUE_SCALE, 1);
+ gl.glPixelTransferf(GL2.GL_ALPHA_SCALE, 1);
+ gl.glPixelTransferf(GL2.GL_RED_BIAS, 0);
+ gl.glPixelTransferf(GL2.GL_GREEN_BIAS, 0);
+ gl.glPixelTransferf(GL2.GL_BLUE_BIAS, 0);
+ gl.glPixelTransferf(GL2.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();
+ }
+}