diff options
Diffstat (limited to 'src/demos/xtrans/XTDesktopManager.java')
-rwxr-xr-x | src/demos/xtrans/XTDesktopManager.java | 214 |
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(); + } +} |