diff options
Diffstat (limited to 'src/classes/com/sun/opengl/impl/x11')
12 files changed, 2226 insertions, 0 deletions
diff --git a/src/classes/com/sun/opengl/impl/x11/X11ExternalGLContext.java b/src/classes/com/sun/opengl/impl/x11/X11ExternalGLContext.java new file mode 100755 index 000000000..4d329ba24 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/x11/X11ExternalGLContext.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2003 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 com.sun.opengl.impl.x11; + +import javax.media.opengl.*; +import com.sun.opengl.impl.*; + +public class X11ExternalGLContext extends X11GLContext { + private boolean firstMakeCurrent = true; + private boolean created = true; + + public X11ExternalGLContext() { + super(null, null); + lockAWT(); + try { + context = GLX.glXGetCurrentContext(); + } finally { + unlockAWT(); + } + GLContextShareSet.contextCreated(this); + resetGLFunctionAvailability(); + } + + protected void create() { + } + + protected int makeCurrentImpl() throws GLException { + if (firstMakeCurrent) { + firstMakeCurrent = false; + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } + + protected void releaseImpl() throws GLException { + } + + protected void destroyImpl() throws GLException { + created = false; + GLContextShareSet.contextDestroyed(this); + } + + public boolean isCreated() { + return created; + } +} diff --git a/src/classes/com/sun/opengl/impl/x11/X11ExternalGLDrawable.java b/src/classes/com/sun/opengl/impl/x11/X11ExternalGLDrawable.java new file mode 100755 index 000000000..371930013 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/x11/X11ExternalGLDrawable.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2003 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 com.sun.opengl.impl.x11; + +import javax.media.opengl.*; +import com.sun.opengl.impl.*; + +public class X11ExternalGLDrawable extends X11GLDrawable { + private int fbConfigID; + private int renderType; + private int screen; + private long readDrawable; + + public X11ExternalGLDrawable() { + super(null, null, null); + lockAWT(); + try { + display = GLX.glXGetCurrentDisplay(); + drawable = GLX.glXGetCurrentDrawable(); + readDrawable = GLX.glXGetCurrentReadDrawable(); + + // Need GLXFBConfig ID in order to properly create new contexts + // on this drawable + long context = GLX.glXGetCurrentContext(); + int[] val = new int[1]; + GLX.glXQueryContext(display, context, GLX.GLX_FBCONFIG_ID, val, 0); + fbConfigID = val[0]; + renderType = GLX.GLX_RGBA_TYPE; + GLX.glXQueryContext(display, context, GLX.GLX_RENDER_TYPE, val, 0); + if ((val[0] & GLX.GLX_RGBA_BIT) == 0) { + if (DEBUG) { + System.err.println("X11ExternalGLDrawable: WARNING: forcing GLX_RGBA_TYPE for newly created contexts"); + } + } + GLX.glXQueryContext(display, context, GLX.GLX_SCREEN, val, 0); + screen = val[0]; + } finally { + unlockAWT(); + } + } + + public GLContext createContext(GLContext shareWith) { + return new Context(shareWith); + } + + public void setSize(int newWidth, int newHeight) { + throw new GLException("Should not call this"); + } + + public int getWidth() { + throw new GLException("Should not call this"); + } + + public int getHeight() { + throw new GLException("Should not call this"); + } + + public void destroy() { + } + + class Context extends X11GLContext { + Context(GLContext shareWith) { + super(X11ExternalGLDrawable.this, shareWith); + this.drawable = drawable; + } + + protected int makeCurrentImpl() throws GLException { + if (drawable.getDrawable() == 0) { + // parent drawable not properly initialized + // FIXME: signal error? + if (DEBUG) { + System.err.println("parent drawable not properly initialized"); + } + return CONTEXT_NOT_CURRENT; + } + + // Note that we have to completely override makeCurrentImpl + // because the underlying makeCurrent call differs from the norm + lockAWT(); + try { + boolean created = false; + if (context == 0) { + create(); + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Created GL context for " + getClass().getName()); + } + created = true; + } + + if (!GLX.glXMakeContextCurrent(drawable.getDisplay(), + drawable.getDrawable(), + readDrawable, + context)) { + throw new GLException("Error making context current"); + } else { + mostRecentDisplay = drawable.getDisplay(); + if (DEBUG && VERBOSE) { + System.err.println(getThreadName() + ": glXMakeCurrent(display " + toHexString(drawable.getDisplay()) + + ", drawable " + toHexString(drawable.getDrawable()) + + ", context " + toHexString(context) + ") succeeded"); + } + } + + if (created) { + resetGLFunctionAvailability(); + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } finally { + unlockAWT(); + } + } + + protected void releaseImpl() throws GLException { + lockAWT(); + try { + if (!GLX.glXMakeContextCurrent(drawable.getDisplay(), 0, 0, 0)) { + throw new GLException("Error freeing OpenGL context"); + } + } finally { + unlockAWT(); + } + } + + protected void create() { + // We already have the GLXFBConfig ID for the context. All we + // need to do is use it to choose the GLXFBConfig and then + // create a context with it. + int[] iattributes = new int[] { + GLX.GLX_FBCONFIG_ID, + fbConfigID, + 0, + 0 + }; + float[] fattributes = new float[0]; + int[] nelementsTmp = new int[1]; + GLXFBConfig[] fbConfigs = GLX.glXChooseFBConfig(display, screen, iattributes, 0, nelementsTmp, 0); + int nelements = nelementsTmp[0]; + if (nelements <= 0) { + throw new GLException("context creation error: couldn't find a suitable frame buffer configuration"); + } + if (nelements != 1) { + throw new GLException("context creation error: shouldn't get more than one GLXFBConfig"); + } + // Note that we currently don't allow selection of anything but + // the first GLXFBConfig in the returned list (there should be only one) + GLXFBConfig fbConfig = fbConfigs[0]; + // Create a gl context for the drawable + X11GLContext other = (X11GLContext) GLContextShareSet.getShareContext(this); + long share = 0; + if (other != null) { + share = other.getContext(); + if (share == 0) { + throw new GLException("GLContextShareSet returned an invalid OpenGL context"); + } + } + // FIXME: how to determine "direct" bit? + context = GLX.glXCreateNewContext(display, fbConfig, renderType, share, true); + if (context == 0) { + String detail = " display=" + toHexString(display) + + " fbconfig=" + fbConfig + + " fbconfigID=" + toHexString(fbConfigID) + + " renderType=" + toHexString(renderType) + + " share=" + toHexString(share); + throw new GLException("context creation error: glXCreateNewContext() failed: " + detail); + } + GLContextShareSet.contextCreated(this); + + if (DEBUG) { + System.err.println("Created context " + toHexString(context) + + " for GLXDrawable " + toHexString(drawable.getDrawable())); + } + } + } +} diff --git a/src/classes/com/sun/opengl/impl/x11/X11GLContext.java b/src/classes/com/sun/opengl/impl/x11/X11GLContext.java new file mode 100644 index 000000000..ed9736f22 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/x11/X11GLContext.java @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2003 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 com.sun.opengl.impl.x11; + +import java.nio.*; +import java.util.*; +import javax.media.opengl.*; +import com.sun.opengl.impl.*; + +public abstract class X11GLContext extends GLContextImpl { + protected X11GLDrawable drawable; + protected long context; + private boolean glXQueryExtensionsStringInitialized; + private boolean glXQueryExtensionsStringAvailable; + private static final Map/*<String, String>*/ functionNameMap; + private GLXExt glXExt; + // Table that holds the addresses of the native C-language entry points for + // GLX extension functions. + private GLXExtProcAddressTable glXExtProcAddressTable; + // Cache the most recent value of the "display" variable (which we + // only guarantee to be valid in between makeCurrent / free pairs) + // so that we can implement displayImpl() (which must be done when + // the context is not current) + protected long mostRecentDisplay; + + static { + functionNameMap = new HashMap(); + functionNameMap.put("glAllocateMemoryNV", "glXAllocateMemoryNV"); + functionNameMap.put("glFreeMemoryNV", "glXFreeMemoryNV"); + } + + public X11GLContext(X11GLDrawable drawable, + GLContext shareWith) { + super(shareWith); + this.drawable = drawable; + } + + public Object getPlatformGLExtensions() { + return getGLXExt(); + } + + public GLXExt getGLXExt() { + if (glXExt == null) { + glXExt = new GLXExtImpl(this); + } + return glXExt; + } + + public GLDrawable getGLDrawable() { + return drawable; + } + + protected String mapToRealGLFunctionName(String glFunctionName) { + String lookup = (String) functionNameMap.get(glFunctionName); + if (lookup != null) { + return lookup; + } + return glFunctionName; + } + + protected String mapToRealGLExtensionName(String glExtensionName) { + return glExtensionName; + } + + /** Helper routine which usually just turns around and calls + * createContext (except for pbuffers, which use a different context + * creation mechanism). Should only be called by {@link + * makeCurrentImpl()}. + */ + protected abstract void create(); + + /** + * Creates and initializes an appropriate OpenGL context. Should only be + * called by {@link create()}. + */ + protected void createContext(boolean onscreen) { + XVisualInfo vis = drawable.chooseVisual(onscreen); + X11GLContext other = (X11GLContext) GLContextShareSet.getShareContext(this); + long share = 0; + if (other != null) { + share = other.getContext(); + if (share == 0) { + throw new GLException("GLContextShareSet returned an invalid OpenGL context"); + } + } + context = GLX.glXCreateContext(drawable.getDisplay(), vis, share, onscreen); + if (context == 0) { + throw new GLException("Unable to create OpenGL context"); + } + GLContextShareSet.contextCreated(this); + } + + protected int makeCurrentImpl() throws GLException { + // FIXME: in offscreen (non-pbuffer) case this is run without the + // AWT lock held + boolean created = false; + if (context == 0) { + create(); + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Created GL context for " + getClass().getName()); + } + created = true; + } + + if (!GLX.glXMakeCurrent(drawable.getDisplay(), drawable.getDrawable(), context)) { + throw new GLException("Error making context current"); + } else { + mostRecentDisplay = drawable.getDisplay(); + if (DEBUG && VERBOSE) { + System.err.println(getThreadName() + ": glXMakeCurrent(display " + toHexString(drawable.getDisplay()) + + ", drawable " + toHexString(drawable.getDrawable()) + + ", context " + toHexString(context) + ") succeeded"); + } + } + + if (created) { + resetGLFunctionAvailability(); + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } + + protected void releaseImpl() throws GLException { + if (!GLX.glXMakeCurrent(drawable.getDisplay(), 0, 0)) { + throw new GLException("Error freeing OpenGL context"); + } + } + + protected void destroyImpl() throws GLException { + lockAWT(); + if (context != 0) { + GLX.glXDestroyContext(mostRecentDisplay, context); + if (DEBUG) { + System.err.println("!!! Destroyed OpenGL context " + context); + } + context = 0; + mostRecentDisplay = 0; + GLContextShareSet.contextDestroyed(this); + } + unlockAWT(); + } + + public boolean isCreated() { + return (context != 0); + } + + protected void resetGLFunctionAvailability() { + super.resetGLFunctionAvailability(); + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Initializing GLX extension address table"); + } + resetProcAddressTable(getGLXExtProcAddressTable()); + } + + public GLXExtProcAddressTable getGLXExtProcAddressTable() { + if (glXExtProcAddressTable == null) { + // FIXME: cache ProcAddressTables by capability bits so we can + // share them among contexts with the same capabilities + glXExtProcAddressTable = new GLXExtProcAddressTable(); + } + return glXExtProcAddressTable; + } + + public synchronized String getPlatformExtensionsString() { + if (drawable.getDisplay() == 0) { + throw new GLException("Context not current"); + } + if (!glXQueryExtensionsStringInitialized) { + glXQueryExtensionsStringAvailable = + (GLDrawableFactoryImpl.getFactoryImpl().dynamicLookupFunction("glXQueryExtensionsString") != 0); + glXQueryExtensionsStringInitialized = true; + } + if (glXQueryExtensionsStringAvailable) { + lockAWT(); + try { + String ret = GLX.glXQueryExtensionsString(drawable.getDisplay(), GLX.DefaultScreen(drawable.getDisplay())); + if (DEBUG) { + System.err.println("!!! GLX extensions: " + ret); + } + return ret; + } finally { + unlockAWT(); + } + } else { + return ""; + } + } + + protected boolean isFunctionAvailable(String glFunctionName) + { + boolean available = super.isFunctionAvailable(glFunctionName); + + // Sanity check for implementations that use proc addresses for run-time + // linking: if the function IS available, then make sure there's a proc + // address for it if it's an extension or not part of the OpenGL 1.1 core + // (post GL 1.1 functions are run-time linked on windows). + assert(!available || + (getGLProcAddressTable().getAddressFor(mapToRealGLFunctionName(glFunctionName)) != 0 || + FunctionAvailabilityCache.isPartOfGLCore("1.1", mapToRealGLFunctionName(glFunctionName))) + ); + + return available; + } + + public boolean isExtensionAvailable(String glExtensionName) { + if (glExtensionName.equals("GL_ARB_pbuffer") || + glExtensionName.equals("GL_ARB_pixel_format")) { + return GLDrawableFactory.getFactory().canCreateGLPbuffer(); + } + return super.isExtensionAvailable(glExtensionName); + } + + + public void setSwapInterval(int interval) { + // FIXME: make the context current first? Currently assumes that + // will not be necessary. Make the caller do this? + GLXExt glXExt = getGLXExt(); + if (glXExt.isExtensionAvailable("GLX_SGI_swap_control")) { + glXExt.glXSwapIntervalSGI(interval); + } + } + + public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) { + return getGLXExt().glXAllocateMemoryNV(arg0, arg1, arg2, arg3); + } + + public int getOffscreenContextPixelDataType() { + throw new GLException("Should not call this"); + } + + public int getOffscreenContextReadBuffer() { + throw new GLException("Should not call this"); + } + + public boolean offscreenImageNeedsVerticalFlip() { + throw new GLException("Should not call this"); + } + + public void bindPbufferToTexture() { + throw new GLException("Should not call this"); + } + + public void releasePbufferFromTexture() { + throw new GLException("Should not call this"); + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + protected long getContext() { + return context; + } + + // These synchronization primitives prevent the AWT from making + // requests from the X server asynchronously to this code. + protected void lockAWT() { + X11GLDrawableFactory.lockAWT(); + } + + protected void unlockAWT() { + X11GLDrawableFactory.unlockAWT(); + } +} diff --git a/src/classes/com/sun/opengl/impl/x11/X11GLDrawable.java b/src/classes/com/sun/opengl/impl/x11/X11GLDrawable.java new file mode 100644 index 000000000..1d4f5389b --- /dev/null +++ b/src/classes/com/sun/opengl/impl/x11/X11GLDrawable.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2003 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 com.sun.opengl.impl.x11; + +import java.awt.Component; + +import javax.media.opengl.*; +import com.sun.opengl.impl.*; + +public abstract class X11GLDrawable extends GLDrawableImpl { + protected static final boolean DEBUG = Debug.debug("X11GLDrawable"); + + protected long display; + protected long drawable; + protected long visualID; + protected Component component; + protected GLCapabilities capabilities; + protected GLCapabilitiesChooser chooser; + + public X11GLDrawable(Component component, + GLCapabilities capabilities, + GLCapabilitiesChooser chooser) { + this.component = component; + this.capabilities = (capabilities == null) ? null : + ((GLCapabilities) capabilities.clone()); + this.chooser = chooser; + } + + public void setRealized(boolean val) { + throw new GLException("Should not call this (should only be called for onscreen GLDrawables)"); + } + + public void destroy() { + throw new GLException("Should not call this (should only be called for offscreen GLDrawables)"); + } + + public void swapBuffers() throws GLException { + } + + public long getDisplay() { + return display; + } + + public long getDrawable() { + return drawable; + } + + //--------------------------------------------------------------------------- + // Internals only below this point + // + + protected XVisualInfo chooseVisual(boolean onscreen) { + if (display == 0) { + throw new GLException("null display"); + } + + // FIXME + if (onscreen) { + // The visual has already been chosen by the time we get here; + // it's specified by the GraphicsConfiguration of the + // GLCanvas. Fortunately, the JAWT supplies the visual ID for + // the component in a portable fashion, so all we have to do is + // use XGetVisualInfo with a VisualIDMask to get the + // corresponding XVisualInfo to pass into glXChooseVisual. + int[] count = new int[1]; + XVisualInfo template = new XVisualInfo(); + // FIXME: probably not 64-bit clean + template.visualid((int) visualID); + lockAWT(); + XVisualInfo[] infos = GLX.XGetVisualInfo(display, GLX.VisualIDMask, template, count, 0); + unlockAWT(); + if (infos == null || infos.length == 0) { + throw new GLException("Error while getting XVisualInfo for visual ID " + visualID); + } + // FIXME: the storage for the infos array is leaked (should + // clean it up somehow when we're done with the visual we're + // returning) + return infos[0]; + } else { + // It isn't clear to me whether we need this much code to handle + // the offscreen case, where we're creating a pixmap into which + // to render...this is what we (incorrectly) used to do for the + // onscreen case + + int screen = 0; // FIXME: provide way to specify this? + XVisualInfo vis = null; + int[] count = new int[1]; + XVisualInfo template = new XVisualInfo(); + template.screen(screen); + XVisualInfo[] infos = null; + GLCapabilities[] caps = null; + lockAWT(); + try { + infos = GLX.XGetVisualInfo(display, GLX.VisualScreenMask, template, count, 0); + if (infos == null) { + throw new GLException("Error while enumerating available XVisualInfos"); + } + caps = new GLCapabilities[infos.length]; + for (int i = 0; i < infos.length; i++) { + caps[i] = X11GLDrawableFactory.xvi2GLCapabilities(display, infos[i]); + } + } finally { + unlockAWT(); + } + int chosen = chooser.chooseCapabilities(capabilities, caps, -1); + if (chosen < 0 || chosen >= caps.length) { + throw new GLException("GLCapabilitiesChooser specified invalid index (expected 0.." + (caps.length - 1) + ")"); + } + if (DEBUG) { + System.err.println("Chosen visual (" + chosen + "):"); + System.err.println(caps[chosen]); + } + vis = infos[chosen]; + if (vis == null) { + throw new GLException("GLCapabilitiesChooser chose an invalid visual"); + } + // FIXME: the storage for the infos array is leaked (should + // clean it up somehow when we're done with the visual we're + // returning) + + return vis; + } + } + + + // These synchronization primitives prevent the AWT from making + // requests from the X server asynchronously to this code. + protected void lockAWT() { + X11GLDrawableFactory.lockAWT(); + } + + protected void unlockAWT() { + X11GLDrawableFactory.unlockAWT(); + } +} diff --git a/src/classes/com/sun/opengl/impl/x11/X11GLDrawableFactory.java b/src/classes/com/sun/opengl/impl/x11/X11GLDrawableFactory.java new file mode 100644 index 000000000..f4523c95e --- /dev/null +++ b/src/classes/com/sun/opengl/impl/x11/X11GLDrawableFactory.java @@ -0,0 +1,439 @@ +/* + * Copyright (c) 2003 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 com.sun.opengl.impl.x11; + +import java.awt.Component; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.security.*; +import java.util.ArrayList; +import java.util.List; +import javax.media.opengl.*; +import com.sun.opengl.impl.*; + +public class X11GLDrawableFactory extends GLDrawableFactoryImpl { + private static final boolean DEBUG = Debug.debug("X11GLDrawableFactory"); + + // There is currently a bug on Linux/AMD64 distributions in glXGetProcAddressARB + private static boolean isLinuxAMD64; + + static { + NativeLibLoader.load(); + + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + String os = System.getProperty("os.name").toLowerCase(); + String arch = System.getProperty("os.arch").toLowerCase(); + if (os.startsWith("linux") && arch.equals("amd64")) { + isLinuxAMD64 = true; + } + return null; + } + }); + } + + public X11GLDrawableFactory() { + // Must initialize GLX support eagerly in case a pbuffer is the + // first thing instantiated + resetProcAddressTable(GLX.getGLXProcAddressTable()); + } + + private static final int MAX_ATTRIBS = 128; + + public GraphicsConfiguration chooseGraphicsConfiguration(GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + GraphicsDevice device) { + if (capabilities == null) { + capabilities = new GLCapabilities(); + } + if (chooser == null) { + chooser = new DefaultGLCapabilitiesChooser(); + } + if (device == null) { + device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); + } + + int screen = X11SunJDKReflection.graphicsDeviceGetScreen(device); + // Until we have a rock-solid visual selection algorithm written + // in pure Java, we're going to provide the underlying window + // system's selection to the chooser as a hint + + int[] attribs = glCapabilities2AttribList(capabilities, isMultisampleAvailable()); + XVisualInfo[] infos = null; + GLCapabilities[] caps = null; + int recommendedIndex = -1; + lockAWT(); + try { + long display = getDisplayConnection(); + XVisualInfo recommendedVis = GLX.glXChooseVisual(display, screen, attribs, 0); + int[] count = new int[1]; + XVisualInfo template = new XVisualInfo(); + template.screen(screen); + infos = GLX.XGetVisualInfo(display, GLX.VisualScreenMask, template, count, 0); + if (infos == null) { + throw new GLException("Error while enumerating available XVisualInfos"); + } + caps = new GLCapabilities[infos.length]; + for (int i = 0; i < infos.length; i++) { + caps[i] = xvi2GLCapabilities(display, infos[i]); + // Attempt to find the visual chosen by glXChooseVisual + if (recommendedVis != null && recommendedVis.visualid() == infos[i].visualid()) { + recommendedIndex = i; + } + } + } finally { + unlockAWT(); + } + int chosen = chooser.chooseCapabilities(capabilities, caps, recommendedIndex); + if (chosen < 0 || chosen >= caps.length) { + throw new GLException("GLCapabilitiesChooser specified invalid index (expected 0.." + (caps.length - 1) + ")"); + } + XVisualInfo vis = infos[chosen]; + if (vis == null) { + throw new GLException("GLCapabilitiesChooser chose an invalid visual"); + } + // FIXME: need to look at glue code and see type of this field + long visualID = vis.visualid(); + // FIXME: the storage for the infos array, as well as that for the + // recommended visual, is leaked; should free them here with XFree() + + // Now figure out which GraphicsConfiguration corresponds to this + // visual by matching the visual ID + GraphicsConfiguration[] configs = device.getConfigurations(); + for (int i = 0; i < configs.length; i++) { + GraphicsConfiguration config = configs[i]; + if (config != null) { + if (X11SunJDKReflection.graphicsConfigurationGetVisualID(config) == visualID) { + return config; + } + } + } + + // Either we weren't able to reflectively introspect on the + // X11GraphicsConfig or something went wrong in the steps above; + // we're going to return null without signaling an error condition + // in this case (although we should distinguish between the two + // and possibly report more of an error in the latter case) + return null; + } + + public GLDrawable getGLDrawable(Object target, + GLCapabilities capabilities, + GLCapabilitiesChooser chooser) { + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + if (!(target instanceof Component)) { + throw new IllegalArgumentException("GLDrawables not supported for objects of type " + + target.getClass().getName() + " (only Components are supported in this implementation)"); + } + return new X11OnscreenGLDrawable((Component) target); + } + + public GLDrawableImpl createOffscreenDrawable(GLCapabilities capabilities, + GLCapabilitiesChooser chooser) { + return new X11OffscreenGLDrawable(capabilities, chooser); + } + + private boolean pbufferSupportInitialized = false; + private boolean canCreateGLPbuffer = false; + public boolean canCreateGLPbuffer() { + if (!pbufferSupportInitialized) { + Runnable r = new Runnable() { + public void run() { + long display = getDisplayConnection(); + lockAWT(); + try { + int[] major = new int[1]; + int[] minor = new int[1]; + if (!GLX.glXQueryVersion(display, major, 0, minor, 0)) { + throw new GLException("glXQueryVersion failed"); + } + if (DEBUG) { + System.err.println("!!! GLX version: major " + major[0] + + ", minor " + minor[0]); + } + + int screen = 0; // FIXME: provide way to specify this? + + // Work around bugs in ATI's Linux drivers where they report they + // only implement GLX version 1.2 but actually do support pbuffers + if (major[0] == 1 && minor[0] == 2) { + String str = GLX.glXQueryServerString(display, screen, GLX.GLX_VENDOR); + if (str != null && str.indexOf("ATI") >= 0) { + canCreateGLPbuffer = true; + } + } else { + canCreateGLPbuffer = ((major[0] > 1) || (minor[0] > 2)); + } + + pbufferSupportInitialized = true; + } finally { + unlockAWT(); + } + } + }; + maybeDoSingleThreadedWorkaround(r); + } + return canCreateGLPbuffer; + } + + public GLPbuffer createGLPbuffer(final GLCapabilities capabilities, + final int initialWidth, + final int initialHeight, + final GLContext shareWith) { + if (!canCreateGLPbuffer()) { + throw new GLException("Pbuffer support not available with current graphics card"); + } + final List returnList = new ArrayList(); + Runnable r = new Runnable() { + public void run() { + X11PbufferGLDrawable pbufferDrawable = new X11PbufferGLDrawable(capabilities, + initialWidth, + initialHeight); + GLPbufferImpl pbuffer = new GLPbufferImpl(pbufferDrawable, shareWith); + returnList.add(pbuffer); + } + }; + maybeDoSingleThreadedWorkaround(r); + return (GLPbuffer) returnList.get(0); + } + + public GLContext createExternalGLContext() { + return new X11ExternalGLContext(); + } + + public boolean canCreateExternalGLDrawable() { + return canCreateGLPbuffer(); + } + + public GLDrawable createExternalGLDrawable() { + return new X11ExternalGLDrawable(); + } + + public long dynamicLookupFunction(String glFuncName) { + long res = 0; + if (!isLinuxAMD64) { + res = GLX.glXGetProcAddressARB(glFuncName); + } + if (res == 0) { + // GLU routines aren't known to the OpenGL function lookup + res = GLX.dlsym(glFuncName); + } + return res; + } + + public static GLCapabilities xvi2GLCapabilities(long display, XVisualInfo info) { + int[] tmp = new int[1]; + int val = glXGetConfig(display, info, GLX.GLX_USE_GL, tmp, 0); + if (val == 0) { + // Visual does not support OpenGL + return null; + } + val = glXGetConfig(display, info, GLX.GLX_RGBA, tmp, 0); + if (val == 0) { + // Visual does not support RGBA + return null; + } + GLCapabilities res = new GLCapabilities(); + res.setDoubleBuffered(glXGetConfig(display, info, GLX.GLX_DOUBLEBUFFER, tmp, 0) != 0); + res.setStereo (glXGetConfig(display, info, GLX.GLX_STEREO, tmp, 0) != 0); + // Note: use of hardware acceleration is determined by + // glXCreateContext, not by the XVisualInfo. Optimistically claim + // that all GLCapabilities have the capability to be hardware + // accelerated. + res.setHardwareAccelerated(true); + res.setDepthBits (glXGetConfig(display, info, GLX.GLX_DEPTH_SIZE, tmp, 0)); + res.setStencilBits (glXGetConfig(display, info, GLX.GLX_STENCIL_SIZE, tmp, 0)); + res.setRedBits (glXGetConfig(display, info, GLX.GLX_RED_SIZE, tmp, 0)); + res.setGreenBits (glXGetConfig(display, info, GLX.GLX_GREEN_SIZE, tmp, 0)); + res.setBlueBits (glXGetConfig(display, info, GLX.GLX_BLUE_SIZE, tmp, 0)); + res.setAlphaBits (glXGetConfig(display, info, GLX.GLX_ALPHA_SIZE, tmp, 0)); + res.setAccumRedBits (glXGetConfig(display, info, GLX.GLX_ACCUM_RED_SIZE, tmp, 0)); + res.setAccumGreenBits(glXGetConfig(display, info, GLX.GLX_ACCUM_GREEN_SIZE, tmp, 0)); + res.setAccumBlueBits (glXGetConfig(display, info, GLX.GLX_ACCUM_BLUE_SIZE, tmp, 0)); + res.setAccumAlphaBits(glXGetConfig(display, info, GLX.GLX_ACCUM_ALPHA_SIZE, tmp, 0)); + if (isMultisampleAvailable()) { + res.setSampleBuffers(glXGetConfig(display, info, GLX.GLX_SAMPLE_BUFFERS_ARB, tmp, 0) != 0); + res.setNumSamples (glXGetConfig(display, info, GLX.GLX_SAMPLES_ARB, tmp, 0)); + } + return res; + } + + public static int[] glCapabilities2AttribList(GLCapabilities caps, + boolean isMultisampleAvailable) { + int colorDepth = (caps.getRedBits() + + caps.getGreenBits() + + caps.getBlueBits()); + if (colorDepth < 15) { + throw new GLException("Bit depths < 15 (i.e., non-true-color) not supported"); + } + int[] res = new int[MAX_ATTRIBS]; + int idx = 0; + res[idx++] = GLX.GLX_RGBA; + if (caps.getDoubleBuffered()) { + res[idx++] = GLX.GLX_DOUBLEBUFFER; + } + if (caps.getStereo()) { + res[idx++] = GLX.GLX_STEREO; + } + res[idx++] = GLX.GLX_RED_SIZE; + res[idx++] = caps.getRedBits(); + res[idx++] = GLX.GLX_GREEN_SIZE; + res[idx++] = caps.getGreenBits(); + res[idx++] = GLX.GLX_BLUE_SIZE; + res[idx++] = caps.getBlueBits(); + res[idx++] = GLX.GLX_ALPHA_SIZE; + res[idx++] = caps.getAlphaBits(); + res[idx++] = GLX.GLX_DEPTH_SIZE; + res[idx++] = caps.getDepthBits(); + res[idx++] = GLX.GLX_STENCIL_SIZE; + res[idx++] = caps.getStencilBits(); + res[idx++] = GLX.GLX_ACCUM_RED_SIZE; + res[idx++] = caps.getAccumRedBits(); + res[idx++] = GLX.GLX_ACCUM_GREEN_SIZE; + res[idx++] = caps.getAccumGreenBits(); + res[idx++] = GLX.GLX_ACCUM_BLUE_SIZE; + res[idx++] = caps.getAccumBlueBits(); + if (isMultisampleAvailable && caps.getSampleBuffers()) { + res[idx++] = GLXExt.GLX_SAMPLE_BUFFERS_ARB; + res[idx++] = GL.GL_TRUE; + res[idx++] = GLXExt.GLX_SAMPLES_ARB; + res[idx++] = caps.getNumSamples(); + } + res[idx++] = 0; + return res; + } + + // JAWT access + private static JAWT jawt; + public static JAWT getJAWT() { + if (jawt == null) { + JAWT j = new JAWT(); + j.version(JAWTFactory.JAWT_VERSION_1_4); + if (!JAWTFactory.JAWT_GetAWT(j)) { + throw new RuntimeException("Unable to initialize JAWT"); + } + jawt = j; + } + return jawt; + } + + public static void lockAWT() { + if (!Java2D.isOGLPipelineActive() || !Java2D.isQueueFlusherThread()) { + getJAWT().Lock(); + } + } + + public static void unlockAWT() { + if (!Java2D.isOGLPipelineActive() || !Java2D.isQueueFlusherThread()) { + getJAWT().Unlock(); + } + } + + public void lockAWTForJava2D() { + lockAWT(); + } + public void unlockAWTForJava2D() { + unlockAWT(); + } + + // Display connection for use by visual selection algorithm and by all offscreen surfaces + private static long staticDisplay; + public static long getDisplayConnection() { + if (staticDisplay == 0) { + lockAWT(); + try { + staticDisplay = GLX.XOpenDisplay(null); + } finally { + unlockAWT(); + } + if (staticDisplay == 0) { + throw new GLException("Unable to open default display, needed for visual selection and offscreen surface handling"); + } + } + return staticDisplay; + } + + private static boolean checkedMultisample; + private static boolean multisampleAvailable; + public static boolean isMultisampleAvailable() { + if (!checkedMultisample) { + long display = getDisplayConnection(); + String exts = GLX.glXGetClientString(display, GLX.GLX_EXTENSIONS); + if (exts != null) { + multisampleAvailable = (exts.indexOf("GLX_ARB_multisample") >= 0); + } + checkedMultisample = true; + } + return multisampleAvailable; + } + + private static String glXGetConfigErrorCode(int err) { + switch (err) { + case GLX.GLX_NO_EXTENSION: return "GLX_NO_EXTENSION"; + case GLX.GLX_BAD_SCREEN: return "GLX_BAD_SCREEN"; + case GLX.GLX_BAD_ATTRIBUTE: return "GLX_BAD_ATTRIBUTE"; + case GLX.GLX_BAD_VISUAL: return "GLX_BAD_VISUAL"; + default: return "Unknown error code " + err; + } + } + + public static int glXGetConfig(long display, XVisualInfo info, int attrib, int[] tmp, int tmp_offset) { + if (display == 0) { + throw new GLException("No display connection"); + } + int res = GLX.glXGetConfig(display, info, attrib, tmp, tmp_offset); + if (res != 0) { + throw new GLException("glXGetConfig failed: error code " + glXGetConfigErrorCode(res)); + } + return tmp[tmp_offset]; + } + + private void maybeDoSingleThreadedWorkaround(Runnable action) { + if (Threading.isSingleThreaded() && + !Threading.isOpenGLThread()) { + Threading.invokeOnOpenGLThread(action); + } else { + action.run(); + } + } +} diff --git a/src/classes/com/sun/opengl/impl/x11/X11OffscreenGLContext.java b/src/classes/com/sun/opengl/impl/x11/X11OffscreenGLContext.java new file mode 100644 index 000000000..e1c8eb3d1 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/x11/X11OffscreenGLContext.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2003 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 com.sun.opengl.impl.x11; + +import javax.media.opengl.*; +import com.sun.opengl.impl.*; + +public class X11OffscreenGLContext extends X11GLContext { + private X11OffscreenGLDrawable drawable; + + public X11OffscreenGLContext(X11OffscreenGLDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + this.drawable = drawable; + } + + public int getOffscreenContextPixelDataType() { + return GL.GL_UNSIGNED_INT_8_8_8_8_REV; + } + + public int getOffscreenContextReadBuffer() { + if (drawable.isDoubleBuffered()) { + return GL.GL_BACK; + } + return GL.GL_FRONT; + } + + public boolean offscreenImageNeedsVerticalFlip() { + // There doesn't seem to be a way to do this in the construction + // of the Pixmap or GLXPixmap + return true; + } + + protected void create() { + createContext(false); + } +} diff --git a/src/classes/com/sun/opengl/impl/x11/X11OffscreenGLDrawable.java b/src/classes/com/sun/opengl/impl/x11/X11OffscreenGLDrawable.java new file mode 100644 index 000000000..2d7dedd7f --- /dev/null +++ b/src/classes/com/sun/opengl/impl/x11/X11OffscreenGLDrawable.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2003 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 com.sun.opengl.impl.x11; + +import javax.media.opengl.*; +import com.sun.opengl.impl.*; + +public class X11OffscreenGLDrawable extends X11GLDrawable { + private long pixmap; + private boolean isDoubleBuffered; + // Width and height of the underlying bitmap + private int width; + private int height; + + public X11OffscreenGLDrawable(GLCapabilities capabilities, + GLCapabilitiesChooser chooser) { + super(null, capabilities, chooser); + } + + public GLContext createContext(GLContext shareWith) { + return new X11OffscreenGLContext(this, shareWith); + } + + public void setSize(int newWidth, int newHeight) { + width = newWidth; + height = newHeight; + if (pixmap != 0) { + destroy(); + } + create(); + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + private void create() { + display = X11GLDrawableFactory.getDisplayConnection(); + XVisualInfo vis = chooseVisual(false); + int bitsPerPixel = vis.depth(); + + lockAWT(); + try { + int screen = GLX.DefaultScreen(display); + pixmap = GLX.XCreatePixmap(display, (int) GLX.RootWindow(display, screen), width, height, bitsPerPixel); + if (pixmap == 0) { + throw new GLException("XCreatePixmap failed"); + } + drawable = GLX.glXCreateGLXPixmap(display, vis, pixmap); + if (drawable == 0) { + GLX.XFreePixmap(display, pixmap); + pixmap = 0; + throw new GLException("glXCreateGLXPixmap failed"); + } + isDoubleBuffered = (X11GLDrawableFactory.glXGetConfig(display, vis, GLX.GLX_DOUBLEBUFFER, new int[1], 0) != 0); + if (DEBUG) { + System.err.println("Created pixmap " + toHexString(pixmap) + + ", GLXPixmap " + toHexString(drawable) + + ", display " + toHexString(display)); + } + } finally { + unlockAWT(); + } + } + + public void destroy() { + if (pixmap != 0) { + if (DEBUG) { + System.err.println("Destroying pixmap " + toHexString(pixmap) + + ", GLXPixmap " + toHexString(drawable) + + ", display " + toHexString(display)); + } + + // Must destroy pixmap and GLXPixmap + lockAWT(); + + if (DEBUG) { + long cur = GLX.glXGetCurrentContext(); + if (cur != 0) { + System.err.println("WARNING: found context " + toHexString(cur) + " current during pixmap destruction"); + } + } + + // FIXME: workaround for crashes on NVidia hardware when + // destroying pixmap (no context is current at the point of the + // crash, at least from the point of view of + // glXGetCurrentContext) + GLX.glXMakeCurrent(display, 0, 0); + + GLX.glXDestroyGLXPixmap(display, drawable); + GLX.XFreePixmap(display, pixmap); + unlockAWT(); + drawable = 0; + pixmap = 0; + display = 0; + } + } + + public boolean isDoubleBuffered() { + return isDoubleBuffered; + } +} diff --git a/src/classes/com/sun/opengl/impl/x11/X11OnscreenGLContext.java b/src/classes/com/sun/opengl/impl/x11/X11OnscreenGLContext.java new file mode 100644 index 000000000..d6b79cb8f --- /dev/null +++ b/src/classes/com/sun/opengl/impl/x11/X11OnscreenGLContext.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2003 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 com.sun.opengl.impl.x11; + +import java.util.*; + +import javax.media.opengl.*; +import com.sun.opengl.impl.*; + +public class X11OnscreenGLContext extends X11GLContext { + protected X11OnscreenGLDrawable drawable; + + public X11OnscreenGLContext(X11OnscreenGLDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + this.drawable = drawable; + } + + protected int makeCurrentImpl() throws GLException { + try { + int lockRes = drawable.lockSurface(); + if (lockRes == X11OnscreenGLDrawable.LOCK_SURFACE_NOT_READY) { + return CONTEXT_NOT_CURRENT; + } + if (lockRes == X11OnscreenGLDrawable.LOCK_SURFACE_CHANGED) { + if (context != 0) { + GLX.glXDestroyContext(mostRecentDisplay, context); + GLContextShareSet.contextDestroyed(this); + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Destroyed OpenGL context " + toHexString(context) + " due to JAWT_LOCK_SURFACE_CHANGED"); + } + context = 0; + } + } + int ret = super.makeCurrentImpl(); + return ret; + } catch (RuntimeException e) { + try { + drawable.unlockSurface(); + } catch (Exception e2) { + // do nothing if unlockSurface throws + } + throw(e); + } + } + + protected void releaseImpl() throws GLException { + try { + super.releaseImpl(); + } finally { + drawable.unlockSurface(); + } + } + + protected void create() { + createContext(true); + } +} diff --git a/src/classes/com/sun/opengl/impl/x11/X11OnscreenGLDrawable.java b/src/classes/com/sun/opengl/impl/x11/X11OnscreenGLDrawable.java new file mode 100644 index 000000000..49000fc14 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/x11/X11OnscreenGLDrawable.java @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2003 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 com.sun.opengl.impl.x11; + +import java.awt.Component; + +import javax.media.opengl.*; +import com.sun.opengl.impl.*; + +public class X11OnscreenGLDrawable extends X11GLDrawable { + public static final int LOCK_SURFACE_NOT_READY = 1; + public static final int LOCK_SURFACE_CHANGED = 2; + public static final int LOCK_SUCCESS = 3; + + // Variables for lockSurface/unlockSurface + private JAWT_DrawingSurface ds; + private JAWT_DrawingSurfaceInfo dsi; + private JAWT_X11DrawingSurfaceInfo x11dsi; + + // Indicates whether the component (if an onscreen context) has been + // realized. Plausibly, before the component is realized the JAWT + // should return an error or NULL object from some of its + // operations; this appears to be the case on Win32 but is not true + // at least with Sun's current X11 implementation (1.4.x), which + // crashes with no other error reported if the DrawingSurfaceInfo is + // fetched from a locked DrawingSurface during the validation as a + // result of calling show() on the main thread. To work around this + // we prevent any JAWT or OpenGL operations from being done until + // addNotify() is called on the component. + protected boolean realized; + + public X11OnscreenGLDrawable(Component component) { + super(component, null, null); + } + + public GLContext createContext(GLContext shareWith) { + return new X11OnscreenGLContext(this, shareWith); + } + + public void setRealized(boolean realized) { + this.realized = realized; + } + + public void setSize(int width, int height) { + component.setSize(width, height); + } + + public int getWidth() { + return component.getWidth(); + } + + public int getHeight() { + return component.getHeight(); + } + + public void swapBuffers() throws GLException { + lockAWT(); + try { + boolean didLock = false; + + if (drawable == 0) { + if (lockSurface() == LOCK_SURFACE_NOT_READY) { + return; + } + + didLock = true; + } + + GLX.glXSwapBuffers(display, drawable); + + if (didLock) { + unlockSurface(); + } + } finally { + unlockAWT(); + } + } + + public int lockSurface() throws GLException { + if (!realized) { + return LOCK_SURFACE_NOT_READY; + } + if (drawable != 0) { + throw new GLException("Surface already locked"); + } + ds = getJAWT().GetDrawingSurface(component); + if (ds == null) { + // Widget not yet realized + return LOCK_SURFACE_NOT_READY; + } + int res = ds.Lock(); + if ((res & JAWTFactory.JAWT_LOCK_ERROR) != 0) { + throw new GLException("Unable to lock surface"); + } + // See whether the surface changed and if so destroy the old + // OpenGL context so it will be recreated (NOTE: removeNotify + // should handle this case, but it may be possible that race + // conditions can cause this code to be triggered -- should test + // more) + int ret = LOCK_SUCCESS; + if ((res & JAWTFactory.JAWT_LOCK_SURFACE_CHANGED) != 0) { + ret = LOCK_SURFACE_CHANGED; + } + dsi = ds.GetDrawingSurfaceInfo(); + if (dsi == null) { + // Widget not yet realized + ds.Unlock(); + getJAWT().FreeDrawingSurface(ds); + ds = null; + return LOCK_SURFACE_NOT_READY; + } + x11dsi = (JAWT_X11DrawingSurfaceInfo) dsi.platformInfo(); + display = x11dsi.display(); + drawable = x11dsi.drawable(); + visualID = x11dsi.visualID(); + if (display == 0 || drawable == 0) { + // Widget not yet realized + ds.FreeDrawingSurfaceInfo(dsi); + ds.Unlock(); + getJAWT().FreeDrawingSurface(ds); + ds = null; + dsi = null; + x11dsi = null; + display = 0; + drawable = 0; + visualID = 0; + return LOCK_SURFACE_NOT_READY; + } + return ret; + } + + public void unlockSurface() { + if (drawable == 0) { + throw new GLException("Surface already unlocked"); + } + ds.FreeDrawingSurfaceInfo(dsi); + ds.Unlock(); + getJAWT().FreeDrawingSurface(ds); + ds = null; + dsi = null; + x11dsi = null; + display = 0; + drawable = 0; + visualID = 0; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private JAWT getJAWT() { + return X11GLDrawableFactory.getJAWT(); + } +} diff --git a/src/classes/com/sun/opengl/impl/x11/X11PbufferGLContext.java b/src/classes/com/sun/opengl/impl/x11/X11PbufferGLContext.java new file mode 100644 index 000000000..0cb945de7 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/x11/X11PbufferGLContext.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2003 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 com.sun.opengl.impl.x11; + +import javax.media.opengl.*; +import com.sun.opengl.impl.*; + +public class X11PbufferGLContext extends X11GLContext { + private X11PbufferGLDrawable drawable; + + public X11PbufferGLContext(X11PbufferGLDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + this.drawable = drawable; + } + + public void bindPbufferToTexture() { + // FIXME: figure out how to implement this + throw new GLException("Not yet implemented"); + } + + public void releasePbufferFromTexture() { + // FIXME: figure out how to implement this + throw new GLException("Not yet implemented"); + } + + protected int makeCurrentImpl() throws GLException { + if (drawable.getDrawable() == 0) { + // pbuffer not instantiated (yet?) + if (DEBUG) { + System.err.println("pbuffer not instantiated"); + } + return CONTEXT_NOT_CURRENT; + } + + // Note that we have to completely override makeCurrentImpl + // because the underlying makeCurrent call differs for pbuffers + lockAWT(); + try { + boolean created = false; + if (context == 0) { + create(); + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Created GL context for " + getClass().getName()); + } + created = true; + } + + if (!GLX.glXMakeContextCurrent(drawable.getDisplay(), + drawable.getDrawable(), + drawable.getDrawable(), + context)) { + throw new GLException("Error making context current"); + } else { + mostRecentDisplay = drawable.getDisplay(); + if (DEBUG && VERBOSE) { + System.err.println(getThreadName() + ": glXMakeCurrent(display " + toHexString(drawable.getDisplay()) + + ", drawable " + toHexString(drawable.getDrawable()) + + ", context " + toHexString(context) + ") succeeded"); + } + } + + if (created) { + resetGLFunctionAvailability(); + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } finally { + unlockAWT(); + } + } + + protected void releaseImpl() throws GLException { + lockAWT(); + try { + if (!GLX.glXMakeContextCurrent(drawable.getDisplay(), 0, 0, 0)) { + throw new GLException("Error freeing OpenGL context"); + } + } finally { + unlockAWT(); + } + } + + public int getFloatingPointMode() { + return drawable.getFloatingPointMode(); + } + + protected void create() { + if (DEBUG) { + System.err.println("Creating context for pbuffer " + drawable.getWidth() + + " x " + drawable.getHeight()); + } + + // Create a gl context for the p-buffer. + X11GLContext other = (X11GLContext) GLContextShareSet.getShareContext(this); + long share = 0; + if (other != null) { + share = other.getContext(); + if (share == 0) { + throw new GLException("GLContextShareSet returned an invalid OpenGL context"); + } + } + context = GLX.glXCreateNewContext(drawable.getDisplay(), drawable.getFBConfig(), GLXExt.GLX_RGBA_TYPE, share, true); + if (context == 0) { + throw new GLException("pbuffer creation error: glXCreateNewContext() failed"); + } + GLContextShareSet.contextCreated(this); + + if (DEBUG) { + System.err.println("Created context for pbuffer " + drawable.getWidth() + + " x " + drawable.getHeight()); + } + } +} diff --git a/src/classes/com/sun/opengl/impl/x11/X11PbufferGLDrawable.java b/src/classes/com/sun/opengl/impl/x11/X11PbufferGLDrawable.java new file mode 100644 index 000000000..2a1248405 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/x11/X11PbufferGLDrawable.java @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2003 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 com.sun.opengl.impl.x11; + +import javax.media.opengl.*; +import com.sun.opengl.impl.*; + +public class X11PbufferGLDrawable extends X11GLDrawable { + private int initWidth; + private int initHeight; + + // drawable in superclass is a GLXPbuffer + private GLXFBConfig fbConfig; + private int width; + private int height; + + protected static final int MAX_PFORMATS = 256; + protected static final int MAX_ATTRIBS = 256; + + public X11PbufferGLDrawable(GLCapabilities capabilities, int initialWidth, int initialHeight) { + super(null, capabilities, null); + this.initWidth = initialWidth; + this.initHeight = initialHeight; + if (initWidth <= 0 || initHeight <= 0) { + throw new GLException("Initial width and height of pbuffer must be positive (were (" + + initWidth + ", " + initHeight + "))"); + } + + if (DEBUG) { + System.out.println("Pbuffer caps on init: " + capabilities + + (capabilities.getOffscreenRenderToTexture() ? " [rtt]" : "") + + (capabilities.getOffscreenRenderToTextureRectangle() ? " [rect]" : "") + + (capabilities.getOffscreenFloatingPointBuffers() ? " [float]" : "")); + } + + createPbuffer(X11GLDrawableFactory.getDisplayConnection()); + } + + public GLContext createContext(GLContext shareWith) { + return new X11PbufferGLContext(this, shareWith); + } + + public void destroy() { + lockAWT(); + if (drawable != 0) { + GLX.glXDestroyPbuffer(display, drawable); + } + unlockAWT(); + display = 0; + } + + public void setSize(int width, int height) { + // FIXME + throw new GLException("Not yet implemented"); + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public void createPbuffer(long display) { + lockAWT(); + try { + if (display == 0) { + throw new GLException("Null display"); + } + + if (capabilities.getOffscreenRenderToTexture()) { + throw new GLException("Render-to-texture pbuffers not supported yet on X11"); + } + + if (capabilities.getOffscreenRenderToTextureRectangle()) { + throw new GLException("Render-to-texture-rectangle pbuffers not supported yet on X11"); + } + + int[] iattributes = new int [2*MAX_ATTRIBS]; + float[] fattributes = new float[2*MAX_ATTRIBS]; + int nfattribs = 0; + int niattribs = 0; + + // Since we are trying to create a pbuffer, the GLXFBConfig we + // request (and subsequently use) must be "p-buffer capable". + iattributes[niattribs++] = GLXExt.GLX_DRAWABLE_TYPE; + iattributes[niattribs++] = GLXExt.GLX_PBUFFER_BIT; + + iattributes[niattribs++] = GLXExt.GLX_RENDER_TYPE; + iattributes[niattribs++] = GLXExt.GLX_RGBA_BIT; + + iattributes[niattribs++] = GLX.GLX_DOUBLEBUFFER; + if (capabilities.getDoubleBuffered()) { + iattributes[niattribs++] = GL.GL_TRUE; + } else { + iattributes[niattribs++] = GL.GL_FALSE; + } + + iattributes[niattribs++] = GLX.GLX_DEPTH_SIZE; + iattributes[niattribs++] = capabilities.getDepthBits(); + + iattributes[niattribs++] = GLX.GLX_RED_SIZE; + iattributes[niattribs++] = capabilities.getRedBits(); + + iattributes[niattribs++] = GLX.GLX_GREEN_SIZE; + iattributes[niattribs++] = capabilities.getGreenBits(); + + iattributes[niattribs++] = GLX.GLX_BLUE_SIZE; + iattributes[niattribs++] = capabilities.getBlueBits(); + + iattributes[niattribs++] = GLX.GLX_ALPHA_SIZE; + iattributes[niattribs++] = capabilities.getAlphaBits(); + + if (capabilities.getStencilBits() > 0) { + iattributes[niattribs++] = GLX.GLX_STENCIL_SIZE; + iattributes[niattribs++] = capabilities.getStencilBits(); + } + + if (capabilities.getAccumRedBits() > 0 || + capabilities.getAccumGreenBits() > 0 || + capabilities.getAccumBlueBits() > 0) { + iattributes[niattribs++] = GLX.GLX_ACCUM_RED_SIZE; + iattributes[niattribs++] = capabilities.getAccumRedBits(); + iattributes[niattribs++] = GLX.GLX_ACCUM_GREEN_SIZE; + iattributes[niattribs++] = capabilities.getAccumGreenBits(); + iattributes[niattribs++] = GLX.GLX_ACCUM_BLUE_SIZE; + iattributes[niattribs++] = capabilities.getAccumBlueBits(); + } + + int screen = 0; // FIXME: provide way to specify this? + + if (capabilities.getOffscreenFloatingPointBuffers()) { + String glXExtensions = GLX.glXQueryExtensionsString(display, screen); + if (glXExtensions == null || + glXExtensions.indexOf("GLX_NV_float_buffer") < 0) { + throw new GLException("Floating-point pbuffers on X11 currently require NVidia hardware"); + } + iattributes[niattribs++] = GLX.GLX_FLOAT_COMPONENTS_NV; + iattributes[niattribs++] = GL.GL_TRUE; + } + + // FIXME: add FSAA support? Don't want to get into a situation + // where we have to retry the glXChooseFBConfig call if it fails + // due to a lack of an antialiased visual... + + iattributes[niattribs++] = 0; // null-terminate + + int[] nelementsTmp = new int[1]; + GLXFBConfig[] fbConfigs = GLX.glXChooseFBConfig(display, screen, iattributes, 0, nelementsTmp, 0); + if (fbConfigs == null || fbConfigs.length == 0 || fbConfigs[0] == null) { + throw new GLException("pbuffer creation error: glXChooseFBConfig() failed"); + } + int nelements = nelementsTmp[0]; + if (nelements <= 0) { + throw new GLException("pbuffer creation error: couldn't find a suitable frame buffer configuration"); + } + // Note that we currently don't allow selection of anything but + // the first GLXFBConfig in the returned list + GLXFBConfig fbConfig = fbConfigs[0]; + + if (DEBUG) { + System.err.println("Found " + fbConfigs.length + " matching GLXFBConfigs"); + System.err.println("Parameters of default one:"); + System.err.println("render type: 0x" + Integer.toHexString(queryFBConfig(display, fbConfig, GLX.GLX_RENDER_TYPE))); + System.err.println("rgba: " + ((queryFBConfig(display, fbConfig, GLX.GLX_RENDER_TYPE) & GLX.GLX_RGBA_BIT) != 0)); + System.err.println("r: " + queryFBConfig(display, fbConfig, GLX.GLX_RED_SIZE)); + System.err.println("g: " + queryFBConfig(display, fbConfig, GLX.GLX_GREEN_SIZE)); + System.err.println("b: " + queryFBConfig(display, fbConfig, GLX.GLX_BLUE_SIZE)); + System.err.println("a: " + queryFBConfig(display, fbConfig, GLX.GLX_ALPHA_SIZE)); + System.err.println("depth: " + queryFBConfig(display, fbConfig, GLX.GLX_DEPTH_SIZE)); + System.err.println("double buffered: " + queryFBConfig(display, fbConfig, GLX.GLX_DOUBLEBUFFER)); + } + + // Create the p-buffer. + niattribs = 0; + + iattributes[niattribs++] = GLXExt.GLX_PBUFFER_WIDTH; + iattributes[niattribs++] = initWidth; + iattributes[niattribs++] = GLXExt.GLX_PBUFFER_HEIGHT; + iattributes[niattribs++] = initHeight; + + iattributes[niattribs++] = 0; + + long tmpBuffer = GLX.glXCreatePbuffer(display, fbConfig, iattributes, 0); + if (tmpBuffer == 0) { + // FIXME: query X error code for detail error message + throw new GLException("pbuffer creation error: glXCreatePbuffer() failed"); + } + + // Set up instance variables + this.display = display; + drawable = tmpBuffer; + this.fbConfig = fbConfig; + + // Determine the actual width and height we were able to create. + int[] tmp = new int[1]; + GLX.glXQueryDrawable(display, drawable, GLXExt.GLX_WIDTH, tmp, 0); + width = tmp[0]; + GLX.glXQueryDrawable(display, drawable, GLXExt.GLX_HEIGHT, tmp, 0); + height = tmp[0]; + + if (DEBUG) { + System.err.println("Created pbuffer " + width + " x " + height); + } + } finally { + unlockAWT(); + } + } + + public int getFloatingPointMode() { + // Floating-point pbuffers currently require NVidia hardware on X11 + return GLPbuffer.NV_FLOAT; + } + + public GLXFBConfig getFBConfig() { + return fbConfig; + } + + private int queryFBConfig(long display, GLXFBConfig fbConfig, int attrib) { + int[] tmp = new int[1]; + if (GLX.glXGetFBConfigAttrib(display, fbConfig, attrib, tmp, 0) != 0) { + throw new GLException("glXGetFBConfigAttrib failed"); + } + return tmp[0]; + } +} diff --git a/src/classes/com/sun/opengl/impl/x11/X11SunJDKReflection.java b/src/classes/com/sun/opengl/impl/x11/X11SunJDKReflection.java new file mode 100644 index 000000000..0760399ab --- /dev/null +++ b/src/classes/com/sun/opengl/impl/x11/X11SunJDKReflection.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2003 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 com.sun.opengl.impl.x11; + +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.lang.reflect.*; +import java.security.*; + +/** This class encapsulates the reflection routines necessary to peek + inside a few data structures in the AWT implementation on X11 for + the purposes of correctly enumerating the available visuals. */ + +public class X11SunJDKReflection { + private static Class x11GraphicsDeviceClass; + private static Method x11GraphicsDeviceGetScreenMethod; + private static Class x11GraphicsConfigClass; + private static Method x11GraphicsConfigGetVisualMethod; + private static boolean initted; + + static { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + try { + x11GraphicsDeviceClass = Class.forName("sun.awt.X11GraphicsDevice"); + x11GraphicsDeviceGetScreenMethod = x11GraphicsDeviceClass.getDeclaredMethod("getScreen", new Class[] {}); + x11GraphicsDeviceGetScreenMethod.setAccessible(true); + + x11GraphicsConfigClass = Class.forName("sun.awt.X11GraphicsConfig"); + x11GraphicsConfigGetVisualMethod = x11GraphicsConfigClass.getDeclaredMethod("getVisual", new Class[] {}); + x11GraphicsConfigGetVisualMethod.setAccessible(true); + initted = true; + } catch (Exception e) { + // Either not a Sun JDK or the interfaces have changed since 1.4.2 / 1.5 + } + return null; + } + }); + } + + public static int graphicsDeviceGetScreen(GraphicsDevice device) { + if (!initted) { + return 0; + } + + try { + return ((Integer) x11GraphicsDeviceGetScreenMethod.invoke(device, new Object[] {})).intValue(); + } catch (Exception e) { + return 0; + } + } + + public static int graphicsConfigurationGetVisualID(GraphicsConfiguration config) { + if (!initted) { + return 0; + } + + try { + return ((Integer) x11GraphicsConfigGetVisualMethod.invoke(config, new Object[] {})).intValue(); + } catch (Exception e) { + return 0; + } + } +} |