diff options
-rw-r--r-- | make/build.xml | 4 | ||||
-rw-r--r-- | src/net/java/games/jogl/DefaultGLCapabilitiesChooser.java | 17 | ||||
-rw-r--r-- | src/net/java/games/jogl/GLCanvas.java | 8 | ||||
-rw-r--r-- | src/net/java/games/jogl/GLCapabilitiesChooser.java | 9 | ||||
-rw-r--r-- | src/net/java/games/jogl/GLDrawableFactory.java | 83 | ||||
-rw-r--r-- | src/net/java/games/jogl/Version.java | 2 | ||||
-rw-r--r-- | src/net/java/games/jogl/impl/GLContextFactory.java | 14 | ||||
-rw-r--r-- | src/net/java/games/jogl/impl/macosx/MacOSXGLContextFactory.java | 8 | ||||
-rw-r--r-- | src/net/java/games/jogl/impl/windows/WindowsGLContext.java | 5 | ||||
-rw-r--r-- | src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java | 8 | ||||
-rw-r--r-- | src/net/java/games/jogl/impl/x11/X11GLContext.java | 194 | ||||
-rw-r--r-- | src/net/java/games/jogl/impl/x11/X11GLContextFactory.java | 169 | ||||
-rw-r--r-- | src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java | 17 | ||||
-rw-r--r-- | src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java | 5 |
14 files changed, 362 insertions, 181 deletions
diff --git a/make/build.xml b/make/build.xml index 275c7cd31..271e63226 100644 --- a/make/build.xml +++ b/make/build.xml @@ -355,7 +355,7 @@ <property name="c.compiler.includes" value="-I"make/stub_includes/opengl" -I"${java.includes.dir}" -I"${java.includes.dir.platform}" -I"make/stub_includes/cg"" /> <property name="c.linker" value="gcc" /> <property name="c.linker.flags" value="-shared" /> - <property name="c.linker.jogl.libs" value="-L"${java.lib.dir.platform}" -ljawt -lGL -lGLU" /> + <property name="c.linker.jogl.libs" value="-L"${java.lib.dir.platform}" -ljawt -lGL -lGLU -lX11" /> <property name="rootrel.c.linker.jogl.dso" value="${rootrel.obj}/libjogl.so" /> <property name="c.linker.jogl.dso" value="${project.root}/${rootrel.c.linker.jogl.dso}" /> <property name="c.linker.jogl.flags" value="-o ${c.linker.jogl.dso}" /> @@ -380,7 +380,7 @@ <property name="c.compiler.includes" value="-I"make/stub_includes/opengl" -I"${java.includes.dir}" -I"${java.includes.dir.platform}"" /> <property name="c.linker" value="cc" /> <property name="c.linker.flags" value="-G" /> - <property name="c.linker.jogl.libs" value="-L"${java.lib.dir.platform}" -ljawt -lGL -lGLU" /> + <property name="c.linker.jogl.libs" value="-L"${java.lib.dir.platform}" -ljawt -lGL -lGLU -lX11" /> <property name="rootrel.c.linker.jogl.dso" value="${rootrel.obj}/libjogl.so" /> <property name="c.linker.jogl.dso" value="${project.root}/${rootrel.c.linker.jogl.dso}" /> <property name="c.linker.jogl.flags" value="-o ${c.linker.jogl.dso}" /> diff --git a/src/net/java/games/jogl/DefaultGLCapabilitiesChooser.java b/src/net/java/games/jogl/DefaultGLCapabilitiesChooser.java index de7f500b5..8d5ecabc9 100644 --- a/src/net/java/games/jogl/DefaultGLCapabilitiesChooser.java +++ b/src/net/java/games/jogl/DefaultGLCapabilitiesChooser.java @@ -71,13 +71,28 @@ package net.java.games.jogl; than accumulation buffer (including alpha) and stencil buffer depth mismatches. + <LI> If a valid windowSystemRecommendedChoice parameter is + supplied, chooses that instead of using the cross-platform code. + </UL> */ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser { private static final boolean DEBUG = false; - public int chooseCapabilities(GLCapabilities desired, GLCapabilities[] available) { + public int chooseCapabilities(GLCapabilities desired, + GLCapabilities[] available, + int windowSystemRecommendedChoice) { + if (windowSystemRecommendedChoice >= 0 && + windowSystemRecommendedChoice < available.length && + available[windowSystemRecommendedChoice] != null) { + if (DEBUG) { + System.err.println("Choosing window system's recommended choice of " + windowSystemRecommendedChoice); + System.err.println(available[windowSystemRecommendedChoice]); + } + return windowSystemRecommendedChoice; + } + if (DEBUG) { for (int i = 0; i < available.length; i++) { System.err.println("Available " + i + ": " + available[i]); diff --git a/src/net/java/games/jogl/GLCanvas.java b/src/net/java/games/jogl/GLCanvas.java index 9d58930e4..ee33a14c9 100644 --- a/src/net/java/games/jogl/GLCanvas.java +++ b/src/net/java/games/jogl/GLCanvas.java @@ -61,14 +61,6 @@ public final class GLCanvas extends Canvas implements GLDrawable { private GLDrawableHelper drawableHelper = new GLDrawableHelper(); private GLContext context; - GLCanvas(GLCapabilities capabilities, - GLCapabilitiesChooser chooser, - GLDrawable shareWith) { - super(); - context = GLContextFactory.getFactory().createGLContext(this, capabilities, chooser, - GLContextHelper.getContext(shareWith)); - } - GLCanvas(GraphicsConfiguration config, GLCapabilities capabilities, GLCapabilitiesChooser chooser, diff --git a/src/net/java/games/jogl/GLCapabilitiesChooser.java b/src/net/java/games/jogl/GLCapabilitiesChooser.java index 16b0e2b76..78486f1e9 100644 --- a/src/net/java/games/jogl/GLCapabilitiesChooser.java +++ b/src/net/java/games/jogl/GLCapabilitiesChooser.java @@ -47,6 +47,11 @@ public interface GLCapabilitiesChooser { GLCapabilities} most closely matching the desired one from the list of all supported. Some of the entries in the <code>available</code> array may be null; the chooser must - ignore these. */ - public int chooseCapabilities(GLCapabilities desired, GLCapabilities[] available); + ignore these. The <em>windowSystemRecommendedChoice</em> + parameter may be provided to the chooser by the underlying + window system; if this index is valid, it is recommended, but + not necessarily required, that the chooser select that entry. */ + public int chooseCapabilities(GLCapabilities desired, + GLCapabilities[] available, + int windowSystemRecommendedChoice); } diff --git a/src/net/java/games/jogl/GLDrawableFactory.java b/src/net/java/games/jogl/GLDrawableFactory.java index 79109771c..113453d54 100644 --- a/src/net/java/games/jogl/GLDrawableFactory.java +++ b/src/net/java/games/jogl/GLDrawableFactory.java @@ -39,6 +39,10 @@ package net.java.games.jogl; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import net.java.games.jogl.impl.*; + /** <P> Provides a virtual machine- and operating system-independent mechanism for creating {@link net.java.games.jogl.GLCanvas} and {@link net.java.games.jogl.GLJPanel} objects. </P> @@ -74,47 +78,80 @@ public class GLDrawableFactory { return factory; } - /** Creates a {@link GLCanvas} with the specified capabilities using - the default capabilities selection algorithm. */ + /** Creates a {@link GLCanvas} on the default graphics device with + the specified capabilities using the default capabilities + selection algorithm. */ public GLCanvas createGLCanvas(GLCapabilities capabilities) { return createGLCanvas(capabilities, null, null); } - /** Creates a {@link GLCanvas} with the specified capabilities using - the default capabilities selection algorithm. The canvas will - share textures and display lists with the specified {@link - GLDrawable}; the drawable must either be null or have been - fabricated from this factory or by classes in this package. A - null drawable indicates no sharing. */ + /** Creates a {@link GLCanvas} on the default graphics device with + the specified capabilities using the default capabilities + selection algorithm. The canvas will share textures and display + lists with the specified {@link GLDrawable}; the drawable must + either be null or have been fabricated from this factory or by + classes in this package. A null drawable indicates no + sharing. */ public GLCanvas createGLCanvas(GLCapabilities capabilities, GLDrawable shareWith) { return createGLCanvas(capabilities, null, shareWith); } - /** Creates a {@link GLCanvas} with the specified capabilities using - the supplied capabilities selection algorithm. A null chooser is - equivalent to using the {@link DefaultGLCapabilitiesChooser}. */ + /** Creates a {@link GLCanvas} on the default graphics device with + the specified capabilities using the supplied capabilities + selection algorithm. A null chooser is equivalent to using the + {@link DefaultGLCapabilitiesChooser}. */ public GLCanvas createGLCanvas(GLCapabilities capabilities, GLCapabilitiesChooser chooser) { return createGLCanvas(capabilities, chooser, null); } - /** Creates a {@link GLCanvas} with the specified capabilities using - the supplied capabilities selection algorithm. A null chooser is - equivalent to using the {@link DefaultGLCapabilitiesChooser}. - The canvas will share textures and display lists with the - specified {@link GLDrawable}; the drawable must either be null - or have been fabricated from this factory or by classes in this - package. A null drawable indicates no sharing. */ + /** Creates a {@link GLCanvas} on the default graphics device with + the specified capabilities using the supplied capabilities + selection algorithm. A null chooser is equivalent to using the + {@link DefaultGLCapabilitiesChooser}. The canvas will share + textures and display lists with the specified {@link + GLDrawable}; the drawable must either be null or have been + fabricated from this factory or by classes in this package. A + null drawable indicates no sharing. */ public GLCanvas createGLCanvas(GLCapabilities capabilities, GLCapabilitiesChooser chooser, GLDrawable shareWith) { - // FIXME: do we need to select a GraphicsConfiguration here as in - // GL4Java? If so, this class will have to be made abstract and - // we'll have to provide hooks into this package to get at the - // GLCanvas and GLJPanel constructors. + return createGLCanvas(capabilities, chooser, shareWith, null); + } + + /** Creates a {@link GLCanvas} on the specified graphics device with + the specified capabilities using the supplied capabilities + selection algorithm. A null chooser is equivalent to using the + {@link DefaultGLCapabilitiesChooser}. The canvas will share + textures and display lists with the specified {@link + GLDrawable}; the drawable must either be null or have been + fabricated from this factory or by classes in this package. A + null drawable indicates no sharing. A null GraphicsDevice is + equivalent to using that returned from + <code>GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()</code>. */ + public GLCanvas createGLCanvas(GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + GLDrawable shareWith, + GraphicsDevice device) { if (chooser == null) { chooser = new DefaultGLCapabilitiesChooser(); } - return new GLCanvas(capabilities, chooser, shareWith); + if (device == null) { + device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); + } + // The platform-specific GLContextFactory will only provide a + // non-null GraphicsConfiguration on platforms where this is + // necessary (currently only X11, as Windows allows the pixel + // format of the window to be set later and Mac OS X seems to + // handle this very differently than all other platforms). On + // other platforms this method returns null; it is the case (at + // least in the Sun AWT implementation) that this will result in + // equivalent behavior to calling the no-arg super() constructor + // for Canvas. + return new GLCanvas(GLContextFactory.getFactory(). + chooseGraphicsConfiguration(capabilities, chooser, device), + capabilities, + chooser, + shareWith); } /** Creates a {@link GLJPanel} with the specified capabilities using diff --git a/src/net/java/games/jogl/Version.java b/src/net/java/games/jogl/Version.java index fb8c3f3c1..3f2acd88b 100644 --- a/src/net/java/games/jogl/Version.java +++ b/src/net/java/games/jogl/Version.java @@ -89,7 +89,7 @@ public final class Version { /** * Version string of this build. */ - private static final String version = "1.0.0-b01"; + private static final String version = "1.1.0-b01"; /** * Returns the verison string and build number of diff --git a/src/net/java/games/jogl/impl/GLContextFactory.java b/src/net/java/games/jogl/impl/GLContextFactory.java index b686d3543..4aa23c397 100644 --- a/src/net/java/games/jogl/impl/GLContextFactory.java +++ b/src/net/java/games/jogl/impl/GLContextFactory.java @@ -40,6 +40,8 @@ package net.java.games.jogl.impl; import java.awt.Component; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; import net.java.games.jogl.*; public abstract class GLContextFactory { @@ -84,6 +86,18 @@ public abstract class GLContextFactory { return factory; } + /** Selects a GraphicsConfiguration on the specified GraphicsDevice + that matches the desired GLCapabilities according to the + specified GLCapabilitiesChooser's selection algorithm and any + hints provided by the underlying window system. This routine is + currently only implemented on X11, where it is necessary to + choose the desired visual before creating the underlying AWT + Canvas; on other platforms it returns null, yielding the default + behavior. */ + public abstract GraphicsConfiguration chooseGraphicsConfiguration(GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + GraphicsDevice device); + public abstract GLContext createGLContext(Component component, GLCapabilities capabilities, GLCapabilitiesChooser chooser, diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXGLContextFactory.java b/src/net/java/games/jogl/impl/macosx/MacOSXGLContextFactory.java index f3e002c22..3e08c9b67 100644 --- a/src/net/java/games/jogl/impl/macosx/MacOSXGLContextFactory.java +++ b/src/net/java/games/jogl/impl/macosx/MacOSXGLContextFactory.java @@ -40,10 +40,18 @@ package net.java.games.jogl.impl.macosx; import java.awt.Component; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; import net.java.games.jogl.*; import net.java.games.jogl.impl.*; public class MacOSXGLContextFactory extends GLContextFactory { + public GraphicsConfiguration chooseGraphicsConfiguration(GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + GraphicsDevice device) { + return null; + } + public GLContext createGLContext(Component component, GLCapabilities capabilities, GLCapabilitiesChooser chooser, diff --git a/src/net/java/games/jogl/impl/windows/WindowsGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsGLContext.java index 87073e22d..f40d7d3d5 100644 --- a/src/net/java/games/jogl/impl/windows/WindowsGLContext.java +++ b/src/net/java/games/jogl/impl/windows/WindowsGLContext.java @@ -280,7 +280,10 @@ public abstract class WindowsGLContext extends GLContext { availableCaps[i] = pfd2GLCapabilities(pfd); } // Supply information to chooser - pixelFormat = chooser.chooseCapabilities(capabilities, availableCaps); + // FIXME: should provide a hint to the pixel format selection + // algorithm, and should be using wglChoosePixelFormatARB in + // order to do so + pixelFormat = chooser.chooseCapabilities(capabilities, availableCaps, -1); if ((pixelFormat < 0) || (pixelFormat >= numFormats)) { throw new GLException("Invalid result " + pixelFormat + " from GLCapabilitiesChooser (should be between 0 and " + diff --git a/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java b/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java index cfad54025..0c8d54431 100644 --- a/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java +++ b/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java @@ -40,10 +40,18 @@ package net.java.games.jogl.impl.windows; import java.awt.Component; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; import net.java.games.jogl.*; import net.java.games.jogl.impl.*; public class WindowsGLContextFactory extends GLContextFactory { + public GraphicsConfiguration chooseGraphicsConfiguration(GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + GraphicsDevice device) { + return null; + } + public GLContext createGLContext(Component component, GLCapabilities capabilities, GLCapabilitiesChooser chooser, diff --git a/src/net/java/games/jogl/impl/x11/X11GLContext.java b/src/net/java/games/jogl/impl/x11/X11GLContext.java index 3f59b5314..f1de46d5a 100644 --- a/src/net/java/games/jogl/impl/x11/X11GLContext.java +++ b/src/net/java/games/jogl/impl/x11/X11GLContext.java @@ -49,6 +49,7 @@ public abstract class X11GLContext extends GLContext { private static JAWT jawt; protected long display; protected long drawable; + protected long visualID; protected long context; private boolean glXQueryExtensionsStringInitialized; private boolean glXQueryExtensionsStringAvailable; @@ -262,47 +263,76 @@ public abstract class X11GLContext extends GLContext { } protected XVisualInfo chooseVisual() { - int screen = 0; // FIXME: provide way to specify this? - XVisualInfo vis = null; - if (chooser == null) { - // Note: this code path isn't taken any more now that the - // DefaultGLCapabilitiesChooser is present. However, it is being - // left in place for debugging purposes. - int[] attribs = glCapabilities2AttribList(capabilities); - vis = GLX.glXChooseVisual(display, screen, attribs); - if (vis == null) { - throw new GLException("Unable to find matching visual"); - } - if (DEBUG) { - System.err.println("Chosen visual from glXChooseVisual:"); - System.err.println(xvi2GLCapabilities(vis)); - } - } else { + if (!isOffscreen()) { + // 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(); - template.screen(screen); - XVisualInfo[] infos = GLX.XGetVisualInfo(display, GLX.VisualScreenMask, template, count); - if (infos == null) { - throw new GLException("Error while enumerating available XVisualInfos"); - } - GLCapabilities[] caps = new GLCapabilities[infos.length]; - for (int i = 0; i < infos.length; i++) { - caps[i] = xvi2GLCapabilities(infos[i]); - } - int chosen = chooser.chooseCapabilities(capabilities, caps); - 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]); + // FIXME: probably not 64-bit clean + template.visualid((int) visualID); + XVisualInfo[] infos = GLX.XGetVisualInfo(display, GLX.VisualIDMask, template, count); + if (infos == null || infos.length == 0) { + throw new GLException("Error while getting XVisualInfo for visual ID " + visualID); } - 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 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; + if (chooser == null) { + // Note: this code path isn't taken any more now that the + // DefaultGLCapabilitiesChooser is present. However, it is being + // left in place for debugging purposes. + int[] attribs = X11GLContextFactory.glCapabilities2AttribList(capabilities); + vis = GLX.glXChooseVisual(display, screen, attribs); + if (vis == null) { + throw new GLException("Unable to find matching visual"); + } + if (DEBUG) { + System.err.println("Chosen visual from glXChooseVisual:"); + System.err.println(X11GLContextFactory.xvi2GLCapabilities(display, vis)); + } + } else { + int[] count = new int[1]; + XVisualInfo template = new XVisualInfo(); + template.screen(screen); + XVisualInfo[] infos = GLX.XGetVisualInfo(display, GLX.VisualScreenMask, template, count); + if (infos == null) { + throw new GLException("Error while enumerating available XVisualInfos"); + } + GLCapabilities[] caps = new GLCapabilities[infos.length]; + for (int i = 0; i < infos.length; i++) { + caps[i] = X11GLContextFactory.xvi2GLCapabilities(display, infos[i]); + } + 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; } - return vis; } protected long createContext(XVisualInfo vis, boolean onscreen) { @@ -333,96 +363,4 @@ public abstract class X11GLContext extends GLContext { protected long getContext() { return context; } - - protected int[] glCapabilities2AttribList(GLCapabilities caps) { - 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[22]; - 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(); - res[idx++] = 0; - return res; - } - - protected GLCapabilities xvi2GLCapabilities(XVisualInfo info) { - int[] tmp = new int[1]; - int val = glXGetConfig(info, GLX.GLX_USE_GL, tmp); - if (val == 0) { - // Visual does not support OpenGL - return null; - } - val = glXGetConfig(info, GLX.GLX_RGBA, tmp); - if (val == 0) { - // Visual does not support RGBA - return null; - } - GLCapabilities res = new GLCapabilities(); - res.setDoubleBuffered(glXGetConfig(info, GLX.GLX_DOUBLEBUFFER, tmp) != 0); - res.setStereo (glXGetConfig(info, GLX.GLX_STEREO, tmp) != 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(info, GLX.GLX_DEPTH_SIZE, tmp)); - res.setStencilBits (glXGetConfig(info, GLX.GLX_STENCIL_SIZE, tmp)); - res.setRedBits (glXGetConfig(info, GLX.GLX_RED_SIZE, tmp)); - res.setGreenBits (glXGetConfig(info, GLX.GLX_GREEN_SIZE, tmp)); - res.setBlueBits (glXGetConfig(info, GLX.GLX_BLUE_SIZE, tmp)); - res.setAlphaBits (glXGetConfig(info, GLX.GLX_ALPHA_SIZE, tmp)); - res.setAccumRedBits (glXGetConfig(info, GLX.GLX_ACCUM_RED_SIZE, tmp)); - res.setAccumGreenBits(glXGetConfig(info, GLX.GLX_ACCUM_GREEN_SIZE, tmp)); - res.setAccumBlueBits (glXGetConfig(info, GLX.GLX_ACCUM_BLUE_SIZE, tmp)); - res.setAccumAlphaBits(glXGetConfig(info, GLX.GLX_ACCUM_ALPHA_SIZE, tmp)); - return res; - } - - protected 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; - } - } - - protected int glXGetConfig(XVisualInfo info, int attrib, int[] tmp) { - if (display == 0) { - throw new GLException("No display connection"); - } - int res = GLX.glXGetConfig(display, info, attrib, tmp); - if (res != 0) { - throw new GLException("glXGetConfig failed: error code " + glXGetConfigErrorCode(res)); - } - return tmp[0]; - } } diff --git a/src/net/java/games/jogl/impl/x11/X11GLContextFactory.java b/src/net/java/games/jogl/impl/x11/X11GLContextFactory.java index 5a8298753..817a41017 100644 --- a/src/net/java/games/jogl/impl/x11/X11GLContextFactory.java +++ b/src/net/java/games/jogl/impl/x11/X11GLContextFactory.java @@ -40,10 +40,75 @@ package net.java.games.jogl.impl.x11; import java.awt.Component; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; import net.java.games.jogl.*; import net.java.games.jogl.impl.*; public class X11GLContextFactory extends GLContextFactory { + static { + NativeLibLoader.load(); + } + + public GraphicsConfiguration chooseGraphicsConfiguration(GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + GraphicsDevice device) { + 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); + long display = getDisplayConnection(); + XVisualInfo recommendedVis = GLX.glXChooseVisual(display, screen, attribs); + int recommendedIndex = -1; + int[] count = new int[1]; + XVisualInfo template = new XVisualInfo(); + template.screen(screen); + XVisualInfo[] infos = GLX.XGetVisualInfo(display, GLX.VisualScreenMask, template, count); + if (infos == null) { + throw new GLException("Error while enumerating available XVisualInfos"); + } + GLCapabilities[] 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; + } + } + 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 GLContext createGLContext(Component component, GLCapabilities capabilities, GLCapabilitiesChooser chooser, @@ -54,4 +119,108 @@ public class X11GLContextFactory extends GLContextFactory { return new X11OffscreenGLContext(capabilities, chooser, shareWith); } } + + public static GLCapabilities xvi2GLCapabilities(long display, XVisualInfo info) { + int[] tmp = new int[1]; + int val = glXGetConfig(display, info, GLX.GLX_USE_GL, tmp); + if (val == 0) { + // Visual does not support OpenGL + return null; + } + val = glXGetConfig(display, info, GLX.GLX_RGBA, tmp); + if (val == 0) { + // Visual does not support RGBA + return null; + } + GLCapabilities res = new GLCapabilities(); + res.setDoubleBuffered(glXGetConfig(display, info, GLX.GLX_DOUBLEBUFFER, tmp) != 0); + res.setStereo (glXGetConfig(display, info, GLX.GLX_STEREO, tmp) != 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)); + res.setStencilBits (glXGetConfig(display, info, GLX.GLX_STENCIL_SIZE, tmp)); + res.setRedBits (glXGetConfig(display, info, GLX.GLX_RED_SIZE, tmp)); + res.setGreenBits (glXGetConfig(display, info, GLX.GLX_GREEN_SIZE, tmp)); + res.setBlueBits (glXGetConfig(display, info, GLX.GLX_BLUE_SIZE, tmp)); + res.setAlphaBits (glXGetConfig(display, info, GLX.GLX_ALPHA_SIZE, tmp)); + res.setAccumRedBits (glXGetConfig(display, info, GLX.GLX_ACCUM_RED_SIZE, tmp)); + res.setAccumGreenBits(glXGetConfig(display, info, GLX.GLX_ACCUM_GREEN_SIZE, tmp)); + res.setAccumBlueBits (glXGetConfig(display, info, GLX.GLX_ACCUM_BLUE_SIZE, tmp)); + res.setAccumAlphaBits(glXGetConfig(display, info, GLX.GLX_ACCUM_ALPHA_SIZE, tmp)); + return res; + } + + public static int[] glCapabilities2AttribList(GLCapabilities caps) { + 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[22]; + 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(); + res[idx++] = 0; + return res; + } + + // Display connection for use by visual selection algorithm and by all offscreen surfaces + private static long staticDisplay; + public static long getDisplayConnection() { + if (staticDisplay == 0) { + staticDisplay = GLX.XOpenDisplay(null); + if (staticDisplay == 0) { + throw new GLException("Unable to open default display, needed for visual selection and offscreen surface handling"); + } + } + return staticDisplay; + } + + 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) { + if (display == 0) { + throw new GLException("No display connection"); + } + int res = GLX.glXGetConfig(display, info, attrib, tmp); + if (res != 0) { + throw new GLException("glXGetConfig failed: error code " + glXGetConfigErrorCode(res)); + } + return tmp[0]; + } } diff --git a/src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java b/src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java index 7890982f3..8c88b0225 100644 --- a/src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java +++ b/src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java @@ -50,9 +50,6 @@ public class X11OffscreenGLContext extends X11GLContext { private int width; private int height; - // Display connection for use by all offscreen surfaces - private long staticDisplay; - public X11OffscreenGLContext(GLCapabilities capabilities, GLCapabilitiesChooser chooser, GLContext shareWith) { @@ -121,7 +118,7 @@ public class X11OffscreenGLContext extends X11GLContext { } protected synchronized boolean makeCurrent(Runnable initAction) throws GLException { - ensureDisplayOpened(); + display = X11GLContextFactory.getDisplayConnection(); if (pendingOffscreenResize) { if (pendingOffscreenWidth != width || pendingOffscreenHeight != height) { if (context != 0) { @@ -166,17 +163,7 @@ public class X11OffscreenGLContext extends X11GLContext { if (context == 0) { throw new GLException("Unable to create OpenGL context"); } - isDoubleBuffered = (glXGetConfig(vis, GLX.GLX_DOUBLEBUFFER, new int[1]) != 0); - } - - private void ensureDisplayOpened() { - if (staticDisplay == 0) { - staticDisplay = GLX.XOpenDisplay(null); - if (staticDisplay == 0) { - throw new GLException("Unable to open default display, needed for offscreen surface handling"); - } - } - display = staticDisplay; + isDoubleBuffered = (X11GLContextFactory.glXGetConfig(display, vis, GLX.GLX_DOUBLEBUFFER, new int[1]) != 0); } private void destroy() { diff --git a/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java b/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java index 0a38e6fc7..911fc3740 100644 --- a/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java +++ b/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java @@ -175,6 +175,7 @@ public class X11OnscreenGLContext extends X11GLContext { 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); @@ -183,6 +184,9 @@ public class X11OnscreenGLContext extends X11GLContext { ds = null; dsi = null; x11dsi = null; + display = 0; + drawable = 0; + visualID = 0; return false; } return true; @@ -200,6 +204,7 @@ public class X11OnscreenGLContext extends X11GLContext { x11dsi = null; display = 0; drawable = 0; + visualID = 0; } protected void create() { |