diff options
Diffstat (limited to 'src')
22 files changed, 1340 insertions, 262 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java index 35810678c..616640bad 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java @@ -54,13 +54,24 @@ import java.lang.reflect.*; public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { protected static final boolean DEBUG = Debug.debug("GLDrawableFactory"); + private boolean isValid = false; + public void shutdown() { + validate(); + isValid = false; + } + + protected final void validate() { + if(!isValid) { + throw new GLException("GLDrawableFactory is already shutdown!"); + } } //--------------------------------------------------------------------------- // Dispatching GLDrawable construction in respect to the NativeWindow Capabilities // public GLDrawable createGLDrawable(NativeWindow target) { + validate(); if (target == null) { throw new IllegalArgumentException("Null target"); } @@ -124,6 +135,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { GLCapabilitiesChooser chooser, int width, int height) { + validate(); if(height<=0 || height<=0) { throw new GLException("Width and height of pbuffer must be positive (were (" + width + ", " + height + "))"); @@ -139,6 +151,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { int width, int height, GLContext shareWith) { + validate(); return new GLPbufferImpl( (GLDrawableImpl) createGLPbufferDrawable(capabilities, chooser, height, height), shareWith); } @@ -155,6 +168,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { GLCapabilitiesChooser chooser, int width, int height) { + validate(); if(width<=0 || height<=0) { throw new GLException("Width and height of pbuffer must be positive (were (" + width + ", " + height + "))"); @@ -174,6 +188,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { protected GLDrawableFactoryImpl() { super(); + isValid = true; } protected void maybeDoSingleThreadedWorkaround(Runnable action) { @@ -279,6 +294,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { * out-of-bounds */ public boolean setDisplayGamma(float gamma, float brightness, float contrast) throws IllegalArgumentException { + validate(); if ((brightness < -1.0f) || (brightness > 1.0f)) { throw new IllegalArgumentException("Brightness must be between -1.0 and 1.0"); } @@ -311,6 +327,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { } public synchronized void resetDisplayGamma() { + validate(); if (gammaShutdownHook == null) { throw new IllegalArgumentException("Should not call this unless setDisplayGamma called first"); } 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 c8bc4fe0d..2d5154442 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfiguration.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfiguration.java @@ -122,10 +122,11 @@ public class EGLGraphicsConfiguration extends DefaultGraphicsConfiguration imple if ( onscreen ) { res = ( 0 != (val & EGL.EGL_WINDOW_BIT) ) ; } else { - res = ( 0 != (val & EGL.EGL_PIXMAP_BIT) ) || usePBuffer ; - } - if ( usePBuffer ) { - res = res && ( 0 != (val & EGL.EGL_PBUFFER_BIT) ) ; + if ( usePBuffer ) { + res = ( 0 != (val & EGL.EGL_PBUFFER_BIT) ) ; + } else { + res = ( 0 != (val & EGL.EGL_PIXMAP_BIT) ) ; + } } return res; @@ -187,17 +188,13 @@ public class EGLGraphicsConfiguration extends DefaultGraphicsConfiguration imple caps.setOnscreen( 0 != (val[0] & EGL.EGL_WINDOW_BIT) ); caps.setPBuffer ( 0 != (val[0] & EGL.EGL_PBUFFER_BIT) ); } else { - throw new GLException("EGL_SURFACE_TYPE does not match !!!"); - } - } else { - if(relaxed) { if(DEBUG) { - System.err.println("Could not determine EGL_SURFACE_TYPE !!!"); + 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 !!!"); } + } else { + throw new GLException("Could not determine EGL_SURFACE_TYPE !!!"); } return caps; 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 5b34e40e1..aed4012a4 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 @@ -412,14 +412,16 @@ public class WindowsWGLGraphicsConfiguration extends DefaultGraphicsConfiguratio if ( onscreen ) { res = ( 0 != (val & WINDOW_BIT) ) ; } else { - res = ( 0 != (val & BITMAP_BIT) ) || usePBuffer ; - } - if ( usePBuffer ) { - res = res && ( 0 != (val & PBUFFER_BIT) ) ; + if ( usePBuffer ) { + res = ( 0 != (val & PBUFFER_BIT) ) ; + } else { + res = ( 0 != (val & BITMAP_BIT) ) ; + } } return res; } + public static GLCapabilities AttribList2GLCapabilities(GLProfile glp, int[] iattribs, int niattribs, int[] iresults, @@ -433,7 +435,10 @@ public class WindowsWGLGraphicsConfiguration extends DefaultGraphicsConfiguratio res.setOnscreen( 0 != (drawableTypeBits & WINDOW_BIT) ); res.setPBuffer ( 0 != (drawableTypeBits & PBUFFER_BIT) ); } else { - throw new GLException("WGL DrawableType does not match !!!"); + 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))+")"); + } + return null; } for (int i = 0; i < niattribs; i++) { 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 55b30ef3a..1a375699c 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 @@ -260,9 +260,11 @@ public class WindowsWGLGraphicsConfigurationFactory extends GraphicsConfiguratio } pixelFormat = 1; // default .. } else if ( pixelFormat > numFormats ) { - throw new GLException("Invalid result " + pixelFormat + - " from GLCapabilitiesChooser (should be between 1 and " + - numFormats + ")"); + // keep on going .. + if(DEBUG) { + System.err.println("GLCapabilitiesChooser specified invalid index (expected 1.." + numFormats + ", got "+pixelFormat+")"); + } + pixelFormat = 1; // default .. } } chosenCaps = availableCaps[pixelFormat-1]; diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/GLXUtil.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/GLXUtil.java index 99c54332f..e3c1381f8 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/GLXUtil.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/GLXUtil.java @@ -54,13 +54,55 @@ public class GLXUtil { /** Workaround for apparent issue with ATI's proprietary drivers where direct contexts still send GLX tokens for GL calls */ - public static boolean isVendorATI(long display) { + public static String getVendorName(long display) { try { X11Lib.XLockDisplay(display); - String vendor = GLX.glXGetClientString(display, GLX.GLX_VENDOR); - return vendor != null && vendor.startsWith("ATI") ; + return GLX.glXGetClientString(display, GLX.GLX_VENDOR); } finally { X11Lib.XUnlockDisplay(display); } } + + public static boolean isVendorNVIDIA(String vendor) { + return vendor != null && vendor.startsWith("NVIDIA") ; + } + + public static boolean isVendorATI(String vendor) { + return vendor != null && vendor.startsWith("ATI") ; + } + + public static boolean isVendorATI(long display) { + return isVendorATI(getVendorName(display)); + } + + public static boolean isVendorNVIDIA(long display) { + return isVendorNVIDIA(getVendorName(display)); + } + + public static void getGLXVersion(long display, int major[], int minor[]) { + if(0 == display) { + throw new GLException("null display handle"); + } + if(major.length<1||minor.length<1) { + throw new GLException("passed int arrays size is not >= 1"); + } + + if (!GLX.glXQueryVersion(display, major, 0, minor, 0)) { + throw new GLException("glXQueryVersion failed"); + } + + // Work around bugs in ATI's Linux drivers where they report they + // only implement GLX version 1.2 on the server side + if (major[0] == 1 && minor[0] == 2) { + String str = GLX.glXGetClientString(display, GLX.GLX_VERSION); + try { + // e.g. "1.3" + major[0] = Integer.valueOf(str.substring(0, 1)).intValue(); + minor[0] = Integer.valueOf(str.substring(2, 3)).intValue(); + } catch (Exception e) { + major[0] = 1; + minor[0] = 2; + } + } + } } 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 097689967..a865e91e8 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 @@ -42,6 +42,8 @@ import com.jogamp.nativewindow.impl.x11.*; public class X11DummyGLXDrawable extends X11OnscreenGLXDrawable { + // private long dummyWindow = 0; + /** * Due to the ATI Bug https://bugzilla.mozilla.org/show_bug.cgi?id=486277, * we cannot switch the Display as we please, @@ -57,12 +59,17 @@ public class X11DummyGLXDrawable extends X11OnscreenGLXDrawable { X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)nw.getGraphicsConfiguration().getNativeGraphicsConfiguration(); GLCapabilities caps = (GLCapabilities) config.getChosenCapabilities(); - long dpy = config.getScreen().getDevice().getHandle(); - int scrn = config.getScreen().getIndex(); - // System.out.println("X11DummyGLXDrawable: dpy "+toHexString(dpy)+", scrn "+scrn); + X11GraphicsDevice device = (X11GraphicsDevice) screen.getDevice(); + long dpy = device.getHandle(); + int scrn = screen.getIndex(); + // long visualID = config.getVisualID(); + // System.out.println("X11DummyGLXDrawable: dpy "+toHexString(dpy)+", scrn "+scrn+", visualID "+toHexString(visualID)); + X11Lib.XLockDisplay(dpy); try{ nw.setSurfaceHandle( X11Lib.RootWindow(dpy, scrn) ); + // dummyWindow = X11Lib.CreateDummyWindow(dpy, scrn, visualID); + // nw.setSurfaceHandle( dummyWindow ); } finally { X11Lib.XUnlockDisplay(dpy); } @@ -80,6 +87,11 @@ public class X11DummyGLXDrawable extends X11OnscreenGLXDrawable { } public void destroy() { - // nothing to do, but allowed + /** + if(0!=dummyWindow) { + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + long dpy = config.getScreen().getDevice().getHandle(); + X11Lib.DestroyDummyWindow(dpy, dummyWindow); + } */ } } 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 055e7236c..142da672a 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 @@ -133,7 +133,7 @@ public abstract class X11GLXContext extends GLContextImpl { } GLCapabilities glCaps = (GLCapabilities) config.getChosenCapabilities(); - isVendorATI = GLXUtil.isVendorATI(display); + isVendorATI = ((X11GLXDrawableFactory)(drawable.getFactoryImpl())).isVendorATI(); if(config.getFBConfigID()<0) { // not able to use FBConfig @@ -148,11 +148,11 @@ public abstract class X11GLXContext extends GLContextImpl { drawable.getNativeWindow().getSurfaceHandle(), drawableRead.getNativeWindow().getSurfaceHandle(), context)) { - throw new GLException("Error making temp context (old2) current: display 0x"+Long.toHexString(display)+", context 0x"+Long.toHexString(context)+", drawable "+drawable); + throw new GLException("Error making temp context (old2) current: display "+toHexString(display)+", context "+toHexString(context)+", drawable "+drawable); } setGLFunctionAvailability(true); if(DEBUG) { - System.err.println("X11GLXContext.createContext done (old2 ctx) 0x"+Long.toHexString(context)); + System.err.println("X11GLXContext.createContext done (old2 ctx) "+toHexString(context)); } } else { @@ -167,7 +167,7 @@ public abstract class X11GLXContext extends GLContextImpl { drawable.getNativeWindow().getSurfaceHandle(), drawableRead.getNativeWindow().getSurfaceHandle(), temp_context)) { - throw new GLException("Error making temp context (old) current: display 0x"+Long.toHexString(display)+", context 0x"+Long.toHexString(context)+", drawable "+drawable); + throw new GLException("Error making temp context (old) current: display "+toHexString(display)+", context "+toHexString(context)+", drawable "+drawable); } setGLFunctionAvailability(true); @@ -182,7 +182,7 @@ public abstract class X11GLXContext extends GLContextImpl { // continue with temp context for GL < 3.0 context = temp_context; if(DEBUG) { - System.err.println("X11GLXContext.createContext done (old ctx < 3.0 - no GLX_ARB_create_context) 0x"+Long.toHexString(context)); + System.err.println("X11GLXContext.createContext done (old ctx < 3.0 - no GLX_ARB_create_context) "+toHexString(context)); } } else { GLXExt glXExt = getGLXExt(); @@ -209,7 +209,7 @@ public abstract class X11GLXContext extends GLContextImpl { /** * don't stricten requirements any further, even compatible would be fine * - } else { + else { attribs[8+0] = GLX.GLX_CONTEXT_PROFILE_MASK_ARB; attribs[8+1] = GLX.GLX_CONTEXT_CORE_PROFILE_BIT_ARB; } @@ -228,7 +228,7 @@ public abstract class X11GLXContext extends GLContextImpl { GLX.glXDestroyContext(display, context); context = 0; } else if(DEBUG) { - System.err.println("X11GLXContext.createContext >= 3.2 available 0x"+Long.toHexString(context)); + System.err.println("X11GLXContext.createContext >= 3.2 available "+toHexString(context)); } } else { if(DEBUG) { @@ -261,7 +261,7 @@ public abstract class X11GLXContext extends GLContextImpl { GLX.glXDestroyContext(display, context); context = 0; } else if(DEBUG) { - System.err.println("X11GLXContext.createContext >= 3.0 available 0x"+Long.toHexString(context)); + System.err.println("X11GLXContext.createContext >= 3.0 available "+toHexString(context)); } } else { if(DEBUG) { @@ -285,10 +285,10 @@ public abstract class X11GLXContext extends GLContextImpl { context)) { GLX.glXMakeContextCurrent(display, 0, 0, 0); GLX.glXDestroyContext(display, temp_context); - throw new GLException("Error making context (old) current: display 0x"+Long.toHexString(display)+", context 0x"+Long.toHexString(context)+", drawable "+drawable); + throw new GLException("Error making context (old) current: display "+toHexString(display)+", context "+toHexString(context)+", drawable "+drawable); } if(DEBUG) { - System.err.println("X11GLXContext.createContext done (old ctx < 3.0 - no 3.0) 0x"+Long.toHexString(context)); + System.err.println("X11GLXContext.createContext done (old ctx < 3.0 - no 3.0) "+toHexString(context)); } } else { GLX.glXDestroyContext(display, temp_context); @@ -296,7 +296,7 @@ public abstract class X11GLXContext extends GLContextImpl { // need to update the GL func table .. updateGLProcAddressTable(); if(DEBUG) { - System.err.println("X11GLXContext.createContext done (new ctx >= 3.0) 0x"+Long.toHexString(context)); + System.err.println("X11GLXContext.createContext done (new ctx >= 3.0) "+toHexString(context)); } } } @@ -337,6 +337,8 @@ public abstract class X11GLXContext extends GLContextImpl { } protected int makeCurrentImplAfterLock() throws GLException { + long dpy = drawable.getNativeWindow().getDisplayHandle(); + getDrawableImpl().getFactoryImpl().lockToolkit(); try { if (drawable.getNativeWindow().getSurfaceHandle() == 0) { @@ -356,7 +358,7 @@ public abstract class X11GLXContext extends GLContextImpl { if (GLX.glXGetCurrentContext() != context) { - if (!GLX.glXMakeContextCurrent(drawable.getNativeWindow().getDisplayHandle(), + if (!GLX.glXMakeContextCurrent(dpy, drawable.getNativeWindow().getSurfaceHandle(), drawableRead.getNativeWindow().getSurfaceHandle(), context)) { @@ -364,7 +366,7 @@ public abstract class X11GLXContext extends GLContextImpl { } if (DEBUG && (VERBOSE || created)) { System.err.println(getThreadName() + ": glXMakeCurrent(display " + - toHexString(drawable.getNativeWindow().getDisplayHandle()) + + toHexString(dpy)+ ", drawable " + toHexString(drawable.getNativeWindow().getSurfaceHandle()) + ", drawableRead " + toHexString(drawableRead.getNativeWindow().getSurfaceHandle()) + ", context " + toHexString(context) + ") succeeded"); @@ -397,10 +399,10 @@ public abstract class X11GLXContext extends GLContextImpl { try { if (context != 0) { if (DEBUG) { - System.err.println("glXDestroyContext(0x" + - Long.toHexString(drawable.getNativeWindow().getDisplayHandle()) + - ", 0x" + - Long.toHexString(context) + ")"); + System.err.println("glXDestroyContext(" + + toHexString(drawable.getNativeWindow().getDisplayHandle()) + + ", " + + toHexString(context) + ")"); } GLX.glXDestroyContext(drawable.getNativeWindow().getDisplayHandle(), context); if (DEBUG) { 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 60ee431dc..eda480d5f 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 @@ -48,6 +48,7 @@ import com.jogamp.nativewindow.impl.NWReflection; import com.jogamp.nativewindow.impl.x11.*; public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements DynamicLookupHelper { + public X11GLXDrawableFactory() { super(); // Must initialize GLX support eagerly in case a pbuffer is the @@ -60,64 +61,121 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna NWReflection.createInstance("com.jogamp.opengl.impl.x11.glx.awt.X11AWTGLXGraphicsConfigurationFactory", new Object[] {}); } catch (Throwable t) { } + + X11GraphicsDevice sharedDevice = new X11GraphicsDevice(X11Util.createThreadLocalDisplay(null)); + vendorName = GLXUtil.getVendorName(sharedDevice.getHandle()); + isVendorATI = GLXUtil.isVendorATI(vendorName); + isVendorNVIDIA = GLXUtil.isVendorNVIDIA(vendorName); + if( isVendorATI() ) { + X11Util.markGlobalDisplayUndeletable(sharedDevice.getHandle()); // ATI hack .. + } + sharedScreen = new X11GraphicsScreen(sharedDevice, 0); + if (DEBUG) { + System.err.println("!!! Vendor: "+vendorName+", ATI: "+isVendorATI+", NV: "+isVendorNVIDIA); + System.err.println("!!! SharedScreen: "+sharedScreen); + } + } + + private X11GraphicsScreen sharedScreen; + private String vendorName; + private boolean isVendorATI; + private boolean isVendorNVIDIA; + + public String getVendorName() { return vendorName; } + public boolean isVendorATI() { return isVendorATI; } + public boolean isVendorNVIDIA() { return isVendorNVIDIA; } + + private X11DummyGLXDrawable sharedDrawable=null; + private GLContext sharedContext=null; + + private void initShared() { + if(null==sharedDrawable) { + X11Lib.XLockDisplay(sharedScreen.getDevice().getHandle()); + sharedDrawable = new X11DummyGLXDrawable(sharedScreen, this, null); + sharedContext = sharedDrawable.createContext(null); + sharedContext.makeCurrent(); + sharedContext.release(); + X11Lib.XUnlockDisplay(sharedScreen.getDevice().getHandle()); + if (DEBUG) { + System.err.println("!!! SharedContext: "+sharedContext); + } + } + } + + public void shutdown() { + super.shutdown(); + if (DEBUG) { + System.err.println("!!! Shutdown Shared:"); + System.err.println("!!! CTX : "+sharedContext); + System.err.println("!!! Drawable: "+sharedDrawable); + System.err.println("!!! Screen : "+sharedScreen); + Exception e = new Exception("Debug"); + e.printStackTrace(); + } + if(null!=sharedContext) { + sharedContext.destroy(); // implies release, if current + } + if(null!=sharedDrawable) { + sharedDrawable.destroy(); + } + if(null!=sharedScreen) { + X11GraphicsDevice sharedDevice = (X11GraphicsDevice) sharedScreen.getDevice(); + if(null!=sharedDevice) { + X11Util.closeThreadLocalDisplay(null); + } + sharedScreen = null; + } + X11Util.shutdown( !isVendorATI(), DEBUG ); } public GLDrawableImpl createOnscreenDrawable(NativeWindow target) { + validate(); if (target == null) { throw new IllegalArgumentException("Null target"); } + if( isVendorATI() ) { + X11Util.markGlobalDisplayUndeletable(target.getDisplayHandle()); // ATI hack .. + } return new X11OnscreenGLXDrawable(this, target); } protected GLDrawableImpl createOffscreenDrawable(NativeWindow target) { + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + if( isVendorATI() ) { + X11Util.markGlobalDisplayUndeletable(target.getDisplayHandle()); // ATI hack .. + } + initShared(); return new X11OffscreenGLXDrawable(this, target); } public boolean canCreateGLPbuffer(AbstractGraphicsDevice device) { + validate(); return glxVersionGreaterEqualThan(device, 1, 3); } private boolean glxVersionsQueried = false; private int glxVersionMajor=0, glxVersionMinor=0; public boolean glxVersionGreaterEqualThan(AbstractGraphicsDevice device, int majorReq, int minorReq) { + validate(); if (!glxVersionsQueried) { if(null == device) { - GLContext ctx = GLContext.getCurrent(); - if( null != ctx) { - device = ctx.getGLDrawable().getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice(); - } + device = (X11GraphicsDevice) sharedScreen.getDevice(); } if(null == device) { - GLException gle = new GLException("FIXME: No AbstractGraphicsDevice (passed or queried via current context - Fallback to ThreadLocal Display .."); - gle.printStackTrace(); - - device = new X11GraphicsDevice(X11Util.getThreadLocalDisplay(null)); + throw new GLException("FIXME: No AbstractGraphicsDevice (passed or shared-device"); } long display = device.getHandle(); int[] major = new int[1]; int[] minor = new int[1]; - if (!GLX.glXQueryVersion(display, major, 0, minor, 0)) { - throw new GLException("glXQueryVersion failed"); - } + GLXUtil.getGLXVersion(display, major, minor); if (DEBUG) { System.err.println("!!! GLX version: major " + major[0] + ", minor " + minor[0]); } - // Work around bugs in ATI's Linux drivers where they report they - // only implement GLX version 1.2 on the server side - if (major[0] == 1 && minor[0] == 2) { - String str = GLX.glXGetClientString(display, GLX.GLX_VERSION); - try { - major[0] = Integer.valueOf(str.substring(0, 1)).intValue(); - minor[0] = Integer.valueOf(str.substring(2, 3)).intValue(); - } catch (NumberFormatException nfe) { - major[0] = 1; - minor[0] = 2; - } - } - glxVersionMajor = major[0]; glxVersionMinor = minor[0]; glxVersionsQueried = true; @@ -127,8 +185,6 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna protected GLDrawableImpl createGLPbufferDrawableImpl(final NativeWindow target) { GLDrawableImpl pbufferDrawable; - X11DummyGLXDrawable dummyDrawable=null; - GLContext dummyContext=null; /** * Due to the ATI Bug https://bugzilla.mozilla.org/show_bug.cgi?id=486277, @@ -136,21 +192,20 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna * The dummy context shall also use the same Display, * since switching Display in this regard is another ATI bug. */ - if( null == GLContext.getCurrent() ) { - X11GraphicsScreen screen = (X11GraphicsScreen) target.getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen(); - dummyDrawable = new X11DummyGLXDrawable(screen, this, null); - dummyContext = dummyDrawable.createContext(null); - dummyContext.makeCurrent(); + boolean usedSharedContext=false; + if( isVendorATI() && null == GLContext.getCurrent() ) { + initShared(); + sharedContext.makeCurrent(); + usedSharedContext=true; + } + if( isVendorATI() ) { + X11Util.markGlobalDisplayUndeletable(target.getDisplayHandle()); // ATI hack .. } try { pbufferDrawable = new X11PbufferGLXDrawable(this, target); } finally { - if(null!=dummyContext) { - dummyContext.release(); - dummyContext.destroy(); - } - if(null!=dummyDrawable) { - dummyDrawable.destroy(); + if(usedSharedContext) { + sharedContext.release(); } } return pbufferDrawable; @@ -158,25 +213,30 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna protected NativeWindow createOffscreenWindow(GLCapabilities capabilities, GLCapabilitiesChooser chooser, int width, int height) { - AbstractGraphicsScreen screen = X11GraphicsScreen.createDefault(); - NullWindow nw = new NullWindow(X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capabilities, chooser, screen)); + X11Lib.XLockDisplay(sharedScreen.getDevice().getHandle()); + NullWindow nw = new NullWindow(X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capabilities, chooser, sharedScreen)); + X11Lib.XUnlockDisplay(sharedScreen.getDevice().getHandle()); nw.setSize(width, height); return nw; } public GLContext createExternalGLContext() { + validate(); return X11ExternalGLXContext.create(this, null); } public boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device) { + validate(); return canCreateGLPbuffer(device); } public GLDrawable createExternalGLDrawable() { + validate(); return X11ExternalGLXDrawable.create(this, null); } public void loadGLULibrary() { + validate(); X11Lib.dlopen("/usr/lib/libGLU.so"); } @@ -191,6 +251,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna } public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) { + validate(); return false; } @@ -210,9 +271,10 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna return gammaRampLength; } - long display = X11Util.getThreadLocalDefaultDisplay(); + long display = sharedScreen.getDevice().getHandle(); + + X11Lib.XLockDisplay(display); try { - X11Lib.XLockDisplay(display); int[] size = new int[1]; boolean res = X11Lib.XF86VidModeGetGammaRampSize(display, X11Lib.DefaultScreen(display), @@ -235,9 +297,9 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna rampData[i] = (short) (ramp[i] * 65535); } - long display = X11Util.getThreadLocalDefaultDisplay(); + long display = sharedScreen.getDevice().getHandle(); + X11Lib.XLockDisplay(display); try { - X11Lib.XLockDisplay(display); boolean res = X11Lib.XF86VidModeSetGammaRamp(display, X11Lib.DefaultScreen(display), rampData.length, @@ -262,9 +324,9 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna rampData.position(2 * size); rampData.limit(3 * size); ShortBuffer blueRampData = rampData.slice(); - long display = X11Util.getThreadLocalDefaultDisplay(); + long display = sharedScreen.getDevice().getHandle(); + X11Lib.XLockDisplay(display); try { - X11Lib.XLockDisplay(display); boolean res = X11Lib.XF86VidModeGetGammaRamp(display, X11Lib.DefaultScreen(display), size, @@ -298,9 +360,9 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements Dyna rampData.position(2 * size); rampData.limit(3 * size); ShortBuffer blueRampData = rampData.slice(); - long display = X11Util.getThreadLocalDefaultDisplay(); + long display = sharedScreen.getDevice().getHandle(); + X11Lib.XLockDisplay(display); try { - X11Lib.XLockDisplay(display); X11Lib.XF86VidModeSetGammaRamp(display, X11Lib.DefaultScreen(display), size, 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 b3a6e5b8c..35daf0ae0 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 @@ -64,18 +64,18 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem int screen = x11Screen.getIndex(); long fbcfg = glXFBConfigID2FBConfig(display, screen, fbcfgID); if(0==fbcfg) { - throw new GLException("FBConfig null of 0x"+Integer.toHexString(fbcfgID)); + throw new GLException("FBConfig null of "+toHexString(fbcfgID)); } if(null==glp) { glp = GLProfile.getDefault(); } GLCapabilities caps = GLXFBConfig2GLCapabilities(glp, display, fbcfg, true, true, true, GLXUtil.isMultisampleAvailable(display)); if(null==caps) { - throw new GLException("GLCapabilities null of 0x"+Long.toHexString(fbcfg)); + throw new GLException("GLCapabilities null of "+toHexString(fbcfg)); } XVisualInfo xvi = GLX.glXGetVisualFromFBConfigCopied(display, fbcfg); if(null==xvi) { - throw new GLException("XVisualInfo null of 0x"+Long.toHexString(fbcfg)); + throw new GLException("XVisualInfo null of "+toHexString(fbcfg)); } return new X11GLXGraphicsConfiguration(x11Screen, caps, caps, new DefaultGLCapabilitiesChooser(), xvi, fbcfg, fbcfgID); } @@ -104,6 +104,10 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem } } + private static int nonZeroOrDontCare(int value) { + return value != 0 ? value : (int)GLX.GLX_DONT_CARE ; + } + public static int[] GLCapabilities2AttribList(GLCapabilities caps, boolean forFBAttr, boolean isMultisampleAvailable, @@ -222,10 +226,11 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem if ( onscreen ) { res = ( 0 != (val & GLX.GLX_WINDOW_BIT) ) ; } else { - res = ( 0 != (val & GLX.GLX_PIXMAP_BIT) ) || usePBuffer ; - } - if ( usePBuffer ) { - res = res && ( 0 != (val & GLX.GLX_PBUFFER_BIT) ) ; + if ( usePBuffer ) { + res = ( 0 != (val & GLX.GLX_PBUFFER_BIT) ) ; + } else { + res = ( 0 != (val & GLX.GLX_PIXMAP_BIT) ) ; + } } return res; @@ -237,7 +242,10 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem int val; val = glXGetFBConfig(display, fbcfg, GLX.GLX_RENDER_TYPE, tmp, 0); if (val != GLX.GLX_RGBA_BIT) { - throw new GLException("Visual does not support RGBA"); + if(DEBUG) { + System.err.println("FBConfig ("+toHexString(fbcfg)+") does not support RGBA: "+toHexString(val)); + } + return null; } GLCapabilities res = new GLCapabilities(glp); @@ -249,7 +257,10 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem res.setOnscreen( 0 != (val & GLX.GLX_WINDOW_BIT) ); res.setPBuffer ( 0 != (val & GLX.GLX_PBUFFER_BIT) ); } else { - throw new GLException("GLX_DRAWABLE_TYPE does not match !!!"); + 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) )+")"); + } + return null; } res.setDoubleBuffered(glXGetFBConfig(display, fbcfg, GLX.GLX_DOUBLEBUFFER, tmp, 0) != 0); res.setStereo (glXGetFBConfig(display, fbcfg, GLX.GLX_STEREO, tmp, 0) != 0); @@ -302,7 +313,7 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem } int res = GLX.glXGetFBConfigAttrib(display, cfg, attrib, tmp, tmp_offset); if (res != 0) { - throw new GLException("glXGetFBConfig(0x"+Long.toHexString(attrib)+") failed: error code " + glXGetFBConfigErrorCode(res)); + throw new GLException("glXGetFBConfig("+toHexString(attrib)+") failed: error code " + glXGetFBConfigErrorCode(res)); } return tmp[tmp_offset]; } @@ -340,8 +351,8 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); } if (DEBUG) { - System.err.println("!!! Fetched XVisualInfo for visual ID 0x" + Long.toHexString(visualID)); - System.err.println("!!! Resulting XVisualInfo: visualid = 0x" + Long.toHexString(res.getVisualid())); + System.err.println("!!! Fetched XVisualInfo for visual ID " + toHexString(visualID)); + System.err.println("!!! Resulting XVisualInfo: visualid = " + toHexString(res.getVisualid())); } return res; } @@ -350,11 +361,17 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem int[] tmp = new int[1]; int val = glXGetConfig(display, info, GLX.GLX_USE_GL, tmp, 0); if (val == 0) { - throw new GLException("Visual does not support OpenGL"); + if(DEBUG) { + System.err.println("Visual ("+toHexString(info.getVisualid())+") does not support OpenGL"); + } + return null; } val = glXGetConfig(display, info, GLX.GLX_RGBA, tmp, 0); if (val == 0) { - throw new GLException("Visual does not support RGBA"); + if(DEBUG) { + System.err.println("Visual ("+toHexString(info.getVisualid())+") does not support RGBA"); + } + return null; } GLCapabilities res = new GLCapabilities(glp); res.setOnscreen (onscreen); @@ -399,13 +416,21 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem } int res = GLX.glXGetConfig(display, info, attrib, tmp, tmp_offset); if (res != 0) { - throw new GLException("glXGetConfig(0x"+Long.toHexString(attrib)+") failed: error code " + glXGetConfigErrorCode(res)); + throw new GLException("glXGetConfig("+toHexString(attrib)+") failed: error code " + glXGetConfigErrorCode(res)); } return tmp[tmp_offset]; } + public static String toHexString(int val) { + return "0x"+Integer.toHexString(val); + } + + public static String toHexString(long val) { + return "0x"+Long.toHexString(val); + } + public String toString() { - return "X11GLXGraphicsConfiguration["+getScreen()+", visualID 0x" + Long.toHexString(getVisualID()) + ", fbConfigID 0x" + Long.toHexString(fbConfigID) + + return "X11GLXGraphicsConfiguration["+getScreen()+", visualID " + toHexString(getVisualID()) + ", fbConfigID " + toHexString(fbConfigID) + ",\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 72551f928..477f2473c 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 @@ -79,9 +79,10 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac // GLCapabilities capsFB = null; long display = x11Screen.getDevice().getHandle(); + + NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); + X11Lib.XLockDisplay(display); try { - NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); - X11Lib.XLockDisplay(display); int screen = x11Screen.getIndex(); boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); @@ -154,14 +155,14 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac x11Screen); if(null==res) { if(usePBuffer) { - throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig"); + throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig for "+caps2); } res = chooseGraphicsConfigurationXVisual((GLCapabilities) caps2, (GLCapabilitiesChooser) chooser, x11Screen); } if(null==res) { - throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration"); + throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig and XVisual for "+caps2); } if(DEBUG) { System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationStatic("+x11Screen+","+caps2+"): "+res); @@ -172,6 +173,7 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac protected static X11GLXGraphicsConfiguration chooseGraphicsConfigurationFBConfig(GLCapabilities capabilities, GLCapabilitiesChooser chooser, X11GraphicsScreen x11Screen) { + long recommendedFBConfig = 0; int recommendedIndex = -1; GLCapabilities[] caps = null; PointerBuffer fbcfgsL = null; @@ -186,37 +188,66 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac // AbstractGraphicsDevice absDevice = x11Screen.getDevice(); long display = absDevice.getHandle(); + + NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); + X11Lib.XLockDisplay(display); try { - NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); - X11Lib.XLockDisplay(display); int screen = x11Screen.getIndex(); boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capabilities, true, isMultisampleAvailable, display, screen); int[] count = { -1 }; + // determine the recommended FBConfig .. fbcfgsL = GLX.glXChooseFBConfigCopied(display, screen, attribs, 0, count, 0); if (fbcfgsL == null || fbcfgsL.limit()<1) { if(DEBUG) { System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed glXChooseFBConfig ("+x11Screen+","+capabilities+"): "+fbcfgsL+", "+count[0]); } - return null; + } else if( !X11GLXGraphicsConfiguration.GLXFBConfigValid( display, fbcfgsL.get(0) ) ) { + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed - GLX FBConfig invalid: ("+x11Screen+","+capabilities+"): "+fbcfgsL+", fbcfg: "+toHexString(fbcfgsL.get(0))); + } + } else { + recommendedFBConfig = fbcfgsL.get(0); } - if( !X11GLXGraphicsConfiguration.GLXFBConfigValid( display, fbcfgsL.get(0) ) ) { + + // get all, glXChooseFBConfig(.. attribs==null ..) == glXGetFBConfig(..) + fbcfgsL = GLX.glXChooseFBConfigCopied(display, screen, null, 0, count, 0); + if (fbcfgsL == null || fbcfgsL.limit()<1) { if(DEBUG) { - System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed - GLX FBConfig invalid: ("+x11Screen+","+capabilities+"): "+fbcfgsL+", fbcfg: 0x"+Long.toHexString(fbcfgsL.get(0))); + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed glXGetFBConfig ("+x11Screen+"): "+fbcfgsL+", "+count[0]); } return null; } - recommendedIndex = 0; // 1st match is always recommended .. + + // make GLCapabilities and seek the recommendedIndex caps = new GLCapabilities[fbcfgsL.limit()]; for (int i = 0; i < fbcfgsL.limit(); i++) { - caps[i] = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glProfile, display, fbcfgsL.get(i), - false, onscreen, usePBuffer, isMultisampleAvailable); + if( !X11GLXGraphicsConfiguration.GLXFBConfigValid( display, fbcfgsL.get(i) ) ) { + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: FBConfig invalid: ("+x11Screen+","+capabilities+"): fbcfg: "+toHexString(fbcfgsL.get(i))); + } + } else { + caps[i] = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glProfile, display, fbcfgsL.get(i), + false, onscreen, usePBuffer, isMultisampleAvailable); + if(caps[i]!=null && recommendedFBConfig==fbcfgsL.get(i)) { + recommendedIndex=i; + if (DEBUG) { + System.err.println("!!! glXChooseFBConfig recommended "+i+", "+caps[i]); + } + } + } } if(null==chooser) { - chosen = recommendedIndex; - } else { + chosen = recommendedIndex; // may still be -1 in case nothing was recommended (-1) + } + + if (chosen < 0) { + if(null==chooser) { + // nothing recommended .. so use our default implementation + chooser = new DefaultGLCapabilitiesChooser(); + } try { chosen = chooser.chooseCapabilities(capabilities, caps, recommendedIndex); } catch (NativeWindowException e) { @@ -231,9 +262,20 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac if(DEBUG) { System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig Failed .. unable to choose config, using first"); } - chosen = 0; // default .. + // seek first available one .. + for(chosen = 0; chosen < caps.length && caps[chosen]==null; chosen++) ; + if(chosen==caps.length) { + // give up .. + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig Failed .. nothing available, bail out"); + } + return null; + } } else if (chosen >= caps.length) { - throw new GLException("GLCapabilitiesChooser specified invalid index (expected 0.." + (caps.length - 1) + ")"); + if(DEBUG) { + System.err.println("GLCapabilitiesChooser specified invalid index (expected 0.." + (caps.length - 1) + ", got "+chosen+")"); + } + return null; } retFBID = X11GLXGraphicsConfiguration.glXFBConfig2FBConfigID(display, fbcfgsL.get(chosen)); @@ -276,9 +318,10 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac AbstractGraphicsDevice absDevice = x11Screen.getDevice(); long display = absDevice.getHandle(); + + NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); + X11Lib.XLockDisplay(display); try { - NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); - X11Lib.XLockDisplay(display); int screen = x11Screen.getIndex(); boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capabilities, false, isMultisampleAvailable, display, screen); @@ -290,7 +333,7 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac if (recommendedVis == null) { System.err.println("null visual"); } else { - System.err.println("visual id 0x" + Long.toHexString(recommendedVis.getVisualid())); + System.err.println("visual id " + toHexString(recommendedVis.getVisualid())); } } int[] count = new int[1]; @@ -326,7 +369,7 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac throw new GLException("GLCapabilitiesChooser specified invalid index (expected 0.." + (caps.length - 1) + ")"); } if (infos[chosen] == null) { - throw new GLException("GLCapabilitiesChooser chose an invalid visual"); + throw new GLException("GLCapabilitiesChooser chose an invalid visual for "+caps[chosen]); } retXVisualInfo = XVisualInfo.create(infos[chosen]); } finally { @@ -335,5 +378,14 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac } return new X11GLXGraphicsConfiguration(x11Screen, caps[chosen], capabilities, chooser, retXVisualInfo, 0, -1); } + + public static String toHexString(int val) { + return "0x"+Integer.toHexString(val); + } + + public static String toHexString(long val) { + return "0x"+Long.toHexString(val); + } + } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXDrawable.java index ea855d28d..41f012122 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXDrawable.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXDrawable.java @@ -75,9 +75,9 @@ public class X11OffscreenGLXDrawable extends X11GLXDrawable { int screen = aScreen.getIndex(); getFactoryImpl().lockToolkit(); + X11Lib.XLockDisplay(dpy); try { - X11Lib.XLockDisplay(dpy); - pixmap = X11Lib.XCreatePixmap(dpy, (int) X11Lib.RootWindow(dpy, screen), + pixmap = X11Lib.XCreatePixmap(dpy, X11Lib.RootWindow(dpy, screen), component.getWidth(), component.getHeight(), bitsPerPixel); if (pixmap == 0) { throw new GLException("XCreatePixmap failed"); @@ -105,10 +105,10 @@ public class X11OffscreenGLXDrawable extends X11GLXDrawable { NativeWindow nw = getNativeWindow(); long display = nw.getDisplayHandle(); - try { - getFactoryImpl().lockToolkit(); - X11Lib.XLockDisplay(display); + getFactoryImpl().lockToolkit(); + X11Lib.XLockDisplay(display); + try { long drawable = nw.getSurfaceHandle(); if (DEBUG) { System.err.println("Destroying pixmap " + toHexString(pixmap) + @@ -135,11 +135,11 @@ public class X11OffscreenGLXDrawable extends X11GLXDrawable { X11Lib.XFreePixmap(display, pixmap); drawable = 0; pixmap = 0; - display = 0; ((SurfaceChangeable)nw).setSurfaceHandle(0); } finally { X11Lib.XUnlockDisplay(display); getFactoryImpl().unlockToolkit(); + display = 0; } } protected void swapBuffersImpl() { 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 63b350bd3..dc6c60664 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 @@ -92,7 +92,7 @@ public class X11AWTGLXGraphicsConfigurationFactory extends GraphicsConfiguration try { long displayHandle = X11SunJDKReflection.graphicsDeviceGetDisplay(device); if(0==displayHandle) { - displayHandle = X11Util.getThreadLocalDefaultDisplay(); + displayHandle = X11Util.createThreadLocalDefaultDisplay(); if(DEBUG) { System.err.println("X11AWTGLXGraphicsConfigurationFactory: using a thread local X11 display"); } diff --git a/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java b/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java index 8603c7184..c5ded88f6 100644 --- a/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java +++ b/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java @@ -89,11 +89,17 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser { int windowSystemRecommendedChoice) { GLCapabilities _desired = (GLCapabilities) desired; GLCapabilities[] _available = (GLCapabilities[]) available; + int availnum = 0; + + for (int i = 0; i < _available.length; i++) { + if(null != _available[i]) { availnum++; } + } 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("Available " + i + ": " + _available[i]); + System.err.println(i + ": " + _available[i]); } System.err.println("Window system's recommended choice: " + windowSystemRecommendedChoice); } @@ -132,6 +138,9 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser { if (_desired.isOnscreen() != cur.isOnscreen()) { continue; } + if (_desired.isPBuffer() != cur.isPBuffer()) { + continue; + } if (_desired.getStereo() != cur.getStereo()) { continue; } diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java index 71cb3cb3b..80c2c10e2 100644 --- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java +++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java @@ -216,6 +216,7 @@ public abstract class GLDrawableFactory { /** * Returns true if it is possible to create a GLPbuffer. Some older * graphics cards do not have this capability. + * @param passing the device for the query, may be null */ public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device); @@ -278,6 +279,7 @@ public abstract class GLDrawableFactory { /** * Returns true if it is possible to create an external GLDrawable * object via {@link #createExternalGLDrawable}. + * @param passing the device for the query, may be null */ public abstract boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device); diff --git a/src/junit/com/jogamp/test/junit/jogl/drawable/TestDrawable01NEWT.java b/src/junit/com/jogamp/test/junit/jogl/drawable/TestDrawable01NEWT.java index fa15e3fef..5abf02b97 100755 --- a/src/junit/com/jogamp/test/junit/jogl/drawable/TestDrawable01NEWT.java +++ b/src/junit/com/jogamp/test/junit/jogl/drawable/TestDrawable01NEWT.java @@ -40,6 +40,8 @@ import java.util.List; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; +import org.junit.AfterClass; +import org.junit.After; import org.junit.Test; import javax.media.opengl.*; @@ -50,21 +52,29 @@ import com.jogamp.newt.opengl.*; public class TestDrawable01NEWT { static GLProfile glp; + static GLDrawableFactory factory; static int width, height; GLCapabilities caps; Window window; GLDrawable drawable; GLContext context; - GLDrawableFactory factory; @BeforeClass public static void initClass() { glp = GLProfile.getDefault(); Assert.assertNotNull(glp); + factory = GLDrawableFactory.getFactory(glp); + Assert.assertNotNull(factory); width = 640; height = 480; } + @AfterClass + public static void releaseClass() { + factory.shutdown(); + factory=null; + } + @Before public void initTest() { caps = new GLCapabilities(glp); @@ -106,8 +116,6 @@ public class TestDrawable01NEWT { Assert.assertTrue(glCaps.getDoubleBuffered()==!onscreen); Assert.assertTrue(glCaps.getDepthBits()>4); - factory = GLDrawableFactory.getFactory(glCaps.getGLProfile()); - Assert.assertNotNull(factory); drawable = factory.createGLDrawable(window); Assert.assertNotNull(drawable); // System.out.println("Pre: "+drawable); @@ -149,10 +157,6 @@ public class TestDrawable01NEWT { drawable = null; context = null; window = null; - - // test code cont .. - factory.shutdown(); - factory = null; } @Test @@ -174,7 +178,22 @@ public class TestDrawable01NEWT { } public static void main(String args[]) { - org.junit.runner.JUnitCore.main(TestDrawable01NEWT.class.getName()); + String tstname = TestDrawable01NEWT.class.getName(); + try { + org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] { + tstname, + "filtertrace=true", + "haltOnError=false", + "haltOnFailure=false", + "showoutput=true", + "outputtoformatters=true", + "logfailedtests=true", + "logtestlistenerevents=true", + "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter", + "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } ); + } catch (Exception e) { + e.printStackTrace(); + } } } diff --git a/src/junit/com/jogamp/test/junit/jogl/offscreen/TestOffscreen01NEWT.java b/src/junit/com/jogamp/test/junit/jogl/offscreen/TestOffscreen01NEWT.java index 436167dbf..e5e7c4a52 100755 --- a/src/junit/com/jogamp/test/junit/jogl/offscreen/TestOffscreen01NEWT.java +++ b/src/junit/com/jogamp/test/junit/jogl/offscreen/TestOffscreen01NEWT.java @@ -40,6 +40,8 @@ import java.util.List; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; +import org.junit.AfterClass; +import org.junit.After; import org.junit.Test; import javax.media.opengl.*; @@ -52,48 +54,223 @@ import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears; import com.jogamp.test.junit.jogl.demos.es1.RedSquare; public class TestOffscreen01NEWT { - int width, height; - GLProfile glp; + static GLProfile glp; + static GLDrawableFactory factory; + static int width, height; GLCapabilities caps; - @Before - public void init() { + @BeforeClass + public static void initClass() { glp = GLProfile.getDefault(); + Assert.assertNotNull(glp); + factory = GLDrawableFactory.getFactory(glp); + Assert.assertNotNull(factory); width = 640; height = 480; + } + + @AfterClass + public static void releaseClass() { + factory.shutdown(); + factory=null; + } + + @Before + public void init() { caps = new GLCapabilities(glp); } + private void do01OffscreenWindowPBuffer(GLCapabilities caps) { + Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + Window window = NewtFactory.createWindow(screen, caps, false /* undecorated */); + Assert.assertNotNull(window); + window.setSize(width, height); + GLWindow glWindow = GLWindow.create(window); + Assert.assertNotNull(glWindow); + glWindow.setVisible(true); + GLEventListener demo = new RedSquare(); + WindowUtilNEWT.setDemoFields(demo, window, glWindow, false); + + while ( glWindow.getTotalFrames() < 2) { + glWindow.display(); + } + + if(null!=glWindow) { + glWindow.destroy(); + } + if(null!=window) { + window.destroy(); + } + if(null!=screen) { + screen.destroy(); + } + if(null!=display) { + display.destroy(); + } + } + + @Test + public void test01aOffscreenWindowPBuffer() { + GLCapabilities caps2 = WindowUtilNEWT.fixCaps(caps, false, true, false); + do01OffscreenWindowPBuffer(caps2); + } + + @Test + public void test01bOffscreenWindowPBufferStencil() { + GLCapabilities caps2 = WindowUtilNEWT.fixCaps(caps, false, true, false); + caps2.setStencilBits(8); + do01OffscreenWindowPBuffer(caps2); + } + @Test - public void test01OffscreenWindow() { + public void test01cOffscreenWindowPBufferStencilAlpha() { GLCapabilities caps2 = WindowUtilNEWT.fixCaps(caps, false, true, false); + caps2.setStencilBits(8); + caps2.setAlphaBits(8); + do01OffscreenWindowPBuffer(caps2); + } + + @Test + public void test01cOffscreenWindowPBuffer555() { + GLCapabilities caps2 = WindowUtilNEWT.fixCaps(caps, false, true, false); + caps2.setRedBits(5); + caps2.setGreenBits(5); + caps2.setBlueBits(5); + do01OffscreenWindowPBuffer(caps2); + } + + @Test + public void test02Offscreen3Windows1DisplayPBuffer() { + GLCapabilities caps2 = WindowUtilNEWT.fixCaps(caps, false, true, false); + int winnum = 3, i; + Window windows[] = new Window[winnum]; + GLWindow glWindows[] = new GLWindow[winnum]; + GLEventListener demos[] = new GLEventListener[winnum]; Display display = NewtFactory.createDisplay(null); // local display Assert.assertNotNull(display); Screen screen = NewtFactory.createScreen(display, 0); // screen 0 Assert.assertNotNull(screen); + + for(i=0; i<winnum; i++) { + System.out.println("Create Window "+i); + windows[i] = NewtFactory.createWindow(screen, caps2, false /* undecorated */); + Assert.assertNotNull(windows[i]); + windows[i].setSize(width, height); + glWindows[i] = GLWindow.create(windows[i]); + Assert.assertNotNull(glWindows[i]); + glWindows[i].setVisible(true); + demos[i] = new RedSquare(); + WindowUtilNEWT.setDemoFields(demos[i], windows[i], glWindows[i], false); + } + + while ( glWindows[0].getTotalFrames() < 2) { + for(i=0; i<winnum; i++) { + glWindows[i].display(); + } + } + + for(i=0; i<winnum; i++) { + if(null!=glWindows[i]) { + glWindows[i].destroy(); + } + if(null!=windows[i]) { + windows[i].destroy(); + } + } + if(null!=screen) { + screen.destroy(); + } + if(null!=display) { + display.destroy(); + } + } + + @Test + public void test03Offscreen3Windows3DisplaysPBuffer() { + GLCapabilities caps2 = WindowUtilNEWT.fixCaps(caps, false, true, false); + int winnum = 3, i; + Display displays[] = new Display[winnum]; + Screen screens[] = new Screen[winnum]; + Window windows[] = new Window[winnum]; + GLWindow glWindows[] = new GLWindow[winnum]; + GLEventListener demos[] = new GLEventListener[winnum]; + + for(i=0; i<winnum; i++) { + System.out.println("Create Window "+i); + displays[i] = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(displays[i]); + screens[i] = NewtFactory.createScreen(displays[i], 0); // screen 0 + Assert.assertNotNull(screens[i]); + windows[i] = NewtFactory.createWindow(screens[i], caps2, false /* undecorated */); + Assert.assertNotNull(windows[i]); + windows[i].setSize(width, height); + glWindows[i] = GLWindow.create(windows[i]); + Assert.assertNotNull(glWindows[i]); + glWindows[i].setVisible(true); + demos[i] = new RedSquare(); + WindowUtilNEWT.setDemoFields(demos[i], windows[i], glWindows[i], false); + } + + while ( glWindows[0].getTotalFrames() < 2) { + for(i=0; i<winnum; i++) { + glWindows[i].display(); + } + } + + for(i=0; i<winnum; i++) { + if(null!=glWindows[i]) { + glWindows[i].destroy(); + } + if(null!=windows[i]) { + windows[i].destroy(); + } + if(null!=screens[i]) { + screens[i].destroy(); + } + if(null!=displays[i]) { + displays[i].destroy(); + } + } + } + + @Test + public void test04OffscreenSnapshotWithDemoPBuffer() { + GLCapabilities caps2 = WindowUtilNEWT.fixCaps(caps, false, true, false); + + System.out.println("Create Window 1"); + Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); Window window = NewtFactory.createWindow(screen, caps2, false /* undecorated */); Assert.assertNotNull(window); window.setSize(width, height); - GLWindow windowOffScreen = GLWindow.create(window); - Assert.assertNotNull(windowOffScreen); - windowOffScreen.setVisible(true); + GLWindow glWindow = GLWindow.create(window); + Assert.assertNotNull(glWindow); + glWindow.setVisible(true); GLWindow windowOnScreen = null; WindowListener wl=null; MouseListener ml=null; SurfaceUpdatedListener ul=null; - WindowUtilNEWT.run(windowOffScreen, null, windowOnScreen, wl, ml, ul, 2, false /*snapshot*/, false /*debug*/); - try { - Thread.sleep(1000); // 1000 ms - } catch (Exception e) {} + GLEventListener demo = new RedSquare(); + Assert.assertNotNull(demo); + + WindowUtilNEWT.run(glWindow, demo, windowOnScreen, wl, ml, ul, 2, true /*snapshot*/, false /*debug*/); if(null!=windowOnScreen) { windowOnScreen.destroy(); } - if(null!=windowOffScreen) { - windowOffScreen.destroy(); + if(null!=glWindow) { + glWindow.destroy(); + } + if(null!=window) { + window.destroy(); } if(null!=screen) { screen.destroy(); @@ -104,8 +281,8 @@ public class TestOffscreen01NEWT { } @Test - public void test02OffscreenSnapshotWithDemo() { - GLCapabilities caps2 = WindowUtilNEWT.fixCaps(caps, false, true, false); + public void test11OffscreenWindowPixmap() { + GLCapabilities caps2 = WindowUtilNEWT.fixCaps(caps, false, false, false); Display display = NewtFactory.createDisplay(null); // local display Assert.assertNotNull(display); @@ -114,9 +291,45 @@ public class TestOffscreen01NEWT { Window window = NewtFactory.createWindow(screen, caps2, false /* undecorated */); Assert.assertNotNull(window); window.setSize(width, height); - GLWindow windowOffScreen = GLWindow.create(window); - Assert.assertNotNull(windowOffScreen); - windowOffScreen.setVisible(true); + GLWindow glWindow = GLWindow.create(window); + Assert.assertNotNull(glWindow); + glWindow.setVisible(true); + GLEventListener demo = new RedSquare(); + WindowUtilNEWT.setDemoFields(demo, window, glWindow, false); + + while ( glWindow.getTotalFrames() < 2) { + glWindow.display(); + } + + if(null!=glWindow) { + glWindow.destroy(); + } + if(null!=window) { + window.destroy(); + } + if(null!=screen) { + screen.destroy(); + } + if(null!=display) { + display.destroy(); + } + } + + @Test + public void test14OffscreenSnapshotWithDemoPixmap() { + GLCapabilities caps2 = WindowUtilNEWT.fixCaps(caps, false, false, false); + + System.out.println("Create Window 1"); + Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + Window window = NewtFactory.createWindow(screen, caps2, false /* undecorated */); + Assert.assertNotNull(window); + window.setSize(width, height); + GLWindow glWindow = GLWindow.create(window); + Assert.assertNotNull(glWindow); + glWindow.setVisible(true); GLWindow windowOnScreen = null; WindowListener wl=null; @@ -126,16 +339,16 @@ public class TestOffscreen01NEWT { GLEventListener demo = new RedSquare(); Assert.assertNotNull(demo); - WindowUtilNEWT.run(windowOffScreen, demo, windowOnScreen, wl, ml, ul, 2, true /*snapshot*/, false /*debug*/); - try { - Thread.sleep(1000); // 1000 ms - } catch (Exception e) {} + WindowUtilNEWT.run(glWindow, demo, windowOnScreen, wl, ml, ul, 2, true /*snapshot*/, false /*debug*/); if(null!=windowOnScreen) { windowOnScreen.destroy(); } - if(null!=windowOffScreen) { - windowOffScreen.destroy(); + if(null!=glWindow) { + glWindow.destroy(); + } + if(null!=window) { + window.destroy(); } if(null!=screen) { screen.destroy(); @@ -144,7 +357,6 @@ public class TestOffscreen01NEWT { display.destroy(); } } - public static void main(String args[]) { String tstname = TestOffscreen01NEWT.class.getName(); try { diff --git a/src/junit/com/jogamp/test/junit/jogl/offscreen/WindowUtilNEWT.java b/src/junit/com/jogamp/test/junit/jogl/offscreen/WindowUtilNEWT.java index f6a6dc4be..7afa7b1e5 100755 --- a/src/junit/com/jogamp/test/junit/jogl/offscreen/WindowUtilNEWT.java +++ b/src/junit/com/jogamp/test/junit/jogl/offscreen/WindowUtilNEWT.java @@ -52,22 +52,27 @@ public class WindowUtilNEWT { return caps2; } + public static void setDemoFields(GLEventListener demo, Window window, GLWindow glWindow, boolean debug) { + Assert.assertNotNull(demo); + Assert.assertNotNull(window); + if(debug) { + MiscUtils.setField(demo, "glDebug", new Boolean(true)); + MiscUtils.setField(demo, "glTrace", new Boolean(true)); + } + if(!MiscUtils.setField(demo, "window", window)) { + MiscUtils.setField(demo, "glWindow", glWindow); + } + } + public static void run(GLWindow windowOffScreen, GLEventListener demo, GLWindow windowOnScreen, WindowListener wl, MouseListener ml, SurfaceUpdatedListener ul, int frames, boolean snapshot, boolean debug) { try { Assert.assertNotNull(windowOffScreen); + Assert.assertNotNull(demo); - if(debug && null!=demo) { - MiscUtils.setField(demo, "glDebug", new Boolean(true)); - MiscUtils.setField(demo, "glTrace", new Boolean(true)); - } - if(null!=demo) { - if(!MiscUtils.setField(demo, "window", windowOffScreen)) { - MiscUtils.setField(demo, "glWindow", windowOffScreen); - } - windowOffScreen.addGLEventListener(demo); - } + setDemoFields(demo, windowOffScreen, windowOffScreen, debug); + windowOffScreen.addGLEventListener(demo); if ( null != windowOnScreen ) { if(null!=wl) { diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java index 95fd6c72b..41ffccc42 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java @@ -34,6 +34,9 @@ package com.jogamp.nativewindow.impl.x11; import java.util.HashMap; import java.util.Map; +import java.util.Collection; +import java.util.ArrayList; +import java.util.Iterator; import javax.media.nativewindow.*; @@ -41,7 +44,7 @@ import com.jogamp.nativewindow.impl.*; /** * Contains a thread safe X11 utility to retrieve thread local display connection,<br> - * as well as the static global discplay connection.<br> + * as well as the static global display connection.<br> * * The TLS variant is thread safe per se, but be aware of the memory leak risk * where an application heavily utilizing this class on temporary new threads.<br> @@ -51,27 +54,98 @@ public class X11Util { static { NativeLibLoaderBase.loadNativeWindow("x11"); + installIOErrorHandler(); } private X11Util() {} private static ThreadLocal currentDisplayMap = new ThreadLocal(); + // not exactly thread safe, but good enough for our purpose, + // which is to tag a NamedDisplay uncloseable after creation. + private static Object globalLock = new Object(); + private static Collection globalNamedDisplayActive = new ArrayList(); + private static Collection globalNamedDisplayPassive = new ArrayList(); + + public static final String nullDeviceName = "nil" ; + public static class NamedDisplay implements Cloneable { - private String name; - private long handle; + String name; + long handle; + int refCount; + boolean unCloseable; protected NamedDisplay(String name, long handle) { this.name=name; this.handle=handle; + this.refCount=1; + this.unCloseable=false; } - public String getName() { return name; } - public long getHandle() { return handle; } + public final String getName() { return name; } + public final String getNameSafe() { return null == name ? nullDeviceName : name; } + public final long getHandle() { return handle; } + public final int getRefCount() { return refCount; } + public final boolean isUncloseable() { return unCloseable; } public Object clone() throws CloneNotSupportedException { return super.clone(); } + + public String toString() { + return "NamedX11Display["+name+", 0x"+Long.toHexString(handle)+", refCount "+refCount+", unCloseable "+unCloseable+"]"; + } + } + + /** Returns the number of unclosed X11 Displays. + * @param realXClosePendingDisplays if true, call XCloseDisplay on the remaining ones + */ + public static int shutdown(boolean realXClosePendingDisplays, boolean verbose) { + int num=0; + String msg; + if(DEBUG||verbose) { + msg = "X11Util.Display: Shutdown (active: "+globalNamedDisplayActive.size()+ + ", passive: "+globalNamedDisplayPassive.size() + ")"; + if(DEBUG) { + Exception e = new Exception(msg); + e.printStackTrace(); + } else if(verbose) { + System.err.println(msg); + } + } + + msg = realXClosePendingDisplays ? "Close" : "Keep" ; + + synchronized(globalLock) { + // for all passive displays .. + Collection namedDisplays = globalNamedDisplayPassive; + globalNamedDisplayPassive = new ArrayList(); + for(Iterator iter=namedDisplays.iterator(); iter.hasNext(); ) { + NamedDisplay ndpy = (NamedDisplay)iter.next(); + if(DEBUG||verbose) { + System.err.println(msg+" passive: "+ndpy); + } + if(realXClosePendingDisplays) { + X11Lib.XCloseDisplay(ndpy.getHandle()); + } + num++; + } + + // for all active displays .. + namedDisplays = globalNamedDisplayActive; + globalNamedDisplayActive = new ArrayList(); + for(Iterator iter=namedDisplays.iterator(); iter.hasNext(); ) { + NamedDisplay ndpy = (NamedDisplay)iter.next(); + if(DEBUG||verbose) { + System.err.println(msg+" active: "+ndpy); + } + if(realXClosePendingDisplays) { + X11Lib.XCloseDisplay(ndpy.getHandle()); + } + num++; + } + } + return num; } /** Returns a clone of the thread local display map, you may {@link Object#wait()} on it */ @@ -79,48 +153,120 @@ public class X11Util { return (Map) ((HashMap)getCurrentDisplayMapImpl()).clone(); } - /** Returns this thread current default display. If it doesn not exist, it is being created */ - public static long getThreadLocalDefaultDisplay() { - return getThreadLocalDisplay(null); + /** Returns this thread current default display. If it doesn not exist, it is being created, otherwise the reference count is increased */ + public static long createThreadLocalDefaultDisplay() { + return createThreadLocalDisplay(null); } - /** Returns this thread named display. If it doesn not exist, it is being created */ - public static long getThreadLocalDisplay(String name) { + /** Returns this thread named display. If it doesn not exist, it is being created, otherwise the reference count is increased */ + public static long createThreadLocalDisplay(String name) { NamedDisplay namedDpy = getCurrentDisplay(name); if(null==namedDpy) { + synchronized(globalLock) { + namedDpy = getNamedDisplay(globalNamedDisplayPassive, name); + if(null != namedDpy) { + if(!globalNamedDisplayPassive.remove(namedDpy)) { throw new RuntimeException("Internal: "+namedDpy); } + globalNamedDisplayActive.add(namedDpy); + addCurrentDisplay( namedDpy ); + } + } + } + if(null==namedDpy) { long dpy = X11Lib.XOpenDisplay(name); if(0==dpy) { throw new NativeWindowException("X11Util.Display: Unable to create a display("+name+") connection in Thread "+Thread.currentThread().getName()); } namedDpy = new NamedDisplay(name, dpy); - setCurrentDisplay( namedDpy ); + synchronized(globalLock) { + globalNamedDisplayActive.add(namedDpy); + addCurrentDisplay( namedDpy ); + } if(DEBUG) { - Exception e = new Exception("X11Util.Display: Created new TLS display("+name+") connection 0x"+Long.toHexString(dpy)+" in thread "+Thread.currentThread().getName()); + Exception e = new Exception("X11Util.Display: Created new TLS "+namedDpy+" in thread "+Thread.currentThread().getName()); + e.printStackTrace(); + } + } else { + namedDpy.refCount++; + if(DEBUG) { + Exception e = new Exception("X11Util.Display: Reused TLS "+namedDpy+" in thread "+Thread.currentThread().getName()); e.printStackTrace(); } } return namedDpy.getHandle(); } - /** Closes this thread named display. It returns the handle of the closed display or 0, if it does not exist. */ + /** Decrease the reference count of this thread named display. If it reaches 0, close it. + It returns the handle of the to be closed display. + It throws a RuntimeException in case the named display does not exist, + or the reference count goes below 0. + */ public static long closeThreadLocalDisplay(String name) { - NamedDisplay namedDpy = removeCurrentDisplay(name); + NamedDisplay namedDpy = getCurrentDisplay(name); if(null==namedDpy) { + throw new RuntimeException("X11Util.Display: Display("+name+") with given handle is not mapped to TLS in thread "+Thread.currentThread().getName()); + } + if(0==namedDpy.refCount) { + throw new RuntimeException("X11Util.Display: "+namedDpy+" has refCount already 0 in thread "+Thread.currentThread().getName()); + } + long dpy = namedDpy.getHandle(); + namedDpy.refCount--; + if(0==namedDpy.refCount) { + synchronized(globalLock) { + if(!globalNamedDisplayActive.remove(namedDpy)) { throw new RuntimeException("Internal: "+namedDpy); } + if(namedDpy.isUncloseable()) { + globalNamedDisplayPassive.add(namedDpy); + } else { + X11Lib.XCloseDisplay(dpy); + } + removeCurrentDisplay(namedDpy); + } if(DEBUG) { - Exception e = new Exception("X11Util.Display: Display("+name+") with given handle is not mapped to TLS in thread "+Thread.currentThread().getName()); + String type = namedDpy.isUncloseable() ? "passive" : "real" ; + Exception e = new Exception("X11Util.Display: Closing ( "+type+" ) TLS "+namedDpy+" in thread "+Thread.currentThread().getName()); e.printStackTrace(); } - return 0; - } - long dpy = namedDpy.getHandle(); - if(DEBUG) { - Exception e = new Exception("X11Util.Display: Closing TLS Display("+name+") with handle 0x"+Long.toHexString(dpy)+" in thread "+Thread.currentThread().getName()); + } else if(DEBUG) { + Exception e = new Exception("X11Util.Display: Keep TLS "+namedDpy+" in thread "+Thread.currentThread().getName()); e.printStackTrace(); } - X11Lib.XCloseDisplay(dpy); return dpy; } + public static String getThreadLocalDisplayName(long handle) { + NamedDisplay ndpy = getNamedDisplay(getCurrentDisplayMapImpl().values(), handle); + return null != ndpy ? ndpy.getName() : null; + } + + public static boolean markThreadLocalDisplayUndeletable(long handle) { + NamedDisplay ndpy = getNamedDisplay(getCurrentDisplayMapImpl().values(), handle); + if( null != ndpy ) { + ndpy.unCloseable=true; + return true; + } + return false; + } + + public static String getGlobalDisplayName(long handle, boolean active) { + String name; + synchronized(globalLock) { + NamedDisplay ndpy = getNamedDisplay(active ? globalNamedDisplayActive : globalNamedDisplayPassive, handle); + name = null != ndpy ? ndpy.getName() : null; + } + return name; + } + + public static boolean markGlobalDisplayUndeletable(long handle) { + boolean r=false; + synchronized(globalLock) { + NamedDisplay ndpy = getNamedDisplay(globalNamedDisplayActive, handle); + if( null != ndpy ) { + ndpy.unCloseable=true; + r=true; + } + } + return r; + } + private static Map getCurrentDisplayMapImpl() { Map displayMap = (Map) currentDisplayMap.get(); if(null==displayMap) { @@ -132,12 +278,11 @@ public class X11Util { /** maps the given display to the thread local display map * and notifies all threads synchronized to this display map. */ - private static NamedDisplay setCurrentDisplay(NamedDisplay newDisplay) { + private static NamedDisplay addCurrentDisplay(NamedDisplay newDisplay) { Map displayMap = getCurrentDisplayMapImpl(); NamedDisplay oldDisplay = null; synchronized(displayMap) { - String name = (null==newDisplay.getName())?"nil":newDisplay.getName(); - oldDisplay = (NamedDisplay) displayMap.put(name, newDisplay); + oldDisplay = (NamedDisplay) displayMap.put(newDisplay.getNameSafe(), newDisplay); displayMap.notifyAll(); } return oldDisplay; @@ -145,22 +290,45 @@ public class X11Util { /** removes the mapping of the given name from the thread local display map * and notifies all threads synchronized to this display map. */ - private static NamedDisplay removeCurrentDisplay(String name) { + private static NamedDisplay removeCurrentDisplay(NamedDisplay ndpy) { Map displayMap = getCurrentDisplayMapImpl(); - NamedDisplay oldDisplay = null; synchronized(displayMap) { - if(null==name) name="nil"; - oldDisplay = (NamedDisplay) displayMap.remove(name); + NamedDisplay ndpyDel = (NamedDisplay) displayMap.remove(ndpy.getNameSafe()); + if(ndpyDel!=ndpy) { + throw new RuntimeException("Wrong mapping req: "+ndpy+", got "+ndpyDel); + } displayMap.notifyAll(); } - return oldDisplay; + return ndpy; } /** Returns the thread local display mapped to the given name */ private static NamedDisplay getCurrentDisplay(String name) { - if(null==name) name="nil"; + if(null==name) name=nullDeviceName; Map displayMap = getCurrentDisplayMapImpl(); return (NamedDisplay) displayMap.get(name); } + private static NamedDisplay getNamedDisplay(Collection namedDisplays, String name) { + if(null==name) name=nullDeviceName; + for(Iterator iter=namedDisplays.iterator(); iter.hasNext(); ) { + NamedDisplay ndpy = (NamedDisplay)iter.next(); + if (ndpy.getNameSafe().equals(name)) { + return ndpy; + } + } + return null; + } + + private static NamedDisplay getNamedDisplay(Collection namedDisplays, long handle) { + for(Iterator iter=namedDisplays.iterator(); iter.hasNext(); ) { + NamedDisplay ndpy = (NamedDisplay)iter.next(); + if (ndpy.getHandle()==handle) { + return ndpy; + } + } + return null; + } + + private static native void installIOErrorHandler(); } diff --git a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java index 52f48660a..69ace3c52 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java +++ b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java @@ -57,7 +57,7 @@ public class X11GraphicsScreen extends DefaultGraphicsScreen implements Cloneabl /** Creates a new X11GraphicsScreen using a thread local display connection */ public static AbstractGraphicsScreen createDefault() { NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); - long display = X11Util.getThreadLocalDefaultDisplay(); + long display = X11Util.createThreadLocalDefaultDisplay(); try { X11Lib.XLockDisplay(display); int scrnIdx = X11Lib.DefaultScreen(display); diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c new file mode 100644 index 000000000..4320a8f12 --- /dev/null +++ b/src/nativewindow/native/x11/Xmisc.c @@ -0,0 +1,471 @@ +/* + * Copyright (c) 2010 Sven Gothel. 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 Sven Gothel 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 + * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <unistd.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +/* Linux headers don't work properly */ +#define __USE_GNU +#include <dlfcn.h> +#undef __USE_GNU + +/* Current versions of Solaris don't expose the XF86 extensions, + although with the recent transition to Xorg this will probably + happen in an upcoming release */ +#if !defined(__sun) && !defined(_HPUX) +#include <X11/extensions/xf86vmode.h> +#else +/* Need to provide stubs for these */ +Bool XF86VidModeGetGammaRampSize( + Display *display, + int screen, + int* size) +{ + return False; +} + +Bool XF86VidModeGetGammaRamp( + Display *display, + int screen, + int size, + unsigned short *red_array, + unsigned short *green_array, + unsigned short *blue_array) { + return False; +} +Bool XF86VidModeSetGammaRamp( + Display *display, + int screen, + int size, + unsigned short *red_array, + unsigned short *green_array, + unsigned short *blue_array) { + return False; +} +#endif /* defined(__sun) || defined(_HPUX) */ + +/* HP-UX doesn't define RTLD_DEFAULT. */ +#if defined(_HPUX) && !defined(RTLD_DEFAULT) +#define RTLD_DEFAULT NULL +#endif + +#include "com_jogamp_nativewindow_impl_x11_X11Lib.h" + +// #define VERBOSE_ON 1 + +#ifdef VERBOSE_ON + // Workaround for ancient compiler on Solaris/SPARC + // #define DBG_PRINT(args...) fprintf(stderr, args); + #define DBG_PRINT0(str) fprintf(stderr, str); + #define DBG_PRINT1(str, arg1) fprintf(stderr, str, arg1); + #define DBG_PRINT2(str, arg1, arg2) fprintf(stderr, str, arg1, arg2); + #define DBG_PRINT3(str, arg1, arg2, arg3) fprintf(stderr, str, arg1, arg2, arg3); + #define DBG_PRINT4(str, arg1, arg2, arg3, arg4) fprintf(stderr, str, arg1, arg2, arg3, arg4); + #define DBG_PRINT5(str, arg1, arg2, arg3, arg4, arg5) fprintf(stderr, str, arg1, arg2, arg3, arg4, arg5); + #define DBG_PRINT6(str, arg1, arg2, arg3, arg4, arg5, arg6) fprintf(stderr, str, arg1, arg2, arg3, arg4, arg5, arg6); + #define DBG_PRINT7(str, arg1, arg2, arg3, arg4, arg5, arg6, arg7) fprintf(stderr, str, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + #define DBG_PRINT8(str, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) fprintf(stderr, str, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + +#else + + // Workaround for ancient compiler on Solaris/SPARC + // #define DBG_PRINT(args...) + #define DBG_PRINT0(str) + #define DBG_PRINT1(str, arg1) + #define DBG_PRINT2(str, arg1, arg2) + #define DBG_PRINT3(str, arg1, arg2, arg3) + #define DBG_PRINT4(str, arg1, arg2, arg3, arg4) + #define DBG_PRINT5(str, arg1, arg2, arg3, arg4, arg5) + #define DBG_PRINT6(str, arg1, arg2, arg3, arg4, arg5, arg6) + #define DBG_PRINT7(str, arg1, arg2, arg3, arg4, arg5, arg6, arg7) + #define DBG_PRINT8(str, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) + +#endif + +/* Need to pull this in as we don't have a stub header for it */ +extern Bool XineramaEnabled(Display* display); + +static void _FatalError(JNIEnv *env, const char* msg, ...) +{ + char buffer[512]; + va_list ap; + + va_start(ap, msg); + vsnprintf(buffer, sizeof(buffer), msg, ap); + va_end(ap); + + fprintf(stderr, buffer); + (*env)->FatalError(env, buffer); +} + +static const char * const ClazzNameInternalBufferUtil = "com/jogamp/nativewindow/impl/InternalBufferUtil"; +static const char * const ClazzNameInternalBufferUtilStaticCstrName = "copyByteBuffer"; +static const char * const ClazzNameInternalBufferUtilStaticCstrSignature = "(Ljava/nio/ByteBuffer;)Ljava/nio/ByteBuffer;"; +static const char * const ClazzNameByteBuffer = "java/nio/ByteBuffer"; +static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException"; +static jclass clazzInternalBufferUtil = NULL; +static jmethodID cstrInternalBufferUtil = NULL; +static jclass clazzByteBuffer = NULL; +static jclass clazzRuntimeException=NULL; + +static void _initClazzAccess(JNIEnv *env) { + jclass c; + + if(NULL!=clazzRuntimeException) return ; + + c = (*env)->FindClass(env, ClazzNameRuntimeException); + if(NULL==c) { + _FatalError(env, "Nativewindow X11Lib: can't find %s", ClazzNameRuntimeException); + } + clazzRuntimeException = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + if(NULL==clazzRuntimeException) { + _FatalError(env, "FatalError: NEWT X11Window: can't use %s", ClazzNameRuntimeException); + } + + c = (*env)->FindClass(env, ClazzNameInternalBufferUtil); + if(NULL==c) { + _FatalError(env, "FatalError: Java_com_jogamp_nativewindow_impl_x11_X11Lib: can't find %s", ClazzNameInternalBufferUtil); + } + clazzInternalBufferUtil = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + if(NULL==clazzInternalBufferUtil) { + _FatalError(env, "FatalError: Java_com_jogamp_nativewindow_impl_x11_X11Lib: can't use %s", ClazzNameInternalBufferUtil); + } + c = (*env)->FindClass(env, ClazzNameByteBuffer); + if(NULL==c) { + _FatalError(env, "FatalError: Java_com_jogamp_nativewindow_impl_x11_X11Lib: can't find %s", ClazzNameByteBuffer); + } + clazzByteBuffer = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + if(NULL==c) { + _FatalError(env, "FatalError: Java_com_jogamp_nativewindow_impl_x11_X11Lib: can't use %s", ClazzNameByteBuffer); + } + + cstrInternalBufferUtil = (*env)->GetStaticMethodID(env, clazzInternalBufferUtil, + ClazzNameInternalBufferUtilStaticCstrName, ClazzNameInternalBufferUtilStaticCstrSignature); + if(NULL==cstrInternalBufferUtil) { + _FatalError(env, "FatalError: Java_com_jogamp_nativewindow_impl_x11_X11Lib:: can't create %s.%s %s", + ClazzNameInternalBufferUtil, ClazzNameInternalBufferUtilStaticCstrName, ClazzNameInternalBufferUtilStaticCstrSignature); + } +} + +static void _throwNewRuntimeException(Display * unlockDisplay, JNIEnv *env, const char* msg, ...) +{ + char buffer[512]; + va_list ap; + + if(NULL!=unlockDisplay) { + XUnlockDisplay(unlockDisplay); + } + + _initClazzAccess(env); + + va_start(ap, msg); + vsnprintf(buffer, sizeof(buffer), msg, ap); + va_end(ap); + + (*env)->ThrowNew(env, clazzRuntimeException, buffer); +} + +static XIOErrorHandler origIOErrorHandler = NULL; +static JNIEnv * displayIOErrorHandlerJNIEnv = NULL; + +static int displayIOErrorHandler(Display *dpy) +{ + _FatalError(displayIOErrorHandlerJNIEnv, "Nativewindow X11 IOError: Display %p not available", dpy); + origIOErrorHandler(dpy); + return 0; +} + +static void displayIOErrorHandlerEnable(int onoff, JNIEnv * env) { + if(onoff) { + if(NULL==origIOErrorHandler) { + displayIOErrorHandlerJNIEnv = env; + origIOErrorHandler = XSetIOErrorHandler(displayIOErrorHandler); + } + } else { + XSetIOErrorHandler(origIOErrorHandler); + origIOErrorHandler = NULL; + displayIOErrorHandlerJNIEnv = NULL; + } +} + +JNIEXPORT void JNICALL +Java_com_jogamp_nativewindow_impl_x11_X11Util_installIOErrorHandler(JNIEnv *env, jclass _unused) { + displayIOErrorHandlerEnable(1, env); +} + +JNIEXPORT jlong JNICALL +Java_com_jogamp_nativewindow_impl_x11_X11Lib_dlopen(JNIEnv *env, jclass _unused, jstring name) { + const jbyte* chars; + void* res; + chars = (*env)->GetStringUTFChars(env, name, NULL); + res = dlopen(chars, RTLD_LAZY | RTLD_GLOBAL); + (*env)->ReleaseStringUTFChars(env, name, chars); + return (jlong) ((intptr_t) res); +} + +JNIEXPORT jlong JNICALL +Java_com_jogamp_nativewindow_impl_x11_X11Lib_dlsym(JNIEnv *env, jclass _unused, jstring name) { + const jbyte* chars; + void* res; + chars = (*env)->GetStringUTFChars(env, name, NULL); + res = dlsym(RTLD_DEFAULT, chars); + (*env)->ReleaseStringUTFChars(env, name, chars); + return (jlong) ((intptr_t) res); +} + +/* Java->C glue code: + * Java package: com.jogamp.nativewindow.impl.x11.X11Lib + * Java method: XVisualInfo XGetVisualInfo(long arg0, long arg1, XVisualInfo arg2, java.nio.IntBuffer arg3) + * C function: XVisualInfo * XGetVisualInfo(Display * , long, XVisualInfo * , int * ); + */ +JNIEXPORT jobject JNICALL +Java_com_jogamp_nativewindow_impl_x11_X11Lib_XGetVisualInfoCopied1__JJLjava_nio_ByteBuffer_2Ljava_lang_Object_2I(JNIEnv *env, jclass _unused, jlong arg0, jlong arg1, jobject arg2, jobject arg3, jint arg3_byte_offset) { + XVisualInfo * _ptr2 = NULL; + int * _ptr3 = NULL; + XVisualInfo * _res; + int count; + jobject jbyteSource; + jobject jbyteCopy; + if(0==arg0) { + _FatalError(env, "invalid display connection.."); + } + if (arg2 != NULL) { + _ptr2 = (XVisualInfo *) (((char*) (*env)->GetDirectBufferAddress(env, arg2)) + 0); + } + if (arg3 != NULL) { + _ptr3 = (int *) (((char*) (*env)->GetPrimitiveArrayCritical(env, arg3, NULL)) + arg3_byte_offset); + } + _res = XGetVisualInfo((Display *) (intptr_t) arg0, (long) arg1, (XVisualInfo *) _ptr2, (int *) _ptr3); + count = _ptr3[0]; + if (arg3 != NULL) { + (*env)->ReleasePrimitiveArrayCritical(env, arg3, _ptr3, 0); + } + if (_res == NULL) return NULL; + + _initClazzAccess(env); + + jbyteSource = (*env)->NewDirectByteBuffer(env, _res, count * sizeof(XVisualInfo)); + jbyteCopy = (*env)->CallStaticObjectMethod(env, + clazzInternalBufferUtil, cstrInternalBufferUtil, jbyteSource); + + XFree(_res); + + return jbyteCopy; +} + +JNIEXPORT jlong JNICALL +Java_com_jogamp_nativewindow_impl_x11_X11Lib_DefaultVisualID(JNIEnv *env, jclass _unused, jlong display, jint screen) { + jlong r; + if(0==display) { + _FatalError(env, "invalid display connection.."); + } + r = (jlong) XVisualIDFromVisual( DefaultVisual( (Display*) (intptr_t) display, screen ) ); + return r; +} + +/* Java->C glue code: + * Java package: com.jogamp.nativewindow.impl.x11.X11Lib + * Java method: void XLockDisplay(long display) + * C function: void XLockDisplay(Display * display); + */ +JNIEXPORT void JNICALL +Java_com_jogamp_nativewindow_impl_x11_X11Lib_XLockDisplay__J(JNIEnv *env, jclass _unused, jlong display) { + if(0==display) { + _FatalError(env, "invalid display connection.."); + } + XLockDisplay((Display *) (intptr_t) display); +} + +/* Java->C glue code: + * Java package: com.jogamp.nativewindow.impl.x11.X11Lib + * Java method: void XUnlockDisplay(long display) + * C function: void XUnlockDisplay(Display * display); + */ +JNIEXPORT void JNICALL +Java_com_jogamp_nativewindow_impl_x11_X11Lib_XUnlockDisplay__J(JNIEnv *env, jclass _unused, jlong display) { + if(0==display) { + _FatalError(env, "invalid display connection.."); + } + XUnlockDisplay((Display *) (intptr_t) display); +} + + +/* Java->C glue code: + * Java package: com.jogamp.nativewindow.impl.x11.X11Lib + * Java method: int XCloseDisplay(long display) + * C function: int XCloseDisplay(Display * display); + */ +JNIEXPORT jint JNICALL +Java_com_jogamp_nativewindow_impl_x11_X11Lib_XCloseDisplay__J(JNIEnv *env, jclass _unused, jlong display) { + int _res; + if(0==display) { + _FatalError(env, "invalid display connection.."); + } + _res = XCloseDisplay((Display *) (intptr_t) display); + return _res; +} + +/* + * Class: com_jogamp_nativewindow_impl_x11_X11Lib + * Method: CreateDummyWindow + * Signature: (JIJ)J +JNIEXPORT jlong JNICALL Java_com_jogamp_nativewindow_impl_x11_X11Lib_CreateDummyWindow + (JNIEnv *env, jobject obj, jlong display, jint screen_index, jlong visualID) +{ + Display * dpy = (Display *)(intptr_t)display; + int scrn_idx = (int)screen_index; + Window windowParent = 0; + Window window = 0; + + XVisualInfo visualTemplate; + XVisualInfo *pVisualQuery = NULL; + Visual *visual = NULL; + int depth; + + XSetWindowAttributes xswa; + unsigned long attrMask; + int n; + + Screen* scrn; + + if(NULL==dpy) { + _FatalError(env, "invalid display connection.."); + return 0; + } + + if(visualID<0) { + _throwNewRuntimeException(NULL, env, "invalid VisualID ..\n"); + return 0; + } + + XLockDisplay(dpy) ; + + XSync(dpy, False); + + scrn = ScreenOfDisplay(dpy, scrn_idx); + + // try given VisualID on screen + memset(&visualTemplate, 0, sizeof(XVisualInfo)); + visualTemplate.screen = scrn_idx; + visualTemplate.visualid = (VisualID)visualID; + pVisualQuery = XGetVisualInfo(dpy, VisualIDMask|VisualScreenMask, &visualTemplate,&n); + if(pVisualQuery!=NULL) { + visual = pVisualQuery->visual; + depth = pVisualQuery->depth; + visualID = (jlong)pVisualQuery->visualid; + XFree(pVisualQuery); + pVisualQuery=NULL; + } + DBG_PRINT5( "X11: [CreateWindow] trying given (dpy %p, screen %d, visualID: %d, parent %p) found: %p\n", dpy, scrn_idx, (int)visualID, windowParent, visual); + + if (visual==NULL) + { + _throwNewRuntimeException(dpy, env, "could not query Visual by given VisualID, bail out!\n"); + return 0; + } + + if(pVisualQuery!=NULL) { + XFree(pVisualQuery); + pVisualQuery=NULL; + } + + if(0==windowParent) { + windowParent = XRootWindowOfScreen(scrn); + } + + attrMask = (CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect) ; + + memset(&xswa, 0, sizeof(xswa)); + xswa.override_redirect = True; // not decorated + xswa.border_pixel = 0; + xswa.background_pixel = 0; + xswa.event_mask = 0 ; // no events + xswa.colormap = XCreateColormap(dpy, + XRootWindow(dpy, scrn_idx), + visual, + AllocNone); + + window = XCreateWindow(dpy, + windowParent, + 0, 0, + 64, 64, + 0, // border width + depth, + InputOutput, + visual, + attrMask, + &xswa); + + XSync(dpy, False); + + XUnlockDisplay(dpy) ; + + DBG_PRINT2( "X11: [CreateWindow] created window %p on display %p\n", window, dpy); + + return (jlong) window; +} + */ + + +/* + * Class: com_jogamp_nativewindow_impl_x11_X11Lib + * Method: DestroyDummyWindow + * Signature: (JJ)V +JNIEXPORT void JNICALL Java_com_jogamp_nativewindow_impl_x11_X11Lib_DestroyDummyWindow + (JNIEnv *env, jobject obj, jlong display, jlong window) +{ + Display * dpy = (Display *)(intptr_t)display; + Window w = (Window) window; + + if(NULL==dpy) { + _throwNewRuntimeException(NULL, env, "invalid display connection..\n"); + return; + } + XLockDisplay(dpy) ; + + XSync(dpy, False); + XUnmapWindow(dpy, w); + XSync(dpy, False); + XDestroyWindow(dpy, w); + XSync(dpy, False); + + XUnlockDisplay(dpy) ; +} + */ + diff --git a/src/newt/classes/com/jogamp/newt/x11/X11Display.java b/src/newt/classes/com/jogamp/newt/x11/X11Display.java index b8eb80b39..5fd6d9640 100755 --- a/src/newt/classes/com/jogamp/newt/x11/X11Display.java +++ b/src/newt/classes/com/jogamp/newt/x11/X11Display.java @@ -61,7 +61,7 @@ public class X11Display extends Display { } protected void createNative() { - long handle= X11Util.getThreadLocalDisplay(name); + long handle= X11Util.createThreadLocalDisplay(name); if (handle == 0 ) { throw new RuntimeException("Error creating display: "+name); } @@ -75,9 +75,7 @@ public class X11Display extends Display { } protected void closeNative() { - if(0==X11Util.closeThreadLocalDisplay(name)) { - throw new NativeWindowException(this+" was not mapped"); - } + X11Util.closeThreadLocalDisplay(name); } protected void dispatchMessages() { diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index 0fccc94bb..33c5324e2 100755 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -149,6 +149,19 @@ static jint X11KeySym2NewtVKey(KeySym keySym) { return keySym; } +static void _FatalError(JNIEnv *env, const char* msg, ...) +{ + char buffer[512]; + va_list ap; + + va_start(ap, msg); + vsnprintf(buffer, sizeof(buffer), msg, ap); + va_end(ap); + + fprintf(stderr, buffer); + (*env)->FatalError(env, buffer); +} + static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException"; static jclass runtimeExceptionClz=NULL; @@ -217,26 +230,6 @@ static void displayDispatchErrorHandlerEnable(int onoff) { } } -static XIOErrorHandler origIOErrorHandler = NULL; - -static int displayDispatchIOErrorHandler(Display *dpy) -{ - fprintf(stderr, "Fatal: NEWT X11 IOError: Display %p not available\n", dpy); - return 0; -} - -static void displayDispatchIOErrorHandlerEnable(int onoff) { - if(onoff) { - if(NULL==origIOErrorHandler) { - origIOErrorHandler = XSetIOErrorHandler(displayDispatchIOErrorHandler); - } - } else { - XSetIOErrorHandler(origIOErrorHandler); - origIOErrorHandler = NULL; - } -} - - /* * Class: com_jogamp_newt_x11_X11Display * Method: initIDs @@ -259,28 +252,24 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_x11_X11Display_initIDs if(NULL==newtWindowClz) { c = (*env)->FindClass(env, ClazzNameNewtWindow); if(NULL==c) { - fprintf(stderr, "FatalError: NEWT X11Window: can't find %s\n", ClazzNameNewtWindow); - return JNI_FALSE; + _FatalError(env, "NEWT X11Window: can't find %s", ClazzNameNewtWindow); } newtWindowClz = (jclass)(*env)->NewGlobalRef(env, c); (*env)->DeleteLocalRef(env, c); if(NULL==newtWindowClz) { - fprintf(stderr, "FatalError: NEWT X11Window: can't use %s\n", ClazzNameNewtWindow); - return JNI_FALSE; + _FatalError(env, "NEWT X11Window: can't use %s", ClazzNameNewtWindow); } } if(NULL==runtimeExceptionClz) { c = (*env)->FindClass(env, ClazzNameRuntimeException); if(NULL==c) { - fprintf(stderr, "FatalError: NEWT X11Window: can't find %s\n", ClazzNameRuntimeException); - return JNI_FALSE; + _FatalError(env, "NEWT X11Window: can't find %s", ClazzNameRuntimeException); } runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c); (*env)->DeleteLocalRef(env, c); if(NULL==runtimeExceptionClz) { - fprintf(stderr, "FatalError: NEWT X11Window: can't use %s\n", ClazzNameRuntimeException); - return JNI_FALSE; + _FatalError(env, "NEWT X11Window: can't use %s", ClazzNameRuntimeException); } } @@ -297,7 +286,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_x11_X11Display_LockDisplay { Display * dpy = (Display *)(intptr_t)display; if(dpy==NULL) { - _throwNewRuntimeException(NULL, env, "given display connection is NULL\n"); + _FatalError(env, "invalid display connection.."); } XLockDisplay(dpy) ; DBG_PRINT1( "X11: LockDisplay 0x%X\n", dpy); @@ -314,7 +303,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_x11_X11Display_UnlockDisplay { Display * dpy = (Display *)(intptr_t)display; if(dpy==NULL) { - _throwNewRuntimeException(NULL, env, "given display connection is NULL\n"); + _FatalError(env, "invalid display connection.."); } XUnlockDisplay(dpy) ; DBG_PRINT1( "X11: UnlockDisplay 0x%X\n", dpy); @@ -334,7 +323,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_x11_X11Display_CompleteDisplay jlong windowDeleteAtom; if(dpy==NULL) { - _throwNewRuntimeException(NULL, env, "given display connection is NULL\n"); + _FatalError(env, "invalid display connection.."); } XLockDisplay(dpy) ; @@ -447,8 +436,6 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_x11_X11Display_DispatchMessages return; } - displayDispatchIOErrorHandlerEnable(1); - // Periodically take a break while( num_events > 0 ) { jobject jwindow = NULL; @@ -462,7 +449,6 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_x11_X11Display_DispatchMessages // num_events = XPending(dpy); // XEventsQueued(dpy, QueuedAfterFlush); // I/O Flush .. // num_events = XEventsQueued(dpy, QueuedAlready); // Better, no I/O .. if ( 0 >= XEventsQueued(dpy, QueuedAlready) ) { - displayDispatchIOErrorHandlerEnable(0); XUnlockDisplay(dpy) ; return; } @@ -470,8 +456,6 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_x11_X11Display_DispatchMessages XNextEvent(dpy, &evt); num_events--; - displayDispatchIOErrorHandlerEnable(0); - if( 0==evt.xany.window ) { _throwNewRuntimeException(dpy, env, "event window NULL, bail out!\n"); return ; @@ -606,8 +590,7 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_x11_X11Screen_GetScreen Screen * scrn= NULL; if(dpy==NULL) { - _throwNewRuntimeException(NULL, env, "invalid display connection..\n"); - return 0; + _FatalError(env, "invalid display connection.."); } XLockDisplay(dpy); @@ -698,8 +681,7 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_x11_X11Window_CreateWindow DBG_PRINT4( "X11: CreateWindow %x/%d %dx%d\n", x, y, width, height); if(dpy==NULL) { - _throwNewRuntimeException(NULL, env, "invalid display connection..\n"); - return 0; + _FatalError(env, "invalid display connection.."); } if(visualID<0) { @@ -711,7 +693,7 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_x11_X11Window_CreateWindow XSync(dpy, False); - scrn = ScreenOfDisplay(dpy, screen_index); + scrn = ScreenOfDisplay(dpy, scrn_idx); // try given VisualID on screen memset(&visualTemplate, 0, sizeof(XVisualInfo)); @@ -809,8 +791,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_x11_X11Window_CloseWindow jobject jwindow; if(dpy==NULL) { - _throwNewRuntimeException(NULL, env, "invalid display connection..\n"); - return; + _FatalError(env, "invalid display connection.."); } XLockDisplay(dpy) ; @@ -854,8 +835,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_x11_X11Window_setVisible0 DBG_PRINT1( "X11: setVisible0 vis %d\n", visible); if(dpy==NULL) { - _throwNewRuntimeException(NULL, env, "invalid display connection..\n"); - return; + _FatalError(env, "invalid display connection.."); } XLockDisplay(dpy) ; @@ -903,8 +883,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_x11_X11Window_setSize0 DBG_PRINT6( "X11: setSize0 %d/%d %dx%d, dec %d, vis %d\n", x, y, width, height, decorationToggle, setVisible); if(dpy==NULL) { - _throwNewRuntimeException(NULL, env, "invalid display connection..\n"); - return; + _FatalError(env, "invalid display connection.."); } XLockDisplay(dpy) ; @@ -963,8 +942,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_x11_X11Window_setPosition0 DBG_PRINT2( "X11: setPos0 . XConfigureWindow %d/%d\n", x, y); if(dpy==NULL) { - _throwNewRuntimeException(NULL, env, "invalid display connection..\n"); - return; + _FatalError(env, "invalid display connection.."); } XLockDisplay(dpy) ; |