diff options
Diffstat (limited to 'src/jogl')
52 files changed, 3482 insertions, 2070 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java index b096f84ae..b1db2974a 100644 --- a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java +++ b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java @@ -33,8 +33,10 @@ import javax.media.opengl.*; import com.jogamp.common.os.Platform; import com.jogamp.common.util.VersionUtil; import com.jogamp.common.util.JogampVersion; +import com.jogamp.common.util.ReflectionUtil; import com.jogamp.nativewindow.NativeWindowVersion; import java.util.jar.Manifest; +import javax.media.nativewindow.AbstractGraphicsDevice; public class JoglVersion extends JogampVersion { @@ -68,15 +70,17 @@ public class JoglVersion extends JogampVersion { } public static StringBuffer getGLInfo(GL gl, StringBuffer sb) { + AbstractGraphicsDevice device = gl.getContext().getGLDrawable().getNativeSurface() + .getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice(); if(null==sb) { sb = new StringBuffer(); } GLContext ctx = gl.getContext(); sb.append(VersionUtil.SEPERATOR).append(Platform.getNewline()); - sb.append("Default Desktop ").append(GLProfile.getDefaultDesktopDevice().getConnection()).append(": ").append(GLProfile.glAvailabilityToString(GLProfile.getDefaultDesktopDevice())); - sb.append(Platform.getNewline()); - sb.append("Default EGL ").append(GLProfile.getDefaultEGLDevice().getConnection()).append(": ").append(GLProfile.glAvailabilityToString(GLProfile.getDefaultEGLDevice())); + sb.append(ReflectionUtil.getBaseName(device.getClass())).append("[type ") + .append(device.getType()).append(", connection ").append(device.getConnection()).append("]: ") + .append(GLProfile.glAvailabilityToString(device)); sb.append(Platform.getNewline()); sb.append("Swap Interval ").append(gl.getSwapInterval()); sb.append(Platform.getNewline()); diff --git a/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java b/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java index c414e6684..5655d1a7a 100644 --- a/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java +++ b/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java @@ -28,13 +28,8 @@ package com.jogamp.opengl.cg; -import com.jogamp.common.os.DynamicLookupHelper; import com.jogamp.common.os.DynamicLibraryBundleInfo; -import com.jogamp.common.os.NativeLibrary; -import com.jogamp.common.os.Platform; import java.util.*; -import java.security.*; -import javax.media.opengl.GLException; public class CgDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo { private static List/*<String>*/ glueLibNames; diff --git a/src/jogl/classes/com/jogamp/opengl/impl/DesktopGLDynamicLookupHelper.java b/src/jogl/classes/com/jogamp/opengl/impl/DesktopGLDynamicLookupHelper.java index 08821910f..77b6ba981 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/DesktopGLDynamicLookupHelper.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/DesktopGLDynamicLookupHelper.java @@ -28,13 +28,8 @@ package com.jogamp.opengl.impl; -import com.jogamp.common.os.DynamicLibraryBundle; -import com.jogamp.common.os.DynamicLibraryBundleInfo; -import com.jogamp.common.os.DynamicLookupHelper; import com.jogamp.common.os.NativeLibrary; import java.util.*; -import java.security.*; -import javax.media.opengl.GLException; public class DesktopGLDynamicLookupHelper extends GLDynamicLookupHelper { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java index cd121979a..c597e5d88 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java @@ -40,16 +40,17 @@ package com.jogamp.opengl.impl; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; + import com.jogamp.common.os.DynamicLookupHelper; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.gluegen.runtime.FunctionAddressResolver; import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLExtensionNames; import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; -import java.nio.ByteBuffer; -import java.util.HashMap; -import java.util.Map; -import java.util.StringTokenizer; + import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; @@ -67,9 +68,9 @@ public abstract class GLContextImpl extends GLContext { /** * Context full qualified name: display_type + display_connection + major + minor + ctp. - * This is the key for all cached ProcAddressTables, etc, to support multi display/device setups. + * This is the key for all cached GL ProcAddressTables, etc, to support multi display/device setups. */ - protected String contextFQN; + private String contextFQN; // Cache of the functions that are available to be called at the current // moment in time @@ -171,9 +172,9 @@ public abstract class GLContextImpl extends GLContext { public GL setGL(GL gl) { if(DEBUG) { - String sgl1 = (null!=this.gl)?this.gl.getClass().toString()+", "+this.gl.toString():"<null>"; - String sgl2 = (null!=gl)?gl.getClass().toString()+", "+gl.toString():"<null>"; - Exception e = new Exception("Info: setGL (OpenGL "+getGLVersion()+"): "+Thread.currentThread()+", "+sgl1+" -> "+sgl2); + String sgl1 = (null!=this.gl)?ReflectionUtil.getBaseName(this.gl.getClass())+", "+this.gl.toString():"<null>"; + String sgl2 = (null!=gl)?ReflectionUtil.getBaseName(gl.getClass())+", "+gl.toString():"<null>"; + Exception e = new Exception("Info: setGL (OpenGL "+getGLVersion()+"): "+Thread.currentThread().getName()+", "+sgl1+" -> "+sgl2); e.printStackTrace(); } this.gl = gl; @@ -505,7 +506,9 @@ public abstract class GLContextImpl extends GLContext { GLContext.getAvailableGLVersionsSet(device)); } - mapGLVersions(device); + if ( !GLContext.getAvailableGLVersionsSet(device) ) { + mapGLVersions(device); + } int reqMajor; if(glp.isGL4()) { @@ -532,20 +535,14 @@ public abstract class GLContextImpl extends GLContext { return _ctx; } - private final void mapGLVersions(AbstractGraphicsDevice device) { - if ( !GLContext.getAvailableGLVersionsSet(device) ) { - synchronized (GLContext.deviceVersionAvailable) { - createContextARBMapVersionsAvailable(4, false /* core */); // GL4 - createContextARBMapVersionsAvailable(4, true /* compat */); // GL4bc - createContextARBMapVersionsAvailable(3, false /* core */); // GL3 - createContextARBMapVersionsAvailable(3, true /* compat */); // GL3bc - createContextARBMapVersionsAvailable(2, true /* compat */); // GL2 - GLContext.setAvailableGLVersionsSet(device); - } - } else { - if(DEBUG) { - System.err.println(getThreadName() + ": no mapping, all versions set "+device.getConnection()); - } + private final void mapGLVersions(AbstractGraphicsDevice device) { + synchronized (GLContext.deviceVersionAvailable) { + createContextARBMapVersionsAvailable(4, false /* core */); // GL4 + createContextARBMapVersionsAvailable(4, true /* compat */); // GL4bc + createContextARBMapVersionsAvailable(3, false /* core */); // GL3 + createContextARBMapVersionsAvailable(3, true /* compat */); // GL3bc + createContextARBMapVersionsAvailable(2, true /* compat */); // GL2 + GLContext.setAvailableGLVersionsSet(device); } } @@ -561,15 +558,9 @@ public abstract class GLContextImpl extends GLContext { ctp |= CTX_PROFILE_COMPAT ; } - // FIXME GL3GL4: - // To avoid OpenGL implementation bugs and raise compatibility - // within JOGL, we map to the proper GL version. - // This may change later when GL3 and GL4 drivers become more mature! - // Bug: To ensure GL profile compatibility within the JOGL application - // Bug: we always try to map against the highest GL version, - // Bug: so the use can always cast to a higher one - // Bug: int majorMax=GLContext.getMaxMajor(); - // Bug: int minorMax=GLContext.getMaxMinor(majorMax); + // To ensure GL profile compatibility within the JOGL application + // we always try to map against the highest GL version, + // so the user can always cast to the highest available one. int majorMax, minorMax; int majorMin, minorMin; int major[] = new int[1]; @@ -810,7 +801,6 @@ public abstract class GLContextImpl extends GLContext { * * @see #setContextVersion */ - protected final void setGLFunctionAvailability(boolean force, int major, int minor, int ctp) { if(null!=this.gl && null!=glProcAddressTable && !force) { return; // already done and not forced @@ -819,6 +809,8 @@ public abstract class GLContextImpl extends GLContext { setGL(createGL(getGLDrawable().getGLProfile())); } + updateGLXProcAddressTable(); + AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); contextFQN = getContextFQN(adevice, major, minor, ctp); @@ -826,8 +818,6 @@ public abstract class GLContextImpl extends GLContext { System.err.println(getThreadName() + ": !!! Context FQN: "+contextFQN); } - updateGLXProcAddressTable(major, minor, ctp); - // // UpdateGLProcAddressTable functionality // @@ -899,7 +889,7 @@ public abstract class GLContextImpl extends GLContext { /** * Updates the platform's 'GLX' function cache */ - protected abstract void updateGLXProcAddressTable(int major, int minor, int ctp); + protected abstract void updateGLXProcAddressTable(); protected boolean hasNativeES2Methods = false; @@ -992,6 +982,14 @@ public abstract class GLContextImpl extends GLContext { return false; } + protected static String getContextFQN(AbstractGraphicsDevice device, int major, int minor, int ctp) { + return device.getUniqueID() + "-" + toHexString(compose8bit(major, minor, ctp, 0)); + } + + protected String getContextFQN() { + return contextFQN; + } + /** Indicates which floating-point pbuffer implementation is in use. Returns one of GLPbuffer.APPLE_FLOAT, GLPbuffer.ATI_FLOAT, or GLPbuffer.NV_FLOAT. */ @@ -1008,6 +1006,7 @@ public abstract class GLContextImpl extends GLContext { /** Only called for offscreen contexts; needed by glReadPixels */ public abstract int getOffscreenContextPixelDataType(); + //---------------------------------------------------------------------- // Helpers for buffer object optimizations diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java index 01e0b8298..6e30f4aa0 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java @@ -165,7 +165,6 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { // fix caps .. GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable(); caps2.setDoubleBuffered(false); // FIXME DBLBUFOFFSCRN - caps2.setOnscreen(false); caps2.setPBuffer(true); capsChosen = caps2; } else { @@ -207,20 +206,8 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { if(null == device) { throw new GLException("No shared device for requested: "+deviceReq); } - GLCapabilitiesImmutable capsChosen; + GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffScreenGLCapabilities(capsRequested, canCreateGLPbuffer(deviceReq)); - if( capsRequested.getDoubleBuffered() || capsRequested.isOnscreen() || capsRequested.isPBuffer()) { - // fix caps .. - GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable(); - caps2.setDoubleBuffered(false); // FIXME DBLBUFOFFSCRN - caps2.setOnscreen(false); - if(caps2.isPBuffer() && !canCreateGLPbuffer(device)) { - caps2.setPBuffer(false); - } - capsChosen = caps2; - } else { - capsChosen = capsRequested; - } device.lock(); try { return createGLDrawable( createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height) ); @@ -233,25 +220,12 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) { - GLCapabilitiesImmutable capsChosen; - AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq); if(null == device) { throw new GLException("No shared device for requested: "+deviceReq); } + GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffScreenGLCapabilities(capsRequested, canCreateGLPbuffer(deviceReq)); - if( capsRequested.getDoubleBuffered() || capsRequested.isOnscreen() || capsRequested.isPBuffer()) { - // fix caps .. - GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable(); - caps2.setDoubleBuffered(false); // FIXME DBLBUFOFFSCRN - caps2.setOnscreen(false); - if(caps2.isPBuffer() && !canCreateGLPbuffer(device)) { - caps2.setPBuffer(false); - } - capsChosen = caps2; - } else { - capsChosen = capsRequested; - } device.lock(); try { return createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height); diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java index 45b04fac1..4aae89bcf 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java @@ -103,6 +103,8 @@ public class GLDrawableHelper { if(0>index) { index = listeners.size(); } + // GLEventListener may be added after context is created, + // hence we earmark initialization for the next display call. listenersToBeInit.add(listener); if(!listenersIter) { // fast path @@ -142,7 +144,6 @@ public class GLDrawableHelper { for (int i=0; i < listeners.size(); i++) { GLEventListener listener = (GLEventListener) listeners.get(i) ; listener.dispose(drawable); - listenersToBeInit.add(listener); } listenersIter = false; } @@ -164,6 +165,12 @@ public class GLDrawableHelper { listenersIter = true; for (int i=0; i < listeners.size(); i++) { GLEventListener listener = (GLEventListener) listeners.get(i) ; + + // If make current ctx, invoked by invokGL(..), results in a new ctx, init gets called. + // This may happen not just for initial setup, but for ctx recreation due to resource change (drawable/window), + // hence the must always be initialized unconditional. + listenersToBeInit.add(listener); + if ( ! init( listener, drawable, false ) ) { throw new GLException("GLEventListener "+listener+" already initialized: "+drawable); } @@ -314,7 +321,7 @@ public class GLDrawableHelper { Runnable initAction) { if(null==context) { if (DEBUG) { - Exception e = new GLException(Thread.currentThread().getName()+"Info: GLDrawableHelper " + this + ".invokeGL(): NULL GLContext"); + Exception e = new GLException(Thread.currentThread().getName()+" Info: GLDrawableHelper " + this + ".invokeGL(): NULL GLContext"); e.printStackTrace(); } return; @@ -323,7 +330,7 @@ public class GLDrawableHelper { if(null==initAction) { // disposal case if(!context.isCreated()) { - throw new GLException("Dispose case (no init action given): Native context must be created: "+context); + throw new GLException(Thread.currentThread().getName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context is not created: "+context); } } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableImpl.java index d7d2836aa..5459d886c 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableImpl.java @@ -146,7 +146,7 @@ public abstract class GLDrawableImpl implements GLDrawable { AbstractGraphicsDevice aDevice = surface.getGraphicsConfiguration().getScreen().getDevice(); if(realizedArg) { if(NativeSurface.LOCK_SURFACE_NOT_READY >= lockSurface()) { - throw new GLException("X11GLXDrawable.setRealized(true): already realized, but surface not ready (lockSurface)"); + throw new GLException("GLDrawableImpl.setRealized(true): already realized, but surface not ready (lockSurface)"); } } else { aDevice.lock(); diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLDynamicLookupHelper.java b/src/jogl/classes/com/jogamp/opengl/impl/GLDynamicLookupHelper.java index e94a9c6e0..c88e96c5e 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLDynamicLookupHelper.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLDynamicLookupHelper.java @@ -29,12 +29,6 @@ package com.jogamp.opengl.impl; import com.jogamp.common.os.DynamicLibraryBundle; -import com.jogamp.common.os.DynamicLibraryBundleInfo; -import com.jogamp.common.os.DynamicLookupHelper; -import com.jogamp.common.os.NativeLibrary; -import java.util.*; -import java.security.*; -import javax.media.opengl.GLException; public class GLDynamicLookupHelper extends DynamicLibraryBundle { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/GLGraphicsConfigurationFactory.java new file mode 100644 index 000000000..62770daf8 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLGraphicsConfigurationFactory.java @@ -0,0 +1,97 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.impl; + +import java.util.List; +import javax.media.nativewindow.CapabilitiesChooser; +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.nativewindow.GraphicsConfigurationFactory; +import javax.media.nativewindow.NativeWindowException; +import javax.media.opengl.DefaultGLCapabilitiesChooser; + +public abstract class GLGraphicsConfigurationFactory extends GraphicsConfigurationFactory { + + protected static int chooseCapabilities(CapabilitiesChooser chooser, CapabilitiesImmutable capsRequested, + List /*<CapabilitiesImmutable>*/ availableCaps, int recommendedIndex) { + if (null == capsRequested) { + throw new NativeWindowException("Null requested capabilities"); + } + if ( 0 == availableCaps.size() ) { + if (DEBUG) { + System.err.println("Empty available capabilities"); + } + return -1; // none available + } + + if(null == chooser && 0 <= recommendedIndex) { + if (DEBUG) { + System.err.println("chooseCapabilities: Using recommendedIndex: idx " + recommendedIndex); + } + return recommendedIndex; + } + int chosenIndex = recommendedIndex; + + if (null == chooser) { + chooser = new DefaultGLCapabilitiesChooser(); + } + + try { + chosenIndex = chooser.chooseCapabilities(capsRequested, availableCaps, recommendedIndex); + if(0 <= chosenIndex) { + if (DEBUG) { + System.err.println("chooseCapabilities: Chosen idx " + chosenIndex); + } + return chosenIndex; + } + } catch (NativeWindowException e) { + if (DEBUG) { + e.printStackTrace(); + } + } + + // keep on going .. + // seek first available one .. + for (chosenIndex = 0; chosenIndex < availableCaps.size() && availableCaps.get(chosenIndex) == null; chosenIndex++) { + // nop + } + if (chosenIndex == availableCaps.size()) { + // give up .. + if (DEBUG) { + System.err.println("chooseCapabilities: Failed .. nothing available, bail out"); + } + return -1; + } + if (DEBUG) { + System.err.println("chooseCapabilities: Fall back to 1st available idx " + chosenIndex); + } + + return chosenIndex; + } + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLGraphicsConfigurationUtil.java b/src/jogl/classes/com/jogamp/opengl/impl/GLGraphicsConfigurationUtil.java new file mode 100644 index 000000000..53d42259a --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLGraphicsConfigurationUtil.java @@ -0,0 +1,133 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.impl; + +import java.util.ArrayList; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; + +public class GLGraphicsConfigurationUtil { + public static final int WINDOW_BIT = 1 << 0; + public static final int BITMAP_BIT = 1 << 1; + public static final int PBUFFER_BIT = 1 << 2; + public static final int ALL_BITS = WINDOW_BIT | BITMAP_BIT | PBUFFER_BIT ; + + public static final StringBuffer winAttributeBits2String(StringBuffer sb, int winattrbits) { + if(null==sb) { + sb = new StringBuffer(); + } + boolean seperator = false; + if( 0 != ( WINDOW_BIT & winattrbits ) ) { + sb.append("WINDOW"); + seperator=true; + } + if( 0 != ( BITMAP_BIT & winattrbits ) ) { + if(seperator) { + sb.append(", "); + } + sb.append("BITMAP"); + seperator=true; + } + if( 0 != ( PBUFFER_BIT & winattrbits ) ) { + if(seperator) { + sb.append(", "); + } + sb.append("PBUFFER"); + } + return sb; + } + + /** + * @return bitmask representing the input boolean in exclusive or logic, ie only one bit will be set + */ + public static final int getWinAttributeBits(boolean isOnscreen, boolean isPBuffer) { + int winattrbits = 0; + if(isOnscreen) { + winattrbits |= WINDOW_BIT; + } else if (!isPBuffer) { + winattrbits |= BITMAP_BIT; + } else { + winattrbits |= PBUFFER_BIT; + } + return winattrbits; + } + + /** + * @see #getWinAttributeBits(boolean, boolean) + */ + public static final int getWinAttributeBits(GLCapabilitiesImmutable caps) { + return getWinAttributeBits(caps.isOnscreen(), caps.isPBuffer()); + } + + public static final boolean addGLCapabilitiesPermutations(ArrayList capsBucket, GLCapabilitiesImmutable temp, int winattrbits) { + int preSize = capsBucket.size(); + if( 0 != ( WINDOW_BIT & winattrbits ) ) { + GLCapabilities cpy = (GLCapabilities) temp.cloneMutable(); + cpy.setOnscreen(true); + capsBucket.add(cpy); + } + if( 0 != ( PBUFFER_BIT & winattrbits ) ) { + GLCapabilities cpy = (GLCapabilities) temp.cloneMutable(); + cpy.setPBuffer(true); + capsBucket.add(cpy); + } + if( 0 != ( BITMAP_BIT & winattrbits ) ) { + GLCapabilities cpy = (GLCapabilities) temp.cloneMutable(); + cpy.setOnscreen(false); + cpy.setPBuffer(false); + capsBucket.add(cpy); + } + return capsBucket.size() > preSize; + } + + public static GLCapabilitiesImmutable fixGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean pbufferAvailable) + { + if( !capsRequested.isOnscreen() ) { + return fixOffScreenGLCapabilities(capsRequested, pbufferAvailable); + } + return capsRequested; + } + public static GLCapabilitiesImmutable fixOffScreenGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean pbufferAvailable) + { + if( capsRequested.getDoubleBuffered() || + capsRequested.isOnscreen() || + ( !pbufferAvailable && capsRequested.isPBuffer() ) ) + { + // fix caps .. + GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable(); + caps2.setDoubleBuffered(false); // FIXME DBLBUFOFFSCRN + caps2.setOnscreen(false); + if(caps2.isPBuffer() && !pbufferAvailable) { + caps2.setPBuffer(false); + } + return caps2; + } + return capsRequested; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLJNILibLoader.java b/src/jogl/classes/com/jogamp/opengl/impl/GLJNILibLoader.java deleted file mode 100644 index 1daf3358b..000000000 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLJNILibLoader.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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.jogamp.opengl.impl; - -// FIXME: refactor Java SE dependencies -//import java.awt.Toolkit; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.HashSet; -import com.jogamp.common.jvm.JNILibLoaderBase; - -public class GLJNILibLoader extends JNILibLoaderBase { - public static void loadNEWT() { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - loadLibrary("newt", nativeOSPreload, true); - return null; - } - }); - } - - private static final String[] nativeOSPreload = { "nativewindow_x11" }; -} - diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java index 558cda106..5119f5360 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java @@ -104,16 +104,18 @@ public class GLPbufferImpl implements GLPbuffer { DisposeAction disposeAction = new DisposeAction(); public void destroy() { - if (null != context) { - try { - drawableHelper.invokeGL(pbufferDrawable, context, disposeAction, null); - } catch (GLException gle) { - gle.printStackTrace(); + if(pbufferDrawable.isRealized()) { + if (null != context && context.isCreated()) { + try { + drawableHelper.invokeGL(pbufferDrawable, context, disposeAction, null); + } catch (GLException gle) { + gle.printStackTrace(); + } + context.destroy(); + // drawableHelper.reset(); } - drawableHelper.reset(); - context.destroy(); + pbufferDrawable.destroy(); } - pbufferDrawable.destroy(); } public void setSize(int width, int height) { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/SharedResourceRunner.java b/src/jogl/classes/com/jogamp/opengl/impl/SharedResourceRunner.java new file mode 100644 index 000000000..765c6620d --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/SharedResourceRunner.java @@ -0,0 +1,249 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.impl; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsScreen; + +public class SharedResourceRunner implements Runnable { + protected static final boolean DEBUG = GLDrawableImpl.DEBUG; + + public static interface Resource { + AbstractGraphicsDevice getDevice(); + AbstractGraphicsScreen getScreen(); + GLDrawableImpl getDrawable(); + GLContextImpl getContext(); + } + + public static interface Implementation { + Resource createSharedResource(String connection); + void releaseSharedResource(Resource shared); + void clear(); + + Resource mapPut(String connection, Resource resource); + Resource mapGet(String connection); + Collection/*<Resource>*/ mapValues(); + } + + Implementation impl = null; + + boolean ready = false; + boolean released = false; + boolean shouldRelease = false; + String initConnection = null; + String releaseConnection = null; + + HashSet devicesTried = new HashSet(); + + private boolean getDeviceTried(String connection) { + synchronized (devicesTried) { + return devicesTried.contains(connection); + } + } + private void addDeviceTried(String connection) { + synchronized (devicesTried) { + devicesTried.add(connection); + } + } + private void removeDeviceTried(String connection) { + synchronized (devicesTried) { + devicesTried.remove(connection); + } + } + + public SharedResourceRunner(Implementation impl) { + this.impl = impl; + } + + public SharedResourceRunner.Resource getShared(AbstractGraphicsDevice device) { + String connection = device.getConnection(); + return impl.mapGet(connection); + } + + public SharedResourceRunner.Resource getOrCreateShared(AbstractGraphicsDevice device) { + String connection = device.getConnection(); + SharedResourceRunner.Resource sr = impl.mapGet(connection); + + if (null == sr && !getDeviceTried(connection)) { + addDeviceTried(connection); + if (DEBUG) { + System.err.println("getOrCreateShared() " + connection + ": trying"); + } + doAndWait(connection, null); + sr = impl.mapGet(connection); + if (DEBUG) { + Throwable t = new Throwable("getOrCreateSharedl() " + connection + ": done"); + t.printStackTrace(); + } + } + return sr; + } + + public SharedResourceRunner.Resource releaseShared(AbstractGraphicsDevice device) { + String connection = device.getConnection(); + SharedResourceRunner.Resource sr = impl.mapGet(connection); + + if (null != sr) { + removeDeviceTried(connection); + if (DEBUG) { + System.err.println("releaseShared() " + connection + ": trying"); + } + doAndWait(null, connection); + if (DEBUG) { + Throwable t = new Throwable("releaseSharedl() " + connection + ": done"); + t.printStackTrace(); + } + } + return sr; + } + + private final void doAndWait(String initConnection, String releaseConnection) { + // wait until thread becomes ready to init new device, + // pass the device and release the sync + String threadName = Thread.currentThread().getName(); + if (DEBUG) { + System.err.println(threadName + " doAndWait START init: " + initConnection + ", release: "+releaseConnection); + } + synchronized (this) { + while (!ready) { + try { + this.wait(); + } catch (InterruptedException ex) { + } + } + if (DEBUG) { + System.err.println(threadName + " initializeAndWait set command init: " + initConnection + ", release: "+releaseConnection); + } + this.initConnection = initConnection; + this.releaseConnection = releaseConnection; + this.notifyAll(); + + // wait until thread has init/released the device + while (!ready || null != this.initConnection || null != this.releaseConnection) { + try { + this.wait(); + } catch (InterruptedException ex) { + } + } + if (DEBUG) { + System.err.println(threadName + " initializeAndWait END init: " + initConnection + ", release: "+releaseConnection); + } + } + // done + } + + public final void releaseAndWait() { + synchronized (this) { + shouldRelease = true; + this.notifyAll(); + + while (!released) { + try { + this.wait(); + } catch (InterruptedException ex) { + } + } + } + } + + public final void run() { + String threadName = Thread.currentThread().getName(); + + if (DEBUG) { + System.err.println(threadName + " STARTED"); + } + + synchronized (this) { + while (!shouldRelease) { + try { + // wait for stop or init + ready = true; + if (DEBUG) { + System.err.println(threadName + " -> ready"); + } + notifyAll(); + this.wait(); + } catch (InterruptedException ex) { } + ready = false; + + if (!shouldRelease) { + if (DEBUG) { + System.err.println(threadName + " woke up for device connection init: " + initConnection + + ", release: " + releaseConnection); + } + if(null != initConnection) { + if (DEBUG) { + System.err.println(threadName + " create Shared for: " + initConnection); + } + Resource sr = impl.createSharedResource(initConnection); + if (null != sr) { + impl.mapPut(initConnection, sr); + } + } + if(null != releaseConnection) { + if (DEBUG) { + System.err.println(threadName + " release Shared for: " + releaseConnection); + } + Resource sr = impl.mapPut(releaseConnection, null); + if (null != sr) { + impl.releaseSharedResource(sr); + } + } + } + initConnection = null; + releaseConnection = null; + } + + if (DEBUG) { + System.err.println(threadName + " release START"); + } + + releaseSharedResources(); + + if (DEBUG) { + System.err.println(threadName + " release END"); + } + + released = true; + ready = false; + notifyAll(); + } + } + + private void releaseSharedResources() { + Collection/*<Resource>*/ sharedResources = impl.mapValues(); + for (Iterator iter = sharedResources.iterator(); iter.hasNext();) { + Resource sr = (Resource) iter.next(); + impl.releaseSharedResource(sr); + } + impl.clear(); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTUtil.java b/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTUtil.java index 36c0a3250..081d1f9b3 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTUtil.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTUtil.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -38,8 +39,6 @@ package com.jogamp.opengl.impl.awt; import com.jogamp.nativewindow.impl.jawt.*; -import com.jogamp.opengl.impl.*; - import javax.media.opengl.*; import java.lang.reflect.*; diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLContext.java index 246814537..107d7fbbb 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLContext.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLContext.java @@ -41,6 +41,8 @@ import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; import java.nio.*; import java.util.*; +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; public abstract class EGLContext extends GLContextImpl { private boolean eglQueryStringInitialized; @@ -191,21 +193,24 @@ public abstract class EGLContext extends GLContextImpl { return true; } - protected final void updateGLXProcAddressTable(int major, int minor, int ctp) { + protected final void updateGLXProcAddressTable() { + AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); + String key = adevice.getUniqueID(); if (DEBUG) { - System.err.println(getThreadName() + ": !!! Initializing EGL extension address table"); + System.err.println(getThreadName() + ": !!! Initializing EGLextension address table: "+key); } eglQueryStringInitialized = false; eglQueryStringAvailable = false; EGLExtProcAddressTable table = null; synchronized(mappedContextTypeObjectLock) { - table = (EGLExtProcAddressTable) mappedGLXProcAddress.get( contextFQN ); + table = (EGLExtProcAddressTable) mappedGLXProcAddress.get( key ); } if(null != table) { eglExtProcAddressTable = table; if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext EGL ProcAddressTable reusing key("+contextFQN+") -> "+table.hashCode()); + System.err.println(getThreadName() + ": !!! GLContext EGL ProcAddressTable reusing key("+key+") -> "+table.hashCode()); } } else { if (eglExtProcAddressTable == null) { @@ -215,9 +220,9 @@ public abstract class EGLContext extends GLContextImpl { } resetProcAddressTable(getEGLExtProcAddressTable()); synchronized(mappedContextTypeObjectLock) { - mappedGLXProcAddress.put(contextFQN, getEGLExtProcAddressTable()); + mappedGLXProcAddress.put(key, getEGLExtProcAddressTable()); if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext EGL ProcAddressTable mapping key("+contextFQN+") -> "+getEGLExtProcAddressTable().hashCode()); + System.err.println(getThreadName() + ": !!! GLContext EGL ProcAddressTable mapping key("+key+") -> "+getEGLExtProcAddressTable().hashCode()); } } } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawableFactory.java index f451cb9bc..c32f2f22c 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawableFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawableFactory.java @@ -37,13 +37,16 @@ package com.jogamp.opengl.impl.egl; import javax.media.nativewindow.*; +import javax.media.nativewindow.egl.EGLGraphicsDevice; import javax.media.opengl.*; + import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.util.*; import com.jogamp.opengl.impl.*; import com.jogamp.nativewindow.impl.ProxySurface; + import java.util.HashMap; -import javax.media.nativewindow.egl.EGLGraphicsDevice; +import java.util.List; public class EGLDrawableFactory extends GLDrawableFactoryImpl { @@ -166,6 +169,10 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { return null; } + SharedResource getOrCreateSharedResource(AbstractGraphicsDevice device) { + return (SharedResource) getOrCreateShared(device); + } + public GLDynamicLookupHelper getGLDynamicLookupHelper(int esProfile) { if (2==esProfile) { if(null==eglES2DynamicLookupHelper) { @@ -184,6 +191,10 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { protected final void shutdownInstance() {} + protected List/*GLCapabilitiesImmutable*/ getAvailableCapabilitiesImpl(AbstractGraphicsDevice device) { + return EGLGraphicsConfigurationFactory.getAvailableCapabilities(this, device); + } + protected GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target) { if (target == null) { throw new IllegalArgumentException("Null target"); diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGLCapabilities.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGLCapabilities.java new file mode 100644 index 000000000..db6d485e3 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGLCapabilities.java @@ -0,0 +1,96 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.impl.egl; + +import java.util.Comparator; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; + +public class EGLGLCapabilities extends GLCapabilities { + long eglcfg; + int eglcfgid; + + /** Comparing EGLConfig ID only */ + public static class EglCfgIDComparator implements Comparator { + + public int compare(Object o1, Object o2) { + if ( ! ( o1 instanceof EGLGLCapabilities ) ) { + Class c = (null != o1) ? o1.getClass() : null ; + throw new ClassCastException("arg1 not a EGLGLCapabilities object: " + c); + } + if ( ! ( o2 instanceof EGLGLCapabilities ) ) { + Class c = (null != o2) ? o2.getClass() : null ; + throw new ClassCastException("arg2 not a EGLGLCapabilities object: " + c); + } + + final EGLGLCapabilities caps1 = (EGLGLCapabilities) o1; + final long id1 = caps1.getEGLConfigID(); + + final EGLGLCapabilities caps2 = (EGLGLCapabilities) o2; + final long id2 = caps2.getEGLConfigID(); + + if(id1 > id2) { + return 1; + } else if(id1 < id2) { + return -1; + } + return 0; + } + } + + public EGLGLCapabilities(long eglcfg, int eglcfgid, GLProfile glp) { + super(glp); + this.eglcfg = eglcfg; + this.eglcfgid = eglcfgid; + } + + public Object cloneMutable() { + return clone(); + } + + public Object clone() { + try { + return super.clone(); + } catch (RuntimeException e) { + throw new GLException(e); + } + } + + final public long getEGLConfig() { return eglcfg; } + final public int getEGLConfigID() { return eglcfgid; } + + public StringBuffer toString(StringBuffer sink) { + if(null == sink) { + sink = new StringBuffer(); + } + sink.append("0x").append(Long.toHexString(eglcfgid)).append(": "); + return super.toString(sink); + } +}
\ No newline at end of file diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfiguration.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfiguration.java index fd37c1f6d..eca324046 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfiguration.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfiguration.java @@ -36,30 +36,29 @@ package com.jogamp.opengl.impl.egl; -import com.jogamp.common.nio.PointerBuffer; +import java.util.ArrayList; import javax.media.nativewindow.*; import javax.media.nativewindow.egl.*; import javax.media.opengl.*; +import com.jogamp.common.nio.PointerBuffer; +import com.jogamp.common.util.ReflectionUtil; import com.jogamp.opengl.impl.*; public class EGLGraphicsConfiguration extends DefaultGraphicsConfiguration implements Cloneable { protected static final boolean DEBUG = Debug.debug("GraphicsConfiguration"); - public long getNativeConfig() { - return config; + public final long getNativeConfig() { + return ((EGLGLCapabilities)capabilitiesChosen).getEGLConfig(); } - public int getNativeConfigID() { - return configID; + public final int getNativeConfigID() { + return ((EGLGLCapabilities)capabilitiesChosen).getEGLConfigID(); } EGLGraphicsConfiguration(AbstractGraphicsScreen absScreen, - GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, - long cfg, int cfgID) { + EGLGLCapabilities capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) { super(absScreen, capsChosen, capsRequested); this.chooser = chooser; - config = cfg; - configID = cfgID; } public static EGLGraphicsConfiguration create(GLCapabilitiesImmutable capsRequested, AbstractGraphicsScreen absScreen, int cfgID) { @@ -73,8 +72,8 @@ public class EGLGraphicsConfiguration extends DefaultGraphicsConfiguration imple } GLProfile glp = capsRequested.getGLProfile(); long cfg = EGLConfigId2EGLConfig(glp, dpy, cfgID); - GLCapabilitiesImmutable caps = EGLConfig2Capabilities(glp, dpy, cfg, false, capsRequested.isOnscreen(), capsRequested.isPBuffer()); - return new EGLGraphicsConfiguration(absScreen, caps, capsRequested, new DefaultGLCapabilitiesChooser(), cfg, cfgID); + EGLGLCapabilities caps = EGLConfig2Capabilities(glp, dpy, cfg, false, capsRequested.isOnscreen(), capsRequested.isPBuffer()); + return new EGLGraphicsConfiguration(absScreen, caps, capsRequested, new DefaultGLCapabilitiesChooser()); } public Object clone() { @@ -88,8 +87,6 @@ public class EGLGraphicsConfiguration extends DefaultGraphicsConfiguration imple if(null!=newConfig) { // FIXME: setScreen( ... ); setChosenCapabilities(newConfig.getChosenCapabilities()); - config = newConfig.getNativeConfig(); - configID = newConfig.getNativeConfigID(); if(DEBUG) { System.err.println("!!! updateGraphicsConfiguration: "+this); } @@ -115,27 +112,61 @@ public class EGLGraphicsConfiguration extends DefaultGraphicsConfiguration imple return configs.get(0); } - static boolean EGLConfigDrawableTypeVerify(int val, boolean onscreen, boolean usePBuffer) { - boolean res; + static int EGLConfigDrawableTypeBits(final long display, final long config) { + int val = 0; - if ( onscreen ) { - res = ( 0 != (val & EGL.EGL_WINDOW_BIT) ) ; - } else { - if ( usePBuffer ) { - res = ( 0 != (val & EGL.EGL_PBUFFER_BIT) ) ; - } else { - res = ( 0 != (val & EGL.EGL_PIXMAP_BIT) ) ; - } + int[] stype = new int[1]; + if(! EGL.eglGetConfigAttrib(display, config, EGL.EGL_SURFACE_TYPE, stype, 0)) { + throw new GLException("Could not determine EGL_SURFACE_TYPE !!!"); + } + + if ( 0 != ( stype[0] & EGL.EGL_WINDOW_BIT ) ) { + val |= GLGraphicsConfigurationUtil.WINDOW_BIT; + } + if ( 0 != ( stype[0] & EGL.EGL_PIXMAP_BIT ) ) { + val |= GLGraphicsConfigurationUtil.BITMAP_BIT; + } + if ( 0 != ( stype[0] & EGL.EGL_PBUFFER_BIT ) ) { + val |= GLGraphicsConfigurationUtil.PBUFFER_BIT; } - return res; + return val; } - public static GLCapabilitiesImmutable EGLConfig2Capabilities(GLProfile glp, long display, long config, + public static EGLGLCapabilities EGLConfig2Capabilities(GLProfile glp, long display, long config, boolean relaxed, boolean onscreen, boolean usePBuffer) { - GLCapabilities caps = new GLCapabilities(glp); + ArrayList bucket = new ArrayList(); + final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer); + if( EGLConfig2Capabilities(bucket, glp, display, config, winattrmask) ) { + return (EGLGLCapabilities) bucket.get(0); + } else if ( relaxed && EGLConfig2Capabilities(bucket, glp, display, config, GLGraphicsConfigurationUtil.ALL_BITS) ) { + return (EGLGLCapabilities) bucket.get(0); + } + return null; + } + + public static boolean EGLConfig2Capabilities(ArrayList capsBucket, + GLProfile glp, long display, long config, + int winattrmask) { + final int allDrawableTypeBits = EGLConfigDrawableTypeBits(display, config); + final int drawableTypeBits = winattrmask & allDrawableTypeBits; + + if( 0 == drawableTypeBits ) { + return false; + } + int[] val = new int[1]; + // get the configID + if(!EGL.eglGetConfigAttrib(display, config, EGL.EGL_CONFIG_ID, val, 0)) { + if(DEBUG) { + // FIXME: this happens on a ATI PC Emulation .. + System.err.println("EGL couldn't retrieve ConfigID for config "+toHexString(config)+", error "+toHexString(EGL.eglGetError())); + } + return false; + } + GLCapabilities caps = new EGLGLCapabilities(config, val[0], glp); + // Read the actual configuration into the choosen caps if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_RED_SIZE, val, 0)) { caps.setRedBits(val[0]); @@ -177,26 +208,7 @@ public class EGLGraphicsConfiguration extends DefaultGraphicsConfiguration imple caps.setTransparentAlphaValue(val[0]==EGL.EGL_DONT_CARE?-1:val[0]); } */ } - if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_SURFACE_TYPE, val, 0)) { - if(EGLConfigDrawableTypeVerify(val[0], onscreen, usePBuffer)) { - caps.setDoubleBuffered(onscreen); - caps.setOnscreen(onscreen); - caps.setPBuffer(usePBuffer); - } else if(relaxed) { - caps.setDoubleBuffered( 0 != (val[0] & EGL.EGL_WINDOW_BIT) ); - caps.setOnscreen( 0 != (val[0] & EGL.EGL_WINDOW_BIT) ); - caps.setPBuffer ( 0 != (val[0] & EGL.EGL_PBUFFER_BIT) ); - } else { - if(DEBUG) { - System.err.println("EGL_SURFACE_TYPE does not match: req(onscrn "+onscreen+", pbuffer "+usePBuffer+"), got(onscreen "+( 0 != (val[0] & EGL.EGL_WINDOW_BIT) )+", pbuffer "+( 0 != (val[0] & EGL.EGL_PBUFFER_BIT) )+", pixmap "+( 0 != (val[0] & EGL.EGL_PIXMAP_BIT) )+")"); - } - return null; - } - } else { - throw new GLException("Could not determine EGL_SURFACE_TYPE !!!"); - } - - return caps; + return GLGraphicsConfigurationUtil.addGLCapabilitiesPermutations(capsBucket, caps, drawableTypeBits ); } public static int[] GLCapabilities2AttribList(GLCapabilitiesImmutable caps) { @@ -288,7 +300,7 @@ public class EGLGraphicsConfiguration extends DefaultGraphicsConfiguration imple } public String toString() { - return getClass().toString()+"["+getScreen()+", eglConfigID 0x"+Integer.toHexString(configID)+ + return ReflectionUtil.getBaseName(getClass())+"["+getScreen()+", eglConfigID "+toHexString(getNativeConfigID())+ ",\n\trequested " + getRequestedCapabilities()+ ",\n\tchosen " + getChosenCapabilities()+ "]"; @@ -296,7 +308,5 @@ public class EGLGraphicsConfiguration extends DefaultGraphicsConfiguration imple } private GLCapabilitiesChooser chooser; - private long config; - private int configID; } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfigurationFactory.java index fc2416cb9..3e3d4f964 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfigurationFactory.java @@ -33,7 +33,6 @@ package com.jogamp.opengl.impl.egl; -import java.io.PrintStream; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.AbstractGraphicsScreen; @@ -41,17 +40,22 @@ import javax.media.nativewindow.CapabilitiesChooser; import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.DefaultGraphicsScreen; import javax.media.nativewindow.GraphicsConfigurationFactory; -import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.egl.EGLGraphicsDevice; -import javax.media.opengl.DefaultGLCapabilitiesChooser; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import javax.media.opengl.GLDrawableFactory; import com.jogamp.common.nio.PointerBuffer; +import com.jogamp.opengl.impl.GLGraphicsConfigurationFactory; +import com.jogamp.opengl.impl.GLGraphicsConfigurationUtil; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.io.PrintStream; /** Subclass of GraphicsConfigurationFactory used when non-AWT tookits @@ -59,8 +63,9 @@ import com.jogamp.common.nio.PointerBuffer; to this one to change the accepted and returned types of the GraphicsDevice and GraphicsConfiguration abstractions. */ -public class EGLGraphicsConfigurationFactory extends GraphicsConfigurationFactory { +public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory { protected static final boolean DEBUG = GraphicsConfigurationFactory.DEBUG || com.jogamp.opengl.impl.Debug.debug("EGL"); + static EGLGLCapabilities.EglCfgIDComparator EglCfgIDComparator = new EGLGLCapabilities.EglCfgIDComparator(); EGLGraphicsConfigurationFactory() { // become the selector for KD/EGL .. @@ -93,6 +98,41 @@ public class EGLGraphicsConfigurationFactory extends GraphicsConfigurationFactor absScreen); } + protected static List/*<EGLGLCapabilities>*/ getAvailableCapabilities(EGLDrawableFactory factory, AbstractGraphicsDevice device) { + EGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device); + if(null == sharedResource) { + throw new GLException("Shared resource for device n/a: "+device); + } + EGLGraphicsDevice eglDevice = sharedResource.getDevice(); + long eglDisplay = eglDevice.getHandle(); + + List/*<EGLGLCapabilities>*/ availableCaps = null; + int[] maxConfigs = new int[1]; + + if(!EGL.eglGetConfigs(eglDisplay, null, 0, maxConfigs, 0)) { + throw new GLException("Graphics configuration get maxConfigs (eglGetConfigs) call failed, error "+toHexString(EGL.eglGetError())); + } + if(0 == maxConfigs[0]) { + throw new GLException("Graphics configuration get maxConfigs (eglGetConfigs) no configs"); + } + + PointerBuffer configs = PointerBuffer.allocateDirect(maxConfigs[0]); + int[] numConfigs = new int[1]; + + if(!EGL.eglGetConfigs(eglDisplay, configs, configs.capacity(), numConfigs, 0)) { + throw new GLException("Graphics configuration get all configs (eglGetConfigs) call failed, error "+toHexString(EGL.eglGetError())); + } + if (numConfigs[0] > 0) { + GLProfile glp = GLProfile.getDefault(device); + availableCaps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs[0], GLGraphicsConfigurationUtil.ALL_BITS); + if( null != availableCaps ) { + Collections.sort(availableCaps, EglCfgIDComparator); + } + } + + return availableCaps; + } + private static EGLGraphicsConfiguration chooseGraphicsConfigurationStatic(GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsReq, GLCapabilitiesChooser chooser, @@ -100,7 +140,6 @@ public class EGLGraphicsConfigurationFactory extends GraphicsConfigurationFactor if (capsChosen == null) { capsChosen = new GLCapabilities(null); } - GLProfile glp = capsChosen.getGLProfile(); if(null==absScreen) { throw new GLException("Null AbstractGraphicsScreen"); @@ -116,12 +155,10 @@ public class EGLGraphicsConfigurationFactory extends GraphicsConfigurationFactor throw new GLException("Invalid EGL display: "+absDevice); } - if(!capsChosen.isOnscreen() && capsChosen.getDoubleBuffered()) { - // OFFSCREEN !DOUBLE_BUFFER // FIXME DBLBUFOFFSCRN - GLCapabilities caps2 = (GLCapabilities) capsChosen.cloneMutable(); - caps2.setDoubleBuffered(false); - capsChosen = caps2; - } + EGLDrawableFactory factory = (EGLDrawableFactory) GLDrawableFactory.getEGLFactory(); + capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, factory.canCreateGLPbuffer(absDevice) ); + + GLProfile glp = capsChosen.getGLProfile(); EGLGraphicsConfiguration res = eglChooseConfig(eglDisplay, capsChosen, capsReq, chooser, absScreen); if(null!=res) { @@ -131,43 +168,6 @@ public class EGLGraphicsConfigurationFactory extends GraphicsConfigurationFactor System.err.println("eglChooseConfig failed with given capabilities "+capsChosen); } - if (chooser == null) { - chooser = new DefaultGLCapabilitiesChooser(); - } - - PointerBuffer configs = PointerBuffer.allocateDirect(10); - int[] numConfigs = new int[1]; - - if(!EGL.eglGetConfigs(eglDisplay, configs, configs.capacity(), numConfigs, 0)) { - throw new GLException("Graphics configuration fetch (eglGetConfigs) failed"); - } - if (numConfigs[0] == 0) { - throw new GLException("Graphics configuration fetch (eglGetConfigs) - no EGLConfig found"); - } - GLCapabilitiesImmutable[] caps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs[0], - capsChosen.isOnscreen(), capsChosen.isPBuffer()); - if(DEBUG) { - System.err.println("EGL Get Configs: "+numConfigs[0]+", Caps "+caps.length); - printCaps("eglGetConfigs", caps, System.err); - } - int chosen = -1; - try { - chosen = chooser.chooseCapabilities(capsChosen, caps, -1); - } catch (NativeWindowException e) { throw new GLException(e); } - if(chosen<0) { - throw new GLException("Graphics configuration chooser failed"); - } - if(DEBUG) { - System.err.println("Chosen "+caps[chosen]); - } - res = eglChooseConfig(eglDisplay, caps[chosen], capsReq, chooser, absScreen); - if(null!=res) { - return res; - } - if(DEBUG) { - System.err.println("eglChooseConfig failed with eglGetConfig/choosen capabilities "+caps[chosen]); - } - // Last try .. add a fixed embedded profile [ATI, Nokia, Intel, ..] // // rgb888 - d16, s4 @@ -221,73 +221,100 @@ public class EGLGraphicsConfigurationFactory extends GraphicsConfigurationFactor } static EGLGraphicsConfiguration eglChooseConfig(long eglDisplay, - GLCapabilitiesImmutable capsChosen0, GLCapabilitiesImmutable capsRequested, + GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) { - GLProfile glp = capsChosen0.getGLProfile(); - int[] attrs = EGLGraphicsConfiguration.GLCapabilities2AttribList(capsChosen0); - PointerBuffer configs = PointerBuffer.allocateDirect(1); + GLProfile glp = capsChosen.getGLProfile(); + boolean onscreen = capsChosen.isOnscreen(); + boolean usePBuffer = capsChosen.isPBuffer(); + List/*<EGLGLCapabilities>*/ availableCaps = null; + final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer); + int recommendedIndex = -1; + long recommendedEGLConfig = -1; + int[] maxConfigs = new int[1]; + + if(!EGL.eglGetConfigs(eglDisplay, null, 0, maxConfigs, 0)) { + throw new GLException("Graphics configuration get maxConfigs (eglGetConfigs) call failed, error "+toHexString(EGL.eglGetError())); + } + if(0 == maxConfigs[0]) { + throw new GLException("Graphics configuration get maxConfigs (eglGetConfigs) no configs"); + } + if (DEBUG) { + System.err.println("!!! eglChooseConfig maxConfigs: "+maxConfigs[0]); + } + + int[] attrs = EGLGraphicsConfiguration.GLCapabilities2AttribList(capsChosen); + PointerBuffer configs = PointerBuffer.allocateDirect(maxConfigs[0]); int[] numConfigs = new int[1]; + + // 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice if (!EGL.eglChooseConfig(eglDisplay, attrs, 0, configs, configs.capacity(), numConfigs, 0)) { - throw new GLException("Graphics configuration selection (eglChooseConfig) failed for "+capsChosen0); + throw new GLException("Graphics configuration selection (eglChooseConfig) failed for "+capsChosen+", error "+toHexString(EGL.eglGetError())); } if (numConfigs[0] > 0) { - if(DEBUG) { - GLCapabilitiesImmutable[] caps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs[0], - capsChosen0.isOnscreen(), capsChosen0.isPBuffer()); - System.err.println("EGL Choose Configs: "+numConfigs[0]+", Caps "+caps.length); - printCaps("eglChooseConfig", caps, System.err); - } - int[] val = new int[1]; - // get the configID - if(!EGL.eglGetConfigAttrib(eglDisplay, configs.get(0), EGL.EGL_CONFIG_ID, val, 0)) { - if(DEBUG) { - // FIXME: this happens on a ATI PC Emulation .. - System.err.println("EGL couldn't retrieve ConfigID for already chosen eglConfig "+capsChosen0+", error 0x"+Integer.toHexString(EGL.eglGetError())); + availableCaps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs[0], winattrmask); + if(availableCaps.size() > 0) { + recommendedEGLConfig = configs.get(0); + recommendedIndex = 0; + if (DEBUG) { + System.err.println("!!! eglChooseConfig recommended fbcfg " + toHexString(recommendedEGLConfig) + ", idx " + recommendedIndex); + System.err.println("!!! user caps " + capsChosen); + System.err.println("!!! fbcfg caps " + availableCaps.get(recommendedIndex)); } - return null; + } else if (DEBUG) { + System.err.println("!!! eglChooseConfig no caps for recommended fbcfg " + toHexString(configs.get(0))); + System.err.println("!!! user caps " + capsChosen); } - GLCapabilitiesImmutable capsChosen1 = EGLGraphicsConfiguration.EGLConfig2Capabilities( - glp, eglDisplay, configs.get(0), - true, capsChosen0.isOnscreen(), capsChosen0.isPBuffer()); - if(null!=capsChosen1) { - if(DEBUG) { - System.err.println("eglChooseConfig found: eglDisplay 0x"+Long.toHexString(eglDisplay)+ - ", eglConfig ID 0x"+Integer.toHexString(val[0])+ - ", "+capsChosen0+" -> "+capsChosen1); - } - return new EGLGraphicsConfiguration(absScreen, capsChosen1, capsRequested, chooser, configs.get(0), val[0]); + } + + // 2nd choice: get all GLCapabilities available, no preferred recommendedIndex available + if( null == availableCaps || 0 == availableCaps.size() ) { + // reset .. + recommendedEGLConfig = -1; + recommendedIndex = -1; + + if(!EGL.eglGetConfigs(eglDisplay, configs, configs.capacity(), numConfigs, 0)) { + throw new GLException("Graphics configuration get all configs (eglGetConfigs) call failed, error "+toHexString(EGL.eglGetError())); } - if(DEBUG) { - System.err.println("eglChooseConfig couldn't verify: eglDisplay 0x"+Long.toHexString(eglDisplay)+ - ", eglConfig ID 0x"+Integer.toHexString(val[0])+ - ", for "+capsChosen0); + if (numConfigs[0] > 0) { + availableCaps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs[0], winattrmask); } - } else { + } + + if( null == availableCaps || 0 == availableCaps.size() ) { if(DEBUG) { - System.err.println("EGL Choose Configs: None using eglDisplay 0x"+Long.toHexString(eglDisplay)+ - ", "+capsChosen0); + // FIXME: this happens on a ATI PC Emulation .. + System.err.println("Graphics configuration 1st choice and 2nd choice failed - no configs"); } + return null; } - return null; + + int chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex); + if ( 0 > chosenIndex ) { + if (DEBUG) { + Thread.dumpStack(); + } + return null; + } + EGLGLCapabilities chosenCaps = (EGLGLCapabilities) availableCaps.get(chosenIndex); + + return new EGLGraphicsConfiguration(absScreen, chosenCaps, capsRequested, chooser); } - static GLCapabilitiesImmutable[] eglConfigs2GLCaps(GLProfile glp, long eglDisplay, PointerBuffer configs, int num, - boolean onscreen, boolean usePBuffer) { - GLCapabilitiesImmutable[] caps = new GLCapabilitiesImmutable[num]; + static List/*<GLCapabilitiesImmutable>*/ eglConfigs2GLCaps(GLProfile glp, long eglDisplay, PointerBuffer configs, int num, int winattrmask) { + ArrayList caps = new ArrayList(num); for(int i=0; i<num; i++) { - caps[i] = EGLGraphicsConfiguration.EGLConfig2Capabilities(glp, eglDisplay, configs.get(i), - true, onscreen, usePBuffer); + EGLGraphicsConfiguration.EGLConfig2Capabilities(caps, glp, eglDisplay, configs.get(i), winattrmask); } return caps; } - static void printCaps(String prefix, GLCapabilitiesImmutable[] caps, PrintStream out) { - for(int i=0; i<caps.length; i++) { - out.println(prefix+"["+i+"] "+caps[i]); + static void printCaps(String prefix, List/*GLCapabilitiesImmutable*/ caps, PrintStream out) { + for(int i=0; i<caps.size(); i++) { + out.println(prefix+"["+i+"] "+caps.get(i)); } } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLContext.java index 6a916765a..3450c456e 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLContext.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLContext.java @@ -223,18 +223,21 @@ public abstract class MacOSXCGLContext extends GLContextImpl } } - protected final void updateGLXProcAddressTable(int major, int minor, int ctp) { + protected final void updateGLXProcAddressTable() { + AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); + String key = adevice.getUniqueID(); if (DEBUG) { - System.err.println(getThreadName() + ": !!! Initializing CGL extension address table"); + System.err.println(getThreadName() + ": !!! Initializing CGL extension address table: "+key); } CGLExtProcAddressTable table = null; synchronized(mappedContextTypeObjectLock) { - table = (CGLExtProcAddressTable) mappedGLXProcAddress.get( contextFQN ); + table = (CGLExtProcAddressTable) mappedGLXProcAddress.get( key ); } if(null != table) { cglExtProcAddressTable = table; if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext CGL ProcAddressTable reusing key("+contextFQN+") -> "+table.hashCode()); + System.err.println(getThreadName() + ": !!! GLContext CGL ProcAddressTable reusing key("+key+") -> "+table.hashCode()); } } else { if (cglExtProcAddressTable == null) { @@ -244,9 +247,9 @@ public abstract class MacOSXCGLContext extends GLContextImpl } resetProcAddressTable(getCGLExtProcAddressTable()); synchronized(mappedContextTypeObjectLock) { - mappedGLXProcAddress.put(contextFQN, getCGLExtProcAddressTable()); + mappedGLXProcAddress.put(key, getCGLExtProcAddressTable()); if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext CGL ProcAddressTable mapping key("+contextFQN+") -> "+getCGLExtProcAddressTable().hashCode()); + System.err.println(getThreadName() + ": !!! GLContext CGL ProcAddressTable mapping key("+key+") -> "+getCGLExtProcAddressTable().hashCode()); } } } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawableFactory.java index 1895c8e67..421bae715 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawableFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawableFactory.java @@ -41,14 +41,17 @@ package com.jogamp.opengl.impl.macosx.cgl; import java.nio.*; +import java.util.HashMap; +import java.util.List; + import javax.media.nativewindow.*; +import javax.media.nativewindow.macosx.MacOSXGraphicsDevice; import javax.media.opengl.*; + import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.util.*; import com.jogamp.opengl.impl.*; import com.jogamp.nativewindow.impl.ProxySurface; -import java.util.HashMap; -import javax.media.nativewindow.macosx.MacOSXGraphicsDevice; public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { private static final DesktopGLDynamicLookupHelper macOSXCGLDynamicLookupHelper; @@ -123,6 +126,10 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { protected final void shutdownInstance() {} + protected List/*GLCapabilitiesImmutable*/ getAvailableCapabilitiesImpl(AbstractGraphicsDevice device) { + throw new UnsupportedOperationException("not yet implemented"); + } + protected GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target) { if (target == null) { throw new IllegalArgumentException("Null target"); diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java index 5d7a0375b..cc06a6775 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java @@ -33,6 +33,7 @@ package com.jogamp.opengl.impl.macosx.cgl; +import com.jogamp.opengl.impl.GLGraphicsConfigurationFactory; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.CapabilitiesChooser; @@ -47,7 +48,7 @@ import javax.media.opengl.GLCapabilitiesImmutable; to this one to change the accepted and returned types of the GraphicsDevice and GraphicsConfiguration abstractions. */ -public class MacOSXCGLGraphicsConfigurationFactory extends GraphicsConfigurationFactory { +public class MacOSXCGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory { protected static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug("GraphicsConfiguration"); MacOSXCGLGraphicsConfigurationFactory() { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java index 702d66fce..95b6f473f 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java @@ -33,6 +33,7 @@ package com.jogamp.opengl.impl.macosx.cgl.awt; +import com.jogamp.opengl.impl.GLGraphicsConfigurationFactory; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; @@ -54,7 +55,7 @@ import javax.media.opengl.GLException; import com.jogamp.opengl.impl.macosx.cgl.MacOSXCGLGraphicsConfiguration; -public class MacOSXAWTCGLGraphicsConfigurationFactory extends GraphicsConfigurationFactory { +public class MacOSXAWTCGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory { protected static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug("GraphicsConfiguration"); public MacOSXAWTCGLGraphicsConfigurationFactory() { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WGLGLCapabilities.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WGLGLCapabilities.java new file mode 100644 index 000000000..b5be4bf8d --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WGLGLCapabilities.java @@ -0,0 +1,243 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import java.util.Comparator; + +import com.jogamp.nativewindow.impl.windows.GDI; +import com.jogamp.nativewindow.impl.windows.PIXELFORMATDESCRIPTOR; +import javax.media.opengl.GL; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; + +public class WGLGLCapabilities extends GLCapabilities { + PIXELFORMATDESCRIPTOR pfd; + int pfdID; + int arb_pixelformat; // -1 PFD, 0 NOP, 1 ARB + + /** Comparing pfd id only */ + public static class PfdIDComparator implements Comparator { + + public int compare(Object o1, Object o2) { + if ( ! ( o1 instanceof WGLGLCapabilities ) ) { + Class c = (null != o1) ? o1.getClass() : null ; + throw new ClassCastException("arg1 not a WGLGLCapabilities object: " + c); + } + if ( ! ( o2 instanceof WGLGLCapabilities ) ) { + Class c = (null != o2) ? o2.getClass() : null ; + throw new ClassCastException("arg2 not a WGLGLCapabilities object: " + c); + } + + final WGLGLCapabilities caps1 = (WGLGLCapabilities) o1; + final long id1 = caps1.getPFDID(); + + final WGLGLCapabilities caps2 = (WGLGLCapabilities) o2; + final long id2 = caps2.getPFDID(); + + if(id1 > id2) { + return 1; + } else if(id1 < id2) { + return -1; + } + return 0; + } + } + + public WGLGLCapabilities(PIXELFORMATDESCRIPTOR pfd, int pfdID, GLProfile glp) { + super(glp); + this.pfd = pfd; + this.pfdID = pfdID; + this.arb_pixelformat = 0; + } + + public boolean setValuesByGDI() { + arb_pixelformat = -1; + + setRedBits(pfd.getCRedBits()); + setGreenBits(pfd.getCGreenBits()); + setBlueBits(pfd.getCBlueBits()); + setAlphaBits(pfd.getCAlphaBits()); + setAccumRedBits(pfd.getCAccumRedBits()); + setAccumGreenBits(pfd.getCAccumGreenBits()); + setAccumBlueBits(pfd.getCAccumBlueBits()); + setAccumAlphaBits(pfd.getCAccumAlphaBits()); + setDepthBits(pfd.getCDepthBits()); + setStencilBits(pfd.getCStencilBits()); + setDoubleBuffered((pfd.getDwFlags() & GDI.PFD_DOUBLEBUFFER) != 0); + setStereo((pfd.getDwFlags() & GDI.PFD_STEREO) != 0); + setHardwareAccelerated((pfd.getDwFlags() & GDI.PFD_GENERIC_FORMAT) == 0 + || (pfd.getDwFlags() & GDI.PFD_GENERIC_ACCELERATED) != 0); + // n/a with non ARB/GDI method: + // multisample + // opaque + // pbuffer + + return true; + } + + public boolean setValuesByARB(final int[] iattribs, final int niattribs, final int[] iresults) { + arb_pixelformat = 1; + + for (int i = 0; i < niattribs; i++) { + int attr = iattribs[i]; + switch (attr) { + case WGLExt.WGL_DRAW_TO_WINDOW_ARB: + case WGLExt.WGL_DRAW_TO_BITMAP_ARB: + case WGLExt.WGL_DRAW_TO_PBUFFER_ARB: + break; + + case WGLExt.WGL_ACCELERATION_ARB: + setHardwareAccelerated(iresults[i] == WGLExt.WGL_FULL_ACCELERATION_ARB); + break; + + case WGLExt.WGL_SUPPORT_OPENGL_ARB: + if (iresults[i] != GL.GL_TRUE) { + return false; + } + break; + + case WGLExt.WGL_DEPTH_BITS_ARB: + setDepthBits(iresults[i]); + break; + + case WGLExt.WGL_STENCIL_BITS_ARB: + setStencilBits(iresults[i]); + break; + + case WGLExt.WGL_DOUBLE_BUFFER_ARB: + setDoubleBuffered(iresults[i] == GL.GL_TRUE); + break; + + case WGLExt.WGL_STEREO_ARB: + setStereo(iresults[i] == GL.GL_TRUE); + break; + + case WGLExt.WGL_PIXEL_TYPE_ARB: + // Fail softly with unknown results here + if (iresults[i] == WGLExt.WGL_TYPE_RGBA_ARB || + iresults[i] == WGLExt.WGL_TYPE_RGBA_FLOAT_ARB) { + setPbufferFloatingPointBuffers(true); + } + break; + + case WGLExt.WGL_FLOAT_COMPONENTS_NV: + if (iresults[i] != 0) { + setPbufferFloatingPointBuffers(true); + } + break; + + case WGLExt.WGL_RED_BITS_ARB: + setRedBits(iresults[i]); + break; + + case WGLExt.WGL_GREEN_BITS_ARB: + setGreenBits(iresults[i]); + break; + + case WGLExt.WGL_BLUE_BITS_ARB: + setBlueBits(iresults[i]); + break; + + case WGLExt.WGL_ALPHA_BITS_ARB: + setAlphaBits(iresults[i]); + break; + + case WGLExt.WGL_ACCUM_RED_BITS_ARB: + setAccumRedBits(iresults[i]); + break; + + case WGLExt.WGL_ACCUM_GREEN_BITS_ARB: + setAccumGreenBits(iresults[i]); + break; + + case WGLExt.WGL_ACCUM_BLUE_BITS_ARB: + setAccumBlueBits(iresults[i]); + break; + + case WGLExt.WGL_ACCUM_ALPHA_BITS_ARB: + setAccumAlphaBits(iresults[i]); + break; + + case WGLExt.WGL_SAMPLE_BUFFERS_ARB: + setSampleBuffers(iresults[i] != 0); + break; + + case WGLExt.WGL_SAMPLES_ARB: + setNumSamples(iresults[i]); + break; + + default: + throw new GLException("Unknown pixel format attribute " + iattribs[i]); + } + } + return true; + } + + public Object cloneMutable() { + return clone(); + } + + public Object clone() { + try { + return super.clone(); + } catch (RuntimeException e) { + throw new GLException(e); + } + } + + final public PIXELFORMATDESCRIPTOR getPFD() { return pfd; } + final public int getPFDID() { return pfdID; } + + final public boolean isSetByARB() { return 0 < arb_pixelformat; } + final public boolean isSetByGDI() { return 0 > arb_pixelformat; } + final public boolean isSet() { return 0 != arb_pixelformat; } + + public StringBuffer toString(StringBuffer sink) { + if(null == sink) { + sink = new StringBuffer(); + } + sink.append(pfdID).append(" "); + switch (arb_pixelformat) { + case -1: + sink.append("gdi"); + break; + case 0: + sink.append("nop"); + break; + case 1: + sink.append("arb"); + break; + default: + throw new InternalError("invalid arb_pixelformat: " + arb_pixelformat); + } + sink.append(": "); + return super.toString(sink); + } +}
\ No newline at end of file diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsBitmapWGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsBitmapWGLDrawable.java index 0d360b339..c61a8d0e4 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsBitmapWGLDrawable.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsBitmapWGLDrawable.java @@ -40,6 +40,7 @@ package com.jogamp.opengl.impl.windows.wgl; +import com.jogamp.common.nio.PointerBuffer; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.SurfaceChangeable; import javax.media.opengl.GLContext; @@ -73,11 +74,19 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable { } private void create() { + int werr; NativeSurface ns = getNativeSurface(); + if(DEBUG) { + System.err.println("WindowsBitmapWGLDrawable (1): "+ns); + } WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration().getNativeGraphicsConfiguration(); GLCapabilitiesImmutable capabilities = (GLCapabilitiesImmutable)config.getRequestedCapabilities(); int width = getWidth(); int height = getHeight(); + + // + // 1. Create DIB Section + // BITMAPINFO info = BITMAPINFO.create(); BITMAPINFOHEADER header = info.getBmiHeader(); int bitsPerPixel = (capabilities.getRedBits() + @@ -97,22 +106,42 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable { header.setBiClrUsed(0); header.setBiClrImportant(0); header.setBiCompression(GDI.BI_RGB); - header.setBiSizeImage(width * height * bitsPerPixel / 8); + int byteNum = width * height * ( bitsPerPixel >> 3 ) ; + header.setBiSizeImage(byteNum); + + PointerBuffer pb = PointerBuffer.allocateDirect(1); + hbitmap = GDI.CreateDIBSection(0, info, GDI.DIB_RGB_COLORS, pb, 0, 0); + werr = GDI.GetLastError(); + if(DEBUG) { + long p = ( pb.capacity() > 0 ) ? pb.get(0) : 0; + System.err.println("WindowsBitmapWGLDrawable: pb sz/ptr "+pb.capacity() + ", "+toHexString(p)); + System.err.println("WindowsBitmapWGLDrawable: " + width+"x"+height + + ", bpp " + bitsPerPixel + + ", bytes " + byteNum + + ", header sz " + header.size() + + ", DIB ptr num " + pb.capacity()+ + ", "+capabilities+ + ", werr "+werr); + } + if (hbitmap == 0) { + throw new GLException("Error creating offscreen bitmap of " + ns + ", werr " + werr); + } + // + // 2. Create memory DC (device context) , and associate it with the DIB. + // long hdc = GDI.CreateCompatibleDC(0); + werr = GDI.GetLastError(); if (hdc == 0) { - System.out.println("LastError: " + GDI.GetLastError()); - throw new GLException("Error creating device context for offscreen OpenGL context"); + GDI.DeleteObject(hbitmap); + hbitmap = 0; + throw new GLException("Error creating device context for offscreen OpenGL context, werr "+werr); } ((SurfaceChangeable)ns).setSurfaceHandle(hdc); - - hbitmap = GDI.CreateDIBSection(hdc, info, GDI.DIB_RGB_COLORS, null, 0, 0); - if (hbitmap == 0) { - GDI.DeleteDC(hdc); - hdc = 0; - throw new GLException("Error creating offscreen bitmap of width " + width + - ", height " + height); + if(DEBUG) { + System.err.println("WindowsBitmapWGLDrawable (2): "+ns); } + if ((origbitmap = GDI.SelectObject(hdc, hbitmap)) == 0) { GDI.DeleteObject(hbitmap); hbitmap = 0; @@ -120,7 +149,8 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable { hdc = 0; throw new GLException("Error selecting bitmap into new device context"); } - config.updateGraphicsConfiguration(getFactory(), ns); + + config.updateGraphicsConfiguration(getFactory(), ns, null); } protected void destroyImpl() { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsDummyWGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsDummyWGLDrawable.java index 015ef61a4..a307e295d 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsDummyWGLDrawable.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsDummyWGLDrawable.java @@ -47,31 +47,40 @@ import javax.media.opengl.GLProfile; import javax.media.nativewindow.AbstractGraphicsScreen; import com.jogamp.nativewindow.impl.ProxySurface; import com.jogamp.nativewindow.impl.windows.GDI; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.NativeSurface; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLException; public class WindowsDummyWGLDrawable extends WindowsWGLDrawable { - private static final int f_dim = 128; + private static final int f_dim = 64; private long hwnd, hdc; protected WindowsDummyWGLDrawable(GLDrawableFactory factory, GLCapabilitiesImmutable caps, AbstractGraphicsScreen absScreen) { super(factory, new ProxySurface(WindowsWGLGraphicsConfigurationFactory.createDefaultGraphicsConfiguration(caps, absScreen)), true); hwnd = GDI.CreateDummyWindow(0, 0, f_dim, f_dim); - hdc = GDI.GetDC(hwnd); + if(0 == hwnd) { + throw new GLException("Error hwnd 0, werr: "+GDI.GetLastError()); + } + // manual debug only - GDI.ShowWindow(hwnd, GDI.SW_SHOW); ProxySurface ns = (ProxySurface) getNativeSurface(); - ns.setSurfaceHandle(hdc); ns.setSize(f_dim, f_dim); - WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration().getNativeGraphicsConfiguration(); - + + if(NativeSurface.LOCK_SURFACE_NOT_READY >= lockSurface()) { + throw new GLException("WindowsDummyWGLDrawable: surface not ready (lockSurface)"); + } try { - config.updateGraphicsConfiguration(factory, ns); + WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + config.updateGraphicsConfiguration(factory, ns, null); if (DEBUG) { System.err.println("!!! WindowsDummyWGLDrawable: "+config); } } catch (Throwable t) { destroyImpl(); throw new GLException(t); + } finally { + unlockSurface(); } } @@ -80,10 +89,56 @@ public class WindowsDummyWGLDrawable extends WindowsWGLDrawable { caps.setDepthBits(16); caps.setDoubleBuffered(true); caps.setOnscreen (true); - caps.setPBuffer (true); return new WindowsDummyWGLDrawable(factory, caps, absScreen); } + public int lockSurface() throws GLException { + int res = NativeSurface.LOCK_SURFACE_NOT_READY; + ProxySurface ns = (ProxySurface) getNativeSurface(); + AbstractGraphicsDevice adevice = ns.getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice(); + adevice.lock(); + try { + res = ns.lockSurface(); + if(NativeSurface.LOCK_SUCCESS == res) { + if(0 == hdc) { + hdc = GDI.GetDC(hwnd); + ns.setSurfaceHandle(hdc); + if(0 == hdc) { + res = NativeSurface.LOCK_SURFACE_NOT_READY; + ns.unlockSurface(); + throw new GLException("Error hdc 0, werr: "+GDI.GetLastError()); + // finally will unlock adevice + } + } + } else { + Throwable t = new Throwable("Error lock failed - res "+res+", hwnd "+toHexString(hwnd)+", hdc "+toHexString(hdc)); + t.printStackTrace(); + } + } finally { + if( NativeSurface.LOCK_SURFACE_NOT_READY == res ) { + adevice.unlock(); + } + } + return res; + } + + public void unlockSurface() { + ProxySurface ns = (ProxySurface) getNativeSurface(); + ns.validateSurfaceLocked(); + AbstractGraphicsDevice adevice = ns.getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice(); + + try { + if ( 0 != hdc && 0 != hwnd && ns.getSurfaceRecursionCount() == 0) { + GDI.ReleaseDC(hwnd, hdc); + hdc=0; + ns.setSurfaceHandle(hdc); + } + surface.unlockSurface(); + } finally { + adevice.unlock(); + } + } + public void setSize(int width, int height) { } @@ -96,10 +151,6 @@ public class WindowsDummyWGLDrawable extends WindowsWGLDrawable { } public GLContext createContext(GLContext shareWith) { - if (hdc == 0) { - // Construction failed - return null; - } // FIXME: figure out how to hook back in the Java 2D / JOGL bridge return new WindowsWGLContext(this, shareWith); } @@ -108,10 +159,12 @@ public class WindowsDummyWGLDrawable extends WindowsWGLDrawable { if (hdc != 0) { GDI.ReleaseDC(hwnd, hdc); hdc = 0; + ProxySurface ns = (ProxySurface) getNativeSurface(); + ns.setSurfaceHandle(hdc); } if (hwnd != 0) { GDI.ShowWindow(hwnd, GDI.SW_HIDE); - GDI.DestroyWindow(hwnd); + GDI.DestroyDummyWindow(hwnd); hwnd = 0; } } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLContext.java index fd70842ac..d8d410d39 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLContext.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLContext.java @@ -66,9 +66,6 @@ public class WindowsExternalWGLContext extends WindowsWGLContext { } GLContextShareSet.contextCreated(this); setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); - WindowsWGLGraphicsConfiguration config = - (WindowsWGLGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); - config.updateGraphicsConfiguration(drawable.getFactory(), drawable.getNativeSurface()); getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } @@ -87,12 +84,8 @@ public class WindowsExternalWGLContext extends WindowsWGLContext { } AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS); - WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfiguration.create(hdc, pfdID, glp, aScreen, true, true); - - ProxySurface ns = new ProxySurface(cfg); - ns.setSurfaceHandle(hdc); - - return new WindowsExternalWGLContext(new Drawable(factory, ns), ctx, cfg); + WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfiguration.create(factory, hdc, pfdID, glp, aScreen, true, true); + return new WindowsExternalWGLContext(new Drawable(factory, new ProxySurface(cfg, hdc)), ctx, cfg); } public int makeCurrent() throws GLException { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLDrawable.java index 66a5c80a4..f3329b73b 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLDrawable.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLDrawable.java @@ -69,14 +69,8 @@ public class WindowsExternalWGLDrawable extends WindowsWGLDrawable { } AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS); - WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfiguration.create(hdc, pfdID, glp, aScreen, true, true); - - ProxySurface ns = new ProxySurface(cfg); - ns.setSurfaceHandle(hdc); - - cfg.updateGraphicsConfiguration(factory, ns); - - return new WindowsExternalWGLDrawable(factory, ns); + WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfiguration.create(factory, hdc, pfdID, glp, aScreen, true, true); + return new WindowsExternalWGLDrawable(factory, new ProxySurface(cfg, hdc)); } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsPbufferWGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsPbufferWGLDrawable.java index 47b33dd6b..720ac84ca 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsPbufferWGLDrawable.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsPbufferWGLDrawable.java @@ -50,7 +50,6 @@ import javax.media.opengl.GLPbuffer; import javax.media.opengl.GLProfile; import com.jogamp.nativewindow.impl.windows.GDI; -import com.jogamp.nativewindow.impl.windows.PIXELFORMATDESCRIPTOR; import javax.media.opengl.GLCapabilitiesImmutable; public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable { @@ -144,7 +143,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable { } if(!WindowsWGLGraphicsConfiguration.GLCapabilities2AttribList(capabilities, - iattributes, sharedCtx, -1, true, floatModeTmp)){ + iattributes, sharedCtx, -1, floatModeTmp)){ throw new GLException("Pbuffer-related extensions not supported"); } @@ -174,96 +173,57 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable { throw new GLException("pbuffer creation error: Couldn't find a suitable pixel format"); } - boolean haveMultisample = sharedCtx.isExtensionAvailable("WGL_ARB_multisample"); - if (DEBUG) { System.err.println("" + nformats + " suitable pixel formats found"); - // query pixel format - iattributes[0] = WGLExt.WGL_RED_BITS_ARB; - iattributes[1] = WGLExt.WGL_GREEN_BITS_ARB; - iattributes[2] = WGLExt.WGL_BLUE_BITS_ARB; - iattributes[3] = WGLExt.WGL_ALPHA_BITS_ARB; - iattributes[4] = WGLExt.WGL_DEPTH_BITS_ARB; - iattributes[5] = (useFloat ? (ati ? WGLExt.WGL_PIXEL_TYPE_ARB : WGLExt.WGL_FLOAT_COMPONENTS_NV) : WGLExt.WGL_RED_BITS_ARB); - iattributes[6] = (haveMultisample ? WGLExt.WGL_SAMPLE_BUFFERS_ARB : WGLExt.WGL_RED_BITS_ARB); - iattributes[7] = (haveMultisample ? WGLExt.WGL_SAMPLES_ARB : WGLExt.WGL_RED_BITS_ARB); - iattributes[8] = WGLExt.WGL_DRAW_TO_PBUFFER_ARB; - int[] ivalues = new int[9]; for (int i = 0; i < nformats; i++) { - if (!wglExt.wglGetPixelFormatAttribivARB(parentHdc, pformats[i], 0, 9, iattributes, 0, ivalues, 0)) { - throw new GLException("Error while querying pixel format " + pformats[i] + - "'s (index " + i + "'s) capabilities for debugging"); - } - System.err.print("pixel format " + pformats[i] + " (index " + i + "): "); - System.err.print( "r: " + ivalues[0]); - System.err.print(" g: " + ivalues[1]); - System.err.print(" b: " + ivalues[2]); - System.err.print(" a: " + ivalues[3]); - System.err.print(" depth: " + ivalues[4]); - if (haveMultisample) { - System.err.print(" multisample: " + ivalues[6]); - } - System.err.print(" samples: " + ivalues[7]); - if (useFloat) { - if (ati) { - if (ivalues[5] == WGLExt.WGL_TYPE_RGBA_FLOAT_ARB) { - System.err.print(" [ati float]"); - } else if (ivalues[5] != WGLExt.WGL_TYPE_RGBA_ARB) { - System.err.print(" [unknown pixel type " + ivalues[5] + "]"); - } - } else { - if (ivalues[5] != 0) { - System.err.print(" [float]"); - } - } - } - - if (ivalues[8] != 0) { - System.err.print(" [pbuffer]"); - } - System.err.println(); + WGLGLCapabilities dbgCaps = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities(sharedCtx, parentHdc, pformats[i], glProfile, false, true); + System.err.println("pixel format " + pformats[i] + " (index " + i + "): " + dbgCaps); } } + int pfdid = 0; long tmpBuffer = 0; - int whichFormat = -1; - // Loop is a workaround for bugs in NVidia's recent drivers - for (whichFormat = 0; whichFormat < nformats; whichFormat++) { - int format = pformats[whichFormat]; - - // Create the p-buffer. - niattribs = 0; - - if (rtt) { - iattributes[niattribs++] = WGLExt.WGL_TEXTURE_FORMAT_ARB; - if (useFloat) { - iattributes[niattribs++] = WGLExt.WGL_TEXTURE_FLOAT_RGB_NV; - } else { - iattributes[niattribs++] = WGLExt.WGL_TEXTURE_RGBA_ARB; - } + { + int whichFormat; + // Loop is a workaround for bugs in NVidia's recent drivers + for (whichFormat = 0; whichFormat < nformats; whichFormat++) { + int format = pformats[whichFormat]; + + // Create the p-buffer. + niattribs = 0; + + if (rtt) { + iattributes[niattribs++] = WGLExt.WGL_TEXTURE_FORMAT_ARB; + if (useFloat) { + iattributes[niattribs++] = WGLExt.WGL_TEXTURE_FLOAT_RGB_NV; + } else { + iattributes[niattribs++] = WGLExt.WGL_TEXTURE_RGBA_ARB; + } - iattributes[niattribs++] = WGLExt.WGL_TEXTURE_TARGET_ARB; - iattributes[niattribs++] = rect ? WGLExt.WGL_TEXTURE_RECTANGLE_NV : WGLExt.WGL_TEXTURE_2D_ARB; + iattributes[niattribs++] = WGLExt.WGL_TEXTURE_TARGET_ARB; + iattributes[niattribs++] = rect ? WGLExt.WGL_TEXTURE_RECTANGLE_NV : WGLExt.WGL_TEXTURE_2D_ARB; - iattributes[niattribs++] = WGLExt.WGL_MIPMAP_TEXTURE_ARB; - iattributes[niattribs++] = GL.GL_FALSE; + iattributes[niattribs++] = WGLExt.WGL_MIPMAP_TEXTURE_ARB; + iattributes[niattribs++] = GL.GL_FALSE; - iattributes[niattribs++] = WGLExt.WGL_PBUFFER_LARGEST_ARB; - iattributes[niattribs++] = GL.GL_FALSE; - } + iattributes[niattribs++] = WGLExt.WGL_PBUFFER_LARGEST_ARB; + iattributes[niattribs++] = GL.GL_FALSE; + } - iattributes[niattribs++] = 0; + iattributes[niattribs++] = 0; - tmpBuffer = wglExt.wglCreatePbufferARB(parentHdc, format, getWidth(), getHeight(), iattributes, 0); - if (tmpBuffer != 0) { - // Done - break; - } - } + tmpBuffer = wglExt.wglCreatePbufferARB(parentHdc, format, getWidth(), getHeight(), iattributes, 0); + if (tmpBuffer != 0) { + // Done + break; + } + } - if (tmpBuffer == 0) { - throw new GLException("pbuffer creation error: wglCreatePbuffer() failed: tried " + nformats + - " pixel formats, last error was: " + wglGetLastError()); + if (0 == tmpBuffer) { + throw new GLException("pbuffer creation error: wglCreatePbuffer() failed: tried " + nformats + + " pixel formats, last error was: " + wglGetLastError()); + } + pfdid = pformats[whichFormat]; } // Get the device context. @@ -280,48 +240,14 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable { // Re-query chosen pixel format { - niattribs = 0; - iattributes[niattribs++] = WGLExt.WGL_ACCELERATION_ARB; - iattributes[niattribs++] = WGLExt.WGL_RED_BITS_ARB; - iattributes[niattribs++] = WGLExt.WGL_GREEN_BITS_ARB; - iattributes[niattribs++] = WGLExt.WGL_BLUE_BITS_ARB; - iattributes[niattribs++] = WGLExt.WGL_ALPHA_BITS_ARB; - iattributes[niattribs++] = WGLExt.WGL_DEPTH_BITS_ARB; - iattributes[niattribs++] = WGLExt.WGL_STENCIL_BITS_ARB; - iattributes[niattribs++] = WGLExt.WGL_DOUBLE_BUFFER_ARB; - iattributes[niattribs++] = WGLExt.WGL_STEREO_ARB; - iattributes[niattribs++] = WGLExt.WGL_ACCUM_RED_BITS_ARB; - iattributes[niattribs++] = WGLExt.WGL_ACCUM_GREEN_BITS_ARB; - iattributes[niattribs++] = WGLExt.WGL_ACCUM_BLUE_BITS_ARB; - iattributes[niattribs++] = WGLExt.WGL_ACCUM_ALPHA_BITS_ARB; - iattributes[niattribs++] = (useFloat ? (ati ? WGLExt.WGL_PIXEL_TYPE_ARB : WGLExt.WGL_FLOAT_COMPONENTS_NV) : WGLExt.WGL_RED_BITS_ARB); - iattributes[niattribs++] = (haveMultisample ? WGLExt.WGL_SAMPLE_BUFFERS_ARB : WGLExt.WGL_RED_BITS_ARB); - iattributes[niattribs++] = (haveMultisample ? WGLExt.WGL_SAMPLES_ARB : WGLExt.WGL_RED_BITS_ARB); - iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_PBUFFER_ARB; - int[] ivalues = new int[niattribs]; - if (wglExt.wglGetPixelFormatAttribivARB(parentHdc, pformats[whichFormat], 0, niattribs, iattributes, 0, ivalues, 0)) { - GLCapabilitiesImmutable newCaps = WindowsWGLGraphicsConfiguration.AttribList2GLCapabilities(glProfile, iattributes, niattribs, ivalues, false, true); - if(null == newCaps|| newCaps.isOnscreen() || !newCaps.isPBuffer()) { - throw new GLException("Error: Selected Onscreen Caps for PBuffer: "+newCaps); - } - PIXELFORMATDESCRIPTOR pfd = WindowsWGLGraphicsConfiguration.createPixelFormatDescriptor(); - if (GDI.DescribePixelFormat(parentHdc, pformats[whichFormat], pfd.size(), pfd) == 0) { - if (DEBUG) { - System.err.println("Unable to describe pixel format (Continue: true) " + whichFormat + "/" + nformats + " pfdID " + pformats[whichFormat]+":\n\t"+newCaps); - } - } - config.setCapsPFD(newCaps, pfd, pformats[whichFormat], true); - } else { - PIXELFORMATDESCRIPTOR pfd = WindowsWGLGraphicsConfiguration.createPixelFormatDescriptor(); - if (GDI.DescribePixelFormat(parentHdc, pformats[whichFormat], pfd.size(), pfd) == 0) { - throw new GLException("Unable to describe pixel format " + pformats[whichFormat]); - } - GLCapabilitiesImmutable newCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(glProfile, pfd, false, true); - if(newCaps.isOnscreen()) { - throw new GLException("Error: Selected Onscreen Caps for PBuffer: "+newCaps+"\n\t"+newCaps); - } - config.setCapsPFD(newCaps, pfd, pformats[whichFormat], false); + WGLGLCapabilities newCaps = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities(sharedCtx, parentHdc, pfdid, glProfile, false, true); + if(null == newCaps) { + throw new GLException("pbuffer creation error: unable to re-query chosen PFD ID: " + pfdid + ", hdc " + this.toHexString(tmpHdc)); + } + if(newCaps.isOnscreen() || !newCaps.isPBuffer()) { + throw new GLException("Error: Selected Onscreen Caps for PBuffer: "+newCaps); } + config.setCapsPFD(newCaps); } // Determine the actual width and height we were able to create. diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLContext.java index e85308371..7d38f8ee8 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLContext.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLContext.java @@ -48,6 +48,7 @@ import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.opengl.GLContext; import javax.media.opengl.GLException; +import javax.media.opengl.GLCapabilitiesImmutable; import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; @@ -55,16 +56,14 @@ import com.jogamp.nativewindow.impl.windows.GDI; import com.jogamp.opengl.impl.GLContextImpl; import com.jogamp.opengl.impl.GLContextShareSet; import com.jogamp.opengl.impl.GLDrawableImpl; -import javax.media.opengl.GLCapabilitiesImmutable; - public class WindowsWGLContext extends GLContextImpl { static final Map/*<String, String>*/ functionNameMap; static final Map/*<String, String>*/ extensionNameMap; private boolean wglGetExtensionsStringEXTInitialized; private boolean wglGetExtensionsStringEXTAvailable; - private boolean wglMakeContextCurrentInitialized; - private boolean wglMakeContextCurrentAvailable; + private boolean wglGLReadDrawableAvailableSet; + private boolean wglGLReadDrawableAvailable; private WGLExt wglExt; // Table that holds the addresses of the native C-language entry points for // WGL extension functions. @@ -89,8 +88,8 @@ public class WindowsWGLContext extends GLContextImpl { protected void resetState() { wglGetExtensionsStringEXTInitialized=false; wglGetExtensionsStringEXTAvailable=false; - wglMakeContextCurrentInitialized=false; - wglMakeContextCurrentAvailable=false; + wglGLReadDrawableAvailableSet=false; + wglGLReadDrawableAvailable=false; // no inner state _wglExt=null; wglExtProcAddressTable=null; } @@ -100,6 +99,9 @@ public class WindowsWGLContext extends GLContextImpl { } /* package private */ final WGLExt getWGLExt() { + if( null == getWGLExtProcAddressTable()) { + throw new InternalError("Null WGLExtProcAddressTable"); + } if (wglExt == null) { wglExt = new WGLExtImpl(this); } @@ -107,27 +109,27 @@ public class WindowsWGLContext extends GLContextImpl { } public final boolean isGLReadDrawableAvailable() { - if(!wglMakeContextCurrentInitialized && null != getWGLExtProcAddressTable()) { + if(!wglGLReadDrawableAvailableSet && null != getWGLExtProcAddressTable()) { WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory)drawable.getFactoryImpl(); AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); AbstractGraphicsDevice device = config.getScreen().getDevice(); switch( factory.isReadDrawableAvailable(device) ) { case 1: - wglMakeContextCurrentAvailable = true; - wglMakeContextCurrentInitialized=true; + wglGLReadDrawableAvailable = true; + wglGLReadDrawableAvailableSet=true; break; case 0: - wglMakeContextCurrentAvailable = false; - wglMakeContextCurrentInitialized=true; + wglGLReadDrawableAvailable = false; + wglGLReadDrawableAvailableSet=true; break; } } - return wglMakeContextCurrentAvailable; + return wglGLReadDrawableAvailable; } private final boolean wglMakeContextCurrent(long hDrawDC, long hReadDC, long ctx) { boolean ok = false; - if(wglMakeContextCurrentAvailable) { + if(wglGLReadDrawableAvailable) { // needs initilized WGL ProcAddress table ok = getWGLExt().wglMakeContextCurrent(hDrawDC, hReadDC, ctx); } else if ( hDrawDC == hReadDC ) { @@ -136,10 +138,17 @@ public class WindowsWGLContext extends GLContextImpl { // should not happen due to 'isGLReadDrawableAvailable()' query in GLContextImpl throw new InternalError("Given readDrawable but no driver support"); } + int werr = ( !ok ) ? GDI.GetLastError() : GDI.ERROR_SUCCESS; + if(DEBUG && !ok) { + Throwable t = new Throwable ("Info: wglMakeContextCurrent draw "+ + this.toHexString(hDrawDC) + ", read " + this.toHexString(hReadDC) + + ", ctx " + this.toHexString(ctx) + ", werr " + werr); + t.printStackTrace(); + } if(!ok && 0==hDrawDC && 0==hReadDC) { // Some GPU's falsely fails with a zero error code (success), // in case this is a release context request we tolerate this - return GDI.GetLastError() == GDI.ERROR_SUCCESS ; + return werr == GDI.ERROR_SUCCESS ; } return ok; } @@ -162,15 +171,15 @@ public class WindowsWGLContext extends GLContextImpl { } protected long createContextARBImpl(long share, boolean direct, int ctp, int major, int minor) { - WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory)drawable.getFactoryImpl(); - AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); - AbstractGraphicsDevice device = config.getScreen().getDevice(); - WindowsWGLContext sharedContext = (WindowsWGLContext) factory.getOrCreateSharedContextImpl(device); - WGLExt _wglExt; - if(null==sharedContext) { - _wglExt = getWGLExt(); - } else { - _wglExt = sharedContext.getWGLExt(); + if( null == getWGLExtProcAddressTable()) { + updateGLXProcAddressTable(); + } + WGLExt _wglExt = getWGLExt(); + if(DEBUG) { + System.err.println(getThreadName()+" - WindowWGLContext.createContextARBImpl: "+getGLVersion(major, minor, ctp, "@creation") + + ", handle "+toHexString(drawable.getHandle()) + ", share "+toHexString(share)+", direct "+direct+ + ", wglCreateContextAttribsARB: "+toHexString(wglExtProcAddressTable._addressof_wglCreateContextAttribsARB)); + Thread.dumpStack(); } boolean ctBwdCompat = 0 != ( CTX_PROFILE_COMPAT & ctp ) ; @@ -221,8 +230,7 @@ public class WindowsWGLContext extends GLContextImpl { } if(0!=ctx) { - // cannot use wglMakeContextCurrent since WGLExt ProcAddressTable is not ready yet. - if( !WGL.wglMakeCurrent(drawable.getHandle(), ctx) ) { + if (!wglMakeContextCurrent(drawable.getHandle(), drawableRead.getHandle(), ctx)) { if(DEBUG) { System.err.println("WindowsWGLContext.createContextARB couldn't make current "+getGLVersion(major, minor, ctp, "@creation")); } @@ -231,7 +239,7 @@ public class WindowsWGLContext extends GLContextImpl { ctx = 0; } else { if (DEBUG) { - System.err.println(getThreadName() + ": createContextARBImpl: OK "+getGLVersion(major, minor, ctp, "@creation")+", share "+share+", direct "+direct+", hasSharedContext "+(null!=sharedContext)); + System.err.println(getThreadName() + ": createContextARBImpl: OK "+getGLVersion(major, minor, ctp, "@creation")+", share "+share+", direct "+direct); } // the following is issued by the caller 'GLContextImpl.createContextARB()' // setGLFunctionAvailability(true, major, minor, ctp); @@ -253,7 +261,7 @@ public class WindowsWGLContext extends GLContextImpl { WindowsWGLContext sharedContext = (WindowsWGLContext) factory.getOrCreateSharedContextImpl(device); GLCapabilitiesImmutable glCaps = drawable.getChosenGLCapabilities(); - isGLReadDrawableAvailable(); // trigger setup wglMakeContextCurrentAvailable + isGLReadDrawableAvailable(); // trigger setup wglGLReadDrawableAvailable // Windows can set up sharing of display lists after creation time WindowsWGLContext other = (WindowsWGLContext) GLContextShareSet.getShareContext(this); @@ -315,12 +323,12 @@ public class WindowsWGLContext extends GLContextImpl { if(0!=contextHandle) { share = 0; // mark as shared thx to the ARB create method - WGL.wglMakeCurrent(0, 0); // the ARB create method used WGL.wglMakeCurrent(0, 0) - if(0!=temp_ctx) { + if(0!=temp_ctx) { + WGL.wglMakeCurrent(0, 0); WGL.wglDeleteContext(temp_ctx); - } - if (!wglMakeContextCurrent(drawable.getHandle(), drawableRead.getHandle(), contextHandle)) { - throw new GLException("Cannot make previous verified context current: 0x" + toHexString(contextHandle) + ", werr: " + GDI.GetLastError()); + if (!wglMakeContextCurrent(drawable.getHandle(), drawableRead.getHandle(), contextHandle)) { + throw new GLException("Cannot make previous verified context current: 0x" + toHexString(contextHandle) + ", werr: " + GDI.GetLastError()); + } } } else { if(glCaps.getGLProfile().isGL3()) { @@ -385,23 +393,26 @@ public class WindowsWGLContext extends GLContextImpl { } } - protected final void updateGLXProcAddressTable(int major, int minor, int ctp) { + protected final void updateGLXProcAddressTable() { + AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); + String key = adevice.getUniqueID(); if (DEBUG) { - System.err.println(getThreadName() + ": !!! Initializing WGL extension address table for " + this); + System.err.println(getThreadName() + ": !!! Initializing WGL extension address table: "+key); } wglGetExtensionsStringEXTInitialized=false; wglGetExtensionsStringEXTAvailable=false; - wglMakeContextCurrentInitialized=false; - wglMakeContextCurrentAvailable=false; + wglGLReadDrawableAvailableSet=false; + wglGLReadDrawableAvailable=false; WGLExtProcAddressTable table = null; synchronized(mappedContextTypeObjectLock) { - table = (WGLExtProcAddressTable) mappedGLXProcAddress.get( contextFQN ); + table = (WGLExtProcAddressTable) mappedGLXProcAddress.get( key ); } if(null != table) { wglExtProcAddressTable = table; if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext WGL ProcAddressTable reusing key("+contextFQN+") -> "+table.hashCode()); + System.err.println(getThreadName() + ": !!! GLContext WGL ProcAddressTable reusing key("+key+") -> "+table.hashCode()); } } else { if (wglExtProcAddressTable == null) { @@ -409,11 +420,11 @@ public class WindowsWGLContext extends GLContextImpl { // share them among contexts classes (GL4, GL4bc, GL3, GL3bc, ..) wglExtProcAddressTable = new WGLExtProcAddressTable(new GLProcAddressResolver()); } - resetProcAddressTable(getWGLExtProcAddressTable()); + resetProcAddressTable(wglExtProcAddressTable); synchronized(mappedContextTypeObjectLock) { - mappedGLXProcAddress.put(contextFQN, getWGLExtProcAddressTable()); + mappedGLXProcAddress.put(key, getWGLExtProcAddressTable()); if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext WGL ProcAddressTable mapping key("+contextFQN+") -> "+getWGLExtProcAddressTable().hashCode()); + System.err.println(getThreadName() + ": !!! GLContext WGL ProcAddressTable mapping key("+key+") -> "+getWGLExtProcAddressTable().hashCode()); } } } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawable.java index a98366f58..83b52fbcb 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawable.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawable.java @@ -68,7 +68,7 @@ public abstract class WindowsWGLDrawable extends GLDrawableImpl { NativeSurface ns = getNativeSurface(); WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration().getNativeGraphicsConfiguration(); - config.updateGraphicsConfiguration(getFactory(), ns); + config.updateGraphicsConfiguration(getFactory(), ns, null); if (DEBUG) { System.err.println("!!! WindowsWGLDrawable.setRealized(true): "+config); } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java index 903e1af81..674690e50 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java @@ -45,8 +45,6 @@ import java.nio.ShortBuffer; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; import java.util.List; import javax.media.nativewindow.AbstractGraphicsDevice; @@ -55,6 +53,8 @@ import javax.media.nativewindow.DefaultGraphicsScreen; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.windows.WindowsGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; @@ -62,15 +62,17 @@ import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; import com.jogamp.common.JogampRuntimeException; +import com.jogamp.common.nio.PointerBuffer; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.nativewindow.impl.ProxySurface; import com.jogamp.nativewindow.impl.windows.GDI; +import com.jogamp.nativewindow.impl.windows.RegisteredClassFactory; import com.jogamp.opengl.impl.DesktopGLDynamicLookupHelper; +import com.jogamp.opengl.impl.GLContextImpl; import com.jogamp.opengl.impl.GLDrawableFactoryImpl; import com.jogamp.opengl.impl.GLDrawableImpl; import com.jogamp.opengl.impl.GLDynamicLookupHelper; -import javax.media.nativewindow.AbstractGraphicsConfiguration; -import javax.media.opengl.GLCapabilitiesImmutable; +import com.jogamp.opengl.impl.SharedResourceRunner; public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { private static final DesktopGLDynamicLookupHelper windowsWGLDynamicLookupHelper; @@ -108,31 +110,182 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { } defaultDevice = new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); + + // Init shared resources off thread + // Will be released via ShutdownHook + sharedResourceImpl = new SharedResourceImplementation(); + sharedResourceRunner = new SharedResourceRunner(sharedResourceImpl); + sharedResourceThread = new Thread(sharedResourceRunner, Thread.currentThread().getName()+"-SharedResourceRunner"); + sharedResourceThread.setDaemon(true); // Allow JVM to exit, even if this one is running + sharedResourceThread.start(); } - static class SharedResource { + WindowsGraphicsDevice defaultDevice; + SharedResourceImplementation sharedResourceImpl; + SharedResourceRunner sharedResourceRunner; + Thread sharedResourceThread; + HashMap/*<connection, SharedResource>*/ sharedMap = new HashMap(); + + long processAffinityChanges = 0; + PointerBuffer procMask = PointerBuffer.allocateDirect(1); + PointerBuffer sysMask = PointerBuffer.allocateDirect(1); + + protected void enterThreadCriticalZone() { + synchronized (sysMask) { + if( 0 == processAffinityChanges) { + long pid = GDI.GetCurrentProcess(); + if ( GDI.GetProcessAffinityMask(pid, procMask, sysMask) ) { + if(DEBUG) { + System.err.println("WindowsWGLDrawableFactory.enterThreadCriticalZone() - 0x" + Long.toHexString(pid) + " - " + Thread.currentThread().getName()); + Thread.dumpStack(); + } + processAffinityChanges = pid; + GDI.SetProcessAffinityMask(pid, 1); + } + } + } + } + + protected void leaveThreadCriticalZone() { + synchronized (sysMask) { + if( 0 != processAffinityChanges) { + long pid = GDI.GetCurrentProcess(); + if( pid != processAffinityChanges) { + throw new GLException("PID doesn't match: set PID 0x" + Long.toHexString(processAffinityChanges) + + " this PID 0x" + Long.toHexString(pid) ); + } + if(DEBUG) { + System.err.println("WindowsWGLDrawableFactory.leaveThreadCriticalZone() - 0x" + Long.toHexString(pid) + " - " + Thread.currentThread().getName()); + } + GDI.SetProcessAffinityMask(pid, sysMask.get(0)); + } + } + } + + static class SharedResource implements SharedResourceRunner.Resource { private WindowsGraphicsDevice device; + private AbstractGraphicsScreen screen; private WindowsDummyWGLDrawable drawable; private WindowsWGLContext context; private boolean canCreateGLPbuffer; private boolean readDrawableAvailable; - SharedResource(WindowsGraphicsDevice dev, WindowsDummyWGLDrawable draw, WindowsWGLContext ctx, + SharedResource(WindowsGraphicsDevice dev, AbstractGraphicsScreen scrn, WindowsDummyWGLDrawable draw, WindowsWGLContext ctx, boolean readBufferAvail, boolean canPbuffer) { device = dev; + screen = scrn; drawable = draw; context = ctx; canCreateGLPbuffer = canPbuffer; readDrawableAvailable = readBufferAvail; } - WindowsGraphicsDevice getDevice() { return device; } - WindowsWGLContext getContext() { return context; } - boolean canCreateGLPbuffer() { return canCreateGLPbuffer; } - boolean isReadDrawableAvailable() { return readDrawableAvailable; } + final public AbstractGraphicsDevice getDevice() { return device; } + final public AbstractGraphicsScreen getScreen() { return screen; } + final public GLDrawableImpl getDrawable() { return drawable; } + final public GLContextImpl getContext() { return context; } + final boolean canCreateGLPbuffer() { return canCreateGLPbuffer; } + final boolean isReadDrawableAvailable() { return readDrawableAvailable; } + } + + class SharedResourceImplementation implements SharedResourceRunner.Implementation { + public void clear() { + synchronized(sharedMap) { + sharedMap.clear(); + } + } + public SharedResourceRunner.Resource mapPut(String connection, SharedResourceRunner.Resource resource) { + synchronized(sharedMap) { + return (SharedResourceRunner.Resource) sharedMap.put(connection, resource); + } + } + public SharedResourceRunner.Resource mapGet(String connection) { + synchronized(sharedMap) { + return (SharedResourceRunner.Resource) sharedMap.get(connection); + } + } + public Collection/*<Resource>*/ mapValues() { + synchronized(sharedMap) { + return sharedMap.values(); + } + } + + public SharedResourceRunner.Resource createSharedResource(String connection) { + WindowsGraphicsDevice sharedDevice = new WindowsGraphicsDevice(connection, AbstractGraphicsDevice.DEFAULT_UNIT); + sharedDevice.lock(); + try { + AbstractGraphicsScreen absScreen = new DefaultGraphicsScreen(sharedDevice, 0); + if (null == absScreen) { + throw new GLException("Couldn't create shared screen for device: "+sharedDevice+", idx 0"); + } + GLProfile glp = GLProfile.getMinDesktop(sharedDevice); + if (null == glp) { + throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice); + } + WindowsDummyWGLDrawable sharedDrawable = WindowsDummyWGLDrawable.create(WindowsWGLDrawableFactory.this, glp, absScreen); + if (null == sharedDrawable) { + throw new GLException("Couldn't create shared drawable for screen: "+absScreen+", "+glp); + } + WindowsWGLContext sharedContext = (WindowsWGLContext) sharedDrawable.createContext(null); + if (null == sharedContext) { + throw new GLException("Couldn't create shared context for drawable: "+sharedDrawable); + } + sharedContext.setSynchronized(true); + boolean canCreateGLPbuffer; + boolean readDrawableAvailable; + sharedContext.makeCurrent(); + try { + canCreateGLPbuffer = sharedContext.getGL().isExtensionAvailable(GL_ARB_pbuffer); + readDrawableAvailable = sharedContext.isExtensionAvailable(WGL_ARB_make_current_read) && + sharedContext.isFunctionAvailable(wglMakeContextCurrent); + } finally { + sharedContext.release(); + } + if (DEBUG) { + System.err.println("!!! SharedDevice: " + sharedDevice); + System.err.println("!!! SharedScreen: " + absScreen); + System.err.println("!!! SharedContext: " + sharedContext); + System.err.println("!!! pbuffer avail: " + canCreateGLPbuffer); + System.err.println("!!! readDrawable: " + readDrawableAvailable); + } + return new SharedResource(sharedDevice, absScreen, sharedDrawable, sharedContext, readDrawableAvailable, canCreateGLPbuffer); + } catch (Throwable t) { + throw new GLException("WindowsWGLDrawableFactory - Could not initialize shared resources for "+connection, t); + } finally { + sharedDevice.unlock(); + } + } + + public void releaseSharedResource(SharedResourceRunner.Resource shared) { + SharedResource sr = (SharedResource) shared; + if (DEBUG) { + System.err.println("!!! Shutdown Shared:"); + System.err.println("!!! Device : " + sr.device); + System.err.println("!!! Screen : " + sr.screen); + System.err.println("!!! Drawable: " + sr.drawable); + System.err.println("!!! CTX : " + sr.context); + } + + if (null != sr.context) { + // may cause JVM SIGSEGV: sharedContext.destroy(); + sr.context = null; + } + + if (null != sr.drawable) { + sr.drawable.destroy(); + sr.drawable = null; + } + + if (null != sr.screen) { + sr.screen = null; + } + + if (null != sr.device) { + sr.device.close(); + sr.device = null; + } + } } - HashMap/*<connection, SharedResource>*/ sharedMap = new HashMap(); - WindowsGraphicsDevice defaultDevice; public final AbstractGraphicsDevice getDefaultDevice() { return defaultDevice; @@ -145,62 +298,24 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { return false; } - HashSet devicesTried = new HashSet(); - private final boolean getDeviceTried(String connection) { - synchronized(devicesTried) { - return devicesTried.contains(connection); - } - } - private final void addDeviceTried(String connection) { - synchronized(devicesTried) { - devicesTried.add(connection); - } - } - final static String GL_ARB_pbuffer = "GL_ARB_pbuffer"; final static String WGL_ARB_make_current_read = "WGL_ARB_make_current_read"; final static String wglMakeContextCurrent = "wglMakeContextCurrent"; - private SharedResource getOrCreateShared(AbstractGraphicsDevice device) { - String connection = device.getConnection(); - SharedResource sr; - synchronized(sharedMap) { - sr = (SharedResource) sharedMap.get(connection); + protected final GLContext getSharedContextImpl(AbstractGraphicsDevice device) { + SharedResourceRunner.Resource sr = sharedResourceRunner.getShared(device); + if(null!=sr) { + return sr.getContext(); } - if(null==sr && !getDeviceTried(connection)) { - addDeviceTried(connection); - NativeWindowFactory.getDefaultToolkitLock().lock(); // OK - try { - WindowsGraphicsDevice sharedDevice = new WindowsGraphicsDevice(connection, AbstractGraphicsDevice.DEFAULT_UNIT); - GLProfile glp = GLProfile.getDefault(/*sharedDevice*/); // can't fetch device profile, which shared resource we create here - AbstractGraphicsScreen absScreen = new DefaultGraphicsScreen(sharedDevice, 0); - WindowsDummyWGLDrawable sharedDrawable = WindowsDummyWGLDrawable.create(this, glp, absScreen); - WindowsWGLContext ctx = (WindowsWGLContext) sharedDrawable.createContext(null); - ctx.makeCurrent(); - boolean canCreateGLPbuffer = ctx.getGL().isExtensionAvailable(GL_ARB_pbuffer); - boolean readDrawableAvailable = ctx.isExtensionAvailable(WGL_ARB_make_current_read) && - ctx.isFunctionAvailable(wglMakeContextCurrent); - ctx.release(); - sr = new SharedResource(sharedDevice, sharedDrawable, ctx, readDrawableAvailable, canCreateGLPbuffer); - synchronized(sharedMap) { - sharedMap.put(connection, sr); - } - if (DEBUG) { - System.err.println("!!! SharedContext: "+ctx+", pbuffer supported "+canCreateGLPbuffer+ - ", readDrawable supported "+readDrawableAvailable); - } + return null; + } - } catch (Throwable t) { - throw new GLException("WindowsWGLDrawableFactory - Could not initialize shared resources", t); - } finally { - NativeWindowFactory.getDefaultToolkitLock().unlock(); // OK - } - } - return sr; + protected final boolean hasSharedContextImpl(AbstractGraphicsDevice device) { + return null != getSharedContextImpl(device); } protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared(device); + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); if(null!=sr) { return sr.getContext(); } @@ -208,43 +323,32 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { } protected AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared(device); + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); if(null!=sr) { return sr.getDevice(); } return null; } - protected final void shutdownInstance() { - if (DEBUG) { - Exception e = new Exception("Debug"); - e.printStackTrace(); + protected WindowsWGLDrawable getOrCreateSharedDrawable(AbstractGraphicsDevice device) { + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); + if(null!=sr) { + return (WindowsWGLDrawable) sr.getDrawable(); } - Collection/*<SharedResource>*/ sharedResources = sharedMap.values(); - for(Iterator iter=sharedResources.iterator(); iter.hasNext(); ) { - SharedResource sr = (SharedResource) iter.next(); - - if (DEBUG) { - System.err.println("!!! Shutdown Shared:"); - System.err.println("!!! Drawable: "+sr.drawable); - System.err.println("!!! CTX : "+sr.context); - } + return null; + } - if (null != sr.context) { - // may cause JVM SIGSEGV: sharedContext.destroy(); - sr.context = null; - } + SharedResource getOrCreateSharedResource(AbstractGraphicsDevice device) { + return (SharedResource) sharedResourceRunner.getOrCreateShared(device); + } - if (null != sr.drawable) { - // may cause JVM SIGSEGV: sharedDrawable.destroy(); - sr.drawable = null; - } + protected final void shutdownInstance() { + sharedResourceRunner.releaseAndWait(); + RegisteredClassFactory.shutdownSharedClasses(); + } - } - sharedMap.clear(); - if (DEBUG) { - System.err.println("!!! Shutdown Shared Finished"); - } + protected List/*GLCapabilitiesImmutable*/ getAvailableCapabilitiesImpl(AbstractGraphicsDevice device) { + return WindowsWGLGraphicsConfigurationFactory.getAvailableCapabilities(this, device); } protected final GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target) { @@ -267,7 +371,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { // PBuffer GLDrawable Creation final AbstractGraphicsDevice device = config.getScreen().getDevice(); - final SharedResource sr = getOrCreateShared(device); + final SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device); if(null==sr) { throw new IllegalArgumentException("No shared resource for "+device); } @@ -278,19 +382,17 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { if (lastContext != null) { lastContext.release(); } - synchronized(sr.context) { - sr.context.makeCurrent(); - try { - GLDrawableImpl pbufferDrawable = new WindowsPbufferWGLDrawable(WindowsWGLDrawableFactory.this, target, - sr.drawable, - sr.context); - returnList.add(pbufferDrawable); - } finally { - sr.context.release(); - if (lastContext != null) { - lastContext.makeCurrent(); - } - } + sr.context.makeCurrent(); + try { + GLDrawableImpl pbufferDrawable = new WindowsPbufferWGLDrawable(WindowsWGLDrawableFactory.this, target, + sr.drawable, + sr.context); + returnList.add(pbufferDrawable); + } finally { + sr.context.release(); + if (lastContext != null) { + lastContext.makeCurrent(); + } } } }; @@ -303,7 +405,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { * and -1 if undefined yet, ie no shared device exist at this point. */ public final int isReadDrawableAvailable(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared((null!=device)?device:defaultDevice); + SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared((null!=device)?device:defaultDevice); if(null!=sr) { return sr.isReadDrawableAvailable() ? 1 : 0 ; } @@ -311,7 +413,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { } public final boolean canCreateGLPbuffer(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared((null!=device)?device:defaultDevice); + SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared((null!=device)?device:defaultDevice); if(null!=sr) { return sr.canCreateGLPbuffer(); } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfiguration.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfiguration.java index aa1b1b70d..36d78b38d 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfiguration.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfiguration.java @@ -33,12 +33,15 @@ package com.jogamp.opengl.impl.windows.wgl; +import java.util.ArrayList; +import java.util.List; + import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.DefaultGraphicsConfiguration; import javax.media.nativewindow.NativeSurface; -import javax.media.opengl.DefaultGLCapabilitiesChooser; +import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.opengl.GL; -import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; @@ -48,84 +51,128 @@ import javax.media.opengl.GLProfile; import com.jogamp.nativewindow.impl.windows.GDI; import com.jogamp.nativewindow.impl.windows.PIXELFORMATDESCRIPTOR; import com.jogamp.opengl.impl.GLContextImpl; -import javax.media.opengl.GLCapabilitiesImmutable; +import com.jogamp.opengl.impl.GLGraphicsConfigurationUtil; public class WindowsWGLGraphicsConfiguration extends DefaultGraphicsConfiguration implements Cloneable { // Keep this under the same debug flag as the drawable factory for convenience protected static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug("GraphicsConfiguration"); + final static String WGL_ARB_pixel_format = "WGL_ARB_pixel_format"; + final static String WGL_ARB_multisample = "WGL_ARB_multisample"; + protected static final int MAX_PFORMATS = 256; protected static final int MAX_ATTRIBS = 256; - private PIXELFORMATDESCRIPTOR pixelfmt; - private int pixelfmtID; - private boolean isChosen = false; private GLCapabilitiesChooser chooser; - private boolean choosenByWGLPixelFormat=false; + private boolean isChosen = false; WindowsWGLGraphicsConfiguration(AbstractGraphicsScreen screen, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, - PIXELFORMATDESCRIPTOR pixelfmt, int pixelfmtID, GLCapabilitiesChooser chooser) { + GLCapabilitiesChooser chooser) { super(screen, capsChosen, capsRequested); this.chooser=chooser; - this.pixelfmt = pixelfmt; - this.pixelfmtID = pixelfmtID; + this.isChosen = false; } - static WindowsWGLGraphicsConfiguration create(long hdc, int pfdID, + WindowsWGLGraphicsConfiguration(AbstractGraphicsScreen screen, + WGLGLCapabilities capsChosen, GLCapabilitiesImmutable capsRequested) { + super(screen, capsChosen, capsRequested); + setCapsPFD(capsChosen); + this.chooser=null; + } + + + static WindowsWGLGraphicsConfiguration create(GLDrawableFactory _factory, long hdc, int pfdID, GLProfile glp, AbstractGraphicsScreen screen, boolean onscreen, boolean usePBuffer) { + if(_factory==null) { + throw new GLException("Null factory"); + } + if(hdc==0) { + throw new GLException("Null HDC"); + } if(pfdID<=0) { throw new GLException("Invalid pixelformat id "+pfdID); } if(null==glp) { glp = GLProfile.getDefault(screen.getDevice()); } - PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(); - if (GDI.DescribePixelFormat(hdc, pfdID, pfd.size(), pfd) == 0) { - throw new GLException("Unable to describe pixel format " + pfdID); + WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory) _factory; + AbstractGraphicsDevice device = screen.getDevice(); + WindowsWGLContext sharedContext = (WindowsWGLContext) factory.getOrCreateSharedContextImpl(device); + boolean hasARB = null != sharedContext && sharedContext.isExtensionAvailable(WGL_ARB_pixel_format) ; + + WGLGLCapabilities caps = null; + + if(hasARB) { + sharedContext.makeCurrent(); + try { + caps = wglARBPFID2GLCapabilities(sharedContext, hdc, pfdID, glp, onscreen, usePBuffer); + } finally { + sharedContext.release(); + } + } else if(!usePBuffer) { + caps = PFD2GLCapabilities(glp, hdc, pfdID, onscreen); } - - GLCapabilitiesImmutable caps = PFD2GLCapabilities(glp, pfd, onscreen, usePBuffer); if(null==caps) { - throw new GLException("Couldn't choose Capabilities by: HDC 0x"+Long.toHexString(hdc)+", pfdID "+pfdID); + throw new GLException("Couldn't choose Capabilities by: HDC 0x"+Long.toHexString(hdc)+", pfdID "+pfdID+", hasARB "+hasARB); } - WindowsWGLGraphicsConfiguration cfg = new WindowsWGLGraphicsConfiguration(screen, caps, caps, pfd, pfdID, new DefaultGLCapabilitiesChooser()); - cfg.setCapsPFD(caps, pfd, pfdID, false); - return cfg; + return new WindowsWGLGraphicsConfiguration(screen, caps, caps); } public Object clone() { return super.clone(); } - final void updateGraphicsConfiguration(GLDrawableFactory factory, NativeSurface ns) { - WindowsWGLGraphicsConfigurationFactory.updateGraphicsConfiguration(chooser, factory, ns); + /** + * Updates the graphics configuration in case it has been determined yet.<br> + * Uses the NativeSurface's HDC.<br> + * Ensures that a PIXELFORMAT is set. + * + * @param factory + * @param ns + * @param pfIDs optional pool of preselected PixelFormat IDs, maybe null for unrestricted selection + * + * @see #isDetermined() + */ + public final void updateGraphicsConfiguration(GLDrawableFactory factory, NativeSurface ns, int[] pfIDs) { + WindowsWGLGraphicsConfigurationFactory.updateGraphicsConfiguration(chooser, factory, ns, pfIDs); } - void setCapsPFD(GLCapabilitiesImmutable caps, PIXELFORMATDESCRIPTOR pfd, int pfdID, boolean choosenByWGLPixelFormat) { - this.pixelfmt = pfd; - this.pixelfmtID = pfdID; + /** + * Preselect the graphics configuration in case it has been determined yet.<br> + * Uses a shared device's HDC and the given pfdIDs to preselect the pfd. + * No PIXELFORMAT is set. + * + * @param factory + * @param pfIDs optional pool of preselected PixelFormat IDs, maybe null for unrestricted selection + * + * @see #isDetermined() + */ + public final void preselectGraphicsConfiguration(GLDrawableFactory factory, int[] pfdIDs) { + AbstractGraphicsDevice device = getNativeGraphicsConfiguration().getScreen().getDevice(); + WindowsWGLGraphicsConfigurationFactory.preselectGraphicsConfiguration(chooser, factory, device, this, pfdIDs); + } + + final void setCapsPFD(WGLGLCapabilities caps) { setChosenCapabilities(caps); this.isChosen=true; - this.choosenByWGLPixelFormat=choosenByWGLPixelFormat; if (DEBUG) { - System.err.println("*** setCapsPFD: WGL-Choosen "+choosenByWGLPixelFormat+", pfdID "+pfdID+", "+caps); + System.err.println("*** setCapsPFD: "+caps); } } - public boolean getCapabilitiesChosen() { - return isChosen; - } - - public PIXELFORMATDESCRIPTOR getPixelFormat() { return pixelfmt; } - public int getPixelFormatID() { return pixelfmtID; } - public boolean isChoosenByWGL() { return choosenByWGLPixelFormat; } + public final boolean isDetermined() { return isChosen; } + public final PIXELFORMATDESCRIPTOR getPixelFormat() { return isChosen ? ((WGLGLCapabilities)capabilitiesChosen).getPFD() : null; } + public final int getPixelFormatID() { return isChosen ? ((WGLGLCapabilities)capabilitiesChosen).getPFDID() : 0; } + public final boolean isChoosenByARB() { return isChosen ? ((WGLGLCapabilities)capabilitiesChosen).isSetByARB() : false; } static int fillAttribsForGeneralWGLARBQuery(boolean haveWGLARBMultisample, int[] iattributes) { int niattribs = 0; iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_WINDOW_ARB; + iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_PBUFFER_ARB; + iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_BITMAP_ARB; iattributes[niattribs++] = WGLExt.WGL_ACCELERATION_ARB; iattributes[niattribs++] = WGLExt.WGL_SUPPORT_OPENGL_ARB; iattributes[niattribs++] = WGLExt.WGL_DEPTH_BITS_ARB; @@ -145,6 +192,10 @@ public class WindowsWGLGraphicsConfiguration extends DefaultGraphicsConfiguratio iattributes[niattribs++] = WGLExt.WGL_SAMPLE_BUFFERS_ARB; iattributes[niattribs++] = WGLExt.WGL_SAMPLES_ARB; } + // pbo float buffer + iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB; // ati + iattributes[niattribs++] = WGLExt.WGL_FLOAT_COMPONENTS_NV; // nvidia + return niattribs; } @@ -159,177 +210,147 @@ public class WindowsWGLGraphicsConfiguration extends DefaultGraphicsConfiguratio return true; } - static GLCapabilitiesImmutable wglARBPFID2GLCapabilities(WindowsWGLContext sharedCtx, long hdc, int pfdID, - GLProfile glp, boolean onscreen, boolean usePBuffer) { - boolean haveWGLChoosePixelFormatARB = sharedCtx.isExtensionAvailable("WGL_ARB_pixel_format"); + static int[] wglAllARBPFIDs(WindowsWGLContext sharedCtx, long hdc) { + int[] iattributes = new int[1]; + int[] iresults = new int[1]; + + WGLExt wglExt = sharedCtx.getWGLExt(); + iattributes[0] = WGLExt.WGL_NUMBER_PIXEL_FORMATS_ARB; + if (!wglExt.wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, iattributes, 0, iresults, 0)) { + if(DEBUG) { + System.err.println("GetPixelFormatAttribivARB: Failed - HDC 0x" + Long.toHexString(hdc) + + ", LastError: " + GDI.GetLastError()); + Thread.dumpStack(); + } + return null; + } + int numFormats = iresults[0]; + if(0 == numFormats) { + if(DEBUG) { + System.err.println("GetPixelFormatAttribivARB: No formats - HDC 0x" + Long.toHexString(hdc) + + ", LastError: " + GDI.GetLastError()); + Thread.dumpStack(); + } + return null; + } + int[] pfdIDs = new int[numFormats]; + for (int i = 0; i < numFormats; i++) { + pfdIDs[i] = 1 + i; + } + return pfdIDs; + } + + static WGLGLCapabilities wglARBPFID2GLCapabilities(WindowsWGLContext sharedCtx, long hdc, int pfdID, + GLProfile glp, boolean onscreen, boolean usePBuffer) { + boolean haveWGLChoosePixelFormatARB = sharedCtx.isExtensionAvailable(WGL_ARB_pixel_format); if (!haveWGLChoosePixelFormatARB) { return null; } - boolean haveWGLARBMultisample = sharedCtx.isExtensionAvailable("WGL_ARB_multisample"); + boolean haveWGLARBMultisample = sharedCtx.isExtensionAvailable(WGL_ARB_multisample); int[] iattributes = new int [2*MAX_ATTRIBS]; int[] iresults = new int [2*MAX_ATTRIBS]; - iattributes[0] = WGLExt.WGL_NUMBER_PIXEL_FORMATS_ARB; - if (sharedCtx.getWGLExt().wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, iattributes, 0, iresults, 0)) { - if(iresults[0] > 0 ) { - int niattribs = fillAttribsForGeneralWGLARBQuery(haveWGLARBMultisample, iattributes); - if (!sharedCtx.getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdID, 0, niattribs, iattributes, 0, iresults, 0)) { - throw new GLException("wglARBPFID2GLCapabilities: Error getting pixel format attributes for pixel format " + pfdID + " of device context"); - } - return AttribList2GLCapabilities(glp, iattributes, niattribs, iresults, - onscreen, usePBuffer); - } + int niattribs = fillAttribsForGeneralWGLARBQuery(haveWGLARBMultisample, iattributes); + + if (!sharedCtx.getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdID, 0, niattribs, iattributes, 0, iresults, 0)) { + throw new GLException("wglARBPFID2GLCapabilities: Error getting pixel format attributes for pixel format " + pfdID + " of device context"); } - long lastErr = GDI.GetLastError(); - // Intel Extreme graphics fails with a zero error code - if (lastErr != 0) { - throw new GLException("wglARBPFID2GLCapabilities: Unable to enumerate pixel formats of window using wglGetPixelFormatAttribivARB: error code " + GDI.GetLastError()); + ArrayList bucket = new ArrayList(1); + final int winattrbits = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer); + if(AttribList2GLCapabilities(bucket, glp, hdc, pfdID, iattributes, niattribs, iresults, winattrbits)) { + return (WGLGLCapabilities) bucket.get(0); } return null; } - static int wglChoosePixelFormatARB(long hdc, WindowsWGLContext sharedContext, - GLCapabilitiesImmutable capabilities, - int[] iattributes, int accelerationMode, float[] fattributes, - int[] pformats) + static int[] wglChoosePixelFormatARB(long hdc, WindowsWGLContext sharedContext, + GLCapabilitiesImmutable capabilities, + int[] iattributes, int accelerationMode, float[] fattributes) { - int numFormats = -1; - - if(WindowsWGLGraphicsConfiguration.GLCapabilities2AttribList(capabilities, - iattributes, - sharedContext, - accelerationMode, - false, - null)) { - int[] numFormatsTmp = new int[1]; - if (sharedContext.getWGLExt().wglChoosePixelFormatARB(hdc, - iattributes, 0, - fattributes, 0, - WindowsWGLGraphicsConfiguration.MAX_PFORMATS, - pformats, 0, - numFormatsTmp, 0)) { - numFormats = numFormatsTmp[0]; - if (DEBUG) { - System.err.println("wglChoosePixelFormatARB1: NumFormats (wglChoosePixelFormatARB) accelMode 0x" + - Integer.toHexString(accelerationMode) + ": " + numFormats + " / " + WindowsWGLGraphicsConfiguration.MAX_PFORMATS); - } - } else { - if (DEBUG) { - System.err.println("wglChoosePixelFormatARB1: wglChoosePixelFormatARB failed: " + GDI.GetLastError() ); - Thread.dumpStack(); - } - } - } else { - if (DEBUG) { - System.err.println("wglChoosePixelFormatARB1: GLCapabilities2AttribList failed: " + GDI.GetLastError() ); - Thread.dumpStack(); - } - } - return numFormats; - } - static GLCapabilitiesImmutable[] wglARBPFIDs2GLCapabilities(WindowsWGLContext sharedCtx, long hdc, int[] pfdIDs, int numFormats, - GLProfile glp, boolean onscreen, boolean usePBuffer) { - boolean haveWGLChoosePixelFormatARB = sharedCtx.isExtensionAvailable("WGL_ARB_pixel_format"); - if (!haveWGLChoosePixelFormatARB) { + if ( !WindowsWGLGraphicsConfiguration.GLCapabilities2AttribList(capabilities, + iattributes, sharedContext, accelerationMode, null)) + { + if (DEBUG) { + System.err.println("wglChoosePixelFormatARB1: GLCapabilities2AttribList failed: " + GDI.GetLastError()); + Thread.dumpStack(); + } return null; } - boolean haveWGLARBMultisample = sharedCtx.isExtensionAvailable("WGL_ARB_multisample"); - - GLCapabilitiesImmutable[] caps = new GLCapabilitiesImmutable[numFormats]; - int[] iattributes = new int [2*MAX_ATTRIBS]; - int[] iresults = new int [2*MAX_ATTRIBS]; - int niattribs = fillAttribsForGeneralWGLARBQuery(haveWGLARBMultisample, iattributes); - - for(int i = 0; i<numFormats; i++) { - if ( pfdIDs[i] >= 1 && - sharedCtx.getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdIDs[i], 0, niattribs, iattributes, 0, iresults, 0) ) { - caps[i] = AttribList2GLCapabilities(glp, iattributes, niattribs, iresults, onscreen, usePBuffer); - } else { - if (DEBUG) { - System.err.println("wglARBPFIDs2GLCapabilities: Cannot get pixel format attributes for pixel format " + - i + "/" + numFormats + ": " + pfdIDs[i]); - } - caps[i] = null; + int[] pformatsTmp = new int[WindowsWGLGraphicsConfiguration.MAX_PFORMATS]; + int[] numFormatsTmp = new int[1]; + if ( !sharedContext.getWGLExt().wglChoosePixelFormatARB(hdc, iattributes, 0, + fattributes, 0, + WindowsWGLGraphicsConfiguration.MAX_PFORMATS, + pformatsTmp, 0, numFormatsTmp, 0)) + { + if (DEBUG) { + System.err.println("wglChoosePixelFormatARB1: wglChoosePixelFormatARB failed: " + GDI.GetLastError()); + Thread.dumpStack(); } + return null; } - return caps; + int numFormats = numFormatsTmp[0]; + int[] pformats = null; + if( 0 < numFormats ) { + pformats = new int[numFormats]; + System.arraycopy(pformatsTmp, 0, pformats, 0, numFormats); + } + if (DEBUG) { + System.err.println("wglChoosePixelFormatARB1: NumFormats (wglChoosePixelFormatARB) accelMode 0x" + + Integer.toHexString(accelerationMode) + ": " + numFormats); + } + return pformats; } - /** - * - * @param sharedCtx - * @param hdc - * @param glp - * @param onscreen - * @param usePBuffer - * @param pfIDs stores the PIXELFORMAT ID for the GLCapabilitiesImmutable[] - * @return the resulting GLCapabilitiesImmutable[] - */ - static GLCapabilitiesImmutable[] wglARBAllPFIDs2GLCapabilities(WindowsWGLContext sharedCtx, long hdc, - GLProfile glp, boolean onscreen, boolean usePBuffer, int[] pfIDs) { - boolean haveWGLChoosePixelFormatARB = sharedCtx.isExtensionAvailable("WGL_ARB_pixel_format"); + static List /*<GLCapabilitiesImmutable>*/ wglARBPFIDs2GLCapabilities(WindowsWGLContext sharedCtx, long hdc, int[] pfdIDs, + GLProfile glp, boolean onscreen, boolean usePBuffer) { + final int winattrbits = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer); + return wglARBPFIDs2GLCapabilitiesImpl(sharedCtx, hdc, pfdIDs, glp, winattrbits); + } + + static List /*<GLCapabilitiesImmutable>*/ wglARBPFIDs2AllGLCapabilities(WindowsWGLContext sharedCtx, long hdc, int[] pfdIDs, + GLProfile glp) { + return wglARBPFIDs2GLCapabilitiesImpl(sharedCtx, hdc, pfdIDs, glp, GLGraphicsConfigurationUtil.ALL_BITS); + } + + private static List /*<GLCapabilitiesImmutable>*/ wglARBPFIDs2GLCapabilitiesImpl(WindowsWGLContext sharedCtx, long hdc, int[] pfdIDs, + GLProfile glp, int winattrbits) { + boolean haveWGLChoosePixelFormatARB = sharedCtx.isExtensionAvailable(WGL_ARB_pixel_format); if (!haveWGLChoosePixelFormatARB) { return null; } - boolean haveWGLARBMultisample = sharedCtx.isExtensionAvailable("WGL_ARB_multisample"); - - // Produce a list of GLCapabilities to give to the - // GLCapabilitiesChooser. - // Use wglGetPixelFormatAttribivARB instead of - // DescribePixelFormat to get higher-precision information - // about the pixel format (should make the GLCapabilities - // more precise as well...i.e., remove the - // "HardwareAccelerated" bit, which is basically - // meaningless, and put in whether it can render to a - // window, to a pbuffer, or to a pixmap) - GLCapabilitiesImmutable[] availableCaps = null; - int numFormats = 0; - int niattribs = 0; - int[] iattributes = new int[2 * MAX_ATTRIBS]; - int[] iresults = new int[2 * MAX_ATTRIBS]; + boolean haveWGLARBMultisample = sharedCtx.isExtensionAvailable(WGL_ARB_multisample); + final int numFormats = pfdIDs.length; - WGLExt wglExt = sharedCtx.getWGLExt(); - iattributes[0] = WGLExt.WGL_NUMBER_PIXEL_FORMATS_ARB; - if (wglExt.wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, iattributes, 0, iresults, 0)) { - numFormats = iresults[0]; - if (DEBUG) { - System.err.println("wglARBAllPFIDs2GLCapabilities: wglGetPixelFormatAttribivARB reported WGL_NUMBER_PIXEL_FORMATS = " + numFormats + ", pfIDs sz "+pfIDs.length); - } - if (numFormats > pfIDs.length) { - numFormats = pfIDs.length; - } + int[] iattributes = new int [2*MAX_ATTRIBS]; + int[] iresults = new int [2*MAX_ATTRIBS]; + int niattribs = fillAttribsForGeneralWGLARBQuery(haveWGLARBMultisample, iattributes); - niattribs = fillAttribsForGeneralWGLARBQuery(haveWGLARBMultisample, iattributes); + ArrayList bucket = new ArrayList(); - availableCaps = new GLCapabilitiesImmutable[numFormats]; - for (int i = 0; i < numFormats; i++) { - pfIDs[i] = i + 1; - if (!wglExt.wglGetPixelFormatAttribivARB(hdc, pfIDs[i], 0, niattribs, iattributes, 0, iresults, 0)) { - throw new GLException("wglARBAllPFIDs2GLCapabilities: Error getting pixel format attributes for pixel format " + pfIDs[i]); - } - availableCaps[i] = AttribList2GLCapabilities(glp, iattributes, niattribs, iresults, onscreen, usePBuffer); - } - } else { - long lastErr = GDI.GetLastError(); - // Some GPU's falsely fails with a zero error code (success) - if (lastErr != GDI.ERROR_SUCCESS) { - throw new GLException("wglARBAllPFIDs2GLCapabilities: Unable to enumerate pixel formats of window using wglGetPixelFormatAttribivARB: error code " + lastErr); + for(int i = 0; i<numFormats; i++) { + if ( pfdIDs[i] >= 1 && + sharedCtx.getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdIDs[i], 0, niattribs, iattributes, 0, iresults, 0) ) { + AttribList2GLCapabilities(bucket, glp, hdc, pfdIDs[i], iattributes, niattribs, iresults, winattrbits); + } else if (DEBUG) { + System.err.println("wglARBPFIDs2GLCapabilities: Cannot get pixel format attributes for pixel format " + + i + "/" + numFormats + ": " + pfdIDs[i] + ", " + + GLGraphicsConfigurationUtil.winAttributeBits2String(null, winattrbits).toString()); } } - return availableCaps; + return bucket; } static boolean GLCapabilities2AttribList(GLCapabilitiesImmutable caps, int[] iattributes, GLContextImpl sharedCtx, - int accellerationValue, - boolean pbuffer, + int accellerationValue, int[] floatMode) throws GLException { - boolean haveWGLChoosePixelFormatARB = sharedCtx.isExtensionAvailable("WGL_ARB_pixel_format"); - boolean haveWGLARBMultisample = sharedCtx.isExtensionAvailable("WGL_ARB_multisample"); + boolean haveWGLChoosePixelFormatARB = sharedCtx.isExtensionAvailable(WGL_ARB_pixel_format); + boolean haveWGLARBMultisample = sharedCtx.isExtensionAvailable(WGL_ARB_multisample); if(DEBUG) { System.err.println("HDC2GLCapabilities: ARB_pixel_format: "+haveWGLChoosePixelFormatARB); System.err.println("HDC2GLCapabilities: ARB_multisample : "+haveWGLARBMultisample); @@ -339,6 +360,9 @@ public class WindowsWGLGraphicsConfiguration extends DefaultGraphicsConfiguratio return false; } + boolean onscreen = caps.isOnscreen(); + boolean pbuffer = caps.isPBuffer(); + int niattribs = 0; iattributes[niattribs++] = WGLExt.WGL_SUPPORT_OPENGL_ARB; @@ -347,11 +371,14 @@ public class WindowsWGLGraphicsConfiguration extends DefaultGraphicsConfiguratio iattributes[niattribs++] = WGLExt.WGL_ACCELERATION_ARB; iattributes[niattribs++] = accellerationValue; } - if (pbuffer) { + if (onscreen) { + iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_WINDOW_ARB; + iattributes[niattribs++] = GL.GL_TRUE; + } else if (pbuffer) { iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_PBUFFER_ARB; iattributes[niattribs++] = GL.GL_TRUE; } else { - iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_WINDOW_ARB; + iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_BITMAP_ARB; iattributes[niattribs++] = GL.GL_TRUE; } @@ -488,204 +515,120 @@ public class WindowsWGLGraphicsConfiguration extends DefaultGraphicsConfiguratio return true; } - public static final int WINDOW_BIT = 1 << 0 ; - public static final int BITMAP_BIT = 1 << 1 ; - public static final int PBUFFER_BIT = 1 << 2 ; - - static int WGLConfig2DrawableTypeBits(int[] iattribs, - int niattribs, - int[] iresults) { + static int AttribList2DrawableTypeBits(final int[] iattribs, final int niattribs, final int[] iresults) { int val = 0; for (int i = 0; i < niattribs; i++) { int attr = iattribs[i]; switch (attr) { case WGLExt.WGL_DRAW_TO_WINDOW_ARB: - if(iresults[i] == GL.GL_TRUE) val |= WINDOW_BIT; + if(iresults[i] == GL.GL_TRUE) val |= GLGraphicsConfigurationUtil.WINDOW_BIT; break; case WGLExt.WGL_DRAW_TO_BITMAP_ARB: - if(iresults[i] == GL.GL_TRUE) val |= BITMAP_BIT; + if(iresults[i] == GL.GL_TRUE) val |= GLGraphicsConfigurationUtil.BITMAP_BIT; break; case WGLExt.WGL_DRAW_TO_PBUFFER_ARB: - if(iresults[i] == GL.GL_TRUE) val |= PBUFFER_BIT; + if(iresults[i] == GL.GL_TRUE) val |= GLGraphicsConfigurationUtil.PBUFFER_BIT; break; } } return val; } - static boolean WGLConfigDrawableTypeVerify(int val, boolean onscreen, boolean usePBuffer) { - boolean res; + static boolean AttribList2GLCapabilities( ArrayList capsBucket, + final GLProfile glp, final long hdc, final int pfdID, final int[] iattribs, + final int niattribs, + final int[] iresults, final int winattrmask) { + final int allDrawableTypeBits = AttribList2DrawableTypeBits(iattribs, niattribs, iresults); + int drawableTypeBits = winattrmask & allDrawableTypeBits; - if ( onscreen ) { - res = ( 0 != (val & WINDOW_BIT) ) ; - } else { - if ( usePBuffer ) { - res = ( 0 != (val & PBUFFER_BIT) ) ; - } else { - res = ( 0 != (val & BITMAP_BIT) ) ; - } + if( 0 == drawableTypeBits ) { + return false; } + PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(); - return res; - } - - static GLCapabilitiesImmutable AttribList2GLCapabilities( - GLProfile glp, int[] iattribs, - int niattribs, - int[] iresults, - boolean onscreen, boolean usePBuffer) { - GLCapabilities res = new GLCapabilities(glp); - int drawableTypeBits = WGLConfig2DrawableTypeBits(iattribs, niattribs, iresults); - if(WGLConfigDrawableTypeVerify(drawableTypeBits, onscreen, usePBuffer)) { - res.setOnscreen(onscreen); - res.setPBuffer(usePBuffer); - } else { - if(DEBUG) { - System.err.println("WGL DrawableType does not match: req(onscrn "+onscreen+", pbuffer "+usePBuffer+"), got(onscreen "+( 0 != (drawableTypeBits & WINDOW_BIT) )+", pbuffer "+( 0 != (drawableTypeBits & PBUFFER_BIT) )+", pixmap "+( 0 != (drawableTypeBits & BITMAP_BIT))+")"); + if (GDI.DescribePixelFormat(hdc, pfdID, pfd.size(), pfd) == 0) { + // remove displayable bits, since pfdID is non displayable + drawableTypeBits = drawableTypeBits & ~(GLGraphicsConfigurationUtil.WINDOW_BIT | GLGraphicsConfigurationUtil.BITMAP_BIT); + if( 0 == drawableTypeBits ) { + return false; } - return null; + // non displayable requested (pbuffer) } + WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp); + res.setValuesByARB(iattribs, niattribs, iresults); - for (int i = 0; i < niattribs; i++) { - int attr = iattribs[i]; - switch (attr) { - case WGLExt.WGL_DRAW_TO_WINDOW_ARB: - case WGLExt.WGL_DRAW_TO_BITMAP_ARB: - case WGLExt.WGL_DRAW_TO_PBUFFER_ARB: - break; + return GLGraphicsConfigurationUtil.addGLCapabilitiesPermutations(capsBucket, res, drawableTypeBits ); + } - case WGLExt.WGL_ACCELERATION_ARB: - res.setHardwareAccelerated(iresults[i] == WGLExt.WGL_FULL_ACCELERATION_ARB); - break; + // + // GDI PIXELFORMAT + // - case WGLExt.WGL_SUPPORT_OPENGL_ARB: - if (iresults[i] != GL.GL_TRUE) { - return null; - } - break; + static int[] wglAllGDIPFIDs(long hdc) { + int numFormats = GDI.DescribePixelFormat(hdc, 1, 0, null); + if (numFormats == 0) { + throw new GLException("DescribePixelFormat: No formats - HDC 0x" + Long.toHexString(hdc) + + ", LastError: " + GDI.GetLastError()); + } + int[] pfdIDs = new int[numFormats]; + for (int i = 0; i < numFormats; i++) { + pfdIDs[i] = 1 + i; + } + return pfdIDs; + } - case WGLExt.WGL_DEPTH_BITS_ARB: - res.setDepthBits(iresults[i]); - break; + static int PFD2DrawableTypeBits(PIXELFORMATDESCRIPTOR pfd) { + int val = 0; - case WGLExt.WGL_STENCIL_BITS_ARB: - res.setStencilBits(iresults[i]); - break; + int dwFlags = pfd.getDwFlags(); - case WGLExt.WGL_DOUBLE_BUFFER_ARB: - res.setDoubleBuffered(iresults[i] == GL.GL_TRUE); - break; + if( 0 != (GDI.PFD_DRAW_TO_WINDOW & dwFlags ) ) { + val |= GLGraphicsConfigurationUtil.WINDOW_BIT; + } + if( 0 != (GDI.PFD_DRAW_TO_BITMAP & dwFlags ) ) { + val |= GLGraphicsConfigurationUtil.BITMAP_BIT; + } + return val; + } - case WGLExt.WGL_STEREO_ARB: - res.setStereo(iresults[i] == GL.GL_TRUE); - break; + static WGLGLCapabilities PFD2GLCapabilities(GLProfile glp, long hdc, int pfdID, boolean onscreen) { + final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, false); + ArrayList capsBucket = new ArrayList(1); + if( PFD2GLCapabilities(capsBucket, glp, hdc, pfdID, winattrmask) ) { + return (WGLGLCapabilities) capsBucket.get(0); + } + return null; + } - case WGLExt.WGL_PIXEL_TYPE_ARB: - // Fail softly with unknown results here - if (iresults[i] == WGLExt.WGL_TYPE_RGBA_ARB|| - iresults[i] == WGLExt.WGL_TYPE_RGBA_FLOAT_ARB) { - res.setPbufferFloatingPointBuffers(true); - } - break; + static boolean PFD2GLCapabilities(ArrayList capsBucket, final GLProfile glp, final long hdc, final int pfdID, final int winattrmask) { + PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(hdc, pfdID); + if(null == pfd) { + return false; + } + if ((pfd.getDwFlags() & GDI.PFD_SUPPORT_OPENGL) == 0) { + return false; + } + final int allDrawableTypeBits = PFD2DrawableTypeBits(pfd); + final int drawableTypeBits = winattrmask & allDrawableTypeBits; - case WGLExt.WGL_FLOAT_COMPONENTS_NV: - if (iresults[i] != 0) { - res.setPbufferFloatingPointBuffers(true); - } - break; - - case WGLExt.WGL_RED_BITS_ARB: - res.setRedBits(iresults[i]); - break; - - case WGLExt.WGL_GREEN_BITS_ARB: - res.setGreenBits(iresults[i]); - break; - - case WGLExt.WGL_BLUE_BITS_ARB: - res.setBlueBits(iresults[i]); - break; - - case WGLExt.WGL_ALPHA_BITS_ARB: - res.setAlphaBits(iresults[i]); - break; - - case WGLExt.WGL_ACCUM_RED_BITS_ARB: - res.setAccumRedBits(iresults[i]); - break; - - case WGLExt.WGL_ACCUM_GREEN_BITS_ARB: - res.setAccumGreenBits(iresults[i]); - break; - - case WGLExt.WGL_ACCUM_BLUE_BITS_ARB: - res.setAccumBlueBits(iresults[i]); - break; - - case WGLExt.WGL_ACCUM_ALPHA_BITS_ARB: - res.setAccumAlphaBits(iresults[i]); - break; - - case WGLExt.WGL_SAMPLE_BUFFERS_ARB: - res.setSampleBuffers(iresults[i] != 0); - break; - - case WGLExt.WGL_SAMPLES_ARB: - res.setNumSamples(iresults[i]); - break; - - default: - throw new GLException("Unknown pixel format attribute " + iattribs[i]); - } + if( 0 == drawableTypeBits ) { + return false; } - return res; - } - // PIXELFORMAT + WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp); + res.setValuesByGDI(); - static GLCapabilitiesImmutable PFD2GLCapabilities(GLProfile glp, PIXELFORMATDESCRIPTOR pfd, boolean onscreen, boolean usePBuffer) { - if ((pfd.getDwFlags() & GDI.PFD_SUPPORT_OPENGL) == 0) { - return null; - } - GLCapabilities res = new GLCapabilities(glp); - res.setRedBits (pfd.getCRedBits()); - res.setGreenBits (pfd.getCGreenBits()); - res.setBlueBits (pfd.getCBlueBits()); - res.setAlphaBits (pfd.getCAlphaBits()); - res.setAccumRedBits (pfd.getCAccumRedBits()); - res.setAccumGreenBits(pfd.getCAccumGreenBits()); - res.setAccumBlueBits (pfd.getCAccumBlueBits()); - res.setAccumAlphaBits(pfd.getCAccumAlphaBits()); - res.setDepthBits (pfd.getCDepthBits()); - res.setStencilBits (pfd.getCStencilBits()); - res.setDoubleBuffered((pfd.getDwFlags() & GDI.PFD_DOUBLEBUFFER) != 0); - res.setStereo ((pfd.getDwFlags() & GDI.PFD_STEREO) != 0); - res.setHardwareAccelerated( (pfd.getDwFlags() & GDI.PFD_GENERIC_FORMAT) == 0 || - (pfd.getDwFlags() & GDI.PFD_GENERIC_ACCELERATED) != 0 ); - res.setOnscreen ( onscreen && ((pfd.getDwFlags() & GDI.PFD_DRAW_TO_WINDOW) != 0) ); - res.setPBuffer ( usePBuffer ); - /* FIXME: Missing ?? - if (GLXUtil.isMultisampleAvailable()) { - res.setSampleBuffers(glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLE_BUFFERS, tmp, 0) != 0); - res.setNumSamples (glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLES, tmp, 0)); - } - res.setBackgroundOpaque(glXGetFBConfig(display, fbcfg, GLX.GLX_TRANSPARENT_TYPE, tmp, 0) != GLX.GLX_NONE); - try { - res.setPbufferFloatingPointBuffers(glXGetFBConfig(display, fbcfg, GLXExt.GLX_FLOAT_COMPONENTS_NV, tmp, 0) != GL.GL_FALSE); - } catch (Exception e) {} - */ - return res; + return GLGraphicsConfigurationUtil.addGLCapabilitiesPermutations(capsBucket, res, drawableTypeBits ); } - static PIXELFORMATDESCRIPTOR GLCapabilities2PFD(GLCapabilitiesImmutable caps) { + static PIXELFORMATDESCRIPTOR GLCapabilities2PFD(GLCapabilitiesImmutable caps, PIXELFORMATDESCRIPTOR pfd) { int colorDepth = (caps.getRedBits() + caps.getGreenBits() + caps.getBlueBits()); if (colorDepth < 15) { throw new GLException("Bit depths < 15 (i.e., non-true-color) not supported"); } - PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(); int pfdFlags = (GDI.PFD_SUPPORT_OPENGL | GDI.PFD_GENERIC_ACCELERATED); if (caps.getDoubleBuffered()) { @@ -718,27 +661,35 @@ public class WindowsWGLGraphicsConfiguration extends DefaultGraphicsConfiguratio pfd.setCStencilBits((byte) caps.getStencilBits()); pfd.setILayerType((byte) GDI.PFD_MAIN_PLANE); - /* FIXME: Missing: - caps.getSampleBuffers() - caps.getNumSamples () - } - caps.getBackgroundOpaque() - try { - caps.getPbufferFloatingPointBuffers() - } catch (Exception e) {} - */ + // n/a with non ARB/GDI method: + // multisample + // opaque + // pbuffer return pfd; } - static PIXELFORMATDESCRIPTOR createPixelFormatDescriptor() { + static PIXELFORMATDESCRIPTOR createPixelFormatDescriptor(long hdc, int pfdID) { PIXELFORMATDESCRIPTOR pfd = PIXELFORMATDESCRIPTOR.create(); pfd.setNSize((short) pfd.size()); pfd.setNVersion((short) 1); + if(0 != hdc && 1 <= pfdID) { + if (GDI.DescribePixelFormat(hdc, pfdID, pfd.size(), pfd) == 0) { + // Accelerated pixel formats that are non displayable + if(DEBUG) { + System.err.println("Info: Non displayable pixel format " + pfdID + " of device context: error code " + GDI.GetLastError()); + } + return null; + } + } return pfd; } + static PIXELFORMATDESCRIPTOR createPixelFormatDescriptor() { + return createPixelFormatDescriptor(0, 0); + } + public String toString() { - return "WindowsWGLGraphicsConfiguration["+getScreen()+", pfdID " + pixelfmtID + ", wglChoosen "+choosenByWGLPixelFormat+ + return "WindowsWGLGraphicsConfiguration["+getScreen()+", pfdID " + getPixelFormatID() + ", ARB-Choosen " + isChoosenByARB() + ",\n\trequested " + getRequestedCapabilities() + ",\n\tchosen " + getChosenCapabilities() + "]"; diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java index 87bbec018..812829168 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java @@ -39,10 +39,10 @@ import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.CapabilitiesChooser; import javax.media.nativewindow.DefaultGraphicsScreen; import javax.media.nativewindow.GraphicsConfigurationFactory; +import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.NativeSurface; -import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.NativeWindowFactory; -import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; @@ -50,17 +50,22 @@ import javax.media.opengl.GLProfile; import com.jogamp.nativewindow.impl.windows.GDI; import com.jogamp.nativewindow.impl.windows.PIXELFORMATDESCRIPTOR; -import javax.media.nativewindow.CapabilitiesImmutable; -import javax.media.opengl.DefaultGLCapabilitiesChooser; -import javax.media.opengl.GLCapabilitiesImmutable; +import com.jogamp.opengl.impl.GLGraphicsConfigurationFactory; +import com.jogamp.opengl.impl.GLGraphicsConfigurationUtil; +import com.jogamp.opengl.impl.SharedResourceRunner; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; /** Subclass of GraphicsConfigurationFactory used when non-AWT tookits are used on Windows platforms. Toolkits will likely need to delegate to this one to change the accepted and returned types of the GraphicsDevice and GraphicsConfiguration abstractions. */ -public class WindowsWGLGraphicsConfigurationFactory extends GraphicsConfigurationFactory { +public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory { protected static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug("GraphicsConfiguration"); + static WGLGLCapabilities.PfdIDComparator PfdIDComparator = new WGLGLCapabilities.PfdIDComparator(); WindowsWGLGraphicsConfigurationFactory() { GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.windows.WindowsGraphicsDevice.class, this); @@ -82,10 +87,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GraphicsConfiguratio static WindowsWGLGraphicsConfiguration createDefaultGraphicsConfiguration(GLCapabilitiesImmutable caps, AbstractGraphicsScreen absScreen) { - if(null==absScreen) { - absScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS); - } - return new WindowsWGLGraphicsConfiguration(absScreen, caps, caps, WindowsWGLGraphicsConfiguration.GLCapabilities2PFD(caps), -1, null); + return chooseGraphicsConfigurationStatic(caps, caps, null, absScreen); } static WindowsWGLGraphicsConfiguration chooseGraphicsConfigurationStatic(GLCapabilitiesImmutable capsChosen, @@ -95,21 +97,82 @@ public class WindowsWGLGraphicsConfigurationFactory extends GraphicsConfiguratio if(null==absScreen) { absScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS); } + AbstractGraphicsDevice absDevice = absScreen.getDevice(); + + capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( + capsChosen, GLDrawableFactory.getDesktopFactory().canCreateGLPbuffer(absDevice) ); - if(!capsChosen.isOnscreen() && capsChosen.getDoubleBuffered()) { - // OFFSCREEN !DOUBLE_BUFFER // FIXME DBLBUFOFFSCRN - GLCapabilities caps2 = (GLCapabilities) capsChosen.cloneMutable(); - caps2.setDoubleBuffered(false); - capsChosen = caps2; + return new WindowsWGLGraphicsConfiguration( absScreen, capsChosen, capsReq, (GLCapabilitiesChooser)chooser ); + } + + protected static List/*<WGLGLCapabilities>*/ getAvailableCapabilities(WindowsWGLDrawableFactory factory, AbstractGraphicsDevice device) { + SharedResourceRunner.Resource sharedResource = factory.getOrCreateSharedResource(device); + if(null == sharedResource) { + throw new GLException("Shared resource for device n/a: "+device); + } + WindowsWGLDrawable sharedDrawable = (WindowsWGLDrawable) sharedResource.getDrawable(); + GLCapabilitiesImmutable capsChosen = sharedDrawable.getChosenGLCapabilities(); + WindowsWGLContext sharedContext = (WindowsWGLContext) sharedResource.getContext(); + List availableCaps = null; + + sharedDrawable.lockSurface(); + try { + long hdc = sharedDrawable.getHandle(); + if (0 == hdc) { + throw new GLException("Error: HDC is null"); + } + if (sharedContext.isExtensionAvailable(WindowsWGLGraphicsConfiguration.WGL_ARB_pixel_format)) { + availableCaps = getAvailableGLCapabilitiesARB(hdc, sharedContext, capsChosen.getGLProfile()); + } + if( null == availableCaps || 0 == availableCaps.size() ) { + availableCaps = getAvailableGLCapabilitiesGDI(hdc, capsChosen); + } + } finally { + sharedDrawable.unlockSurface(); } - return new WindowsWGLGraphicsConfiguration(absScreen, capsChosen, capsReq, - WindowsWGLGraphicsConfiguration.GLCapabilities2PFD(capsChosen), -1, - (GLCapabilitiesChooser)chooser); + if( null != availableCaps ) { + Collections.sort(availableCaps, PfdIDComparator); + } + return availableCaps; } + static List/*<WGLGLCapabilities>*/ getAvailableGLCapabilitiesARB(long hdc, WindowsWGLContext sharedContext, GLProfile glProfile) { + int[] pformats = WindowsWGLGraphicsConfiguration.wglAllARBPFIDs(sharedContext, hdc); + return WindowsWGLGraphicsConfiguration.wglARBPFIDs2AllGLCapabilities(sharedContext, hdc, pformats, glProfile); + } + + static List/*<WGLGLCapabilities>*/ getAvailableGLCapabilitiesGDI(long hdc, GLCapabilitiesImmutable capsChosen) { + boolean onscreen = capsChosen.isOnscreen(); + if(capsChosen.isPBuffer()) { + return null; + } + GLProfile glProfile = capsChosen.getGLProfile(); + + int[] pformats = WindowsWGLGraphicsConfiguration.wglAllGDIPFIDs(hdc); + int numFormats = pformats.length; + ArrayList bucket = new ArrayList(numFormats); + for (int i = 0; i < numFormats; i++) { + bucket.add( WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(glProfile, hdc, pformats[i], onscreen) ); + } + return bucket; + } + + /** + * + * @param chooser + * @param _factory + * @param ns + * @param pfIDs optional pool of preselected PixelFormat IDs, maybe null for unrestricted selection + */ static void updateGraphicsConfiguration(CapabilitiesChooser chooser, - GLDrawableFactory _factory, NativeSurface ns) { + GLDrawableFactory factory, NativeSurface ns, int[] pfdIDs) { + if (chooser != null && !(chooser instanceof GLCapabilitiesChooser)) { + throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects"); + } + if (factory == null) { + throw new IllegalArgumentException("GLDrawableFactory is null"); + } if (ns == null) { throw new IllegalArgumentException("NativeSurface is null"); } @@ -118,22 +181,75 @@ public class WindowsWGLGraphicsConfigurationFactory extends GraphicsConfiguratio throw new GLException("Error: HDC is null"); } WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration) ns.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + + if(!config.isDetermined()) { + updateGraphicsConfiguration(config, chooser, factory, hdc, false, pfdIDs); + } else { + // set PFD if not set yet + int pfdID = -1; + boolean set = false; + if ( 1 > ( pfdID = GDI.GetPixelFormat(hdc) ) ) { + if (!GDI.SetPixelFormat(hdc, config.getPixelFormatID(), config.getPixelFormat())) { + throw new GLException("Unable to set pixel format " + config.getPixelFormatID() + + " for device context " + toHexString(hdc) + + ": error code " + GDI.GetLastError()); + } + set = true; + pfdID = config.getPixelFormatID(); + } + if (DEBUG) { + System.err.println("!!! setPixelFormat (post): hdc "+toHexString(hdc) +", "+config.getPixelFormatID()+" -> "+pfdID+", set: "+set); + Thread.dumpStack(); + } + } + } + + static void preselectGraphicsConfiguration(CapabilitiesChooser chooser, + GLDrawableFactory _factory, AbstractGraphicsDevice device, + WindowsWGLGraphicsConfiguration config, int[] pfdIDs) { if (chooser != null && !(chooser instanceof GLCapabilitiesChooser)) { throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects"); } + if (_factory == null) { + throw new IllegalArgumentException("GLDrawableFactory is null"); + } + if (config == null) { + throw new IllegalArgumentException("WindowsWGLGraphicsConfiguration is null"); + } + WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory) _factory; + WindowsWGLDrawable sharedDrawable = factory.getOrCreateSharedDrawable(device); + if(null == sharedDrawable) { + throw new IllegalArgumentException("Shared Drawable is null"); + } + sharedDrawable.lockSurface(); + try { + long hdc = sharedDrawable.getHandle(); + if (0 == hdc) { + throw new GLException("Error: HDC is null"); + } + updateGraphicsConfiguration(config, chooser, factory, hdc, true, pfdIDs); + } finally { + sharedDrawable.unlockSurface(); + } + } + private static void updateGraphicsConfiguration(WindowsWGLGraphicsConfiguration config, CapabilitiesChooser chooser, + GLDrawableFactory factory, long hdc, boolean extHDC, int[] pfdIDs) { if (DEBUG) { - System.err.println("updateGraphicsConfiguration: hdc "+toHexString(hdc)); + if(extHDC) { + System.err.println("updateGraphicsConfiguration(using shared): hdc "+toHexString(hdc)); + } else { + System.err.println("updateGraphicsConfiguration(using target): hdc "+toHexString(hdc)); + } System.err.println("!!! user chosen caps " + config.getChosenCapabilities()); } - - if( !updateGraphicsConfigurationARB(hdc, config, chooser, (WindowsWGLDrawableFactory) _factory) ) { - updateGraphicsConfigurationGDI(hdc, config, chooser, (WindowsWGLDrawableFactory) _factory); + if( !updateGraphicsConfigurationARB(hdc, extHDC, config, chooser, (WindowsWGLDrawableFactory)factory, pfdIDs) ) { + updateGraphicsConfigurationGDI(hdc, extHDC, config, chooser, pfdIDs); } } - private static boolean updateGraphicsConfigurationARB(long hdc, WindowsWGLGraphicsConfiguration config, - CapabilitiesChooser chooser, WindowsWGLDrawableFactory factory) { + private static boolean updateGraphicsConfigurationARB(long hdc, boolean extHDC, WindowsWGLGraphicsConfiguration config, + CapabilitiesChooser chooser, WindowsWGLDrawableFactory factory, int[] pformats) { AbstractGraphicsDevice device = config.getScreen().getDevice(); WindowsWGLContext sharedContext = (WindowsWGLContext) factory.getOrCreateSharedContextImpl(device); if (null == sharedContext) { @@ -142,282 +258,204 @@ public class WindowsWGLGraphicsConfigurationFactory extends GraphicsConfiguratio } return false; } + if (!sharedContext.isExtensionAvailable(WindowsWGLGraphicsConfiguration.WGL_ARB_pixel_format)) { + if (DEBUG) { + System.err.println("updateGraphicsConfigurationARB: "+WindowsWGLGraphicsConfiguration.WGL_ARB_pixel_format+" not available"); + } + return false; + } + GLCapabilitiesImmutable capsChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities(); boolean onscreen = capsChosen.isOnscreen(); boolean usePBuffer = capsChosen.isPBuffer(); GLProfile glProfile = capsChosen.getGLProfile(); - int pixelFormatSet = -1; // 1-based pixel format - GLCapabilitiesImmutable pixelFormatCaps = null; - - GLCapabilitiesImmutable[] availableCaps = null; - int[] pformats = null; // if != null, then index matches availableCaps - int numFormats = -1; - int recommendedIndex = -1; - - synchronized (sharedContext) { - sharedContext.makeCurrent(); - try { - if (!sharedContext.isExtensionAvailable("WGL_ARB_pixel_format")) { - if (DEBUG) { - System.err.println("updateGraphicsConfigurationARB: wglChoosePixelFormatARB not available"); - } - return false; + WGLGLCapabilities pixelFormatCaps = null; // chosen or preset PFD ID's caps + boolean pixelFormatSet = false; // indicates a preset PFD ID [caps] + + sharedContext.makeCurrent(); + try { + final int presetPFDID = extHDC ? -1 : GDI.GetPixelFormat(hdc) ; + if ( 1 <= presetPFDID ) { + // Pixelformat already set by either + // - a previous preselectGraphicsConfiguration() call on the same HDC, + // - the graphics driver, copying the HDC's pixelformat to the new one, + // - or the Java2D/OpenGL pipeline's configuration + if (DEBUG) { + System.err.println("updateGraphicsConfigurationARB: Pixel format already chosen for HDC: " + toHexString(hdc) + + ", pixelformat " + presetPFDID); } - if ((pixelFormatSet = GDI.GetPixelFormat(hdc)) >= 1) { - // Pixelformat already set by either - // - a previous updateGraphicsConfiguration() call on the same HDC, - // - the graphics driver, copying the HDC's pixelformat to the new one, - // - or the Java2D/OpenGL pipeline's configuration - if (DEBUG) { - System.err.println("updateGraphicsConfigurationARB: Pixel format already chosen for HDC: " + toHexString(hdc) - + ", pixelformat " + pixelFormatSet); - } - - // only fetch the specific one .. - pixelFormatCaps = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities(sharedContext, hdc, pixelFormatSet, glProfile, onscreen, usePBuffer); - } else { + pixelFormatSet = true; + pixelFormatCaps = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities(sharedContext, hdc, presetPFDID, glProfile, onscreen, usePBuffer); + } else { + int recommendedIndex = -1; // recommended index + + if(null == pformats) { + // No given PFD IDs + // + // 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice int[] iattributes = new int[2 * WindowsWGLGraphicsConfiguration.MAX_ATTRIBS]; float[] fattributes = new float[1]; - pformats = new int[WindowsWGLGraphicsConfiguration.MAX_PFORMATS]; - - // 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice - numFormats = WindowsWGLGraphicsConfiguration.wglChoosePixelFormatARB(hdc, sharedContext, capsChosen, - iattributes, -1, fattributes, pformats); - if (0 < numFormats) { - availableCaps = WindowsWGLGraphicsConfiguration.wglARBPFIDs2GLCapabilities(sharedContext, hdc, pformats, numFormats, - glProfile, onscreen, usePBuffer); - if (null != availableCaps) { - recommendedIndex = 0; - pixelFormatCaps = availableCaps[0]; - if (DEBUG) { - System.err.println("updateGraphicsConfigurationARB: NumFormats (wglChoosePixelFormatARB) " + numFormats + " / " + WindowsWGLGraphicsConfiguration.MAX_PFORMATS); - System.err.println("updateGraphicsConfigurationARB: Used wglChoosePixelFormatARB to recommend pixel format " + pformats[recommendedIndex] + ", idx " + recommendedIndex); - System.err.println("!!! recommended caps " + pixelFormatCaps); - } + pformats = WindowsWGLGraphicsConfiguration.wglChoosePixelFormatARB(hdc, sharedContext, capsChosen, + iattributes, -1, fattributes); + + if (null != pformats) { + recommendedIndex = 0; + } else { + if(DEBUG) { + System.err.println("updateGraphicsConfigurationARB: wglChoosePixelFormatARB failed with: "+capsChosen); } - } - - // 2nd choice: get all GLCapabilities available, no preferred recommendedIndex available - if (null == availableCaps) { + // 2nd choice: get all GLCapabilities available, no preferred recommendedIndex available + pformats = WindowsWGLGraphicsConfiguration.wglAllARBPFIDs(sharedContext, hdc); if (DEBUG) { - System.err.println("updateGraphicsConfigurationARB: wglChoosePixelFormatARB failed (Query all formats without recommendation): " + GDI.GetLastError()); + System.err.println("updateGraphicsConfigurationARB: NumFormats (wglAllARBPFIDs) " + pformats.length); } - availableCaps = WindowsWGLGraphicsConfiguration.wglARBAllPFIDs2GLCapabilities(sharedContext, hdc, - glProfile, onscreen, usePBuffer, pformats); - if (null != availableCaps) { - numFormats = availableCaps.length; + } + if (null == pformats) { + if (DEBUG) { + Thread.dumpStack(); } + return false; } } - } finally { - sharedContext.release(); - } - } // synchronized(factory.sharedContext) - - if (pixelFormatSet <= 0 && null == availableCaps) { - if (DEBUG) { - System.err.println("updateGraphicsConfigurationARB: No PixelFormat chosen via ARB ... (LastError: " + GDI.GetLastError() + ")"); - } - return false; - } - - int pfdID; - if (pixelFormatSet <= 0) { - if (null == pixelFormatCaps && null == chooser) { - chooser = new DefaultGLCapabilitiesChooser(); - } - - int chosenIndex = recommendedIndex; - try { - if (null != chooser) { - chosenIndex = chooser.chooseCapabilities(capsChosen, availableCaps, recommendedIndex); - pixelFormatCaps = availableCaps[chosenIndex]; + List /*<WGLGLCapabilities>*/ availableCaps = + WindowsWGLGraphicsConfiguration.wglARBPFIDs2GLCapabilities(sharedContext, hdc, pformats, + glProfile, onscreen, usePBuffer); + if( null == availableCaps || 0 == availableCaps.size() ) { if (DEBUG) { - System.err.println("updateGraphicsConfigurationARB: chooser: idx " + chosenIndex); - System.err.println("!!! chosen caps " + pixelFormatCaps); + System.err.println("updateGraphicsConfigurationARB: wglARBPFIDs2GLCapabilities failed with " + pformats.length + + " pfd ids, onscreen " + onscreen + ", pbuffer " + usePBuffer); + Thread.dumpStack(); } + return false; } - } catch (NativeWindowException e) { + if (DEBUG) { - e.printStackTrace(); + System.err.println("updateGraphicsConfigurationARB: " + pformats.length + + " pfd ids, onscreen " + onscreen + ", pbuffer " + usePBuffer + ", " + availableCaps.size() + " glcaps"); + if(0 <= recommendedIndex) { + System.err.println("updateGraphicsConfigurationARB: Used wglChoosePixelFormatARB to recommend pixel format " + + pformats[recommendedIndex] + ", idx " + recommendedIndex +", "+availableCaps.get(recommendedIndex)); + } } - } - if (chosenIndex < 0) { - // keep on going .. - // seek first available one .. - for (chosenIndex = 0; chosenIndex < availableCaps.length && availableCaps[chosenIndex] == null; chosenIndex++) { - // nop - } - if (chosenIndex == availableCaps.length) { - // give up .. + int chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex); + if ( 0 > chosenIndex ) { if (DEBUG) { - System.err.println("updateGraphicsConfigurationARB: Failed .. nothing available, bail out"); + Thread.dumpStack(); } return false; } - pixelFormatCaps = availableCaps[chosenIndex]; + pixelFormatCaps = (WGLGLCapabilities) availableCaps.get(chosenIndex); + if( null == pixelFormatCaps) { + throw new GLException("Null Capabilities with "+ + " chosen pfdID: native recommended "+ (recommendedIndex+1) + + " chosen "+pixelFormatCaps.getPFDID()); + } if (DEBUG) { - System.err.println("updateGraphicsConfigurationARB: Failed .. unable to choose config, using first available idx: " + chosenIndex); - System.err.println("!!! fallback caps " + pixelFormatCaps); + System.err.println("!!! chosen pfdID (ARB): native recommended "+ (recommendedIndex+1) + + " chosen "+pixelFormatCaps); } } - pfdID = pformats[chosenIndex]; - } else { - pfdID = pixelFormatSet; - } - if (DEBUG) { - System.err.println("updateGraphicsConfigurationARB: using pfdID "+pfdID); - } - - PIXELFORMATDESCRIPTOR pfd = WindowsWGLGraphicsConfiguration.createPixelFormatDescriptor(); - - if (GDI.DescribePixelFormat(hdc, pfdID, pfd.size(), pfd) == 0) { - throw new GLException("updateGraphicsConfigurationARB: Error describing the chosen pixel format: " + pfdID + ", " + GDI.GetLastError()); + } finally { + sharedContext.release(); } - if (pixelFormatSet <= 0) { - if (!GDI.SetPixelFormat(hdc, pfdID, pfd)) { - throw new GLException("Unable to set pixel format " + pfdID + + if ( !extHDC && !pixelFormatSet ) { + if (!GDI.SetPixelFormat(hdc, pixelFormatCaps.getPFDID(), pixelFormatCaps.getPFD())) { + throw new GLException("Unable to set pixel format " + pixelFormatCaps.getPFDID() + " for device context " + toHexString(hdc) + ": error code " + GDI.GetLastError()); } + if (DEBUG) { + System.err.println("!!! setPixelFormat (ARB): hdc "+toHexString(hdc) +", "+config.getPixelFormatID()+" -> "+pixelFormatCaps.getPFDID()); + } } - - config.setCapsPFD(pixelFormatCaps, pfd, pfdID, true); + config.setCapsPFD(pixelFormatCaps); return true; } - private static boolean updateGraphicsConfigurationGDI(long hdc, WindowsWGLGraphicsConfiguration config, - CapabilitiesChooser chooser, WindowsWGLDrawableFactory factory) { + private static boolean updateGraphicsConfigurationGDI(long hdc, boolean extHDC, WindowsWGLGraphicsConfiguration config, + CapabilitiesChooser chooser, int[] pformats) { GLCapabilitiesImmutable capsChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities(); + if(capsChosen.isPBuffer()) { + if (DEBUG) { + System.err.println("updateGraphicsConfigurationGDI: no pbuffer supported on GDI: " + capsChosen); + } + return false; + } boolean onscreen = capsChosen.isOnscreen(); - boolean usePBuffer = capsChosen.isPBuffer(); GLProfile glProfile = capsChosen.getGLProfile(); - int pixelFormatSet = -1; // 1-based pixel format - GLCapabilitiesImmutable pixelFormatCaps = null; + ArrayList/*<WGLGLCapabilities>*/ availableCaps = new ArrayList(); + int pfdID; // chosen or preset PFD ID + WGLGLCapabilities pixelFormatCaps = null; // chosen or preset PFD ID's caps + boolean pixelFormatSet = false; // indicates a preset PFD ID [caps] - GLCapabilitiesImmutable[] availableCaps = null; - int numFormats = -1; - int recommendedIndex = -1; - - if ((pixelFormatSet = GDI.GetPixelFormat(hdc)) != 0) { + if ( !extHDC && 1 <= ( pfdID = GDI.GetPixelFormat(hdc) ) ) { // Pixelformat already set by either - // - a previous updateGraphicsConfiguration() call on the same HDC, + // - a previous preselectGraphicsConfiguration() call on the same HDC, // - the graphics driver, copying the HDC's pixelformat to the new one, // - or the Java2D/OpenGL pipeline's configuration if (DEBUG) { System.err.println("updateGraphicsConfigurationGDI: NOTE: pixel format already chosen for HDC: " + toHexString(hdc) - + ", pixelformat " + pixelFormatSet); + + ", pixelformat " + pfdID); } - } + pixelFormatSet = true; + pixelFormatCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(glProfile, hdc, pfdID, onscreen); + } else { + if(null == pformats) { + pformats = WindowsWGLGraphicsConfiguration.wglAllGDIPFIDs(hdc); + } + final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, false); - int recommendedPixelFormat = pixelFormatSet; + for (int i = 0; i < pformats.length; i++) { + WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(availableCaps, glProfile, hdc, pformats[i], winattrmask); + } - numFormats = GDI.DescribePixelFormat(hdc, 1, 0, null); - if (numFormats == 0) { - throw new GLException("Unable to enumerate pixel formats of window " - + toHexString(hdc) + " for GLCapabilitiesChooser (LastError: " + GDI.GetLastError() + ")"); - } - if (DEBUG) { - System.err.println("updateGraphicsConfigurationGDI: NumFormats (DescribePixelFormat) " + numFormats); - } - - PIXELFORMATDESCRIPTOR pfd = WindowsWGLGraphicsConfiguration.createPixelFormatDescriptor(); - availableCaps = new GLCapabilitiesImmutable[numFormats]; - for (int i = 0; i < numFormats; i++) { - if (GDI.DescribePixelFormat(hdc, 1 + i, pfd.size(), pfd) == 0) { - throw new GLException("Error describing pixel format " + (1 + i) + " of device context"); + // 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice + PIXELFORMATDESCRIPTOR pfd = WindowsWGLGraphicsConfiguration.createPixelFormatDescriptor(); + pfd = WindowsWGLGraphicsConfiguration.GLCapabilities2PFD(capsChosen, pfd); + pfdID = GDI.ChoosePixelFormat(hdc, pfd); + int recommendedIndex = -1 ; + if( 1 <= pfdID ) { + // seek index .. + for (recommendedIndex = availableCaps.size() - 1 ; + 0 <= recommendedIndex && pfdID != ((WGLGLCapabilities) availableCaps.get(recommendedIndex)).getPFDID(); + recommendedIndex--) + { /* nop */ } } - availableCaps[i] = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(glProfile, pfd, onscreen, usePBuffer); - } - - int pfdID; - - if (pixelFormatSet <= 0) { - pfd = WindowsWGLGraphicsConfiguration.GLCapabilities2PFD(capsChosen); - recommendedPixelFormat = GDI.ChoosePixelFormat(hdc, pfd); - recommendedIndex = recommendedPixelFormat - 1; - pixelFormatCaps = availableCaps[recommendedIndex]; + // 2nd choice: if no preferred recommendedIndex available if (DEBUG) { - System.err.println("updateGraphicsConfigurationGDI: ChoosePixelFormat(HDC " + toHexString(hdc) + ") = " + recommendedPixelFormat + " (LastError: " + GDI.GetLastError() + ")"); - System.err.println("!!! recommended caps " + pixelFormatCaps); + System.err.println("updateGraphicsConfigurationGDI: ChoosePixelFormat(HDC " + toHexString(hdc) + ") = " + pfdID + ", idx " + recommendedIndex + " (LastError: " + GDI.GetLastError() + ")"); } - - int chosenIndex = recommendedIndex; - try { - if (null != chooser) { - chosenIndex = chooser.chooseCapabilities(capsChosen, availableCaps, recommendedIndex); - pixelFormatCaps = availableCaps[chosenIndex]; - if (DEBUG) { - System.err.println("updateGraphicsConfigurationGDI: chooser: idx " + chosenIndex); - System.err.println("!!! chosen caps " + pixelFormatCaps); - } - } - } catch (NativeWindowException e) { + int chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex); + if ( 0 > chosenIndex ) { if (DEBUG) { - e.printStackTrace(); + Thread.dumpStack(); } + return false; } - - if (chosenIndex < 0) { - // keep on going .. - // seek first available one .. - for (chosenIndex = 0; chosenIndex < availableCaps.length && availableCaps[chosenIndex] == null; chosenIndex++) { - // nop - } - if (chosenIndex == availableCaps.length) { - // give up .. - if (DEBUG) { - System.err.println("updateGraphicsConfigurationGDI: Failed .. nothing available, bail out"); - } - return false; - } - pixelFormatCaps = availableCaps[chosenIndex]; - if (DEBUG) { - System.err.println("updateGraphicsConfigurationGDI: Failed .. unable to choose config, using first available idx: " + chosenIndex); - System.err.println("!!! fallback caps " + pixelFormatCaps); - } - } - pfdID = chosenIndex + 1; - } else { - pfdID = pixelFormatSet; - pixelFormatCaps = availableCaps[pixelFormatSet-1]; + pixelFormatCaps = (WGLGLCapabilities) availableCaps.get(chosenIndex); if (DEBUG) { - System.err.println("updateGraphicsConfigurationGDI: Using preset PFID: " + pixelFormatSet); - System.err.println("!!! preset caps " + pixelFormatCaps); + System.err.println("!!! chosen pfdID (GDI): native recommended "+ (recommendedIndex+1) + + ", caps " + pixelFormatCaps); } } - if (DEBUG) { - System.err.println("updateGraphicsConfigurationGDI: using pfdID "+pfdID); - } - - if (GDI.DescribePixelFormat(hdc, pfdID, pfd.size(), pfd) == 0) { - throw new GLException("Error describing the chosen pixel format: " + pfdID + ", " + GDI.GetLastError()); - } - if (pixelFormatSet <= 0) { - if (!GDI.SetPixelFormat(hdc, pfdID, pfd)) { - throw new GLException("Unable to set pixel format " + pfdID + + if ( !extHDC && !pixelFormatSet ) { + if (!GDI.SetPixelFormat(hdc, pixelFormatCaps.getPFDID(), pixelFormatCaps.getPFD())) { + throw new GLException("Unable to set pixel format " + pixelFormatCaps.getPFDID() + " for device context " + toHexString(hdc) + ": error code " + GDI.GetLastError()); } + if (DEBUG) { + System.err.println("!!! setPixelFormat (GDI): hdc "+toHexString(hdc) +", "+config.getPixelFormatID()+" -> " + pixelFormatCaps.getPFDID()); + } } - - config.setCapsPFD(pixelFormatCaps, pfd, pfdID, true); + config.setCapsPFD(pixelFormatCaps); return true; - - } - - static String getThreadName() { - return Thread.currentThread().getName(); - } - - static String toHexString(long hex) { - return "0x" + Long.toHexString(hex); } } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java index da4f2113d..f753c08c5 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -33,6 +34,9 @@ package com.jogamp.opengl.impl.windows.wgl.awt; +import com.jogamp.common.util.ArrayHashSet; +import com.jogamp.nativewindow.impl.jawt.windows.Win32SunJDKReflection; +import com.jogamp.opengl.impl.GLGraphicsConfigurationFactory; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; @@ -53,8 +57,9 @@ import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLException; import com.jogamp.opengl.impl.windows.wgl.WindowsWGLGraphicsConfiguration; +import javax.media.opengl.GLDrawableFactory; -public class WindowsAWTWGLGraphicsConfigurationFactory extends GraphicsConfigurationFactory { +public class WindowsAWTWGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory { protected static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug("GraphicsConfiguration"); public WindowsAWTWGLGraphicsConfigurationFactory() { @@ -72,6 +77,9 @@ public class WindowsAWTWGLGraphicsConfigurationFactory extends GraphicsConfigura if(null==absScreen) { absScreen = AWTGraphicsScreen.createScreenDevice(-1, AbstractGraphicsDevice.DEFAULT_UNIT); + if(DEBUG) { + System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: creating default device: "+absScreen); + } } AWTGraphicsScreen awtScreen = (AWTGraphicsScreen) absScreen; device = ((AWTGraphicsDevice)awtScreen.getDevice()).getGraphicsDevice(); @@ -92,28 +100,74 @@ public class WindowsAWTWGLGraphicsConfigurationFactory extends GraphicsConfigura if(DEBUG) { System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: got "+absScreen); } - GraphicsConfiguration gc = device.getDefaultConfiguration(); + WindowsGraphicsDevice winDevice = new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); DefaultGraphicsScreen winScreen = new DefaultGraphicsScreen(winDevice, awtScreen.getIndex()); - if(DEBUG) { - System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: made "+winScreen); - } + GraphicsConfigurationFactory configFactory = GraphicsConfigurationFactory.getFactory(winDevice); + GLDrawableFactory drawableFactory = GLDrawableFactory.getFactory( ((GLCapabilitiesImmutable)capsChosen).getGLProfile() ); WindowsWGLGraphicsConfiguration winConfig = (WindowsWGLGraphicsConfiguration) - GraphicsConfigurationFactory.getFactory(winDevice).chooseGraphicsConfiguration(capsChosen, - capsRequested, - chooser, winScreen); - + configFactory.chooseGraphicsConfiguration(capsChosen, + capsRequested, + chooser, winScreen); if (winConfig == null) { throw new GLException("Unable to choose a GraphicsConfiguration: "+capsChosen+",\n\t"+chooser+"\n\t"+winScreen); } - if(DEBUG) { - System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: chosen "+winConfig); + GraphicsConfiguration chosenGC = null; + + // 1st Choice: Create an AWT GraphicsConfiguration with the desired PFD + // This gc will probably not be able to support GDI (WGL_SUPPORT_GDI_ARB, PFD_SUPPORT_GDI) + // however on most GPUs this is the current situation for Windows, + // otherwise no hardware accelerated PFD could be achieved. + // - preselect with no constrains + // - try to create dedicated GC + winConfig.preselectGraphicsConfiguration(drawableFactory, null); + if ( 1 <= winConfig.getPixelFormatID() ) { + chosenGC = Win32SunJDKReflection.graphicsConfigurationGet(device, winConfig.getPixelFormatID()); + if(DEBUG) { + System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: Found new AWT PFD ID "+winConfig.getPixelFormatID()+" -> "+winConfig); + } + } + + if( null == chosenGC ) { + // 2nd Choice: Choose and match the GL Visual with AWT: + // - collect all AWT PFDs + // - choose a GL config from the pool of AWT PFDs + // + // The resulting GraphicsConfiguration has to be 'forced' on the AWT native peer, + // ie. returned by GLCanvas's getGraphicsConfiguration() befor call by super.addNotify(). + // + + // collect all available PFD IDs + GraphicsConfiguration[] configs = device.getConfigurations(); + int[] pfdIDs = new int[configs.length]; + ArrayHashSet pfdIDOSet = new ArrayHashSet(); + for (int i = 0; i < configs.length; i++) { + GraphicsConfiguration gc = configs[i]; + pfdIDs[i] = Win32SunJDKReflection.graphicsConfigurationGetPixelFormatID(gc); + pfdIDOSet.add(new Integer(pfdIDs[i])); + if(DEBUG) { + System.err.println("AWT pfd["+i+"] "+pfdIDs[i]); + } + } + if(DEBUG) { + System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: PFD IDs: "+pfdIDs.length+", unique: "+pfdIDOSet.size()); + } + winConfig.preselectGraphicsConfiguration(drawableFactory, pfdIDs); + int gcIdx = pfdIDOSet.indexOf(new Integer(winConfig.getPixelFormatID())); + if( 0 > gcIdx ) { + chosenGC = configs[gcIdx]; + if(DEBUG) { + System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: Found matching AWT PFD ID "+winConfig.getPixelFormatID()+" -> "+winConfig); + } + } } - // We have nothing to match .. so choose the default + if ( null == chosenGC ) { + throw new GLException("Unable to determine GraphicsConfiguration: "+winConfig); + } return new AWTGraphicsConfiguration(awtScreen, winConfig.getChosenCapabilities(), winConfig.getRequestedCapabilities(), - gc, winConfig); + chosenGC, winConfig); } } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11DummyGLXDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11DummyGLXDrawable.java index 72698d759..1f2bf9344 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11DummyGLXDrawable.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11DummyGLXDrawable.java @@ -35,7 +35,7 @@ import com.jogamp.nativewindow.impl.*; import com.jogamp.nativewindow.impl.x11.*; public class X11DummyGLXDrawable extends X11OnscreenGLXDrawable { - private static final int f_dim = 128; + private static final int f_dim = 64; private long dummyWindow = 0; /** diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLCapabilities.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLCapabilities.java new file mode 100644 index 000000000..e3a1e7d72 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLCapabilities.java @@ -0,0 +1,116 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import com.jogamp.nativewindow.impl.x11.XVisualInfo; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; +import java.util.Comparator; + +public class X11GLCapabilities extends GLCapabilities { + XVisualInfo xVisualInfo; + long fbcfg; + int fbcfgid; + + /** Comparing xvisual id only */ + public static class XVisualIDComparator implements Comparator { + + public int compare(Object o1, Object o2) { + if ( ! ( o1 instanceof X11GLCapabilities ) ) { + Class c = (null != o1) ? o1.getClass() : null ; + throw new ClassCastException("arg1 not a X11GLCapabilities object: " + c); + } + if ( ! ( o2 instanceof X11GLCapabilities ) ) { + Class c = (null != o2) ? o2.getClass() : null ; + throw new ClassCastException("arg2 not a X11GLCapabilities object: " + c); + } + + final X11GLCapabilities caps1 = (X11GLCapabilities) o1; + final long id1 = caps1.getXVisualID(); + + final X11GLCapabilities caps2 = (X11GLCapabilities) o2; + final long id2 = caps2.getXVisualID(); + + if(id1 > id2) { + return 1; + } else if(id1 < id2) { + return -1; + } + return 0; + } + } + + public X11GLCapabilities(XVisualInfo xVisualInfo, long fbcfg, int fbcfgid, GLProfile glp) { + super(glp); + this.xVisualInfo = xVisualInfo; + this.fbcfg = fbcfg; + this.fbcfgid = fbcfgid; + } + + public X11GLCapabilities(XVisualInfo xVisualInfo, GLProfile glp) { + super(glp); + this.xVisualInfo = xVisualInfo; + this.fbcfg = 0; + this.fbcfgid = -1; + } + + public Object cloneMutable() { + return clone(); + } + + public Object clone() { + try { + return super.clone(); + } catch (RuntimeException e) { + throw new GLException(e); + } + } + + final public XVisualInfo getXVisualInfo() { return xVisualInfo; } + final public long getXVisualID() { return xVisualInfo.getVisualid(); } + + final public long getFBConfig() { return fbcfg; } + final public int getFBConfigID() { return fbcfgid; } + final public boolean isFBConfig() { return 0!=fbcfg && fbcfgid>0; } + + public StringBuffer toString(StringBuffer sink) { + if(null == sink) { + sink = new StringBuffer(); + } + sink.append("0x").append(Long.toHexString(xVisualInfo.getVisualid())).append(" "); + if(isFBConfig()) { + sink.append("0x").append(Integer.toHexString(fbcfgid)); + } else { + sink.append("----"); + } + sink.append(": "); + return super.toString(sink); + } +}
\ No newline at end of file diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXContext.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXContext.java index fddfb4cd1..dd25f241e 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXContext.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXContext.java @@ -40,11 +40,14 @@ package com.jogamp.opengl.impl.x11.glx; -import com.jogamp.common.util.VersionNumber; import java.nio.*; import java.util.*; + import javax.media.opengl.*; import javax.media.nativewindow.*; +import javax.media.nativewindow.x11.X11GraphicsDevice; + +import com.jogamp.common.util.VersionNumber; import com.jogamp.opengl.impl.*; import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; @@ -119,21 +122,23 @@ public abstract class X11GLXContext extends GLContextImpl { protected Map/*<String, String>*/ getExtensionNameMap() { return extensionNameMap; } - public final boolean isGLReadDrawableAvailable() { + public final boolean isGLXVersionGreaterEqualOneThree() { if(null == glXVersion) { X11GLXDrawableFactory factory = (X11GLXDrawableFactory)drawable.getFactoryImpl(); X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); - AbstractGraphicsDevice device = config.getScreen().getDevice(); + X11GraphicsDevice device = (X11GraphicsDevice) config.getScreen().getDevice(); glXVersion = factory.getGLXVersion(device); - if( null != glXVersion ) { - glXVersionOneThreeCapable = glXVersion.compareTo(factory.versionOneThree)>=0; - } + glXVersionOneThreeCapable = ( null != glXVersion ) ? glXVersion.compareTo(X11GLXDrawableFactory.versionOneThree) >= 0 : false ; } return glXVersionOneThreeCapable; } + public final boolean isGLReadDrawableAvailable() { + return isGLXVersionGreaterEqualOneThree(); + } + private final boolean glXMakeContextCurrent(long dpy, long writeDrawable, long readDrawable, long ctx) { boolean res = false; @@ -173,18 +178,13 @@ public abstract class X11GLXContext extends GLContextImpl { } protected long createContextARBImpl(long share, boolean direct, int ctp, int major, int minor) { - X11GLXDrawableFactory factory = (X11GLXDrawableFactory)drawable.getFactoryImpl(); - - X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); - AbstractGraphicsDevice device = config.getScreen().getDevice(); - X11GLXContext sharedContext = (X11GLXContext) factory.getOrCreateSharedContextImpl(device); - long display = device.getHandle(); - - GLXExt glXExt; - if(null==sharedContext) { - glXExt = getGLXExt(); - } else { - glXExt = sharedContext.getGLXExt(); + updateGLXProcAddressTable(); + GLXExt _glXExt = getGLXExt(); + if(DEBUG) { + System.err.println("X11GLXContext.createContextARBImpl: "+getGLVersion(major, minor, ctp, "@creation") + + ", handle "+toHexString(drawable.getHandle()) + ", share "+toHexString(share)+", direct "+direct+ + ", glXCreateContextAttribsARB: "+toHexString(glXExtProcAddressTable._addressof_glXCreateContextAttribsARB)); + Thread.dumpStack(); } boolean ctBwdCompat = 0 != ( CTX_PROFILE_COMPAT & ctp ) ; @@ -224,11 +224,15 @@ public abstract class X11GLXContext extends GLContextImpl { } } + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsDevice device = config.getScreen().getDevice(); + long display = device.getHandle(); + try { // critical path, a remote display might not support this command, // hence we need to catch the X11 Error within this block. X11Util.XSync(display, false); - ctx = glXExt.glXCreateContextAttribsARB(display, config.getFBConfig(), share, direct, attribs, 0); + ctx = _glXExt.glXCreateContextAttribsARB(display, config.getFBConfig(), share, direct, attribs, 0); X11Util.XSync(display, false); } catch (RuntimeException re) { if(DEBUG) { @@ -247,7 +251,7 @@ public abstract class X11GLXContext extends GLContextImpl { ctx = 0; } else { if (DEBUG) { - System.err.println(getThreadName() + ": createContextARBImpl: OK "+getGLVersion(major, minor, ctp, "@creation")+", share "+share+", direct "+direct+", hasSharedContext "+(null!=sharedContext)); + System.err.println(getThreadName() + ": createContextARBImpl: OK "+getGLVersion(major, minor, ctp, "@creation")+", share "+share+", direct "+direct); } // the following is issued by the caller 'GLContextImpl.createContextARB()' // setGLFunctionAvailability(true, major, minor, ctp); @@ -458,21 +462,24 @@ public abstract class X11GLXContext extends GLContextImpl { // Should check for X errors and raise GLException } - protected final void updateGLXProcAddressTable(int major, int minor, int ctp) { + protected final void updateGLXProcAddressTable() { + AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); + String key = adevice.getUniqueID(); if (DEBUG) { - System.err.println(getThreadName() + ": !!! Initializing GLX extension address table"); + System.err.println(getThreadName() + ": !!! Initializing GLX extension address table: "+key); } glXQueryExtensionsStringInitialized = false; glXQueryExtensionsStringAvailable = false; GLXExtProcAddressTable table = null; synchronized(mappedContextTypeObjectLock) { - table = (GLXExtProcAddressTable) mappedGLXProcAddress.get( contextFQN ); + table = (GLXExtProcAddressTable) mappedGLXProcAddress.get( key ); } if(null != table) { glXExtProcAddressTable = table; if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext GLX ProcAddressTable reusing key("+contextFQN+") -> "+table.hashCode()); + System.err.println(getThreadName() + ": !!! GLContext GLX ProcAddressTable reusing key("+key+") -> "+table.hashCode()); } } else { if (glXExtProcAddressTable == null) { @@ -480,9 +487,10 @@ public abstract class X11GLXContext extends GLContextImpl { } resetProcAddressTable(getGLXExtProcAddressTable()); synchronized(mappedContextTypeObjectLock) { - mappedGLXProcAddress.put(contextFQN, getGLXExtProcAddressTable()); + mappedGLXProcAddress.put(key, getGLXExtProcAddressTable()); if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext GLX ProcAddressTable mapping key("+contextFQN+") -> "+getGLXExtProcAddressTable().hashCode()); + System.err.println(getThreadName() + ": !!! GLContext GLX ProcAddressTable mapping key("+key+") -> "+getGLXExtProcAddressTable().hashCode()); + Thread.dumpStack(); } } } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java index 3abbcee57..709e2ddab 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java @@ -37,7 +37,11 @@ package com.jogamp.opengl.impl.x11.glx; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; import java.nio.*; + import javax.media.nativewindow.*; import javax.media.nativewindow.x11.*; import javax.media.opengl.*; @@ -47,10 +51,6 @@ import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.util.*; import com.jogamp.nativewindow.impl.ProxySurface; import com.jogamp.nativewindow.impl.x11.*; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { @@ -72,6 +72,13 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } } + public static VersionNumber getGLXVersion(X11GraphicsDevice device) { + int[] major = new int[1]; + int[] minor = new int[1]; + GLXUtil.getGLXVersion(device.getHandle(), major, minor); + return new VersionNumber(major[0], minor[0], 0); + } + public GLDynamicLookupHelper getGLDynamicLookupHelper(int profile) { return x11GLXDynamicLookupHelper; } @@ -90,204 +97,22 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { defaultDevice = new X11GraphicsDevice(X11Util.getNullDisplayName(), AbstractGraphicsDevice.DEFAULT_UNIT); - // Init shared resources via own thread + // Init shared resources off thread // Will be released via ShutdownHook - sharedResourcesRunner = new SharedResourcesRunner(); - sharedResourcesThread = new Thread(sharedResourcesRunner, Thread.currentThread().getName()+"-SharedResourcesRunner"); - sharedResourcesThread.setDaemon(true); // Allow JVM to exit, even if this one is running - sharedResourcesThread.start(); + sharedResourceImpl = new SharedResourceImplementation(); + sharedResourceRunner = new SharedResourceRunner(sharedResourceImpl); + sharedResourceThread = new Thread(sharedResourceRunner, Thread.currentThread().getName()+"-SharedResourceRunner"); + sharedResourceThread.setDaemon(true); // Allow JVM to exit, even if this one is running + sharedResourceThread.start(); } - class SharedResourcesRunner implements Runnable { - boolean ready = false; - boolean released = false; - boolean shouldRelease = false; - String initConnection = null; - SharedResource result = null; - - public final void initializeAndWait(String connection) { - // wait until thread becomes ready to init new device, - // pass the device and release the sync - String threadName = Thread.currentThread().getName(); - if (DEBUG) { - System.err.println(threadName+ " initializeAndWait START: "+connection); - } - synchronized (this) { - while (!ready) { - try { - this.wait(); - } catch (InterruptedException ex) { } - } - if (DEBUG) { - System.err.println(threadName+ " initializeAndWait set command: "+connection); - } - initConnection = connection; - this.notifyAll(); - - // wait until thread has initialized the device - while (!ready || null != initConnection) { - try { - this.wait(); - } catch (InterruptedException ex) { } - } - if (DEBUG) { - System.err.println(threadName+ " initializeAndWait done: "+connection); - } - } - // done - } - - public final void releaseAndWait() { - synchronized (this) { - shouldRelease = true; - this.notifyAll(); - - while (!released) { - try { - this.wait(); - } catch (InterruptedException ex) { - } - } - } - } - - public final void run() { - String threadName = Thread.currentThread().getName(); - - synchronized (this) { - if (DEBUG) { - System.err.println(threadName+ " STARTED -> ready"); - } - - while (!shouldRelease) { - try { - // wait for stop or init - ready = true; - this.wait(); - } catch (InterruptedException ex) { } - ready = false; - - if(!shouldRelease && null!=initConnection) { - if (DEBUG) { - System.err.println(threadName+ " create Shared for: "+initConnection); - } - SharedResource sr = createSharedResource(initConnection); - if(null!=sr) { - synchronized(sharedMap) { - sharedMap.put(initConnection, sr); - } - } - if (DEBUG) { - String msg = "Info: (" + threadName + ") initializedSharedResource for device connection: "+initConnection+" -> ready"; - System.err.println(msg); - Throwable t = new Throwable(msg); - t.printStackTrace(); - } - } - initConnection = null; - notifyAll(); - } - - if (DEBUG) { - System.err.println(threadName+ " release START"); - } - - releaseSharedResources(); - - if (DEBUG) { - System.err.println(threadName+ " release END"); - } - - released = true; - ready = false; - notifyAll(); - } - } - - private final SharedResource createSharedResource(String connection) { - X11GraphicsDevice sharedDevice = new X11GraphicsDevice(X11Util.createDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT); - sharedDevice.setCloseDisplay(true); - sharedDevice.lock(); - try { - String glXVendorName = GLXUtil.getVendorName(sharedDevice.getHandle()); - X11GraphicsScreen sharedScreen = new X11GraphicsScreen(sharedDevice, 0); - X11DummyGLXDrawable sharedDrawable = X11DummyGLXDrawable.create(sharedScreen, X11GLXDrawableFactory.this, - GLProfile.getDefault(sharedDevice)); - if (null == sharedScreen || null == sharedDrawable) { - throw new GLException("Couldn't init shared screen(" + sharedScreen + ")/drawable(" + sharedDrawable + ")"); - } - X11GLXContext sharedContext; - VersionNumber glXVersion; - try { - X11GLXContext ctx = (X11GLXContext) sharedDrawable.createContext(null); - ctx.makeCurrent(); - { - int[] major = new int[1]; - int[] minor = new int[1]; - GLXUtil.getGLXVersion(sharedDevice.getHandle(), major, minor); - glXVersion = new VersionNumber(major[0], minor[0], 0); - } - ctx.release(); - sharedContext = ctx; - } catch (Throwable t) { - throw new GLException("X11GLXDrawableFactory - Could not initialize shared resources", t); - } - if (null == sharedContext) { - throw new GLException("X11GLXDrawableFactory - Shared Context is null"); - } - if (DEBUG) { - System.err.println("!!! SharedDevice: "+sharedDevice); - System.err.println("!!! SharedScreen: "+sharedScreen); - System.err.println("!!! SharedContext: "+sharedContext); - System.err.println("!!! GLX Vendor: "+glXVendorName); - System.err.println("!!! GLX Version: "+glXVersion + - " >= 1.3: " + ( glXVersion.compareTo(versionOneThree) >= 0 ) ); - } - return new SharedResource(sharedDevice, sharedScreen, sharedDrawable, sharedContext, glXVersion, glXVendorName); - } finally { - sharedDevice.unlock(); - } - } - - private final void releaseSharedResources() { - Collection/*<SharedResource>*/ sharedResources = sharedMap.values(); - for(Iterator iter=sharedResources.iterator(); iter.hasNext(); ) { - SharedResource sr = (SharedResource) iter.next(); - - if (DEBUG) { - System.err.println("!!! Shutdown Shared:"); - System.err.println("!!! Device : "+sr.device); - System.err.println("!!! Screen : "+sr.screen); - System.err.println("!!! Drawable: "+sr.drawable); - System.err.println("!!! CTX : "+sr.context); - } - - if (null != sr.context) { - // may cause JVM SIGSEGV: sharedContext.destroy(); - sr.context = null; - } - - if (null != sr.drawable) { - // may cause JVM SIGSEGV: sharedDrawable.destroy(); - sr.drawable = null; - } - - if (null != sr.screen) { - sr.screen = null; - } - - if (null != sr.device) { - sr.device.close(); - sr.device=null; - } - } - sharedMap.clear(); - } - } - Thread sharedResourcesThread = null; - SharedResourcesRunner sharedResourcesRunner=null; + X11GraphicsDevice defaultDevice; + SharedResourceImplementation sharedResourceImpl; + SharedResourceRunner sharedResourceRunner; + Thread sharedResourceThread; + HashMap/*<connection, SharedResource>*/ sharedMap = new HashMap(); - static class SharedResource { + static class SharedResource implements SharedResourceRunner.Resource { X11GraphicsDevice device; X11GraphicsScreen screen; X11DummyGLXDrawable drawable; @@ -297,7 +122,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { boolean isGLXVendorNVIDIA; VersionNumber glXVersion; - SharedResource(X11GraphicsDevice dev, X11GraphicsScreen scrn, + SharedResource(X11GraphicsDevice dev, X11GraphicsScreen scrn, X11DummyGLXDrawable draw, X11GLXContext ctx, VersionNumber glXVer, String glXVendor) { device = dev; @@ -309,16 +134,119 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { isGLXVendorATI = GLXUtil.isVendorATI(glXVendorName); isGLXVendorNVIDIA = GLXUtil.isVendorNVIDIA(glXVendorName); } - X11GraphicsDevice getDevice() { return device; } - X11GraphicsScreen getScreen() { return screen; } - X11GLXContext getContext() { return context; } - String getGLXVendorName() { return glXVendorName; } - boolean isGLXVendorATI() { return isGLXVendorATI; } - boolean isGLXVendorNVIDIA() { return isGLXVendorNVIDIA; } - VersionNumber getGLXVersion() { return glXVersion; } + final public AbstractGraphicsDevice getDevice() { return device; } + final public AbstractGraphicsScreen getScreen() { return screen; } + final public GLDrawableImpl getDrawable() { return drawable; } + final public GLContextImpl getContext() { return context; } + + final String getGLXVendorName() { return glXVendorName; } + final boolean isGLXVendorATI() { return isGLXVendorATI; } + final boolean isGLXVendorNVIDIA() { return isGLXVendorNVIDIA; } + final VersionNumber getGLXVersion() { return glXVersion; } + final boolean isGLXVersionGreaterEqualOneThree() { + return ( null != glXVersion ) ? glXVersion.compareTo(versionOneThree) >= 0 : false ; + } + } + + class SharedResourceImplementation implements SharedResourceRunner.Implementation { + public void clear() { + synchronized(sharedMap) { + sharedMap.clear(); + } + } + public SharedResourceRunner.Resource mapPut(String connection, SharedResourceRunner.Resource resource) { + synchronized(sharedMap) { + return (SharedResourceRunner.Resource) sharedMap.put(connection, resource); + } + } + public SharedResourceRunner.Resource mapGet(String connection) { + synchronized(sharedMap) { + return (SharedResourceRunner.Resource) sharedMap.get(connection); + } + } + public Collection/*<Resource>*/ mapValues() { + synchronized(sharedMap) { + return sharedMap.values(); + } + } + + public SharedResourceRunner.Resource createSharedResource(String connection) { + X11GraphicsDevice sharedDevice = new X11GraphicsDevice(X11Util.createDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT); + sharedDevice.setCloseDisplay(true); + sharedDevice.lock(); + try { + String glXVendorName = GLXUtil.getVendorName(sharedDevice.getHandle()); + X11GraphicsScreen sharedScreen = new X11GraphicsScreen(sharedDevice, 0); + if (null == sharedScreen) { + throw new GLException("Couldn't create shared screen for device: "+sharedDevice+", idx 0"); + } + GLProfile glp = GLProfile.getMinDesktop(sharedDevice); + if (null == glp) { + throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice); + } + X11DummyGLXDrawable sharedDrawable = X11DummyGLXDrawable.create(sharedScreen, X11GLXDrawableFactory.this, glp); + if (null == sharedDrawable) { + throw new GLException("Couldn't create shared drawable for screen: "+sharedScreen+", "+glp); + } + X11GLXContext sharedContext = (X11GLXContext) sharedDrawable.createContext(null); + if (null == sharedContext) { + throw new GLException("Couldn't create shared context for drawable: "+sharedDrawable); + } + sharedContext.setSynchronized(true); + VersionNumber glXVersion = getGLXVersion(sharedDevice); + boolean madeCurrent = false; + sharedContext.makeCurrent(); + try { + madeCurrent = sharedContext.isCurrent(); + } finally { + sharedContext.release(); + } + if (DEBUG) { + System.err.println("!!! SharedDevice: " + sharedDevice); + System.err.println("!!! SharedScreen: " + sharedScreen); + System.err.println("!!! SharedContext: " + sharedContext + ", madeCurrent " + madeCurrent); + System.err.println("!!! GLX Vendor: " + glXVendorName); + System.err.println("!!! GLX Version: " + glXVersion + + " >= 1.3: " + (glXVersion.compareTo(versionOneThree) >= 0)); + } + return new SharedResource(sharedDevice, sharedScreen, sharedDrawable, sharedContext, glXVersion, glXVendorName); + } catch (Throwable t) { + throw new GLException("WindowsWGLDrawableFactory - Could not initialize shared resources for "+connection, t); + } finally { + sharedDevice.unlock(); + } + } + + public void releaseSharedResource(SharedResourceRunner.Resource shared) { + SharedResource sr = (SharedResource) shared; + if (DEBUG) { + System.err.println("!!! Shutdown Shared:"); + System.err.println("!!! Device : " + sr.device); + System.err.println("!!! Screen : " + sr.screen); + System.err.println("!!! Drawable: " + sr.drawable); + System.err.println("!!! CTX : " + sr.context); + } + + if (null != sr.context) { + // may cause JVM SIGSEGV: sharedContext.destroy(); + sr.context = null; + } + + if (null != sr.drawable) { + // may cause JVM SIGSEGV: sharedDrawable.destroy(); + sr.drawable = null; + } + + if (null != sr.screen) { + sr.screen = null; + } + + if (null != sr.device) { + sr.device.close(); + sr.device = null; + } + } } - HashMap/*<connection, SharedResource>*/ sharedMap = new HashMap(); - X11GraphicsDevice defaultDevice; public final AbstractGraphicsDevice getDefaultDevice() { return defaultDevice; @@ -331,44 +259,8 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { return false; } - HashSet devicesTried = new HashSet(); - private final boolean getDeviceTried(String connection) { - synchronized(devicesTried) { - return devicesTried.contains(connection); - } - } - private final void addDeviceTried(String connection) { - synchronized(devicesTried) { - devicesTried.add(connection); - } - } - - private SharedResource getOrCreateShared(AbstractGraphicsDevice device) { - String connection = device.getConnection(); - SharedResource sr; - synchronized(sharedMap) { - sr = (SharedResource) sharedMap.get(connection); - } - - if(null==sr && !getDeviceTried(connection)) { - addDeviceTried(connection); - if (DEBUG) { - System.err.println("getOrCreateShared() "+connection+": trying"); - } - sharedResourcesRunner.initializeAndWait(connection); - synchronized(sharedMap) { - sr = (SharedResource) sharedMap.get(connection); - } - if(DEBUG) { - Throwable t = new Throwable("getOrCreateSharedl() "+connection+": done"); - t.printStackTrace(); - } - } - return sr; - } - protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared(device); + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); if(null!=sr) { return sr.getContext(); } @@ -376,7 +268,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } protected AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared(device); + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); if(null!=sr) { return sr.getDevice(); } @@ -384,53 +276,53 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } protected final long getOrCreateSharedDpy(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared(device); + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); if(null!=sr) { return sr.getDevice().getHandle(); } return 0; } - protected final VersionNumber getGLXVersion(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared(device); - if(null!=sr) { - return sr.getGLXVersion(); - } - return null; + SharedResource getOrCreateSharedResource(AbstractGraphicsDevice device) { + return (SharedResource) sharedResourceRunner.getOrCreateShared(device); } - protected final String getGLXVendorName(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared(device); + public final String getGLXVendorName(AbstractGraphicsDevice device) { + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); if(null!=sr) { - return sr.getGLXVendorName(); + return ((SharedResource)sr).getGLXVendorName(); } return GLXUtil.getVendorName(device.getHandle()); } - protected final boolean isGLXVendorATI(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared(device); + public final boolean isGLXVendorATI(AbstractGraphicsDevice device) { + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); if(null!=sr) { - return sr.isGLXVendorATI(); + return ((SharedResource)sr).isGLXVendorATI(); } return GLXUtil.isVendorATI(device.getHandle()); } - protected final boolean isGLXVendorNVIDIA(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared(device); + public final boolean isGLXVendorNVIDIA(AbstractGraphicsDevice device) { + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); if(null!=sr) { - return sr.isGLXVendorNVIDIA(); + return ((SharedResource)sr).isGLXVendorNVIDIA(); } return GLXUtil.isVendorNVIDIA(device.getHandle()); } protected final void shutdownInstance() { - sharedResourcesRunner.releaseAndWait(); + sharedResourceRunner.releaseAndWait(); // Don't really close pending Display connections, // since this may trigger a JVM exception X11Util.shutdown( false, DEBUG ); } + protected List/*GLCapabilitiesImmutable*/ getAvailableCapabilitiesImpl(AbstractGraphicsDevice device) { + return X11GLXGraphicsConfigurationFactory.getAvailableCapabilities(this, device); + } + protected final GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target) { if (target == null) { throw new IllegalArgumentException("Null target"); @@ -458,15 +350,13 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { * The dummy context shall also use the same Display, * since switching Display in this regard is another ATI bug. */ - SharedResource sr = getOrCreateShared(device); + SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device); if( null!=sr && sr.isGLXVendorATI() && null == GLContext.getCurrent() ) { - synchronized(sr.context) { - sr.context.makeCurrent(); - try { - pbufferDrawable = new X11PbufferGLXDrawable(this, target); - } finally { - sr.context.release(); - } + sr.getContext().makeCurrent(); + try { + pbufferDrawable = new X11PbufferGLXDrawable(this, target); + } finally { + sr.getContext().release(); } } else { pbufferDrawable = new X11PbufferGLXDrawable(this, target); @@ -474,19 +364,26 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { return pbufferDrawable; } - public final boolean glXVersionGreaterEqualOneThree(AbstractGraphicsDevice device) { - VersionNumber glXVersion = getGLXVersion(device); - return ( null != glXVersion ) ? glXVersion.compareTo(versionOneThree) >= 0 : false ; + public final boolean isGLXVersionGreaterEqualOneThree(AbstractGraphicsDevice device) { + SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device); + if(null!=sr) { + return sr.isGLXVersionGreaterEqualOneThree(); + } + if( device instanceof X11GraphicsDevice ) { + VersionNumber v = getGLXVersion( (X11GraphicsDevice) device); + return ( null != v ) ? v.compareTo(versionOneThree) >= 0 : false ; + } + return false; } public final boolean canCreateGLPbuffer(AbstractGraphicsDevice device) { if(null == device) { - SharedResource sr = getOrCreateShared(defaultDevice); + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(defaultDevice); if(null!=sr) { device = sr.getDevice(); } } - return glXVersionGreaterEqualOneThree(device); + return isGLXVersionGreaterEqualOneThree(device); } protected final NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device, @@ -494,9 +391,9 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { GLCapabilitiesChooser chooser, int width, int height) { X11GraphicsScreen screen = null; - SharedResource sr = getOrCreateShared(device); + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); if(null!=sr) { - screen = sr.getScreen(); + screen = (X11GraphicsScreen) sr.getScreen(); } if(null==screen) { return null; diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfiguration.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfiguration.java index 3dbaab21b..f7779ab28 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfiguration.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfiguration.java @@ -33,10 +33,13 @@ package com.jogamp.opengl.impl.x11.glx; -import com.jogamp.common.nio.PointerBuffer; +import java.util.ArrayList; + import javax.media.nativewindow.*; import javax.media.nativewindow.x11.*; import javax.media.opengl.*; + +import com.jogamp.common.nio.PointerBuffer; import com.jogamp.opengl.impl.*; import com.jogamp.nativewindow.impl.x11.*; @@ -44,17 +47,12 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem protected static final boolean DEBUG = Debug.debug("GraphicsConfiguration"); public static final int MAX_ATTRIBS = 128; - private long fbConfig; - private int fbConfigID; private GLCapabilitiesChooser chooser; X11GLXGraphicsConfiguration(X11GraphicsScreen screen, - GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, - XVisualInfo info, long fbcfg, int fbcfgID) { - super(screen, capsChosen, capsRequested, info); + X11GLCapabilities capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) { + super(screen, capsChosen, capsRequested, capsChosen.getXVisualInfo()); this.chooser=chooser; - fbConfig = fbcfg; - fbConfigID = fbcfgID; } static X11GLXGraphicsConfiguration create(GLProfile glp, X11GraphicsScreen x11Screen, int fbcfgID) { @@ -70,23 +68,23 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem if(null==glp) { glp = GLProfile.getDefault(x11Screen.getDevice()); } - GLCapabilitiesImmutable caps = GLXFBConfig2GLCapabilities(glp, display, fbcfg, true, true, true, GLXUtil.isMultisampleAvailable(display)); + X11GLCapabilities caps = GLXFBConfig2GLCapabilities(glp, display, fbcfg, true, true, true, GLXUtil.isMultisampleAvailable(display)); if(null==caps) { throw new GLException("GLCapabilities null of "+toHexString(fbcfg)); } - XVisualInfo xvi = GLX.glXGetVisualFromFBConfig(display, fbcfg); - if(null==xvi) { - throw new GLException("XVisualInfo null of "+toHexString(fbcfg)); - } - return new X11GLXGraphicsConfiguration(x11Screen, caps, caps, new DefaultGLCapabilitiesChooser(), xvi, fbcfg, fbcfgID); + return new X11GLXGraphicsConfiguration(x11Screen, caps, caps, new DefaultGLCapabilitiesChooser()); } public Object clone() { return super.clone(); } - public long getFBConfig() { return fbConfig; } - public int getFBConfigID() { return fbConfigID; } + public final long getFBConfig() { + return ((X11GLCapabilities)capabilitiesChosen).getFBConfig(); + } + public final int getFBConfigID() { + return ((X11GLCapabilities)capabilitiesChosen).getFBConfigID(); + } void updateGraphicsConfiguration() { X11GLXGraphicsConfiguration newConfig = (X11GLXGraphicsConfiguration) @@ -96,8 +94,6 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem // FIXME: setScreen( ... ); setXVisualInfo(newConfig.getXVisualInfo()); setChosenCapabilities(newConfig.getChosenCapabilities()); - fbConfig = newConfig.getFBConfig(); - fbConfigID = newConfig.getFBConfigID(); if(DEBUG) { System.err.println("!!! updateGraphicsConfiguration: "+this); } @@ -220,49 +216,63 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem return true; } - static boolean GLXFBConfigDrawableTypeVerify(int val, boolean onscreen, boolean usePBuffer) { - boolean res; + static int FBCfgDrawableTypeBits(final long display, final long fbcfg) { + int val = 0; - if ( onscreen ) { - res = ( 0 != (val & GLX.GLX_WINDOW_BIT) ) ; - } else { - if ( usePBuffer ) { - res = ( 0 != (val & GLX.GLX_PBUFFER_BIT) ) ; - } else { - res = ( 0 != (val & GLX.GLX_PIXMAP_BIT) ) ; - } - } + int[] tmp = new int[1]; + int fbtype = glXGetFBConfig(display, fbcfg, GLX.GLX_DRAWABLE_TYPE, tmp, 0); - return res; + if ( 0 != ( fbtype & GLX.GLX_WINDOW_BIT ) ) { + val |= GLGraphicsConfigurationUtil.WINDOW_BIT; + } + if ( 0 != ( fbtype & GLX.GLX_PIXMAP_BIT ) ) { + val |= GLGraphicsConfigurationUtil.BITMAP_BIT; + } + if ( 0 != ( fbtype & GLX.GLX_PBUFFER_BIT ) ) { + val |= GLGraphicsConfigurationUtil.PBUFFER_BIT; + } + return val; } - static GLCapabilitiesImmutable GLXFBConfig2GLCapabilities(GLProfile glp, long display, long fbcfg, + static X11GLCapabilities GLXFBConfig2GLCapabilities(GLProfile glp, long display, long fbcfg, boolean relaxed, boolean onscreen, boolean usePBuffer, boolean isMultisampleAvailable) { - int[] tmp = new int[1]; - int val; - val = glXGetFBConfig(display, fbcfg, GLX.GLX_RENDER_TYPE, tmp, 0); - if (val != GLX.GLX_RGBA_BIT) { - if(DEBUG) { - System.err.println("FBConfig ("+toHexString(fbcfg)+") does not support RGBA: "+toHexString(val)); - } - return null; + ArrayList bucket = new ArrayList(); + final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer); + if( GLXFBConfig2GLCapabilities(bucket, glp, display, fbcfg, winattrmask, isMultisampleAvailable) ) { + return (X11GLCapabilities) bucket.get(0); + } else if ( relaxed && GLXFBConfig2GLCapabilities(bucket, glp, display, fbcfg, GLGraphicsConfigurationUtil.ALL_BITS, isMultisampleAvailable) ) { + return (X11GLCapabilities) bucket.get(0); } - GLCapabilities res = new GLCapabilities(glp); - - val = glXGetFBConfig(display, fbcfg, GLX.GLX_DRAWABLE_TYPE, tmp, 0); - if(GLXFBConfigDrawableTypeVerify(val, onscreen, usePBuffer)) { - res.setOnscreen(onscreen); - res.setPBuffer(usePBuffer); - } else if(relaxed) { - res.setOnscreen( 0 != (val & GLX.GLX_WINDOW_BIT) ); - res.setPBuffer ( 0 != (val & GLX.GLX_PBUFFER_BIT) ); - } else { + return null; + } + + static boolean GLXFBConfig2GLCapabilities(ArrayList capsBucket, + GLProfile glp, long display, long fbcfg, + int winattrmask, boolean isMultisampleAvailable) { + final int allDrawableTypeBits = FBCfgDrawableTypeBits(display, fbcfg); + int drawableTypeBits = winattrmask & allDrawableTypeBits; + + int fbcfgid = X11GLXGraphicsConfiguration.glXFBConfig2FBConfigID(display, fbcfg); + XVisualInfo visualInfo = GLX.glXGetVisualFromFBConfig(display, fbcfg); + if(null == visualInfo) { if(DEBUG) { - System.err.println("FBConfig ("+toHexString(fbcfg)+") GLX_DRAWABLE_TYPE does not match: req(onscrn "+onscreen+", pbuffer "+usePBuffer+"), got(onscreen "+( 0 != (val & GLX.GLX_WINDOW_BIT) )+", pbuffer "+( 0 != (val & GLX.GLX_PBUFFER_BIT) )+", pixmap "+( 0 != (val & GLX.GLX_PIXMAP_BIT) )+")"); + System.err.println("X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities: Null XVisualInfo for FBConfigID 0x" + Integer.toHexString(fbcfgid)); } - return null; + // onscreen must have an XVisualInfo + drawableTypeBits = drawableTypeBits & ~GLGraphicsConfigurationUtil.WINDOW_BIT; } + + if( 0 == drawableTypeBits ) { + return false; + } + + int[] tmp = new int[1]; + if(GLX.GLX_BAD_ATTRIBUTE == GLX.glXGetFBConfigAttrib(display, fbcfg, GLX.GLX_RENDER_TYPE, tmp, 0)) { + return false; + } + + GLCapabilities res = new X11GLCapabilities(visualInfo, fbcfg, fbcfgid, glp); res.setDoubleBuffered(glXGetFBConfig(display, fbcfg, GLX.GLX_DOUBLEBUFFER, tmp, 0) != 0); res.setStereo (glXGetFBConfig(display, fbcfg, GLX.GLX_STEREO, tmp, 0) != 0); res.setHardwareAccelerated(glXGetFBConfig(display, fbcfg, GLX.GLX_CONFIG_CAVEAT, tmp, 0) != GLX.GLX_SLOW_CONFIG); @@ -297,7 +307,8 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem try { res.setPbufferFloatingPointBuffers(glXGetFBConfig(display, fbcfg, GLXExt.GLX_FLOAT_COMPONENTS_NV, tmp, 0) != GL.GL_FALSE); } catch (Exception e) {} - return res; + + return GLGraphicsConfigurationUtil.addGLCapabilitiesPermutations(capsBucket, res, drawableTypeBits ); } private static String glXGetFBConfigErrorCode(int err) { @@ -352,26 +363,34 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem return res; } - static GLCapabilitiesImmutable XVisualInfo2GLCapabilities(GLProfile glp, long display, XVisualInfo info, - boolean onscreen, boolean usePBuffer, boolean isMultisampleEnabled) { + static boolean XVisualInfo2GLCapabilities(ArrayList capsBucket, + GLProfile glp, long display, XVisualInfo info, + final int winattrmask, boolean isMultisampleEnabled) { + final int allDrawableTypeBits = GLGraphicsConfigurationUtil.WINDOW_BIT | GLGraphicsConfigurationUtil.BITMAP_BIT ; + final int drawableTypeBits = winattrmask & allDrawableTypeBits; + + if( 0 == drawableTypeBits ) { + return false; + } + int[] tmp = new int[1]; int val = glXGetConfig(display, info, GLX.GLX_USE_GL, tmp, 0); if (val == 0) { if(DEBUG) { System.err.println("Visual ("+toHexString(info.getVisualid())+") does not support OpenGL"); } - return null; + return false; } val = glXGetConfig(display, info, GLX.GLX_RGBA, tmp, 0); if (val == 0) { if(DEBUG) { System.err.println("Visual ("+toHexString(info.getVisualid())+") does not support RGBA"); } - return null; + return false; } - GLCapabilities res = new GLCapabilities(glp); - res.setOnscreen (onscreen); - res.setPBuffer (usePBuffer); + + GLCapabilities res = new X11GLCapabilities(info, glp); + 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 @@ -393,7 +412,8 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem res.setSampleBuffers(glXGetConfig(display, info, GLX.GLX_SAMPLE_BUFFERS, tmp, 0) != 0); res.setNumSamples (glXGetConfig(display, info, GLX.GLX_SAMPLES, tmp, 0)); } - return res; + + return GLGraphicsConfigurationUtil.addGLCapabilitiesPermutations(capsBucket, res, drawableTypeBits); } private static String glXGetConfigErrorCode(int err) { @@ -417,16 +437,8 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem return tmp[tmp_offset]; } - static String toHexString(int val) { - return "0x"+Integer.toHexString(val); - } - - static String toHexString(long val) { - return "0x"+Long.toHexString(val); - } - public String toString() { - return "X11GLXGraphicsConfiguration["+getScreen()+", visualID " + toHexString(getVisualID()) + ", fbConfigID " + toHexString(fbConfigID) + + return "X11GLXGraphicsConfiguration["+getScreen()+", visualID " + toHexString(getVisualID()) + ", fbConfigID " + toHexString(getFBConfigID()) + ",\n\trequested " + getRequestedCapabilities()+ ",\n\tchosen " + getChosenCapabilities()+ "]"; diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfigurationFactory.java index 327ecd0be..b391dc948 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfigurationFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfigurationFactory.java @@ -39,12 +39,13 @@ import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.CapabilitiesChooser; import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.GraphicsConfigurationFactory; -import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.x11.X11GraphicsScreen; +import javax.media.nativewindow.x11.X11GraphicsDevice; import javax.media.opengl.DefaultGLCapabilitiesChooser; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; @@ -53,6 +54,12 @@ import com.jogamp.nativewindow.impl.x11.X11Lib; import com.jogamp.nativewindow.impl.x11.X11Util; import com.jogamp.nativewindow.impl.x11.XVisualInfo; import com.jogamp.opengl.impl.Debug; +import com.jogamp.opengl.impl.GLGraphicsConfigurationFactory; +import com.jogamp.opengl.impl.GLGraphicsConfigurationUtil; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; /** Subclass of GraphicsConfigurationFactory used when non-AWT toolkits @@ -60,8 +67,9 @@ import com.jogamp.opengl.impl.Debug; to this one to change the accepted and returned types of the GraphicsDevice and GraphicsConfiguration abstractions. */ -public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFactory { +public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory { protected static final boolean DEBUG = Debug.debug("GraphicsConfiguration"); + static X11GLCapabilities.XVisualIDComparator XVisualIDComparator = new X11GLCapabilities.XVisualIDComparator(); X11GLXGraphicsConfigurationFactory() { GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.x11.X11GraphicsDevice.class, this); @@ -88,6 +96,86 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac (GLCapabilitiesChooser)chooser, (X11GraphicsScreen)absScreen); } + protected static List/*<X11GLCapabilities>*/ getAvailableCapabilities(X11GLXDrawableFactory factory, AbstractGraphicsDevice device) { + X11GLXDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device); + if(null == sharedResource) { + throw new GLException("Shared resource for device n/a: "+device); + } + X11GraphicsScreen sharedScreen = (X11GraphicsScreen) sharedResource.getScreen(); + X11GLXDrawable sharedDrawable = (X11GLXDrawable) sharedResource.getDrawable(); + GLCapabilitiesImmutable capsChosen = sharedDrawable.getChosenGLCapabilities(); + GLProfile glp = capsChosen.getGLProfile(); + + List/*GLCapabilitiesImmutable*/ availableCaps = null; + + if( sharedResource.isGLXVersionGreaterEqualOneThree() ) { + availableCaps = getAvailableGLCapabilitiesFBConfig(sharedScreen, glp); + } + if( null == availableCaps || 0 == availableCaps.size() ) { + availableCaps = getAvailableGLCapabilitiesXVisual(sharedScreen, glp); + } + if( null != availableCaps ) { + Collections.sort(availableCaps, XVisualIDComparator); + } + return availableCaps; + } + + static List/*<X11GLCapabilities>*/ getAvailableGLCapabilitiesFBConfig(X11GraphicsScreen x11Screen, GLProfile glProfile) { + PointerBuffer fbcfgsL = null; + + // Utilizing FBConfig + // + AbstractGraphicsDevice absDevice = x11Screen.getDevice(); + long display = absDevice.getHandle(); + + int screen = x11Screen.getIndex(); + boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); + int[] count = { -1 }; + ArrayList availableCaps = new ArrayList(); + + fbcfgsL = GLX.glXChooseFBConfig(display, screen, null, 0, count, 0); + if (fbcfgsL == null || fbcfgsL.limit()<=0) { + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.getAvailableGLCapabilitiesFBConfig: Failed glXChooseFBConfig ("+x11Screen+"): "+fbcfgsL+", "+count[0]); + } + return null; + } + for (int i = 0; i < fbcfgsL.limit(); i++) { + if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, display, fbcfgsL.get(i), GLGraphicsConfigurationUtil.ALL_BITS, isMultisampleAvailable) ) { + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.getAvailableGLCapabilitiesFBConfig: FBConfig invalid (2): ("+x11Screen+"): fbcfg: "+toHexString(fbcfgsL.get(i))); + } + } + } + return availableCaps; + } + + static List/*<X11GLCapabilities>*/ getAvailableGLCapabilitiesXVisual(X11GraphicsScreen x11Screen, GLProfile glProfile) { + AbstractGraphicsDevice absDevice = x11Screen.getDevice(); + long display = absDevice.getHandle(); + + int screen = x11Screen.getIndex(); + boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); + + int[] count = new int[1]; + XVisualInfo template = XVisualInfo.create(); + template.setScreen(screen); + XVisualInfo[] infos = X11Util.XGetVisualInfo(display, X11Lib.VisualScreenMask, template, count, 0); + if (infos == null || infos.length<1) { + throw new GLException("Error while enumerating available XVisualInfos"); + } + ArrayList availableCaps = new ArrayList(); + for (int i = 0; i < infos.length; i++) { + if( !X11GLXGraphicsConfiguration.XVisualInfo2GLCapabilities(availableCaps, glProfile, display, infos[i], GLGraphicsConfigurationUtil.ALL_BITS, isMultisampleAvailable) ) { + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.getAvailableGLCapabilitiesXVisual: XVisual invalid: ("+x11Screen+"): fbcfg: "+toHexString(infos[i].getVisualid())); + } + } + } + return availableCaps; + } + + static X11GLXGraphicsConfiguration chooseGraphicsConfigurationStatic(GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsReq, GLCapabilitiesChooser chooser, @@ -99,18 +187,16 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac if (capsChosen == null) { capsChosen = new GLCapabilities(null); } + X11GraphicsDevice x11Device = (X11GraphicsDevice) x11Screen.getDevice(); + X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory(); - if(!capsChosen.isOnscreen() && capsChosen.getDoubleBuffered()) { - // OFFSCREEN !DOUBLE_BUFFER // FIXME DBLBUFOFFSCRN - GLCapabilities caps2 = (GLCapabilities) capsChosen.cloneMutable(); - caps2.setDoubleBuffered(false); - capsChosen = caps2; - } - + capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, factory.canCreateGLPbuffer(x11Device) ); boolean usePBuffer = capsChosen.isPBuffer(); - X11GLXGraphicsConfiguration res; - res = chooseGraphicsConfigurationFBConfig(capsChosen, capsReq, chooser, x11Screen); + X11GLXGraphicsConfiguration res = null; + if( factory.isGLXVersionGreaterEqualOneThree(x11Device) ) { + res = chooseGraphicsConfigurationFBConfig(capsChosen, capsReq, chooser, x11Screen); + } if(null==res) { if(usePBuffer) { throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig for "+capsChosen); @@ -138,14 +224,8 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac } return null; } - XVisualInfo visualInfo = GLX.glXGetVisualFromFBConfig(display, fbcfg); - if (visualInfo==null) { - System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed glXGetVisualFromFBConfig ("+x11Screen+", "+toHexString(fbcfg)+")"); - return null; - } - GLCapabilitiesImmutable caps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glp, display, fbcfg, true, true, true, GLXUtil.isMultisampleAvailable(display)); - return new X11GLXGraphicsConfiguration(x11Screen, caps, caps, new DefaultGLCapabilitiesChooser(), visualInfo, fbcfg, fbID); - + X11GLCapabilities caps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glp, display, fbcfg, true, true, true, GLXUtil.isMultisampleAvailable(display)); + return new X11GLXGraphicsConfiguration(x11Screen, caps, caps, new DefaultGLCapabilitiesChooser()); } private static X11GLXGraphicsConfiguration chooseGraphicsConfigurationFBConfig(GLCapabilitiesImmutable capsChosen, @@ -154,10 +234,7 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac X11GraphicsScreen x11Screen) { long recommendedFBConfig = -1; int recommendedIndex = -1; - int retFBID=-1; - GLCapabilitiesImmutable[] availableCaps = null; PointerBuffer fbcfgsL = null; - XVisualInfo retXVisualInfo = null; GLProfile glProfile = capsChosen.getGLProfile(); boolean onscreen = capsChosen.isOnscreen(); boolean usePBuffer = capsChosen.isPBuffer(); @@ -171,39 +248,39 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capsChosen, true, isMultisampleAvailable, display, screen); int[] count = { -1 }; + ArrayList/*<X11GLCapabilities>*/ availableCaps = new ArrayList(); + final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer); // 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice fbcfgsL = GLX.glXChooseFBConfig(display, screen, attribs, 0, count, 0); if (fbcfgsL != null && fbcfgsL.limit()>0) { - availableCaps = new GLCapabilitiesImmutable[fbcfgsL.limit()]; for (int i = 0; i < fbcfgsL.limit(); i++) { - if( !X11GLXGraphicsConfiguration.GLXFBConfigValid( display, fbcfgsL.get(i) ) ) { + if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, display, fbcfgsL.get(i), winattrmask, isMultisampleAvailable) ) { if(DEBUG) { System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: FBConfig invalid (1): ("+x11Screen+","+capsChosen+"): fbcfg: "+toHexString(fbcfgsL.get(i))); } - } else { - availableCaps[i] = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glProfile, display, fbcfgsL.get(i), - false, onscreen, usePBuffer, isMultisampleAvailable); } } - if(availableCaps[0]!=null) { + if(availableCaps.size() > 0) { recommendedFBConfig = fbcfgsL.get(0); recommendedIndex=0; if (DEBUG) { System.err.println("!!! glXChooseFBConfig recommended fbcfg " + toHexString(recommendedFBConfig) + ", idx " + recommendedIndex); System.err.println("!!! user caps " + capsChosen); - System.err.println("!!! fbcfg caps " + availableCaps[recommendedIndex]); - } - } else { - if (DEBUG) { - System.err.println("!!! glXChooseFBConfig no caps for recommended fbcfg " + toHexString(recommendedFBConfig)); - System.err.println("!!! user caps " + capsChosen); + System.err.println("!!! fbcfg caps " + availableCaps.get(recommendedIndex)); } + } else if (DEBUG) { + System.err.println("!!! glXChooseFBConfig no caps for recommended fbcfg " + toHexString(fbcfgsL.get(0))); + System.err.println("!!! user caps " + capsChosen); } } // 2nd choice: get all GLCapabilities available, no preferred recommendedIndex available - if(null == availableCaps) { + if( 0 == availableCaps.size() ) { + // reset .. + recommendedFBConfig = -1; + recommendedIndex = -1; + fbcfgsL = GLX.glXChooseFBConfig(display, screen, null, 0, count, 0); if (fbcfgsL == null || fbcfgsL.limit()<=0) { if(DEBUG) { @@ -212,78 +289,24 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac return null; } - availableCaps = new GLCapabilitiesImmutable[fbcfgsL.limit()]; for (int i = 0; i < fbcfgsL.limit(); i++) { - if( !X11GLXGraphicsConfiguration.GLXFBConfigValid( display, fbcfgsL.get(i) ) ) { + if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, display, fbcfgsL.get(i), winattrmask, isMultisampleAvailable) ) { if(DEBUG) { System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: FBConfig invalid (2): ("+x11Screen+"): fbcfg: "+toHexString(fbcfgsL.get(i))); } - } else { - availableCaps[i] = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glProfile, display, fbcfgsL.get(i), - false, onscreen, usePBuffer, isMultisampleAvailable); } } } - - if( recommendedIndex < 1 && null==chooser) { - chooser = new DefaultGLCapabilitiesChooser(); - } - - int chosenIndex = recommendedIndex; - try { - if(null != chooser) { - chosenIndex = chooser.chooseCapabilities(capsChosen, availableCaps, recommendedIndex); - if(DEBUG) { - System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig chooser: idx "+chosenIndex); - System.err.println("!!! user caps " + capsChosen); - System.err.println("!!! chosen caps " + availableCaps[chosenIndex]); - } - } - } catch (NativeWindowException e) { - if(DEBUG) { - e.printStackTrace(); - } - } - - if (chosenIndex < 0) { - // keep on going .. - // seek first available one .. - for(chosenIndex = 0; chosenIndex < availableCaps.length && availableCaps[chosenIndex]==null; chosenIndex++) { - // nop - } - if(chosenIndex==availableCaps.length) { - // give up .. - if(DEBUG) { - System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig Failed .. nothing available, bail out"); - } - return null; - } - if(DEBUG) { - System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig Failed .. unable to choose config, using first available idx: "+chosenIndex); - System.err.println("!!! user caps " + capsChosen); - System.err.println("!!! fallback caps " + availableCaps[chosenIndex]); - } - } else if (chosenIndex >= availableCaps.length) { - if(DEBUG) { - System.err.println("GLCapabilitiesChooser specified invalid index (expected 0.." + (availableCaps.length - 1) + ", got "+chosenIndex+")"); + int chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex); + if ( 0 > chosenIndex ) { + if (DEBUG) { + Thread.dumpStack(); } return null; } + X11GLCapabilities chosenCaps = (X11GLCapabilities) availableCaps.get(chosenIndex); - retFBID = X11GLXGraphicsConfiguration.glXFBConfig2FBConfigID(display, fbcfgsL.get(chosenIndex)); - - retXVisualInfo = GLX.glXGetVisualFromFBConfig(display, fbcfgsL.get(chosenIndex)); - if (retXVisualInfo==null) { - if(DEBUG) { - System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed glXGetVisualFromFBConfig ("+x11Screen+", "+fbcfgsL.get(chosenIndex) +" (Continue: "+(false==availableCaps[chosenIndex].isOnscreen())+"):\n\t"+availableCaps[chosenIndex]); - } - if(availableCaps[chosenIndex].isOnscreen()) { - // Onscreen drawables shall have a XVisual .. - return null; - } - } - - return new X11GLXGraphicsConfiguration(x11Screen, availableCaps[chosenIndex], capsReq, chooser, retXVisualInfo, fbcfgsL.get(chosenIndex), retFBID); + return new X11GLXGraphicsConfiguration(x11Screen, chosenCaps, capsReq, chooser); } private static X11GLXGraphicsConfiguration chooseGraphicsConfigurationXVisual(GLCapabilitiesImmutable capsChosen, @@ -294,16 +317,10 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac chooser = new DefaultGLCapabilitiesChooser(); } - // 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 - GLProfile glProfile = capsChosen.getGLProfile(); - boolean onscreen = capsChosen.isOnscreen(); - GLCapabilitiesImmutable[] caps = null; + final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(capsChosen.isOnscreen(), false /* pbuffer */); + ArrayList availableCaps = new ArrayList(); int recommendedIndex = -1; - XVisualInfo retXVisualInfo = null; - int chosen=-1; AbstractGraphicsDevice absDevice = x11Screen.getDevice(); long display = absDevice.getHandle(); @@ -311,8 +328,8 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac int screen = x11Screen.getIndex(); boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capsChosen, false, isMultisampleAvailable, display, screen); - XVisualInfo[] infos = null; + // 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice XVisualInfo recommendedVis = GLX.glXChooseVisual(display, screen, attribs, 0); if (DEBUG) { System.err.print("!!! glXChooseVisual recommended "); @@ -322,51 +339,39 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac System.err.println("visual id " + toHexString(recommendedVis.getVisualid())); } } + + // 2nd choice: get all GLCapabilities available, preferred recommendedIndex might be available if 1st choice was successful int[] count = new int[1]; XVisualInfo template = XVisualInfo.create(); template.setScreen(screen); - infos = X11Util.XGetVisualInfo(display, X11Lib.VisualScreenMask, template, count, 0); + XVisualInfo[] infos = X11Util.XGetVisualInfo(display, X11Lib.VisualScreenMask, template, count, 0); if (infos == null || infos.length<1) { throw new GLException("Error while enumerating available XVisualInfos"); } - caps = new GLCapabilitiesImmutable[infos.length]; + for (int i = 0; i < infos.length; i++) { - caps[i] = X11GLXGraphicsConfiguration.XVisualInfo2GLCapabilities(glProfile, display, infos[i], onscreen, false, isMultisampleAvailable); - // Attempt to find the visual chosenIndex by glXChooseVisual - if (recommendedVis != null && recommendedVis.getVisualid() == infos[i].getVisualid()) { - recommendedIndex = i; + if( !X11GLXGraphicsConfiguration.XVisualInfo2GLCapabilities(availableCaps, glProfile, display, infos[i], winattrmask, isMultisampleAvailable) ) { + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.getAvailableGLCapabilitiesXVisual: XVisual invalid: ("+x11Screen+"): fbcfg: "+toHexString(infos[i].getVisualid())); + } + } else { + // Attempt to find the visual chosenIndex by glXChooseVisual + if (recommendedVis != null && recommendedVis.getVisualid() == infos[i].getVisualid()) { + recommendedIndex = availableCaps.size() - 1; + } } } - try { - chosen = chooser.chooseCapabilities(capsChosen, caps, recommendedIndex); - } catch (NativeWindowException e) { - if(DEBUG) { - e.printStackTrace(); - } - chosen = -1; - } - if (chosen < 0) { - // keep on going .. - if(DEBUG) { - System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationXVisual Failed .. unable to choose config, using first"); - } - chosen = 0; // default .. - } else if (chosen >= caps.length) { - throw new GLException("GLCapabilitiesChooser specified invalid index (expected 0.." + (caps.length - 1) + ")"); - } - if (infos[chosen] == null) { - throw new GLException("GLCapabilitiesChooser chose an invalid visual for "+caps[chosen]); - } - retXVisualInfo = XVisualInfo.create(infos[chosen]); - return new X11GLXGraphicsConfiguration(x11Screen, caps[chosen], capsReq, chooser, retXVisualInfo, 0, -1); - } - static String toHexString(int val) { - return "0x"+Integer.toHexString(val); - } + int chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex); + if ( 0 > chosenIndex ) { + if (DEBUG) { + Thread.dumpStack(); + } + return null; + } + X11GLCapabilities chosenCaps = (X11GLCapabilities) availableCaps.get(chosenIndex); - static String toHexString(long val) { - return "0x"+Long.toHexString(val); + return new X11GLXGraphicsConfiguration(x11Screen, chosenCaps, capsReq, chooser); } } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java index 0fbe7a1c9..898a8a658 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java @@ -43,10 +43,8 @@ import javax.media.opengl.*; import com.jogamp.opengl.impl.*; import com.jogamp.nativewindow.impl.jawt.x11.*; import com.jogamp.nativewindow.impl.x11.*; -import com.jogamp.opengl.impl.x11.glx.X11GLXGraphicsConfigurationFactory; -import java.awt.image.ColorModel; -public class X11AWTGLXGraphicsConfigurationFactory extends GraphicsConfigurationFactory { +public class X11AWTGLXGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory { protected static final boolean DEBUG = Debug.debug("GraphicsConfiguration"); public X11AWTGLXGraphicsConfigurationFactory() { @@ -91,11 +89,11 @@ public class X11AWTGLXGraphicsConfigurationFactory extends GraphicsConfiguration displayHandle = X11Util.createDisplay(null); owner = true; if(DEBUG) { - System.err.println("X11AWTGLXGraphicsConfigurationFactory: using a thread local X11 display"); + System.err.println(Thread.currentThread().getName() + " - X11AWTGLXGraphicsConfigurationFactory: using a thread local X11 display"); } } else { if(DEBUG) { - System.err.println("X11AWTGLXGraphicsConfigurationFactory: using AWT X11 display 0x"+Long.toHexString(displayHandle)); + System.err.println(Thread.currentThread().getName() + " - X11AWTGLXGraphicsConfigurationFactory: using AWT X11 display 0x"+Long.toHexString(displayHandle)); } /** * May cause an exception on NVidia X11 Display destruction, @@ -153,15 +151,13 @@ public class X11AWTGLXGraphicsConfigurationFactory extends GraphicsConfiguration visualID = x11Config.getVisualID(); for (int i = 0; i < configs.length; i++) { gc = configs[i]; - if (gc != null) { - if (X11SunJDKReflection.graphicsConfigurationGetVisualID(gc) == visualID) { - if(DEBUG) { - System.err.println("Found matching default AWT visual: 0x"+Long.toHexString(visualID) +" -> "+x11Config); - } - return new AWTGraphicsConfiguration(awtScreen, - x11Config.getChosenCapabilities(), x11Config.getRequestedCapabilities(), - gc, x11Config); + if (X11SunJDKReflection.graphicsConfigurationGetVisualID(gc) == visualID) { + if(DEBUG) { + System.err.println("Found matching default AWT visual: 0x"+Long.toHexString(visualID) +" -> "+x11Config); } + return new AWTGraphicsConfiguration(awtScreen, + x11Config.getChosenCapabilities(), x11Config.getRequestedCapabilities(), + gc, x11Config); } } diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java index f22e11cb7..6073a75f8 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -43,11 +44,9 @@ import com.jogamp.opengl.impl.Debug; import com.jogamp.opengl.util.*; import com.jogamp.opengl.util.packrect.*; import com.jogamp.opengl.util.texture.*; -import com.jogamp.opengl.util.texture.awt.*; import java.awt.AlphaComposite; import java.awt.Color; -import java.awt.Composite; // For debugging purposes import java.awt.EventQueue; @@ -71,7 +70,6 @@ import java.security.*; import javax.media.opengl.*; import javax.media.opengl.glu.*; -import javax.media.opengl.glu.gl2.*; import javax.media.opengl.awt.*; @@ -720,7 +718,7 @@ public class TextRenderer { // The OpenGL spec is unclear about whether this changes the // buffer bindings, so preemptively zero out the GL_ARRAY_BUFFER // binding - if (is15Available(gl)) { + if (getUseVertexArrays() && is15Available(gl)) { try { gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0); } catch (Exception e) { @@ -1236,7 +1234,7 @@ public class TextRenderer { // The OpenGL spec is unclear about whether this changes the // buffer bindings, so preemptively zero out the GL_ARRAY_BUFFER // binding - if (is15Available(gl)) { + if (getUseVertexArrays() && is15Available(gl)) { try { gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0); } catch (Exception e) { @@ -1558,6 +1556,8 @@ public class TextRenderer { final int undefined = -2; FontRenderContext fontRenderContext; List/*<Glyph>*/ glyphsOutput = new ArrayList/*<Glyph>*/(); + HashMap/*<String, GlyphVector>*/fullGlyphVectorCache = new HashMap/*<String, GlyphVector>*/(); + HashMap/*<Character, GlyphMetrics>*/glyphMetricsCache = new HashMap/*<Character, GlyphMetrics>*/(); // The mapping from unicode character to font-specific glyph ID int[] unicodes2Glyphs; // The mapping from glyph ID to Glyph @@ -1573,8 +1573,13 @@ public class TextRenderer { public List/*<Glyph>*/ getGlyphs(CharSequence inString) { glyphsOutput.clear(); - iter.initFromCharSequence(inString); - GlyphVector fullRunGlyphVector = font.createGlyphVector(getFontRenderContext(), iter); + GlyphVector fullRunGlyphVector; + fullRunGlyphVector = (GlyphVector) fullGlyphVectorCache.get(inString.toString()); + if (fullRunGlyphVector == null) { + iter.initFromCharSequence(inString); + fullRunGlyphVector = font.createGlyphVector(getFontRenderContext(), iter); + fullGlyphVectorCache.put(inString.toString(), fullRunGlyphVector); + } boolean complex = (fullRunGlyphVector.getLayoutFlags() != 0); if (complex || DISABLE_GLYPH_CACHE) { // Punt to the robust version of the renderer @@ -1585,7 +1590,13 @@ public class TextRenderer { int lengthInGlyphs = fullRunGlyphVector.getNumGlyphs(); int i = 0; while (i < lengthInGlyphs) { - Glyph glyph = getGlyph(inString, fullRunGlyphVector, i); + Character letter = CharacterCache.valueOf(inString.charAt(i)); + GlyphMetrics metrics = (GlyphMetrics) glyphMetricsCache.get(letter); + if (metrics == null) { + metrics = fullRunGlyphVector.getGlyphMetrics(i); + glyphMetricsCache.put(letter, metrics); + } + Glyph glyph = getGlyph(inString, metrics, i); if (glyph != null) { glyphsOutput.add(glyph); i++; @@ -1594,7 +1605,7 @@ public class TextRenderer { // the cache StringBuffer buf = new StringBuffer(); while (i < lengthInGlyphs && - getGlyph(inString, fullRunGlyphVector, i) == null) { + getGlyph(inString, fullRunGlyphVector.getGlyphMetrics(i), i) == null) { buf.append(inString.charAt(i++)); } glyphsOutput.add(new Glyph(buf.toString(), @@ -1645,7 +1656,7 @@ public class TextRenderer { // if the unicode or glyph ID would be out of bounds of the // glyph cache. private Glyph getGlyph(CharSequence inString, - GlyphVector fullRunGlyphVector, + GlyphMetrics glyphMetrics, int index) { char unicodeID = inString.charAt(index); @@ -1661,7 +1672,7 @@ public class TextRenderer { // Must fabricate the glyph singleUnicode[0] = unicodeID; GlyphVector gv = font.createGlyphVector(getFontRenderContext(), singleUnicode); - return getGlyph(unicodeID, gv, fullRunGlyphVector.getGlyphMetrics(index)); + return getGlyph(unicodeID, gv, glyphMetrics); } // It's unclear whether this variant might produce less @@ -1698,6 +1709,26 @@ public class TextRenderer { return glyph; } } + + private static class CharacterCache { + private CharacterCache() { + } + + static final Character cache[] = new Character[127 + 1]; + + static { + for (int i = 0; i < cache.length; i++) { + cache[i] = new Character((char) i); + } + } + + public static Character valueOf(char c) { + if (c <= 127) { // must cache + return CharacterCache.cache[c]; + } + return new Character(c); + } + } class Pipelined_QuadRenderer { int mOutstandingGlyphsVerticesPipeline = 0; @@ -1712,7 +1743,7 @@ public class TextRenderer { mVertCoords = Buffers.newDirectFloatBuffer(kTotalBufferSizeCoordsVerts); mTexCoords = Buffers.newDirectFloatBuffer(kTotalBufferSizeCoordsTex); - usingVBOs = is15Available(gl); + usingVBOs = getUseVertexArrays() && is15Available(gl); if (usingVBOs) { try { @@ -1918,7 +1949,7 @@ public class TextRenderer { * rendering, or whether text is rendered using the OpenGL * immediate mode commands. Defaults to true. */ - public boolean getUseVertexArrays() { + public final boolean getUseVertexArrays() { return useVertexArrays; } @@ -1943,7 +1974,7 @@ public class TextRenderer { return smoothing; } - private boolean is15Available(GL gl) { + private final boolean is15Available(GL gl) { if (!checkFor_isExtensionAvailable_GL_VERSION_1_5) { isExtensionAvailable_GL_VERSION_1_5 = gl.isExtensionAvailable("GL_VERSION_1_5"); checkFor_isExtensionAvailable_GL_VERSION_1_5 = true; diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/TextureRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/awt/TextureRenderer.java index bc5aa517e..86dca59f4 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/awt/TextureRenderer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/awt/TextureRenderer.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -47,10 +48,8 @@ import java.awt.Rectangle; import java.awt.image.*; import javax.media.opengl.*; -import javax.media.opengl.glu.*; import javax.media.opengl.glu.gl2.*; import com.jogamp.opengl.util.texture.*; -import com.jogamp.opengl.util.texture.spi.*; import com.jogamp.opengl.util.texture.awt.*; /** Provides the ability to render into an OpenGL {@link diff --git a/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java b/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java index 695fad5a9..ecba18147 100644 --- a/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java +++ b/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java @@ -42,6 +42,7 @@ package javax.media.opengl; import javax.media.nativewindow.NativeWindowException; import com.jogamp.opengl.impl.Debug; +import java.util.List; import javax.media.nativewindow.CapabilitiesImmutable; /** <P> The default implementation of the {@link @@ -85,38 +86,40 @@ import javax.media.nativewindow.CapabilitiesImmutable; public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser { private static final boolean DEBUG = Debug.debug("CapabilitiesChooser"); - public int chooseCapabilities(CapabilitiesImmutable desired, - CapabilitiesImmutable[] available, - int windowSystemRecommendedChoice) { - GLCapabilitiesImmutable _desired = (GLCapabilitiesImmutable) desired; - GLCapabilitiesImmutable[] _available = (GLCapabilitiesImmutable[]) available; - int availnum = 0; - - for (int i = 0; i < _available.length; i++) { - if(null != _available[i]) { availnum++; } + public int chooseCapabilities(final CapabilitiesImmutable desired, + final List /*<CapabilitiesImmutable>*/ available, + final int windowSystemRecommendedChoice) { + if ( null == desired ) { + throw new NativeWindowException("Null desired capabilities"); + } + if ( 0 == available.size() ) { + throw new NativeWindowException("Empty available capabilities"); } + final GLCapabilitiesImmutable gldes = (GLCapabilitiesImmutable) desired; + final int availnum = available.size(); + if (DEBUG) { - System.err.println("Desired: " + _desired); - System.err.println("Available: Valid " + availnum + "/" + _available.length); - for (int i = 0; i < _available.length; i++) { - System.err.println(i + ": " + _available[i]); + System.err.println("Desired: " + gldes); + System.err.println("Available: " + availnum); + for (int i = 0; i < available.size(); i++) { + System.err.println(i + ": " + available.get(i)); } System.err.println("Window system's recommended choice: " + windowSystemRecommendedChoice); } if (windowSystemRecommendedChoice >= 0 && - windowSystemRecommendedChoice < _available.length && - _available[windowSystemRecommendedChoice] != null) { + windowSystemRecommendedChoice < availnum && + null != available.get(windowSystemRecommendedChoice)) { if (DEBUG) { System.err.println("Choosing window system's recommended choice of " + windowSystemRecommendedChoice); - System.err.println(_available[windowSystemRecommendedChoice]); + System.err.println(available.get(windowSystemRecommendedChoice)); } return windowSystemRecommendedChoice; } // Create score array - int[] scores = new int[_available.length]; + int[] scores = new int[availnum]; int NO_SCORE = -9999999; int DOUBLE_BUFFER_MISMATCH_PENALTY = 1000; int STENCIL_MISMATCH_PENALTY = 500; @@ -131,18 +134,18 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser { scores[i] = NO_SCORE; } // Compute score for each - for (int i = 0; i < scores.length; i++) { - GLCapabilitiesImmutable cur = _available[i]; + for (int i = 0; i < availnum; i++) { + GLCapabilitiesImmutable cur = (GLCapabilitiesImmutable) available.get(i); if (cur == null) { continue; } - if (_desired.isOnscreen() != cur.isOnscreen()) { + if (gldes.isOnscreen() != cur.isOnscreen()) { continue; } - if (!_desired.isOnscreen() && _desired.isPBuffer() && !cur.isPBuffer()) { + if (!gldes.isOnscreen() && gldes.isPBuffer() && !cur.isPBuffer()) { continue; // only skip if requested Offscreen && PBuffer, but no PBuffer available } - if (_desired.getStereo() != cur.getStereo()) { + if (gldes.getStereo() != cur.getStereo()) { continue; } int score = 0; @@ -150,20 +153,20 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser { // (Note that this decides the direction of all other penalties) score += (COLOR_MISMATCH_PENALTY_SCALE * ((cur.getRedBits() + cur.getGreenBits() + cur.getBlueBits() + cur.getAlphaBits()) - - (_desired.getRedBits() + _desired.getGreenBits() + _desired.getBlueBits() + _desired.getAlphaBits()))); + (gldes.getRedBits() + gldes.getGreenBits() + gldes.getBlueBits() + gldes.getAlphaBits()))); // Compute difference in depth buffer depth score += (DEPTH_MISMATCH_PENALTY_SCALE * sign(score) * - Math.abs(cur.getDepthBits() - _desired.getDepthBits())); + Math.abs(cur.getDepthBits() - gldes.getDepthBits())); // Compute difference in accumulation buffer depth score += (ACCUM_MISMATCH_PENALTY_SCALE * sign(score) * Math.abs((cur.getAccumRedBits() + cur.getAccumGreenBits() + cur.getAccumBlueBits() + cur.getAccumAlphaBits()) - - (_desired.getAccumRedBits() + _desired.getAccumGreenBits() + _desired.getAccumBlueBits() + _desired.getAccumAlphaBits()))); + (gldes.getAccumRedBits() + gldes.getAccumGreenBits() + gldes.getAccumBlueBits() + gldes.getAccumAlphaBits()))); // Compute difference in stencil bits - score += STENCIL_MISMATCH_PENALTY_SCALE * sign(score) * (cur.getStencilBits() - _desired.getStencilBits()); - if (cur.getDoubleBuffered() != _desired.getDoubleBuffered()) { + score += STENCIL_MISMATCH_PENALTY_SCALE * sign(score) * (cur.getStencilBits() - gldes.getStencilBits()); + if (cur.getDoubleBuffered() != gldes.getDoubleBuffered()) { score += sign(score) * DOUBLE_BUFFER_MISMATCH_PENALTY; } - if ((_desired.getStencilBits() > 0) && (cur.getStencilBits() == 0)) { + if ((gldes.getStencilBits() > 0) && (cur.getStencilBits() == 0)) { score += sign(score) * STENCIL_MISMATCH_PENALTY; } scores[i] = score; @@ -172,12 +175,12 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser { // non-hardware-accelerated visuals out boolean gotHW = false; int maxAbsoluteHWScore = 0; - for (int i = 0; i < scores.length; i++) { + for (int i = 0; i < availnum; i++) { int score = scores[i]; if (score == NO_SCORE) { continue; } - GLCapabilitiesImmutable cur = _available[i]; + GLCapabilitiesImmutable cur = (GLCapabilitiesImmutable) available.get(i); if (cur.getHardwareAccelerated()) { int absScore = Math.abs(score); if (!gotHW || @@ -188,12 +191,12 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser { } } if (gotHW) { - for (int i = 0; i < scores.length; i++) { + for (int i = 0; i < availnum; i++) { int score = scores[i]; if (score == NO_SCORE) { continue; } - GLCapabilitiesImmutable cur = _available[i]; + GLCapabilitiesImmutable cur = (GLCapabilitiesImmutable) available.get(i); if (!cur.getHardwareAccelerated()) { if (score <= 0) { score -= maxAbsoluteHWScore; @@ -207,7 +210,7 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser { if (DEBUG) { System.err.print("Scores: ["); - for (int i = 0; i < _available.length; i++) { + for (int i = 0; i < availnum; i++) { if (i > 0) { System.err.print(","); } @@ -219,7 +222,7 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser { // Ready to select. Choose score closest to 0. int scoreClosestToZero = NO_SCORE; int chosenIndex = -1; - for (int i = 0; i < scores.length; i++) { + for (int i = 0; i < availnum; i++) { int score = scores[i]; if (score == NO_SCORE) { continue; @@ -238,7 +241,7 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser { if (DEBUG) { System.err.println("Chosen index: " + chosenIndex); System.err.println("Chosen capabilities:"); - System.err.println(_available[chosenIndex]); + System.err.println(available.get(chosenIndex)); } return chosenIndex; @@ -250,4 +253,5 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser { } return 1; } + } diff --git a/src/jogl/classes/javax/media/opengl/GLCapabilities.java b/src/jogl/classes/javax/media/opengl/GLCapabilities.java index 82f83dc82..1ae9e40aa 100644 --- a/src/jogl/classes/javax/media/opengl/GLCapabilities.java +++ b/src/jogl/classes/javax/media/opengl/GLCapabilities.java @@ -143,6 +143,56 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil return res; } + /** comparing hw/sw, stereo, multisample, stencil, RGBA and depth only */ + public int compareTo(Object o) { + if ( ! ( o instanceof GLCapabilities ) ) { + Class c = (null != o) ? o.getClass() : null ; + throw new ClassCastException("Not a GLCapabilities object: " + c); + } + + final GLCapabilities caps = (GLCapabilities) o; + + if(hardwareAccelerated && !caps.hardwareAccelerated) { + return 1; + } else if(!hardwareAccelerated && caps.hardwareAccelerated) { + return -1; + } + + if(stereo && !caps.stereo) { + return 1; + } else if(!stereo && caps.stereo) { + return -1; + } + + final int ms = sampleBuffers ? numSamples : 0; + final int xms = caps.sampleBuffers ? caps.numSamples : 0; + + if(ms > xms) { + return 1; + } else if( ms < xms ) { + return -1; + } + + if(stencilBits > caps.stencilBits) { + return 1; + } else if(stencilBits < caps.stencilBits) { + return -1; + } + + final int sc = super.compareTo(caps); // RGBA + if(0 != sc) { + return sc; + } + + if(depthBits > caps.depthBits) { + return 1; + } else if(depthBits < caps.depthBits) { + return -1; + } + + return 0; // they are equal: hw/sw, stereo, multisample, stencil, RGBA and depth + } + /** Returns the GL profile you desire or used by the drawable. */ public GLProfile getGLProfile() { return glProfile; @@ -158,11 +208,30 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil return pbuffer; } - /** Enables or disables pbuffer usage. */ + /** + * Enables or disables pbuffer usage.<br> + * If enabled, onscreen := false. + * Defaults to false. + */ public void setPBuffer(boolean onOrOff) { + if(onOrOff) { + setOnscreen(false); + } pbuffer = onOrOff; } + /** + * Sets whether the drawable surface supports onscreen.<br> + * If enabled, pbuffer := false.<br> + * Defaults to true. + */ + public void setOnscreen(boolean onscreen) { + if(onscreen) { + setPBuffer(false); + } + super.setOnscreen(onscreen); + } + /** Indicates whether double-buffering is enabled. */ public boolean getDoubleBuffered() { return doubleBuffered; @@ -340,28 +409,54 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil return pbufferRenderToTextureRectangle; } + public StringBuffer toString(StringBuffer sink) { + if(null == sink) { + sink = new StringBuffer(); + } + + int samples = sampleBuffers ? numSamples : 0 ; + + super.toString(sink); + + sink.append(", accum-rgba ").append(accumRedBits).append("/").append(accumGreenBits).append("/").append(accumBlueBits).append("/").append(accumAlphaBits); + sink.append(", dp/st/ms: ").append(depthBits).append("/").append(stencilBits).append("/").append(samples); + if(doubleBuffered) { + sink.append(", dbl"); + } else { + sink.append(", one"); + } + if(stereo) { + sink.append(", stereo"); + } else { + sink.append(", mono "); + } + if(hardwareAccelerated) { + sink.append(", hw, "); + } else { + sink.append(", sw, "); + } + sink.append(glProfile); + if(!isOnscreen()) { + if(pbuffer) { + sink.append(", pbuffer [r2t ").append(pbufferRenderToTexture?1:0) + .append(", r2tr ").append(pbufferRenderToTextureRectangle?1:0) + .append(", float ").append(pbufferFloatingPointBuffers?1:0) + .append("]"); + } else { + sink.append(", pixmap"); + } + } + + return sink; + } + /** Returns a textual representation of this GLCapabilities object. */ public String toString() { StringBuffer msg = new StringBuffer(); - msg.append("GLCapabilities["); - msg.append(super.toString()); - msg.append(", GL profile: " + glProfile + - ", PBuffer: " + pbuffer + - ", DoubleBuffered: " + doubleBuffered + - ", Stereo: " + stereo + - ", HardwareAccelerated: " + hardwareAccelerated + - ", DepthBits: " + depthBits + - ", StencilBits: " + stencilBits + - ", Red Accum: " + accumRedBits + - ", Green Accum: " + accumGreenBits + - ", Blue Accum: " + accumBlueBits + - ", Alpha Accum: " + accumAlphaBits + - ", Multisample: " + sampleBuffers + - ", Num samples: "+(sampleBuffers ? numSamples : 0)); - msg.append(", PBuffer-FloatingPointBuffers: "+pbufferFloatingPointBuffers+ - ", PBuffer-RenderToTexture: "+pbufferRenderToTexture+ - ", PBuffer-RenderToTextureRectangle: "+pbufferRenderToTextureRectangle+ "]"); + msg.append("GLCaps["); + toString(msg); + msg.append("]"); return msg.toString(); } } diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java index 72073deef..4c9b737d5 100644 --- a/src/jogl/classes/javax/media/opengl/GLContext.java +++ b/src/jogl/classes/javax/media/opengl/GLContext.java @@ -40,10 +40,10 @@ package javax.media.opengl; -import com.jogamp.opengl.impl.Debug; import java.util.HashMap; import java.util.HashSet; import javax.media.nativewindow.AbstractGraphicsDevice; +import com.jogamp.opengl.impl.Debug; /** Abstraction for an OpenGL rendering context. In order to perform OpenGL rendering, a context must be "made current" on the current @@ -579,10 +579,6 @@ public abstract class GLContext { */ private static /*final*/ HashSet/*<UniqueDeviceString>*/ deviceVersionsAvailableSet = new HashSet(); - protected static String getContextFQN(AbstractGraphicsDevice device, int major, int minor, int ctp) { - return device.getUniqueID() + "-" + toHexString(compose8bit(major, minor, ctp, 0)); - } - protected static String getDeviceVersionAvailableKey(AbstractGraphicsDevice device, int major, int profile) { return device.getUniqueID() + "-" + toHexString(compose8bit(major, profile, 0, 0)); } diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java index f9591e84d..500173cf2 100644 --- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java +++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java @@ -40,14 +40,14 @@ package javax.media.opengl; -import com.jogamp.common.JogampRuntimeException; -import com.jogamp.common.impl.Debug; -import com.jogamp.common.util.ReflectionUtil; - import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; -import java.util.HashSet; +import java.util.List; + +import com.jogamp.common.JogampRuntimeException; +import com.jogamp.common.impl.Debug; +import com.jogamp.common.util.ReflectionUtil; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; @@ -221,6 +221,9 @@ public abstract class GLDrawableFactory { } } + protected void enterThreadCriticalZone() {}; + protected void leaveThreadCriticalZone() {}; + protected abstract void shutdownInstance(); /** @@ -237,6 +240,24 @@ public abstract class GLDrawableFactory { */ public abstract boolean getIsDeviceCompatible(AbstractGraphicsDevice device); + protected final AbstractGraphicsDevice validateDevice(AbstractGraphicsDevice device) { + if(null==device) { + device = getDefaultDevice(); + if(null==device) { + throw new InternalError("no default device"); + } + if (GLProfile.DEBUG) { + System.err.println("Info: GLDrawableFactory.validateDevice: using default device : "+device); + } + } else if( !getIsDeviceCompatible(device) ) { + if (GLProfile.DEBUG) { + System.err.println("Info: GLDrawableFactory.validateDevice: device not compatible : "+device); + } + return null; + } + return device; + } + /** * Returns true if a shared context is already mapped to the <code>device</code> {@link AbstractGraphicsDevice#getConnection()}, * or if a new shared context could be created and mapped. Otherwise return false.<br> @@ -256,24 +277,28 @@ public abstract class GLDrawableFactory { * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device. */ protected final GLContext getOrCreateSharedContext(AbstractGraphicsDevice device) { - if(null==device) { - device = getDefaultDevice(); - if(null==device) { - throw new InternalError("no default device"); - } - if (GLProfile.DEBUG) { - System.err.println("Info: GLDrawableFactory.getOrCreateSharedContext: using default device : "+device); - } - } else if( !getIsDeviceCompatible(device) ) { - if (GLProfile.DEBUG) { - System.err.println("Info: GLDrawableFactory.getOrCreateSharedContext: device not compatible : "+device); - } - return null; + device = validateDevice(device); + if(null!=device) { + return getOrCreateSharedContextImpl(device); } - return getOrCreateSharedContextImpl(device); + return null; } protected abstract GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device); + /** + * Returns the sole GLDrawableFactory instance for the desktop (X11, WGL, ..) if exist or null + */ + public static GLDrawableFactory getDesktopFactory() { + return nativeOSFactory; + } + + /** + * Returns the sole GLDrawableFactory instance for EGL if exist or null + */ + public static GLDrawableFactory getEGLFactory() { + return eglFactory; + } + /** * Returns the sole GLDrawableFactory instance. * @@ -298,6 +323,34 @@ public abstract class GLDrawableFactory { throw new GLException("No native platform GLDrawableFactory, nor EGLDrawableFactory available: "+glProfileImplName); } + protected static GLDrawableFactory getFactoryImpl(AbstractGraphicsDevice device) throws GLException { + if(null != nativeOSFactory && nativeOSFactory.getIsDeviceCompatible(device)) { + return nativeOSFactory; + } + if(null != eglFactory && eglFactory.getIsDeviceCompatible(device)) { + return eglFactory; + } + throw new GLException("No native platform GLDrawableFactory, nor EGLDrawableFactory available: "+device); + } + + /** + * Returns an array of available GLCapabilities for the device.<br> + * The list is sorted by the native ID, ascending.<br> + * The chosen GLProfile statement in the result may not refer to the maximum available profile + * due to implementation constraints, ie using the shared resource. + * + * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device. + * @return A list of {@link javax.media.opengl.GLCapabilitiesImmutable}'s, maybe empty if none is available. + */ + public final List/*GLCapabilitiesImmutable*/ getAvailableCapabilities(AbstractGraphicsDevice device) { + device = validateDevice(device); + if(null!=device) { + return getAvailableCapabilitiesImpl(device); + } + return null; + } + protected abstract List/*GLCapabilitiesImmutable*/ getAvailableCapabilitiesImpl(AbstractGraphicsDevice device); + //---------------------------------------------------------------------- // Methods to create high-level objects diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java index c7b1e80cf..10d92b050 100644 --- a/src/jogl/classes/javax/media/opengl/GLProfile.java +++ b/src/jogl/classes/javax/media/opengl/GLProfile.java @@ -47,12 +47,13 @@ import com.jogamp.opengl.impl.GLDrawableFactoryImpl; import com.jogamp.opengl.impl.GLDynamicLookupHelper; import com.jogamp.opengl.impl.DesktopGLDynamicLookupHelper; import com.jogamp.opengl.JoglVersion; -import java.util.HashMap; -import java.util.Iterator; -import java.security.*; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.opengl.fixedfunc.GLPointerFunc; import javax.media.nativewindow.NativeWindowFactory; +import java.util.HashMap; +import java.util.Iterator; +import java.security.*; +import java.util.List; /** * Specifies the the OpenGL profile. @@ -70,8 +71,13 @@ public class GLProfile { /** * Static one time initialization of JOGL. * <p> + * The parameter <code>firstUIActionOnProcess</code> has an impact on concurrent locking,<br> + * see {@link javax.media.nativewindow.NativeWindowFactory#initSingleton(boolean) NativeWindowFactory.initSingleton(firstUIActionOnProcess)}. + * </p> + * <p> * Applications shall call this methods <b>ASAP</b>, before any other UI invocation.<br> - * You may issue the call in your main function.<br> + * You may issue the call in your <code>main class</code> static block, which is the earliest point in your application/applet lifecycle, + * or within the <code>main function</code>.<br> * In case applications are able to initialize JOGL before any other UI action,<br> * they shall invoke this method with <code>firstUIActionOnProcess=true</code> and benefit from fast native multithreading support on all platforms if possible.</P> * <P> @@ -341,17 +347,35 @@ public class GLProfile { /** * All GL Profiles in the order of default detection. - * Desktop compatibility profiles (the one with fixed function pipeline) comes first. - * - * FIXME GL3GL4: Due to GL3 and GL4 implementation bugs, we still choose GL2 first, if available! + * Desktop compatibility profiles (the one with fixed function pipeline) comes first + * from highest to lowest version. * * <ul> - * <li> GL2 - * <li> GL3bc * <li> GL4bc + * <li> GL3bc + * <li> GL2 * <li> GL2GL3 + * <li> GL4 * <li> GL3 + * <li> GL2ES2 + * <li> GLES2 + * <li> GL2ES1 + * <li> GLES1 + * </ul> + * + */ + public static final String[] GL_PROFILE_LIST_ALL = new String[] { GL4bc, GL3bc, GL2, GL2GL3, GL4, GL3, GL2ES2, GLES2, GL2ES1, GLES1 }; + + /** + * Order of maximum profiles. + * + * <ul> + * <li> GL4bc * <li> GL4 + * <li> GL3bc + * <li> GL3 + * <li> GL2 + * <li> GL2GL3 * <li> GL2ES2 * <li> GLES2 * <li> GL2ES1 @@ -359,7 +383,21 @@ public class GLProfile { * </ul> * */ - public static final String[] GL_PROFILE_LIST_ALL = new String[] { GL2, GL3bc, GL4bc, GL2GL3, GL3, GL4, GL2ES2, GLES2, GL2ES1, GLES1 }; + public static final String[] GL_PROFILE_LIST_MAX = new String[] { GL4bc, GL4, GL3bc, GL3, GL2, GL2GL3, GL2ES2, GLES2, GL2ES1, GLES1 }; + + /** + * Order of minimum original desktop profiles. + * + * <ul> + * <li> GL2 + * <li> GL3bc + * <li> GL4bc + * <li> GL3 + * <li> GL4 + * </ul> + * + */ + public static final String[] GL_PROFILE_LIST_MIN_DESKTOP = new String[] { GL2, GL3bc, GL4bc, GL3, GL4 }; /** * Order of maximum fixed function profiles @@ -389,13 +427,11 @@ public class GLProfile { * </ul> * */ - public static final String[] GL_PROFILE_LIST_MAX_PROGSHADER = new String[] { GL4, GL4bc, GL3, GL3bc, GL2, GL2ES2, GLES2 }; + public static final String[] GL_PROFILE_LIST_MAX_PROGSHADER = new String[] { GL4bc, GL4, GL3bc, GL3, GL2, GL2ES2, GLES2 }; /** * All GL2ES2 Profiles in the order of default detection. * - * FIXME GL3GL4: Due to GL3 and GL4 implementation bugs, we still choose GL2 first, if available! - * * <ul> * <li> GL2ES2 * <li> GL2 @@ -405,13 +441,11 @@ public class GLProfile { * </ul> * */ - public static final String[] GL_PROFILE_LIST_GL2ES2 = new String[] { GL2ES2, GL2, GL3, GL4, GLES2 }; + public static final String[] GL_PROFILE_LIST_GL2ES2 = new String[] { GL2ES2, GL4, GL3, GL2, GLES2 }; /** * All GL2ES1 Profiles in the order of default detection. * - * FIXME GL3GL4: Due to GL3 and GL4 implementation bugs, we still choose GL2 first, if available! - * * <ul> * <li> GL2ES1 * <li> GL2 @@ -421,7 +455,7 @@ public class GLProfile { * </ul> * */ - public static final String[] GL_PROFILE_LIST_GL2ES1 = new String[] { GL2ES1, GL2, GL3bc, GL4bc, GLES1 }; + public static final String[] GL_PROFILE_LIST_GL2ES1 = new String[] { GL2ES1, GL4bc, GL3bc, GL2, GLES1 }; /** * All GLES Profiles in the order of default detection. @@ -449,7 +483,48 @@ public class GLProfile { } /** - * Returns the highest profile, implementing the fixed function pipeline + * Returns the highest profile. + * It selects the first of the set: {@link GLProfile#GL_PROFILE_LIST_MAX} + * + * @throws GLException if no implementation for the given profile is found. + * @see #GL_PROFILE_LIST_MAX + */ + public static GLProfile getMaximum(AbstractGraphicsDevice device) + throws GLException + { + return get(device, GL_PROFILE_LIST_MAX); + } + + /** Uses the default device */ + public static GLProfile getMaximum() + throws GLException + { + return get(GL_PROFILE_LIST_MAX); + } + + /** + * Returns the lowest desktop profile. + * It selects the first of the set: {@link GLProfile#GL_PROFILE_LIST_MIN_DESKTOP} + * + * @throws GLException if no implementation for the given profile is found. + * @see #GL_PROFILE_LIST_MIN_DESKTOP + */ + public static GLProfile getMinDesktop(AbstractGraphicsDevice device) + throws GLException + { + return get(device, GL_PROFILE_LIST_MIN_DESKTOP); + } + + /** Uses the default device */ + public static GLProfile getMinDesktop() + throws GLException + { + return get(GL_PROFILE_LIST_MIN_DESKTOP); + } + + + /** + * Returns the highest profile, implementing the fixed function pipeline. * It selects the first of the set: {@link GLProfile#GL_PROFILE_LIST_MAX_FIXEDFUNC} * * @throws GLException if no implementation for the given profile is found. @@ -1082,6 +1157,7 @@ public class GLProfile { * Throws an GLException if no profile could be found at all. */ private static void initProfilesForDefaultDevices(boolean firstUIActionOnProcess) { + NativeWindowFactory.initSingleton(firstUIActionOnProcess); if(DEBUG) { System.err.println("GLProfile.init firstUIActionOnProcess: "+ firstUIActionOnProcess @@ -1092,8 +1168,6 @@ public class GLProfile { System.err.println(JoglVersion.getInstance()); } - NativeWindowFactory.initSingleton(firstUIActionOnProcess); - ClassLoader classloader = GLProfile.class.getClassLoader(); isAWTAvailable = NativeWindowFactory.isAWTAvailable() && @@ -1187,7 +1261,7 @@ public class GLProfile { boolean addedAnyProfile = initProfilesForDevice(defaultDesktopDevice) || initProfilesForDevice(defaultEGLDevice); - + if(DEBUG) { System.err.println("GLProfile.init isAWTAvailable "+isAWTAvailable); System.err.println("GLProfile.init has desktopFactory "+(null!=desktopFactory)); @@ -1196,8 +1270,8 @@ public class GLProfile { System.err.println("GLProfile.init has eglFactory "+(null!=eglFactory)); System.err.println("GLProfile.init hasGLES1Impl "+hasGLES1Impl); System.err.println("GLProfile.init hasGLES2Impl "+hasGLES2Impl); - System.err.println("GLProfile.init defaultDesktopDevice "+defaultDevice); - System.err.println("GLProfile.init defaultEGLDevice "+defaultDevice); + System.err.println("GLProfile.init defaultDesktopDevice "+defaultDesktopDevice); + System.err.println("GLProfile.init defaultEGLDevice "+defaultEGLDevice); System.err.println("GLProfile.init defaultDevice "+defaultDevice); } @@ -1211,10 +1285,22 @@ public class GLProfile { * @return true if any profile for the device exists, otherwise false */ private static synchronized boolean initProfilesForDevice(AbstractGraphicsDevice device) { + if(null == device) { + return false; + } + GLDrawableFactory factory = GLDrawableFactory.getFactoryImpl(device); + factory.enterThreadCriticalZone(); + try { + return initProfilesForDeviceImpl(device); + } finally { + factory.leaveThreadCriticalZone(); + } + } + private static synchronized boolean initProfilesForDeviceImpl(AbstractGraphicsDevice device) { boolean isSet = GLContext.getAvailableGLVersionsSet(device); if(DEBUG) { - String msg = "Info: GLProfile.initProfilesForDevice: "+device.getConnection()+", isSet "+isSet; + String msg = "Info: GLProfile.initProfilesForDevice: "+device+", isSet "+isSet; Throwable t = new Throwable(msg); t.printStackTrace(); // System.err.println(msg); @@ -1234,7 +1320,7 @@ public class GLProfile { // hence querying all available GLProfiles boolean desktopSharedCtxAvail = desktopFactory.getIsSharedContextAvailable(device); if (DEBUG) { - System.err.println("GLProfile.initProfilesForDevice: "+device.getConnection()+": desktop Shared Ctx "+desktopSharedCtxAvail); + System.err.println("GLProfile.initProfilesForDevice: "+device+": desktop Shared Ctx "+desktopSharedCtxAvail); } if( null == GLContext.getAvailableGLVersion(device, 2, GLContext.CTX_PROFILE_COMPAT) ) { // nobody yet set the available desktop versions, see {@link GLContextImpl#makeCurrent}, @@ -1243,13 +1329,8 @@ public class GLProfile { 2, GLContext.CTX_PROFILE_COMPAT, 1, 5, GLContext.CTX_PROFILE_COMPAT|GLContext.CTX_OPTION_ANY); } - computeProfileMap(device, false /* desktopCtxUndef*/, false /* eglCtxUndef */); - addedDesktopProfile = null != GLProfile.getDefault(device); - } else if(DEBUG) { - System.err.println("GLProfile: DesktopFactory - Device is not available: "+device.getConnection()); - } - - if( null!=eglFactory && ( hasGLES2Impl || hasGLES1Impl ) && eglFactory.getIsDeviceCompatible(device)) { + addedDesktopProfile = computeProfileMap(device, false /* desktopCtxUndef*/, false /* eglCtxUndef */); + } else if( null!=eglFactory && ( hasGLES2Impl || hasGLES1Impl ) && eglFactory.getIsDeviceCompatible(device)) { // 1st pretend we have all EGL profiles .. computeProfileMap(device, false /* desktopCtxUndef*/, true /* eglCtxUndef */); @@ -1257,7 +1338,7 @@ public class GLProfile { // hence querying all available GLProfiles boolean eglSharedCtxAvail = eglFactory.getIsSharedContextAvailable(device); if (DEBUG) { - System.err.println("GLProfile.initProfilesForDevice: "+device.getConnection()+": egl Shared Ctx "+eglSharedCtxAvail); + System.err.println("GLProfile.initProfilesForDevice: "+device+": egl Shared Ctx "+eglSharedCtxAvail); } if(hasGLES2Impl && null == GLContext.getAvailableGLVersion(device, 2, GLContext.CTX_PROFILE_ES) ) { // nobody yet set the available desktop versions, see {@link GLContextImpl#makeCurrent}, @@ -1273,10 +1354,12 @@ public class GLProfile { 1, GLContext.CTX_PROFILE_ES, 1, 0, GLContext.CTX_PROFILE_ES|GLContext.CTX_OPTION_ANY); } - computeProfileMap(device, false /* desktopCtxUndef*/, false /* eglCtxUndef */); - addedEGLProfile = null != GLProfile.get(device, GL_PROFILE_LIST_GLES); - } else if(DEBUG) { - System.err.println("GLProfile: EGLFactory - Device is not available: "+device.getConnection()); + addedEGLProfile = computeProfileMap(device, false /* desktopCtxUndef*/, false /* eglCtxUndef */); + } else { + setProfileMap(device, new HashMap()); // empty + if(DEBUG) { + System.err.println("GLProfile: EGLFactory - Device is not available: "+device); + } } if(!GLContext.getAvailableGLVersionsSet(device)) { @@ -1288,9 +1371,16 @@ public class GLProfile { System.err.println("GLProfile.initProfilesForDevice: "+device.getConnection()+": "+glAvailabilityToString(device)); if(addedDesktopProfile) { dumpGLInfo(desktopFactory, device); - } - if(addedEGLProfile) { + List/*<GLCapabilitiesImmutable>*/ availCaps = desktopFactory.getAvailableCapabilities(device); + for(int i=0; i<availCaps.size(); i++) { + System.err.println(availCaps.get(i)); + } + } else if(addedEGLProfile) { dumpGLInfo(eglFactory, device); + List/*<GLCapabilitiesImmutable>*/ availCaps = eglFactory.getAvailableCapabilities(device); + for(int i=0; i<availCaps.size(); i++) { + System.err.println(availCaps.get(i)); + } } } @@ -1299,16 +1389,12 @@ public class GLProfile { private static void dumpGLInfo(GLDrawableFactoryImpl factory, AbstractGraphicsDevice device) { GLContext ctx = factory.getOrCreateSharedContext(device); - AbstractGraphicsDevice nativeDevice = ctx.getGLDrawable().getNativeSurface() - .getGraphicsConfiguration().getNativeGraphicsConfiguration() - .getScreen().getDevice(); - nativeDevice.lock(); + System.err.println("GLProfile.dumpGLInfo: "+ctx); + ctx.makeCurrent(); try { - ctx.makeCurrent(); System.err.println(JoglVersion.getGLInfo(ctx.getGL(), null)); - ctx.release(); } finally { - nativeDevice.unlock(); + ctx.release(); } } @@ -1359,7 +1445,7 @@ public class GLProfile { sb.append("]"); } - private static void computeProfileMap(AbstractGraphicsDevice device, boolean desktopCtxUndef, boolean eglCtxUndef) { + private static boolean computeProfileMap(AbstractGraphicsDevice device, boolean desktopCtxUndef, boolean eglCtxUndef) { if (DEBUG) { System.err.println("GLProfile.init map "+device.getConnection()+", desktopCtxUndef "+desktopCtxUndef+", eglCtxUndef "+eglCtxUndef); } @@ -1390,6 +1476,7 @@ public class GLProfile { _mappedProfiles.put(GL_DEFAULT, defaultGLProfile); } setProfileMap(device, _mappedProfiles); + return _mappedProfiles.size() > 0; } /** @@ -1489,11 +1576,10 @@ public class GLProfile { String deviceKey = device.getUniqueID(); HashMap map = (HashMap) deviceConn2ProfileMap.get(deviceKey); if(null==map) { - map = new HashMap(); - synchronized ( deviceConn2ProfileMap ) { - deviceConn2ProfileMap.put(deviceKey, map); - } initProfilesForDevice(device); + if( null == deviceConn2ProfileMap.get(deviceKey) ) { + throw new InternalError("initProfilesForDevice(..) didn't issue setProfileMap(..) on "+device); + } } return map; } diff --git a/src/jogl/classes/javax/media/opengl/awt/AWTGLAutoDrawable.java b/src/jogl/classes/javax/media/opengl/awt/AWTGLAutoDrawable.java index d92cec389..d1e725b00 100644 --- a/src/jogl/classes/javax/media/opengl/awt/AWTGLAutoDrawable.java +++ b/src/jogl/classes/javax/media/opengl/awt/AWTGLAutoDrawable.java @@ -40,7 +40,6 @@ package javax.media.opengl.awt; import javax.media.opengl.*; -import javax.media.opengl.glu.*; public interface AWTGLAutoDrawable extends GLAutoDrawable, ComponentEvents { /** Requests a new width and height for this AWTGLAutoDrawable. */ diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index 8b20b9ed1..acabe58a5 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -40,31 +40,62 @@ package javax.media.opengl.awt; -import com.jogamp.common.GlueGenVersion; -import com.jogamp.common.util.VersionUtil; -import com.jogamp.nativewindow.NativeWindowVersion; -import javax.media.opengl.*; -import javax.media.nativewindow.*; -import javax.media.nativewindow.awt.*; - -import com.jogamp.opengl.impl.*; -import com.jogamp.opengl.JoglVersion; +import java.beans.Beans; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.awt.Canvas; import java.awt.Color; -import java.awt.Component; import java.awt.FontMetrics; import java.awt.Frame; import java.awt.Graphics; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; -import java.awt.Window; -import java.awt.event.WindowEvent; -import java.awt.event.WindowAdapter; -import java.awt.geom.*; -import java.beans.*; -import java.lang.reflect.*; -import java.security.*; +import java.awt.geom.Rectangle2D; + +import java.awt.EventQueue; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; + +import javax.media.nativewindow.WindowClosingProtocol; +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.GraphicsConfigurationFactory; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.nativewindow.awt.AWTGraphicsConfiguration; +import javax.media.nativewindow.awt.AWTGraphicsDevice; +import javax.media.nativewindow.awt.AWTGraphicsScreen; +import javax.media.nativewindow.awt.AWTWindowClosingProtocol; + +import javax.media.opengl.GL; +import javax.media.opengl.GLAnimatorControl; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesChooser; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; +import javax.media.opengl.GLRunnable; +import javax.media.opengl.Threading; + +import com.jogamp.nativewindow.NativeWindowVersion; +import com.jogamp.common.GlueGenVersion; +import com.jogamp.common.util.VersionUtil; +import com.jogamp.opengl.JoglVersion; + +import com.jogamp.common.util.locks.RecursiveLock; +import com.jogamp.opengl.impl.Debug; +import com.jogamp.opengl.impl.GLContextImpl; +import com.jogamp.opengl.impl.GLDrawableHelper; +import com.jogamp.opengl.impl.ThreadingImpl; // FIXME: Subclasses need to call resetGLFunctionAvailability() on their // context whenever the displayChanged() function is called on our @@ -104,7 +135,7 @@ import java.security.*; * </ul> */ -public class GLCanvas extends Canvas implements AWTGLAutoDrawable { +public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosingProtocol { private static final boolean DEBUG; private static final GLProfile defaultGLProfile; @@ -126,6 +157,13 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { private GLContext shareWith; private GraphicsDevice device; + private AWTWindowClosingProtocol awtWindowClosingProtocol = + new AWTWindowClosingProtocol(this, new Runnable() { + public void run() { + GLCanvas.this.destroy(); + } + }); + /** Creates a new GLCanvas component with a default set of OpenGL capabilities, using the default OpenGL capabilities selection mechanism, on the default screen device. */ @@ -202,33 +240,6 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { this.device = device; } - protected interface DestroyMethod { - public void destroyMethod(); - } - - /* package private */ final static Object addClosingListener(Component c, final DestroyMethod d) { - WindowAdapter cl = null; - Window w = getWindow(c); - if(null!=w) { - cl = new WindowAdapter() { - public void windowClosing(WindowEvent e) { - // we have to issue this call rigth away, - // otherwise the window gets destroyed - d.destroyMethod(); - } - }; - w.addWindowListener(cl); - } - return cl; - } - - private final static Window getWindow(Component c) { - while ( c!=null && ! ( c instanceof Window ) ) { - c = c.getParent(); - } - return (Window)c; - } - /** * Overridden to choose a GraphicsConfiguration on a parent container's * GraphicsDevice because both devices @@ -340,18 +351,33 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { } public GLContext createContext(GLContext shareWith) { - return drawable.createContext(shareWith); + drawableSync.lock(); + try { + return (null != drawable) ? drawable.createContext(shareWith) : null; + } finally { + drawableSync.unlock(); + } } public void setRealized(boolean realized) { } public boolean isRealized() { - return ( null != drawable ) ? drawable.isRealized() : false; + drawableSync.lock(); + try { + return ( null != drawable ) ? drawable.isRealized() : false; + } finally { + drawableSync.unlock(); + } } - private Object closingListener = null; - private Object closingListenerLock = new Object(); + public int getDefaultCloseOperation() { + return awtWindowClosingProtocol.getDefaultCloseOperation(); + } + + public int setDefaultCloseOperation(int op) { + return awtWindowClosingProtocol.setDefaultCloseOperation(op); + } public void display() { if( !validateGLDrawable() ) { @@ -359,63 +385,63 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { } maybeDoSingleThreadedWorkaround(displayOnEventDispatchThreadAction, displayAction); - if(null==closingListener) { - synchronized(closingListenerLock) { - if(null==closingListener) { - closingListener=addClosingListener(this, new DestroyMethod() { - public void destroyMethod() { destroy(); } }); - } - } - } + + awtWindowClosingProtocol.addClosingListenerOneShot(); } private void dispose(boolean regenerate) { - if(DEBUG) { - Exception ex1 = new Exception("Info: dispose("+regenerate+") - start"); - ex1.printStackTrace(); - } - - if(null!=context) { - boolean animatorPaused = false; - GLAnimatorControl animator = getAnimator(); - if(null!=animator) { - // can't remove us from animator for recreational addNotify() - animatorPaused = animator.pause(); + drawableSync.lock(); + try { + if(DEBUG) { + Exception ex1 = new Exception("Info: dispose("+regenerate+") - start, hasContext " + + (null!=context) + ", hasDrawable " + (null!=drawable)); + ex1.printStackTrace(); } - disposeRegenerate=regenerate; - - if (Threading.isSingleThreaded() && - !Threading.isOpenGLThread()) { - // Workaround for termination issues with applets -- - // sun.applet.AppletPanel should probably be performing the - // remove() call on the EDT rather than on its own thread - // Hint: User should run remove from EDT. - if (ThreadingImpl.isAWTMode() && - Thread.holdsLock(getTreeLock())) { - // The user really should not be invoking remove() from this - // thread -- but since he/she is, we can not go over to the - // EDT at this point. Try to destroy the context from here. - if(context.isCreated()) { - drawableHelper.invokeGL(drawable, context, disposeAction, null); + if(null!=context) { + boolean animatorPaused = false; + GLAnimatorControl animator = getAnimator(); + if(null!=animator) { + // can't remove us from animator for recreational addNotify() + animatorPaused = animator.pause(); + } + + disposeRegenerate=regenerate; + + if (Threading.isSingleThreaded() && + !Threading.isOpenGLThread()) { + // Workaround for termination issues with applets -- + // sun.applet.AppletPanel should probably be performing the + // remove() call on the EDT rather than on its own thread + // Hint: User should run remove from EDT. + if (ThreadingImpl.isAWTMode() && + Thread.holdsLock(getTreeLock())) { + // The user really should not be invoking remove() from this + // thread -- but since he/she is, we can not go over to the + // EDT at this point. Try to destroy the context from here. + if(context.isCreated()) { + drawableHelper.invokeGL(drawable, context, disposeAction, null); + } + } else if(context.isCreated()) { + Threading.invokeOnOpenGLThread(disposeOnEventDispatchThreadAction); + } + } else if(context.isCreated()) { + drawableHelper.invokeGL(drawable, context, disposeAction, null); } - } else if(context.isCreated()) { - Threading.invokeOnOpenGLThread(disposeOnEventDispatchThreadAction); - } - } else if(context.isCreated()) { - drawableHelper.invokeGL(drawable, context, disposeAction, null); - } - if(animatorPaused) { - animator.resume(); + if(animatorPaused) { + animator.resume(); + } + } + if(!regenerate) { + disposeAbstractGraphicsDevice(); } - } - if(!regenerate) { - disposeAbstractGraphicsDeviceAction.run(); - } - if(DEBUG) { - System.err.println("dispose("+regenerate+") - stop"); + if(DEBUG) { + System.err.println("dispose("+regenerate+") - stop"); + } + } finally { + drawableSync.unlock(); } } @@ -459,6 +485,8 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { } } + RecursiveLock drawableSync = new RecursiveLock(); + /** Overridden to track when this component is added to a container. Subclasses which override this method must call super.addNotify() in their addNotify() method in order to @@ -472,59 +500,71 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { ex1.printStackTrace(); } - /** - * 'super.addNotify()' determines the GraphicsConfiguration, - * while calling this class's overriden 'getGraphicsConfiguration()' method - * after which it creates the native peer. - * Hence we have to set the 'awtConfig' before since it's GraphicsConfiguration - * is being used in getGraphicsConfiguration(). - * This code order also allows recreation, ie re-adding the GLCanvas. - */ - awtConfig = chooseGraphicsConfiguration(capsReqUser, capsReqUser, chooser, device); - if(null==awtConfig) { - throw new GLException("Error: NULL AWTGraphicsConfiguration"); - } + drawableSync.lock(); + try { + /** + * 'super.addNotify()' determines the GraphicsConfiguration, + * while calling this class's overriden 'getGraphicsConfiguration()' method + * after which it creates the native peer. + * Hence we have to set the 'awtConfig' before since it's GraphicsConfiguration + * is being used in getGraphicsConfiguration(). + * This code order also allows recreation, ie re-adding the GLCanvas. + */ + awtConfig = chooseGraphicsConfiguration(capsReqUser, capsReqUser, chooser, device); + if(null==awtConfig) { + throw new GLException("Error: NULL AWTGraphicsConfiguration"); + } - if (!Beans.isDesignTime()) { - // no lock required, since this resource ain't available yet - drawable = GLDrawableFactory.getFactory(capsReqUser.getGLProfile()) - .createGLDrawable(NativeWindowFactory.getNativeWindow(this, awtConfig)); - context = (GLContextImpl) drawable.createContext(shareWith); - context.setSynchronized(true); - } + if (!Beans.isDesignTime()) { + // no lock required, since this resource ain't available yet + drawable = GLDrawableFactory.getFactory(capsReqUser.getGLProfile()) + .createGLDrawable(NativeWindowFactory.getNativeWindow(this, awtConfig)); + context = (GLContextImpl) drawable.createContext(shareWith); + context.setSynchronized(true); + } - // before native peer is valid: X11 - disableBackgroundErase(); + // before native peer is valid: X11 + disableBackgroundErase(); - // issues getGraphicsConfiguration() and creates the native peer - super.addNotify(); + // issues getGraphicsConfiguration() and creates the native peer + super.addNotify(); - // after native peer is valid: Windows - disableBackgroundErase(); + // after native peer is valid: Windows + disableBackgroundErase(); - validateGLDrawable(); + // init drawable by paint/display makes the init sequence more equal + // for all launch flavors (applet/javaws/..) + // validateGLDrawable(); - if(DEBUG) { - System.err.println(Thread.currentThread().getName()+" - Info: addNotify - end"); + if(DEBUG) { + System.err.println(Thread.currentThread().getName()+" - Info: addNotify - end: peer: "+getPeer()); + } + } finally { + drawableSync.unlock(); } } private boolean validateGLDrawable() { boolean realized = false; if (!Beans.isDesignTime()) { - if ( null != drawable ) { - realized = drawable.isRealized(); - if ( !realized && 0 < drawable.getWidth() * drawable.getHeight() ) { - drawable.setRealized(true); - realized = true; - sendReshape=true; // ensure a reshape is being send .. - if(DEBUG) { - String msg = Thread.currentThread().getName()+" - Realized Drawable: "+drawable.toString(); - // System.err.println(msg); - Throwable t = new Throwable(msg); - t.printStackTrace(); + drawableSync.lock(); + try { + if ( null != drawable ) { + realized = drawable.isRealized(); + if ( !realized && 0 < drawable.getWidth() * drawable.getHeight() ) { + drawable.setRealized(true); + realized = true; + sendReshape=true; // ensure a reshape is being send .. + if(DEBUG) { + String msg = Thread.currentThread().getName()+" - Realized Drawable: "+drawable.toString(); + // System.err.println(msg); + Throwable t = new Throwable(msg); + t.printStackTrace(); + } } } + } finally { + drawableSync.unlock(); } } return realized; @@ -544,18 +584,24 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { ex1.printStackTrace(); } + awtWindowClosingProtocol.removeClosingListener(); + if (Beans.isDesignTime()) { super.removeNotify(); } else { + drawableSync.lock(); try { dispose(false); } finally { + context=null; drawable=null; + awtConfig=null; super.removeNotify(); + drawableSync.unlock(); } } if(DEBUG) { - System.err.println(Thread.currentThread().getName()+" - Info: removeNotify - end"); + System.err.println(Thread.currentThread().getName()+" - Info: removeNotify - end, peer: "+getPeer()); } } @@ -662,15 +708,30 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { } public NativeSurface getNativeSurface() { - return drawable.getNativeSurface(); + drawableSync.lock(); + try { + return (null != drawable) ? drawable.getNativeSurface() : null; + } finally { + drawableSync.unlock(); + } } public long getHandle() { - return drawable.getHandle(); + drawableSync.lock(); + try { + return (null != drawable) ? drawable.getHandle() : 0; + } finally { + drawableSync.unlock(); + } } public GLDrawableFactory getFactory() { - return drawable.getFactory(); + drawableSync.lock(); + try { + return (null != drawable) ? drawable.getFactory() : null; + } finally { + drawableSync.unlock(); + } } public String toString() { @@ -703,6 +764,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { if(null!=drawable) { drawable.setRealized(false); + drawable=null; } if(disposeRegenerate) { @@ -743,13 +805,34 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { } boolean closed = adevice.close(); if(DEBUG) { - System.err.println("GLCanvas.dispose(false): closed GraphicsDevice: "+adeviceMsg+", result: "+closed); + System.err.println(Thread.currentThread().getName() + " - GLCanvas.dispose(false): closed GraphicsDevice: "+adeviceMsg+", result: "+closed); } } + awtConfig=null; } } private DisposeAbstractGraphicsDeviceAction disposeAbstractGraphicsDeviceAction = new DisposeAbstractGraphicsDeviceAction(); + /** + * Disposes the AbstractGraphicsDevice within EDT, + * since resources created (X11: Display), must be destroyed in the same thread, where they have been created. + * + * @see #chooseGraphicsConfiguration(javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, java.awt.GraphicsDevice) + */ + void disposeAbstractGraphicsDevice() { + if( EventQueue.isDispatchThread() || Thread.holdsLock(getTreeLock()) ) { + disposeAbstractGraphicsDeviceAction.run(); + } else { + try { + EventQueue.invokeAndWait(disposeAbstractGraphicsDeviceAction); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (InterruptedException e) { + throw new GLException(e); + } + } + } + class InitAction implements Runnable { public void run() { drawableHelper.init(GLCanvas.this); @@ -851,20 +934,55 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { } } - private static AWTGraphicsConfiguration chooseGraphicsConfiguration(GLCapabilitiesImmutable capsChosen, - GLCapabilitiesImmutable capsRequested, - GLCapabilitiesChooser chooser, - GraphicsDevice device) { + /** + * Issues the GraphicsConfigurationFactory's choosing facility within EDT, + * since resources created (X11: Display), must be destroyed in the same thread, where they have been created. + * + * @param capsChosen + * @param capsRequested + * @param chooser + * @param device + * @return the chosen AWTGraphicsConfiguration + * + * @see #disposeAbstractGraphicsDevice() + */ + private AWTGraphicsConfiguration chooseGraphicsConfiguration(final GLCapabilitiesImmutable capsChosen, + final GLCapabilitiesImmutable capsRequested, + final GLCapabilitiesChooser chooser, + final GraphicsDevice device) { // Make GLCanvas behave better in NetBeans GUI builder if (Beans.isDesignTime()) { return null; } - AbstractGraphicsScreen aScreen = AWTGraphicsScreen.createScreenDevice(device, AbstractGraphicsDevice.DEFAULT_UNIT); - AWTGraphicsConfiguration config = (AWTGraphicsConfiguration) - GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class).chooseGraphicsConfiguration(capsChosen, - capsRequested, - chooser, aScreen); + final AbstractGraphicsScreen aScreen = AWTGraphicsScreen.createScreenDevice(device, AbstractGraphicsDevice.DEFAULT_UNIT); + AWTGraphicsConfiguration config = null; + + if( EventQueue.isDispatchThread() || Thread.holdsLock(getTreeLock()) ) { + config = (AWTGraphicsConfiguration) + GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class).chooseGraphicsConfiguration(capsChosen, + capsRequested, + chooser, aScreen); + } else { + try { + final ArrayList bucket = new ArrayList(1); + EventQueue.invokeAndWait(new Runnable() { + public void run() { + AWTGraphicsConfiguration c = (AWTGraphicsConfiguration) + GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class).chooseGraphicsConfiguration(capsChosen, + capsRequested, + chooser, aScreen); + bucket.add(c); + } + }); + config = ( bucket.size() > 0 ) ? (AWTGraphicsConfiguration)bucket.get(0) : null ; + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (InterruptedException e) { + throw new GLException(e); + } + } + if (config == null) { throw new GLException("Error: Couldn't fetch AWTGraphicsConfiguration"); } @@ -881,6 +999,12 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { System.err.println(NativeWindowVersion.getInstance()); System.err.println(JoglVersion.getInstance()); + GLDrawableFactory factory = GLDrawableFactory.getDesktopFactory(); + List/*<GLCapabilitiesImmutable>*/ availCaps = factory.getAvailableCapabilities(null); + for(int i=0; i<availCaps.size(); i++) { + System.err.println(availCaps.get(i)); + } + GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault(GLProfile.getDefaultDesktopDevice()) ); Frame frame = new Frame("JOGL AWT Test"); diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index c8bfe94d8..46c799d71 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -40,19 +40,57 @@ package javax.media.opengl.awt; -import javax.media.opengl.*; -import javax.media.nativewindow.*; - -import java.awt.*; -import java.awt.geom.*; -import java.awt.image.*; -import java.beans.*; -import java.nio.*; -import java.security.*; +import java.nio.ByteBuffer; +import java.nio.IntBuffer; +import java.beans.Beans; +import java.security.AccessControlContext; +import java.security.AccessController; + +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsEnvironment; +import java.awt.Rectangle; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferInt; import javax.swing.JPanel; + +import javax.media.nativewindow.WindowClosingProtocol; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.awt.AWTWindowClosingProtocol; + +import javax.media.opengl.DefaultGLCapabilitiesChooser; +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.GL2GL3; +import javax.media.opengl.GLAnimatorControl; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesChooser; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLException; +import javax.media.opengl.GLPbuffer; +import javax.media.opengl.GLProfile; +import javax.media.opengl.GLRunnable; +import javax.media.opengl.Threading; import com.jogamp.opengl.util.FBObject; -import com.jogamp.opengl.impl.*; -import com.jogamp.opengl.impl.awt.*; +import com.jogamp.opengl.impl.Debug; +import com.jogamp.opengl.impl.GLContextImpl; +import com.jogamp.opengl.impl.GLDrawableFactoryImpl; +import com.jogamp.opengl.impl.GLDrawableHelper; +import com.jogamp.opengl.impl.GLDrawableImpl; +import com.jogamp.opengl.impl.ThreadingImpl; +import com.jogamp.opengl.impl.awt.Java2D; +import com.jogamp.opengl.impl.awt.Java2DGLContext; // FIXME: Subclasses need to call resetGLFunctionAvailability() on their // context whenever the displayChanged() function is called on their @@ -85,7 +123,7 @@ import com.jogamp.opengl.impl.awt.*; * </P> */ -public class GLJPanel extends JPanel implements AWTGLAutoDrawable { +public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosingProtocol { private static final boolean DEBUG = Debug.debug("GLJPanel"); private static final boolean VERBOSE = Debug.verbose(); @@ -129,8 +167,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable { !Debug.isPropertyDefined("jogl.gljpanel.noogl", true, localACC); // For handling reshape events lazily - private int reshapeX; - private int reshapeY; + // private int reshapeX; + // private int reshapeY; private int reshapeWidth; private int reshapeHeight; @@ -139,6 +177,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable { private int viewportX; private int viewportY; + private AWTWindowClosingProtocol awtWindowClosingProtocol = + new AWTWindowClosingProtocol(this, new Runnable() { + public void run() { + GLJPanel.this.destroy(); + } + }); + static { // Force eager initialization of part of the Java2D class since // otherwise it's likely it will try to be initialized while on @@ -255,6 +300,19 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable { drawableHelper.invokeGL(disposeDrawable, disposeContext, disposeAction, null); } + if(!regenerate) { + AbstractGraphicsDevice adevice = disposeDrawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice(); + String adeviceMsg=null; + if(DEBUG) { + adeviceMsg = adevice.toString(); + } + // boolean closed = adevice.close(); + boolean closed = false; + if (DEBUG) { + System.err.println("GLJPanel.dispose(false): closed GraphicsDevice: " + adeviceMsg + ", result: " + closed); + } + } + backend.setContext(disposeContext); if(null==disposeContext) { isInitialized = false; @@ -352,6 +410,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable { Exception ex1 = new Exception("Info: removeNotify - start"); ex1.printStackTrace(); } + + awtWindowClosingProtocol.removeClosingListener(); + dispose(false); if (backend != null) { backend.destroy(); @@ -374,8 +435,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable { public void reshape(int x, int y, int width, int height) { super.reshape(x, y, width, height); - reshapeX = x; - reshapeY = y; + // reshapeX = x; + // reshapeY = y; reshapeWidth = width; reshapeHeight = height; handleReshape = true; @@ -560,17 +621,16 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable { // a different implementation -- try again } while (backend == null); - if(null==closingListener) { - synchronized(closingListenerLock) { - if(null==closingListener) { - closingListener=GLCanvas.addClosingListener(this, new GLCanvas.DestroyMethod() { - public void destroyMethod() { destroy(); } }); - } - } - } + awtWindowClosingProtocol.addClosingListenerOneShot(); + } + + public int getDefaultCloseOperation() { + return awtWindowClosingProtocol.getDefaultCloseOperation(); + } + + public int setDefaultCloseOperation(int op) { + return awtWindowClosingProtocol.setDefaultCloseOperation(op); } - private Object closingListener = null; - private Object closingListenerLock = new Object(); private void handleReshape() { panelWidth = reshapeWidth; @@ -656,16 +716,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable { disposeDrawable.setRealized(true); disposeContext = (GLContextImpl) disposeDrawable.createContext(shareWith); disposeContext.setSynchronized(true); - } else { - AbstractGraphicsDevice adevice = disposeDrawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice(); - String adeviceMsg=null; - if(DEBUG) { - adeviceMsg = adevice.toString(); - } - boolean closed = adevice.close(); - if (DEBUG) { - System.err.println("GLJPanel.dispose(false): closed GraphicsDevice: " + adeviceMsg + ", result: " + closed); - } } } } |