From 72a84b422327c6abb688339419d3552ec0e5c70c Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Mon, 9 Jul 2012 17:07:02 +0200 Subject: EGLGraphicsDevice adds desctruction callback and nativeDisplayID; EGLDisplayUtil adds creation of EGLGraphicsDevice. Due to EGL's location in JOGL, supporting destruction of an EGLGraphicsDevice is solved (hack) temporary by passing an eglTerminate callback to it's ctor. Using EGLGraphicsDevice's close() method to also issue eglTerminate() simplifies the code. In future we shall move EGL to nativewindow! --- .../classes/jogamp/opengl/egl/EGLDisplayUtil.java | 95 ++++++++++++++++++---- .../classes/jogamp/opengl/egl/EGLDrawable.java | 74 ++++++++--------- .../jogamp/opengl/egl/EGLDrawableFactory.java | 23 ++---- .../egl/EGLGraphicsConfigurationFactory.java | 34 ++++---- 4 files changed, 133 insertions(+), 93 deletions(-) (limited to 'src/jogl/classes/jogamp/opengl') diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java index e09400c09..7f10d3bd9 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java @@ -30,12 +30,15 @@ package jogamp.opengl.egl; import java.nio.IntBuffer; +import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; +import javax.media.opengl.GLException; import jogamp.opengl.Debug; import com.jogamp.common.util.LongIntHashMap; +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; /** * This implementation provides recursive calls to @@ -67,23 +70,6 @@ public class EGLDisplayUtil { return eglDisplay; } - public static long eglGetDisplay(NativeSurface surface, boolean allowFallBackToDefault) { - final long nDisplay; - if( NativeWindowFactory.TYPE_WINDOWS.equals(NativeWindowFactory.getNativeWindowType(false)) ) { - nDisplay = surface.getSurfaceHandle(); // don't even ask .. - } else { - nDisplay = surface.getDisplayHandle(); // 0 == EGL.EGL_DEFAULT_DISPLAY - } - long eglDisplay = EGLDisplayUtil.eglGetDisplay(nDisplay); - if (eglDisplay == EGL.EGL_NO_DISPLAY && nDisplay != EGL.EGL_DEFAULT_DISPLAY && allowFallBackToDefault) { - if(DEBUG) { - System.err.println("EGLDisplayUtil.eglGetDisplay(): Fall back to EGL_DEFAULT_DISPLAY"); - } - eglDisplay = EGLDisplayUtil.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY); - } - return eglDisplay; - } - public static synchronized boolean eglInitialize(long eglDisplay, int[] major, int major_offset, int[] minor, int minor_offset) { final boolean res; final int refCnt = eglDisplayCounter.get(eglDisplay) + 1; // 0 + 1 = 1 -> 1st init @@ -99,7 +85,19 @@ public class EGLDisplayUtil { return res; } + /** + * + * @param eglDisplay + * @param major + * @param minor + * @return true if the eglDisplay is valid and it's reference counter becomes one and {@link EGL#eglTerminate(long)} was successful, otherwise false + * + * @see EGL#eglInitialize(long, int[], int, int[], int)} + */ public static synchronized boolean eglInitialize(long eglDisplay, IntBuffer major, IntBuffer minor) { + if( EGL.EGL_NO_DISPLAY == eglDisplay) { + return false; + } final boolean res; final int refCnt = eglDisplayCounter.get(eglDisplay) + 1; // 0 + 1 = 1 -> 1st init if(1==refCnt) { // only initialize once @@ -114,7 +112,14 @@ public class EGLDisplayUtil { return res; } + /** + * @param eglDisplay the EGL display handle + * @return true if the eglDisplay is valid and it's reference counter becomes zero and {@link EGL#eglTerminate(long)} was successful, otherwise false + */ public static synchronized boolean eglTerminate(long eglDisplay) { + if( EGL.EGL_NO_DISPLAY == eglDisplay) { + return false; + } final boolean res; final int refCnt = eglDisplayCounter.get(eglDisplay) - 1; // 1 - 1 = 0 -> final terminate if(0==refCnt) { // no terminate if still in use or already terminated @@ -130,4 +135,60 @@ public class EGLDisplayUtil { } return res; } + + public static final EGLGraphicsDevice.EGLTerminateCallback eglTerminateCallback = new EGLGraphicsDevice.EGLTerminateCallback() { + public void eglTerminate(long eglDisplayHandle) { + EGLDisplayUtil.eglTerminate(eglDisplayHandle); + } + }; + + /** + * @param nativeDisplayID + * @param connection + * @param unitID + * @return an initialized EGLGraphicsDevice + * @throws GLException if {@link EGL#eglGetDisplay(long)} or {@link EGL#eglInitialize(long, int[], int, int[], int)} fails + * @see EGLGraphicsDevice#EGLGraphicsDevice(long, long, String, int, com.jogamp.nativewindow.egl.EGLGraphicsDevice.EGLTerminateCallback) + */ + public static EGLGraphicsDevice eglCreateEGLGraphicsDevice(long nativeDisplayID, String connection, int unitID) { + long eglDisplay = EGLDisplayUtil.eglGetDisplay(nativeDisplayID); + if (eglDisplay == EGL.EGL_NO_DISPLAY) { + throw new GLException("Failed to created EGL display: 0x"+Long.toHexString(nativeDisplayID)+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } + if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) { + throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } + return new EGLGraphicsDevice(nativeDisplayID, eglDisplay, connection, unitID, eglTerminateCallback); + } + + /** + * @param surface + * @param allowFallBackToDefault + * @return an initialized EGLGraphicsDevice + * @throws GLException if {@link EGL#eglGetDisplay(long)} or {@link EGL#eglInitialize(long, int[], int, int[], int)} fails + */ + public static EGLGraphicsDevice eglCreateEGLGraphicsDevice(NativeSurface surface, boolean allowFallBackToDefault) { + long nativeDisplayID; + if( NativeWindowFactory.TYPE_WINDOWS.equals(NativeWindowFactory.getNativeWindowType(false)) ) { + nativeDisplayID = surface.getSurfaceHandle(); // don't even ask .. + } else { + nativeDisplayID = surface.getDisplayHandle(); // 0 == EGL.EGL_DEFAULT_DISPLAY + } + long eglDisplay = EGLDisplayUtil.eglGetDisplay(nativeDisplayID); + if (eglDisplay == EGL.EGL_NO_DISPLAY && nativeDisplayID != EGL.EGL_DEFAULT_DISPLAY && allowFallBackToDefault) { + if(DEBUG) { + System.err.println("EGLDisplayUtil.eglGetDisplay(): Fall back to EGL_DEFAULT_DISPLAY"); + } + nativeDisplayID = EGL.EGL_DEFAULT_DISPLAY; + eglDisplay = EGLDisplayUtil.eglGetDisplay(nativeDisplayID); + } + if (eglDisplay == EGL.EGL_NO_DISPLAY) { + throw new GLException("Failed to created EGL display: "+surface+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } + if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) { + throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } + final AbstractGraphicsDevice adevice = surface.getGraphicsConfiguration().getScreen().getDevice(); + return new EGLGraphicsDevice(nativeDisplayID, eglDisplay, adevice.getConnection(), adevice.getUnitID(), eglTerminateCallback); + } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java index 491f22119..d777c4f04 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java @@ -46,34 +46,34 @@ import javax.media.opengl.*; import com.jogamp.nativewindow.egl.*; public abstract class EGLDrawable extends GLDrawableImpl { - protected boolean ownEGLDisplay = false; // for destruction - protected boolean ownEGLSurface = false; // for destruction + private boolean ownEGLDisplay = false; // for destruction + private boolean ownEGLSurface = false; // for destruction private EGLGraphicsConfiguration eglConfig; - protected long eglDisplay; - protected long eglSurface; + private EGLGraphicsDevice eglDevice; + private long eglSurface; protected EGLDrawable(EGLDrawableFactory factory, NativeSurface component) throws GLException { super(factory, component, false); eglSurface=EGL.EGL_NO_SURFACE; - eglDisplay=0; + eglDevice=null; } - public long getDisplay() { - return eglDisplay; + public final long getDisplay() { + return null != eglDevice ? eglDevice.getHandle() : 0; } @Override - public long getHandle() { + public final long getHandle() { return eglSurface; } - public EGLGraphicsConfiguration getGraphicsConfiguration() { + public final EGLGraphicsConfiguration getGraphicsConfiguration() { return eglConfig; } @Override - public GLCapabilitiesImmutable getChosenGLCapabilities() { + public final GLCapabilitiesImmutable getChosenGLCapabilities() { return (null==eglConfig)?super.getChosenGLCapabilities():(GLCapabilitiesImmutable)eglConfig.getChosenCapabilities(); } @@ -82,17 +82,17 @@ public abstract class EGLDrawable extends GLDrawableImpl { protected abstract long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle); - private void recreateSurface() { + private final void recreateSurface() { // create a new EGLSurface .. if(EGL.EGL_NO_SURFACE!=eglSurface) { - EGL.eglDestroySurface(eglDisplay, eglSurface); + EGL.eglDestroySurface(eglDevice.getHandle(), eglSurface); } if(DEBUG) { - System.err.println(getThreadName() + ": createSurface using eglDisplay "+toHexString(eglDisplay)+", "+eglConfig); + System.err.println(getThreadName() + ": createSurface using "+eglDevice+", "+eglConfig); } - eglSurface = createSurface(eglDisplay, eglConfig.getNativeConfig(), surface.getSurfaceHandle()); + eglSurface = createSurface(eglDevice.getHandle(), eglConfig.getNativeConfig(), surface.getSurfaceHandle()); int eglError0 = EGL.EGL_SUCCESS; if (EGL.EGL_NO_SURFACE == eglSurface) { eglError0 = EGL.eglGetError(); @@ -105,7 +105,7 @@ public abstract class EGLDrawable extends GLDrawableImpl { if(DEBUG) { System.err.println(getThreadName() + ": Info: Creation of window surface w/ surface handle failed: "+eglConfig+", error "+toHexString(eglError0)+", retry w/ windowHandle"); } - eglSurface = createSurface(eglDisplay, eglConfig.getNativeConfig(), nw.getWindowHandle()); + eglSurface = createSurface(eglDevice.getHandle(), eglConfig.getNativeConfig(), nw.getWindowHandle()); if (EGL.EGL_NO_SURFACE == eglSurface) { eglError0 = EGL.eglGetError(); } @@ -130,7 +130,7 @@ public abstract class EGLDrawable extends GLDrawableImpl { } @Override - protected void setRealizedImpl() { + protected final void setRealizedImpl() { if (realized) { AbstractGraphicsConfiguration aConfig = surface.getGraphicsConfiguration(); AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice(); @@ -139,9 +139,10 @@ public abstract class EGLDrawable extends GLDrawableImpl { System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): using existing EGL config - START"); } // just fetch the data .. trust but verify .. - eglDisplay = aDevice.getHandle(); - if (eglDisplay == EGL.EGL_NO_DISPLAY) { - throw new GLException("Invalid EGL display in EGLGraphicsDevice from "+aDevice); + ownEGLDisplay = false; + eglDevice = (EGLGraphicsDevice) aDevice; + if (eglDevice.getHandle() == EGL.EGL_NO_DISPLAY) { + throw new GLException("Invalid EGL display in EGLGraphicsDevice "+eglDevice); } if(aConfig instanceof EGLGraphicsConfiguration) { eglConfig = (EGLGraphicsConfiguration) aConfig; // done .. @@ -151,12 +152,13 @@ public abstract class EGLDrawable extends GLDrawableImpl { int[] tmp = new int[1]; if ( 0 != surface.getSurfaceHandle() && - EGL.eglQuerySurface(eglDisplay, surface.getSurfaceHandle(), EGL.EGL_CONFIG_ID, tmp, 0) ) { + EGL.eglQuerySurface(eglDevice.getHandle(), surface.getSurfaceHandle(), EGL.EGL_CONFIG_ID, tmp, 0) ) { // surface holds static EGLSurface eglSurface = surface.getSurfaceHandle(); if(DEBUG) { System.err.println(getThreadName() + ": setSurface re-using component's EGLSurface: handle "+toHexString(eglSurface)); } + ownEGLSurface=false; } else { // EGLSurface is ours - subsequent updateHandle() will issue recreateSurface(); ownEGLSurface=true; @@ -173,35 +175,28 @@ public abstract class EGLDrawable extends GLDrawableImpl { // EGLSurface is ours .. ownEGLSurface=true; - eglDisplay = EGLDisplayUtil.eglGetDisplay(surface, true); - if (eglDisplay == EGL.EGL_NO_DISPLAY) { - throw new GLException("Failed to created EGL display: "+surface+", "+aDevice+", error "+toHexString(EGL.eglGetError())); - } - if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) { - throw new GLException("eglInitialize failed"+", error "+Integer.toHexString(EGL.eglGetError())); - } - EGLGraphicsDevice e = new EGLGraphicsDevice(eglDisplay, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); - AbstractGraphicsScreen s = new DefaultGraphicsScreen(e, aConfig.getScreen().getIndex()); + eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface, true); + AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex()); final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities(); if(aConfig instanceof EGLGraphicsConfiguration) { final EGLGLCapabilities capsChosen = (EGLGLCapabilities) aConfig.getChosenCapabilities(); if(0 == capsChosen.getEGLConfig()) { // 'refresh' the native EGLConfig handle - capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDisplay, capsChosen.getEGLConfigID())); + capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDevice.getHandle(), capsChosen.getEGLConfigID())); if(0 == capsChosen.getEGLConfig()) { throw new GLException("Refreshing native EGLConfig handle failed: "+capsChosen+" of "+aConfig); } } - eglConfig = new EGLGraphicsConfiguration(s, capsChosen, capsRequested, null); + eglConfig = new EGLGraphicsConfiguration(eglScreen, capsChosen, capsRequested, null); if(DEBUG) { System.err.println(getThreadName() + ": Reusing chosenCaps: "+eglConfig); } } else { eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( - capsRequested, capsRequested, null, s, aConfig.getVisualID(VIDType.NATIVE), false); + capsRequested, capsRequested, null, eglScreen, aConfig.getVisualID(VIDType.NATIVE), false); if (null == eglConfig) { - throw new GLException("Couldn't create EGLGraphicsConfiguration from "+s); + throw new GLException("Couldn't create EGLGraphicsConfiguration from "+eglScreen); } else if(DEBUG) { System.err.println(getThreadName() + ": Chosen eglConfig: "+eglConfig); } @@ -213,25 +208,23 @@ public abstract class EGLDrawable extends GLDrawableImpl { } } else if (ownEGLSurface && eglSurface != EGL.EGL_NO_SURFACE) { if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealized(false): ownDisplay "+ownEGLDisplay+", ownSurface "+ownEGLSurface+", eglDisplay: "+toHexString(eglDisplay)+", eglSurface: "+toHexString(eglSurface)); + System.err.println(getThreadName() + ": EGLDrawable.setRealized(false): ownDisplay "+ownEGLDisplay+", ownSurface "+ownEGLSurface+", "+eglDevice+", eglSurface: "+toHexString(eglSurface)); } // Destroy the window surface - if (!EGL.eglDestroySurface(eglDisplay, eglSurface)) { + if (!EGL.eglDestroySurface(eglDevice.getHandle(), eglSurface)) { throw new GLException("Error destroying window surface (eglDestroySurface)"); } eglSurface = EGL.EGL_NO_SURFACE; - if (ownEGLDisplay && EGL.EGL_NO_DISPLAY!=eglDisplay) { - EGLDisplayUtil.eglTerminate(eglDisplay); - } - eglDisplay=EGL.EGL_NO_DISPLAY; eglConfig=null; + eglDevice.close(); + eglDevice=null; } } @Override protected final void swapBuffersImpl() { // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers() - if(!EGL.eglSwapBuffers(eglDisplay, eglSurface)) { + if(!EGL.eglSwapBuffers(eglDevice.getHandle(), eglSurface)) { throw new GLException("Error swapping buffers, eglError "+toHexString(EGL.eglGetError())+", "+this); } } @@ -270,6 +263,7 @@ public abstract class EGLDrawable extends GLDrawableImpl { public String toString() { return getClass().getName()+"[realized "+isRealized()+ ",\n\tfactory "+getFactory()+ + ",\n\tdevice "+eglDevice+ ",\n\tsurface "+getNativeSurface()+ ",\n\teglSurface "+toHexString(eglSurface)+ ",\n\teglConfig "+eglConfig+ diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java index e4f6f0ef8..f4fa1f13f 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java @@ -184,10 +184,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { if(DEBUG) { System.err.println("EGLDrawableFactory.destroy("+shutdownType+"): "+sr.device.toString()); } - final long eglDisplay = sr.device.getHandle(); - if(EGL.EGL_NO_DISPLAY != eglDisplay) { - EGLDisplayUtil.eglTerminate(eglDisplay); - } + sr.device.close(); } sharedMap.clear(); sharedMap = null; @@ -282,22 +279,14 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { if(null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper) { return null; } - String connection = adevice.getConnection(); + final String connection = adevice.getConnection(); SharedResource sr; synchronized(sharedMap) { sr = sharedMap.get(connection); } if(null==sr) { - long eglDisplay = EGLDisplayUtil.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY); - if (eglDisplay == EGL.EGL_NO_DISPLAY) { - throw new GLException("Failed to created EGL default display: error 0x"+Integer.toHexString(EGL.eglGetError())); - } else if(DEBUG) { - System.err.println("EGLDrawableFactory.createShared: eglDisplay(EGL_DEFAULT_DISPLAY): 0x"+Long.toHexString(eglDisplay)); - } - if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) { - throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError())); - } - final EGLGraphicsDevice sharedDevice = new EGLGraphicsDevice(eglDisplay, connection, adevice.getUnitID()); + final EGLGraphicsDevice sharedDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, connection, adevice.getUnitID()); + // final boolean madeCurrentES1 = isEGLContextAvailable(sharedDevice, GLProfile.GLES1); // final boolean madeCurrentES2 = isEGLContextAvailable(sharedDevice, GLProfile.GLES2); final boolean madeCurrentES1 = true; // FIXME @@ -401,7 +390,9 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } @Override - protected NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) { + protected NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) { + final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq; + final EGLGraphicsDevice device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID()); WrappedSurface ns = new WrappedSurface(EGLGraphicsConfigurationFactory.createOffscreenGraphicsConfiguration(device, capsChosen, capsRequested, chooser)); ns.surfaceSizeChanged(width, height); return ns; diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java index 5ab2632c6..809e2b688 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java @@ -223,23 +223,17 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact throw new GLException("Null AbstractGraphicsDevice"); } - final long eglDisplay; + final EGLGraphicsDevice eglDevice; final boolean ownEGLDisplay; - if( !(absDevice instanceof EGLGraphicsDevice) ) { - eglDisplay = EGLDisplayUtil.eglGetDisplay(absDevice.getHandle()); - if (eglDisplay == EGL.EGL_NO_DISPLAY) { - throw new GLException("Could not get EGL display from: "+absDevice); - } - if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) { - throw new GLException("eglInitialize failed eglDisplay 0x"+Long.toHexString(eglDisplay)+", "+absDevice+", error 0x"+Integer.toHexString(EGL.eglGetError())); - } - ownEGLDisplay = true; - } else { - eglDisplay = absDevice.getHandle(); - if (eglDisplay == EGL.EGL_NO_DISPLAY) { - throw new GLException("Invalid EGL display: "+absDevice); + if( absDevice instanceof EGLGraphicsDevice ) { + eglDevice = (EGLGraphicsDevice) absDevice; + if (eglDevice.getHandle() == EGL.EGL_NO_DISPLAY) { + throw new GLException("Invalid EGL display: "+eglDevice); } ownEGLDisplay = false; + } else { + eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(absDevice.getHandle(), absDevice.getConnection(), absDevice.getUnitID()); + ownEGLDisplay = true; } EGLDrawableFactory factory = (EGLDrawableFactory) GLDrawableFactory.getEGLFactory(); @@ -248,7 +242,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact GLProfile glp = capsChosen.getGLProfile(); GLCapabilities fixedCaps; - EGLGraphicsConfiguration res = eglChooseConfig(eglDisplay, capsChosen, capsReq, chooser, absScreen, nativeVisualID, forceTransparentFlag); + EGLGraphicsConfiguration res = eglChooseConfig(eglDevice.getHandle(), capsChosen, capsReq, chooser, absScreen, nativeVisualID, forceTransparentFlag); if(null==res) { if(DEBUG) { System.err.println("eglChooseConfig failed with given capabilities "+capsChosen); @@ -267,7 +261,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact if(DEBUG) { System.err.println("trying fixed caps (1): "+fixedCaps); } - res = eglChooseConfig(eglDisplay, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false); + res = eglChooseConfig(eglDevice.getHandle(), fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false); } if(null==res) { // @@ -280,7 +274,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact if(DEBUG) { System.err.println("trying fixed caps (2): "+fixedCaps); } - res = eglChooseConfig(eglDisplay, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false); + res = eglChooseConfig(eglDevice.getHandle(), fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false); } if(null==res) { // @@ -295,14 +289,14 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact if(DEBUG) { System.err.println("trying fixed caps (3): "+fixedCaps); } - res = eglChooseConfig(eglDisplay, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false); + res = eglChooseConfig(eglDevice.getHandle(), fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false); } if(null==res) { throw new GLException("Graphics configuration failed [direct caps, eglGetConfig/chooser and fixed-caps(1-3)]"); } if(ownEGLDisplay) { - ((EGLGLCapabilities) res.getChosenCapabilities()).setEGLConfig(0); // eglDisplay: EOL - EGLDisplayUtil.eglTerminate(eglDisplay); + ((EGLGLCapabilities) res.getChosenCapabilities()).setEGLConfig(0); // eglDisplay: EOL + eglDevice.close(); } return res; } -- cgit v1.2.3 From 20bf031db719f7baa4c6e74734fc999061e08fe2 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Thu, 19 Jul 2012 21:15:10 +0200 Subject: Bug 599 - FBObject / Offscreen Support - Part 1 - New FBObject implementation handling FBO and it's attachments *** API CHANGE: Util -> Core *** while it's size and sample-count can be reconfigured on the fly. - com.jogamp.opengl.util.FBObject -> com.jogamp.opengl.FBObject - agnostic to texture unit - separate attachments using OO hierarchy reflecting FBO - handling MSAA and blitting - no FBO destruction for reconfig (attach/detach) - New GLFBODrawableImpl impl. an FBObject based GLDrawable - Instantiated by a dummy native surface (onscreen and invisible) hooked up to a dummy GLDrawable, which is the delegation for context creation. - Utilizies ProxySurface.UpstreamSurfaceHook for dummy surface avoiding specialization for native platforms. - TODO: Allow to utilize common surface interface as a dummy-surface to supporting API seperation of windowing/GL. The latter allows impl. of createGLDrawable(NativeSurface) with FBO. - New OffscreenAutoDrawable (extends GLAutoDrawableDelegate) for all offscreen drawables. Shall replace GLPbuffer. - New GLCapabilities*.isFBO() / setFBO(boolean) to request FBO offscreen, similar to isPBuffer(). Rule: if both are requested, FBO shall be favored. - GLContext adds raw FBO availability query (min. FBO avail), FBObject contains fine grained queries (TODO: Move parts to GLContext for efficiency). - Add framebuffer tracking, allowing fast querying: - GLBase/GLContext: public int getBoundFramebuffer(int target); public int getDefaultDrawFramebuffer(); public int getDefaultReadFramebuffer(); - GLContextImpl public final void setBoundFramebuffer(int target, int framebufferName) .. called by GL impl bind framebuffer - GL: getDefaultDrawFramebuffer(), getDefaultReadFramebuffer() Adding default framebuffer queries being issued by GL.glBindFramebuffer(target, 0) w/ a default framebuffer, o.e. zero. This allows a transparent use of a custom FBO even in case the applications attempts to reset FBO to zero. Value flow: GL <- GLContext <- GLDrawable, - GLCapabilities handle fbo/pbuffer seperate, don't disable the other - GLContext/GL track read/write framebuffer to be queried by FBObject to determine whether to bind/unbind a framebuffer - Test cases for multiple FBO w/ and w/o MSAA Other Features: - New interface ProxySurface.UpstreamSurfaceHook, allowing to hook an upstream surface of unknown type providing lifecycle and information (size, ..) callbacks. Used for all new dummy NativeSurface impl and SWT GLCanvas. - GLContext -> GLDrawable propagation context/drawable lifecycle via ProxySurface.UpstreamSurfaceHook allowing dynamic resources to react (create, init, ..) - contextRealized() - contextMadeCurrent() - SurfaceChangeable -> MutableSurface currently only contains setting the surface handle. TODO: May need to move ProxySurface.UpstreamSurfaceHook -> MutableSurface.UpstreamSurfaceHook, allowing other impl. classes (NEWT OffscreenWindow) to utilize the new upstream hookup mechanism - will allow FBO/Dummy window to work. - SWT GLCanvas using ProxySurface.UpstreamSurfaceHook for proper size propagation. - New GLAutoDrawable::getUpstreamWidget(), allowing GLEventListener to fetch the owning Java side UI element (NEWT, SWT, AWT, ..). - GLDrawableFactory: Removed createOffscreenSurface() - unused and not GL related - EGLDrawableFactory handles device/profile avail. mapping while actually creating context/drawable. This allows us to learn whether the ES context is software/hardware as well as FBO avail. - EGLDrawable: Removed secret buckets of EGL configs :) Employ native surface (X11, WGL, ..) to EGL 'mapping' in EGLDrawableFactory utilizing new EGLUpstreamSurfaceHook (implements ProxySurface.UpstreamSurfaceHook). Other Bugs: - Add CTX_OPTION_DEBUG to ctx/extension cache key since only a debug ctx may expose the ARB debug capability. This bug caused lack of ARB/AMD debug functionality. - Fix GLProfile deadlock (debug mode, w/ EGL/ES, no X11), dump availability information _after_ lock. - ImmModeSink draw(): Use GL's glDrawElements(..), don't cast for GL2ES1. Fixes use for GL2ES2. - Fix KeyEvent.getKeyChar() comment (-> only stable for keyTyped(..)) Misc: - Refined alot of API doc - New GLExtensions holds commonly used GL extension strings, allows better referencing and usage lookup. - Move GL (interface) decl. to GLBase - GLBuffers: Cleanup API doc (format, types) - TextureIO: Add PAM and PPM static suffix identifier - GLCapabilities getNumSamples() returns 0 if sampleBuffers is disabled, this seems to be more natural. - finalized a lot --- .gitignore | 5 +- doc/Platform.GLES.txt | 4 +- doc/TODO.txt | 11 +- etc/test.bat | 2 +- etc/test_dbg.bat | 2 +- make/config/jogl/gl-common.cfg | 13 + make/config/jogl/gl-if-CustomJavaCode-gl.java | 26 - .../config/jogl/gl-impl-CustomJavaCode-common.java | 53 +- .../jogl/gl-impl-CustomJavaCode-desktop.java | 25 +- .../jogl/gl-impl-CustomJavaCode-gl2_es2.java | 6 +- make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java | 56 +- make/config/jogl/gl-impl-CustomJavaCode-gles1.java | 66 +- make/config/jogl/gl-impl-CustomJavaCode-gles2.java | 63 +- make/scripts/java-win32-dbg.bat | 13 +- make/scripts/java-win32.bat | 4 +- make/scripts/java-win64-dbg.bat | 12 +- make/scripts/java-win64.bat | 3 +- make/scripts/tests-x32.bat | 3 +- make/scripts/tests-x64.bat | 5 +- make/scripts/tests.sh | 41 +- make/stub_includes/opengl/macosx-window-system.h | 2 +- .../jogamp/gluegen/opengl/BuildStaticGLInfo.java | 4 +- .../com/jogamp/gluegen/opengl/GLConfiguration.java | 10 +- .../com/jogamp/gluegen/opengl/GLEmitter.java | 18 +- .../gluegen/runtime/opengl/GLExtensionNames.java | 190 -- .../gluegen/runtime/opengl/GLNameResolver.java | 191 ++ .../runtime/opengl/GLProcAddressResolver.java | 4 +- src/jogl/classes/com/jogamp/opengl/FBObject.java | 1943 ++++++++++++++++++++ .../classes/com/jogamp/opengl/GLExtensions.java | 81 + .../classes/com/jogamp/opengl/JoglVersion.java | 18 +- .../com/jogamp/opengl/OffscreenAutoDrawable.java | 89 + .../classes/com/jogamp/opengl/swt/GLCanvas.java | 72 +- .../classes/com/jogamp/opengl/util/FBObject.java | 483 ----- .../classes/com/jogamp/opengl/util/GLBuffers.java | 179 +- .../com/jogamp/opengl/util/GLReadBufferUtil.java | 12 +- .../com/jogamp/opengl/util/ImmModeSink.java | 25 +- .../com/jogamp/opengl/util/awt/Screenshot.java | 3 +- .../com/jogamp/opengl/util/awt/TextRenderer.java | 3 +- .../com/jogamp/opengl/util/texture/Texture.java | 25 +- .../com/jogamp/opengl/util/texture/TextureIO.java | 8 + .../opengl/util/texture/TextureSequence.java | 1 - .../util/texture/spi/NetPbmTextureWriter.java | 6 +- .../media/opengl/DefaultGLCapabilitiesChooser.java | 5 +- .../classes/javax/media/opengl/GLAutoDrawable.java | 48 +- .../javax/media/opengl/GLAutoDrawableDelegate.java | 18 +- src/jogl/classes/javax/media/opengl/GLBase.java | 55 + .../classes/javax/media/opengl/GLCapabilities.java | 31 +- .../media/opengl/GLCapabilitiesImmutable.java | 6 +- src/jogl/classes/javax/media/opengl/GLContext.java | 94 +- .../javax/media/opengl/GLDrawableFactory.java | 84 +- src/jogl/classes/javax/media/opengl/GLProfile.java | 52 +- .../classes/javax/media/opengl/awt/GLCanvas.java | 7 +- .../classes/javax/media/opengl/awt/GLJPanel.java | 7 +- .../jogamp/graph/curve/opengl/VBORegion2PES2.java | 32 +- src/jogl/classes/jogamp/opengl/GLContextImpl.java | 190 +- .../jogamp/opengl/GLDebugMessageHandler.java | 22 +- .../jogamp/opengl/GLDrawableFactoryImpl.java | 234 ++- src/jogl/classes/jogamp/opengl/GLDrawableImpl.java | 47 +- .../classes/jogamp/opengl/GLFBODrawableImpl.java | 138 ++ .../jogamp/opengl/GLGraphicsConfigurationUtil.java | 66 +- src/jogl/classes/jogamp/opengl/GLPbufferImpl.java | 8 +- src/jogl/classes/jogamp/opengl/egl/EGLContext.java | 76 +- .../classes/jogamp/opengl/egl/EGLDisplayUtil.java | 27 +- .../classes/jogamp/opengl/egl/EGLDrawable.java | 214 +-- .../jogamp/opengl/egl/EGLDrawableFactory.java | 307 +++- .../opengl/egl/EGLGraphicsConfiguration.java | 2 +- .../egl/EGLGraphicsConfigurationFactory.java | 65 +- .../jogamp/opengl/egl/EGLOnscreenDrawable.java | 4 +- .../jogamp/opengl/egl/EGLPbufferDrawable.java | 34 +- .../jogamp/opengl/egl/EGLUpstreamSurfaceHook.java | 56 + .../jogamp/opengl/macosx/cgl/MacOSXCGLContext.java | 24 +- .../opengl/macosx/cgl/MacOSXCGLDrawable.java | 4 - .../macosx/cgl/MacOSXCGLDrawableFactory.java | 153 +- .../macosx/cgl/MacOSXCGLGraphicsConfiguration.java | 4 +- .../macosx/cgl/MacOSXExternalCGLContext.java | 3 +- .../macosx/cgl/MacOSXPbufferCGLDrawable.java | 12 +- .../jogamp/opengl/util/av/EGLMediaPlayerImpl.java | 8 +- .../windows/wgl/WindowsBitmapWGLDrawable.java | 6 +- .../windows/wgl/WindowsDummyWGLDrawable.java | 109 -- .../windows/wgl/WindowsExternalWGLContext.java | 3 +- .../windows/wgl/WindowsExternalWGLDrawable.java | 7 +- .../windows/wgl/WindowsPbufferWGLContext.java | 4 +- .../windows/wgl/WindowsPbufferWGLDrawable.java | 19 +- .../opengl/windows/wgl/WindowsWGLContext.java | 6 +- .../windows/wgl/WindowsWGLDrawableFactory.java | 130 +- .../wgl/WindowsWGLGraphicsConfiguration.java | 22 +- .../WindowsWGLGraphicsConfigurationFactory.java | 19 +- .../jogamp/opengl/x11/glx/X11DummyGLXDrawable.java | 102 - .../opengl/x11/glx/X11ExternalGLXContext.java | 12 +- .../opengl/x11/glx/X11ExternalGLXDrawable.java | 5 +- .../jogamp/opengl/x11/glx/X11GLXContext.java | 9 +- .../opengl/x11/glx/X11GLXDrawableFactory.java | 145 +- .../x11/glx/X11GLXGraphicsConfiguration.java | 29 +- .../glx/X11GLXGraphicsConfigurationFactory.java | 17 +- .../opengl/x11/glx/X11OnscreenGLXDrawable.java | 7 +- .../opengl/x11/glx/X11PbufferGLXDrawable.java | 18 +- .../opengl/x11/glx/X11PixmapGLXDrawable.java | 6 +- .../macosx/MacOSXWindowSystemInterface-pbuffer.m | 2 +- .../native/macosx/MacOSXWindowSystemInterface.m | 12 +- .../com/jogamp/nativewindow/WrappedSurface.java | 34 +- .../jogamp/nativewindow/egl/EGLGraphicsDevice.java | 42 +- .../com/jogamp/nativewindow/swt/SWTAccessor.java | 3 - .../jogamp/nativewindow/x11/X11GraphicsDevice.java | 36 +- .../jogamp/nativewindow/x11/X11GraphicsScreen.java | 8 +- .../media/nativewindow/AbstractGraphicsDevice.java | 27 +- .../media/nativewindow/DefaultGraphicsDevice.java | 13 + .../javax/media/nativewindow/MutableSurface.java | 44 + .../javax/media/nativewindow/ProxySurface.java | 127 +- .../media/nativewindow/SurfaceChangeable.java | 54 - .../jogamp/nativewindow/SurfaceUpdatedHelper.java | 4 +- .../nativewindow/jawt/macosx/MacOSXJAWTWindow.java | 21 +- .../jogamp/nativewindow/macosx/OSXUtil.java | 13 +- .../jogamp/nativewindow/windows/GDISurface.java | 51 +- src/nativewindow/native/macosx/OSXmisc.m | 52 +- src/newt/classes/com/jogamp/newt/Window.java | 16 +- .../classes/com/jogamp/newt/event/KeyEvent.java | 2 +- .../classes/com/jogamp/newt/opengl/GLWindow.java | 7 +- src/newt/classes/jogamp/newt/OffscreenWindow.java | 41 +- .../classes/jogamp/newt/driver/android/MD.java | 2 +- .../jogamp/newt/driver/macosx/MacWindow.java | 8 +- src/newt/native/NewtMacWindow.m | 6 +- .../test/junit/graph/TestTextRendererNEWT00.java | 2 +- .../graph/demos/GPURendererListenerBase01.java | 2 +- .../junit/graph/demos/ui/UIListenerBase01.java | 2 +- .../test/junit/jogl/acore/TestFBODrawableNEWT.java | 272 +++ .../test/junit/jogl/acore/TestFBOMRTNEWT01.java | 266 +++ .../junit/jogl/acore/TestFBOMix2DemosES2NEWT.java | 258 +++ .../jogl/acore/TestGLAutoDrawableDelegateNEWT.java | 2 +- .../acore/TestGLContextDrawableSwitchNEWT.java | 2 +- .../test/junit/jogl/acore/TestGLProfile01NEWT.java | 2 +- .../junit/jogl/acore/TestShutdownCompleteNEWT.java | 2 +- .../test/junit/jogl/caps/MultisampleDemoES1.java | 154 -- .../junit/jogl/caps/TestMultisampleES1AWT.java | 19 +- .../junit/jogl/caps/TestMultisampleES1NEWT.java | 20 +- .../junit/jogl/caps/TestMultisampleES2NEWT.java | 143 ++ .../opengl/test/junit/jogl/demos/es1/GearsES1.java | 19 +- .../junit/jogl/demos/es1/MultisampleDemoES1.java | 123 ++ .../test/junit/jogl/demos/es2/FBOMix2DemosES2.java | 309 ++++ .../opengl/test/junit/jogl/demos/es2/GearsES2.java | 39 +- .../junit/jogl/demos/es2/MultisampleDemoES2.java | 178 ++ .../test/junit/jogl/demos/es2/RedSquareES2.java | 48 +- .../jogl/demos/es2/TextureSequenceCubeES2.java | 9 +- .../test/junit/jogl/demos/es2/av/MovieCube.java | 5 +- .../test/junit/jogl/demos/es2/av/MovieSimple.java | 5 +- .../jogl/demos/es2/newt/TestGearsES2NEWT.java | 3 - .../jogl/demos/es2/newt/TestRedSquareES2NEWT.java | 7 +- .../junit/jogl/demos/es2/shader/mgl_default_xxx.fp | 10 + .../junit/jogl/demos/es2/shader/mgl_default_xxx.vp | 14 + .../junit/jogl/demos/es2/shader/texture02_xxx.fp | 20 + .../opengl/test/junit/jogl/demos/gl2/Gears.java | 18 +- .../jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java | 188 ++ .../demos/gl2/awt/TestGearsGLJPanelAWTBug450.java | 194 -- .../test/junit/jogl/glsl/TestFBOMRTNEWT01.java | 229 --- .../junit/jogl/glsl/TestGLSLShaderState01NEWT.java | 1 - .../junit/jogl/glsl/TestGLSLShaderState02NEWT.java | 1 - .../test/junit/jogl/offscreen/ReadBufferBase.java | 4 +- .../test/junit/jogl/offscreen/Surface2File.java | 2 +- .../test/junit/jogl/swt/TestSWTAccessor02GLn.java | 41 +- .../TestGLReadBufferUtilTextureIOWrite01AWT.java | 19 +- .../TestGLReadBufferUtilTextureIOWrite01NEWT.java | 36 +- .../TestGLReadBufferUtilTextureIOWrite02AWT.java | 20 +- .../TestGLReadBufferUtilTextureIOWrite02NEWT.java | 20 +- .../util/texture/TestPNGTextureFromFileAWT.java | 13 +- .../util/texture/TestPNGTextureFromFileNEWT.java | 11 +- .../jogamp/opengl/test/junit/util/UITestCase.java | 55 +- 165 files changed, 6996 insertions(+), 3008 deletions(-) delete mode 100644 src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLExtensionNames.java create mode 100644 src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLNameResolver.java create mode 100644 src/jogl/classes/com/jogamp/opengl/FBObject.java create mode 100644 src/jogl/classes/com/jogamp/opengl/GLExtensions.java create mode 100644 src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java delete mode 100644 src/jogl/classes/com/jogamp/opengl/util/FBObject.java create mode 100644 src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java create mode 100644 src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java delete mode 100644 src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java delete mode 100644 src/jogl/classes/jogamp/opengl/x11/glx/X11DummyGLXDrawable.java create mode 100644 src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java delete mode 100644 src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/caps/MultisampleDemoES1.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES2NEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/MultisampleDemoES1.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/MultisampleDemoES2.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.fp create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.vp create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture02_xxx.fp create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWTBug450.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestFBOMRTNEWT01.java (limited to 'src/jogl/classes/jogamp/opengl') diff --git a/.gitignore b/.gitignore index 6e3af642b..1cd3375b4 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,7 @@ javadoc_public build-temp make/temp* .idea/workspace.xml -**~ \ No newline at end of file +.settings/* +**~ +build* +make/lib/external/* diff --git a/doc/Platform.GLES.txt b/doc/Platform.GLES.txt index 0bcd3bc8b..901e040c4 100644 --- a/doc/Platform.GLES.txt +++ b/doc/Platform.GLES.txt @@ -33,7 +33,7 @@ a request for e.g. GL2ES2 will utilize the highest common desktop profile. ...> Linux: - PVRVFrame 2.09.29.0649 + PVRVFrame 2.09.29.0649, Version_REL_2.10 Debian Wheezy/testing x64, NV 290.10, 32bit libraries: OK GL_VENDOR Imagination Technologies (Host GL: `NVIDIA Corporation`) GL_RENDERER PowerVR PVRVFrame 8.1 SGX (Host GL: `GeForce GTX 460/PCI/SSE2`) @@ -75,7 +75,7 @@ Linux: Ubuntu 11.10 x64, AMD Catalyst 12.1, 64bit libraries, libgles2-mesa 7.11-0ubuntu3: Error (swrast error, null values) Windows: - PVRVFrame 2.09.29.0649 + PVRVFrame 2.09.29.0649, Version_REL_2.10 Windows7 64bit, NV 290.10, 32bit libraries: OK GL_VENDOR Imagination Technologies (Host GL: `NVIDIA Corporation`) GL_RENDERER PowerVR PVRVFrame 8.1 SGX (Host GL: `GeForce GTX 460/PCIe/SSE2`) diff --git a/doc/TODO.txt b/doc/TODO.txt index f86d31e4c..82f013265 100644 --- a/doc/TODO.txt +++ b/doc/TODO.txt @@ -1,16 +1,15 @@ WIP: +- GLPbuffer -> GLOffscreenAutoDrawable + - GLPbuffer GLDrawableFactory.createPbuffer() -> + GLOffscreenAutoDrawable GLDrawableFactory.createOffsceenAutoDrawable() + - Mark both deprecated! + Random, somewhat old to-do list: - Non-const array types must be properly released with JNI_COMMIT in order to see side effects if the array was copied. -- figure out how to deal with WGL entry points: - WINGDIAPI HGLRC WINAPI wglCreateLayerContext(HDC, int); - WINGDIAPI BOOL WINAPI wglUseFontBitmapsA(HDC, DWORD, DWORD, DWORD); - WINGDIAPI BOOL WINAPI wglUseFontBitmapsW(HDC, DWORD, DWORD, DWORD); - see commented-out section in make/stub_includes/win32/wingdi.h - - Need a disciplined mechanism for converting char* argument types. For example, many C functions accept a "char*" argument with the semantic that output data will be written into the buffer pointed to by the diff --git a/etc/test.bat b/etc/test.bat index 0c82233ca..d635c7e8f 100755 --- a/etc/test.bat +++ b/etc/test.bat @@ -1,7 +1,7 @@ set BLD_DIR=jar -set CP_ALL=.;%BLD_DIR%\gluegen-rt.jar;%BLD_DIR%\jogl.all.jar +set CP_ALL=.;%BLD_DIR%\gluegen-rt.jar;%BLD_DIR%\jogl-all.jar echo CP_ALL %CP_ALL% set X_ARGS="-Dsun.java2d.noddraw=true" "-Dsun.awt.noerasebackground=true" diff --git a/etc/test_dbg.bat b/etc/test_dbg.bat index 33bbb912b..209690758 100755 --- a/etc/test_dbg.bat +++ b/etc/test_dbg.bat @@ -1,7 +1,7 @@ set BLD_DIR=jar -set CP_ALL=.;%BLD_DIR%\gluegen-rt.jar;%BLD_DIR%\jogl.all.jar +set CP_ALL=.;%BLD_DIR%\gluegen-rt.jar;%BLD_DIR%\jogl-all.jar echo CP_ALL %CP_ALL% set D_ARGS="-Djogamp.debug=all" "-Dnativewindow.debug=all" "-Djogl.debug=all" "-Dnewt.debug=all" diff --git a/make/config/jogl/gl-common.cfg b/make/config/jogl/gl-common.cfg index 8af080ec8..9c5467583 100644 --- a/make/config/jogl/gl-common.cfg +++ b/make/config/jogl/gl-common.cfg @@ -481,6 +481,19 @@ JavaPrologue glGetString return _context.getGLVersion(); JavaPrologue glGetString } */ JavaPrologue glGetString } +# +# Allow special FBO GLContext/GLDrawable to reset to it's +# default FBO framebuffer. +# +JavaPrologue glBindFramebuffer if( 0 == framebuffer ) { +JavaPrologue glBindFramebuffer if( GL_FRAMEBUFFER == target || 0x8CA9 /* GL_DRAW_FRAMEBUFFER */ == target ) { +JavaPrologue glBindFramebuffer framebuffer = _context.getDefaultDrawFramebuffer(); +JavaPrologue glBindFramebuffer } else if( 0x8CA8 /* GL_READ_FRAMEBUFFER */ == target ) { +JavaPrologue glBindFramebuffer framebuffer = _context.getDefaultReadFramebuffer(); +JavaPrologue glBindFramebuffer } +JavaPrologue glBindFramebuffer } +JavaEpilogue glBindFramebuffer _context.setBoundFramebuffer(target, framebuffer); + # # Directives for Vertex Buffer Object and Pixel Buffer Object checking # diff --git a/make/config/jogl/gl-if-CustomJavaCode-gl.java b/make/config/jogl/gl-if-CustomJavaCode-gl.java index 77378aa45..9ea4f98b4 100644 --- a/make/config/jogl/gl-if-CustomJavaCode-gl.java +++ b/make/config/jogl/gl-if-CustomJavaCode-gl.java @@ -57,29 +57,3 @@ earmarked for ES 3.0 (hence kept in GL while fixing Bug 590) */ public static final int GL_HALF_FLOAT = 0x140B; - public void glClearDepth( double depth ); - - public void glDepthRange(double zNear, double zFar); - - /** - * @param target a GL buffer (VBO) target as used in {@link GL#glBindBuffer(int, int)}, ie {@link GL#GL_ELEMENT_ARRAY_BUFFER}, {@link GL#GL_ARRAY_BUFFER}, .. - * @return the GL buffer (VBO) name bound to a target via {@link GL#glBindBuffer(int, int)} or 0 if unbound. - */ - public int glGetBoundBuffer(int target); - - /** - * @param buffer a GL buffer name, generated with {@link GL#glGenBuffers(int, int[], int)} and used in {@link GL#glBindBuffer(int, int)}, {@link GL#glBufferData(int, long, java.nio.Buffer, int)} or {@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)} for example. - * @return the size of the given GL buffer - */ - public long glGetBufferSize(int buffer); - - /** - * @return true if a VBO is bound to {@link GL.GL_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false - */ - public boolean glIsVBOArrayEnabled(); - - /** - * @return true if a VBO is bound to {@link GL.GL_ELEMENT_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false - */ - public boolean glIsVBOElementArrayEnabled(); - diff --git a/make/config/jogl/gl-impl-CustomJavaCode-common.java b/make/config/jogl/gl-impl-CustomJavaCode-common.java index d552bc6e4..b05ba2643 100644 --- a/make/config/jogl/gl-impl-CustomJavaCode-common.java +++ b/make/config/jogl/gl-impl-CustomJavaCode-common.java @@ -1,48 +1,57 @@ + @Override public GLProfile getGLProfile() { return this.glProfile; } private final GLProfile glProfile; - public int glGetBoundBuffer(int target) { + @Override + public final int glGetBoundBuffer(int target) { return bufferStateTracker.getBoundBufferObject(target, this); } - public long glGetBufferSize(int buffer) { + @Override + public final long glGetBufferSize(int buffer) { return bufferSizeTracker.getDirectStateBufferSize(buffer, this); } - public boolean glIsVBOArrayEnabled() { + @Override + public final boolean glIsVBOArrayEnabled() { return checkArrayVBOEnabled(false); } - public boolean glIsVBOElementArrayEnabled() { + @Override + public final boolean glIsVBOElementArrayEnabled() { return checkElementVBOEnabled(false); } + @Override public final boolean isGL() { return true; } + @Override public final GL getGL() throws GLException { return this; } - public boolean isFunctionAvailable(String glFunctionName) { + @Override + public final boolean isFunctionAvailable(String glFunctionName) { return _context.isFunctionAvailable(glFunctionName); } - public boolean isExtensionAvailable(String glExtensionName) { + @Override + public final boolean isExtensionAvailable(String glExtensionName) { return _context.isExtensionAvailable(glExtensionName); } - public Object getExtension(String extensionName) { + @Override + public final Object getExtension(String extensionName) { // At this point we don't expose any extensions using this mechanism return null; } - /** Returns the context this GL object is associated with for better - error checking by DebugGL. */ - public GLContext getContext() { + @Override + public final GLContext getContext() { return _context; } @@ -51,18 +60,36 @@ /** * @see javax.media.opengl.GLContext#setSwapInterval(int) */ - public void setSwapInterval(int interval) { + @Override + public final void setSwapInterval(int interval) { _context.setSwapInterval(interval); } /** * @see javax.media.opengl.GLContext#getSwapInterval() */ - public int getSwapInterval() { + @Override + public final int getSwapInterval() { return _context.getSwapInterval(); } - public Object getPlatformGLExtensions() { + @Override + public final Object getPlatformGLExtensions() { return _context.getPlatformGLExtensions(); } + @Override + public final int getBoundFramebuffer(int target) { + return _context.getBoundFramebuffer(target); + } + + @Override + public final int getDefaultDrawFramebuffer() { + return _context.getDefaultDrawFramebuffer(); + } + + @Override + public final int getDefaultReadFramebuffer() { + return _context.getDefaultReadFramebuffer(); + } + diff --git a/make/config/jogl/gl-impl-CustomJavaCode-desktop.java b/make/config/jogl/gl-impl-CustomJavaCode-desktop.java index 33b0f1326..6a74b80a6 100644 --- a/make/config/jogl/gl-impl-CustomJavaCode-desktop.java +++ b/make/config/jogl/gl-impl-CustomJavaCode-desktop.java @@ -4,34 +4,42 @@ return GLBuffers.sizeof(this, imageSizeTemp, format, type, width, height, depth, pack) ; } + @Override public final boolean isGL4bc() { return _context.isGL4bc(); } + @Override public final boolean isGL4() { return _context.isGL4(); } + @Override public final boolean isGL3bc() { return _context.isGL3bc(); } + @Override public final boolean isGL3() { return _context.isGL3(); } + @Override public final boolean isGL2() { return _context.isGL2(); } + @Override public final boolean isGL2ES1() { return _context.isGL2ES1(); } + @Override public final boolean isGL2ES2() { return _context.isGL2ES2(); } + @Override public final boolean isGLES2Compatible() { return _context.isGLES2Compatible(); } @@ -40,10 +48,12 @@ return _context.isGL2GL3(); } + @Override public final boolean hasGLSL() { return _context.hasGLSL(); } + @Override public final GL4bc getGL4bc() throws GLException { if(!isGL4bc()) { throw new GLException("Not a GL4bc implementation"); @@ -51,6 +61,7 @@ return this; } + @Override public final GL4 getGL4() throws GLException { if(!isGL4()) { throw new GLException("Not a GL4 implementation"); @@ -58,6 +69,7 @@ return this; } + @Override public final GL3bc getGL3bc() throws GLException { if(!isGL3bc()) { throw new GLException("Not a GL3bc implementation"); @@ -65,6 +77,7 @@ return this; } + @Override public final GL3 getGL3() throws GLException { if(!isGL3()) { throw new GLException("Not a GL3 implementation"); @@ -72,6 +85,7 @@ return this; } + @Override public final GL2 getGL2() throws GLException { if(!isGL2()) { throw new GLException("Not a GL2 implementation"); @@ -79,6 +93,7 @@ return this; } + @Override public final GL2ES1 getGL2ES1() throws GLException { if(!isGL2ES1()) { throw new GLException("Not a GL2ES1 implementation"); @@ -86,6 +101,7 @@ return this; } + @Override public final GL2ES2 getGL2ES2() throws GLException { if(!isGL2ES2()) { throw new GLException("Not a GL2ES2 implementation"); @@ -93,6 +109,7 @@ return this; } + @Override public final GL2GL3 getGL2GL3() throws GLException { if(!isGL2GL3()) { throw new GLException("Not a GL2GL3 implementation"); @@ -100,26 +117,32 @@ return this; } + @Override public final boolean isGLES1() { return false; } + @Override public final boolean isGLES2() { return false; } + @Override public final boolean isGLES() { return false; } + @Override public final GLES1 getGLES1() throws GLException { throw new GLException("Not a GLES1 implementation"); } + @Override public final GLES2 getGLES2() throws GLException { throw new GLException("Not a GLES2 implementation"); } - public boolean isNPOTTextureAvailable() { + @Override + public final boolean isNPOTTextureAvailable() { return _context.isNPOTTextureAvailable(); } diff --git a/make/config/jogl/gl-impl-CustomJavaCode-gl2_es2.java b/make/config/jogl/gl-impl-CustomJavaCode-gl2_es2.java index b31a087e7..82b791208 100644 --- a/make/config/jogl/gl-impl-CustomJavaCode-gl2_es2.java +++ b/make/config/jogl/gl-impl-CustomJavaCode-gl2_es2.java @@ -1,4 +1,5 @@ - public void glVertexAttribPointer(GLArrayData array) { + @Override + public final void glVertexAttribPointer(GLArrayData array) { if(array.getComponentCount()==0) return; if(array.isVBO()) { glVertexAttribPointer(array.getLocation(), array.getComponentCount(), array.getComponentType(), @@ -9,7 +10,8 @@ } } - public void glUniform(GLUniformData data) { + @Override + public final void glUniform(GLUniformData data) { boolean done=false; if(data.isBuffer()) { Buffer buffer = data.getBuffer(); diff --git a/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java b/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java index 95aa7cc2c..e079a1a24 100644 --- a/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java +++ b/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java @@ -33,7 +33,7 @@ public GL4bcImpl(GLProfile glp, GLContextImpl context) { * Provides platform-independent access to the wglAllocateMemoryNV / * glXAllocateMemoryNV extension. */ -public java.nio.ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) { +public final java.nio.ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) { return _context.glAllocateMemoryNV(arg0, arg1, arg2, arg3); } @@ -52,7 +52,7 @@ private boolean haveGL15; private boolean haveGL21; private boolean haveARBVertexBufferObject; -private void initBufferObjectExtensionChecks() { +private final void initBufferObjectExtensionChecks() { if (bufferObjectExtensionsInitialized) return; bufferObjectExtensionsInitialized = true; @@ -63,12 +63,12 @@ private void initBufferObjectExtensionChecks() { haveARBVertexBufferObject = isExtensionAvailable("GL_ARB_vertex_buffer_object"); } -private boolean checkBufferObject(boolean extension1, - boolean extension2, - boolean extension3, - boolean enabled, - int state, - String kind, boolean throwException) { +private final boolean checkBufferObject(boolean extension1, + boolean extension2, + boolean extension3, + boolean enabled, + int state, + String kind, boolean throwException) { if (inBeginEndPair) { throw new GLException("May not call this between glBegin and glEnd"); } @@ -100,7 +100,7 @@ private boolean checkBufferObject(boolean extension1, return true; } -private boolean checkArrayVBODisabled(boolean throwException) { +private final boolean checkArrayVBODisabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(haveGL15, haveARBVertexBufferObject, @@ -110,7 +110,7 @@ private boolean checkArrayVBODisabled(boolean throwException) { "array vertex_buffer_object", throwException); } -private boolean checkArrayVBOEnabled(boolean throwException) { +private final boolean checkArrayVBOEnabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(haveGL15, haveARBVertexBufferObject, @@ -120,7 +120,7 @@ private boolean checkArrayVBOEnabled(boolean throwException) { "array vertex_buffer_object", throwException); } -private boolean checkElementVBODisabled(boolean throwException) { +private final boolean checkElementVBODisabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(haveGL15, haveARBVertexBufferObject, @@ -130,7 +130,7 @@ private boolean checkElementVBODisabled(boolean throwException) { "element vertex_buffer_object", throwException); } -private boolean checkElementVBOEnabled(boolean throwException) { +private final boolean checkElementVBOEnabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(haveGL15, haveARBVertexBufferObject, @@ -140,7 +140,7 @@ private boolean checkElementVBOEnabled(boolean throwException) { "element vertex_buffer_object", throwException); } -private boolean checkUnpackPBODisabled(boolean throwException) { +private final boolean checkUnpackPBODisabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(haveARBPixelBufferObject, haveEXTPixelBufferObject, @@ -150,7 +150,7 @@ private boolean checkUnpackPBODisabled(boolean throwException) { "unpack pixel_buffer_object", throwException); } -private boolean checkUnpackPBOEnabled(boolean throwException) { +private final boolean checkUnpackPBOEnabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(haveARBPixelBufferObject, haveEXTPixelBufferObject, @@ -160,7 +160,7 @@ private boolean checkUnpackPBOEnabled(boolean throwException) { "unpack pixel_buffer_object", throwException); } -private boolean checkPackPBODisabled(boolean throwException) { +private final boolean checkPackPBODisabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(haveARBPixelBufferObject, haveEXTPixelBufferObject, @@ -170,7 +170,7 @@ private boolean checkPackPBODisabled(boolean throwException) { "pack pixel_buffer_object", throwException); } -private boolean checkPackPBOEnabled(boolean throwException) { +private final boolean checkPackPBOEnabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(haveARBPixelBufferObject, haveEXTPixelBufferObject, @@ -180,18 +180,20 @@ private boolean checkPackPBOEnabled(boolean throwException) { "pack pixel_buffer_object", throwException); } -public boolean glIsPBOPackEnabled() { +@Override +public final boolean glIsPBOPackEnabled() { return checkPackPBOEnabled(false); } -public boolean glIsPBOUnpackEnabled() { +@Override +public final boolean glIsPBOUnpackEnabled() { return checkUnpackPBOEnabled(false); } -private HashMap arbMemCache = new HashMap(); +private final HashMap arbMemCache = new HashMap(); /** Entry point to C language function:
LPVOID glMapBuffer(GLenum target, GLenum access); */ -public java.nio.ByteBuffer glMapBuffer(int target, int access) { +public final java.nio.ByteBuffer glMapBuffer(int target, int access) { final long __addr_ = ((GL4bcProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBuffer; if (__addr_ == 0) { throw new GLException("Method \"glMapBuffer\" not available"); @@ -230,7 +232,7 @@ public java.nio.ByteBuffer glMapBuffer(int target, int access) { native private long dispatch_glMapBuffer(int target, int access, long glProcAddress); /** Entry point to C language function: GLvoid * {@native glMapNamedBufferEXT}(GLuint buffer, GLenum access);
Part of GL_EXT_direct_state_access */ -public java.nio.ByteBuffer glMapNamedBufferEXT(int bufferName, int access) { +public final java.nio.ByteBuffer glMapNamedBufferEXT(int bufferName, int access) { final long __addr_ = ((GL4bcProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapNamedBufferEXT; if (__addr_ == 0) { throw new GLException("Method \"glMapNamedBufferEXT\" not available"); @@ -269,7 +271,8 @@ private native long dispatch_glMapNamedBufferEXT(int buffer, int access, long pr native private ByteBuffer newDirectByteBuffer(long addr, long capacity); - public void glVertexPointer(GLArrayData array) { + @Override + public final void glVertexPointer(GLArrayData array) { if(array.getComponentCount()==0) return; if(array.isVBO()) { glVertexPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset()); @@ -277,7 +280,8 @@ native private ByteBuffer newDirectByteBuffer(long addr, long capacity); glVertexPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getBuffer()); } } - public void glColorPointer(GLArrayData array) { + @Override + public final void glColorPointer(GLArrayData array) { if(array.getComponentCount()==0) return; if(array.isVBO()) { glColorPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset()); @@ -286,7 +290,8 @@ native private ByteBuffer newDirectByteBuffer(long addr, long capacity); } } - public void glNormalPointer(GLArrayData array) { + @Override + public final void glNormalPointer(GLArrayData array) { if(array.getComponentCount()==0) return; if(array.getComponentCount()!=3) { throw new GLException("Only 3 components per normal allowed"); @@ -297,7 +302,8 @@ native private ByteBuffer newDirectByteBuffer(long addr, long capacity); glNormalPointer(array.getComponentType(), array.getStride(), array.getBuffer()); } } - public void glTexCoordPointer(GLArrayData array) { + @Override + public final void glTexCoordPointer(GLArrayData array) { if(array.getComponentCount()==0) return; if(array.isVBO()) { glTexCoordPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset()); diff --git a/make/config/jogl/gl-impl-CustomJavaCode-gles1.java b/make/config/jogl/gl-impl-CustomJavaCode-gles1.java index dff33cf81..68eadc683 100644 --- a/make/config/jogl/gl-impl-CustomJavaCode-gles1.java +++ b/make/config/jogl/gl-impl-CustomJavaCode-gles1.java @@ -12,98 +12,122 @@ public GLES1Impl(GLProfile glp, GLContextImpl context) { this.glProfile = glp; } +@Override public final boolean isGL4bc() { return false; } +@Override public final boolean isGL4() { return false; } +@Override public final boolean isGL3bc() { return false; } +@Override public final boolean isGL3() { return false; } +@Override public final boolean isGL2() { return false; } +@Override public final boolean isGLES1() { return true; } +@Override public final boolean isGLES2() { return false; } +@Override public final boolean isGLES() { return true; } +@Override public final boolean isGL2ES1() { return true; } +@Override public final boolean isGL2ES2() { return false; } +@Override public final boolean isGLES2Compatible() { return false; } +@Override public final boolean isGL2GL3() { return false; } +@Override public final boolean hasGLSL() { return false; } +@Override public boolean isNPOTTextureAvailable() { return false; } +@Override public final GL4bc getGL4bc() throws GLException { throw new GLException("Not a GL4bc implementation"); } +@Override public final GL4 getGL4() throws GLException { throw new GLException("Not a GL4 implementation"); } +@Override public final GL3bc getGL3bc() throws GLException { throw new GLException("Not a GL3bc implementation"); } +@Override public final GL3 getGL3() throws GLException { throw new GLException("Not a GL3 implementation"); } +@Override public final GL2 getGL2() throws GLException { throw new GLException("Not a GL2 implementation"); } +@Override public final GLES1 getGLES1() throws GLException { return this; } +@Override public final GLES2 getGLES2() throws GLException { throw new GLException("Not a GLES2 implementation"); } +@Override public final GL2ES1 getGL2ES1() throws GLException { return this; } +@Override public final GL2ES2 getGL2ES2() throws GLException { throw new GLException("Not a GL2ES2 implementation"); } +@Override public final GL2GL3 getGL2GL3() throws GLException { throw new GLException("Not a GL2GL3 implementation"); } @@ -119,17 +143,17 @@ private final GLStateTracker glStateTracker; private boolean bufferObjectExtensionsInitialized = false; private boolean haveOESFramebufferObject; -private void initBufferObjectExtensionChecks() { +private final void initBufferObjectExtensionChecks() { if (bufferObjectExtensionsInitialized) return; bufferObjectExtensionsInitialized = true; haveOESFramebufferObject = isExtensionAvailable("GL_OES_framebuffer_object"); } -private boolean checkBufferObject(boolean avail, - boolean enabled, - int state, - String kind, boolean throwException) { +private final boolean checkBufferObject(boolean avail, + boolean enabled, + int state, + String kind, boolean throwException) { if (!avail) { if (!enabled) return true; @@ -157,7 +181,7 @@ private boolean checkBufferObject(boolean avail, return true; } -private boolean checkArrayVBODisabled(boolean throwException) { +private final boolean checkArrayVBODisabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(true, false, @@ -165,7 +189,7 @@ private boolean checkArrayVBODisabled(boolean throwException) { "array vertex_buffer_object", throwException); } -private boolean checkArrayVBOEnabled(boolean throwException) { +private final boolean checkArrayVBOEnabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(true, true, @@ -173,7 +197,7 @@ private boolean checkArrayVBOEnabled(boolean throwException) { "array vertex_buffer_object", throwException); } -private boolean checkElementVBODisabled(boolean throwException) { +private final boolean checkElementVBODisabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(true, false, @@ -181,7 +205,7 @@ private boolean checkElementVBODisabled(boolean throwException) { "element vertex_buffer_object", throwException); } -private boolean checkElementVBOEnabled(boolean throwException) { +private final boolean checkElementVBOEnabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(true, true, @@ -189,30 +213,30 @@ private boolean checkElementVBOEnabled(boolean throwException) { "element vertex_buffer_object", throwException); } -private boolean checkUnpackPBODisabled(boolean throwException) { +private final boolean checkUnpackPBODisabled(boolean throwException) { // PBO n/a for ES 1.1 or ES 2.0 return true; } -private boolean checkUnpackPBOEnabled(boolean throwException) { +private final boolean checkUnpackPBOEnabled(boolean throwException) { // PBO n/a for ES 1.1 or ES 2.0 return false; } -private boolean checkPackPBODisabled(boolean throwException) { +private final boolean checkPackPBODisabled(boolean throwException) { // PBO n/a for ES 1.1 or ES 2.0 return true; } -private boolean checkPackPBOEnabled(boolean throwException) { +private final boolean checkPackPBOEnabled(boolean throwException) { // PBO n/a for ES 1.1 or ES 2.0 return false; } -private HashMap arbMemCache = new HashMap(); +private final HashMap arbMemCache = new HashMap(); /** Entry point to C language function:
LPVOID glMapBuffer(GLenum target, GLenum access); */ -public java.nio.ByteBuffer glMapBuffer(int target, int access) { +public final java.nio.ByteBuffer glMapBuffer(int target, int access) { final long __addr_ = ((GLES1ProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBuffer; if (__addr_ == 0) { throw new GLException("Method \"glMapBuffer\" not available"); @@ -252,7 +276,8 @@ native private long dispatch_glMapBuffer(int target, int access, long glProcAddr native private ByteBuffer newDirectByteBuffer(long addr, long capacity); -public void glVertexPointer(GLArrayData array) { +@Override +public final void glVertexPointer(GLArrayData array) { if(array.getComponentCount()==0) return; if(array.isVBO()) { glVertexPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset()); @@ -260,7 +285,8 @@ public void glVertexPointer(GLArrayData array) { glVertexPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getBuffer()); } } -public void glColorPointer(GLArrayData array) { +@Override +public final void glColorPointer(GLArrayData array) { if(array.getComponentCount()==0) return; if(array.isVBO()) { glColorPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset()); @@ -269,7 +295,8 @@ public void glColorPointer(GLArrayData array) { } } -public void glNormalPointer(GLArrayData array) { +@Override +public final void glNormalPointer(GLArrayData array) { if(array.getComponentCount()==0) return; if(array.getComponentCount()!=3) { throw new GLException("Only 3 components per normal allowed"); @@ -280,7 +307,8 @@ public void glNormalPointer(GLArrayData array) { glNormalPointer(array.getComponentType(), array.getStride(), array.getBuffer()); } } -public void glTexCoordPointer(GLArrayData array) { +@Override +public final void glTexCoordPointer(GLArrayData array) { if(array.getComponentCount()==0) return; if(array.isVBO()) { glTexCoordPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset()); diff --git a/make/config/jogl/gl-impl-CustomJavaCode-gles2.java b/make/config/jogl/gl-impl-CustomJavaCode-gles2.java index a4976f5ea..760287364 100644 --- a/make/config/jogl/gl-impl-CustomJavaCode-gles2.java +++ b/make/config/jogl/gl-impl-CustomJavaCode-gles2.java @@ -1,6 +1,3 @@ -// Tracks glBegin/glEnd calls to determine whether it is legal to -// query Vertex Buffer Object state -private boolean inBeginEndPair; public GLES2Impl(GLProfile glp, GLContextImpl context) { this._context = context; @@ -16,18 +13,22 @@ public GLES2Impl(GLProfile glp, GLContextImpl context) { this.glProfile = glp; } +@Override public final boolean isGL4bc() { return false; } +@Override public final boolean isGL4() { return false; } +@Override public final boolean isGL3bc() { return false; } +@Override public final boolean isGL3() { return false; } @@ -36,78 +37,97 @@ public final boolean isGL2() { return false; } +@Override public final boolean isGLES1() { return false; } +@Override public final boolean isGLES2() { return true; } +@Override public final boolean isGLES() { return true; } +@Override public final boolean isGL2ES1() { return false; } +@Override public final boolean isGL2ES2() { return true; } +@Override public final boolean isGLES2Compatible() { return true; } +@Override public final boolean isGL2GL3() { return false; } +@Override public final boolean hasGLSL() { return true; } +@Override public boolean isNPOTTextureAvailable() { return true; } +@Override public final GL4bc getGL4bc() throws GLException { throw new GLException("Not a GL4bc implementation"); } +@Override public final GL4 getGL4() throws GLException { throw new GLException("Not a GL4 implementation"); } +@Override public final GL3bc getGL3bc() throws GLException { throw new GLException("Not a GL3bc implementation"); } +@Override public final GL3 getGL3() throws GLException { throw new GLException("Not a GL3 implementation"); } +@Override public final GL2 getGL2() throws GLException { throw new GLException("Not a GL2 implementation"); } +@Override public final GLES1 getGLES1() throws GLException { throw new GLException("Not a GLES1 implementation"); } +@Override public final GLES2 getGLES2() throws GLException { return this; } +@Override public final GL2ES1 getGL2ES1() throws GLException { throw new GLException("Not a GL2ES1 implementation"); } +@Override public final GL2ES2 getGL2ES2() throws GLException { return this; } +@Override public final GL2GL3 getGL2GL3() throws GLException { throw new GLException("Not a GL2GL3 implementation"); } @@ -123,17 +143,17 @@ private final GLStateTracker glStateTracker; private boolean bufferObjectExtensionsInitialized = false; private boolean haveOESFramebufferObject; -private void initBufferObjectExtensionChecks() { +private final void initBufferObjectExtensionChecks() { if (bufferObjectExtensionsInitialized) return; bufferObjectExtensionsInitialized = true; haveOESFramebufferObject = isExtensionAvailable("GL_OES_framebuffer_object"); } -private boolean checkBufferObject(boolean avail, - boolean enabled, - int state, - String kind, boolean throwException) { +private final boolean checkBufferObject(boolean avail, + boolean enabled, + int state, + String kind, boolean throwException) { if (!avail) { if (!enabled) return true; @@ -161,7 +181,7 @@ private boolean checkBufferObject(boolean avail, return true; } -private boolean checkArrayVBODisabled(boolean throwException) { +private final boolean checkArrayVBODisabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(true, false, @@ -169,7 +189,7 @@ private boolean checkArrayVBODisabled(boolean throwException) { "array vertex_buffer_object", throwException); } -private boolean checkArrayVBOEnabled(boolean throwException) { +private final boolean checkArrayVBOEnabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(true, true, @@ -177,7 +197,7 @@ private boolean checkArrayVBOEnabled(boolean throwException) { "array vertex_buffer_object", throwException); } -private boolean checkElementVBODisabled(boolean throwException) { +private final boolean checkElementVBODisabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(true, false, @@ -185,7 +205,7 @@ private boolean checkElementVBODisabled(boolean throwException) { "element vertex_buffer_object", throwException); } -private boolean checkElementVBOEnabled(boolean throwException) { +private final boolean checkElementVBOEnabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(true, true, @@ -193,30 +213,31 @@ private boolean checkElementVBOEnabled(boolean throwException) { "element vertex_buffer_object", throwException); } -private boolean checkUnpackPBODisabled(boolean throwException) { +private final boolean checkUnpackPBODisabled(boolean throwException) { // PBO n/a for ES 1.1 or ES 2.0 return true; } -private boolean checkUnpackPBOEnabled(boolean throwException) { +private final boolean checkUnpackPBOEnabled(boolean throwException) { // PBO n/a for ES 1.1 or ES 2.0 return false; } -private boolean checkPackPBODisabled(boolean throwException) { +private final boolean checkPackPBODisabled(boolean throwException) { // PBO n/a for ES 1.1 or ES 2.0 return true; } -private boolean checkPackPBOEnabled(boolean throwException) { +private final boolean checkPackPBOEnabled(boolean throwException) { // PBO n/a for ES 1.1 or ES 2.0 return false; } -private HashMap arbMemCache = new HashMap(); +private final HashMap arbMemCache = new HashMap(); /** Entry point to C language function:
LPVOID glMapBuffer(GLenum target, GLenum access); */ -public java.nio.ByteBuffer glMapBuffer(int target, int access) { +@Override +public final java.nio.ByteBuffer glMapBuffer(int target, int access) { final long __addr_ = ((GLES2ProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBuffer; if (__addr_ == 0) { throw new GLException("Method \"glMapBuffer\" not available"); @@ -256,11 +277,13 @@ native private long dispatch_glMapBuffer(int target, int access, long glProcAddr native private ByteBuffer newDirectByteBuffer(long addr, long capacity); -public void glClearDepth(double depth) { +@Override +public final void glClearDepth(double depth) { glClearDepthf((float)depth); } -public void glDepthRange(double zNear, double zFar) { +@Override +public final void glDepthRange(double zNear, double zFar) { glDepthRangef((float)zNear, (float)zFar); } diff --git a/make/scripts/java-win32-dbg.bat b/make/scripts/java-win32-dbg.bat index d1797bdbb..6f8206721 100755 --- a/make/scripts/java-win32-dbg.bat +++ b/make/scripts/java-win32-dbg.bat @@ -9,9 +9,9 @@ set BLD_DIR=..\%BLD_SUB% set FFMPEG_LIB=%PROJECT_ROOT%\make\lib\ffmpeg\x32 -set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%FFMPEG_LIB%;%PATH% -REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\angle\win32;%PATH% -REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\PVRVFrame\OGLES-2.0\Windows_x86_32;%PATH% +REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%FFMPEG_LIB%;%PATH% +REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\angle\win32;%PATH% +set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\PVRVFrame\OGLES-2.0\Windows_x86_32;%PATH% REM set LIB_DIR=%BLD_DIR%\lib;..\..\gluegen\%BLD_SUB%\obj set LIB_DIR=%FFMPEG_LIB% @@ -20,11 +20,14 @@ set CP_ALL=.;%BLD_DIR%\jar\jogl-all.jar;%BLD_DIR%\jar\jogl-test.jar;..\..\gluege echo CP_ALL %CP_ALL% -set D_ARGS="-Djogamp.debug.IOUtil" "-Djogl.debug.GLSLCode" "-Djogl.debug.GLMediaPlayer" +set D_ARGS="-Djogl.debug.GLContext" "-Djogl.debug.FBObject" +REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.DontQuery" +REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.QueryNativeTK" +REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" +REM set D_ARGS="-Djogamp.debug.IOUtil" "-Djogl.debug.GLSLCode" "-Djogl.debug.GLMediaPlayer" REM set D_ARGS="-Djogl.debug.ExtensionAvailabilityCache" "-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.ProcAddressHelper=true" "-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true" REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.NativeLibrary=true" REM set D_ARGS="-Djogamp.debug.JNILibLoader=true" "-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true" "-Djogl.debug.GLProfile=true" -REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" REM set D_ARGS="-Dnewt.debug.Window" "-Dnativewindow.debug.TraceLock" REM set D_ARGS="-Dnativewindow.debug.TraceLock" REM set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Display" diff --git a/make/scripts/java-win32.bat b/make/scripts/java-win32.bat index 9d59c045e..1d8430280 100755 --- a/make/scripts/java-win32.bat +++ b/make/scripts/java-win32.bat @@ -8,8 +8,8 @@ set PROJECT_ROOT=D:\projects\jogamp\jogl set BLD_DIR=..\%BLD_SUB% REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw\bin;%PATH% -set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\angle\win32;%PATH% -REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\PVRVFrame\OGLES-2.0\Windows_x86_32;%PATH% +REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\angle\win32;%PATH% +set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\PVRVFrame\OGLES-2.0\Windows_x86_32;%PATH% set BLD_DIR=..\%BLD_SUB% REM set LIB_DIR=..\..\gluegen\%BLD_SUB%\obj;%BLD_DIR%\lib diff --git a/make/scripts/java-win64-dbg.bat b/make/scripts/java-win64-dbg.bat index d6b0435ea..109755d2e 100755 --- a/make/scripts/java-win64-dbg.bat +++ b/make/scripts/java-win64-dbg.bat @@ -9,7 +9,8 @@ set BLD_DIR=..\%BLD_SUB% set FFMPEG_LIB=%PROJECT_ROOT%\make\lib\ffmpeg\x64 -set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%FFMPEG_LIB%;%PATH% +set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw\bin;%PATH% +REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\PVRVFrame\OGLES-2.0\Windows_x86_64;%PATH% REM set LIB_DIR=%BLD_DIR%\lib;..\..\gluegen\%BLD_SUB%\obj set LIB_DIR=%FFMPEG_LIB% @@ -17,7 +18,13 @@ set CP_ALL=.;%BLD_DIR%\jar\jogl-all.jar;%BLD_DIR%\jar\jogl-test.jar;..\..\gluege echo CP_ALL %CP_ALL% -set D_ARGS="-Djogamp.debug.IOUtil" "-Djogl.debug.GLSLCode" "-Djogl.debug.GLMediaPlayer" +set D_ARGS="-Djogl.debug.GLContext" "-Djogl.debug.FBObject" +REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.DontQuery" +REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.QueryNativeTK" +REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" +REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug=all" "-Djogl.debug.EGLDrawableFactory.DontQuery" +REM set D_ARGS="-Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.CapabilitiesChooser -Djogl.debug.GLProfile" +REM set D_ARGS="-Djogamp.debug.IOUtil" "-Djogl.debug.GLSLCode" "-Djogl.debug.GLMediaPlayer" REM set D_ARGS="-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true" "-Djogl.debug.GLSLCode" REM set D_ARGS="-Djogl.debug.ExtensionAvailabilityCache" "-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.ProcAddressHelper=true" "-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true" REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.NativeLibrary=true" @@ -33,7 +40,6 @@ REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLC REM set D_ARGS="-Dnewt.debug.Window" REM set D_ARGS="-Djogl.debug.GLDebugMessageHandler" "-Djogl.debug.DebugGL" "-Djogl.debug.TraceGL" REM set D_ARGS="-Djogl.debug.DebugGL" "-Djogl.debug.GLDebugMessageHandler" "-Djogl.debug.GLSLCode" -REM set D_ARGS="-Djogl.debug.GraphicsConfiguration" "-Djogl.debug.CapabilitiesChooser" REM set D_ARGS="-Djogl.debug.GLContext" "-Dnewt.debug=all" REM set D_ARGS="-Dnewt.debug.Window" "-Dnativewindow.debug.TraceLock" REM set D_ARGS="-Dnativewindow.debug.TraceLock" diff --git a/make/scripts/java-win64.bat b/make/scripts/java-win64.bat index b8f438aab..2c09feedc 100755 --- a/make/scripts/java-win64.bat +++ b/make/scripts/java-win64.bat @@ -4,7 +4,8 @@ set J2RE_HOME=c:\jre1.6.0_30_x64 set JAVA_HOME=c:\jdk1.6.0_30_x64 set ANT_PATH=C:\apache-ant-1.8.2 -set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw\bin;%PATH% +REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw\bin;%PATH% +set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\PVRVFrame\OGLES-2.0\Windows_x86_64;%PATH% set BLD_DIR=..\%BLD_SUB% REM set LIB_DIR=%BLD_DIR%\lib;..\..\gluegen\%BLD_SUB%\obj diff --git a/make/scripts/tests-x32.bat b/make/scripts/tests-x32.bat index c29dcef39..7947759a4 100755 --- a/make/scripts/tests-x32.bat +++ b/make/scripts/tests-x32.bat @@ -51,7 +51,7 @@ REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.TestScreenMode0 REM scripts\java-win32.bat com.jogamp.opengl.test.junit.newt.ManualScreenMode03NEWT REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple %* -scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube %* +REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube %* REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.TexCubeES2 %* REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.TestDisplayLifecycle01NEWT @@ -94,6 +94,7 @@ REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMe REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.acore.TestMapBuffer01NEWT REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01 +scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT %* REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.glsl.TestFBOMRTNEWT01 REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT %* diff --git a/make/scripts/tests-x64.bat b/make/scripts/tests-x64.bat index 32729d235..0b3711784 100755 --- a/make/scripts/tests-x64.bat +++ b/make/scripts/tests-x64.bat @@ -72,7 +72,7 @@ REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingPr REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWT01GLn %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWT02GLn %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTAWT01GLn %* -scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn %* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen02BitmapNEWT -time 5000 @@ -96,7 +96,8 @@ REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMe REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestMapBuffer01NEWT REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01 -REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.glsl.TestFBOMRTNEWT01 +scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.glsl.TestFBOMRTNEWT01 %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT %* diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 0258187fd..591f5f9d2 100755 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -53,10 +53,17 @@ function jrun() { swton=$1 shift + #D_ARGS="-Djogl.debug.FBObject -Djogl.debug.DebugGL" + #D_ARGS="-Djogl.debug.FBObject" + #D_ARGS="-Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.GLDrawable -Djogl.debug.GLContext -Djogl.debug.FBObject" #D_ARGS="-Djogl.debug.GLContext.NoProfileAliasing" #D_ARGS="-Djogamp.debug=all -Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all" #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all" + #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all -Djogamp.debug.Lock" #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all" + #D_ARGS="-Djogl.debug.EGLDrawableFactory.DontQuery -Djogl.debug.GLDrawable" + #D_ARGS="-Djogl.debug.EGLDrawableFactory.QueryNativeTK -Djogl.debug.GLDrawable" + #D_ARGS="-Djogl.debug.GLDrawable" #D_ARGS="-Djogl.debug=all -Dnewt.debug=all" #D_ARGS="-Djogl.debug.DebugGL -Djogl.debug.TraceGL" #D_ARGS="-Djogl.debug.GLDebugMessageHandler" @@ -71,6 +78,7 @@ function jrun() { #D_ARGS="-Djogamp.debug.IOUtil -Djogl.debug.GLSLCode -Djogl.debug.GLMediaPlayer" #D_ARGS="-Djogl.debug.GLArrayData" #D_ARGS="-Djogl.debug.EGL -Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.GLDrawable" + #D_ARGS="-Djogl.debug.GLDrawable" #D_ARGS="-Dnewt.test.Screen.disableScreenMode -Dnewt.debug.Screen" #D_ARGS="-Djogl.debug.ExtensionAvailabilityCache -Djogl.debug=all -Dnativewindow.debug=all -Djogamp.debug.ProcAddressHelper=true -Djogamp.debug.NativeLibrary=true -Djogamp.debug.NativeLibrary.Lookup=true" #D_ARGS="-Dnewt.debug.MainThread" @@ -85,7 +93,7 @@ function jrun() { #D_ARGS="-Dnativewindow.debug.NativeWindow" #D_ARGS="-Dnewt.debug.Window -Dnewt.debug.Display -Dnewt.debug.EDT" #D_ARGS="-Dnewt.debug.EDT -Dnewt.debug.Window -Djogl.debug.GLContext" - #D_ARGS="-Dnativewindow.debug.ToolkitLock.TraceLock -Dnativewindow.debug.X11Util.XErrorStackDump -Dnativewindow.debug.X11Util.TraceDisplayLifecycle -Dnativewindow.debug.X11Util" + #D_ARGS="-Dnativewindow.debug.X11Util.XErrorStackDump -Dnativewindow.debug.X11Util.TraceDisplayLifecycle -Dnativewindow.debug.X11Util" #D_ARGS="-Dnativewindow.debug.X11Util -Djogl.debug.GLContext -Djogl.debug.GLDrawable -Dnewt.debug=all" #D_ARGS="-Dnativewindow.debug.X11Util -Dnativewindow.debug.X11Util.XSync" #D_ARGS="-Dnativewindow.debug.X11Util.XSync -Dnewt.debug.Window" @@ -100,9 +108,9 @@ function jrun() { #D_ARGS="-Djogl.debug.Animator -Dnewt.debug=all" #D_ARGS="-Dnewt.debug.EDT -Dnewt.debug.Display -Dnativewindow.debug.X11Util -Djogl.debug.GLDrawable -Djogl.debug.GLCanvas" #D_ARGS="-Djogl.debug.GLContext" - #D_ARGS="-Djogl.debug.GraphicsConfiguration -Djogl.debug.CapabilitiesChooser" + #D_ARGS="-Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.CapabilitiesChooser" #D_ARGS="-Dnewt.debug.Screen -Dnewt.debug.EDT -Djogamp.debug.Lock" - #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GraphicsConfiguration" + #D_ARGS="-Djogl.debug.GLContext -Dnativewindow.debug.GraphicsConfiguration" #D_ARGS="-Dnewt.debug.EDT" #D_ARGS="-Dnewt.debug.Window -Dnewt.debug.Display -Dnewt.debug.EDT -Djogl.debug.GLContext" #D_ARGS="-Dnewt.debug.Window -Djogl.debug.Animator -Dnewt.debug.Screen" @@ -115,8 +123,6 @@ function jrun() { #D_ARGS="-Xprof" #D_ARGS="-Djogl.debug.Animator" #D_ARGS="-Dnativewindow.debug=all" - #D_ARGS="-Djogl.debug.GraphicsConfiguration" - #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.GraphicsConfiguration" #D_ARGS="-Djogl.debug.GLCanvas" #D_ARGS="-Dnativewindow.debug.ToolkitLock.TraceLock" #D_ARGS="-Djogl.debug.graph.curve -Djogl.debug.GLSLCode -Djogl.debug.TraceGL" @@ -162,20 +168,20 @@ function jrun() { C_ARG="com.jogamp.newt.util.MainThread" fi fi + #export LD_LIBRARY_PATH=$spath/../lib/external/PVRVFrame/OGLES-2.0/Linux_x86_64:$LD_LIBRARY_PATH + #export LD_LIBRARY_PATH=$spath/../lib/external/PVRVFrame/OGLES-2.0/Linux_x86_32:$LD_LIBRARY_PATH + #export LD_LIBRARY_PATH=/usr/local/projects/Xorg.modular/build-x86_64/lib:$LD_LIBRARY_PATH + #export LD_LIBRARY_PATH=/opt-linux-x86_64/x11lib-1.3:$LD_LIBRARY_PATH + #export LD_LIBRARY_PATH=/opt-linux-x86_64/mesa-7.8.1/lib64:$LD_LIBRARY_PATH + #export LD_LIBRARY_PATH=/usr/lib/mesa:/usr/lib32/mesa:$LD_LIBRARY_PATH + #export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/mesa:/usr/lib/i386-linux-gnu/mesa:$LD_LIBRARY_PATH echo echo "Test Start: $*" echo echo LD_LIBRARY_PATH $LD_LIBRARY_PATH echo echo $javaexe $javaxargs $X_ARGS $D_ARGS $C_ARG $* - #LD_LIBRARY_PATH=/usr/local/projects/Xorg.modular/build-x86_64/lib:$LD_LIBRARY_PATH \ - #LD_LIBRARY_PATH=/opt-linux-x86_64/x11lib-1.3:$LD_LIBRARY_PATH \ - #LD_LIBRARY_PATH=/opt-linux-x86_64/mesa-7.8.1/lib64:$LD_LIBRARY_PATH \ #LIBGL_DRIVERS_PATH=/usr/lib/mesa:/usr/lib32/mesa \ - #LD_LIBRARY_PATH=/usr/lib/mesa:/usr/lib32/mesa:$LD_LIBRARY_PATH \ - #LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/mesa:/usr/lib/i386-linux-gnu/mesa:$LD_LIBRARY_PATH \ - #LD_LIBRARY_PATH=$spath/../lib/PVRVFrame/OGLES-2.0/Linux_x86_64:$LD_LIBRARY_PATH \ - #LD_LIBRARY_PATH=$spath/../lib/PVRVFrame/OGLES-2.0/Linux_x86_32:$LD_LIBRARY_PATH \ #gdb --args $javaexe $javaxargs $X_ARGS $D_ARGS $C_ARG $* $javaexe $javaxargs $X_ARGS $D_ARGS $C_ARG $* echo @@ -228,6 +234,7 @@ function testawtswt() { #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT2 $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateNEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLContextDrawableSwitchNEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT $* #testnoawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01NEWT $* #testnoawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting02NEWT $* @@ -292,7 +299,7 @@ function testawtswt() { # swt (testswt) # #testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTEclipseGLCanvas01GLn $* -testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $* +#testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $* #testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $* #testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor02GLn $* @@ -322,7 +329,8 @@ testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $* #testawt com.jogamp.opengl.test.junit.newt.parenting.TestTranslucentParentingAWT $* #testawt com.jogamp.opengl.test.junit.newt.TestCloseNewtAWT #testawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES1AWT $* -#testawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES1NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES1NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES2NEWT $* #testawt com.jogamp.opengl.test.junit.jogl.caps.TestTranslucencyAWT $* #testawt com.jogamp.opengl.test.junit.jogl.caps.TestTranslucencyNEWT $* #testawt com.jogamp.opengl.test.junit.jogl.glsl.TestShaderCompilationBug459AWT @@ -358,7 +366,9 @@ testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $* #testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLShaderState01NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLShaderState02NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01 $* -#testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestFBOMRTNEWT01 $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOMRTNEWT01 $* +testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOMix2DemosES2NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT $* # # Graph @@ -394,6 +404,7 @@ testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $* #testawt com.jogamp.opengl.test.junit.newt.TestFocus02SwingAWTRobot $* #linux: +#testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES2NEWT $* # linux NV: cannot make ctx current .. # osx: #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingFocusTraversal01AWT $* diff --git a/make/stub_includes/opengl/macosx-window-system.h b/make/stub_includes/opengl/macosx-window-system.h index e7fe13553..47b51a509 100644 --- a/make/stub_includes/opengl/macosx-window-system.h +++ b/make/stub_includes/opengl/macosx-window-system.h @@ -31,7 +31,7 @@ NSView* getNSView(NSOpenGLContext* ctx); NSOpenGLContext* createContext(NSOpenGLContext* shareContext, NSView* nsView, - Bool isBackingLayerView, + Bool allowIncompleteView, NSOpenGLPixelFormat* pixelFormat, Bool opaque, int* viewNotReady); diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java index 87a734e1f..482d35cae 100644 --- a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java +++ b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java @@ -293,9 +293,9 @@ public class BuildStaticGLInfo { output.println(" public static String getFunctionAssociation(String glFunctionName)"); output.println(" {"); output.println(" String mappedName = null;"); - output.println(" int funcNamePermNum = com.jogamp.gluegen.runtime.opengl.GLExtensionNames.getFuncNamePermutationNumber(glFunctionName);"); + output.println(" int funcNamePermNum = com.jogamp.gluegen.runtime.opengl.GLNameResolver.getFuncNamePermutationNumber(glFunctionName);"); output.println(" for(int i = 0; null==mappedName && i < funcNamePermNum; i++) {"); - output.println(" String tmp = com.jogamp.gluegen.runtime.opengl.GLExtensionNames.getFuncNamePermutation(glFunctionName, i);"); + output.println(" String tmp = com.jogamp.gluegen.runtime.opengl.GLNameResolver.getFuncNamePermutation(glFunctionName, i);"); output.println(" try {"); output.println(" mappedName = (String)funcToAssocMap.get(tmp);"); output.println(" } catch (Exception e) { }"); diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java index c1a4facd2..ba025e18c 100755 --- a/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java +++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java @@ -43,7 +43,7 @@ import com.jogamp.gluegen.GlueEmitterControls; import com.jogamp.gluegen.GlueGen; import com.jogamp.gluegen.MethodBinding; import com.jogamp.gluegen.procaddress.ProcAddressConfiguration; -import com.jogamp.gluegen.runtime.opengl.GLExtensionNames; +import com.jogamp.gluegen.runtime.opengl.GLNameResolver; import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -224,11 +224,11 @@ public class GLConfiguration extends ProcAddressConfiguration { } } } - boolean isGLEnum = GLExtensionNames.isGLEnumeration(symbol); - boolean isGLFunc = GLExtensionNames.isGLFunction(symbol); + boolean isGLEnum = GLNameResolver.isGLEnumeration(symbol); + boolean isGLFunc = GLNameResolver.isGLFunction(symbol); if (isGLFunc || isGLEnum) { - if (GLExtensionNames.isExtensionVEN(symbol, isGLFunc)) { - String extSuffix = GLExtensionNames.getExtensionSuffix(symbol, isGLFunc); + if (GLNameResolver.isExtensionVEN(symbol, isGLFunc)) { + String extSuffix = GLNameResolver.getExtensionSuffix(symbol, isGLFunc); if (getDropUniqVendorExtensions(extSuffix)) { if (DEBUG_IGNORES) { System.err.println("Ignore UniqVendorEXT: " + symbol + ", vendor " + extSuffix); diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java index f4658ad7b..809c6783d 100644 --- a/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java +++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java @@ -51,7 +51,7 @@ import com.jogamp.gluegen.SymbolFilter; import com.jogamp.gluegen.cgram.types.FunctionSymbol; import com.jogamp.gluegen.procaddress.ProcAddressEmitter; import com.jogamp.gluegen.procaddress.ProcAddressJavaMethodBindingEmitter; -import com.jogamp.gluegen.runtime.opengl.GLExtensionNames; +import com.jogamp.gluegen.runtime.opengl.GLNameResolver; import java.io.IOException; import java.io.PrintWriter; @@ -110,13 +110,13 @@ public class GLEmitter extends ProcAddressEmitter { if (declarations != null) { for (Iterator iterator = declarations.iterator(); iterator.hasNext();) { String decl = iterator.next(); - boolean isGLFunction = GLExtensionNames.isGLFunction(decl); + boolean isGLFunction = GLNameResolver.isGLFunction(decl); boolean isGLEnumeration = false; if (!isGLFunction) { - isGLEnumeration = GLExtensionNames.isGLEnumeration(decl); + isGLEnumeration = GLNameResolver.isGLEnumeration(decl); } if (isGLFunction || isGLEnumeration) { - String renamed = GLExtensionNames.normalize(decl, isGLFunction); + String renamed = GLNameResolver.normalize(decl, isGLFunction); if (!renamed.equals(decl)) { config.addJavaSymbolRename(decl, renamed); } @@ -181,7 +181,7 @@ public class GLEmitter extends ProcAddressEmitter { String cause = null; for (String decl : declarations) { boolean isFunc = !decl.startsWith("GL_"); - if (!GLExtensionNames.isExtension(decl, isFunc)) { + if (!GLNameResolver.isExtension(decl, isFunc)) { isExtension = false; break; } @@ -199,7 +199,7 @@ public class GLEmitter extends ProcAddressEmitter { } } cause = decl; - String unifiedName = GLExtensionNames.normalize(decl, isFunc); + String unifiedName = GLNameResolver.normalize(decl, isFunc); // NOTE that we look up the unified name in the // BuildStaticGLInfo's notion of the APIs -- since // we might not be emitting glue code for the @@ -472,12 +472,12 @@ public class GLEmitter extends ProcAddressEmitter { w.println(" * it was statically linked."); w.println(" */"); w.println(" public long getAddressFor(String functionNameUsr) {"); - w.println(" String functionNameBase = "+GLExtensionNames.class.getName()+".normalizeVEN(com.jogamp.gluegen.runtime.opengl.GLExtensionNames.normalizeARB(functionNameUsr, true), true);"); + w.println(" String functionNameBase = "+GLNameResolver.class.getName()+".normalizeVEN(com.jogamp.gluegen.runtime.opengl.GLNameResolver.normalizeARB(functionNameUsr, true), true);"); w.println(" String addressFieldNameBase = PROCADDRESS_VAR_PREFIX + functionNameBase;"); w.println(" java.lang.reflect.Field addressField = null;"); - w.println(" int funcNamePermNum = "+GLExtensionNames.class.getName()+".getFuncNamePermutationNumber(functionNameBase);"); + w.println(" int funcNamePermNum = "+GLNameResolver.class.getName()+".getFuncNamePermutationNumber(functionNameBase);"); w.println(" for(int i = 0; null==addressField && i < funcNamePermNum; i++) {"); - w.println(" String addressFieldName = "+GLExtensionNames.class.getName()+".getFuncNamePermutation(addressFieldNameBase, i);"); + w.println(" String addressFieldName = "+GLNameResolver.class.getName()+".getFuncNamePermutation(addressFieldNameBase, i);"); w.println(" try {"); w.println(" addressField = getClass().getField(addressFieldName);"); w.println(" } catch (Exception e) { }"); diff --git a/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLExtensionNames.java b/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLExtensionNames.java deleted file mode 100644 index 426333034..000000000 --- a/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLExtensionNames.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - * You acknowledge that this software is not designed or intended for use - * in the design, construction, operation or maintenance of any nuclear - * facility. - * - */ -package com.jogamp.gluegen.runtime.opengl; - -public class GLExtensionNames { - //GL_XYZ : GL_XYZ, GL_XYZ_GL2, GL_XYZ_ARB, GL_XYZ_OES, GL_XYZ_OML - //GL_XYZ : GL_XYZ, GL_GL2_XYZ, GL_ARB_XYZ, GL_OES_XYZ, GL_OML_XYZ - // - // Pass-1 Unify ARB extensions with the same value - // Pass-2 Unify vendor extensions, - // if exist as an ARB extension with the same value. - // Pass-3 Emit - - public static final String[] extensionsARB = { "ARB", "GL2", "OES", "KHR", "OML" }; - public static final String[] extensionsVEN = { "3DFX", - "AMD", - "ANGLE", - "ARM", - "APPLE", - "ATI", - "EXT", - "HI", - "HP", - "IBM", - "IMG", - "MESA", - "MESAX", - "NV", - "QCOM", - "SGI", - "SGIS", - "SGIX", - "SUN", - "VIV", - "WIN" - }; - - - public static final boolean isGLFunction(String str) { - return str.startsWith("gl") || /* str.startsWith("glu") || str.startsWith("glX") || */ - str.startsWith("egl") || str.startsWith("wgl") || str.startsWith("agl") || - str.startsWith("cgl") ; - } - - public static final boolean isGLEnumeration(String str) { - return str.startsWith("GL_") || str.startsWith("GLU_") || str.startsWith("GLX_") || - str.startsWith("EGL_") || str.startsWith("WGL_") || str.startsWith("AGL_") || - str.startsWith("CGL_") ; - } - - public static final int getExtensionIdx(String[] extensions, String str, boolean isGLFunc) { - if(isGLFunc) { - for(int i = extensions.length - 1 ; i>=0 ; i--) { - if( str.endsWith(extensions[i]) ) { - return i; - } - } - } else { - for(int i = extensions.length - 1 ; i>=0 ; i--) { - if( str.endsWith("_"+extensions[i]) ) { - return i; - } - } - } - return -1; - } - - public static final boolean isExtension(String[] extensions, String str, boolean isGLFunc) { - return getExtensionIdx(extensions, str, isGLFunc)>=0; - } - - public static final String getExtensionSuffix(String str, boolean isGLFunc) { - int idx = getExtensionIdx(extensionsARB, str, isGLFunc); - if(idx>=0) { - return extensionsARB[idx]; - } - idx = getExtensionIdx(extensionsVEN, str, isGLFunc); - if(idx>=0) { - return extensionsVEN[idx]; - } - return null; - } - - public static final String normalize(String[] extensions, String str, boolean isGLFunc) { - boolean touched = false; - for(int i = extensions.length - 1 ; !touched && i>=0 ; i--) { - if(isGLFunc) { - if(str.endsWith(extensions[i])) { - // functions - str = str.substring(0, str.length()-extensions[i].length()); - touched=true; - } - } else { - if(str.endsWith("_"+extensions[i])) { - // enums - str = str.substring(0, str.length()-1-extensions[i].length()); - touched=true; - } - } - } - return str; - } - public static final String normalizeARB(String str, boolean isGLFunc) { - return normalize(extensionsARB, str, isGLFunc); - } - public static final boolean isExtensionARB(String str, boolean isGLFunc) { - return isExtension(extensionsARB, str, isGLFunc); - } - public static final String normalizeVEN(String str, boolean isGLFunc) { - return normalize(extensionsVEN, str, isGLFunc); - } - public static final boolean isExtensionVEN(String str, boolean isGLFunc) { - return isExtension(extensionsVEN, str, isGLFunc); - } - public static final String normalize(String str, boolean isGLFunc) { - if (isExtensionARB(str, isGLFunc)) { - return normalizeARB(str, isGLFunc); - } - if (isExtensionVEN(str, isGLFunc)) { - return normalizeVEN(str, isGLFunc); - } - return str; - } - public static final boolean isExtension(String str, boolean isGLFunc) { - return isExtension(extensionsARB, str, isGLFunc) || - isExtension(extensionsVEN, str, isGLFunc); - } - - public static final int getFuncNamePermutationNumber(String name) { - if(isExtensionARB(name, true) || isExtensionVEN(name, true)) { - // no name permutation, if it's already a known extension - return 1; - } - return 1 + extensionsARB.length + extensionsVEN.length; - } - - public static final String getFuncNamePermutation(String name, int i) { - // identity - if(i==0) { - return name; - } - if(0>i || i>=(1+extensionsARB.length + extensionsVEN.length)) { - throw new RuntimeException("Index out of range [0.."+(1+extensionsARB.length+extensionsVEN.length-1)+"]: "+i); - } - // ARB - i-=1; - if(i=0 ; i--) { + if( str.endsWith(extensions[i]) ) { + return i; + } + } + } else { + for(int i = extensions.length - 1 ; i>=0 ; i--) { + if( str.endsWith("_"+extensions[i]) ) { + return i; + } + } + } + return -1; + } + + public static final boolean isExtension(String[] extensions, String str, boolean isGLFunc) { + return getExtensionIdx(extensions, str, isGLFunc)>=0; + } + + public static final String getExtensionSuffix(String str, boolean isGLFunc) { + int idx = getExtensionIdx(extensionsARB, str, isGLFunc); + if(idx>=0) { + return extensionsARB[idx]; + } + idx = getExtensionIdx(extensionsVEN, str, isGLFunc); + if(idx>=0) { + return extensionsVEN[idx]; + } + return null; + } + + public static final String normalize(String[] extensions, String str, boolean isGLFunc) { + boolean touched = false; + for(int i = extensions.length - 1 ; !touched && i>=0 ; i--) { + if(isGLFunc) { + if(str.endsWith(extensions[i])) { + // functions + str = str.substring(0, str.length()-extensions[i].length()); + touched=true; + } + } else { + if(str.endsWith("_"+extensions[i])) { + // enums + str = str.substring(0, str.length()-1-extensions[i].length()); + touched=true; + } + } + } + return str; + } + public static final String normalizeARB(String str, boolean isGLFunc) { + return normalize(extensionsARB, str, isGLFunc); + } + public static final boolean isExtensionARB(String str, boolean isGLFunc) { + return isExtension(extensionsARB, str, isGLFunc); + } + public static final String normalizeVEN(String str, boolean isGLFunc) { + return normalize(extensionsVEN, str, isGLFunc); + } + public static final boolean isExtensionVEN(String str, boolean isGLFunc) { + return isExtension(extensionsVEN, str, isGLFunc); + } + public static final String normalize(String str, boolean isGLFunc) { + if (isExtensionARB(str, isGLFunc)) { + return normalizeARB(str, isGLFunc); + } + if (isExtensionVEN(str, isGLFunc)) { + return normalizeVEN(str, isGLFunc); + } + return str; + } + public static final boolean isExtension(String str, boolean isGLFunc) { + return isExtension(extensionsARB, str, isGLFunc) || + isExtension(extensionsVEN, str, isGLFunc); + } + + public static final int getFuncNamePermutationNumber(String name) { + if(isExtensionARB(name, true) || isExtensionVEN(name, true)) { + // no name permutation, if it's already a known extension + return 1; + } + return 1 + extensionsARB.length + extensionsVEN.length; + } + + public static final String getFuncNamePermutation(String name, int i) { + // identity + if(i==0) { + return name; + } + if(0>i || i>=(1+extensionsARB.length + extensionsVEN.length)) { + throw new RuntimeException("Index out of range [0.."+(1+extensionsARB.length+extensionsVEN.length-1)+"]: "+i); + } + // ARB + i-=1; + if(i + * Supports on-the-fly reconfiguration of dimension and multisample buffers via {@link #reset(GL, int, int, int)} + * while preserving the {@link Attachment} references. + *

+ *

+ * Integrates default read/write framebuffers via {@link GLContext#getDefaultReadFramebuffer()} and {@link GLContext#getDefaultReadFramebuffer()}, + * which is being hooked at {@link GL#glBindFramebuffer(int, int)} when the default (zero) framebuffer is selected. + *

+ * + *

FIXME: Implement support for {@link Type#DEPTH_TEXTURE}, {@link Type#STENCIL_TEXTURE} .

+ */ +public class FBObject { + protected static final boolean DEBUG = Debug.debug("FBObject"); + + /** + * Returns true if basic FBO support is available, otherwise false. + *

+ * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= core 3.0 or implements the extensions + * ARB_ES2_compatibility, ARB_framebuffer_object, EXT_framebuffer_object or OES_framebuffer_object. + *

+ *

+ * Basic FBO support may only include one color attachment and no multisampling, + * as well as limited internal formats for renderbuffer. + *

+ * @see GLContext#hasFBO() + */ + public static final boolean supportsBasicFBO(GL gl) { + return gl.getContext().hasFBO(); + } + + /** + * Returns true if full FBO support is available, otherwise false. + *

+ * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions + * ARB_framebuffer_object, or all of + * EXT_framebuffer_object, EXT_framebuffer_multisample, + * EXT_framebuffer_blit, GL_EXT_packed_depth_stencil. + *

+ *

+ * Full FBO support includes multiple color attachments and multisampling. + *

+ */ + public static final boolean supportsFullFBO(GL gl) { + return gl.isGL3() || // GL >= 3.0 + + gl.isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object + + ( gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_object) && // All EXT_framebuffer_object* + gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) && + gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) && + gl.isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil) ) ; + } + + public static final int getMaxSamples(GL gl) { + if( supportsFullFBO(gl) ) { + int[] val = new int[] { 0 } ; + gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0); + return val[0]; + } else { + return 0; + } + } + + /** Common super class of all attachments */ + public static abstract class Attachment { + public enum Type { + NONE, DEPTH, STENCIL, DEPTH_STENCIL, COLOR, COLOR_TEXTURE, DEPTH_TEXTURE, STENCIL_TEXTURE; + + /** + * Returns {@link #COLOR}, {@link #DEPTH}, {@link #STENCIL} or {@link #DEPTH_STENCIL} + * @throws IllegalArgumentException if format cannot be handled. + */ + public static Type determine(int format) throws IllegalArgumentException { + switch(format) { + case GL.GL_RGBA4: + case GL.GL_RGB5_A1: + case GL.GL_RGB565: + case GL.GL_RGB8: + case GL.GL_RGBA8: + return Type.COLOR; + case GL.GL_DEPTH_COMPONENT16: + case GL.GL_DEPTH_COMPONENT24: + case GL.GL_DEPTH_COMPONENT32: + return Type.DEPTH; + case GL.GL_STENCIL_INDEX1: + case GL.GL_STENCIL_INDEX4: + case GL.GL_STENCIL_INDEX8: + return Type.STENCIL; + case GL.GL_DEPTH24_STENCIL8: + return Type.DEPTH_STENCIL; + default: + throw new IllegalArgumentException("format invalid: 0x"+Integer.toHexString(format)); + } + } + }; + + /** immutable type [{@link #COLOR}, {@link #DEPTH}, {@link #STENCIL}, {@link #COLOR_TEXTURE}, {@link #DEPTH_TEXTURE}, {@link #STENCIL_TEXTURE} ] */ + public final Type type; + + /** immutable the internal format */ + public final int format; + + private int width, height; + + private int name; + + /** true if resource is initialized by {@link #initialize(GL)}, hence {@link #free(GL)} is allowed to free the GL resources. */ + protected boolean resourceOwner; + + private int initCounter; + + protected Attachment(Type type, int iFormat, int width, int height, int name) { + this.type = type; + this.format = iFormat; + this.width = width; + this.height = height; + this.name = name; + this.resourceOwner = false; + this.initCounter = 0; + } + + /** width of attachment */ + public final int getWidth() { return width; } + /** height of attachment */ + public final int getHeight() { return height; } + /* pp */ final void setSize(int w, int h) { width = w; height = h; } + + /** buffer name [1..max], maybe a texture or renderbuffer name, depending on type. */ + public final int getName() { return name; } + /* pp */ final void setName(int n) { name = n; } + + public final int getInitCounter() { return initCounter; } + + /** + * Initializes the attachment buffer and set it's parameter, if uninitialized, i.e. name is zero. + *

Implementation employs an initialization counter, hence it can be paired recursively with {@link #free(GL)}.

+ * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case. + */ + public void initialize(GL gl) throws GLException { + initCounter++; + /* + super.initialize(gl); + if(1 == getInitCounter() && 0 == getName() ) { + do init .. + freeResources = true; // if all OK + } + */ + } + + /** + * Releases the attachment buffer if initialized, i.e. name is zero. + *

Implementation employs an initialization counter, hence it can be paired recursively with {@link #initialize(GL)}.

+ * @throws GLException if buffer release fails. + */ + public void free(GL gl) throws GLException { + /* + if(1 == getInitCounter() && freeResources && .. ) { + do free .. + } + super.free(gl); + */ + initCounter--; + if(0 == initCounter) { + resourceOwner = false; + name = 0; + } + if(DEBUG) { + System.err.println("Attachment.free: "+this); + } + } + + /** + *

+ * Comparison by {@link #type}, {@link #format}, {@link #width}, {@link #height} and {@link #name}. + *

+ * {@inheritDoc} + */ + @Override + public boolean equals(Object o) { + if( this == o ) return true; + if( ! ( o instanceof Attachment ) ) return false; + final Attachment a = (Attachment)o; + return type == a.type && + format == a.format || + width == a.width || + height== a.height || + name == a.name ; + } + + /** + *

+ * Hashed by {@link #type}, {@link #format}, {@link #width}, {@link #height} and {@link #name}. + *

+ * {@inheritDoc} + */ + @Override + public int hashCode() { + // 31 * x == (x << 5) - x + int hash = 31 + type.ordinal(); + hash = ((hash << 5) - hash) + format; + hash = ((hash << 5) - hash) + width; + hash = ((hash << 5) - hash) + height; + hash = ((hash << 5) - hash) + name; + return hash; + } + + int objectHashCode() { return super.hashCode(); } + + public String toString() { + return getClass().getSimpleName()+"[type "+type+", format 0x"+Integer.toHexString(format)+", "+width+"x"+height+ + ", name 0x"+Integer.toHexString(name)+", obj 0x"+Integer.toHexString(objectHashCode())+ + ", resOwner "+resourceOwner+", initCount "+initCounter+"]"; + } + + public static Type getType(int attachmentPoint, int maxColorAttachments) { + if( GL.GL_COLOR_ATTACHMENT0 <= attachmentPoint && attachmentPoint < GL.GL_COLOR_ATTACHMENT0+maxColorAttachments ) { + return Type.COLOR; + } + switch(attachmentPoint) { + case GL.GL_DEPTH_ATTACHMENT: + return Type.DEPTH; + case GL.GL_STENCIL_ATTACHMENT: + return Type.STENCIL; + default: + throw new IllegalArgumentException("Invalid attachment point 0x"+Integer.toHexString(attachmentPoint)); + } + } + } + + /** Other renderbuffer attachment which maybe a colorbuffer, depth or stencil. */ + public static class RenderAttachment extends Attachment { + private int samples; + + /** + * @param type allowed types are {@link Type#DEPTH}, {@link Type#STENCIL} or {@link Type#COLOR} + * @param iFormat + * @param samples + * @param width + * @param height + * @param name + */ + public RenderAttachment(Type type, int iFormat, int samples, int width, int height, int name) { + super(validateType(type), iFormat, width, height, name); + this.samples = samples; + } + + /** number of samples, or zero for no multisampling */ + public final int getSamples() { return samples; } + /* pp */ final void setSamples(int s) { samples = s; } + + private static Type validateType(Type type) { + switch(type) { + case DEPTH: + case STENCIL: + case COLOR: + return type; + default: + throw new IllegalArgumentException("Invalid type: "+type); + } + } + + /** + *

+ * Comparison by {@link #type}, {@link #format}, {@link #samples}, {@link #width}, {@link #height} and {@link #name}. + *

+ * {@inheritDoc} + */ + @Override + public boolean equals(Object o) { + if( this == o ) return true; + if( ! ( o instanceof RenderAttachment ) ) return false; + return super.equals(o) && + samples == ((RenderAttachment)o).samples; + } + + /** + *

+ * Hashed by {@link #type}, {@link #format}, {@link #samples}, {@link #width}, {@link #height} and {@link #name}. + *

+ * {@inheritDoc} + */ + @Override + public int hashCode() { + // 31 * x == (x << 5) - x + int hash = super.hashCode(); + hash = ((hash << 5) - hash) + samples; + return hash; + } + + @Override + public void initialize(GL gl) throws GLException { + super.initialize(gl); + if( 1 == getInitCounter() && 0 == getName() ) { + final int[] name = new int[] { -1 }; + gl.glGenRenderbuffers(1, name, 0); + if( 0 == name[0] ) { + throw new GLException("null renderbuffer, "+this); + } + setName(name[0]); + + gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, getName()); + if( samples > 0 ) { + ((GL2GL3)gl).glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, samples, format, getWidth(), getHeight()); + } else { + gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, format, getWidth(), getHeight()); + } + int glerr = gl.glGetError(); + if(GL.GL_NO_ERROR != glerr) { + gl.glDeleteRenderbuffers(1, name, 0); + setName(0); + throw new GLException("GL Error 0x"+Integer.toHexString(glerr)+" while creating "+this); + } + resourceOwner = true; + if(DEBUG) { + System.err.println("Attachment.init: "+this); + } + } + } + + @Override + public void free(GL gl) { + if(1 == getInitCounter() && resourceOwner && 0 != getName() ) { + final int[] name = new int[] { getName() }; + gl.glDeleteRenderbuffers(1, name, 0); + } + super.free(gl); + } + + public String toString() { + return getClass().getSimpleName()+"[type "+type+", format 0x"+Integer.toHexString(format)+", samples "+samples+", "+getWidth()+"x"+getHeight()+ + ", name 0x"+Integer.toHexString(getName())+", obj 0x"+Integer.toHexString(objectHashCode())+ + ", resOwner "+resourceOwner+", initCount "+getInitCounter()+"]"; + } + } + + /** + * Marker interface, denotes a color buffer attachment. + *

Always an instance of {@link Attachment}.

+ *

Either an instance of {@link ColorAttachment} or {@link TextureAttachment}. + */ + public static interface Colorbuffer { + } + + /** Color render buffer attachment */ + public static class ColorAttachment extends RenderAttachment implements Colorbuffer { + public ColorAttachment(int iFormat, int samples, int width, int height, int name) { + super(Type.COLOR, iFormat, samples, width, height, name); + } + } + + /** Texture attachment */ + public static class TextureAttachment extends Attachment implements Colorbuffer { + /** details of the texture setup */ + public final int dataFormat, dataType, magFilter, minFilter, wrapS, wrapT; + + /** + * @param type allowed types are [ {@link Type#COLOR_TEXTURE}, {@link Type#DEPTH_TEXTURE}, {@link Type#STENCIL_TEXTURE} ] + * @param iFormat + * @param width + * @param height + * @param dataFormat + * @param dataType + * @param magFilter + * @param minFilter + * @param wrapS + * @param wrapT + * @param name + */ + public TextureAttachment(Type type, int iFormat, int width, int height, int dataFormat, int dataType, + int magFilter, int minFilter, int wrapS, int wrapT, int name) { + super(validateType(type), iFormat, width, height, name); + this.dataFormat = dataFormat; + this.dataType = dataType; + this.magFilter = magFilter; + this.minFilter = minFilter; + this.wrapS = wrapS; + this.wrapT = wrapT; + } + + private static Type validateType(Type type) { + switch(type) { + case COLOR_TEXTURE: + case DEPTH_TEXTURE: + case STENCIL_TEXTURE: + return type; + default: + throw new IllegalArgumentException("Invalid type: "+type); + } + } + + /** + * Initializes the texture and set it's parameter, if uninitialized, i.e. name is zero. + * @throws GLException if texture generation and setup fails. The just created texture name will be deleted in this case. + */ + @Override + public void initialize(GL gl) throws GLException { + super.initialize(gl); + if( 1 == getInitCounter() && 0 == getName() ) { + final int[] name = new int[] { -1 }; + gl.glGenTextures(1, name, 0); + if(0 == name[0]) { + throw new GLException("null texture, "+this); + } + setName(name[0]); + + gl.glBindTexture(GL.GL_TEXTURE_2D, name[0]); + gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, format, getWidth(), getHeight(), 0, dataFormat, dataType, null); + if( 0 < magFilter ) { + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, magFilter); + } + if( 0 < minFilter ) { + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, minFilter); + } + if( 0 < wrapS ) { + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, wrapS); + } + if( 0 < wrapT ) { + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapT); + } + int glerr = gl.glGetError(); + if(GL.GL_NO_ERROR != glerr) { + gl.glDeleteTextures(1, name, 0); + setName(0); + throw new GLException("GL Error 0x"+Integer.toHexString(glerr)+" while creating "+this); + } + resourceOwner = true; + } + if(DEBUG) { + System.err.println("Attachment.init: "+this); + } + } + + @Override + public void free(GL gl) { + if(1 == getInitCounter() && resourceOwner && 0 != getName() ) { + final int[] name = new int[] { getName() }; + gl.glDeleteTextures(1, name, 0); + } + super.free(gl); + } + } + + private boolean initialized; + private boolean basicFBOSupport; + private boolean fullFBOSupport; + private boolean rgba8Avail; + private boolean depth24Avail; + private boolean depth32Avail; + private boolean stencil01Avail; + private boolean stencil04Avail; + private boolean stencil08Avail; + private boolean stencil16Avail; + private boolean packedDepthStencilAvail; + private int maxColorAttachments, maxSamples, maxTextureSize, maxRenderbufferSize; + + private int width, height, samples; + private int vStatus; + private int fbName; + private boolean bound; + + private int colorAttachmentCount; + private Colorbuffer[] colorAttachmentPoints; // colorbuffer attachment points + private RenderAttachment depth, stencil; // depth and stencil maybe equal in case of packed-depth-stencil + + private final FBObject samplesSink; // MSAA sink + private TextureAttachment samplesSinkTexture; + private boolean samplesSinkDirty; + + // + // ColorAttachment helper .. + // + + private final void validateColorAttachmentPointRange(int point) { + if(maxColorAttachments != colorAttachmentPoints.length) { + throw new InternalError("maxColorAttachments "+maxColorAttachments+", array.lenght "+colorAttachmentPoints); + } + if(0 > point || point >= maxColorAttachments) { + throw new IllegalArgumentException("attachment point out of range: "+point+", should be within [0.."+(maxColorAttachments-1)+"]"); + } + } + + private final void validateAddColorAttachment(int point, Colorbuffer ca) { + validateColorAttachmentPointRange(point); + if( null != colorAttachmentPoints[point] ) { + throw new IllegalArgumentException("Cannot attach "+ca+", attachment point already in use by "+colorAttachmentPoints[point]); + } + } + + private final void addColorAttachment(int point, Colorbuffer ca) { + validateColorAttachmentPointRange(point); + final Colorbuffer c = colorAttachmentPoints[point]; + if( null != c && c != ca ) { + throw new IllegalArgumentException("Add failed: requested to add "+ca+" at "+point+", but slot is holding "+c+"; "+this); + } + colorAttachmentPoints[point] = ca; + colorAttachmentCount++; + } + + private final void removeColorAttachment(int point, Colorbuffer ca) { + validateColorAttachmentPointRange(point); + final Colorbuffer c = colorAttachmentPoints[point]; + if( null != c && c != ca ) { + throw new IllegalArgumentException("Remove failed: requested to removed "+ca+" at "+point+", but slot is holding "+c+"; "+this); + } + colorAttachmentPoints[point] = null; + colorAttachmentCount--; + } + + /** + * Return the {@link Colorbuffer} attachment at attachmentPoint if it is attached to this FBO, otherwise null. + * + * @see #attachColorbuffer(GL, boolean) + * @see #attachColorbuffer(GL, boolean) + * @see #attachTexture2D(GL, int, boolean, int, int, int, int) + * @see #attachTexture2D(GL, int, int, int, int, int, int, int, int) + */ + public final Colorbuffer getColorbuffer(int attachmentPoint) { + validateColorAttachmentPointRange(attachmentPoint); + return colorAttachmentPoints[attachmentPoint]; + } + + /** + * Finds the passed {@link Colorbuffer} within the valid range of attachment points + * using reference comparison only. + *

+ * Note: Slow. Implementation uses a logN array search to save resources, i.e. not using a HashMap. + *

+ * @param ca the {@link Colorbuffer} to look for. + * @return -1 if the {@link Colorbuffer} could not be found, otherwise [0..{@link #getMaxColorAttachments()}-1] + */ + public final int getColorbufferAttachmentPoint(Colorbuffer ca) { + for(int i=0; ireference only. + * + *

+ * Note: Slow. Uses {@link #getColorbufferAttachmentPoint(Colorbuffer)} to determine it's attachment point + * to be used for {@link #getColorbuffer(int)} + *

+ * + * @see #attachColorbuffer(GL, boolean) + * @see #attachColorbuffer(GL, boolean) + * @see #attachTexture2D(GL, int, boolean, int, int, int, int) + * @see #attachTexture2D(GL, int, int, int, int, int, int, int, int) + */ + public final Colorbuffer getColorbuffer(Colorbuffer ca) { + final int p = getColorbufferAttachmentPoint(ca); + return p>=0 ? getColorbuffer(p) : null; + } + + /** + * Creates an uninitialized FBObject instance. + *

+ * Call {@link #init(GL, int, int, int)} .. etc to use it. + *

+ */ + public FBObject() { + this(false); + } + /* pp */ FBObject(boolean isSampleSink) { + this.initialized = false; + + // TBD @ init + this.basicFBOSupport = false; + this.fullFBOSupport = false; + this.rgba8Avail = false; + this.depth24Avail = false; + this.depth32Avail = false; + this.stencil01Avail = false; + this.stencil04Avail = false; + this.stencil08Avail = false; + this.stencil16Avail = false; + this.packedDepthStencilAvail = false; + this.maxColorAttachments=-1; + this.maxSamples=-1; + this.maxTextureSize = 0; + this.maxRenderbufferSize = 0; + + this.width = 0; + this.height = 0; + this.samples = 0; + this.vStatus = -1; + this.fbName = 0; + this.bound = false; + + this.colorAttachmentPoints = null; // at init .. + this.colorAttachmentCount = 0; + this.depth = null; + this.stencil = null; + + this.samplesSink = isSampleSink ? null : new FBObject(true); + this.samplesSinkTexture = null; + this.samplesSinkDirty = true; + } + + private void init(GL gl, int width, int height, int samples) throws GLException { + if(initialized) { + throw new GLException("FBO already initialized"); + } + fullFBOSupport = supportsFullFBO(gl); + + if( !fullFBOSupport && !supportsBasicFBO(gl) ) { + throw new GLException("FBO not supported w/ context: "+gl.getContext()+", "+this); + } + + basicFBOSupport = true; + + rgba8Avail = gl.isGL2GL3() || gl.isExtensionAvailable(GLExtensions.OES_rgb8_rgba8); + depth24Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_depth24); + depth32Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_depth32); + stencil01Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil1); + stencil04Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil4); + stencil08Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil8); + stencil16Avail = fullFBOSupport; + + packedDepthStencilAvail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_packed_depth_stencil); + + final boolean NV_fbo_color_attachments = gl.isExtensionAvailable(GLExtensions.NV_fbo_color_attachments); + + int val[] = new int[1]; + + int glerr = gl.glGetError(); + if(DEBUG && GL.GL_NO_ERROR != glerr) { + System.err.println("FBObject.init-preexisting.0 GL Error 0x"+Integer.toHexString(glerr)); + } + + int realMaxColorAttachments = 1; + maxColorAttachments = 1; + if( null != samplesSink && fullFBOSupport || NV_fbo_color_attachments ) { + try { + gl.glGetIntegerv(GL2GL3.GL_MAX_COLOR_ATTACHMENTS, val, 0); + glerr = gl.glGetError(); + if(GL.GL_NO_ERROR == glerr) { + realMaxColorAttachments = 1 <= val[0] ? val[0] : 1; // cap minimum to 1 + } else if(DEBUG) { + System.err.println("FBObject.init-GL_MAX_COLOR_ATTACHMENTS query GL Error 0x"+Integer.toHexString(glerr)); + } + } catch (GLException gle) {} + } + maxColorAttachments = realMaxColorAttachments <= 8 ? realMaxColorAttachments : 8; // cap to limit array size + + colorAttachmentPoints = new Colorbuffer[maxColorAttachments]; + colorAttachmentCount = 0; + + maxSamples = 0; + if(fullFBOSupport) { + gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0); + glerr = gl.glGetError(); + if(GL.GL_NO_ERROR == glerr) { + maxSamples = val[0]; + } else if(DEBUG) { + System.err.println("FBObject.init-GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr)); + } + } + gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, val, 0); + maxTextureSize = val[0]; + gl.glGetIntegerv(GL.GL_MAX_RENDERBUFFER_SIZE, val, 0); + this.maxRenderbufferSize = val[0]; + + glerr = gl.glGetError(); + if(DEBUG && GL.GL_NO_ERROR != glerr) { + System.err.println("FBObject.init-preexisting.1 GL Error 0x"+Integer.toHexString(glerr)); + } + + this.width = width; + this.height = height; + this.samples = samples <= maxSamples ? samples : maxSamples; + + if(DEBUG) { + System.err.println("FBObject "+width+"x"+height+", "+samples+" -> "+samples+" samples"); + System.err.println("basicFBOSupport: "+basicFBOSupport); + System.err.println("fullFBOSupport: "+fullFBOSupport); + System.err.println("maxColorAttachments: "+maxColorAttachments+"/"+realMaxColorAttachments); + System.err.println("maxSamples: "+maxSamples); + System.err.println("maxTextureSize: "+maxTextureSize); + System.err.println("maxRenderbufferSize: "+maxRenderbufferSize); + System.err.println("rgba8: "+rgba8Avail); + System.err.println("depth24: "+depth24Avail); + System.err.println("depth32: "+depth32Avail); + System.err.println("stencil01: "+stencil01Avail); + System.err.println("stencil04: "+stencil04Avail); + System.err.println("stencil08: "+stencil08Avail); + System.err.println("stencil16: "+stencil16Avail); + System.err.println("packedDepthStencil: "+packedDepthStencilAvail); + System.err.println("NV_fbo_color_attachments: "+NV_fbo_color_attachments); + System.err.println(gl.getContext().getGLVersion()); + System.err.println(JoglVersion.getGLStrings(gl, null).toString()); + System.err.println(gl.getContext()); + } + + checkNoError(null, gl.glGetError(), "FBObject Init.pre"); // throws GLException if error + + if(width > 2 + maxTextureSize || height> 2 + maxTextureSize || + width > maxRenderbufferSize || height> maxRenderbufferSize ) { + throw new GLException("size "+width+"x"+height+" exceeds on of the maxima [texture "+maxTextureSize+", renderbuffer "+maxRenderbufferSize+"]"); + } + + if(null != samplesSink) { + // init sampling sink + samplesSink.reset(gl, width, height); + resetMSAATexture2DSink(gl); + } + + // generate fbo .. + gl.glGenFramebuffers(1, val, 0); + fbName = val[0]; + if(0 == fbName) { + throw new GLException("null framebuffer"); + } + + // bind fbo .. + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbName); + checkNoError(gl, gl.glGetError(), "FBObject Init.bindFB"); // throws GLException if error + if(!gl.glIsFramebuffer(fbName)) { + checkNoError(gl, GL.GL_INVALID_VALUE, "FBObject Init.isFB"); // throws GLException + } + bound = true; + initialized = true; + + updateStatus(gl); + if(DEBUG) { + System.err.println("FBObject.init(): "+this); + } + } + + /** + * Initializes or resets this FBO's instance. + *

+ * In case the new parameters are compatible with the current ones + * no action will be performed. Otherwise all attachments will be recreated + * to match the new given parameters. + *

+ *

+ * Currently incompatibility and hence recreation is given if + * the size or sample count doesn't match for subsequent calls. + *

+ * + *

Leaves the FBO bound state untouched

+ * + * @param gl the current GL context + * @param newWidth + * @param newHeight + * @throws GLException in case of an error + */ + public final void reset(GL gl, int newWidth, int newHeight) { + reset(gl, newWidth, newHeight, 0); + } + + /** + * Initializes or resets this FBO's instance. + *

+ * In case the new parameters are compatible with the current ones + * no action will be performed. Otherwise all attachments will be recreated + * to match the new given parameters. + *

+ *

+ * Currently incompatibility and hence recreation is given if + * the size or sample count doesn't match for subsequent calls. + *

+ * + *

Leaves the FBO bound state untouched

+ * + * @param gl the current GL context + * @param newWidth + * @param newHeight + * @param newSamples if > 0, MSAA will be used, otherwise no multisampling. Will be capped to {@link #getMaxSamples()}. + * @throws GLException in case of an error + */ + public final void reset(GL gl, int newWidth, int newHeight, int newSamples) { + if(!initialized) { + init(gl, newWidth, newHeight, newSamples); + return; + } + newSamples = newSamples <= maxSamples ? newSamples : maxSamples; // clamp + + if( newWidth != width || newHeight != height || newSamples != samples ) { + if(DEBUG) { + System.err.println("FBObject.reset - START - "+this); + } + + final boolean wasBound = isBound(); + + width = newWidth; + height = newHeight; + samples = newSamples; + detachAllImpl(gl, true , true); + resetMSAATexture2DSink(gl); + + if(wasBound) { + bind(gl); + } else { + unbind(gl); + } + + if(DEBUG) { + System.err.println("FBObject.reset - END - "+this); + } + } + } + + /** + * Note that the status may reflect an incomplete state during transition of attachments. + * @return The FB status. {@link GL.GL_FRAMEBUFFER_COMPLETE} if ok, otherwise return GL FBO error state or -1 + * @see #validateStatus() + */ + public final int getStatus() { + return vStatus; + } + + /** return the {@link #getStatus()} as a string. */ + public final String getStatusString() { + return getStatusString(vStatus); + } + + public static final String getStatusString(int fbStatus) { + switch(fbStatus) { + case -1: + return "NOT A FBO"; + + case GL.GL_FRAMEBUFFER_COMPLETE: + return "OK"; + + case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + return("GL FBO: incomplete, incomplete attachment\n"); + case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + return("GL FBO: incomplete, missing attachment"); + case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: + return("GL FBO: incomplete, attached images must have same dimensions"); + case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS: + return("GL FBO: incomplete, attached images must have same format"); + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: + return("GL FBO: incomplete, missing draw buffer"); + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: + return("GL FBO: incomplete, missing read buffer"); + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: + return("GL FBO: incomplete, missing multisample buffer"); + case GL3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: + return("GL FBO: incomplete, layer targets"); + + case GL.GL_FRAMEBUFFER_UNSUPPORTED: + return("GL FBO: Unsupported framebuffer format"); + case GL2GL3.GL_FRAMEBUFFER_UNDEFINED: + return("GL FBO: framebuffer undefined"); + + case 0: + return("GL FBO: incomplete, implementation fault"); + default: + return("GL FBO: incomplete, implementation ERROR 0x"+Integer.toHexString(fbStatus)); + } + } + + /** + * The status may even be valid if incomplete during transition of attachments. + * @see #getStatus() + */ + public final boolean isStatusValid() { + switch(vStatus) { + case GL.GL_FRAMEBUFFER_COMPLETE: + return true; + + case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: + case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS: + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: + case GL3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: + if(0 == colorAttachmentCount || null == depth) { + // we are in transition + return true; + } + + case GL.GL_FRAMEBUFFER_UNSUPPORTED: + case GL2GL3.GL_FRAMEBUFFER_UNDEFINED: + + case 0: + default: + System.out.println("Framebuffer " + fbName + " is incomplete: status = 0x" + Integer.toHexString(vStatus) + + " : " + getStatusString(vStatus)); + return false; + } + } + + private final boolean checkNoError(GL gl, int err, String exceptionMessage) throws GLException { + if(GL.GL_NO_ERROR != err) { + if(null != gl) { + destroy(gl); + } + if(null != exceptionMessage) { + throw new GLException(exceptionMessage+" GL Error 0x"+Integer.toHexString(err)); + } + return false; + } + return true; + } + + private final void checkInitialized() throws GLException { + if(!initialized) { + throw new GLException("FBO not initialized, call init(GL) first."); + } + } + + /** + * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point, + * selecting the texture data type and format automatically. + * + *

Using default min/mag filter {@link GL#GL_NEAREST} and default wrapS/wrapT {@link GL#GL_CLAMP_TO_EDGE}.

+ * + *

Leaves the FBO bound.

+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param alpha set to true if you request alpha channel, otherwise false; + * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen + */ + public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha) throws GLException { + return attachTexture2D(gl, attachmentPoint, alpha, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + } + + /** + * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point, + * selecting the texture data type and format automatically. + * + *

Leaves the FBO bound.

+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param alpha set to true if you request alpha channel, otherwise false; + * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER} + * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} + * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} + * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} + * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen + */ + public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha, int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { + final int textureInternalFormat, textureDataFormat, textureDataType; + if(gl.isGLES()) { + textureInternalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB; + textureDataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB; + textureDataType = GL.GL_UNSIGNED_BYTE; + } else { + textureInternalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8; + textureDataFormat = alpha ? GL.GL_BGRA : GL.GL_RGB; + textureDataType = alpha ? GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV : GL.GL_UNSIGNED_BYTE; + } + return attachTexture2D(gl, attachmentPoint, textureInternalFormat, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT); + } + + /** + * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point. + * + *

Leaves the FBO bound.

+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param internalFormat internalFormat parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} + * @param dataFormat format parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} + * @param dataType type parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} + * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER} + * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} + * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} + * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} + * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen + */ + public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, + int internalFormat, int dataFormat, int dataType, + int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { + return attachTexture2D(gl, attachmentPoint, + new TextureAttachment(Type.COLOR_TEXTURE, internalFormat, width, height, dataFormat, dataType, + magFilter, minFilter, wrapS, wrapT, 0 /* name */)); + } + + /** + * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point. + * + *

+ * In case the passed TextureAttachment texA is uninitialized, i.e. it's texture name is zero, + * a new texture name is generated and setup w/ the texture parameter.
+ * Otherwise, i.e. texture name is not zero, the passed TextureAttachment texA is + * considered complete and assumed matching this FBO requirement. A GL error may occur is the latter is untrue. + *

+ * + *

Leaves the FBO bound.

+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param texA the to be attached {@link TextureAttachment}. Maybe complete or uninitialized, see above. + * @return the passed TextureAttachment texA instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen + */ + public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, TextureAttachment texA) throws GLException { + validateAddColorAttachment(attachmentPoint, texA); + + if(samples>0) { + removeColorAttachment(attachmentPoint, texA); + throw new GLException("Texture2D not supported w/ MSAA. If you have enabled MSAA with exisiting texture attachments, you may want to detach them via detachAllTexturebuffer(gl)."); + } + + texA.initialize(gl); + addColorAttachment(attachmentPoint, texA); + + bind(gl); + + // Set up the color buffer for use as a renderable texture: + gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, + GL.GL_TEXTURE_2D, texA.getName(), 0); + updateStatus(gl); + + if(!isStatusValid()) { + detachColorbuffer(gl, attachmentPoint); + throw new GLException("attachTexture2D "+texA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this); + } + if(DEBUG) { + System.err.println("FBObject.attachTexture2D: "+this); + } + return texA; + } + + /** + * Attaches a Color Buffer to this FBO's instance at the given attachment point, + * selecting the format automatically. + * + *

Leaves the FBO bound.

+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param alpha set to true if you request alpha channel, otherwise false; + * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the colorbuffer couldn't be allocated + */ + public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, boolean alpha) throws GLException { + final int internalFormat; + if( rgba8Avail ) { + internalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8 ; + } else { + internalFormat = alpha ? GL.GL_RGBA4 : GL.GL_RGB565; + } + return attachColorbuffer(gl, attachmentPoint, internalFormat); + } + + /** + * Attaches a Color Buffer to this FBO's instance at the given attachment point. + * + *

Leaves the FBO bound.

+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param internalFormat usually {@link GL#GL_RGBA4}, {@link GL#GL_RGB5_A1}, {@link GL#GL_RGB565}, {@link GL#GL_RGB8} or {@link GL#GL_RGBA8} + * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the colorbuffer couldn't be allocated + * @throws IllegalArgumentException if internalFormat doesn't reflect a colorbuffer + */ + public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, int internalFormat) throws GLException, IllegalArgumentException { + final Attachment.Type atype = Attachment.Type.determine(internalFormat); + if( Attachment.Type.COLOR != atype ) { + throw new IllegalArgumentException("colorformat invalid: 0x"+Integer.toHexString(internalFormat)+", "+this); + } + + return attachColorbuffer(gl, attachmentPoint, new ColorAttachment(internalFormat, samples, width, height, 0)); + } + + /** + * Attaches a Color Buffer to this FBO's instance at the given attachment point. + * + *

Leaves the FBO bound.

+ * + * @param gl + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param colA the template for the new {@link ColorAttachment} + * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the colorbuffer couldn't be allocated + */ + public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, ColorAttachment colA) throws GLException { + validateAddColorAttachment(attachmentPoint, colA); + + colA.initialize(gl); + addColorAttachment(attachmentPoint, colA); + + bind(gl); + + // Attach the color buffer + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, + GL.GL_RENDERBUFFER, colA.getName()); + + updateStatus(gl); + if(!isStatusValid()) { + detachColorbuffer(gl, attachmentPoint); + throw new GLException("attachColorbuffer "+colA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this); + } + if(DEBUG) { + System.err.println("FBObject.attachColorbuffer: "+this); + } + return colA; + } + + + /** + * Attaches one depth, stencil or packed-depth-stencil buffer to this FBO's instance, + * selecting the internalFormat automatically. + *

+ * Stencil and depth buffer can be attached only once. + *

+ *

+ * In case the desired type or bit-number is not supported, the next available one is chosen. + *

+ *

+ * Use {@link #getDepthAttachment()} and/or {@link #getStencilAttachment()} to retrieve details + * about the attached buffer. The details cannot be returned, since it's possible 2 buffers + * are being created, depth and stencil. + *

+ * + *

Leaves the FBO bound.

+ * + * @param gl + * @param atype either {@link Type#DEPTH}, {@link Type#STENCIL} or {@link Type#DEPTH_STENCIL} + * @param reqBits desired bits for depth or -1 for default (24 bits) + * @throws GLException in case the renderbuffer couldn't be allocated or one is already attached. + * @throws IllegalArgumentException + * @see #getDepthAttachment() + * @see #getStencilAttachment() + */ + public final void attachRenderbuffer(GL gl, Attachment.Type atype, int reqBits) throws GLException, IllegalArgumentException { + if( 0 > reqBits ) { + reqBits = 24; + } + final int internalFormat; + int internalStencilFormat = -1; + + switch ( atype ) { + case DEPTH: + if( 32 <= reqBits && depth32Avail ) { + internalFormat = GL.GL_DEPTH_COMPONENT32; + } else if( 24 <= reqBits && depth24Avail ) { + internalFormat = GL.GL_DEPTH_COMPONENT24; + } else { + internalFormat = GL.GL_DEPTH_COMPONENT16; + } + break; + + case STENCIL: + if( 16 <= reqBits && stencil16Avail ) { + internalFormat = GL2GL3.GL_STENCIL_INDEX16; + } else if( 8 <= reqBits && stencil08Avail ) { + internalFormat = GL.GL_STENCIL_INDEX8; + } else if( 4 <= reqBits && stencil04Avail ) { + internalFormat = GL.GL_STENCIL_INDEX4; + } else if( 1 <= reqBits && stencil01Avail ) { + internalFormat = GL.GL_STENCIL_INDEX1; + } else { + throw new GLException("stencil buffer n/a"); + } + break; + + case DEPTH_STENCIL: + if( packedDepthStencilAvail ) { + internalFormat = GL.GL_DEPTH24_STENCIL8; + } else { + if( 24 <= reqBits && depth24Avail ) { + internalFormat = GL.GL_DEPTH_COMPONENT24; + } else { + internalFormat = GL.GL_DEPTH_COMPONENT16; + } + if( stencil08Avail ) { + internalStencilFormat = GL.GL_STENCIL_INDEX8; + } else if( stencil04Avail ) { + internalStencilFormat = GL.GL_STENCIL_INDEX4; + } else if( stencil01Avail ) { + internalStencilFormat = GL.GL_STENCIL_INDEX1; + } else { + throw new GLException("stencil buffer n/a"); + } + } + break; + default: + throw new IllegalArgumentException("only depth/stencil types allowed, was "+atype+", "+this); + } + + attachRenderbufferImpl(gl, atype, internalFormat); + + if(0<=internalStencilFormat) { + attachRenderbufferImpl(gl, Attachment.Type.STENCIL, internalStencilFormat); + } + } + + /** + * Attaches one depth, stencil or packed-depth-stencil buffer to this FBO's instance, + * depending on the internalFormat. + *

+ * Stencil and depth buffer can be attached only once. + *

+ *

+ * Use {@link #getDepthAttachment()} and/or {@link #getStencilAttachment()} to retrieve details + * about the attached buffer. The details cannot be returned, since it's possible 2 buffers + * are being created, depth and stencil. + *

+ * + *

Leaves the FBO bound.

+ * + * @param gl the current GL context + * @param internalFormat {@link GL#GL_DEPTH_COMPONENT16}, {@link GL#GL_DEPTH_COMPONENT24}, {@link GL#GL_DEPTH_COMPONENT32}, + * {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4}, {@link GL#GL_STENCIL_INDEX8} + * or {@link GL#GL_DEPTH24_STENCIL8} + * @throws GLException in case the renderbuffer couldn't be allocated or one is already attached. + * @throws IllegalArgumentException + * @see #getDepthAttachment() + * @see #getStencilAttachment() + */ + public final void attachRenderbuffer(GL gl, int internalFormat) throws GLException, IllegalArgumentException { + final Attachment.Type atype = Attachment.Type.determine(internalFormat); + if( Attachment.Type.DEPTH != atype && Attachment.Type.STENCIL != atype && Attachment.Type.DEPTH_STENCIL != atype ) { + throw new IllegalArgumentException("renderformat invalid: 0x"+Integer.toHexString(internalFormat)+", "+this); + } + attachRenderbufferImpl(gl, atype, internalFormat); + } + + protected final void attachRenderbufferImpl(GL gl, Attachment.Type atype, int internalFormat) throws GLException { + if( null != depth && ( Attachment.Type.DEPTH == atype || Attachment.Type.DEPTH_STENCIL == atype ) ) { + throw new GLException("FBO depth buffer already attached (rb "+depth+"), type is "+atype+", 0x"+Integer.toHexString(internalFormat)+", "+this); + } + if( null != stencil && ( Attachment.Type.STENCIL== atype || Attachment.Type.DEPTH_STENCIL == atype ) ) { + throw new GLException("FBO stencil buffer already attached (rb "+stencil+"), type is "+atype+", 0x"+Integer.toHexString(internalFormat)+", "+this); + } + attachRenderbufferImpl2(gl, atype, internalFormat); + } + + private final void attachRenderbufferImpl2(GL gl, Attachment.Type atype, int internalFormat) throws GLException { + if( Attachment.Type.DEPTH == atype ) { + if(null == depth) { + depth = new RenderAttachment(Type.DEPTH, internalFormat, samples, width, height, 0); + } else { + depth.setSize(width, height); + depth.setSamples(samples); + } + depth.initialize(gl); + } else if( Attachment.Type.STENCIL == atype ) { + if(null == stencil) { + stencil = new RenderAttachment(Type.STENCIL, internalFormat, samples, width, height, 0); + } else { + stencil.setSize(width, height); + stencil.setSamples(samples); + } + stencil.initialize(gl); + } else if( Attachment.Type.DEPTH_STENCIL == atype ) { + if(null == depth) { + depth = new RenderAttachment(Type.DEPTH, internalFormat, samples, width, height, 0); + } else { + depth.setSize(width, height); + depth.setSamples(samples); + } + depth.initialize(gl); + if(null == stencil) { + stencil = new RenderAttachment(Type.STENCIL, internalFormat, samples, width, height, depth.getName()); + } else { + stencil.setName(depth.getName()); + stencil.setSize(width, height); + stencil.setSamples(samples); + } + stencil.initialize(gl); + } + + bind(gl); + + // Attach the buffer + if( Attachment.Type.DEPTH == atype ) { + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depth.getName()); + } else if( Attachment.Type.STENCIL == atype ) { + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, stencil.getName()); + } else if( Attachment.Type.DEPTH_STENCIL == atype ) { + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depth.getName()); + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, stencil.getName()); + } + + updateStatus(gl); + if( !isStatusValid() ) { + detachRenderbuffer(gl, atype); + throw new GLException("renderbuffer attachment failed: "+this.getStatusString()); + } + + if(DEBUG) { + System.err.println("FBObject.attachRenderbuffer: "+this); + } + } + + /** + *

Leaves the FBO bound!

+ * @param gl + * @param ca + * @throws IllegalArgumentException + */ + public final void detachColorbuffer(GL gl, int attachmentPoint) throws IllegalArgumentException { + if(null == detachColorbufferImpl(gl, attachmentPoint, false)) { + throw new IllegalArgumentException("ColorAttachment at "+attachmentPoint+", not attached, "+this); + } + if(DEBUG) { + System.err.println("FBObject.detachAll: "+this); + } + } + + private final Colorbuffer detachColorbufferImpl(GL gl, int attachmentPoint, boolean recreate) { + final Colorbuffer colbuf = colorAttachmentPoints[attachmentPoint]; // shortcut, don't validate here + + if(null == colbuf) { + return null; + } + + bind(gl); + + if(colbuf instanceof TextureAttachment) { + final TextureAttachment texA = (TextureAttachment) colbuf; + if( 0 != texA.getName() ) { + gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, + GL.GL_TEXTURE_2D, 0, 0); + gl.glBindTexture(GL.GL_TEXTURE_2D, 0); + } + texA.free(gl); + removeColorAttachment(attachmentPoint, texA); + if(recreate) { + texA.setSize(width, height); + attachTexture2D(gl, attachmentPoint, texA); + } + } else if(colbuf instanceof ColorAttachment) { + final ColorAttachment colA = (ColorAttachment) colbuf; + if( 0 != colA.getName() ) { + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0+attachmentPoint, + GL.GL_RENDERBUFFER, 0); + } + colA.free(gl); + removeColorAttachment(attachmentPoint, colbuf); + if(recreate) { + colA.setSize(width, height); + colA.setSamples(samples); + attachColorbuffer(gl, attachmentPoint, colA); + } + } + return colbuf; + } + + /** + * + * @param gl + * @param reqAType {@link Type#DEPTH}, {@link Type#DEPTH} or {@link Type#DEPTH_STENCIL} + */ + public final void detachRenderbuffer(GL gl, Attachment.Type atype) throws IllegalArgumentException { + detachRenderbufferImpl(gl, atype, false); + } + + public final boolean isDepthStencilPackedFormat() { + final boolean res = null != depth && null != stencil && + depth.format == stencil.format ; + if(res && depth.getName() != stencil.getName() ) { + throw new InternalError("depth/stencil packed format not sharing: depth "+depth+", stencil "+stencil); + } + return res; + } + + private final void detachRenderbufferImpl(GL gl, Attachment.Type atype, boolean recreate) throws IllegalArgumentException { + switch ( atype ) { + case DEPTH: + case STENCIL: + case DEPTH_STENCIL: + break; + default: + throw new IllegalArgumentException("only depth/stencil types allowed, was "+atype+", "+this); + } + if( null == depth && null == stencil ) { + return ; // nop + } + // reduction of possible combinations, create unique atype command(s) + final ArrayList actions = new ArrayList(2); + if( isDepthStencilPackedFormat() ) { + // packed + actions.add(Attachment.Type.DEPTH_STENCIL); + } else { + // individual + switch ( atype ) { + case DEPTH: + if( null != depth ) { actions.add(Attachment.Type.DEPTH); } + break; + case STENCIL: + if( null != stencil ) { actions.add(Attachment.Type.STENCIL); } + break; + case DEPTH_STENCIL: + if( null != depth ) { actions.add(Attachment.Type.DEPTH); } + if( null != stencil ) { actions.add(Attachment.Type.STENCIL); } + break; + default: // handled + } + } + + bind(gl); + + for(int i = 0; i < actions.size(); i++) { + final int format; + + Attachment.Type action = actions.get(i); + switch ( action ) { + case DEPTH: + format = depth.format; + if( 0 != depth.getName() ) { + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, 0); + } + depth.free(gl); + if(!recreate) { + depth = null; + } + break; + case STENCIL: + format = stencil.format; + if(0 != stencil.getName()) { + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0); + } + stencil.free(gl); + if(!recreate) { + stencil = null; + } + break; + case DEPTH_STENCIL: + format = depth.format; + if(0 != depth.getName()) { + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, 0); + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0); + } + depth.free(gl); + stencil.free(gl); + if(!recreate) { + depth = null; + stencil = null; + } + break; + default: + throw new InternalError("XXX"); + } + if(recreate) { + attachRenderbufferImpl2(gl, action, format); + } + } + } + + /** + * Detaches all {@link ColorAttachment}s, {@link TextureAttachment}s and {@link RenderAttachment}s. + *

Leaves the FBO bound!

+ *

+ * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. + *

+ * @param gl the current GL context + */ + public final void detachAll(GL gl) { + if(null != samplesSink) { + samplesSink.detachAll(gl); + } + detachAllImpl(gl, true/* detachNonColorbuffer */, false /* recreate */); + } + + /** + * Detaches all {@link ColorAttachment}s and {@link TextureAttachment}s. + *

Leaves the FBO bound!

+ *

+ * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. + *

+ * @param gl the current GL context + */ + public final void detachAllColorbuffer(GL gl) { + if(null != samplesSink) { + samplesSink.detachAllColorbuffer(gl); + } + detachAllImpl(gl, false/* detachNonColorbuffer */, false /* recreate */); + } + + /** + * Detaches all {@link TextureAttachment}s + *

Leaves the FBO bound!

+ *

+ * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. + *

+ * @param gl the current GL context + */ + public final void detachAllTexturebuffer(GL gl) { + if(null != samplesSink) { + samplesSink.detachAllTexturebuffer(gl); + } + for(int i=0; i0 ) { + throw new InternalError("Non zero ColorAttachments "+this); + } + + if(detachNonColorbuffer) { + detachRenderbufferImpl(gl, Attachment.Type.DEPTH_STENCIL, recreate); + } + + if(DEBUG) { + System.err.println("FBObject.detachAll: [resetNonColorbuffer "+detachNonColorbuffer+", recreate "+recreate+"]: "+this); + } + } + + /** + * @param gl the current GL context + */ + public final void destroy(GL gl) { + if(null != samplesSink) { + samplesSink.destroy(gl); + } + + detachAllImpl(gl, true /* detachNonColorbuffer */, false /* recreate */); + + // cache FB names, preset exposed to zero, + // braking ties w/ GL/GLContext link to getReadFramebuffer()/getWriteFramebuffer() + final int fb_cache = fbName; + fbName = 0; + + int name[] = new int[1]; + if(0!=fb_cache) { + name[0] = fb_cache; + gl.glDeleteFramebuffers(1, name, 0); + } + initialized = false; + bound = false; + if(DEBUG) { + System.err.println("FBObject.destroy: "+this); + } + } + + private final boolean sampleSinkSizeMismatch() { + return samplesSink.getWidth() != width || samplesSink.getHeight() != height ; + } + private final boolean sampleSinkTexMismatch() { + return null == samplesSinkTexture || 0 == samplesSinkTexture.getName() ; + } + private final boolean sampleSinkDepthStencilMismatch() { + final boolean depthMismatch = ( null != depth && null == samplesSink.depth ) || + ( null != depth && null != samplesSink.depth && + depth.format != samplesSink.depth.format ); + + final boolean stencilMismatch = ( null != stencil && null == samplesSink.stencil ) || + ( null != stencil && null != samplesSink.stencil && + stencil.format != samplesSink.stencil.format ); + + return depthMismatch || stencilMismatch; + } + + private final void resetMSAATexture2DSink(GL gl) throws GLException { + if(0 == samples) { + // MSAA off + if(null != samplesSink) { + samplesSink.detachAll(gl); + } + return; + } + + boolean sampleSinkSizeMismatch = sampleSinkSizeMismatch(); + boolean sampleSinkTexMismatch = sampleSinkTexMismatch(); + boolean sampleSinkDepthStencilMismatch = sampleSinkDepthStencilMismatch(); + + /** if(DEBUG) { + System.err.println("FBObject.resetMSAATexture2DSink.0: \n\tTHIS "+this+",\n\tSINK "+samplesSink+ + "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch); + } */ + + if(!sampleSinkSizeMismatch && !sampleSinkTexMismatch && !sampleSinkDepthStencilMismatch) { + // all properties match .. + return; + } + + unbind(gl); + + if(DEBUG) { + System.err.println("FBObject.resetMSAATexture2DSink: BEGIN\n\tTHIS "+this+",\n\tSINK "+samplesSink+ + "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch); + } + + if( sampleSinkDepthStencilMismatch ) { + samplesSink.detachAllRenderbuffer(gl); + } + + if( sampleSinkSizeMismatch ) { + samplesSink.reset(gl, width, height); + } + + if(null == samplesSinkTexture) { + samplesSinkTexture = samplesSink.attachTexture2D(gl, 0, true); + } else if( 0 == samplesSinkTexture.getName() ) { + samplesSinkTexture.setSize(width, height); + samplesSink.attachTexture2D(gl, 0, samplesSinkTexture); + } + + if( sampleSinkDepthStencilMismatch ) { + samplesSink.attachRenderbuffer(gl, depth.format); + if( null != stencil && !isDepthStencilPackedFormat() ) { + samplesSink.attachRenderbuffer(gl, stencil.format); + } + } + + sampleSinkSizeMismatch = sampleSinkSizeMismatch(); + sampleSinkTexMismatch = sampleSinkTexMismatch(); + sampleSinkDepthStencilMismatch = sampleSinkDepthStencilMismatch(); + if(sampleSinkSizeMismatch || sampleSinkTexMismatch || sampleSinkDepthStencilMismatch) { + throw new InternalError("Samples sink mismatch after reset: \n\tTHIS "+this+",\n\t SINK "+samplesSink+ + "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch); + } + + if(DEBUG) { + System.err.println("FBObject.resetMSAATexture2DSink: END\n\tTHIS "+this+",\n\tSINK "+samplesSink+ + "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch); + } + } + + /** + * Bind this FBO, i.e. bind write framebuffer to {@link #getWriteFramebuffer()}. + * + *

If multisampling is used, it sets the read framebuffer to the sampling sink {@link #getWriteFramebuffer()}, + * if full FBO is supported.

+ * + *

+ * In case you have attached more than one color buffer, + * you may want to setup {@link GL2GL3#glDrawBuffers(int, int[], int)}. + *

+ * @param gl the current GL context + * @throws GLException + */ + public final void bind(GL gl) throws GLException { + if(!bound || fbName != gl.getBoundFramebuffer(GL.GL_FRAMEBUFFER)) { + checkInitialized(); + if(samples > 0 && fullFBOSupport) { + // draw to multisampling - read from samplesSink + gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, getWriteFramebuffer()); + gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, getReadFramebuffer()); + } else { + // one for all + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, getWriteFramebuffer()); + } + + checkNoError(null, gl.glGetError(), "FBObject post-bind"); // throws GLException if error + bound = true; + samplesSinkDirty = true; + } + } + + /** + * Unbind this FBO, i.e. bind read and write framebuffer to default, see {@link GLBase#getDefaultDrawFramebuffer()}. + * + *

If full FBO is supported, sets the read and write framebuffer individually to default, hence not disturbing + * an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()}

+ * + * @param gl the current GL context + * @throws GLException + */ + public final void unbind(GL gl) throws GLException { + if(bound) { + if(fullFBOSupport) { + // default read/draw buffers, may utilize GLContext/GLDrawable override of + // GLContext.getDefaultDrawFramebuffer() and GLContext.getDefaultReadFramebuffer() + gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, 0); + gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, 0); + } else { + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer + } + checkNoError(null, gl.glGetError(), "FBObject post-unbind"); // throws GLException if error + bound = false; + } + } + + /** + * Returns true if framebuffer object is bound via {@link #bind(GL)}, otherwise false. + *

+ * Method verifies the bound state via {@link GL#getBoundFramebuffer(int)}. + *

+ * @param gl the current GL context + */ + public final boolean isBound(GL gl) { + bound = bound && fbName != gl.getBoundFramebuffer(GL.GL_FRAMEBUFFER) ; + return bound; + } + + /** Returns true if framebuffer object is bound via {@link #bind(GL)}, otherwise false. */ + public final boolean isBound() { return bound; } + + /** + * Samples the multisampling colorbuffer (msaa-buffer) to it's sink {@link #getSamplingSink()}. + * + *

The operation is skipped, if no multisampling is used or + * the msaa-buffer has not been flagged dirty by a previous call of {@link #bind(GL)}, + * see {@link #isSamplingBufferDirty()}

+ * + *

If full FBO is supported, sets the read and write framebuffer individually to default after sampling, hence not disturbing + * an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()}

+ * + *

In case you intend to employ {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)} + * you may want to call {@link GL#glBindFramebuffer(int, int) glBindFramebuffer}({@link GL2GL3#GL_READ_FRAMEBUFFER}, {@link #getReadFramebuffer()}); + *

+ * + *

Leaves the FBO unbound.

+ * + * @param gl the current GL context + * @param ta {@link TextureAttachment} to use, prev. attached w/ {@link #attachTexture2D(GL, int, boolean, int, int, int, int) attachTexture2D(..)} + * @throws IllegalArgumentException + */ + public final void syncSamplingBuffer(GL gl) { + unbind(gl); + if(samples>0 && samplesSinkDirty) { + samplesSinkDirty = false; + resetMSAATexture2DSink(gl); + gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, fbName); + gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, samplesSink.getWriteFramebuffer()); + ((GL2GL3)gl).glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, // since MSAA is supported, ugly cast is OK + GL.GL_COLOR_BUFFER_BIT, GL.GL_NEAREST); + if(fullFBOSupport) { + // default read/draw buffers, may utilize GLContext/GLDrawable override of + // GLContext.getDefaultDrawFramebuffer() and GLContext.getDefaultReadFramebuffer() + gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, 0); + gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, 0); + } else { + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer + } + } + } + + /** + * Bind the given texture colorbuffer. + * + *

If multisampling is being used, {@link #syncSamplingBuffer(GL)} is being called.

+ * + *

Leaves the FBO unbound!

+ * + * @param gl the current GL context + * @param ta {@link TextureAttachment} to use, prev. attached w/ {@link #attachTexture2D(GL, int, boolean, int, int, int, int) attachTexture2D(..)} + * @throws IllegalArgumentException + */ + public final void use(GL gl, TextureAttachment ta) throws IllegalArgumentException { + if(null == ta) { throw new IllegalArgumentException("null TextureAttachment"); } + if(samples > 0 && samplesSinkTexture == ta) { + syncSamplingBuffer(gl); + } else { + unbind(gl); + } + gl.glBindTexture(GL.GL_TEXTURE_2D, ta.getName()); // use it .. + } + + /** + * Unbind texture, ie bind 'non' texture 0 + * + *

Leaves the FBO unbound.

+ */ + public final void unuse(GL gl) { + unbind(gl); + gl.glBindTexture(GL.GL_TEXTURE_2D, 0); // don't use it + } + + /** + * Returns true if basic or full FBO is supported, otherwise false. + * @param full true for full FBO supported query, otherwise false for basic FBO support query. + * @see #supportsFullFBO(GL) + * @see #supportsBasicFBO(GL) + * @throws GLException if {@link #init(GL)} hasn't been called. + */ + public final boolean supportsFBO(boolean full) throws GLException { checkInitialized(); return full ? fullFBOSupport : basicFBOSupport; } + + /** + * Returns true if renderbuffer accepts internal format {@link GL#GL_RGB8} and {@link GL#GL_RGBA8}, otherwise false. + * @throws GLException if {@link #init(GL)} hasn't been called. + */ + public final boolean supportsRGBA8() throws GLException { checkInitialized(); return rgba8Avail; } + + /** + * Returns true if {@link GL#GL_DEPTH_COMPONENT16}, {@link GL#GL_DEPTH_COMPONENT24} or {@link GL#GL_DEPTH_COMPONENT32} is supported, otherwise false. + * @param bits 16, 24 or 32 bits + * @throws GLException if {@link #init(GL)} hasn't been called. + */ + public final boolean supportsDepth(int bits) throws GLException { + checkInitialized(); + switch(bits) { + case 16: return basicFBOSupport; + case 24: return depth24Avail; + case 32: return depth32Avail; + default: return false; + } + } + + /** + * Returns true if {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4}, {@link GL#GL_STENCIL_INDEX8} or {@link GL2GL3#GL_STENCIL_INDEX16} is supported, otherwise false. + * @param bits 1, 4, 8 or 16 bits + * @throws GLException if {@link #init(GL)} hasn't been called. + */ + public final boolean supportsStencil(int bits) throws GLException { + checkInitialized(); + switch(bits) { + case 1: return stencil01Avail; + case 4: return stencil04Avail; + case 8: return stencil08Avail; + case 16: return stencil16Avail; + default: return false; + } + } + + /** + * Returns true if {@link GL#GL_DEPTH24_STENCIL8} is supported, otherwise false. + * @throws GLException if {@link #init(GL)} hasn't been called. + */ + public final boolean supportsPackedDepthStencil() throws GLException { checkInitialized(); return packedDepthStencilAvail; } + + /** + * Returns the maximum number of colorbuffer attachments. + * @throws GLException if {@link #init(GL)} hasn't been called. + */ + public final int getMaxColorAttachments() throws GLException { checkInitialized(); return maxColorAttachments; } + + /** + * Returns the maximum number of samples for multisampling. Maybe zero if multisampling is not supported. + * @throws GLException if {@link #init(GL)} hasn't been called. + */ + public final int getMaxSamples() throws GLException { checkInitialized(); return maxSamples; } + + /** + * Returns true if this instance has been initialized with {@link #reset(GL, int, int)} + * or {@link #reset(GL, int, int, int)}, otherwise false + */ + public final boolean isInitialized() { return initialized; } + /** Returns the width */ + public final int getWidth() { return width; } + /** Returns the height */ + public final int getHeight() { return height; } + /** Returns the number of samples for multisampling (MSAA). zero if no multisampling is used. */ + public final int getNumSamples() { return samples; } + /** Returns the framebuffer name to render to. */ + public final int getWriteFramebuffer() { return fbName; } + /** Returns the framebuffer name to read from. Depending on multisampling, this may be a different framebuffer. */ + public final int getReadFramebuffer() { return ( samples > 0 ) ? samplesSink.getReadFramebuffer() : fbName; } + /** Return the number of color/texture attachments */ + public final int getColorAttachmentCount() { return colorAttachmentCount; } + /** Return the stencil {@link RenderAttachment} attachment, if exist. Maybe share the same {@link Attachment#getName()} as {@link #getDepthAttachment()}, if packed depth-stencil is being used. */ + public final RenderAttachment getStencilAttachment() { return stencil; } + /** Return the depth {@link RenderAttachment} attachment. Maybe share the same {@link Attachment#getName()} as {@link #getStencilAttachment()}, if packed depth-stencil is being used. */ + public final RenderAttachment getDepthAttachment() { return depth; } + + /** Return the complete multisampling {@link FBObject} sink, if using multisampling. */ + public final FBObject getSamplingSinkFBO() { return samplesSink; } + + /** Return the multisampling {@link TextureAttachment} sink, if using multisampling. */ + public final TextureAttachment getSamplingSink() { return samplesSinkTexture; } + /** + * Returns true if the multisampling colorbuffer (msaa-buffer) + * has been flagged dirty by a previous call of {@link #bind(GL)}, + * otherwise false. + */ + public final boolean isSamplingBufferDirty() { return samplesSinkDirty; } + + int objectHashCode() { return super.hashCode(); } + + public final String toString() { + final String caps = null != colorAttachmentPoints ? Arrays.asList(colorAttachmentPoints).toString() : null ; + return "FBO[name r/w "+fbName+"/"+getReadFramebuffer()+", init "+initialized+", bound "+bound+", size "+width+"x"+height+", samples "+samples+"/"+maxSamples+ + ", depth "+depth+", stencil "+stencil+", color attachments: "+colorAttachmentCount+"/"+maxColorAttachments+ + ": "+caps+", msaa-sink "+samplesSinkTexture+", isSamplesSink "+(null == samplesSink)+ + ", obj 0x"+Integer.toHexString(objectHashCode())+"]"; + } + + private final void updateStatus(GL gl) { + if( 0 == fbName ) { + vStatus = -1; + } else { + vStatus = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/GLExtensions.java b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java new file mode 100644 index 000000000..f7e25fa01 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java @@ -0,0 +1,81 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl; + +/** + * Class holding OpenGL extension strings, commonly used by JOGL's implementation. + */ +public class GLExtensions { + public static final String VERSION_1_2 = "GL_VERSION_1_2"; + public static final String VERSION_1_4 = "GL_VERSION_1_4"; + public static final String VERSION_1_5 = "GL_VERSION_1_5"; + public static final String VERSION_2_0 = "GL_VERSION_2_0"; + + public static final String ARB_debug_output = "GL_ARB_debug_output"; + public static final String AMD_debug_output = "GL_AMD_debug_output"; + + public static final String ARB_framebuffer_object = "GL_ARB_framebuffer_object"; + public static final String OES_framebuffer_object = "GL_OES_framebuffer_object"; + public static final String EXT_framebuffer_object = "GL_EXT_framebuffer_object"; + public static final String EXT_framebuffer_blit = "GL_EXT_framebuffer_blit"; + public static final String EXT_framebuffer_multisample = "GL_EXT_framebuffer_multisample"; + public static final String EXT_packed_depth_stencil = "GL_EXT_packed_depth_stencil"; + public static final String OES_depth24 = "GL_OES_depth24"; + public static final String OES_depth32 = "GL_OES_depth32"; + public static final String OES_packed_depth_stencil = "GL_OES_packed_depth_stencil"; + public static final String NV_fbo_color_attachments = "GL_NV_fbo_color_attachments"; + + public static final String ARB_ES2_compatibility = "GL_ARB_ES2_compatibility"; + + public static final String EXT_abgr = "GL_EXT_abgr"; + public static final String OES_rgb8_rgba8 = "GL_OES_rgb8_rgba8"; + public static final String OES_stencil1 = "GL_OES_stencil1"; + public static final String OES_stencil4 = "GL_OES_stencil4"; + public static final String OES_stencil8 = "GL_OES_stencil8"; + public static final String APPLE_float_pixels = "GL_APPLE_float_pixels"; + + public static final String ARB_texture_non_power_of_two = "GL_ARB_texture_non_power_of_two"; + public static final String ARB_texture_rectangle = "GL_ARB_texture_rectangle"; + public static final String EXT_texture_rectangle = "GL_EXT_texture_rectangle"; + public static final String NV_texture_rectangle = "GL_NV_texture_rectangle"; + public static final String EXT_texture_format_BGRA8888 = "GL_EXT_texture_format_BGRA8888"; + public static final String IMG_texture_format_BGRA8888 = "GL_IMG_texture_format_BGRA8888"; + public static final String EXT_texture_compression_s3tc = "GL_EXT_texture_compression_s3tc"; + public static final String NV_texture_compression_vtc = "GL_NV_texture_compression_vtc"; + public static final String SGIS_generate_mipmap = "GL_SGIS_generate_mipmap"; + public static final String OES_read_format = "GL_OES_read_format"; + + public static final String OES_EGL_image_external = "GL_OES_EGL_image_external"; + + // + // Aliased GLX/WGL/.. extensions + // + + public static final String ARB_pixel_format = "GL_ARB_pixel_format"; + public static final String ARB_pbuffer = "GL_ARB_pbuffer"; +} diff --git a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java index 75785fd86..cdb4b82bb 100644 --- a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java +++ b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java @@ -93,11 +93,13 @@ public class JoglVersion extends JogampVersion { return sb; } - public static StringBuilder getDefaultOpenGLInfo(StringBuilder sb, boolean withCapabilitiesInfo) { + public static StringBuilder getDefaultOpenGLInfo(AbstractGraphicsDevice device, StringBuilder sb, boolean withCapabilitiesInfo) { if(null==sb) { sb = new StringBuilder(); } - final AbstractGraphicsDevice device = GLProfile.getDefaultDevice(); + if(null == device) { + device = GLProfile.getDefaultDevice(); + } sb.append("Default Profiles on device ").append(device).append(Platform.getNewline()); if(null!=device) { GLProfile.glAvailabilityToString(device, sb, "\t", 1); @@ -120,13 +122,21 @@ public class JoglVersion extends JogampVersion { if(null==sb) { sb = new StringBuilder(); } - GLContext ctx = gl.getContext(); - + sb.append(VersionUtil.SEPERATOR).append(Platform.getNewline()); sb.append(device.getClass().getSimpleName()).append("[type ") .append(device.getType()).append(", connection ").append(device.getConnection()).append("]: ").append(Platform.getNewline()); GLProfile.glAvailabilityToString(device, sb, "\t", 1); sb.append(Platform.getNewline()); + + return getGLStrings(gl, sb); + } + + public static StringBuilder getGLStrings(GL gl, StringBuilder sb) { + if(null==sb) { + sb = new StringBuilder(); + } + final GLContext ctx = gl.getContext(); sb.append("Swap Interval ").append(gl.getSwapInterval()); sb.append(Platform.getNewline()); sb.append("GL Profile ").append(gl.getGLProfile()); diff --git a/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java b/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java new file mode 100644 index 000000000..1ea8595c6 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java @@ -0,0 +1,89 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl; + +import javax.media.opengl.GLAutoDrawableDelegate; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLException; + +import jogamp.opengl.GLFBODrawableImpl; + +/** + * Platform-independent class exposing FBO offscreen functionality to + * applications. + *

+ * This class distinguishes itself from {@link GLAutoDrawableDelegate} + * with it's {@link #setSize(int, int)} functionality. + *

+ */ +public class OffscreenAutoDrawable extends GLAutoDrawableDelegate { + + public OffscreenAutoDrawable(GLDrawable drawable, GLContext context, Object upstreamWidget) { + super(drawable, context, upstreamWidget); + } + + /** + * Attempts to resize this offscreen auto drawable, if supported + * by the underlying {@link GLDrawable). + * @param newWidth + * @param newHeight + * @return true if resize was executed, otherwise false. + * @throws GLException in case of an error during the resize operation + */ + public boolean setSize(int newWidth, int newHeight) throws GLException { + boolean done = false; + if(drawable instanceof GLFBODrawableImpl) { + context.makeCurrent(); + try { + ((GLFBODrawableImpl)drawable).setSize(context.getGL(), newWidth, newHeight); + done = true; + } finally { + context.release(); + } + } + if(done) { + this.defaultWindowResizedOp(); + return true; + } + return false; + } + + /** + * If the underlying {@link GLDrawable} is an FBO implementation + * and contains an {#link FBObject}, the same is returned. + * Otherwise returns null. + */ + public FBObject getFBObject() { + if(drawable instanceof GLFBODrawableImpl) { + return ((GLFBODrawableImpl)drawable).getFBObject(); + } + return null; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java index 5ee58b78d..0d9d3ddf5 100644 --- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java +++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java @@ -231,6 +231,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite) */ device = SWTAccessor.getDevice(this); + /* Since we have no means of querying the screen index yet, assume 0. Good choice due to Xinerama alike settings anyways. */ + final int screenIdx = 0; /* Native handle for the control, used to associate with GLContext */ nativeWindowHandle = SWTAccessor.getWindowHandle(this); @@ -243,7 +245,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(caps.getGLProfile()); /* Create a NativeWindow proxy for the SWT canvas */ - proxySurface = glFactory.createProxySurface(device, nativeWindowHandle, caps, chooser); + proxySurface = glFactory.createProxySurface(device, screenIdx, nativeWindowHandle, caps, chooser, swtCanvasUpStreamHook); /* Associate a GL surface with the proxy */ drawable = glFactory.createGLDrawable(proxySurface); @@ -265,12 +267,58 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { addControlListener(new ControlAdapter() { @Override public void controlResized(final ControlEvent arg0) { - clientArea = GLCanvas.this.getClientArea(); - /* Mark for OpenGL reshape next time the control is painted */ - sendReshape = true; + updateSizeCheck(); } }); } + private final ProxySurface.UpstreamSurfaceHook swtCanvasUpStreamHook = new ProxySurface.UpstreamSurfaceHook() { + @Override + public final void create(ProxySurface s) { /* nop */ } + + @Override + public final void destroy(ProxySurface s) { /* nop */ } + + @Override + public final int getWidth(ProxySurface s) { + return clientArea.width; + } + + @Override + public final int getHeight(ProxySurface s) { + return clientArea.height; + } + + @Override + public String toString() { + return "SETUpstreamSurfaceHook[upstream: "+GLCanvas.this.toString()+"]"; + } + + }; + + protected final void updateSizeCheck() { + clientArea = GLCanvas.this.getClientArea(); + if (clientArea != null && + proxySurface.getWidth() != clientArea.width && + proxySurface.getHeight() != clientArea.height) { + sendReshape = true; // Mark for OpenGL reshape next time the control is painted + } + sendReshape = false; + } + + @Override + public final Object getUpstreamWidget() { + return this; + } + + @Override + public int getWidth() { + return clientArea.width; + } + + @Override + public int getHeight() { + return clientArea.height; + } @Override public void addGLEventListener(final GLEventListener arg0) { @@ -417,25 +465,11 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { return (drawable != null) ? drawable.getHandle() : 0; } - @Override - public int getHeight() { - final Rectangle clientArea = this.clientArea; - if (clientArea == null) return 0; - return clientArea.height; - } - @Override public NativeSurface getNativeSurface() { return (drawable != null) ? drawable.getNativeSurface() : null; } - @Override - public int getWidth() { - final Rectangle clientArea = this.clientArea; - if (clientArea == null) return 0; - return clientArea.width; - } - @Override public boolean isRealized() { return (drawable != null) ? drawable.isRealized() : false; @@ -515,7 +549,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { // System.err.println(NativeWindowVersion.getInstance()); System.err.println(JoglVersion.getInstance()); - System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true).toString()); + System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString()); final GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault(GLProfile.getDefaultDevice()) ); final Display display = new Display(); diff --git a/src/jogl/classes/com/jogamp/opengl/util/FBObject.java b/src/jogl/classes/com/jogamp/opengl/util/FBObject.java deleted file mode 100644 index 3e049a334..000000000 --- a/src/jogl/classes/com/jogamp/opengl/util/FBObject.java +++ /dev/null @@ -1,483 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2011 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package com.jogamp.opengl.util; - -import javax.media.opengl.*; - -public class FBObject { - static final int MAX_FBO_TEXTURES = 32; // just for our impl .. not the real 'max' FBO color attachments - private int[] fbo_tex_names; - private int[] fbo_tex_units; - private int fbo_tex_num; - private int colorattachment_num; - - private boolean initialized; - private int width, height; - private int fb, depth_rb, stencil_rb, vStatus; - private boolean bound; - - public FBObject(int width, int height) { - this.fbo_tex_names = new int[MAX_FBO_TEXTURES]; - this.fbo_tex_units = new int[MAX_FBO_TEXTURES]; - this.fbo_tex_num = 0; - this.colorattachment_num = 0; - this.initialized = false; - this.width = width; - this.height = height; - this.fb = 0; - this.depth_rb = 0; - this.stencil_rb = 0; - this.bound = false; - } - - /** - * @return true if the FB status is valid, otherwise false - * @see #getStatus() - */ - public boolean isStatusValid() { - switch(vStatus) { - case GL.GL_FRAMEBUFFER_COMPLETE: - return true; - case GL.GL_FRAMEBUFFER_UNSUPPORTED: - case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: - case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: - case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS: - //case GL2.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: - //case GL2.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: - //case GL2.GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT: - case 0: - default: - System.out.println("Framebuffer " + fb + " is incomplete: status = 0x" + Integer.toHexString(vStatus) + - " : " + getStatusString(vStatus)); - return false; - } - } - - /** - * @return The FB status. {@link GL.GL_FRAMEBUFFER_COMPLETE} if ok, otherwise return GL FBO error state or -1 - * @see #validateStatus() - */ - public int getStatus() { - return vStatus; - } - - public String getStatusString() { - return getStatusString(vStatus); - } - - public static final String getStatusString(int fbStatus) { - switch(fbStatus) { - case -1: - return "NOT A FBO"; - case GL.GL_FRAMEBUFFER_COMPLETE: - return "OK"; - case GL.GL_FRAMEBUFFER_UNSUPPORTED: - return("GL FBO: Unsupported framebuffer format"); - case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - return("GL FBO: incomplete, incomplete attachment\n"); - case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: - return("GL FBO: incomplete, missing attachment"); - case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: - return("GL FBO: incomplete, attached images must have same dimensions"); - case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS: - return("GL FBO: incomplete, attached images must have same format"); - case GL2.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: - return("GL FBO: incomplete, missing draw buffer"); - case GL2.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: - return("GL FBO: incomplete, missing read buffer"); - case GL2.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: - return("GL FBO: incomplete, missing multisample buffer"); - case 0: - return("GL FBO: incomplete, implementation fault"); - default: - return("GL FBO: incomplete, implementation ERROR"); - } - } - - private boolean checkNoError(GL gl, int err, String exceptionMessage) { - if(GL.GL_NO_ERROR != err) { - if(null != gl) { - destroy(gl); - } - if(null != exceptionMessage) { - throw new GLException(exceptionMessage+" GL Error 0x"+Integer.toHexString(err)); - } - return false; - } - return true; - } - - private final void checkInitialized() { - if(!initialized) { - throw new GLException("FBO not initialized, call init(GL) first."); - } - } - - private final void checkBound(GL gl, boolean shallBeBound) { - checkInitialized(); - if(bound != shallBeBound) { - final String s0 = shallBeBound ? "not" : "already" ; - throw new GLException("FBO "+s0+" bound "+toString()); - } - checkNoError(null, gl.glGetError(), "FBObject pre"); // throws GLException if error - } - - /** - * Initializes this FBO's instance with it's texture. - * - *

Leaves the FBO bound!

- * - * @param gl the current GL context - * @throws GLException in case of an error - */ - public void init(GL gl) throws GLException { - if(initialized) { - throw new GLException("FBO already initialized"); - } - checkNoError(null, gl.glGetError(), "FBObject Init.pre"); // throws GLException if error - - // generate fbo .. - int name[] = new int[1]; - - gl.glGenFramebuffers(1, name, 0); - fb = name[0]; - if(fb==0) { - throw new GLException("null generated framebuffer"); - } - - // bind fbo .. - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fb); - checkNoError(gl, gl.glGetError(), "FBObject Init.bindFB"); // throws GLException if error - if(!gl.glIsFramebuffer(fb)) { - checkNoError(gl, GL.GL_INVALID_VALUE, "FBObject Init.isFB"); // throws GLException - } - bound = true; - initialized = true; - - updateStatus(gl); - } - - /** - * Attaches a[nother] Texture2D Color Buffer to this FBO's instance, - * selecting the texture data type and format automatically. - *

This may be done as many times as many color attachments are supported, - * see {@link GL2GL3#GL_MAX_COLOR_ATTACHMENTS}.

- * - *

Assumes a bound FBO

- *

Leaves the FBO bound!

- * - * @param gl the current GL context - * @param texUnit the desired texture unit ranging from [0..{@link GL2#GL_MAX_TEXTURE_UNITS}-1], or -1 if no unit shall be activate at {@link #use(GL, int)} - * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER} - * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} - * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} - * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} - * @return idx of the new attached texture, otherwise -1 - * @throws GLException in case of an error - */ - public int attachTexture2D(GL gl, int texUnit, int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { - final int textureInternalFormat, textureDataFormat, textureDataType; - if(gl.isGLES()) { - textureInternalFormat=GL.GL_RGBA; - textureDataFormat=GL.GL_RGBA; - textureDataType=GL.GL_UNSIGNED_BYTE; - } else { - textureInternalFormat=GL.GL_RGBA8; - textureDataFormat=GL.GL_BGRA; - textureDataType=GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV; - } - return attachTexture2D(gl, texUnit, textureInternalFormat, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT); - } - - /** - * Attaches a[nother] Texture2D Color Buffer to this FBO's instance, - * selecting the texture data type and format automatically. - *

This may be done as many times as many color attachments are supported, - * see {@link GL2GL3#GL_MAX_COLOR_ATTACHMENTS}.

- * - *

Assumes a bound FBO

- *

Leaves the FBO bound!

- * - * @param gl the current GL context - * @param texUnit the desired texture unit ranging from [0..{@link GL2#GL_MAX_TEXTURE_UNITS}-1], or -1 if no unit shall be activate at {@link #use(GL, int)} - * @param textureInternalFormat internalFormat parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} - * @param textureDataFormat format parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} - * @param textureDataType type parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} - * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER} - * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} - * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} - * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} - * @return index of the texture colorbuffer if bound and configured successfully, otherwise -1 - * @throws GLException in case the texture colorbuffer couldn't be allocated - */ - public int attachTexture2D(GL gl, int texUnit, - int textureInternalFormat, int textureDataFormat, int textureDataType, - int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { - checkBound(gl, true); - final int fbo_tex_idx = fbo_tex_num; - gl.glGenTextures(1, fbo_tex_names, fbo_tex_num); - if(fbo_tex_names[fbo_tex_idx]==0) { - throw new GLException("null generated texture"); - } - fbo_tex_units[fbo_tex_idx] = texUnit; - fbo_tex_num++; - if(0<=texUnit) { - gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit); - } - gl.glBindTexture(GL.GL_TEXTURE_2D, fbo_tex_names[fbo_tex_idx]); - checkNoError(gl, gl.glGetError(), "FBObject Init.bindTex"); // throws GLException if error - gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, textureInternalFormat, width, height, 0, - textureDataFormat, textureDataType, null); - int glerr = gl.glGetError(); - if(GL.GL_NO_ERROR != glerr) { - int[] sz = new int[1]; - gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, sz, 0); - // throws GLException if error - checkNoError(gl, glerr, "FBObject Init.texImage2D: "+ - " int-fmt 0x"+Integer.toHexString(textureInternalFormat)+ - ", "+width+"x"+height+ - ", data-fmt 0x"+Integer.toHexString(textureDataFormat)+ - ", data-type 0x"+Integer.toHexString(textureDataType)+ - ", max tex-sz "+sz[0]); - } - if( 0 < magFilter ) { - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, magFilter); - } - if( 0 < minFilter ) { - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, minFilter); - } - if( 0 < wrapS ) { - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, wrapS); - } - if( 0 < wrapT ) { - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapT); - } - - // Set up the color buffer for use as a renderable texture: - gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, - GL.GL_COLOR_ATTACHMENT0 + colorattachment_num++, - GL.GL_TEXTURE_2D, fbo_tex_names[fbo_tex_idx], 0); - - updateStatus(gl); - return isStatusValid() ? fbo_tex_idx : -1; - } - - /** - * Attaches one Depth Buffer to this FBO's instance. - *

This may be done only one time.

- * - *

Assumes a bound FBO

- *

Leaves the FBO bound!

- * @param gl the current GL context - * @param depthComponentType {@link GL#GL_DEPTH_COMPONENT16}, {@link GL#GL_DEPTH_COMPONENT24} or {@link GL#GL_DEPTH_COMPONENT32} - * @return true if the depth renderbuffer could be bound and configured, otherwise false - * @throws GLException in case the depth renderbuffer couldn't be allocated or one is already attached. - */ - public boolean attachDepthBuffer(GL gl, int depthComponentType) throws GLException { - checkBound(gl, true); - if(depth_rb != 0) { - throw new GLException("FBO depth buffer already attached (rb "+depth_rb+")"); - } - int name[] = new int[1]; - gl.glGenRenderbuffers(1, name, 0); - depth_rb = name[0]; - if(depth_rb==0) { - throw new GLException("null generated renderbuffer"); - } - // Initialize the depth buffer: - gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, depth_rb); - if(!gl.glIsRenderbuffer(depth_rb)) { - System.err.println("not a depthbuffer: "+ depth_rb); - name[0] = depth_rb; - gl.glDeleteRenderbuffers(1, name, 0); - depth_rb=0; - return false; - } - - gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, depthComponentType, width, height); - // Set up the depth buffer attachment: - gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, - GL.GL_DEPTH_ATTACHMENT, - GL.GL_RENDERBUFFER, depth_rb); - updateStatus(gl); - return isStatusValid(); - } - - /** - * Attaches one Stencil Buffer to this FBO's instance. - *

This may be done only one time.

- * - *

Assumes a bound FBO

- *

Leaves the FBO bound!

- * @param gl the current GL context - * @param stencilComponentType {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4} or {@link GL#GL_STENCIL_INDEX8} - * @return true if the stencil renderbuffer could be bound and configured, otherwise false - * @throws GLException in case the stencil renderbuffer couldn't be allocated or one is already attached. - */ - public boolean attachStencilBuffer(GL gl, int stencilComponentType) throws GLException { - checkBound(gl, true); - if(stencil_rb != 0) { - throw new GLException("FBO stencil buffer already attached (rb "+stencil_rb+")"); - } - int name[] = new int[1]; - gl.glGenRenderbuffers(1, name, 0); - stencil_rb = name[0]; - if(stencil_rb==0) { - throw new GLException("null generated stencilbuffer"); - } - // Initialize the stencil buffer: - gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, stencil_rb); - if(!gl.glIsRenderbuffer(stencil_rb)) { - System.err.println("not a stencilbuffer: "+ stencil_rb); - name[0] = stencil_rb; - gl.glDeleteRenderbuffers(1, name, 0); - stencil_rb=0; - return false; - } - gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, stencilComponentType, width, height); - gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, - GL.GL_STENCIL_ATTACHMENT, - GL.GL_RENDERBUFFER, stencil_rb); - updateStatus(gl); - return isStatusValid(); - } - - /** - * @param gl the current GL context - */ - public void destroy(GL gl) { - if(bound) { - unbind(gl); - } - - int name[] = new int[1]; - - if(0!=stencil_rb) { - name[0] = stencil_rb; - gl.glDeleteRenderbuffers(1, name, 0); - stencil_rb = 0; - } - if(0!=depth_rb) { - name[0] = depth_rb; - gl.glDeleteRenderbuffers(1, name, 0); - depth_rb=0; - } - if(null!=fbo_tex_names && fbo_tex_num>0) { - gl.glDeleteTextures(1, fbo_tex_names, fbo_tex_num); - fbo_tex_names = new int[MAX_FBO_TEXTURES]; - fbo_tex_units = new int[MAX_FBO_TEXTURES]; - fbo_tex_num = 0; - } - colorattachment_num = 0; - if(0!=fb) { - name[0] = fb; - gl.glDeleteFramebuffers(1, name, 0); - fb = 0; - } - initialized = false; - } - - /** - * Bind this FBO - *

In case you have attached more than one color buffer, - * you may want to setup {@link GL2GL3#glDrawBuffers(int, int[], int)}.

- * @param gl the current GL context - */ - public void bind(GL gl) { - checkBound(gl, false); - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fb); - bound = true; - } - - /** - * Unbind FBO, ie bind 'non' FBO 0 - * @param gl the current GL context - */ - public void unbind(GL gl) { - checkBound(gl, true); - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); - bound = false; - } - - /** - * Bind the texture with given index. - * - *

If a valid texture unit was named via {@link #attachTexture2D(GL, int, int, int, int, int) attachTexture2D(..)}, - * the unit is activated via {@link GL#glActiveTexture(int) glActiveTexture(GL.GL_TEXTURE0 + unit)}.

- * @param gl the current GL context - * @param texIdx index of the texture to use, prev. attached w/ {@link #attachTexture2D(GL, int, int, int, int, int) attachTexture2D(..)} - */ - public void use(GL gl, int texIdx) { - checkBound(gl, false); - if(texIdx >= fbo_tex_num) { - throw new GLException("Invalid texId, only "+fbo_tex_num+" textures are attached"); - } - if(0<=fbo_tex_units[texIdx]) { - gl.glActiveTexture(GL.GL_TEXTURE0 + fbo_tex_units[texIdx]); - } - gl.glBindTexture(GL.GL_TEXTURE_2D, fbo_tex_names[texIdx]); // use it .. - } - - /** Unbind texture, ie bind 'non' texture 0 */ - public void unuse(GL gl) { - checkBound(gl, false); - gl.glBindTexture(GL.GL_TEXTURE_2D, 0); // don't use it - } - - public final boolean isBound() { return bound; } - public final int getWidth() { return width; } - public final int getHeight() { return height; } - public final int getFBName() { return fb; } - public final int getTextureNumber() { return fbo_tex_num; } - public final int getTextureName(int idx) { return fbo_tex_names[idx]; } - - /** @return the named texture unit ranging from [0..{@link GL2#GL_MAX_TEXTURE_UNITS}-1], or -1 if no unit was desired. */ - public final int getTextureUnit(int idx) { return fbo_tex_units[idx]; } - public final int getColorAttachmentNumber() { return colorattachment_num; } - public final int getStencilBuffer() { return stencil_rb; } - public final int getDepthBuffer() { return depth_rb; } - public final String toString() { - return "FBO[name "+fb+", size "+width+"x"+height+", color num "+colorattachment_num+", tex num "+fbo_tex_num+", depth "+depth_rb+", stencil "+stencil_rb+"]"; - } - - private void updateStatus(GL gl) { - if(!gl.glIsFramebuffer(fb)) { - vStatus = -1; - } else { - vStatus = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER); - } - } -} diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java index 8401b9cd2..331d6fa4e 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java @@ -39,6 +39,7 @@ package com.jogamp.opengl.util; import com.jogamp.common.nio.Buffers; + import javax.media.opengl.GL; import javax.media.opengl.GL2; import javax.media.opengl.GL2ES2; @@ -56,22 +57,32 @@ import java.nio.*; public class GLBuffers extends Buffers { /** - * @param glType shall be one of - * GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, - * GL_UNSIGNED_INT, GL_INT, GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE, - * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, - * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, - * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, - * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, - * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV, - * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV - * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV, - * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, - * GL_HILO16_NV, GL_SIGNED_HILO16_NV (27) + * @param glType shall be one of (29)
+ * GL_BYTE, GL_UNSIGNED_BYTE,
+ * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV,
+ *
+ * GL_SHORT, GL_UNSIGNED_SHORT,
+ * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV,
+ * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV,
+ * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV,
+ * GL.GL_HALF_FLOAT, GLES2.GL_HALF_FLOAT_OES:
+ *
+ * GL_FIXED, GL_INT
+ * GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8,
+ * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2,
+ * GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8,
+ * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV
+ * GL_HILO16_NV, GL_SIGNED_HILO16_NV
+ *
+ * GL2GL3.GL_FLOAT_32_UNSIGNED_INT_24_8_REV
+ *
+ * GL_FLOAT, GL_DOUBLE
+ * * @return -1 if glType is unhandled, otherwise the actual value > 0 */ public static final int sizeOfGLType(int glType) { - switch (glType) { // 25 + switch (glType) { // 29 + // case GL2.GL_BITMAP: case GL.GL_BYTE: case GL.GL_UNSIGNED_BYTE: case GL2GL3.GL_UNSIGNED_BYTE_3_3_2: @@ -86,6 +97,8 @@ public class GLBuffers extends Buffers { case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV: case GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1: case GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV: + case GL.GL_HALF_FLOAT: + case GLES2.GL_HALF_FLOAT_OES: return SIZEOF_SHORT; case GL.GL_FIXED: @@ -108,29 +121,38 @@ public class GLBuffers extends Buffers { case GL.GL_FLOAT: return SIZEOF_FLOAT; - case GL2.GL_DOUBLE: + case GL2GL3.GL_DOUBLE: return SIZEOF_DOUBLE; } return -1; } /** - * @param glType shall be one of - * GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, - * GL_UNSIGNED_INT, GL_INT, GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE, - * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, - * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, - * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, - * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, - * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV, - * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV - * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV, - * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, - * GL_HILO16_NV, GL_SIGNED_HILO16_NV (27) + * @param glType shall be one of (29)
+ * GL_BYTE, GL_UNSIGNED_BYTE,
+ * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV,
+ *
+ * GL_SHORT, GL_UNSIGNED_SHORT,
+ * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV,
+ * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV,
+ * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV,
+ * GL_HALF_FLOAT, GL_HALF_FLOAT_OES
+ *
+ * GL_FIXED, GL_INT
+ * GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8,
+ * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2,
+ * GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8,
+ * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV
+ * GL_HILO16_NV, GL_SIGNED_HILO16_NV
+ *
+ * GL_FLOAT_32_UNSIGNED_INT_24_8_REV
+ *
+ * GL_FLOAT, GL_DOUBLE
+ * * @return null if glType is unhandled, otherwise the new Buffer object */ public static final Buffer newDirectGLBuffer(int glType, int numElements) { - switch (glType) { + switch (glType) { // 29 case GL.GL_BYTE: case GL.GL_UNSIGNED_BYTE: case GL2GL3.GL_UNSIGNED_BYTE_3_3_2: @@ -145,6 +167,8 @@ public class GLBuffers extends Buffers { case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV: case GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1: case GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV: + case GL.GL_HALF_FLOAT: + case GLES2.GL_HALF_FLOAT_OES: return newDirectShortBuffer(numElements); case GL.GL_FIXED: @@ -174,18 +198,26 @@ public class GLBuffers extends Buffers { } /** - * @param glType shall be one of - * GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, - * GL_UNSIGNED_INT, GL_INT, GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE, - * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, - * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, - * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, - * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, - * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV, - * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV - * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV, - * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, - * GL_HILO16_NV, GL_SIGNED_HILO16_NV (27) + * @param glType shall be one of (29)
+ * GL_BYTE, GL_UNSIGNED_BYTE,
+ * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV,
+ *
+ * GL_SHORT, GL_UNSIGNED_SHORT,
+ * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV,
+ * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV,
+ * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV,
+ * GL_HALF_FLOAT, GL_HALF_FLOAT_OES
+ *
+ * GL_FIXED, GL_INT
+ * GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8,
+ * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2,
+ * GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8,
+ * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV
+ * GL_HILO16_NV, GL_SIGNED_HILO16_NV
+ *
+ * GL_FLOAT_32_UNSIGNED_INT_24_8_REV
+ *
+ * GL_FLOAT, GL_DOUBLE
* @return null if glType is unhandled or parent is null or bufLen is 0, otherwise the new Buffer object */ public static final Buffer sliceGLBuffer(ByteBuffer parent, int bytePos, int byteLen, int glType) { @@ -195,7 +227,7 @@ public class GLBuffers extends Buffers { parent.position(bytePos); parent.limit(bytePos + byteLen); - switch (glType) { + switch (glType) { // 29 case GL.GL_BYTE: case GL.GL_UNSIGNED_BYTE: case GL2GL3.GL_UNSIGNED_BYTE_3_3_2: @@ -210,6 +242,8 @@ public class GLBuffers extends Buffers { case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV: case GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1: case GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV: + case GL.GL_HALF_FLOAT: + case GLES2.GL_HALF_FLOAT_OES: return parent.asShortBuffer(); case GL.GL_FIXED: @@ -362,28 +396,46 @@ public class GLBuffers extends Buffers { * * @param tmp a pass through integer array of size >= 1 used to store temp data (performance) * - * @param format must be one of - * GL_COLOR_INDEX, GL_STENCIL_INDEX, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL, - * GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_LUMINANCE, - * GL_RG, GL_LUMINANCE_ALPHA, - * GL_RGB, GL_BGR, GL_RGBA, GL_BGRA, GL_ABGR_EXT, - * GL_RED_INTEGER, GL_GREEN_INTEGER, GL_BLUE_INTEGER, - * GL_RG_INTEGER, GL_RGB_INTEGER, GL_BGR_INTEGER, - * GL_RGBA_INTEGER, GL_BGRA_INTEGER, GL_HILO_NV, GL_SIGNED_HILO_NV (26) + * @param format must be one of (26)
+ * GL_COLOR_INDEX GL_STENCIL_INDEX
+ * GL_DEPTH_COMPONENT GL_DEPTH_STENCIL
+ * GL_RED GL_RED_INTEGER
+ * GL_GREEN GL_GREEN_INTEGER
+ * GL_BLUE GL_BLUE_INTEGER
+ * GL_ALPHA GL_LUMINANCE (12)
+ *
+ * GL_LUMINANCE_ALPHA GL_RG
+ * GL_RG_INTEGER GL_HILO_NV
+ * GL_SIGNED_HILO_NV (5)
+ *
+ * GL_RGB GL_RGB_INTEGER
+ * GL_BGR GL_BGR_INTEGER (4)
+ *
+ * GL_RGBA GL_RGBA_INTEGER
+ * GL_BGRA GL_BGRA_INTEGER
+ * GL_ABGR_EXT (5)
* - * @param type must be one of - * GL_BITMAP, - * GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, - * GL_UNSIGNED_INT, GL_INT, GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE, - * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, - * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, - * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, - * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, - * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV, - * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV - * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV, - * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, - * GL_HILO16_NV, GL_SIGNED_HILO16_NV (28) + * @param type must be one of (30)
+ * GL_BITMAP,
+ * GL_BYTE, GL_UNSIGNED_BYTE,
+ * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV,
+ *
+ * GL_SHORT, GL_UNSIGNED_SHORT,
+ * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV,
+ * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV,
+ * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV,
+ * GL_HALF_FLOAT, GL_HALF_FLOAT_OES
+ *
+ * GL_FIXED, GL_INT
+ * GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8,
+ * GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2,
+ * GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8,
+ * GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV
+ * GL_HILO16_NV, GL_SIGNED_HILO16_NV
+ *
+ * GL_FLOAT_32_UNSIGNED_INT_24_8_REV
+ *
+ * GL_FLOAT, GL_DOUBLE
* * @param width in pixels * @param height in pixels @@ -402,7 +454,7 @@ public class GLBuffers extends Buffers { if (height < 0) return 0; if (depth < 0) return 0; - switch (format) /* 24 */ { + switch (format) /* 26 */ { case GL2.GL_COLOR_INDEX: case GL2GL3.GL_STENCIL_INDEX: case GL2GL3.GL_DEPTH_COMPONENT: @@ -445,7 +497,7 @@ public class GLBuffers extends Buffers { throw new GLException("format 0x"+Integer.toHexString(format)+" not supported [yet], pls notify the maintainer in case this is our bug."); } - switch (type) /* 26 */ { + switch (type) /* 30 */ { case GL2.GL_BITMAP: if (GL2.GL_COLOR_INDEX == format || GL2GL3.GL_STENCIL_INDEX == format) { return (depth * (height * ((width+7)/8))); @@ -460,6 +512,7 @@ public class GLBuffers extends Buffers { case GLES2.GL_HALF_FLOAT_OES: esize = 2; break; + case GL.GL_FIXED: case GL2ES2.GL_INT: case GL.GL_UNSIGNED_INT: case GL.GL_FLOAT: diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java index 368cbc0a2..b0fae8a6d 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java @@ -35,6 +35,7 @@ import java.io.IOException; import java.nio.*; import javax.media.opengl.*; +import com.jogamp.opengl.GLExtensions; import com.jogamp.opengl.util.texture.Texture; import com.jogamp.opengl.util.texture.TextureData; import com.jogamp.opengl.util.texture.TextureIO; @@ -67,6 +68,10 @@ public class GLReadBufferUtil { return null!=readTextureData && null!=readPixelBuffer ; } + public boolean hasAlpha() { return 4 == components ? true : false ; } + + public GLPixelStorageModes getGLPixelStorageModes() { return psm; } + /** * @return the raw pixel ByteBuffer, filled by {@link #readPixels(GLAutoDrawable, boolean)} */ @@ -104,13 +109,14 @@ public class GLReadBufferUtil { /** * Read the drawable's pixels to TextureData and Texture, if requested at construction * - * @param gl the current GL object + * @param gl the current GL context object. It's read drawable is being used as the pixel source. * @param drawable the drawable to read from * @param flip weather to flip the data vertically or not * * @see #GLReadBufferUtil(boolean, boolean) */ - public boolean readPixels(GL gl, GLDrawable drawable, boolean flip) { + public boolean readPixels(GL gl, boolean flip) { + final GLDrawable drawable = gl.getContext().getGLReadDrawable(); final int textureInternalFormat, textureDataFormat, textureDataType; final int[] glImplColorReadVals = new int[] { 0, 0 }; @@ -118,7 +124,7 @@ public class GLReadBufferUtil { textureInternalFormat=GL.GL_RGB; textureDataFormat=GL.GL_RGB; textureDataType = GL.GL_UNSIGNED_BYTE; - } else if(gl.isGLES2Compatible() || gl.isExtensionAvailable("GL_OES_read_format")) { + } else if(gl.isGLES2Compatible() || gl.isExtensionAvailable(GLExtensions.OES_read_format)) { gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_FORMAT, glImplColorReadVals, 0); gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_TYPE, glImplColorReadVals, 1); textureInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB; diff --git a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java index 3b817afcf..cf0373044 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java +++ b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java @@ -1,15 +1,20 @@ package com.jogamp.opengl.util; -import com.jogamp.common.util.*; -import com.jogamp.opengl.util.glsl.ShaderState; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.ShortBuffer; +import java.util.ArrayList; +import java.util.Iterator; -import javax.media.opengl.*; -import javax.media.opengl.fixedfunc.*; +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES1; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLException; +import javax.media.opengl.fixedfunc.GLPointerFunc; -import java.nio.*; -import java.util.Iterator; -import java.util.ArrayList; +import com.jogamp.common.util.ReflectionUtil; +import com.jogamp.opengl.util.glsl.ShaderState; public class ImmModeSink { @@ -337,10 +342,8 @@ public class ImmModeSink { enableBuffer(gl, true); if (buffer!=null) { - GL2ES1 glf = gl.getGL2ES1(); - if(null==indices) { - glf.glDrawArrays(mode, 0, count); + gl.glDrawArrays(mode, 0, count); } else { Class clazz = indices.getClass(); int type=-1; @@ -352,7 +355,7 @@ public class ImmModeSink { if(0>type) { throw new GLException("Given Buffer Class not supported: "+clazz+", should be ubyte or ushort:\n\t"+this); } - glf.glDrawElements(mode, indices.remaining(), type, indices); + gl.glDrawElements(mode, indices.remaining(), type, indices); // GL2: gl.glDrawRangeElements(mode, 0, indices.remaining()-1, indices.remaining(), type, indices); } } diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java b/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java index fa66673fd..0022d5c2d 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java +++ b/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java @@ -48,6 +48,7 @@ import javax.media.opengl.GLException; import javax.media.opengl.glu.gl2.GLUgl2; import com.jogamp.common.util.IOUtil; +import com.jogamp.opengl.GLExtensions; import com.jogamp.opengl.util.GLPixelStorageModes; import com.jogamp.opengl.util.TGAWriter; @@ -392,7 +393,7 @@ public class Screenshot { private static void checkExtABGR() { GL2 gl = GLUgl2.getCurrentGL2(); - if (!gl.isExtensionAvailable("GL_EXT_abgr")) { + if (!gl.isExtensionAvailable(GLExtensions.EXT_abgr)) { throw new IllegalArgumentException("Saving alpha channel requires GL_EXT_abgr"); } } diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java index 622ee1b79..1735fcddd 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java @@ -41,6 +41,7 @@ package com.jogamp.opengl.util.awt; import com.jogamp.common.nio.Buffers; +import com.jogamp.opengl.GLExtensions; import com.jogamp.opengl.util.*; import com.jogamp.opengl.util.packrect.*; import com.jogamp.opengl.util.texture.*; @@ -1976,7 +1977,7 @@ public class TextRenderer { private final boolean is15Available(GL gl) { if (!checkFor_isExtensionAvailable_GL_VERSION_1_5) { - isExtensionAvailable_GL_VERSION_1_5 = gl.isExtensionAvailable("GL_VERSION_1_5"); + isExtensionAvailable_GL_VERSION_1_5 = gl.isExtensionAvailable(GLExtensions.VERSION_1_5); checkFor_isExtensionAvailable_GL_VERSION_1_5 = true; } return isExtensionAvailable_GL_VERSION_1_5; diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java b/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java index 49d4add5f..e7bf87a36 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java @@ -44,6 +44,7 @@ import javax.media.nativewindow.NativeWindowFactory; import jogamp.opengl.*; +import com.jogamp.opengl.GLExtensions; import com.jogamp.opengl.util.texture.spi.*; /** @@ -262,8 +263,8 @@ public class Texture { * * See the performance tips above for hints * on how to maximize performance when using many Texture objects. - * @param gl TODO - * + * + * @param gl the current GL context * @throws GLException if no OpenGL context was current or if any * OpenGL-related errors occurred */ @@ -448,12 +449,12 @@ public class Texture { // See whether we have automatic mipmap generation support boolean haveAutoMipmapGeneration = - (gl.isExtensionAvailable("GL_VERSION_1_4") || - gl.isExtensionAvailable("GL_SGIS_generate_mipmap")); + (gl.isExtensionAvailable(GLExtensions.VERSION_1_4) || + gl.isExtensionAvailable(GLExtensions.SGIS_generate_mipmap)); // Indicate to the TextureData what functionality is available - data.setHaveEXTABGR(gl.isExtensionAvailable("GL_EXT_abgr")); - data.setHaveGL12(gl.isExtensionAvailable("GL_VERSION_1_2")); + data.setHaveEXTABGR(gl.isExtensionAvailable(GLExtensions.EXT_abgr)); + data.setHaveGL12(gl.isExtensionAvailable(GLExtensions.VERSION_1_2)); // Indicates whether both width and height are power of two boolean isPOT = isPowerOfTwo(imgWidth) && isPowerOfTwo(imgHeight); @@ -646,7 +647,7 @@ public class Texture { int minFilter = (data.getMipmap() ? GL.GL_LINEAR_MIPMAP_LINEAR : GL.GL_LINEAR); int magFilter = GL.GL_LINEAR; - int wrapMode = (gl.isExtensionAvailable("GL_VERSION_1_2") || !gl.isGL2()) ? GL.GL_CLAMP_TO_EDGE : GL2.GL_CLAMP; + int wrapMode = (gl.isExtensionAvailable(GLExtensions.VERSION_1_2) || !gl.isGL2()) ? GL.GL_CLAMP_TO_EDGE : GL2.GL_CLAMP; // REMIND: figure out what to do for GL_TEXTURE_RECTANGLE_ARB if (texTarget != GL2.GL_TEXTURE_RECTANGLE_ARB) { @@ -925,8 +926,8 @@ public class Texture { private void updateSubImageImpl(GL gl, TextureData data, int newTarget, int mipmapLevel, int dstx, int dsty, int srcx, int srcy, int width, int height) throws GLException { - data.setHaveEXTABGR(gl.isExtensionAvailable("GL_EXT_abgr")); - data.setHaveGL12(gl.isExtensionAvailable("GL_VERSION_1_2")); + data.setHaveEXTABGR(gl.isExtensionAvailable(GLExtensions.EXT_abgr)); + data.setHaveGL12(gl.isExtensionAvailable(GLExtensions.VERSION_1_2)); Buffer buffer = data.getBuffer(); if (buffer == null && data.getMipmapData() == null) { @@ -1044,8 +1045,8 @@ public class Texture { case GL.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: case GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: case GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - if (!gl.isExtensionAvailable("GL_EXT_texture_compression_s3tc") && - !gl.isExtensionAvailable("GL_NV_texture_compression_vtc")) { + if (!gl.isExtensionAvailable(GLExtensions.EXT_texture_compression_s3tc) && + !gl.isExtensionAvailable(GLExtensions.NV_texture_compression_vtc)) { throw new GLException("DXTn compressed textures not supported by this graphics card"); } break; @@ -1081,7 +1082,7 @@ public class Texture { private static boolean haveTexRect(GL gl) { return (!disableTexRect && TextureIO.isTexRectEnabled() && - gl.isExtensionAvailable("GL_ARB_texture_rectangle")); + gl.isExtensionAvailable(GLExtensions.ARB_texture_rectangle)); } private static boolean preferTexRect(GL gl) { diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java index ca97cdc4b..b878c6002 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java @@ -155,6 +155,14 @@ public class TextureIO { file. */ public static final String TIFF = "tiff"; + /** Constant which can be used as a file suffix to indicate a PAM + file, NetPbm magic 7 - binary RGB and RGBA. Write support only. */ + public static final String PAM = "pam"; + + /** Constant which can be used as a file suffix to indicate a PAM + file, NetPbm magic 6 - binary RGB. Write support only. */ + public static final String PPM = "ppm"; + private static final boolean DEBUG = Debug.debug("TextureIO"); // For manually disabling the use of the texture rectangle diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java index 5ee2104a3..6b41c0bc8 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java @@ -102,7 +102,6 @@ import javax.media.opengl.GL; */ public interface TextureSequence { public static final String GL_OES_EGL_image_external_Required_Prelude = "#extension GL_OES_EGL_image_external : enable\n"; - public static final String GL_OES_EGL_image_external = "GL_OES_EGL_image_external"; public static final String samplerExternalOES = "samplerExternalOES"; public static final String sampler2D = "sampler2D"; diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java index c2b131b97..cd42a1157 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java @@ -77,8 +77,10 @@ public class NetPbmTextureWriter implements TextureWriter { public int getMagic() { return magic; } - public static final String PPM = "ppm"; - public static final String PAM = "pam"; + /** @see TextureIO#PPM */ + public static final String PPM = TextureIO.PPM; + /** @see TextureIO#PAM */ + public static final String PAM = TextureIO.PAM; public String getSuffix() { return (magic==6)?PPM:PAM; } diff --git a/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java b/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java index b57b85e5c..1b84bd9bd 100644 --- a/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java +++ b/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java @@ -141,7 +141,7 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser { for (int i = 0; i < scores.length; i++) { scores[i] = NO_SCORE; } - final int gldes_samples = gldes.getSampleBuffers() ? gldes.getNumSamples() : 0; + final int gldes_samples = gldes.getNumSamples(); // Compute score for each for (int i = 0; i < availnum; i++) { @@ -158,8 +158,7 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser { if (gldes.getStereo() != cur.getStereo()) { continue; } - final int cur_samples = - cur.getSampleBuffers() ? cur.getNumSamples() : 0; + final int cur_samples = cur.getNumSamples() ; int score = 0; // Compute difference in color depth diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java index 80d4f796c..0b2c664fe 100644 --- a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java +++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java @@ -51,8 +51,8 @@ import jogamp.opengl.Debug; calls to {@link GLContext#makeCurrent makeCurrent} will block if the context is current on another thread. This allows the internal GLContext for the GLAutoDrawable to be used both by the event - based rendering mechanism as well by end users directly.

- + based rendering mechanism as well by end users directly. +

The implementation shall initialize itself as soon as possible, ie if the attached {@link javax.media.nativewindow.NativeSurface NativeSurface} becomes visible/realized. The following protocol shall be satisfied: @@ -64,18 +64,18 @@ import jogamp.opengl.Debug; registered {@link GLEventListener}s. This can be done immediatly, or with the followup {@link #display display(..)} call.

  • Send a reshape event by calling {@link GLEventListener#reshape reshape(..)} for all registered {@link GLEventListener}s. This shall be done after the {@link GLEventListener#init init(..)} calls.
  • -

    - +

    +

    Another implementation detail is the drawable reconfiguration. One use case is where a window is being dragged to another screen with a different pixel configuration, ie {@link GLCapabilities}. The implementation - shall be able to detect such cases in conjunction with the associated {@link javax.media.nativewindow.NativeSurface NativeSurface}.
    + shall be able to detect such cases in conjunction with the associated {@link javax.media.nativewindow.NativeSurface NativeSurface}.
    For example, AWT's {@link java.awt.Canvas} 's {@link java.awt.Canvas#getGraphicsConfiguration getGraphicsConfiguration()} is capable to determine a display device change. This is demonstrated within {@link javax.media.opengl.awt.GLCanvas}'s and NEWT's AWTCanvas {@link javax.media.opengl.awt.GLCanvas#getGraphicsConfiguration getGraphicsConfiguration()} specialization. Another demonstration is NEWT's {@link javax.media.nativewindow.NativeWindow NativeWindow} - implementation on the Windows platform, which utilizes the native platform's MonitorFromWindow(HWND) function.
    + implementation on the Windows platform, which utilizes the native platform's MonitorFromWindow(HWND) function.
    All OpenGL resources shall be regenerated, while the drawable's {@link GLCapabilities} has - to be choosen again. The following protocol shall be satisfied. + to be chosen again. The following protocol shall be satisfied.

    • Controlled disposal:
      • @@ -97,16 +97,16 @@ import jogamp.opengl.Debug;
      Note: Current graphics driver keep the surface configuration for a given window, even if the window is moved to a monitor with a different pixel configuration, ie 32bpp to 16bpp. However, it is best to not assume such behavior - and make your application comply with the above protocol.

      - - However, to not introduce to much breakage with older applications and because of the situation + and make your application comply with the above protocol. +

      + Avoiding breakage with older applications and because of the situation mentioned above, the boolean system property jogl.screenchange.action will control the - screen change action as follows:
      - + screen change action as follows:

           -Djogl.screenchange.action=false Disable the drawable reconfiguration (the default)
           -Djogl.screenchange.action=true  Enable  the drawable reconfiguration
           
      +

      */ public interface GLAutoDrawable extends GLDrawable { /** Flag reflecting wheather the drawable reconfiguration will be issued in @@ -362,5 +362,29 @@ public interface GLAutoDrawable extends GLDrawable { demos for examples. @return the set GL pipeline or null if not successful */ public GL setGL(GL gl); + + /** + * Method may return the upstream UI toolkit object + * holding this {@link GLAutoDrawable} instance, if exist. + *

      + * Currently known Java UI toolkits and it's known return types are: + * + * + *
      Toolkit GLAutoDrawable Implementation ~ Return Type of getUpstreamWidget() + *
      NEWT {@link com.jogamp.newt.opengl.GLWindow} has a {@link com.jogamp.newt.Window} + *
      SWT {@link com.jogamp.opengl.swt.GLCanvas} is a {@link org.eclipse.swt.widgets.Canvas} + *
      AWT {@link javax.media.opengl.awt.GLCanvas} is a {@link java.awt.Canvas} + *
      AWT {@link javax.media.opengl.awt.GLJPanel} is a {@link javax.swing.JPanel} + *
      + * However, the result may be other object types than the listed above + * due to new supported toolkits. + *

      + *

      + * This method may also return null if no UI toolkit is being used, + * as common for offscreen rendering. + *

      + * @return + */ + public Object getUpstreamWidget(); } diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java index 89d5cc4cb..1f6166719 100644 --- a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java +++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java @@ -56,8 +56,14 @@ import jogamp.opengl.GLDrawableImpl; public class GLAutoDrawableDelegate extends GLAutoDrawableBase { public static final boolean DEBUG = Debug.debug("GLAutoDrawableDelegate"); - public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context) { + /** + * @param drawable + * @param context + * @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}. + */ + public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context, Object upstreamWidget) { super((GLDrawableImpl)drawable, (GLContextImpl)context); + this.upstreamWidget = null; } // @@ -80,8 +86,14 @@ public class GLAutoDrawableDelegate extends GLAutoDrawableBase { // Complete GLAutoDrawable // - private RecursiveLock lock = LockFactory.createRecursiveLock(); // instance wide lock - + private final RecursiveLock lock = LockFactory.createRecursiveLock(); // instance wide lock + private final Object upstreamWidget; + + @Override + public final Object getUpstreamWidget() { + return upstreamWidget; + } + /** * {@inheritDoc} *

      diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java index bd24b15bc..f5831a72d 100644 --- a/src/jogl/classes/javax/media/opengl/GLBase.java +++ b/src/jogl/classes/javax/media/opengl/GLBase.java @@ -340,5 +340,60 @@ public interface GLBase { * completeness. */ public Object getExtension(String extensionName); + + /** Aliased entrypoint of void {@native glClearDepth}(GLclampd depth); and void {@native glClearDepthf}(GLclampf depth); . */ + public void glClearDepth( double depth ); + + /** Aliased entrypoint of void {@native glDepthRange}(GLclampd depth); and void {@native glDepthRangef}(GLclampf depth); . */ + public void glDepthRange(double zNear, double zFar); + + /** + * @param target a GL buffer (VBO) target as used in {@link GL#glBindBuffer(int, int)}, ie {@link GL#GL_ELEMENT_ARRAY_BUFFER}, {@link GL#GL_ARRAY_BUFFER}, .. + * @return the GL buffer (VBO) name bound to a target via {@link GL#glBindBuffer(int, int)} or 0 if unbound. + */ + public int glGetBoundBuffer(int target); + + /** + * @param buffer a GL buffer name, generated with {@link GL#glGenBuffers(int, int[], int)} and used in {@link GL#glBindBuffer(int, int)}, {@link GL#glBufferData(int, long, java.nio.Buffer, int)} or {@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)} for example. + * @return the size of the given GL buffer + */ + public long glGetBufferSize(int buffer); + + /** + * @return true if a VBO is bound to {@link GL.GL_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false + */ + public boolean glIsVBOArrayEnabled(); + + /** + * @return true if a VBO is bound to {@link GL.GL_ELEMENT_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false + */ + public boolean glIsVBOElementArrayEnabled(); + + /** + * Return the framebuffer name bound to this context, + * see {@link GL#glBindFramebuffer(int, int)}. + */ + public int getBoundFramebuffer(int target); + + /** + * Return the default draw framebuffer name. + *

      + * May differ from it's default zero + * in case an framebuffer object ({@link FBObject}) based drawable + * is being used. + *

      + */ + public int getDefaultDrawFramebuffer(); + + /** + * Return the default read framebuffer name. + *

      + * May differ from it's default zero + * in case an framebuffer object ({@link FBObject}) based drawable + * is being used. + *

      + */ + public int getDefaultReadFramebuffer(); + } diff --git a/src/jogl/classes/javax/media/opengl/GLCapabilities.java b/src/jogl/classes/javax/media/opengl/GLCapabilities.java index e5258bcfd..8845ec665 100644 --- a/src/jogl/classes/javax/media/opengl/GLCapabilities.java +++ b/src/jogl/classes/javax/media/opengl/GLCapabilities.java @@ -183,8 +183,8 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil return -1; } - final int ms = sampleBuffers ? numSamples : 0; - final int xms = caps.getSampleBuffers() ? caps.getNumSamples() : 0; + final int ms = getNumSamples(); + final int xms = caps.getNumSamples() ; if(ms > xms) { return 1; @@ -231,15 +231,13 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil /** * Enables or disables pbuffer usage. *

      - * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)} - * and {@link #setFBO(int) setFBO(false)}
      + * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}. *

      * Defaults to false. */ public void setPBuffer(boolean enable) { if(enable) { setOnscreen(false); - setFBO(false); } isPBuffer = enable; } @@ -252,28 +250,28 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil /** * Enables or disables FBO usage. *

      - * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)} - * and {@link #setPBuffer(int) setPBuffer(false)}
      + * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}. *

      * Defaults to false. */ public void setFBO(boolean enable) { if(enable) { setOnscreen(false); - setPBuffer(false); } isFBO = enable; } /** * Sets whether the drawable surface supports onscreen.
      - * If enabled this method also invokes {@link #setPBuffer(int) setPBuffer(false)}
      + * If enabled this method also invokes {@link #setPBuffer(int) setPBuffer(false)} + * and {@link #setFBO(int) setFBO(false)}
      * Defaults to true. */ @Override public void setOnscreen(boolean onscreen) { if(onscreen) { setPBuffer(false); + setFBO(false); } super.setOnscreen(onscreen); } @@ -413,15 +411,18 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil return sampleBuffers; } - /** If sample buffers are enabled, indicates the number of buffers - to be allocated. Defaults to 2. */ + /** + * If sample buffers are enabled, indicates the number of buffers + * to be allocated. Defaults to 2. + * @see #getNumSamples() + */ public void setNumSamples(int numSamples) { this.numSamples = numSamples; } @Override public final int getNumSamples() { - return numSamples; + return sampleBuffers ? numSamples : 0; } /** For pbuffers only, indicates whether floating-point buffers @@ -492,12 +493,14 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil if(!isOnscreen()) { if(isFBO) { sink.append(", fbo"); - } else if(isPBuffer) { + } + if(isPBuffer) { sink.append(", pbuffer [r2t ").append(pbufferRenderToTexture?1:0) .append(", r2tr ").append(pbufferRenderToTextureRectangle?1:0) .append(", float ").append(pbufferFloatingPointBuffers?1:0) .append("]"); - } else { + } + if(!isFBO && !isPBuffer) { sink.append(", pixmap"); } } diff --git a/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java b/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java index 883f3912e..7e0459b2d 100644 --- a/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java +++ b/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java @@ -111,7 +111,7 @@ public interface GLCapabilitiesImmutable extends CapabilitiesImmutable { /** * Returns the number of sample buffers to be allocated if sample - * buffers are enabled. Defaults to 2. + * buffers are enabled, otherwise returns 0. Defaults to 2. */ int getNumSamples(); @@ -144,12 +144,12 @@ public interface GLCapabilitiesImmutable extends CapabilitiesImmutable { boolean getStereo(); /** - * Indicates whether pbuffer is used/requested. + * Indicates whether pbuffer offscreen is used/requested. */ boolean isPBuffer(); /** - * Indicates whether FBO is used/requested. + * Indicates whether FBO offscreen is used/requested. */ boolean isFBO(); diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java index 351f90027..63a02ad9c 100644 --- a/src/jogl/classes/javax/media/opengl/GLContext.java +++ b/src/jogl/classes/javax/media/opengl/GLContext.java @@ -55,6 +55,7 @@ import com.jogamp.common.os.Platform; import com.jogamp.common.util.IntObjectHashMap; import com.jogamp.common.util.locks.LockFactory; import com.jogamp.common.util.locks.RecursiveLock; +import com.jogamp.opengl.GLExtensions; /** Abstraction for an OpenGL rendering context. In order to perform OpenGL rendering, a context must be "made current" on the current @@ -69,6 +70,7 @@ import com.jogamp.common.util.locks.RecursiveLock; abstraction provides a stable object which clients can use to refer to a given context. */ public abstract class GLContext { + /** * If true (default), bootstrapping the available GL profiles * will use the highest compatible GL context for each profile, @@ -120,13 +122,13 @@ public abstract class GLContext { protected static final int CTX_PROFILE_ES = 1 << 3; /** ARB_create_context related: flag forward compatible. Cache key value. See {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */ protected static final int CTX_OPTION_FORWARD = 1 << 4; - /** ARB_create_context related: flag debug. Not a cache key. See {@link #setContextCreationFlags(int)}, {@link GLAutoDrawable#setContextCreationFlags(int)}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */ + /** ARB_create_context related: flag debug. Cache key value. See {@link #setContextCreationFlags(int)}, {@link GLAutoDrawable#setContextCreationFlags(int)}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */ public static final int CTX_OPTION_DEBUG = 1 << 5; /** GL_ARB_ES2_compatibility implementation related: Context is compatible w/ ES2. Not a cache key. See {@link #isGLES2Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */ protected static final int CTX_IMPL_ES2_COMPAT = 1 << 8; - /** Context supports FBO, details see {@link #hasFBO()}. + /** Context supports basic FBO, details see {@link #hasFBO()}. * Not a cache key. * @see #hasFBO() * @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile) @@ -136,16 +138,6 @@ public abstract class GLContext { /** Context uses software rasterizer, otherwise hardware rasterizer. Cache key value. See {@link #isHardwareRasterizer()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */ protected static final int CTX_IMPL_ACCEL_SOFT = 1 << 15; - protected static final String GL_ARB_ES2_compatibility = "GL_ARB_ES2_compatibility"; - protected static final String GL_ARB_framebuffer_object = "GL_ARB_framebuffer_object"; - protected static final String GL_EXT_framebuffer_object = "GL_EXT_framebuffer_object"; - protected static final String GL_EXT_framebuffer_blit = "GL_EXT_framebuffer_blit"; - protected static final String GL_EXT_framebuffer_multisample = "GL_EXT_framebuffer_multisample"; - protected static final String GL_EXT_packed_depth_stencil = "GL_EXT_packed_depth_stencil"; - protected static final String GL_ARB_texture_non_power_of_two = "GL_ARB_texture_non_power_of_two"; - protected static final String GL_EXT_texture_format_BGRA8888 = "GL_EXT_texture_format_BGRA8888"; - protected static final String GL_IMG_texture_format_BGRA8888 = "GL_IMG_texture_format_BGRA8888"; - private static final ThreadLocal currentContext = new ThreadLocal(); private final HashMap attachedObjectsByString = new HashMap(); @@ -639,11 +631,19 @@ public abstract class GLContext { return 0 == ( ctxOptions & CTX_IMPL_ACCEL_SOFT ) ; } - /** Returns whether the context supports FBO, hence is either GL-ES >= 2.0, >= core GL 3.0 or implements the extensions - * GL_ARB_ES2_compatibility, ARB_framebuffer_object or all of - * EXT_framebuffer_object, EXT_framebuffer_multisample, - * EXT_framebuffer_blit, GL_EXT_packed_depth_stencil. + /** + * Returns true if basic FBO support is available, otherwise false. + *

      + * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= core 3.0 or implements the extensions + * GL_ARB_ES2_compatibility, GL_ARB_framebuffer_object, GL_EXT_framebuffer_object or GL_OES_framebuffer_object. + *

      + *

      + * Basic FBO support may only include one color attachment and no multisampling, + * as well as limited internal formats for renderbuffer. + *

      * @see #CTX_IMPL_FBO + * @see com.jogamp.opengl.FBObject#supportsBasicFBO(GL) + * @see com.jogamp.opengl.FBObject#supportsFullFBO(GL) */ public final boolean hasFBO() { return 0 != ( ctxOptions & CTX_IMPL_FBO ) ; @@ -659,13 +659,13 @@ public abstract class GLContext { /** Note: The GL impl. may return a const value, ie {@link GLES2#isNPOTTextureAvailable()} always returns true. */ public boolean isNPOTTextureAvailable() { - return isGL3() || isGLES2Compatible() || isExtensionAvailable(GL_ARB_texture_non_power_of_two); + return isGL3() || isGLES2Compatible() || isExtensionAvailable(GLExtensions.ARB_texture_non_power_of_two); } public boolean isTextureFormatBGRA8888Available() { return isGL2GL3() || - isExtensionAvailable(GL_EXT_texture_format_BGRA8888) || - isExtensionAvailable(GL_IMG_texture_format_BGRA8888) ; + isExtensionAvailable(GLExtensions.EXT_texture_format_BGRA8888) || + isExtensionAvailable(GLExtensions.IMG_texture_format_BGRA8888) ; } /** @see GLProfile#isGL4bc() */ @@ -798,7 +798,32 @@ public abstract class GLContext { } protected boolean bindSwapBarrierImpl(int group, int barrier) { /** nop per default .. **/ return false; } - + /** + * Return the framebuffer name bound to this context, + * see {@link GL#glBindFramebuffer(int, int)}. + */ + public abstract int getBoundFramebuffer(int target); + + /** + * Return the default draw framebuffer name. + *

      + * May differ from it's default zero + * in case an framebuffer object ({@link FBObject}) based drawable + * is being used. + *

      + */ + public abstract int getDefaultDrawFramebuffer(); + + /** + * Return the default read framebuffer name. + *

      + * May differ from it's default zero + * in case an framebuffer object ({@link FBObject}) based drawable + * is being used. + *

      + */ + public abstract int getDefaultReadFramebuffer(); + /** * @return The extension implementing the GLDebugOutput feature, * either GL_ARB_debug_output or GL_AMD_debug_output. @@ -984,6 +1009,7 @@ public abstract class GLContext { deviceVersionsAvailableSet.add(devKey); if (DEBUG) { System.err.println(getThreadName() + ": createContextARB: SET mappedVersionsAvailableSet "+devKey); + System.err.println(GLContext.dumpAvailableGLVersions(null).toString()); } } } @@ -1010,6 +1036,10 @@ public abstract class GLContext { validateProfileBits(profile, "profile"); validateProfileBits(resCtp, "resCtp"); + if(DEBUG) { + System.err.println("GLContext.mapAvailableGLVersion: "+device+": "+getGLVersion(reqMajor, 0, profile, null)+" -> "+getGLVersion(resMajor, resMinor, resCtp, null)); + // Thread.dumpStack(); + } final String key = getDeviceVersionAvailableKey(device, reqMajor, profile); final Integer val = new Integer(composeBits(resMajor, resMinor, resCtp)); synchronized(deviceVersionAvailable) { @@ -1122,7 +1152,9 @@ public abstract class GLContext { } else /* if (glpImpl.isGL2()) */ { reqMajorCTP[0]=2; } - if( glpImpl.isGL2() ) { // incl GL3bc and GL4bc + if( glpImpl.isGLES() ) { + reqMajorCTP[1]=CTX_PROFILE_ES; + } else if( glpImpl.isGL2() ) { // incl GL3bc and GL4bc reqMajorCTP[1]=CTX_PROFILE_COMPAT; } else { reqMajorCTP[1]=CTX_PROFILE_CORE; @@ -1141,8 +1173,7 @@ public abstract class GLContext { int _major[] = { 0 }; int _minor[] = { 0 }; int _ctp[] = { 0 }; - if( GLContext.getAvailableGLVersion(device, reqMajorCTP[0], reqMajorCTP[1], - _major, _minor, _ctp)) { + if( GLContext.getAvailableGLVersion(device, reqMajorCTP[0], reqMajorCTP[1], _major, _minor, _ctp)) { return _ctp[0]; } return 0; // n/a @@ -1180,6 +1211,23 @@ public abstract class GLContext { return null; } + /** + * Returns true if it is possible to create an framebuffer object (FBO). + *

      + * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent. + *

      + *

      + * FBO support is queried as described in {@link #hasFBO()}. + *

      + * + * @param device the device to request whether FBO is available for + * @param glp {@link GLProfile} to check for FBO capabilities + * @see GLContext#hasFBO() + */ + public static final boolean isFBOAvailable(AbstractGraphicsDevice device, GLProfile glp) { + return 0 != ( CTX_IMPL_FBO & getAvailableContextProperties(device, glp) ); + } + /** * @param device the device to request whether the profile is available for * @param reqMajor Key Value either 1, 2, 3 or 4 diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java index d6480e7aa..612a02f14 100644 --- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java +++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java @@ -50,9 +50,11 @@ import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.util.ReflectionUtil; import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; import javax.media.opengl.GLProfile.ShutdownType; import jogamp.opengl.Debug; @@ -398,9 +400,18 @@ public abstract class GLDrawableFactory { /** * Creates a Offscreen GLDrawable incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions. *

      - * A Pbuffer drawable/surface is created if both {@link javax.media.opengl.GLCapabilities#isPBuffer() caps.isPBuffer()} - * and {@link #canCreateGLPbuffer(javax.media.nativewindow.AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true.
      - * Otherwise a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated.
      + * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}, see below. + *

      + *

      + * A FBO drawable is created if both {@link javax.media.opengl.GLCapabilities#isFBO() caps.isFBO()} + * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true. + *

      + *

      + * A Pbuffer drawable is created if both {@link javax.media.opengl.GLCapabilities#isPBuffer() caps.isPBuffer()} + * and {@link #canCreateGLPbuffer(javax.media.nativewindow.AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. + *

      + *

      + * If neither FBO nor Pbuffer is available, a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated. *

      * * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be null for the platform's default device. @@ -421,42 +432,31 @@ public abstract class GLDrawableFactory { throws GLException; /** - * Creates an offscreen NativeSurface.
      - * A Pbuffer surface is created if both {@link javax.media.opengl.GLCapabilities#isPBuffer() caps.isPBuffer()} - * and {@link #canCreateGLPbuffer(javax.media.nativewindow.AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true.
      - * Otherwise a simple pixmap/bitmap surface is created. The latter is unlikely to be hardware accelerated.
      - * - * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be null for the platform's default device. - * @param caps the requested GLCapabilties - * @param chooser the custom chooser, may be null for default - * @param width the requested offscreen width - * @param height the requested offscreen height - * @return the created offscreen native surface - * - * @throws GLException if any window system-specific errors caused - * the creation of the GLDrawable to fail. - */ - public abstract NativeSurface createOffscreenSurface(AbstractGraphicsDevice device, - GLCapabilitiesImmutable caps, - GLCapabilitiesChooser chooser, - int width, int height); - - /** - * Highly experimental API entry, allowing developer of new windowing system bindings - * to leverage the native window handle to produce a NativeSurface implementation (ProxySurface), having the required GLCapabilities.
      - * Such surface can be used to instantiate a GLDrawable and hence test your new binding w/o the - * costs of providing a full set of abstraction like the AWT GLCanvas or even the native NEWT bindings. + * Creates a proxy {@link NativeSurface} w/ defined surface handle, i.e. a {@link WrappedSurface} or {@link GDISurface} instance. + *

      + * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}. + *

      + *

      + * Lifecycle (destruction) of the given surface handle shall be handled by the caller. + *

      + *

      + * Such surface can be used to instantiate a GLDrawable. With the help of {@link GLAutoDrawableDelegate} + * you will be able to implement a new native windowing system binding almost on-the-fly, see {@link com.jogamp.opengl.swt.GLCanvas}. + *

      * - * @param device the platform's target device, shall not be null + * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be null for the platform's default device. + * Caller has to ensure it is compatible w/ the given windowHandle + * @param screenIdx matching screen index of given windowHandle * @param windowHandle the native window handle * @param caps the requested GLCapabilties * @param chooser the custom chooser, may be null for default - * @return The proxy surface wrapping the windowHandle on the device + * @param upstream optional {@link ProxySurface.UpstreamSurfaceHook} allowing control of the {@link ProxySurface}'s lifecycle and data it presents. + * @return the created {@link ProxySurface} instance w/ defined surface handle. */ - public abstract ProxySurface createProxySurface(AbstractGraphicsDevice device, + public abstract ProxySurface createProxySurface(AbstractGraphicsDevice device, + int screenIdx, long windowHandle, - GLCapabilitiesImmutable caps, - GLCapabilitiesChooser chooser); + GLCapabilitiesImmutable caps, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream); /** * Returns true if it is possible to create a GLPbuffer. Some older @@ -492,23 +492,7 @@ public abstract class GLDrawableFactory { GLContext shareWith) throws GLException; - /** - * Returns true if it is possible to create an framebuffer object (FBO). - *

      - * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent. - *

      - *

      - * FBO support is queried as described in {@link GLContext#hasFBO()}. - *

      - * - * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be null for the platform's default device. - * @param glp {@link GLProfile} to check for FBO capabilities - * @see GLContext#hasFBO() - */ - public final boolean canCreateFBO(AbstractGraphicsDevice device, GLProfile glp) { - return 0 != ( GLContext.CTX_IMPL_FBO & GLContext.getAvailableContextProperties(device, glp) ); - } - + //---------------------------------------------------------------------- // Methods for interacting with third-party OpenGL libraries diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java index a7200b560..73d13a387 100644 --- a/src/jogl/classes/javax/media/opengl/GLProfile.java +++ b/src/jogl/classes/javax/media/opengl/GLProfile.java @@ -117,10 +117,12 @@ public class GLProfile { * @deprecated Use {@link #initSingleton()}. This method is subject to be removed in future versions of JOGL. */ public static void initSingleton(final boolean firstUIActionOnProcess) { + final boolean justInitialized; initLock.lock(); try { if(!initialized) { // volatile: ok initialized = true; + justInitialized = true; if(DEBUG) { System.err.println("GLProfile.initSingleton(firstUIActionOnProcess: "+firstUIActionOnProcess+") - thread "+Thread.currentThread().getName()); Thread.dumpStack(); @@ -166,10 +168,17 @@ public class GLProfile { return null; } }); + } else { + justInitialized = false; } } finally { initLock.unlock(); } + if(DEBUG) { + if( justInitialized && ( hasGL234Impl || hasGLES1Impl || hasGLES2Impl ) ) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(defaultDevice, null, true)); + } + } } /** @@ -1532,18 +1541,17 @@ public class GLProfile { if(DEBUG) { // System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile+" (desktop: "+addedDesktopProfile+", egl "+addedEGLProfile+")"); - System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile); - System.err.println("GLProfile.init isAWTAvailable "+isAWTAvailable); - System.err.println("GLProfile.init hasDesktopGLFactory "+hasDesktopGLFactory); - System.err.println("GLProfile.init hasGL234Impl "+hasGL234Impl); - System.err.println("GLProfile.init hasEGLFactory "+hasEGLFactory); - System.err.println("GLProfile.init hasGLES1Impl "+hasGLES1Impl); - System.err.println("GLProfile.init hasGLES2Impl "+hasGLES2Impl); - System.err.println("GLProfile.init defaultDevice "+defaultDevice); - System.err.println("GLProfile.init profile order "+array2String(GL_PROFILE_LIST_ALL)); - if(hasGL234Impl || hasGLES1Impl || hasGLES2Impl) { // avoid deadlock - System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true)); - } + System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile); + System.err.println("GLProfile.init isAWTAvailable "+isAWTAvailable); + System.err.println("GLProfile.init hasDesktopGLFactory "+hasDesktopGLFactory); + System.err.println("GLProfile.init hasGL234Impl "+hasGL234Impl); + System.err.println("GLProfile.init hasEGLFactory "+hasEGLFactory); + System.err.println("GLProfile.init hasGLES1Impl "+hasGLES1Impl); + System.err.println("GLProfile.init hasGLES2Impl "+hasGLES2Impl); + System.err.println("GLProfile.init defaultDevice "+defaultDevice); + System.err.println("GLProfile.init defaultDevice Desktop "+defaultDesktopDevice); + System.err.println("GLProfile.init defaultDevice EGL "+defaultEGLDevice); + System.err.println("GLProfile.init profile order "+array2String(GL_PROFILE_LIST_ALL)); } } @@ -1642,24 +1650,6 @@ public class GLProfile { if (DEBUG) { System.err.println("GLProfile.initProfilesForDevice: "+device+": egl Shared Ctx "+eglSharedCtxAvail); } - if( hasGLES2Impl ) { - // The native ES2 impl. overwrites a previous mapping using 'ES2 compatibility' by a desktop profile - GLContext.mapAvailableGLVersion(device, - 2, GLContext.CTX_PROFILE_ES, - 2, 0, GLContext.CTX_PROFILE_ES|GLContext.CTX_IMPL_ES2_COMPAT); - if (DEBUG) { - System.err.println(GLContext.getThreadName() + ": initProfilesForDeviceCritical-MapVersionsAvailable HAVE: ES2 -> ES 2.0"); - } - } - if( hasGLES1Impl ) { - // Always favor the native ES1 impl. - GLContext.mapAvailableGLVersion(device, - 1, GLContext.CTX_PROFILE_ES, - 1, 0, GLContext.CTX_PROFILE_ES); - if (DEBUG) { - System.err.println(GLContext.getThreadName() + ": initProfilesForDeviceCritical-MapVersionsAvailable HAVE: ES1 -> ES 1.0"); - } - } addedEGLProfile = computeProfileMap(device, false /* desktopCtxUndef*/, false /* esCtxUndef */); } @@ -1767,7 +1757,7 @@ public class GLProfile { } _mappedProfiles.put(profile, glProfile); if (DEBUG) { - System.err.println("GLProfile.init map "+glProfile+" on devide "+device.getConnection()); + System.err.println("GLProfile.init map "+glProfile+" on device "+device.getConnection()); } if(null==defaultGLProfileHW && isHardwareRasterizer[0]) { defaultGLProfileHW=glProfile; diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index 48f7ea24a..c2e36ef9b 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -261,6 +261,11 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing this.device = device; } + @Override + public final Object getUpstreamWidget() { + return this; + } + @Override public void setShallUseOffscreenLayer(boolean v) { shallUseOffscreenLayer = v; @@ -1070,7 +1075,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing // System.err.println(NativeWindowVersion.getInstance()); System.err.println(JoglVersion.getInstance()); - System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true).toString()); + System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString()); final GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault(GLProfile.getDefaultDevice()) ); final Frame frame = new Frame("JOGL AWT Test"); diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index cd18c5098..acb8f2183 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -87,7 +87,7 @@ import jogamp.opengl.awt.Java2D; import jogamp.opengl.awt.Java2DGLContext; import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol; -import com.jogamp.opengl.util.FBObject; +import com.jogamp.opengl.FBObject; import com.jogamp.opengl.util.GLBuffers; // FIXME: Subclasses need to call resetGLFunctionAvailability() on their @@ -250,6 +250,11 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing this.shareWith = shareWith; } + @Override + public final Object getUpstreamWidget() { + return this; + } + @Override public void display() { if (EventQueue.isDispatchThread()) { diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java index 804e9ee14..aabef29b0 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java +++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java @@ -32,7 +32,6 @@ import java.nio.FloatBuffer; import javax.media.opengl.GL2ES2; // FIXME: Subsume GL2GL3.GL_DRAW_FRAMEBUFFER -> GL2ES2.GL_DRAW_FRAMEBUFFER ! import javax.media.opengl.GL; -import javax.media.opengl.GLException; import javax.media.opengl.GLUniformData; import javax.media.opengl.fixedfunc.GLMatrixFunc; @@ -45,7 +44,9 @@ import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.curve.opengl.GLRegion; import com.jogamp.graph.curve.opengl.RenderState; -import com.jogamp.opengl.util.FBObject; +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.FBObject.Attachment; +import com.jogamp.opengl.FBObject.TextureAttachment; import com.jogamp.opengl.util.GLArrayDataServer; import com.jogamp.opengl.util.PMVMatrix; import com.jogamp.opengl.util.glsl.ShaderState; @@ -60,6 +61,7 @@ public class VBORegion2PES2 extends GLRegion { private FBObject fbo; + private TextureAttachment texA; private PMVMatrix fboPMVMatrix; GLUniformData mgl_fboPMVMatrix; @@ -72,7 +74,7 @@ public class VBORegion2PES2 extends GLRegion { super(renderModes); fboPMVMatrix = new PMVMatrix(); mgl_fboPMVMatrix = new GLUniformData(UniformNames.gcu_PMVMatrix, 4, 4, fboPMVMatrix.glGetPMvMatrixf()); - mgl_ActiveTexture = new GLUniformData(UniformNames.gcu_TextureUnit, textureEngine); + mgl_ActiveTexture = new GLUniformData(UniformNames.gcu_TextureUnit, textureEngine); } public void update(GL2ES2 gl, RenderState rs) { @@ -214,8 +216,9 @@ public class VBORegion2PES2 extends GLRegion { final ShaderState st = rs.getShaderState(); gl.glViewport(0, 0, width, hight); - st.uniform(gl, mgl_ActiveTexture); - fbo.use(gl, 0); + st.uniform(gl, mgl_ActiveTexture); + gl.glActiveTexture(GL.GL_TEXTURE0 + mgl_ActiveTexture.intValue()); + fbo.use(gl, texA); verticeFboAttr.enableBuffer(gl, true); texCoordFboAttr.enableBuffer(gl, true); indicesFbo.enableBuffer(gl, true); @@ -244,20 +247,16 @@ public class VBORegion2PES2 extends GLRegion { // System.out.println("FBO Scale: " + m.glGetMatrixf().get(0) +" " + m.glGetMatrixf().get(5)); if(null != fbo && fbo.getWidth() != tex_width_c && fbo.getHeight() != tex_height_c ) { - fbo.destroy(gl); - fbo = null; + fbo.reset(gl, tex_width_c, tex_height_c); } - if(null == fbo) { - fbo = new FBObject(tex_width_c, tex_height_c); - fbo.init(gl); + if(null == fbo) { + fbo = new FBObject(); + fbo.reset(gl, tex_width_c, tex_height_c); // FIXME: shall not use bilinear, due to own AA ? However, w/o bilinear result is not smooth - fbo.attachTexture2D(gl, mgl_ActiveTexture.intValue(), GL2ES2.GL_LINEAR, GL2ES2.GL_LINEAR, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE); - // fbo.attachTexture2D(gl, mgl_ActiveTexture.intValue(), GL2ES2.GL_NEAREST, GL2ES2.GL_NEAREST, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE); - fbo.attachDepthBuffer(gl, GL.GL_DEPTH_COMPONENT16); // FIXME: or shall we use 24 or 32 bit depth ? - if(!fbo.isStatusValid()) { - throw new GLException("FBO invalid: "+fbo); - } + texA = fbo.attachTexture2D(gl, 0, true, GL2ES2.GL_LINEAR, GL2ES2.GL_LINEAR, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE); + // texA = fbo.attachTexture2D(gl, 0, GL2ES2.GL_NEAREST, GL2ES2.GL_NEAREST, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE); + fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24); } else { fbo.bind(gl); } @@ -305,6 +304,7 @@ public class VBORegion2PES2 extends GLRegion { if(null != fbo) { fbo.destroy(gl); fbo = null; + texA = null; } if(null != verticeTxtAttr) { st.ownAttribute(verticeTxtAttr, false); diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index 4dd8806fa..e730bc62e 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -49,8 +49,9 @@ import com.jogamp.common.os.DynamicLookupHelper; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.gluegen.runtime.FunctionAddressResolver; import com.jogamp.gluegen.runtime.ProcAddressTable; -import com.jogamp.gluegen.runtime.opengl.GLExtensionNames; +import com.jogamp.gluegen.runtime.opengl.GLNameResolver; import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; +import com.jogamp.opengl.GLExtensions; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; @@ -88,13 +89,14 @@ public abstract class GLContextImpl extends GLContext { // Tracks creation and initialization of buffer objects to avoid // repeated glGet calls upon glMapBuffer operations private GLBufferSizeTracker bufferSizeTracker; // Singleton - Set by GLContextShareSet - private GLBufferStateTracker bufferStateTracker = new GLBufferStateTracker(); - private GLStateTracker glStateTracker = new GLStateTracker(); + private final GLBufferStateTracker bufferStateTracker = new GLBufferStateTracker(); + private final GLStateTracker glStateTracker = new GLStateTracker(); private GLDebugMessageHandler glDebugHandler = null; + private final int[] boundFBOTarget = new int[] { 0, 0 }; // { draw, read } protected GLDrawableImpl drawable; protected GLDrawableImpl drawableRead; - + protected GL gl; protected static final Object mappedContextTypeObjectLock; @@ -140,11 +142,11 @@ public abstract class GLContextImpl extends GLContext { bufferSizeTracker.clearCachedBufferSizes(); } - if (bufferStateTracker != null) { + if (bufferStateTracker != null) { // bufferStateTracker.clearBufferObjectState(); } - if (glStateTracker != null) { + if (glStateTracker != null) { // glStateTracker.clearStates(false); } @@ -156,6 +158,11 @@ public abstract class GLContextImpl extends GLContext { glRenderer = ""; glRendererLowerCase = glRenderer; + + if (boundFBOTarget != null) { // + boundFBOTarget[0] = 0; // draw + boundFBOTarget[1] = 0; // read + } super.resetStates(); } @@ -199,7 +206,7 @@ public abstract class GLContextImpl extends GLContext { drawableRead = (GLDrawableImpl) readWrite; } final GLDrawable old = drawable; - drawable = ( null != readWrite ) ? (GLDrawableImpl) readWrite : null; + drawable = (GLDrawableImpl) readWrite ; if(lockHeld) { makeCurrent(); } @@ -252,16 +259,19 @@ public abstract class GLContextImpl extends GLContext { public void release() throws GLException { release(false); } - private void release(boolean force) throws GLException { + private void release(boolean inDestruction) throws GLException { if(TRACE_SWITCH) { - System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - release() - force: "+force+", "+lock); + System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - release() - force: "+inDestruction+", "+lock); } if ( !lock.isOwner(Thread.currentThread()) ) { throw new GLException("Context not current on current thread "+Thread.currentThread().getName()+": "+this); } - final boolean actualRelease = ( force || lock.getHoldCount() == 1 ) && 0 != contextHandle; + final boolean actualRelease = ( inDestruction || lock.getHoldCount() == 1 ) && 0 != contextHandle; try { if( actualRelease ) { + if( !inDestruction ) { + drawable.contextMadeCurrent(this, false); + } releaseImpl(); } } finally { @@ -306,13 +316,12 @@ public abstract class GLContextImpl extends GLContext { } try { // release current context - if(null != glDebugHandler) { - if(lock.getHoldCount() == 1) { - // needs current context to disable debug handler - makeCurrent(); - } - glDebugHandler.enable(false); + if(lock.getHoldCount() == 1) { + // needs current context to disable debug handler + makeCurrent(); } + drawable.contextRealized(this, false); + glDebugHandler.enable(false); if(lock.getHoldCount() > 1) { // pending release() after makeCurrent() release(true); @@ -488,11 +497,18 @@ public abstract class GLContextImpl extends GLContext { if(TRACE_GL) { gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) ); } + + drawable.contextRealized(this, true); + if(DEBUG || TRACE_SWITCH) { System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT_NEW - "+lock); } - } else if(TRACE_SWITCH) { - System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT - "+lock); + } else { + drawable.contextMadeCurrent(this, true); + + if(TRACE_SWITCH) { + System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT - "+lock); + } } /* FIXME: refactor dependence on Java 2D / JOGL bridge @@ -543,14 +559,11 @@ public abstract class GLContextImpl extends GLContext { final AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration(); final AbstractGraphicsDevice device = config.getScreen().getDevice(); - if( !GLContext.getAvailableGLVersionsSet(device) ) { - final int reqMajor; - final int reqProfile; - if( 0 != ( ctxOptions & GLContext.CTX_PROFILE_ES) ) { - // ES1 or ES2 - reqMajor = ctxMajorVersion; - reqProfile = GLContext.CTX_PROFILE_ES; - } else { + // Non ARB desktop profiles may not have been registered + if( !GLContext.getAvailableGLVersionsSet(device) ) { // not yet set + if( 0 == ( ctxOptions & GLContext.CTX_PROFILE_ES) ) { // not ES profile + final int reqMajor; + final int reqProfile; if(ctxMajorVersion<3 || ctxMajorVersion==3 && ctxMinorVersion==0) { reqMajor = 2; } else { @@ -561,12 +574,13 @@ public abstract class GLContextImpl extends GLContext { } else { reqProfile = GLContext.CTX_PROFILE_COMPAT; } - } - GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, - ctxMajorVersion, ctxMinorVersion, ctxOptions); - GLContext.setAvailableGLVersionsSet(device); - if (DEBUG) { - System.err.println(getThreadName() + ": createContextOLD-MapVersionsAvailable HAVE: " + device+" -> "+reqMajor+"."+reqProfile+ " -> "+getGLVersion()); + GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, + ctxMajorVersion, ctxMinorVersion, ctxOptions); + GLContext.setAvailableGLVersionsSet(device); + + if (DEBUG) { + System.err.println(getThreadName() + ": createContextOLD-MapVersionsAvailable HAVE: " + device+" -> "+reqMajor+"."+reqProfile+ " -> "+getGLVersion()); + } } } } @@ -776,7 +790,7 @@ public abstract class GLContextImpl extends GLContext { } /** - * Note: Since context creation is temproary, caller need to issue {@link #resetStates()}, if creation was successful, i.e. returns true. + * Note: Since context creation is temporary, caller need to issue {@link #resetStates()}, if creation was successful, i.e. returns true. * This method does not reset the states, allowing the caller to utilize the state variables. **/ private final boolean createContextARBMapVersionsAvailable(int reqMajor, int reqProfile) { @@ -1034,22 +1048,29 @@ public abstract class GLContextImpl extends GLContext { table.reset(getDrawableImpl().getGLDynamicLookupHelper() ); } - private final void initGLRendererStrings() { + private final boolean initGLRendererStrings() { final GLDynamicLookupHelper glDynLookupHelper = getDrawableImpl().getGLDynamicLookupHelper(); final long _glGetString = glDynLookupHelper.dynamicLookupFunction("glGetString"); if(0 == _glGetString) { // FIXME System.err.println("Warning: Entry point to 'glGetString' is NULL."); - Thread.dumpStack(); + if(DEBUG) { + Thread.dumpStack(); + } + return false; } else { final String _glRenderer = glGetStringInt(GL.GL_RENDERER, _glGetString); if(null == _glRenderer) { // FIXME - System.err.println("Warning: GL_RENDERER is NULL."); - Thread.dumpStack(); + if(DEBUG) { + System.err.println("Warning: GL_RENDERER is NULL."); + Thread.dumpStack(); + } + return false; } else { glRenderer = _glRenderer; glRendererLowerCase = glRenderer.toLowerCase(); + return true; } } } @@ -1088,17 +1109,20 @@ public abstract class GLContextImpl extends GLContext { } updateGLXProcAddressTable(); - initGLRendererStrings(); + final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration(); + final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); + + if( !initGLRendererStrings() && DEBUG) { + System.err.println("Warning: intialization of GL renderer strings failed. "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)); + } if(!isCurrentContextHardwareRasterizer()) { ctxProfileBits |= GLContext.CTX_IMPL_ACCEL_SOFT; } - final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration(); - final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); contextFQN = getContextFQN(adevice, major, minor, ctxProfileBits); if (DEBUG) { - System.err.println(getThreadName() + ": Context FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)); + System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.0 FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)); } // @@ -1154,11 +1178,10 @@ public abstract class GLContextImpl extends GLContext { } } - if( 0 != ( CTX_PROFILE_ES & ctxProfileBits ) && ctxMajorVersion >= 2 || - isExtensionAvailable(GL_ARB_ES2_compatibility) ) { + if( ( 0 != ( CTX_PROFILE_ES & ctxProfileBits ) && major >= 2 ) || isExtensionAvailable(GLExtensions.ARB_ES2_compatibility) ) { ctxProfileBits |= CTX_IMPL_ES2_COMPAT; ctxProfileBits |= CTX_IMPL_FBO; - } else if( hasFBOImpl(ctxMajorVersion, ctxProfileBits, extensionAvailability) ) { + } else if( hasFBOImpl(major, ctxProfileBits, extensionAvailability) ) { ctxProfileBits |= CTX_IMPL_FBO; } @@ -1168,23 +1191,26 @@ public abstract class GLContextImpl extends GLContext { setContextVersion(major, minor, ctxProfileBits, true); setDefaultSwapInterval(); + + if(DEBUG) { + System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: "+contextFQN+" - "+GLContext.getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, null)); + } } - protected static final boolean hasFBOImpl(int ctxMajorVersion, int ctxProfileBits, ExtensionAvailabilityCache extCache) { - return ( ctxMajorVersion >= 3 ) || // any >= 3.0 GL ctx + protected static final boolean hasFBOImpl(int major, int ctp, ExtensionAvailabilityCache extCache) { + return ( 0 != (ctp & CTX_PROFILE_ES) && major >= 2 ) || // ES >= 2.0 - ( 0 != (ctxProfileBits & CTX_PROFILE_ES) && ctxMajorVersion >= 2 ) || // ES >= 2.0 + major >= 3 || // any >= 3.0 GL ctx ( null != extCache && - ( extCache.isExtensionAvailable(GL_ARB_ES2_compatibility) ) || // ES 2.0 compatible + extCache.isExtensionAvailable(GLExtensions.ARB_ES2_compatibility) || // ES 2.0 compatible - ( extCache.isExtensionAvailable(GL_ARB_framebuffer_object) ) || // ARB_framebuffer_object + extCache.isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object - ( extCache.isExtensionAvailable(GL_EXT_framebuffer_object) && // EXT_framebuffer_object* - extCache.isExtensionAvailable(GL_EXT_framebuffer_multisample) && - extCache.isExtensionAvailable(GL_EXT_framebuffer_blit) && - extCache.isExtensionAvailable(GL_EXT_packed_depth_stencil) ) ); + extCache.isExtensionAvailable(GLExtensions.EXT_framebuffer_object) || // EXT_framebuffer_object + + extCache.isExtensionAvailable(GLExtensions.OES_framebuffer_object) ) ; // OES_framebuffer_object excluded } protected final void removeCachedVersion(int major, int minor, int ctxProfileBits) { @@ -1259,11 +1285,11 @@ public abstract class GLContextImpl extends GLContext { // dynamic function lookup at last incl name aliasing (not cached) DynamicLookupHelper dynLookup = getDrawableImpl().getGLDynamicLookupHelper(); - String tmpBase = GLExtensionNames.normalizeVEN(GLExtensionNames.normalizeARB(glFunctionName, true), true); + String tmpBase = GLNameResolver.normalizeVEN(GLNameResolver.normalizeARB(glFunctionName, true), true); long addr = 0; - int variants = GLExtensionNames.getFuncNamePermutationNumber(tmpBase); + int variants = GLNameResolver.getFuncNamePermutationNumber(tmpBase); for(int i = 0; 0==addr && i < variants; i++) { - String tmp = GLExtensionNames.getFuncNamePermutation(tmpBase, i); + String tmp = GLNameResolver.getFuncNamePermutation(tmpBase, i); try { addr = dynLookup.dynamicLookupFunction(tmp); } catch (Exception e) { } @@ -1317,7 +1343,7 @@ public abstract class GLContextImpl extends GLContext { protected static String getContextFQN(AbstractGraphicsDevice device, int major, int minor, int ctxProfileBits) { // remove non-key values - ctxProfileBits &= ~( GLContext.CTX_OPTION_DEBUG | GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ) ; + ctxProfileBits &= ~( GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ) ; return device.getUniqueID() + "-" + toHexString(composeBits(major, minor, ctxProfileBits)); } @@ -1371,6 +1397,56 @@ public abstract class GLContextImpl extends GLContext { return lock.getQueueLength()>0; } + //--------------------------------------------------------------------------- + // Special FBO hook + // + + /** + * Tracks {@link GL#GL_FRAMEBUFFER}, {@link GL2GL3#GL_DRAW_FRAMEBUFFER} and {@link GL2GL3#GL_READ_FRAMEBUFFER} + * to be returned via {@link #getBoundFramebuffer(int)}. + * + *

      Invoked by {@link GL#glBindFramebuffer(int, int)}.

      + * + *

      Assumes valid framebufferName range of [0..{@link Integer#MAX_VALUE}]

      + * + *

      Does not throw an exception if target is unknown or framebufferName invalid.

      + */ + public final void setBoundFramebuffer(int target, int framebufferName) { + if(0 > framebufferName) { + return; // ignore invalid name + } + switch(target) { + case GL.GL_FRAMEBUFFER: + boundFBOTarget[0] = framebufferName; // draw + boundFBOTarget[1] = framebufferName; // read + break; + case GL2GL3.GL_DRAW_FRAMEBUFFER: + boundFBOTarget[0] = framebufferName; // draw + break; + case GL2GL3.GL_READ_FRAMEBUFFER: + boundFBOTarget[1] = framebufferName; // read + break; + default: // ignore untracked target + } + } + @Override + public final int getBoundFramebuffer(int target) { + switch(target) { + case GL.GL_FRAMEBUFFER: + case GL2GL3.GL_DRAW_FRAMEBUFFER: + return boundFBOTarget[0]; // draw + case GL2GL3.GL_READ_FRAMEBUFFER: + return boundFBOTarget[1]; // read + default: + throw new InternalError("Invalid FBO target name: "+toHexString(target)); + } + } + + @Override + public final int getDefaultDrawFramebuffer() { return drawable.getDefaultDrawFramebuffer(); } + @Override + public final int getDefaultReadFramebuffer() { return drawable.getDefaultReadFramebuffer(); } + //--------------------------------------------------------------------------- // GL_ARB_debug_output, GL_AMD_debug_output helpers // diff --git a/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java b/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java index b950c2fdf..0000e6199 100644 --- a/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java +++ b/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java @@ -37,6 +37,8 @@ import javax.media.opengl.GLException; import com.jogamp.common.os.Platform; import com.jogamp.gluegen.runtime.ProcAddressTable; +import com.jogamp.opengl.GLExtensions; + import jogamp.opengl.gl4.GL4bcProcAddressTable; /** @@ -54,12 +56,6 @@ import jogamp.opengl.gl4.GL4bcProcAddressTable; * the messages are translated to ARB {@link GLDebugMessage}, using {@link GLDebugMessage#translateAMDEvent(javax.media.opengl.GLContext, long, int, int, int, String)}.

      */ public class GLDebugMessageHandler { - /** Extension GL_ARB_debug_output implementing GLDebugMessage */ - public static final String GL_ARB_debug_output = "GL_ARB_debug_output".intern(); - - /** Extension GL_AMD_debug_output implementing GLDebugMessage */ - public static final String GL_AMD_debug_output = "GL_AMD_debug_output".intern(); - private static final boolean DEBUG = Debug.debug("GLDebugMessageHandler"); private static final int EXT_ARB = 1; @@ -131,11 +127,11 @@ public class GLDebugMessageHandler { } return; } - if( ctx.isExtensionAvailable(GL_ARB_debug_output) ) { - extName = GL_ARB_debug_output; + if( ctx.isExtensionAvailable(GLExtensions.ARB_debug_output) ) { + extName = GLExtensions.ARB_debug_output; extType = EXT_ARB; - } else if( ctx.isExtensionAvailable(GL_AMD_debug_output) ) { - extName = GL_AMD_debug_output; + } else if( ctx.isExtensionAvailable(GLExtensions.AMD_debug_output) ) { + extName = GLExtensions.AMD_debug_output; extType = EXT_AMD; } if(DEBUG) { @@ -145,6 +141,8 @@ public class GLDebugMessageHandler { if(0 == extType) { if(DEBUG) { System.err.println("GLDebugMessageHandler: No extension available! "+ctx.getGLVersion()); + System.err.println("GL_EXTENSIONS "+ctx.getGLExtensionCount()); + System.err.println(ctx.getGLExtensionsString()); } return; } @@ -190,11 +188,11 @@ public class GLDebugMessageHandler { } public final boolean isExtensionARB() { - return extName == GL_ARB_debug_output; + return extName == GLExtensions.ARB_debug_output; } public final boolean isExtensionAMD() { - return extName == GL_AMD_debug_output; + return extName == GLExtensions.AMD_debug_output; } /** diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java index e5c44a8d4..897d3fcaf 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java @@ -1,22 +1,22 @@ /* * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. * Copyright (c) 2010 JogAmp Community. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -29,11 +29,11 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * You acknowledge that this software is not designed or intended for use * in the design, construction, operation or maintenance of any nuclear * facility. - * + * * Sun gratefully acknowledges that this software was originally authored * and developed by Kenneth Bradley Russell and Christopher John Kline. */ @@ -47,7 +47,8 @@ import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.OffscreenLayerSurface; import javax.media.nativewindow.ProxySurface; -import javax.media.nativewindow.SurfaceChangeable; +import javax.media.nativewindow.MutableSurface; +import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesImmutable; @@ -88,7 +89,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { return null; } protected abstract GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device); - + /** * Returns the shared device mapped to the device {@link AbstractGraphicsDevice#getConnection()}, * either a preexisting or newly created, or null if creation failed or not supported.
      @@ -115,7 +116,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { } protected abstract AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device); - /** + /** * Returns the GLDynamicLookupHelper * @param profile if EGL/ES, profile 1 refers to ES1 and 2 to ES2, * otherwise the profile is ignored. @@ -125,6 +126,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { //--------------------------------------------------------------------------- // Dispatching GLDrawable construction in respect to the NativeSurface Capabilities // + @Override public GLDrawable createGLDrawable(NativeSurface target) { if (target == null) { throw new IllegalArgumentException("Null target"); @@ -132,23 +134,37 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { final MutableGraphicsConfiguration config = (MutableGraphicsConfiguration) target.getGraphicsConfiguration(); final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); final AbstractGraphicsDevice adevice = config.getScreen().getDevice(); + final boolean isFBOAvailable = GLContext.isFBOAvailable(adevice, chosenCaps.getGLProfile()); GLDrawable result = null; adevice.lock(); try { final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(target, true); if(null != ols) { - // layered surface -> Offscreen/PBuffer + // layered surface -> Offscreen/[FBO|PBuffer] final GLCapabilities chosenCapsMod = (GLCapabilities) chosenCaps.cloneMutable(); chosenCapsMod.setOnscreen(false); - chosenCapsMod.setPBuffer(canCreateGLPbuffer(adevice)); + if( isFBOAvailable ) { + chosenCapsMod.setFBO(true); + } else if(canCreateGLPbuffer(adevice)) { + chosenCapsMod.setPBuffer(true); + } else { + chosenCapsMod.setFBO(false); + chosenCapsMod.setPBuffer(false); + } config.setChosenCapabilities(chosenCapsMod); if(DEBUG) { System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable -> Offscreen-Layer: "+target); } - if( ! ( target instanceof SurfaceChangeable ) ) { + if( ! ( target instanceof MutableSurface ) ) { throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen layered surface: "+target); + } + if( ((GLCapabilitiesImmutable)config.getRequestedCapabilities()).isFBO() && isFBOAvailable ) { + // FIXME JAU: Need to revise passed MutableSurface to work w/ FBO .. + final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(target); + result = new GLFBODrawableImpl(this, dummyDrawable, target, target.getWidth(), target.getHeight(), 0 /* textureUnit */); + } else { + result = createOffscreenDrawableImpl(target); } - result = createOffscreenDrawableImpl(target); } else if(chosenCaps.isOnscreen()) { // onscreen if(DEBUG) { @@ -158,12 +174,18 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { } else { // offscreen if(DEBUG) { - System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable (PBuffer: "+chosenCaps.isPBuffer()+"): "+target); + System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable, FBO-chosen(-avail)/PBuffer: "+chosenCaps.isFBO()+"("+isFBOAvailable+")/"+chosenCaps.isPBuffer()+": "+target); } - if( ! ( target instanceof SurfaceChangeable ) ) { + if( ! ( target instanceof MutableSurface ) ) { throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen: "+target); } - result = createOffscreenDrawableImpl(target); + if( ((GLCapabilitiesImmutable)config.getRequestedCapabilities()).isFBO() && isFBOAvailable ) { + // FIXME JAU: Need to revise passed MutableSurface to work w/ FBO .. + final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(target); + result = new GLFBODrawableImpl(this, dummyDrawable, target, target.getWidth(), target.getHeight(), 0 /* textureUnit */); + } else { + result = createOffscreenDrawableImpl(target); + } } } finally { adevice.unlock(); @@ -176,43 +198,42 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { //--------------------------------------------------------------------------- // - // Onscreen GLDrawable construction + // Onscreen GLDrawable construction // protected abstract GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target); //--------------------------------------------------------------------------- // - // PBuffer Offscreen GLDrawable construction + // PBuffer Offscreen GLDrawable construction // - + + @Override public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device); + @Override public GLPbuffer createGLPbuffer(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height, GLContext shareWith) { - if(height<=0 || height<=0) { - throw new GLException("Width and height of pbuffer must be positive (were (" + - width + ", " + height + "))"); + if(width<=0 || height<=0) { + throw new GLException("initial size must be positive (were (" + width + " x " + height + "))"); } - AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq); if(null == device) { throw new GLException("No shared device for requested: "+deviceReq); } - - if (!canCreateGLPbuffer(device)) { - throw new GLException("Pbuffer support not available with device: "+device); + if ( !canCreateGLPbuffer(device) ) { + throw new GLException("Pbuffer not available with device: "+device); } - - GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(capsRequested); + + final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(capsRequested); GLDrawableImpl drawable = null; device.lock(); try { - drawable = (GLDrawableImpl) createGLDrawable( createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height) ); + drawable = (GLDrawableImpl) createGLDrawable( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, width, height, null) ); if(null != drawable) { drawable.setRealized(true); } @@ -228,75 +249,155 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { //--------------------------------------------------------------------------- // - // Offscreen GLDrawable construction + // Offscreen GLDrawable construction // - protected abstract GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) ; - + @Override public GLDrawable createOffscreenDrawable(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, - int width, - int height) { + int width, int height) { if(width<=0 || height<=0) { - throw new GLException("Width and height of pbuffer must be positive (were (" + - width + ", " + height + "))"); + throw new GLException("initial size must be positive (were (" + width + " x " + height + "))"); } - AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq); + final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq); if(null == device) { throw new GLException("No shared device for requested: "+deviceReq); } - GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffScreenGLCapabilities(capsRequested, canCreateGLPbuffer(deviceReq)); - + + if( capsRequested.isFBO() && GLContext.isFBOAvailable(device, capsRequested.getGLProfile()) ) { + device.lock(); + try { + return createFBODrawableImpl(device, capsRequested, chooser, width, height); + } finally { + device.unlock(); + } + } + + final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(capsRequested, false, canCreateGLPbuffer(device)); device.lock(); try { - return createGLDrawable( createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height) ); + return createOffscreenDrawableImpl( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, width, height, null) ); } finally { device.unlock(); } } - public NativeSurface createOffscreenSurface(AbstractGraphicsDevice deviceReq, - GLCapabilitiesImmutable capsRequested, - GLCapabilitiesChooser chooser, - int width, int height) { - AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq); + /** Creates a platform independent offscreen FBO GLDrawable implementation */ + protected GLDrawable createFBODrawableImpl(AbstractGraphicsDevice device, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, + int initialWidth, int initialHeight) { + final GLCapabilitiesImmutable dummyCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(requestedCaps); + final NativeSurface dummySurface = createDummySurfaceImpl(device, true, dummyCaps, null, 64, 64); + final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(dummySurface); + + return new GLFBODrawableImpl(this, dummyDrawable, dummySurface, initialWidth, initialHeight, 0 /* textureUnit */); + } + + /** Creates a platform dependent offscreen pbuffer/pixmap GLDrawable implementation */ + protected abstract GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) ; + + /** + * Creates a mutable {@link ProxySurface} w/o defined surface handle. + *

      + * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}. + *

      + *

      + * Lifecycle (destruction) of the TBD surface handle shall be handled by the caller. + *

      + * @param device a valid platform dependent target device. + * @param createNewDevice if true a new device instance is created using device details, + * otherwise device instance is used as-is. + * @param capsChosen + * @param capsRequested + * @param chooser the custom chooser, may be null for default + * @param width the initial width + * @param height the initial height + * @param lifecycleHook optional control of the surface's lifecycle + * @return the created {@link MutableSurface} instance w/o defined surface handle + */ + protected abstract ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice, + GLCapabilitiesImmutable capsChosen, + GLCapabilitiesImmutable capsRequested, + GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook); + + /** + * A dummy surface is not visible on screen and will not be used to render directly to, + * it maybe on- or offscreen. + *

      + * It is used to allow the creation of a {@link GLDrawable} and {@link GLContext} to query information. + * It also allows creation of framebuffer objects which are used for rendering. + *

      + * @param deviceReq which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be null for the platform's default device. + * @param requestedCaps + * @param chooser the custom chooser, may be null for default + * @param width the initial width + * @param height the initial height + * + * @return the created {@link MutableSurface} instance w/o defined surface handle + */ + public NativeSurface createDummySurface(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, + int width, int height) { + final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq); if(null == device) { throw new GLException("No shared device for requested: "+deviceReq); } - GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffScreenGLCapabilities(capsRequested, canCreateGLPbuffer(deviceReq)); - device.lock(); try { - return createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height); + return createDummySurfaceImpl(device, true, requestedCaps, chooser, width, height); } finally { device.unlock(); } } - + /** - * creates an offscreen NativeSurface, which must implement SurfaceChangeable as well, - * so the windowing system related implementation is able to set the surface handle. + * A dummy surface is not visible on screen and will not be used to render directly to, + * it maybe on- or offscreen. + *

      + * It is used to allow the creation of a {@link GLDrawable} and {@link GLContext} to query information. + * It also allows creation of framebuffer objects which are used for rendering. + *

      + * @param device a valid platform dependent target device. + * @param createNewDevice if true a new device instance is created using device details, + * otherwise device instance is used as-is. + * @param requestedCaps + * @param chooser the custom chooser, may be null for default + * @param width the initial width + * @param height the initial height + * @return the created {@link MutableSurface} instance w/o defined surface handle */ - protected abstract NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device, - GLCapabilitiesImmutable capabilities, GLCapabilitiesImmutable capsRequested, - GLCapabilitiesChooser chooser, - int width, int height); + public abstract ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice, + GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height); - public ProxySurface createProxySurface(AbstractGraphicsDevice device, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) { + //--------------------------------------------------------------------------- + // + // ProxySurface (Wrapped pre-existing native surface) construction + // + + @Override + public ProxySurface createProxySurface(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, + GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) { + final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq); if(null == device) { - throw new GLException("No shared device for requested: "+device); + throw new GLException("No shared device for requested: "+deviceReq); } device.lock(); try { - return createProxySurfaceImpl(device, windowHandle, capsRequested, chooser); + return createProxySurfaceImpl(device, screenIdx, windowHandle, capsRequested, chooser, upstream); } finally { device.unlock(); } - } - - protected abstract ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice device, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser); + } + + /** + * Creates a {@link ProxySurface} with a set surface handle. + *

      + * Implementation is also required to allocate it's own {@link AbstractGraphicsDevice} instance. + *

      + * @param upstream TODO + */ + protected abstract ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, + GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream); //--------------------------------------------------------------------------- // @@ -304,7 +405,8 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { // protected abstract GLContext createExternalGLContextImpl(); - + + @Override public GLContext createExternalGLContext() { NativeWindowFactory.getDefaultToolkitLock().lock(); try { @@ -316,6 +418,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { protected abstract GLDrawable createExternalGLDrawableImpl(); + @Override public GLDrawable createExternalGLDrawable() { NativeWindowFactory.getDefaultToolkitLock().lock(); try { @@ -398,7 +501,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { * normal ahead of time, use resetDisplayGamma(). Throws * IllegalArgumentException if any of the parameters were * out-of-bounds. - * + * * @param gamma The gamma value, typically > 1.0 (default value is * 1.0) * @param brightness The brightness value between -1.0 and 1.0, @@ -484,7 +587,8 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { return; if (gammaShutdownHook == null) { gammaShutdownHook = new Thread(new Runnable() { - public void run() { + @Override + public void run() { synchronized (GLDrawableFactoryImpl.this) { resetGammaRamp(originalGammaRamp); } diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java index 58a4ac6b4..abf2bf557 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java @@ -42,6 +42,7 @@ package jogamp.opengl; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.ProxySurface; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; @@ -75,7 +76,7 @@ public abstract class GLDrawableImpl implements GLDrawable { if( !realized ) { return; // destroyed already } - GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities(); + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities(); if ( caps.getDoubleBuffered() ) { if(!surface.surfaceSwap()) { int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release] @@ -149,6 +150,9 @@ public abstract class GLDrawableImpl implements GLDrawable { realized = realizedArg; AbstractGraphicsDevice aDevice = surface.getGraphicsConfiguration().getScreen().getDevice(); if(realizedArg) { + if(surface instanceof ProxySurface) { + ((ProxySurface)surface).createNotify(); + } if(NativeSurface.LOCK_SURFACE_NOT_READY >= lockSurface()) { throw new GLException("GLDrawableImpl.setRealized(true): Surface not ready (lockSurface)"); } @@ -156,17 +160,21 @@ public abstract class GLDrawableImpl implements GLDrawable { aDevice.lock(); } try { - setRealizedImpl(); if(realizedArg) { + setRealizedImpl(); updateHandle(); } else { destroyHandle(); + setRealizedImpl(); } } finally { if(realizedArg) { unlockSurface(); } else { aDevice.unlock(); + if(surface instanceof ProxySurface) { + ((ProxySurface)surface).destroyNotify(); + } } } } else if(DEBUG) { @@ -175,6 +183,39 @@ public abstract class GLDrawableImpl implements GLDrawable { } protected abstract void setRealizedImpl(); + /** + * Callback for special implementations, allowing GLContext to trigger GL related lifecycle: construct, destroy. + *

      + * If realized is true, the context has just been created and made current. + *

      + *

      + * If realized is false, the context is still current and will be release and destroyed after this method returns. + *

      + *

      + * @see #contextMadeCurrent(GLContext, boolean) + */ + protected void contextRealized(GLContext glc, boolean realized) {} + + /** + * Callback for special implementations, allowing GLContext to trigger GL related lifecycle: makeCurrent, release. + *

      + * Will not be called if {@link #contextRealized(GLContext, boolean)} has been triggered. + *

      + *

      + * If current is true, the context has just been made current. + *

      + *

      + * If current is false, the context is still current and will be release after this method returns. + *

      + * @see #contextRealized(GLContext, boolean) + */ + protected void contextMadeCurrent(GLContext glc, boolean current) { } + + /** Callback for special implementations, allowing GLContext to fetch a custom default render framebuffer. Defaults to zero.*/ + protected int getDefaultDrawFramebuffer() { return 0; } + /** Callback for special implementations, allowing GLContext to fetch a custom default read framebuffer. Defaults to zero. */ + protected int getDefaultReadFramebuffer() { return 0; } + @Override public final synchronized boolean isRealized() { return realized; @@ -190,10 +231,12 @@ public abstract class GLDrawableImpl implements GLDrawable { return surface.getHeight(); } + /** @see NativeSurface#lockSurface() */ public final int lockSurface() throws GLException { return surface.lockSurface(); } + /** @see NativeSurface#unlockSurface() */ public final void unlockSurface() { surface.unlockSurface(); } diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java new file mode 100644 index 000000000..b7ea4f826 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java @@ -0,0 +1,138 @@ +package jogamp.opengl; + +import javax.media.nativewindow.NativeSurface; +import javax.media.opengl.GL; +import javax.media.opengl.GL2GL3; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLException; + +import com.jogamp.nativewindow.MutableGraphicsConfiguration; +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.FBObject.Attachment; +import com.jogamp.opengl.FBObject.TextureAttachment; + +/** + * Offscreen GLDrawable implementation using framebuffer object (FBO) + * as it's offscreen rendering mechanism. + * + * @see GLDrawableImpl#contextRealized(GLContext, boolean) + * @see GLDrawableImpl#contextMadeCurrent(GLContext, boolean) + * @see GLDrawableImpl#getDefaultDrawFramebuffer() + * @see GLDrawableImpl#getDefaultReadFramebuffer() + */ +public class GLFBODrawableImpl extends GLDrawableImpl { + final GLDrawableImpl parent; + final FBObject fbo; + int texUnit; + int samplesTexUnit = 0; + int width=0, height=0, samples=0; + + protected GLFBODrawableImpl(GLDrawableFactoryImpl factory, GLDrawableImpl parent, + NativeSurface surface, int initialWidth, int initialHeight, int textureUnit) { + super(factory, surface, false); + this.parent = parent; + this.texUnit = textureUnit; + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities(); + this.width = initialWidth; + this.height = initialHeight; + this.samples = caps.getNumSamples(); + this.fbo = new FBObject(); + } + + @Override + protected void contextRealized(GLContext glc, boolean realized) { + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities(); + final GL gl = glc.getGL(); + if(realized) { + fbo.reset(gl, width, height, samples); + samples = fbo.getNumSamples(); // update, maybe capped + if(samples > 0) { + fbo.attachColorbuffer(gl, 0, caps.getAlphaBits()>0); + } else { + fbo.attachTexture2D(gl, 0, caps.getAlphaBits()>0); + } + if( caps.getStencilBits() > 0 ) { + fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH_STENCIL, 24); + } else { + fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24); + } + } else if(null != fbo) { + fbo.destroy(gl); + } + } + + @Override + protected void contextMadeCurrent(GLContext glc, boolean current) { + final GL gl = glc.getGL(); + if(current) { + fbo.bind(gl); + } else { + fbo.unbind(gl); + gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit); + fbo.use(gl, samples > 0 ? fbo.getSamplingSink() : (TextureAttachment) fbo.getColorbuffer(0) ); + if( samples > 0) { + gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, fbo.getReadFramebuffer()); + } + } + } + + @Override + protected int getDefaultDrawFramebuffer() { return fbo.getWriteFramebuffer(); } + + @Override + protected int getDefaultReadFramebuffer() { return fbo.getReadFramebuffer(); } + + public FBObject getFBObject() { return fbo; } + + public void setSize(GL gl, int newWidth, int newHeight) throws GLException { + width = newWidth; + height = newHeight; + fbo.reset(gl, width, height, samples); + samples = fbo.getNumSamples(); // update, maybe capped + } + + public void setSamples(GL gl, int newSamples) throws GLException { + samples = newSamples; + fbo.reset(gl, width, height, samples); + samples = fbo.getNumSamples(); // update, maybe capped + } + + + @Override + public GLContext createContext(GLContext shareWith) { + final GLContext ctx = parent.createContext(shareWith); + ctx.setGLDrawable(this, false); + return ctx; + } + + @Override + public GLDynamicLookupHelper getGLDynamicLookupHelper() { + return parent.getGLDynamicLookupHelper(); + } + + @Override + protected void swapBuffersImpl() { + } + + @Override + protected void setRealizedImpl() { + parent.setRealized(realized); + if(realized) { + final MutableGraphicsConfiguration msConfig = (MutableGraphicsConfiguration) surface.getGraphicsConfiguration(); + final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) msConfig.getChosenCapabilities(); + final GLCapabilitiesImmutable chosenFBOCaps = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(chosenCaps, true /*FBO*/, false /*PBO*/); + msConfig.setChosenCapabilities(chosenFBOCaps); + } + } + + @Override + public int getWidth() { + return width; + } + + @Override + public int getHeight() { + return height; + } +} diff --git a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java index b7c15bfda..900d6a2a0 100644 --- a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java +++ b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java @@ -38,7 +38,8 @@ public class GLGraphicsConfigurationUtil { public static final int WINDOW_BIT = 1 << 0; public static final int BITMAP_BIT = 1 << 1; public static final int PBUFFER_BIT = 1 << 2; - public static final int ALL_BITS = WINDOW_BIT | BITMAP_BIT | PBUFFER_BIT ; + public static final int FBO_BIT = 1 << 3; + public static final int ALL_BITS = WINDOW_BIT | BITMAP_BIT | PBUFFER_BIT | FBO_BIT ; public static final StringBuilder winAttributeBits2String(StringBuilder sb, int winattrbits) { if(null==sb) { @@ -61,30 +62,43 @@ public class GLGraphicsConfigurationUtil { sb.append(", "); } sb.append("PBUFFER"); + seperator=true; + } + if( 0 != ( FBO_BIT & winattrbits ) ) { + if(seperator) { + sb.append(", "); + } + sb.append("FBO"); } return sb; } /** + * @param isFBO TODO * @return bitmask representing the input boolean in exclusive or logic, ie only one bit will be set */ - public static final int getWinAttributeBits(boolean isOnscreen, boolean isPBuffer) { + public static final int getWinAttributeBits(boolean isOnscreen, boolean isPBuffer, boolean isFBO) { int winattrbits = 0; if(isOnscreen) { winattrbits |= WINDOW_BIT; - } else if (!isPBuffer) { - winattrbits |= BITMAP_BIT; } else { - winattrbits |= PBUFFER_BIT; + if(isFBO) { + winattrbits |= FBO_BIT; + } + if (!isPBuffer) { + winattrbits |= BITMAP_BIT; + } else { + winattrbits |= PBUFFER_BIT; + } } return winattrbits; } /** - * @see #getWinAttributeBits(boolean, boolean) + * @see #getWinAttributeBits(boolean, boolean, boolean) */ public static final int getWinAttributeBits(GLCapabilitiesImmutable caps) { - return getWinAttributeBits(caps.isOnscreen(), caps.isPBuffer()); + return getWinAttributeBits(caps.isOnscreen(), caps.isPBuffer(), false); } public static final boolean addGLCapabilitiesPermutations(List capsBucket, GLCapabilitiesImmutable temp, int winattrbits) { @@ -92,43 +106,58 @@ public class GLGraphicsConfigurationUtil { if( 0 != ( WINDOW_BIT & winattrbits ) ) { GLCapabilities cpy = (GLCapabilities) temp.cloneMutable(); cpy.setOnscreen(true); + cpy.setPBuffer(false); + cpy.setFBO(false); capsBucket.add(cpy); } - if( 0 != ( PBUFFER_BIT & winattrbits ) ) { + if( 0 != ( PBUFFER_BIT & winattrbits ) || 0 != ( FBO_BIT & winattrbits ) ) { GLCapabilities cpy = (GLCapabilities) temp.cloneMutable(); - cpy.setPBuffer(true); + cpy.setFBO(0 != ( FBO_BIT & winattrbits )); + cpy.setPBuffer(0 != ( PBUFFER_BIT & winattrbits )); capsBucket.add(cpy); } if( 0 != ( BITMAP_BIT & winattrbits ) ) { GLCapabilities cpy = (GLCapabilities) temp.cloneMutable(); cpy.setOnscreen(false); cpy.setPBuffer(false); + cpy.setFBO(false); capsBucket.add(cpy); } return capsBucket.size() > preSize; } - public static GLCapabilitiesImmutable fixGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean pbufferAvailable) + public static GLCapabilitiesImmutable fixGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean fboAvailable, boolean pbufferAvailable) { if( !capsRequested.isOnscreen() ) { - return fixOffScreenGLCapabilities(capsRequested, pbufferAvailable); + return fixOffscreenGLCapabilities(capsRequested, fboAvailable, pbufferAvailable); } - return capsRequested; + return fixOnscreenGLCapabilities(capsRequested); } - public static GLCapabilitiesImmutable fixOffScreenGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean pbufferAvailable) + public static GLCapabilitiesImmutable fixOnscreenGLCapabilities(GLCapabilitiesImmutable capsRequested) + { + if( !capsRequested.isOnscreen() ) { + // fix caps .. + GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable(); + caps2.setOnscreen(true); + return caps2; + } + return capsRequested; + } + + public static GLCapabilitiesImmutable fixOffscreenGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean fboAvailable, boolean pbufferAvailable) { if( capsRequested.getDoubleBuffered() || capsRequested.isOnscreen() || - ( !pbufferAvailable && capsRequested.isPBuffer() ) ) + ( fboAvailable != capsRequested.isFBO() ) || + ( pbufferAvailable != capsRequested.isPBuffer() ) ) { // fix caps .. GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable(); caps2.setDoubleBuffered(false); // FIXME DBLBUFOFFSCRN caps2.setOnscreen(false); - if(caps2.isPBuffer() && !pbufferAvailable) { - caps2.setPBuffer(false); - } + caps2.setFBO( fboAvailable ); + caps2.setPBuffer( pbufferAvailable ); return caps2; } return capsRequested; @@ -136,12 +165,13 @@ public class GLGraphicsConfigurationUtil { public static GLCapabilitiesImmutable fixGLPBufferGLCapabilities(GLCapabilitiesImmutable capsRequested) { - if( capsRequested.getDoubleBuffered() || capsRequested.isOnscreen() || !capsRequested.isPBuffer()) { + if( capsRequested.getDoubleBuffered() || capsRequested.isOnscreen() || !capsRequested.isPBuffer() || capsRequested.isFBO() ) { // fix caps .. GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable(); caps2.setDoubleBuffered(false); // FIXME DBLBUFOFFSCRN - we don't need to be single buffered .. caps2.setOnscreen(false); caps2.setPBuffer(true); + caps2.setFBO(false); return caps2; } return capsRequested; diff --git a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java index a8277fd71..bbc28e283 100644 --- a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java @@ -54,8 +54,7 @@ import javax.media.opengl.GLPbuffer; public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer { private int floatMode; - public GLPbufferImpl(GLDrawableImpl pbufferDrawable, - GLContext sharedContext) { + public GLPbufferImpl(GLDrawableImpl pbufferDrawable, GLContext sharedContext) { super(pbufferDrawable, null); // drawable := pbufferDrawable GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) @@ -111,6 +110,11 @@ public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer { // GLAutoDrawable completion // + @Override + public final Object getUpstreamWidget() { + return null; + } + @Override public void destroy() { defaultDestroyOp(); diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java index 65a4c3ece..c5d0df645 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java @@ -110,14 +110,8 @@ public abstract class EGLContext extends GLContextImpl { @Override protected void makeCurrentImpl() throws GLException { - if(EGL.EGL_NO_DISPLAY==((EGLDrawable)drawable).getDisplay() ) { - throw new GLException("drawable not properly initialized, NO DISPLAY: "+drawable); - } if (EGL.eglGetCurrentContext() != contextHandle) { - if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(), - drawable.getHandle(), - drawableRead.getHandle(), - contextHandle)) { + if (!EGL.eglMakeCurrent(drawable.getNativeSurface().getDisplayHandle(), drawable.getHandle(), drawableRead.getHandle(), contextHandle)) { throw new GLException("Error making context 0x" + Long.toHexString(contextHandle) + " current: error code 0x" + Integer.toHexString(EGL.eglGetError())); } @@ -126,10 +120,7 @@ public abstract class EGLContext extends GLContextImpl { @Override protected void releaseImpl() throws GLException { - if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(), - EGL.EGL_NO_SURFACE, - EGL.EGL_NO_SURFACE, - EGL.EGL_NO_CONTEXT)) { + if (!EGL.eglMakeCurrent(drawable.getNativeSurface().getDisplayHandle(), EGL.EGL_NO_SURFACE, EGL.EGL_NO_SURFACE, EGL.EGL_NO_CONTEXT)) { throw new GLException("Error freeing OpenGL context 0x" + Long.toHexString(contextHandle) + ": error code 0x" + Integer.toHexString(EGL.eglGetError())); } @@ -137,7 +128,7 @@ public abstract class EGLContext extends GLContextImpl { @Override protected void destroyImpl() throws GLException { - if (!EGL.eglDestroyContext(((EGLDrawable)drawable).getDisplay(), contextHandle)) { + if (!EGL.eglDestroyContext(drawable.getNativeSurface().getDisplayHandle(), contextHandle)) { final int eglError = EGL.eglGetError(); if(EGL.EGL_SUCCESS != eglError) { /* oops, Mesa EGL impl. may return false, but has no EGL error */ throw new GLException("Error destroying OpenGL context 0x" + @@ -158,16 +149,16 @@ public abstract class EGLContext extends GLContextImpl { @Override protected boolean createImpl(GLContextImpl shareWith) throws GLException { - long eglDisplay = ((EGLDrawable)drawable).getDisplay(); - EGLGraphicsConfiguration config = ((EGLDrawable)drawable).getGraphicsConfiguration(); - GLProfile glProfile = drawable.getGLProfile(); - long eglConfig = config.getNativeConfig(); + final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration(); + final long eglDisplay = config.getScreen().getDevice().getHandle(); + final GLProfile glProfile = drawable.getGLProfile(); + final long eglConfig = config.getNativeConfig(); long shareWithHandle = EGL.EGL_NO_CONTEXT; - if (eglDisplay == 0) { + if ( 0 == eglDisplay ) { throw new GLException("Error: attempted to create an OpenGL context without a display connection"); } - if (eglConfig == 0) { + if ( 0 == eglConfig ) { throw new GLException("Error: attempted to create an OpenGL context without a graphics configuration"); } @@ -217,10 +208,7 @@ public abstract class EGLContext extends GLContextImpl { ",\n\t"+this+ ",\n\tsharing with 0x" + Long.toHexString(shareWithHandle)); } - if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(), - drawable.getHandle(), - drawableRead.getHandle(), - contextHandle)) { + if (!EGL.eglMakeCurrent(eglDisplay, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) { throw new GLException("Error making context 0x" + Long.toHexString(contextHandle) + " current: error code " + EGL.eglGetError()); } @@ -269,8 +257,7 @@ public abstract class EGLContext extends GLContextImpl { eglQueryStringInitialized = true; } if (eglQueryStringAvailable) { - final String ret = EGL.eglQueryString(((EGLDrawable)drawable).getDisplay(), - EGL.EGL_EXTENSIONS); + final String ret = EGL.eglQueryString(drawable.getNativeSurface().getDisplayHandle(), EGL.EGL_EXTENSIONS); if (DEBUG) { System.err.println("EGL extensions: " + ret); } @@ -291,7 +278,7 @@ public abstract class EGLContext extends GLContextImpl { } return false; } - return EGL.eglSwapInterval(((EGLDrawable)drawable).getDisplay(), interval); + return EGL.eglSwapInterval(drawable.getNativeSurface().getDisplayHandle(), interval); } @Override @@ -300,6 +287,45 @@ public abstract class EGLContext extends GLContextImpl { @Override public abstract void releasePbufferFromTexture(); + // + // Accessible .. + // + + /** + * If context is an ES profile, map it to the given device + * via {@link GLContext#mapAvailableGLVersion(AbstractGraphicsDevice, int, int, int, int, int)}. + *

      + * We intentionally override a non native EGL device ES profile mapping, + * i.e. this will override/modify an already 'set' X11/WGL/.. mapping. + *

      + * + * @param device + */ + protected void mapCurrentAvailableGLVersion(AbstractGraphicsDevice device) { + mapCurrentAvailableGLVersionImpl(device, ctxMajorVersion, ctxMinorVersion, ctxOptions); + } + + protected static void mapStaticGLESVersion(AbstractGraphicsDevice device, int major) { + int ctp = ( 2 == major ) ? ( GLContext.CTX_PROFILE_ES | GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ) : ( GLContext.CTX_PROFILE_ES ); + mapCurrentAvailableGLVersionImpl(device, major, 0, ctp); + } + private static void mapCurrentAvailableGLVersionImpl(AbstractGraphicsDevice device, int major, int minor, int ctp) { + if( 0 != ( ctp & GLContext.CTX_PROFILE_ES) ) { + // ES1 or ES2 + final int reqMajor = major; + final int reqProfile = GLContext.CTX_PROFILE_ES; + GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, + major, minor, ctp); + } + } + + protected static boolean getAvailableGLVersionsSet(AbstractGraphicsDevice device) { + return GLContext.getAvailableGLVersionsSet(device); + } + protected static void setAvailableGLVersionsSet(AbstractGraphicsDevice device) { + GLContext.setAvailableGLVersionsSet(device); + } + protected static String toHexString(int hex) { return GLContext.toHexString(hex); } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java index 7f10d3bd9..432010f49 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java @@ -136,7 +136,17 @@ public class EGLDisplayUtil { return res; } - public static final EGLGraphicsDevice.EGLTerminateCallback eglTerminateCallback = new EGLGraphicsDevice.EGLTerminateCallback() { + public static final EGLGraphicsDevice.EGLDisplayLifecycleCallback eglLifecycleCallback = new EGLGraphicsDevice.EGLDisplayLifecycleCallback() { + public long eglGetAndInitDisplay(long nativeDisplayID) { + long eglDisplay = EGLDisplayUtil.eglGetDisplay(nativeDisplayID); + if (eglDisplay == EGL.EGL_NO_DISPLAY) { + throw new GLException("Failed to created EGL display: 0x"+Long.toHexString(nativeDisplayID)+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } + if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) { + throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } + return eglDisplay; + } public void eglTerminate(long eglDisplayHandle) { EGLDisplayUtil.eglTerminate(eglDisplayHandle); } @@ -148,17 +158,12 @@ public class EGLDisplayUtil { * @param unitID * @return an initialized EGLGraphicsDevice * @throws GLException if {@link EGL#eglGetDisplay(long)} or {@link EGL#eglInitialize(long, int[], int, int[], int)} fails - * @see EGLGraphicsDevice#EGLGraphicsDevice(long, long, String, int, com.jogamp.nativewindow.egl.EGLGraphicsDevice.EGLTerminateCallback) + * @see EGLGraphicsDevice#EGLGraphicsDevice(long, long, String, int, com.jogamp.nativewindow.egl.EGLGraphicsDevice.EGLDisplayLifecycleCallback) */ public static EGLGraphicsDevice eglCreateEGLGraphicsDevice(long nativeDisplayID, String connection, int unitID) { - long eglDisplay = EGLDisplayUtil.eglGetDisplay(nativeDisplayID); - if (eglDisplay == EGL.EGL_NO_DISPLAY) { - throw new GLException("Failed to created EGL display: 0x"+Long.toHexString(nativeDisplayID)+", error 0x"+Integer.toHexString(EGL.eglGetError())); - } - if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) { - throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError())); - } - return new EGLGraphicsDevice(nativeDisplayID, eglDisplay, connection, unitID, eglTerminateCallback); + final EGLGraphicsDevice eglDisplay = new EGLGraphicsDevice(nativeDisplayID, 0, connection, unitID, eglLifecycleCallback); + eglDisplay.open(); + return eglDisplay; } /** @@ -189,6 +194,6 @@ public class EGLDisplayUtil { throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError())); } final AbstractGraphicsDevice adevice = surface.getGraphicsConfiguration().getScreen().getDevice(); - return new EGLGraphicsDevice(nativeDisplayID, eglDisplay, adevice.getConnection(), adevice.getUnitID(), eglTerminateCallback); + return new EGLGraphicsDevice(nativeDisplayID, eglDisplay, adevice.getConnection(), adevice.getUnitID(), eglLifecycleCallback); } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java index d777c4f04..383b61f88 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java @@ -36,82 +36,65 @@ package jogamp.opengl.egl; -import jogamp.opengl.GLDynamicLookupHelper; -import jogamp.opengl.GLDrawableImpl; +import javax.media.nativewindow.MutableSurface; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindow; +import javax.media.nativewindow.ProxySurface; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLException; -import javax.media.nativewindow.*; -import javax.media.nativewindow.VisualIDHolder.VIDType; -import javax.media.opengl.*; +import jogamp.opengl.GLDrawableImpl; +import jogamp.opengl.GLDynamicLookupHelper; -import com.jogamp.nativewindow.egl.*; +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; public abstract class EGLDrawable extends GLDrawableImpl { - private boolean ownEGLDisplay = false; // for destruction private boolean ownEGLSurface = false; // for destruction - private EGLGraphicsConfiguration eglConfig; - private EGLGraphicsDevice eglDevice; - private long eglSurface; - protected EGLDrawable(EGLDrawableFactory factory, - NativeSurface component) throws GLException { + protected EGLDrawable(EGLDrawableFactory factory, NativeSurface component) throws GLException { super(factory, component, false); - eglSurface=EGL.EGL_NO_SURFACE; - eglDevice=null; - } - - public final long getDisplay() { - return null != eglDevice ? eglDevice.getHandle() : 0; - } - - @Override - public final long getHandle() { - return eglSurface; - } - - public final EGLGraphicsConfiguration getGraphicsConfiguration() { - return eglConfig; - } - - @Override - public final GLCapabilitiesImmutable getChosenGLCapabilities() { - return (null==eglConfig)?super.getChosenGLCapabilities():(GLCapabilitiesImmutable)eglConfig.getChosenCapabilities(); } @Override public abstract GLContext createContext(GLContext shareWith); - protected abstract long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle); + protected abstract long createSurface(EGLGraphicsConfiguration config, long nativeSurfaceHandle); private final void recreateSurface() { - // create a new EGLSurface .. - if(EGL.EGL_NO_SURFACE!=eglSurface) { - EGL.eglDestroySurface(eglDevice.getHandle(), eglSurface); - } - + final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) surface.getGraphicsConfiguration(); + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglConfig.getScreen().getDevice(); if(DEBUG) { - System.err.println(getThreadName() + ": createSurface using "+eglDevice+", "+eglConfig); + System.err.println(getThreadName() + ": createSurface using "+eglConfig); + } + if( EGL.EGL_NO_SURFACE != surface.getSurfaceHandle() ) { + EGL.eglDestroySurface(eglDevice.getHandle(), surface.getSurfaceHandle()); } - - eglSurface = createSurface(eglDevice.getHandle(), eglConfig.getNativeConfig(), surface.getSurfaceHandle()); - int eglError0 = EGL.EGL_SUCCESS; + + final EGLUpstreamSurfaceHook upstreamHook = (EGLUpstreamSurfaceHook) ((ProxySurface)surface).getUpstreamSurfaceHook(); + final NativeSurface upstreamSurface = upstreamHook.getUpstreamSurface(); + long eglSurface = createSurface(eglConfig, upstreamSurface.getSurfaceHandle()); + + int eglError0; if (EGL.EGL_NO_SURFACE == eglSurface) { eglError0 = EGL.eglGetError(); if(EGL.EGL_BAD_NATIVE_WINDOW == eglError0) { // Try window handle if available and differs (Windows HDC / HWND). // ANGLE impl. required HWND on Windows. - if(surface instanceof NativeWindow) { - final NativeWindow nw = (NativeWindow) surface; + if(upstreamSurface instanceof NativeWindow) { + final NativeWindow nw = (NativeWindow) upstreamSurface; if(nw.getWindowHandle() != nw.getSurfaceHandle()) { if(DEBUG) { System.err.println(getThreadName() + ": Info: Creation of window surface w/ surface handle failed: "+eglConfig+", error "+toHexString(eglError0)+", retry w/ windowHandle"); } - eglSurface = createSurface(eglDevice.getHandle(), eglConfig.getNativeConfig(), nw.getWindowHandle()); + eglSurface = createSurface(eglConfig, nw.getWindowHandle()); if (EGL.EGL_NO_SURFACE == eglSurface) { eglError0 = EGL.eglGetError(); } } } } + } else { + eglError0 = EGL.EGL_SUCCESS; } if (EGL.EGL_NO_SURFACE == eglSurface) { throw new GLException("Creation of window surface failed: "+eglConfig+", "+surface+", error "+toHexString(eglError0)); @@ -120,6 +103,8 @@ public abstract class EGLDrawable extends GLDrawableImpl { if(DEBUG) { System.err.println(getThreadName() + ": setSurface using component: handle "+toHexString(surface.getSurfaceHandle())+" -> "+toHexString(eglSurface)); } + + ((MutableSurface)surface).setSurfaceHandle(eglSurface); } @Override @@ -131,123 +116,71 @@ public abstract class EGLDrawable extends GLDrawableImpl { @Override protected final void setRealizedImpl() { + final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) surface.getGraphicsConfiguration(); + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglConfig.getScreen().getDevice(); if (realized) { - AbstractGraphicsConfiguration aConfig = surface.getGraphicsConfiguration(); - AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice(); - if(aDevice instanceof EGLGraphicsDevice) { + final long eglDisplayHandle = eglDevice.getHandle(); + if (EGL.EGL_NO_DISPLAY == eglDisplayHandle) { + throw new GLException("Invalid EGL display in EGLGraphicsDevice "+eglDevice); + } + int[] tmp = new int[1]; + boolean eglSurfaceValid = 0 != surface.getSurfaceHandle(); + if(eglSurfaceValid) { + eglSurfaceValid = EGL.eglQuerySurface(eglDisplayHandle, surface.getSurfaceHandle(), EGL.EGL_CONFIG_ID, tmp, 0); + if(!eglSurfaceValid) { + if(DEBUG) { + System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl eglQuerySuface failed: "+toHexString(EGL.eglGetError())+", "+surface); + } + } + } + if(eglSurfaceValid) { + // surface holds valid EGLSurface if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): using existing EGL config - START"); + System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl re-using component's EGLSurface: handle "+toHexString(surface.getSurfaceHandle())); + } + ownEGLSurface=false; + } else { + // EGLSurface is ours - subsequent updateHandle() will issue recreateSurface(); + // However .. let's validate the surface object first + if( ! (surface instanceof ProxySurface) ) { + throw new InternalError("surface not ProxySurface: "+surface.getClass().getName()+", "+surface); } - // just fetch the data .. trust but verify .. - ownEGLDisplay = false; - eglDevice = (EGLGraphicsDevice) aDevice; - if (eglDevice.getHandle() == EGL.EGL_NO_DISPLAY) { - throw new GLException("Invalid EGL display in EGLGraphicsDevice "+eglDevice); + final ProxySurface.UpstreamSurfaceHook upstreamHook = ((ProxySurface)surface).getUpstreamSurfaceHook(); + if( null == upstreamHook ) { + throw new InternalError("null upstreamHook of: "+surface); } - if(aConfig instanceof EGLGraphicsConfiguration) { - eglConfig = (EGLGraphicsConfiguration) aConfig; // done .. - if (null == eglConfig) { - throw new GLException("Null EGLGraphicsConfiguration from "+aConfig); - } - - int[] tmp = new int[1]; - if ( 0 != surface.getSurfaceHandle() && - EGL.eglQuerySurface(eglDevice.getHandle(), surface.getSurfaceHandle(), EGL.EGL_CONFIG_ID, tmp, 0) ) { - // surface holds static EGLSurface - eglSurface = surface.getSurfaceHandle(); - if(DEBUG) { - System.err.println(getThreadName() + ": setSurface re-using component's EGLSurface: handle "+toHexString(eglSurface)); - } - ownEGLSurface=false; - } else { - // EGLSurface is ours - subsequent updateHandle() will issue recreateSurface(); - ownEGLSurface=true; - } - } else { - throw new GLException("EGLGraphicsDevice hold by non EGLGraphicsConfiguration: "+aConfig); + if( ! (upstreamHook instanceof EGLUpstreamSurfaceHook) ) { + throw new InternalError("upstreamHook not EGLUpstreamSurfaceHook: Surface: "+surface.getClass().getName()+", "+surface+"; UpstreamHook: "+upstreamHook.getClass().getName()+", "+upstreamHook); } - } else { - if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): creating new EGL config - START"); + if( null == ((EGLUpstreamSurfaceHook)upstreamHook).getUpstreamSurface() ) { + throw new InternalError("null upstream surface"); } - // create a new EGL config .. - ownEGLDisplay=true; - // EGLSurface is ours .. ownEGLSurface=true; - - eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface, true); - AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex()); - final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities(); - if(aConfig instanceof EGLGraphicsConfiguration) { - final EGLGLCapabilities capsChosen = (EGLGLCapabilities) aConfig.getChosenCapabilities(); - if(0 == capsChosen.getEGLConfig()) { - // 'refresh' the native EGLConfig handle - capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDevice.getHandle(), capsChosen.getEGLConfigID())); - if(0 == capsChosen.getEGLConfig()) { - throw new GLException("Refreshing native EGLConfig handle failed: "+capsChosen+" of "+aConfig); - } - } - eglConfig = new EGLGraphicsConfiguration(eglScreen, capsChosen, capsRequested, null); - if(DEBUG) { - System.err.println(getThreadName() + ": Reusing chosenCaps: "+eglConfig); - } - } else { - eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( - capsRequested, capsRequested, null, eglScreen, aConfig.getVisualID(VIDType.NATIVE), false); - - if (null == eglConfig) { - throw new GLException("Couldn't create EGLGraphicsConfiguration from "+eglScreen); - } else if(DEBUG) { - System.err.println(getThreadName() + ": Chosen eglConfig: "+eglConfig); - } + if(DEBUG) { + System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl owning EGLSurface"); } - // subsequent updateHandle() will issue recreateSurface(); - } - if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): END: ownDisplay "+ownEGLDisplay+", ownSurface "+ownEGLSurface); } - } else if (ownEGLSurface && eglSurface != EGL.EGL_NO_SURFACE) { + } else if (ownEGLSurface && surface.getSurfaceHandle() != EGL.EGL_NO_SURFACE) { if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealized(false): ownDisplay "+ownEGLDisplay+", ownSurface "+ownEGLSurface+", "+eglDevice+", eglSurface: "+toHexString(eglSurface)); + System.err.println(getThreadName() + ": EGLDrawable.setRealized(false): ownSurface "+ownEGLSurface+", "+eglDevice+", eglSurface: "+toHexString(surface.getSurfaceHandle())); } // Destroy the window surface - if (!EGL.eglDestroySurface(eglDevice.getHandle(), eglSurface)) { + if (!EGL.eglDestroySurface(eglDevice.getHandle(), surface.getSurfaceHandle())) { throw new GLException("Error destroying window surface (eglDestroySurface)"); } - eglSurface = EGL.EGL_NO_SURFACE; - eglConfig=null; - eglDevice.close(); - eglDevice=null; + ((MutableSurface)surface).setSurfaceHandle(EGL.EGL_NO_SURFACE); } } @Override protected final void swapBuffersImpl() { + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice(); // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers() - if(!EGL.eglSwapBuffers(eglDevice.getHandle(), eglSurface)) { + if(!EGL.eglSwapBuffers(eglDevice.getHandle(), surface.getSurfaceHandle())) { throw new GLException("Error swapping buffers, eglError "+toHexString(EGL.eglGetError())+", "+this); } } - /** - * Surface not realizes yet (onscreen) .. Quering EGL surface size only makes sense for external drawable. - * Leave it here for later impl. of an EGLExternalDrawable. - public int getWidth() { - int[] tmp = new int[1]; - if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_WIDTH, tmp, 0)) { - throw new GLException("Error querying surface width, eglError "+toHexString(EGL.eglGetError())); - } - return tmp[0]; - } - - public int getHeight() { - int[] tmp = new int[1]; - if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_HEIGHT, tmp, 0)) { - throw new GLException("Error querying surface height, eglError "+toHexString(EGL.eglGetError())); - } - return tmp[0]; - } */ - @Override public GLDynamicLookupHelper getGLDynamicLookupHelper() { if (getGLProfile().usesNativeGLES2()) { @@ -263,10 +196,9 @@ public abstract class EGLDrawable extends GLDrawableImpl { public String toString() { return getClass().getName()+"[realized "+isRealized()+ ",\n\tfactory "+getFactory()+ - ",\n\tdevice "+eglDevice+ ",\n\tsurface "+getNativeSurface()+ - ",\n\teglSurface "+toHexString(eglSurface)+ - ",\n\teglConfig "+eglConfig+ + ",\n\teglSurface "+toHexString(surface.getSurfaceHandle())+ + ",\n\teglConfig "+surface.getGraphicsConfiguration()+ ",\n\trequested "+getRequestedGLCapabilities()+ ",\n\tchosen "+getChosenGLCapabilities()+"]"; } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java index f4fa1f13f..c848e3e5c 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java @@ -46,21 +46,29 @@ import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.DefaultGraphicsScreen; +import javax.media.nativewindow.MutableSurface; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; +import javax.media.nativewindow.VisualIDHolder.VIDType; import javax.media.nativewindow.VisualIDHolder; +import javax.media.opengl.GL; +import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; import javax.media.opengl.GLProfile.ShutdownType; +import jogamp.opengl.Debug; import jogamp.opengl.GLDrawableFactoryImpl; import jogamp.opengl.GLDrawableImpl; import jogamp.opengl.GLDynamicLookupHelper; +import jogamp.opengl.GLGraphicsConfigurationUtil; import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.os.Platform; @@ -69,6 +77,9 @@ import com.jogamp.nativewindow.WrappedSurface; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; public class EGLDrawableFactory extends GLDrawableFactoryImpl { + /* package */ static final boolean QUERY_EGL_ES = !Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.DontQuery", true); + /* package */ static final boolean QUERY_EGL_ES_NATIVE_TK = Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.QueryNativeTK", true); + private static GLDynamicLookupHelper eglES1DynamicLookupHelper = null; private static GLDynamicLookupHelper eglES2DynamicLookupHelper = null; private static boolean isANGLE = false; @@ -231,7 +242,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { // final EGLContext getContextES1() { return contextES1; } // final EGLContext getContextES2() { return contextES2; } final boolean wasES1ContextAvailable() { return wasES1ContextCreated; } - final boolean wasES2ContextAvailable() { return wasES2ContextCreated; } + final boolean wasES2ContextAvailable() { return wasES2ContextCreated; } } @Override @@ -245,35 +256,98 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { return null!=eglES2DynamicLookupHelper || null!=eglES1DynamicLookupHelper; } - /** - private boolean isEGLContextAvailable(EGLGraphicsDevice sharedDevice, String profile) { - boolean madeCurrent = false; - final GLCapabilities caps = new GLCapabilities(GLProfile.get(profile)); - caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0); - caps.setDoubleBuffered(false); - caps.setOnscreen(false); - caps.setPBuffer(true); - final EGLDrawable drawable = (EGLDrawable) createGLDrawable( createOffscreenSurfaceImpl(sharedDevice, caps, caps, null, 64, 64) ); - if(null!=drawable) { + private boolean isEGLContextAvailable(AbstractGraphicsDevice adevice, EGLGraphicsDevice sharedEGLDevice, String profileString) { + if( !GLProfile.isAvailable(adevice, profileString) ) { + return false; + } + final GLProfile glp = GLProfile.get(adevice, profileString) ; + final GLDrawableFactoryImpl desktopFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getDesktopFactory(); + EGLGraphicsDevice eglDevice = null; + NativeSurface surface = null; + ProxySurface upstreamSurface = null; // X11, GLX, .. + boolean success = false; + boolean deviceFromUpstreamSurface = false; + try { + final GLCapabilities caps = new GLCapabilities(glp); + caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0); + if(adevice instanceof EGLGraphicsDevice || null == desktopFactory || !QUERY_EGL_ES_NATIVE_TK) { + eglDevice = sharedEGLDevice; // reuse + surface = createDummySurfaceImpl(eglDevice, false, caps, null, 64, 64); // egl pbuffer offscreen + upstreamSurface = (ProxySurface)surface; + upstreamSurface.createNotify(); + deviceFromUpstreamSurface = false; + } else { + surface = desktopFactory.createDummySurface(adevice, caps, null, 64, 64); // X11, WGL, .. dummy window + upstreamSurface = ( surface instanceof ProxySurface ) ? (ProxySurface)surface : null ; + if(null != upstreamSurface) { + upstreamSurface.createNotify(); + } + eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface, true); + deviceFromUpstreamSurface = true; + } + + final EGLDrawable drawable = (EGLDrawable) createOnscreenDrawableImpl ( surface ); + drawable.setRealized(true); final EGLContext context = (EGLContext) drawable.createContext(null); if (null != context) { - context.setSynchronized(true); try { context.makeCurrent(); // could cause exception - madeCurrent = context.isCurrent(); + success = context.isCurrent(); + if(success) { + final String glVersion = context.getGL().glGetString(GL.GL_VERSION); + if(null == glVersion) { + // Oops .. something is wrong + if(DEBUG) { + System.err.println("EGLDrawableFactory.isEGLContextAvailable: "+eglDevice+", "+context.getGLVersion()+" - VERSION is null, dropping availability!"); + } + success = false; + } + } + if(success) { + context.mapCurrentAvailableGLVersion(eglDevice); + if(eglDevice != adevice) { + context.mapCurrentAvailableGLVersion(adevice); + } + } } catch (GLException gle) { if (DEBUG) { - System.err.println("EGLDrawableFactory.createShared: INFO: makeCurrent failed"); + System.err.println("EGLDrawableFactory.createShared: INFO: context create/makeCurrent failed"); gle.printStackTrace(); } } finally { context.destroy(); } } - drawable.destroy(); + drawable.setRealized(false); + } catch (Throwable t) { + if(DEBUG) { + System.err.println("Catched Exception:"); + t.printStackTrace(); + } + success = false; + } finally { + if(eglDevice == sharedEGLDevice) { + if(null != upstreamSurface) { + upstreamSurface.destroyNotify(); + } + } else if( deviceFromUpstreamSurface ) { + if(null != eglDevice) { + eglDevice.close(); + } + if(null != upstreamSurface) { + upstreamSurface.destroyNotify(); + } + } else { + if(null != upstreamSurface) { + upstreamSurface.destroyNotify(); + } + if(null != eglDevice) { + eglDevice.close(); + } + } } - return madeCurrent; - } */ + return success; + } /* package */ SharedResource getOrCreateEGLSharedResource(AbstractGraphicsDevice adevice) { if(null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper) { @@ -285,18 +359,41 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { sr = sharedMap.get(connection); } if(null==sr) { - final EGLGraphicsDevice sharedDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, connection, adevice.getUnitID()); + final boolean madeCurrentES1; + final boolean madeCurrentES2; + final EGLGraphicsDevice sharedDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); - // final boolean madeCurrentES1 = isEGLContextAvailable(sharedDevice, GLProfile.GLES1); - // final boolean madeCurrentES2 = isEGLContextAvailable(sharedDevice, GLProfile.GLES2); - final boolean madeCurrentES1 = true; // FIXME - final boolean madeCurrentES2 = true; // FIXME + if(QUERY_EGL_ES) { + madeCurrentES1 = isEGLContextAvailable(adevice, sharedDevice, GLProfile.GLES1); + madeCurrentES2 = isEGLContextAvailable(adevice, sharedDevice, GLProfile.GLES2); + } else { + madeCurrentES1 = true; + madeCurrentES2 = true; + EGLContext.mapStaticGLESVersion(sharedDevice, 1); + if(sharedDevice != adevice) { + EGLContext.mapStaticGLESVersion(adevice, 1); + } + EGLContext.mapStaticGLESVersion(sharedDevice, 2); + if(sharedDevice != adevice) { + EGLContext.mapStaticGLESVersion(adevice, 2); + } + } + + if( !EGLContext.getAvailableGLVersionsSet(adevice) ) { + // Even though we override the non EGL native mapping intentionally, + // avoid exception due to double 'set' - carefull exception of the rule. + EGLContext.setAvailableGLVersionsSet(adevice); + } sr = new SharedResource(sharedDevice, madeCurrentES1, madeCurrentES2); + synchronized(sharedMap) { sharedMap.put(connection, sr); + if(adevice != sharedDevice) { + sharedMap.put(sharedDevice.getConnection(), sr); + } } if (DEBUG) { - System.err.println("EGLDrawableFactory.createShared: device: " + sharedDevice); + System.err.println("EGLDrawableFactory.createShared: devices: queried " + QUERY_EGL_ES + "[nativeTK "+QUERY_EGL_ES_NATIVE_TK+"], " + adevice + ", " + sharedDevice); System.err.println("EGLDrawableFactory.createShared: context ES1: " + madeCurrentES1); System.err.println("EGLDrawableFactory.createShared: context ES2: " + madeCurrentES2); } @@ -367,8 +464,51 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { if (target == null) { throw new IllegalArgumentException("Null target"); } - return new EGLOnscreenDrawable(this, target); + return new EGLOnscreenDrawable(this, getEGLSurface(target)); + } + + protected static NativeSurface getEGLSurface(NativeSurface surface) { + AbstractGraphicsConfiguration aConfig = surface.getGraphicsConfiguration(); + AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice(); + if( aDevice instanceof EGLGraphicsDevice && aConfig instanceof EGLGraphicsConfiguration ) { + // already in native EGL format + if(DEBUG) { + System.err.println(getThreadName() + ": getEGLSurface - already in EGL format - use as-is: "+aConfig); + } + return surface; + } + // create EGL instance out of platform native types + final EGLGraphicsDevice eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface, true); + final AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex()); + final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities(); + final EGLGraphicsConfiguration eglConfig; + if( aConfig instanceof EGLGraphicsConfiguration ) { + // Config is already in EGL type - reuse .. + final EGLGLCapabilities capsChosen = (EGLGLCapabilities) aConfig.getChosenCapabilities(); + if( 0 == capsChosen.getEGLConfig() ) { + // 'refresh' the native EGLConfig handle + capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDevice.getHandle(), capsChosen.getEGLConfigID())); + if( 0 == capsChosen.getEGLConfig() ) { + throw new GLException("Refreshing native EGLConfig handle failed: "+capsChosen+" of "+aConfig); + } + } + eglConfig = new EGLGraphicsConfiguration(eglScreen, capsChosen, capsRequested, null); + if(DEBUG) { + System.err.println(getThreadName() + ": getEGLSurface - Reusing chosenCaps: "+eglConfig); + } + } else { + eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( + capsRequested, capsRequested, null, eglScreen, aConfig.getVisualID(VIDType.NATIVE), false); + + if (null == eglConfig) { + throw new GLException("Couldn't create EGLGraphicsConfiguration from "+eglScreen); + } else if(DEBUG) { + System.err.println(getThreadName() + ": getEGLSurface - Chosen eglConfig: "+eglConfig); + } + } + return new WrappedSurface(eglConfig, EGL.EGL_NO_SURFACE, surface.getWidth(), surface.getHeight(), new EGLUpstreamSurfaceHook(surface)); } + static String getThreadName() { return Thread.currentThread().getName(); } @Override protected GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) { @@ -390,22 +530,115 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } @Override - protected NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) { - final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq; - final EGLGraphicsDevice device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID()); - WrappedSurface ns = new WrappedSurface(EGLGraphicsConfigurationFactory.createOffscreenGraphicsConfiguration(device, capsChosen, capsRequested, chooser)); - ns.surfaceSizeChanged(width, height); - return ns; + protected ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, + GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, + GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) { + final EGLGraphicsDevice device; + if(createNewDevice) { + final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq; + device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID()); + } else { + device = (EGLGraphicsDevice) deviceReq; + } + final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0); + final EGLGraphicsConfiguration config = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false); + if(null == config) { + throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen); + } + return new WrappedSurface(config, 0, width, height, lifecycleHook); + } + + @Override + public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, + GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) { + final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(requestedCaps, false, canCreateGLPbuffer(deviceReq)); + return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, width, height, dummySurfaceLifecycleHook); + } + private static final ProxySurface.UpstreamSurfaceHook dummySurfaceLifecycleHook = new ProxySurface.UpstreamSurfaceHook() { + @Override + public final void create(ProxySurface s) { + if( EGL.EGL_NO_SURFACE == s.getSurfaceHandle() ) { + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice(); + if(0 == eglDevice.getHandle()) { + eglDevice.open(); + s.setImplBitfield(ProxySurface.OWN_DEVICE); + } + createPBufferSurfaceImpl(s, false); + if(DEBUG) { + System.err.println("EGLDrawableFactory.dummySurfaceLifecycleHook.create: "+s); + } + } + } + @Override + public final void destroy(ProxySurface s) { + if( EGL.EGL_NO_SURFACE != s.getSurfaceHandle() ) { + final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) s.getGraphicsConfiguration(); + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) config.getScreen().getDevice(); + EGL.eglDestroySurface(eglDevice.getHandle(), s.getSurfaceHandle()); + s.setSurfaceHandle(EGL.EGL_NO_SURFACE); + if( 0 != ( ProxySurface.OWN_DEVICE & s.getImplBitfield() ) ) { + eglDevice.close(); + } + if(DEBUG) { + System.err.println("EGLDrawableFactory.dummySurfaceLifecycleHook.create: "+s); + } + } + } + @Override + public final int getWidth(ProxySurface s) { + return s.initialWidth; + } + @Override + public final int getHeight(ProxySurface s) { + return s.initialHeight; + } + @Override + public String toString() { + return "EGLSurfaceLifecycleHook[]"; + } + + }; + + /** + * @param ms {@link MutableSurface} which dimensions and config are being used to create the pbuffer surface. + * It will also hold the resulting pbuffer surface handle. + * @param useTexture + * @return the passed {@link MutableSurface} which now has the EGL pbuffer surface set as it's handle + */ + protected static MutableSurface createPBufferSurfaceImpl(MutableSurface ms, boolean useTexture) { + final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) ms.getGraphicsConfiguration(); + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) config.getScreen().getDevice(); + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); + final int texFormat; + + if(useTexture) { + texFormat = caps.getAlphaBits() > 0 ? EGL.EGL_TEXTURE_RGBA : EGL.EGL_TEXTURE_RGB ; + } else { + texFormat = EGL.EGL_NO_TEXTURE; + } + + if (DEBUG) { + System.out.println("Pbuffer config: " + config); + } + + final int[] attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(ms.getWidth(), ms.getHeight(), texFormat); + final long surf = EGL.eglCreatePbufferSurface(eglDevice.getHandle(), config.getNativeConfig(), attrs, 0); + if (EGL.EGL_NO_SURFACE==surf) { + throw new GLException("Creation of window surface (eglCreatePbufferSurface) failed, dim "+ms.getWidth()+"x"+ms.getHeight()+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } else if(DEBUG) { + System.err.println("PBuffer setSurface result: eglSurface 0x"+Long.toHexString(surf)); + } + ms.setSurfaceHandle(surf); + return ms; } @Override - protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice adevice, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) { - // FIXME device/windowHandle -> screen ?! - EGLGraphicsDevice device = (EGLGraphicsDevice) adevice; - DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0); - EGLGraphicsConfiguration cfg = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false); - WrappedSurface ns = new WrappedSurface(cfg, windowHandle); - return ns; + protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) { + final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq; + final EGLGraphicsDevice device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID()); + final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx); + final EGLGraphicsConfiguration cfg = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false); + return new WrappedSurface(cfg, windowHandle, 0, 0, upstream); } @Override diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java index 56e7a4d22..214b36493 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java @@ -151,7 +151,7 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple public static EGLGLCapabilities EGLConfig2Capabilities(GLProfile glp, long display, long config, boolean relaxed, boolean onscreen, boolean usePBuffer, boolean forceTransparentFlag) { List bucket = new ArrayList(); - final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer); + final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer, false); if( EGLConfig2Capabilities(bucket, glp, display, config, winattrmask, forceTransparentFlag) ) { return (EGLGLCapabilities) bucket.get(0); } else if ( relaxed && EGLConfig2Capabilities(bucket, glp, display, config, GLGraphicsConfigurationUtil.ALL_BITS, forceTransparentFlag) ) { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java index 809e2b688..6be9cb547 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java @@ -38,7 +38,6 @@ import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.CapabilitiesChooser; import javax.media.nativewindow.CapabilitiesImmutable; -import javax.media.nativewindow.DefaultGraphicsScreen; import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.VisualIDHolder; import javax.media.nativewindow.VisualIDHolder.VIDType; @@ -47,6 +46,7 @@ import javax.media.nativewindow.NativeWindowFactory; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; import javax.media.opengl.GLDrawableFactory; @@ -180,6 +180,9 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact } EGLGraphicsDevice eglDevice = sharedResource.getDevice(); long eglDisplay = eglDevice.getHandle(); + if(0 == eglDisplay) { + throw new GLException("null eglDisplay"); + } List availableCaps = null; IntBuffer numConfigs = Buffers.newDirectIntBuffer(1); @@ -236,11 +239,9 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact ownEGLDisplay = true; } - EGLDrawableFactory factory = (EGLDrawableFactory) GLDrawableFactory.getEGLFactory(); - capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, factory.canCreateGLPbuffer(absDevice) ); - - GLProfile glp = capsChosen.getGLProfile(); - GLCapabilities fixedCaps; + final GLProfile glp = capsChosen.getGLProfile(); + final EGLDrawableFactory factory = (EGLDrawableFactory) GLDrawableFactory.getEGLFactory(); + capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, GLContext.isFBOAvailable(absDevice, glp), factory.canCreateGLPbuffer(absDevice) ); EGLGraphicsConfiguration res = eglChooseConfig(eglDevice.getHandle(), capsChosen, capsReq, chooser, absScreen, nativeVisualID, forceTransparentFlag); if(null==res) { @@ -251,13 +252,18 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact // Last try .. add a fixed embedded profile [ATI, Nokia, Intel, ..] // // rgb888 - d16, s4 - fixedCaps = new GLCapabilities(glp); + final GLCapabilities fixedCaps = new GLCapabilities(glp); fixedCaps.setRedBits(8); fixedCaps.setGreenBits(8); fixedCaps.setBlueBits(8); fixedCaps.setDepthBits(16); fixedCaps.setSampleBuffers(true); fixedCaps.setNumSamples(4); + if( !capsChosen.isOnscreen() ) { + fixedCaps.setOnscreen(false); + fixedCaps.setPBuffer(capsChosen.isPBuffer()); + fixedCaps.setFBO(capsChosen.isFBO()); + } if(DEBUG) { System.err.println("trying fixed caps (1): "+fixedCaps); } @@ -266,11 +272,16 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact if(null==res) { // // rgb565 - d16, s0 - fixedCaps = new GLCapabilities(glp); + final GLCapabilities fixedCaps = new GLCapabilities(glp); fixedCaps.setRedBits(5); fixedCaps.setGreenBits(6); fixedCaps.setBlueBits(5); fixedCaps.setDepthBits(16); + if( !capsChosen.isOnscreen() ) { + fixedCaps.setOnscreen(false); + fixedCaps.setPBuffer(capsChosen.isPBuffer()); + fixedCaps.setFBO(capsChosen.isFBO()); + } if(DEBUG) { System.err.println("trying fixed caps (2): "+fixedCaps); } @@ -279,13 +290,18 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact if(null==res) { // // rgb565 - d16, s4 - fixedCaps = new GLCapabilities(glp); + final GLCapabilities fixedCaps = new GLCapabilities(glp); fixedCaps.setRedBits(5); fixedCaps.setGreenBits(6); fixedCaps.setBlueBits(5); fixedCaps.setDepthBits(16); fixedCaps.setSampleBuffers(true); fixedCaps.setNumSamples(4); + if( !capsChosen.isOnscreen() ) { + fixedCaps.setOnscreen(false); + fixedCaps.setPBuffer(capsChosen.isPBuffer()); + fixedCaps.setFBO(capsChosen.isFBO()); + } if(DEBUG) { System.err.println("trying fixed caps (3): "+fixedCaps); } @@ -309,7 +325,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact final GLProfile glp = capsChosen.getGLProfile(); final boolean onscreen = capsChosen.isOnscreen(); final boolean usePBuffer = capsChosen.isPBuffer(); - final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer); + final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer, false); List availableCaps = null; int recommendedIndex = -1; long recommendedEGLConfig = -1; @@ -322,8 +338,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact throw new GLException("EGLGraphicsConfiguration.eglChooseConfig: Get maxConfigs (eglGetConfigs) no configs"); } if (DEBUG) { - System.err.println("EGLGraphicsConfiguration.eglChooseConfig: eglChooseConfig maxConfigs: "+numConfigs.get(0)); - System.err.println("EGLGraphicsConfiguration.eglChooseConfig: eglDisplay "+toHexString(eglDisplay)+", "+capsChosen+", nativeVisualID "+toHexString(nativeVisualID)); + System.err.println("EGLGraphicsConfiguration.eglChooseConfig: eglChooseConfig eglDisplay "+toHexString(eglDisplay)+", nativeVisualID "+toHexString(nativeVisualID)+", onscreen "+onscreen+", usePBuffer "+usePBuffer+", "+capsChosen+", numConfigs "+numConfigs.get(0)); } final IntBuffer attrs = Buffers.newDirectIntBuffer(EGLGraphicsConfiguration.GLCapabilities2AttribList(capsChosen)); @@ -362,7 +377,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact throw new GLException("EGLGraphicsConfiguration.eglChooseConfig: #2 Get all configs (eglGetConfigs) call failed, error "+toHexString(EGL.eglGetError())); } if (numConfigs.get(0) > 0) { - availableCaps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs.get(0), winattrmask, forceTransparentFlag); + availableCaps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs.get(0), winattrmask, forceTransparentFlag); } } @@ -370,6 +385,8 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact if(DEBUG) { // FIXME: this happens on a ATI PC Emulation .. System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #2 Graphics configuration 1st choice and 2nd choice failed - no configs"); + availableCaps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs.get(0), GLGraphicsConfigurationUtil.ALL_BITS, forceTransparentFlag); + printCaps("AllCaps", availableCaps, System.err); } return null; } @@ -428,27 +445,5 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact out.println(prefix+"["+i+"] "+caps.get(i)); } } - - static EGLGraphicsConfiguration createOffscreenGraphicsConfiguration(AbstractGraphicsDevice device, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsReq, GLCapabilitiesChooser chooser) { - if(capsChosen.isOnscreen()) { - throw new GLException("Error: Onscreen set: "+capsChosen); - } - - if(capsChosen.getDoubleBuffered()) { - // OFFSCREEN !DOUBLE_BUFFER // FIXME DBLBUFOFFSCRN - GLCapabilities caps2 = (GLCapabilities) capsChosen.cloneMutable(); - caps2.setDoubleBuffered(false); - capsChosen = caps2; - } - - DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0); - EGLGraphicsConfiguration eglConfig = chooseGraphicsConfigurationStatic(capsChosen, capsReq, chooser, screen, VisualIDHolder.VID_UNDEFINED, false); - if (null == eglConfig) { - throw new GLException("Couldn't create EGLGraphicsConfiguration from "+screen); - } else if(DEBUG) { - System.err.println("Chosen eglConfig: "+eglConfig); - } - return eglConfig; - } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java index 3768f1588..d54057775 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java @@ -54,8 +54,8 @@ public class EGLOnscreenDrawable extends EGLDrawable { } @Override - protected long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle) { - return EGL.eglCreateWindowSurface(eglDpy, eglNativeCfg, surfaceHandle, null); + protected long createSurface(EGLGraphicsConfiguration config, long nativeSurfaceHandle) { + return EGL.eglCreateWindowSurface(config.getScreen().getDevice().getHandle(), config.getNativeConfig(), nativeSurfaceHandle, null); } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java index b2217c095..4a36625bd 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java @@ -40,15 +40,11 @@ package jogamp.opengl.egl; -import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.NativeSurface; -import javax.media.nativewindow.SurfaceChangeable; -import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.nativewindow.MutableSurface; import javax.media.opengl.GLContext; -import javax.media.opengl.GLException; public class EGLPbufferDrawable extends EGLDrawable { - private int texFormat; protected static final boolean useTexture = false; // No yet .. protected EGLPbufferDrawable(EGLDrawableFactory factory, NativeSurface target) { @@ -56,30 +52,12 @@ public class EGLPbufferDrawable extends EGLDrawable { } @Override - protected long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle) { - final AbstractGraphicsConfiguration config = getNativeSurface().getGraphicsConfiguration(); - final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); - - if(useTexture) { - texFormat = caps.getAlphaBits() > 0 ? EGL.EGL_TEXTURE_RGBA : EGL.EGL_TEXTURE_RGB ; - } else { - texFormat = EGL.EGL_NO_TEXTURE; - } - - if (DEBUG) { - System.out.println("Pbuffer config: " + config); - } - - NativeSurface nw = getNativeSurface(); - int[] attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(nw.getWidth(), nw.getHeight(), texFormat); - long surf = EGL.eglCreatePbufferSurface(eglDpy, eglNativeCfg, attrs, 0); - if (EGL.EGL_NO_SURFACE==surf) { - throw new GLException("Creation of window surface (eglCreatePbufferSurface) failed, dim "+nw.getWidth()+"x"+nw.getHeight()+", error 0x"+Integer.toHexString(EGL.eglGetError())); - } else if(DEBUG) { - System.err.println("PBuffer setSurface result: eglSurface 0x"+Long.toHexString(surf)); + protected long createSurface(EGLGraphicsConfiguration config, long nativeSurfaceHandle) { + final MutableSurface ms = (MutableSurface)getNativeSurface(); + if(config != ms.getGraphicsConfiguration()) { + throw new InternalError("Not same: "+config.hashCode()+", "+ms.getGraphicsConfiguration()+": "+config+", "+ms.getGraphicsConfiguration()); } - ((SurfaceChangeable)nw).setSurfaceHandle(surf); - return surf; + return EGLDrawableFactory.createPBufferSurfaceImpl(ms, useTexture).getSurfaceHandle(); } @Override diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java new file mode 100644 index 000000000..42c6e100e --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java @@ -0,0 +1,56 @@ +package jogamp.opengl.egl; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.ProxySurface; +import javax.media.opengl.GLException; + +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; + +public class EGLUpstreamSurfaceHook implements ProxySurface.UpstreamSurfaceHook { + private final NativeSurface upstreamSurface; + + public EGLUpstreamSurfaceHook(NativeSurface upstream) { + upstreamSurface = upstream; + } + + public final NativeSurface getUpstreamSurface() { return upstreamSurface; } + + @Override + public final void create(ProxySurface surface) { + if(upstreamSurface instanceof ProxySurface) { + ((ProxySurface)upstreamSurface).createNotify(); + if(NativeSurface.LOCK_SURFACE_NOT_READY >= upstreamSurface.lockSurface()) { + throw new GLException("Could not lock: "+upstreamSurface); + } + } + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice(); + eglDevice.open(); + } + + @Override + public final void destroy(ProxySurface surface) { + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice(); + eglDevice.close(); + if(upstreamSurface instanceof ProxySurface) { + upstreamSurface.unlockSurface(); + ((ProxySurface)upstreamSurface).destroyNotify(); + } + } + + @Override + public final int getWidth(ProxySurface s) { + return upstreamSurface.getWidth(); + } + + @Override + public final int getHeight(ProxySurface s) { + return upstreamSurface.getHeight(); + } + + @Override + public String toString() { + final String us_s = null != upstreamSurface ? ( upstreamSurface.getClass().getName() + ": " + upstreamSurface ) : "nil"; + return "EGLUpstreamSurfaceHook[upstream: "+us_s+"]"; + } + +} diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java index aa66aa9d1..4bf2a3c9d 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java @@ -48,6 +48,7 @@ import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.OffscreenLayerSurface; +import javax.media.nativewindow.ProxySurface; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLException; @@ -63,6 +64,7 @@ import com.jogamp.common.os.Platform; import com.jogamp.common.util.VersionNumber; import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; +import com.jogamp.opengl.GLExtensions; public abstract class MacOSXCGLContext extends GLContextImpl { @@ -252,9 +254,11 @@ public abstract class MacOSXCGLContext extends GLContextImpl @Override protected void makeCurrentImpl() throws GLException { + /** FIXME: won't work w/ special drawables (like FBO) - check for CGL mode regressions! + * if (getOpenGLMode() != ((MacOSXCGLDrawable)drawable).getOpenGLMode()) { setOpenGLMode(((MacOSXCGLDrawable)drawable).getOpenGLMode()); - } + } */ if (!impl.makeCurrent(contextHandle)) { throw new GLException("Error making Context current: "+this); } @@ -338,8 +342,8 @@ public abstract class MacOSXCGLContext extends GLContextImpl @Override public boolean isExtensionAvailable(String glExtensionName) { - if (glExtensionName.equals("GL_ARB_pbuffer") || - glExtensionName.equals("GL_ARB_pixel_format")) { + if (glExtensionName.equals(GLExtensions.ARB_pbuffer) || + glExtensionName.equals(GLExtensions.ARB_pixel_format)) { return true; } return super.isExtensionAvailable(glExtensionName); @@ -426,10 +430,13 @@ public abstract class MacOSXCGLContext extends GLContextImpl @Override public long create(long share, int ctp, int major, int minor) { long ctx = 0; - final MacOSXCGLDrawable drawable = (MacOSXCGLDrawable) MacOSXCGLContext.this.drawable; final NativeSurface surface = drawable.getNativeSurface(); final MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) surface.getGraphicsConfiguration(); final OffscreenLayerSurface backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(surface, true); + boolean allowIncompleteView = null != backingLayerHost; + if( !allowIncompleteView && surface instanceof ProxySurface ) { + allowIncompleteView = 0 != ( ProxySurface.INVISIBLE_WINDOW & ((ProxySurface)surface).getImplBitfield() ) ; + } final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); long pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2NSPixelFormat(chosenCaps, ctp, major, minor); if (pixelFormat == 0) { @@ -443,13 +450,12 @@ public abstract class MacOSXCGLContext extends GLContextImpl screenVSyncTimeout = 1000000f / sRefreshRate; if(DEBUG) { System.err.println("NS create OSX>=lion "+isLionOrLater); - System.err.println("NS create backendType: "+drawable.getOpenGLMode()); + System.err.println("NS create allowIncompleteView: "+allowIncompleteView); System.err.println("NS create backingLayerHost: "+backingLayerHost); System.err.println("NS create share: "+share); System.err.println("NS create chosenCaps: "+chosenCaps); System.err.println("NS create pixelFormat: "+toHexString(pixelFormat)); System.err.println("NS create drawable native-handle: "+toHexString(drawable.getHandle())); - System.err.println("NS create drawable NSView-handle: "+toHexString(drawable.getNSViewHandle())); System.err.println("NS create screen refresh-rate: "+sRefreshRate+" hz, "+screenVSyncTimeout+" micros"); // Thread.dumpStack(); } @@ -457,7 +463,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl int[] viewNotReady = new int[1]; // Try to allocate a context with this ctx = CGL.createContext(share, - drawable.getNSViewHandle(), null!=backingLayerHost, + drawable.getHandle(), allowIncompleteView, pixelFormat, chosenCaps.isBackgroundOpaque(), viewNotReady, 0); @@ -473,10 +479,6 @@ public abstract class MacOSXCGLContext extends GLContextImpl CGL.setContextOpacity(ctx, 0); } - if(DEBUG) { - GLCapabilitiesImmutable caps0 = MacOSXCGLGraphicsConfiguration.NSPixelFormat2GLCapabilities(null, pixelFormat); - System.err.println("NS create pixelformat2GLCaps: "+caps0); - } GLCapabilitiesImmutable fixedCaps = MacOSXCGLGraphicsConfiguration.NSPixelFormat2GLCapabilities(chosenCaps.getGLProfile(), pixelFormat); fixedCaps = GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(fixedCaps, chosenCaps.isBackgroundOpaque()); config.setChosenCapabilities(fixedCaps); diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java index 257635b8c..841edb2b0 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java @@ -106,10 +106,6 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl { protected void setRealizedImpl() { } - protected long getNSViewHandle() { - return GLBackendType.NSOPENGL == openGLMode ? getHandle() : 0; - } - protected void registerContext(MacOSXCGLContext ctx) { // NOTE: we need to keep track of the created contexts in order to // implement swapBuffers() because of how Mac OS X implements its diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java index 4e9d18fed..9689d9f64 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java @@ -50,8 +50,8 @@ import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.DefaultGraphicsScreen; import javax.media.nativewindow.NativeSurface; -import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; import javax.media.opengl.GL; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; @@ -62,15 +62,19 @@ import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; import javax.media.opengl.GLProfile.ShutdownType; +import jogamp.nativewindow.macosx.OSXUtil; import jogamp.opengl.DesktopGLDynamicLookupHelper; +import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableFactoryImpl; import jogamp.opengl.GLDrawableImpl; import jogamp.opengl.GLDynamicLookupHelper; +import jogamp.opengl.GLGraphicsConfigurationUtil; import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.nativewindow.WrappedSurface; import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice; +import com.jogamp.opengl.GLExtensions; public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { private static DesktopGLDynamicLookupHelper macOSXCGLDynamicLookupHelper = null; @@ -214,44 +218,39 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { if (null == glp) { throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice); } - final GLCapabilities caps = new GLCapabilities(glp); - caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0); - caps.setDepthBits(5); - caps.setDoubleBuffered(false); - caps.setOnscreen(false); - caps.setPBuffer(true); - final MacOSXCGLDrawable drawable = (MacOSXCGLDrawable) createGLDrawable( createOffscreenSurfaceImpl(sharedDevice, caps, caps, null, 64, 64) ); - if(null!=drawable) { - drawable.setRealized(true); - final GLContext context = drawable.createContext(null); - if (null != context) { - try { - context.makeCurrent(); // could cause exception - madeCurrent = context.isCurrent(); - if(madeCurrent) { - GL gl = context.getGL(); - hasNPOTTextures = gl.isNPOTTextureAvailable(); - hasRECTTextures = gl.isExtensionAvailable("GL_EXT_texture_rectangle"); - hasAppleFloatPixels = gl.isExtensionAvailable("GL_APPLE_float_pixels"); - } - } catch (GLException gle) { - if (DEBUG) { - System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: makeCurrent catched exception:"); - gle.printStackTrace(); - } - } finally { - try { - context.destroy(); - } catch (GLException gle) { - if (DEBUG) { - System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: destroy catched exception:"); - gle.printStackTrace(); - } - } + final GLDrawableImpl sharedDrawable = createOnscreenDrawableImpl(createDummySurfaceImpl(sharedDevice, false, new GLCapabilities(glp), null, 64, 64)); + sharedDrawable.setRealized(true); + + final GLContextImpl sharedContext = (GLContextImpl) sharedDrawable.createContext(null); + if (null == sharedContext) { + throw new GLException("Couldn't create shared context for drawable: "+sharedDrawable); + } + + try { + sharedContext.makeCurrent(); // could cause exception + madeCurrent = sharedContext.isCurrent(); + if(madeCurrent) { + GL gl = sharedContext.getGL(); + hasNPOTTextures = gl.isNPOTTextureAvailable(); + hasRECTTextures = gl.isExtensionAvailable(GLExtensions.EXT_texture_rectangle); + hasAppleFloatPixels = gl.isExtensionAvailable(GLExtensions.APPLE_float_pixels); + } + } catch (GLException gle) { + if (DEBUG) { + System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: makeCurrent catched exception:"); + gle.printStackTrace(); + } + } finally { + try { + sharedContext.destroy(); + } catch (GLException gle) { + if (DEBUG) { + System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: destroy catched exception:"); + gle.printStackTrace(); } } - drawable.setRealized(false); } + sharedDrawable.setRealized(false); } sr = new SharedResource(sharedDevice, madeCurrent, hasNPOTTextures, hasRECTTextures, hasAppleFloatPixels); synchronized(sharedMap) { @@ -332,18 +331,82 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { } @Override - protected NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device,GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) { - AbstractGraphicsScreen screen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_MACOSX); - WrappedSurface ns = new WrappedSurface(MacOSXCGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, true)); - ns.surfaceSizeChanged(width, height); - return ns; + protected ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, + GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, + GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) { + final MacOSXGraphicsDevice device; + if(createNewDevice) { + device = new MacOSXGraphicsDevice(deviceReq.getUnitID()); + } else { + device = (MacOSXGraphicsDevice)deviceReq; + } + final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, 0); + final MacOSXCGLGraphicsConfiguration config = MacOSXCGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, true); + if(null == config) { + throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen); + } + return new WrappedSurface(config, 0, width, height, lifecycleHook); } @Override - protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice device, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) { - AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, 0); - WrappedSurface ns = new WrappedSurface(MacOSXCGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, true), windowHandle); - return ns; + public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, + GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) { + final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(requestedCaps); + return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, width, height, dummySurfaceLifecycleHook); + } + private static final ProxySurface.UpstreamSurfaceHook dummySurfaceLifecycleHook = new ProxySurface.UpstreamSurfaceHook() { + long nsWindow = 0; + @Override + public final void create(ProxySurface s) { + if(0 == nsWindow && 0 == s.getSurfaceHandle()) { + nsWindow = OSXUtil.CreateNSWindow(0, 0, s.getWidth(), s.getHeight()); + if(0 == nsWindow) { + throw new GLException("Error NS window 0"); + } + long nsView = OSXUtil.GetNSView(nsWindow); + if(0 == nsView) { + throw new GLException("Error NS view 0"); + } + s.setSurfaceHandle(nsView); + s.setImplBitfield(ProxySurface.INVISIBLE_WINDOW); + if(DEBUG) { + System.err.println("MacOSXCGLDrawableFactory.dummySurfaceLifecycleHook.create: "+s); + } + } + } + @Override + public final void destroy(ProxySurface s) { + if(0 != nsWindow && 0 != s.getSurfaceHandle()) { + OSXUtil.DestroyNSWindow(nsWindow); + nsWindow = 0; + s.setSurfaceHandle(0); + if(DEBUG) { + System.err.println("MacOSXCGLDrawableFactory.dummySurfaceLifecycleHook.destroy: "+s); + } + } + } + @Override + public final int getWidth(ProxySurface s) { + return s.initialWidth; + } + @Override + public final int getHeight(ProxySurface s) { + return s.initialHeight; + } + + @Override + public String toString() { + return "MacOSXLSurfaceLifecycleHook[]"; + } + + }; + + @Override + protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) { + final MacOSXGraphicsDevice device = new MacOSXGraphicsDevice(deviceReq.getUnitID()); + final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx); + final MacOSXCGLGraphicsConfiguration config = MacOSXCGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, true); + return new WrappedSurface(config, windowHandle, 0, 0, upstream); } @Override diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java index 8393a688e..421e1ef96 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java @@ -154,7 +154,7 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration break; case CGL.NSOpenGLPFASamples: - ivalues[idx] = caps.getSampleBuffers() ? ivalues[idx] = caps.getNumSamples() : 0; + ivalues[idx] = caps.getNumSamples() ; break; default: @@ -233,7 +233,7 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration return fmt.get(0); } - static GLCapabilitiesImmutable CGLPixelFormat2GLCapabilities(long pixelFormat) { + static GLCapabilitiesImmutable CGLPixelFormat2GLCapabilities(long pixelFormat) { return PixelFormat2GLCapabilities(null, pixelFormat, false); } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java index ad4c06af2..6be9e386d 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java @@ -114,8 +114,7 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext { // set a fake marker stating a valid drawable currentDrawable = 1; } - WrappedSurface ns = new WrappedSurface(cfg); - ns.setSurfaceHandle(currentDrawable); + WrappedSurface ns = new WrappedSurface(cfg, currentDrawable, 64, 64, null); return new MacOSXExternalCGLContext(new Drawable(factory, ns), isNSContext, contextHandle); } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java index 242cea068..b144c020d 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java @@ -42,7 +42,7 @@ package jogamp.opengl.macosx.cgl; import javax.media.nativewindow.DefaultGraphicsConfiguration; import javax.media.nativewindow.NativeSurface; -import javax.media.nativewindow.SurfaceChangeable; +import javax.media.nativewindow.MutableSurface; import javax.media.opengl.GL; import javax.media.opengl.GL2; import javax.media.opengl.GL2GL3; @@ -95,12 +95,6 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable { return ctx; } - @Override - protected long getNSViewHandle() { - // pbuffer handle is NSOpenGLPixelBuffer - return 0; - } - @Override public long getHandle() { return pBuffer; @@ -115,7 +109,7 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable { NativeSurface ns = getNativeSurface(); impl.destroy(pBuffer); this.pBuffer = 0; - ((SurfaceChangeable)ns).setSurfaceHandle(0); + ((MutableSurface)ns).setSurfaceHandle(0); } } @@ -174,7 +168,7 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable { throw new GLException("pbuffer creation error: CGL.createPBuffer() failed"); } - ((SurfaceChangeable)ns).setSurfaceHandle(pBuffer); + ((MutableSurface)ns).setSurfaceHandle(pBuffer); } @Override diff --git a/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java index 31f13297b..6bf8839af 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java +++ b/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java @@ -113,7 +113,7 @@ public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl { // create EGLImage from texture clientBuffer = null; // FIXME nioTmp.put(0, EGL.EGL_NONE); - image = eglExt.eglCreateImageKHR( eglDrawable.getDisplay(), eglCtx.getHandle(), + image = eglExt.eglCreateImageKHR( eglDrawable.getNativeSurface().getDisplayHandle(), eglCtx.getHandle(), EGLExt.EGL_GL_TEXTURE_2D_KHR, clientBuffer, nioTmp); if (0==image) { @@ -130,7 +130,7 @@ public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl { // rendering the EGLImage texture before we tell OpenMAX to fill // it with a new frame. tmp[0] = EGL.EGL_NONE; - sync = eglExt.eglCreateSyncKHR(eglDrawable.getDisplay(), EGLExt.EGL_SYNC_FENCE_KHR, tmp, 0); + sync = eglExt.eglCreateSyncKHR(eglDrawable.getNativeSurface().getDisplayHandle(), EGLExt.EGL_SYNC_FENCE_KHR, tmp, 0); if (0==sync) { throw new RuntimeException("EGLSync creation failed: "+EGL.eglGetError()+", ctx "+eglCtx+", err "+toHexString(EGL.eglGetError())); } @@ -159,10 +159,10 @@ public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl { final EGLTextureFrame eglTex = (EGLTextureFrame) imgTex; if(0!=eglTex.getImage()) { - eglExt.eglDestroyImageKHR(eglDrawable.getDisplay(), eglTex.getImage()); + eglExt.eglDestroyImageKHR(eglDrawable.getNativeSurface().getDisplayHandle(), eglTex.getImage()); } if(0!=eglTex.getSync()) { - eglExt.eglDestroySyncKHR(eglDrawable.getDisplay(), eglTex.getSync()); + eglExt.eglDestroySyncKHR(eglDrawable.getNativeSurface().getDisplayHandle(), eglTex.getSync()); } super.destroyTexImage(gl, imgTex); } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java index 296d53ce3..cf6f43b1c 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java @@ -41,7 +41,7 @@ package jogamp.opengl.windows.wgl; import javax.media.nativewindow.NativeSurface; -import javax.media.nativewindow.SurfaceChangeable; +import javax.media.nativewindow.MutableSurface; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawableFactory; @@ -139,7 +139,7 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable { hbitmap = 0; throw new GLException("Error creating device context for offscreen OpenGL context, werr "+werr); } - ((SurfaceChangeable)ns).setSurfaceHandle(hdc); + ((MutableSurface)ns).setSurfaceHandle(hdc); if(DEBUG) { System.err.println("WindowsBitmapWGLDrawable (2): "+ns); } @@ -164,7 +164,7 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable { GDI.DeleteDC(ns.getSurfaceHandle()); origbitmap = 0; hbitmap = 0; - ((SurfaceChangeable)ns).setSurfaceHandle(0); + ((MutableSurface)ns).setSurfaceHandle(0); } } } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java deleted file mode 100644 index 05d6d9862..000000000 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - * You acknowledge that this software is not designed or intended for use - * in the design, construction, operation or maintenance of any nuclear - * facility. - * - * Sun gratefully acknowledges that this software was originally authored - * and developed by Kenneth Bradley Russell and Christopher John Kline. - */ - -package jogamp.opengl.windows.wgl; - -import javax.media.nativewindow.AbstractGraphicsScreen; -import javax.media.nativewindow.NativeSurface; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLDrawableFactory; -import javax.media.opengl.GLException; -import javax.media.opengl.GLProfile; - -import jogamp.nativewindow.windows.GDI; -import jogamp.nativewindow.windows.GDISurface; -import jogamp.nativewindow.windows.GDIUtil; - -public class WindowsDummyWGLDrawable extends WindowsWGLDrawable { - private long hwnd; - private boolean handleHwndLifecycle; - - private WindowsDummyWGLDrawable(GLDrawableFactory factory, GDISurface ns, boolean handleHwndLifecycle) { - super(factory, ns, true); - this.handleHwndLifecycle = handleHwndLifecycle; - - if(NativeSurface.LOCK_SURFACE_NOT_READY >= ns.lockSurface()) { - throw new GLException("WindowsDummyWGLDrawable: surface not ready (lockSurface)"); - } - try { - WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration(); - config.updateGraphicsConfiguration(factory, ns, null); - if (DEBUG) { - System.err.println("WindowsDummyWGLDrawable: "+config); - } - } catch (Throwable t) { - setRealized(false); - throw new GLException(t); - } finally { - unlockSurface(); - } - } - - public static WindowsDummyWGLDrawable create(GLDrawableFactory factory, GLProfile glp, AbstractGraphicsScreen absScreen, - long windowHandle, int width, int height, boolean handleWindowLifecycle) { - if(0 == windowHandle) { - throw new GLException("Error windowHandle 0, werr: "+GDI.GetLastError()); - } - GLCapabilities caps = new GLCapabilities(glp); - WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfigurationFactory.createDefaultGraphicsConfiguration(caps, absScreen); - GDISurface ns = new GDISurface(cfg, windowHandle); - ns.surfaceSizeChanged(width, height); - return new WindowsDummyWGLDrawable(factory, ns, handleWindowLifecycle); - } - - @Override - public GLContext createContext(GLContext shareWith) { - // FIXME: figure out how to hook back in the Java 2D / JOGL bridge - return new WindowsWGLContext(this, shareWith); - } - - @Override - protected void setRealizedImpl() { - super.setRealizedImpl(); - if(!realized) { - if (handleHwndLifecycle && hwnd != 0) { - GDI.ShowWindow(hwnd, GDI.SW_HIDE); - GDIUtil.DestroyDummyWindow(hwnd); - hwnd = 0; - } - } - } -} diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java index 86441c688..96c1187d3 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java @@ -55,7 +55,6 @@ import com.jogamp.nativewindow.WrappedSurface; import jogamp.nativewindow.windows.GDI; import jogamp.opengl.GLContextShareSet; - public class WindowsExternalWGLContext extends WindowsWGLContext { private GLContext lastContext; @@ -103,7 +102,7 @@ public class WindowsExternalWGLContext extends WindowsWGLContext { System.err.println("WindowsExternalWGLContext valid hdc/pfd, retrieved cfg: " + cfg); } } - return new WindowsExternalWGLContext(new Drawable(factory, new WrappedSurface(cfg, hdc)), ctx, cfg); + return new WindowsExternalWGLContext(new Drawable(factory, new WrappedSurface(cfg, hdc, 64, 64, null)), ctx, cfg); } @Override diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java index 8f22aa60e..15bd005dc 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java @@ -50,6 +50,7 @@ import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; import jogamp.nativewindow.windows.GDI; +import jogamp.nativewindow.windows.GDIUtil; import com.jogamp.nativewindow.WrappedSurface; @@ -69,9 +70,9 @@ public class WindowsExternalWGLDrawable extends WindowsWGLDrawable { throw new GLException("Error: attempted to make an external GLContext without a valid pixelformat, werr " + GDI.GetLastError()); } - AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS); - WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfiguration.createFromExternal(factory, hdc, pfdID, glp, aScreen, true); - return new WindowsExternalWGLDrawable(factory, new WrappedSurface(cfg, hdc)); + final AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS); + final WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfiguration.createFromExternal(factory, hdc, pfdID, glp, aScreen, true); + return new WindowsExternalWGLDrawable(factory, new WrappedSurface(cfg, hdc, 64, 64, null)); } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java index a11d6e78e..7dda6a1f1 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java @@ -42,6 +42,8 @@ package jogamp.opengl.windows.wgl; import javax.media.opengl.*; +import com.jogamp.opengl.GLExtensions; + import jogamp.opengl.GLContextImpl; public class WindowsPbufferWGLContext extends WindowsWGLContext { @@ -112,7 +114,7 @@ public class WindowsPbufferWGLContext extends WindowsWGLContext { } else { hasRTT = true; - if (rect && !gl.isExtensionAvailable("GL_NV_texture_rectangle")) { + if (rect && !gl.isExtensionAvailable(GLExtensions.NV_texture_rectangle)) { System.err.println("WindowsPbufferWGLContext: WARNING: GL_NV_texture_rectangle extension not " + "supported; skipping requested render_to_texture_rectangle support for pbuffer"); rect = false; diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java index b00c796ec..175622343 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java @@ -42,7 +42,7 @@ package jogamp.opengl.windows.wgl; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowException; -import javax.media.nativewindow.SurfaceChangeable; +import javax.media.nativewindow.MutableSurface; import javax.media.opengl.GL; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; @@ -92,7 +92,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable { if (wglExt.wglReleasePbufferDCARB(buffer, ns.getSurfaceHandle()) == 0) { throw new GLException("Error releasing pbuffer device context: error code " + GDI.GetLastError()); } - ((SurfaceChangeable)ns).setSurfaceHandle(0); + ((MutableSurface)ns).setSurfaceHandle(0); } if (!wglExt.wglDestroyPbufferARB(buffer)) { throw new GLException("Error destroying pbuffer: error code " + GDI.GetLastError()); @@ -121,7 +121,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable { } try { long sharedHdc = sharedSurface.getSurfaceHandle(); - WGLExt wglExt = sharedResource.getContext().getWGLExt(); + WGLExt wglExt = ((WindowsWGLContext)sharedResource.getContext()).getWGLExt(); if (DEBUG) { System.out.println("Pbuffer config: " + config); @@ -131,7 +131,6 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable { float[] fattributes = new float[1]; int[] floatModeTmp = new int[1]; int niattribs = 0; - int width, height; GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities(); GLProfile glProfile = chosenCaps.getGLProfile(); @@ -206,7 +205,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable { iattributes[niattribs++] = WGLExt.WGL_MIPMAP_TEXTURE_ARB; iattributes[niattribs++] = GL.GL_FALSE; - iattributes[niattribs++] = WGLExt.WGL_PBUFFER_LARGEST_ARB; + iattributes[niattribs++] = WGLExt.WGL_PBUFFER_LARGEST_ARB; // exact iattributes[niattribs++] = GL.GL_FALSE; } @@ -235,7 +234,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable { NativeSurface ns = getNativeSurface(); // Set up instance variables buffer = tmpBuffer; - ((SurfaceChangeable)ns).setSurfaceHandle(tmpHdc); + ((MutableSurface)ns).setSurfaceHandle(tmpHdc); cachedWGLExt = wglExt; // Re-query chosen pixel format @@ -249,14 +248,6 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable { } config.setCapsPFD(newCaps); } - - // Determine the actual width and height we were able to create. - int[] tmp = new int[1]; - wglExt.wglQueryPbufferARB( buffer, WGLExt.WGL_PBUFFER_WIDTH_ARB, tmp, 0 ); - width = tmp[0]; - wglExt.wglQueryPbufferARB( buffer, WGLExt.WGL_PBUFFER_HEIGHT_ARB, tmp, 0 ); - height = tmp[0]; - ((SurfaceChangeable)ns).surfaceSizeChanged(width, height); } finally { sharedSurface.unlockSurface(); } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java index f143c158b..8825bad0a 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java @@ -53,6 +53,8 @@ import javax.media.opengl.GLCapabilitiesImmutable; import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; +import com.jogamp.opengl.GLExtensions; + import jogamp.nativewindow.windows.GDI; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableImpl; @@ -77,8 +79,8 @@ public class WindowsWGLContext extends GLContextImpl { functionNameMap.put("glFreeMemoryNV", "wglFreeMemoryNV"); extensionNameMap = new HashMap(); - extensionNameMap.put("GL_ARB_pbuffer", "WGL_ARB_pbuffer"); - extensionNameMap.put("GL_ARB_pixel_format", "WGL_ARB_pixel_format"); + extensionNameMap.put(GLExtensions.ARB_pbuffer, WindowsWGLDrawableFactory.WGL_ARB_pbuffer); + extensionNameMap.put(GLExtensions.ARB_pixel_format, WindowsWGLDrawableFactory.WGL_ARB_pixel_format); } // FIXME: figure out how to hook back in the Java 2D / JOGL bridge diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java index 176d27a71..09e97ff79 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java @@ -51,9 +51,10 @@ import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.DefaultGraphicsScreen; import javax.media.nativewindow.NativeSurface; -import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; import javax.media.opengl.GL; +import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; @@ -67,9 +68,11 @@ import jogamp.nativewindow.windows.GDISurface; import jogamp.nativewindow.windows.GDIUtil; import jogamp.nativewindow.windows.RegisteredClassFactory; import jogamp.opengl.DesktopGLDynamicLookupHelper; +import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableFactoryImpl; import jogamp.opengl.GLDrawableImpl; import jogamp.opengl.GLDynamicLookupHelper; +import jogamp.opengl.GLGraphicsConfigurationUtil; import jogamp.opengl.SharedResourceRunner; import com.jogamp.common.JogampRuntimeException; @@ -79,6 +82,7 @@ import com.jogamp.common.util.ReflectionUtil; import com.jogamp.common.util.VersionNumber; import com.jogamp.nativewindow.WrappedSurface; import com.jogamp.nativewindow.windows.WindowsGraphicsDevice; +import com.jogamp.opengl.GLExtensions; public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { private static DesktopGLDynamicLookupHelper windowsWGLDynamicLookupHelper = null; @@ -203,8 +207,8 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { static class SharedResource implements SharedResourceRunner.Resource { private WindowsGraphicsDevice device; private AbstractGraphicsScreen screen; - private WindowsDummyWGLDrawable drawable; - private WindowsWGLContext context; + private GLDrawableImpl drawable; + private GLContextImpl context; private boolean hasARBPixelFormat; private boolean hasARBMultisample; private boolean hasARBPBuffer; @@ -214,7 +218,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { private boolean isVendorNVIDIA; private boolean needsCurrenContext4ARBPFDQueries; - SharedResource(WindowsGraphicsDevice dev, AbstractGraphicsScreen scrn, WindowsDummyWGLDrawable draw, WindowsWGLContext ctx, + SharedResource(WindowsGraphicsDevice dev, AbstractGraphicsScreen scrn, GLDrawableImpl draw, GLContextImpl ctx, boolean arbPixelFormat, boolean arbMultisample, boolean arbPBuffer, boolean arbReadDrawable, String glVendor) { device = dev; screen = scrn; @@ -250,9 +254,9 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { @Override final public AbstractGraphicsScreen getScreen() { return screen; } @Override - final public WindowsWGLDrawable getDrawable() { return drawable; } + final public GLDrawableImpl getDrawable() { return drawable; } @Override - final public WindowsWGLContext getContext() { return context; } + final public GLContextImpl getContext() { return context; } final boolean hasARBPixelFormat() { return hasARBPixelFormat; } final boolean hasARBMultisample() { return hasARBMultisample; } @@ -302,21 +306,18 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { @Override public SharedResourceRunner.Resource createSharedResource(String connection) { - WindowsGraphicsDevice sharedDevice = new WindowsGraphicsDevice(connection, AbstractGraphicsDevice.DEFAULT_UNIT); + final WindowsGraphicsDevice sharedDevice = new WindowsGraphicsDevice(connection, AbstractGraphicsDevice.DEFAULT_UNIT); sharedDevice.lock(); try { - AbstractGraphicsScreen absScreen = new DefaultGraphicsScreen(sharedDevice, 0); - GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP, false); + final AbstractGraphicsScreen absScreen = new DefaultGraphicsScreen(sharedDevice, 0); + final GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP, false); if (null == glp) { throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice); } - final int f_dim = 64; - long hwnd = GDIUtil.CreateDummyWindow(0, 0, f_dim, f_dim); - WindowsDummyWGLDrawable sharedDrawable = WindowsDummyWGLDrawable.create(WindowsWGLDrawableFactory.this, glp, absScreen, hwnd, f_dim, f_dim, true); - if (null == sharedDrawable) { - throw new GLException("Couldn't create shared drawable for screen: "+absScreen+", "+glp); - } - WindowsWGLContext sharedContext = (WindowsWGLContext) sharedDrawable.createContext(null); + final GLDrawableImpl sharedDrawable = createOnscreenDrawableImpl(createDummySurfaceImpl(sharedDevice, false, new GLCapabilities(glp), null, 64, 64)); + sharedDrawable.setRealized(true); + + final GLContextImpl sharedContext = (GLContextImpl) sharedDrawable.createContext(null); if (null == sharedContext) { throw new GLException("Couldn't create shared context for drawable: "+sharedDrawable); } @@ -329,7 +330,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { try { hasARBPixelFormat = sharedContext.isExtensionAvailable(WGL_ARB_pixel_format); hasARBMultisample = sharedContext.isExtensionAvailable(WGL_ARB_multisample); - hasARBPBuffer = sharedContext.isExtensionAvailable(GL_ARB_pbuffer); + hasARBPBuffer = sharedContext.isExtensionAvailable(GLExtensions.ARB_pbuffer); hasARBReadDrawableAvailable = sharedContext.isExtensionAvailable(WGL_ARB_make_current_read) && sharedContext.isFunctionAvailable(wglMakeContextCurrent); vendor = sharedContext.getGL().glGetString(GL.GL_VENDOR); @@ -401,7 +402,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { return false; } - final static String GL_ARB_pbuffer = "GL_ARB_pbuffer"; + final static String WGL_ARB_pbuffer = "WGL_ARB_pbuffer"; final static String WGL_ARB_pixel_format = "WGL_ARB_pixel_format"; final static String WGL_ARB_multisample = "WGL_ARB_multisample"; final static String WGL_NV_float_buffer = "WGL_NV_float_buffer"; @@ -534,22 +535,89 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { } @Override - protected final NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) { - AbstractGraphicsScreen screen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS); - WrappedSurface ns = new WrappedSurface(WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( - capsChosen, capsRequested, chooser, screen) ); - ns.surfaceSizeChanged(width, height); - return ns; + protected final ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, + GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, + GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) { + final WindowsGraphicsDevice device; + if(createNewDevice) { + device = new WindowsGraphicsDevice(deviceReq.getConnection(), deviceReq.getUnitID()); + } else { + device = (WindowsGraphicsDevice)deviceReq; + } + final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, 0); + final WindowsWGLGraphicsConfiguration config = WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen); + if(null == config) { + throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen); + } + return new WrappedSurface(config, 0, width, height, lifecycleHook); } @Override - protected final ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice adevice, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) { - // FIXME device/windowHandle -> screen ?! - WindowsGraphicsDevice device = (WindowsGraphicsDevice) adevice; - AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, 0); - WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen); - GDISurface ns = new GDISurface(cfg, windowHandle); - return ns; + public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, + GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) { + final WindowsGraphicsDevice device; + if(createNewDevice) { + device = new WindowsGraphicsDevice(deviceReq.getConnection(), deviceReq.getUnitID()); + } else { + device = (WindowsGraphicsDevice)deviceReq; + } + final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, 0); + final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(requestedCaps); + final WindowsWGLGraphicsConfiguration config = WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(chosenCaps, requestedCaps, chooser, screen); + if(null == config) { + throw new GLException("Choosing GraphicsConfiguration failed w/ "+requestedCaps+" on "+screen); + } + return new GDISurface(config, 0, width, height, dummySurfaceLifecycleHook); + } + private static final ProxySurface.UpstreamSurfaceHook dummySurfaceLifecycleHook = new ProxySurface.UpstreamSurfaceHook() { + @Override + public final void create(ProxySurface s) { + final GDISurface ms = (GDISurface)s; + if(0 == ms.getWindowHandle()) { + final long windowHandle = GDIUtil.CreateDummyWindow(0, 0, s.getWidth(), s.getHeight()); + if(0 == windowHandle) { + throw new GLException("Error windowHandle 0, werr: "+GDI.GetLastError()); + } + ms.setWindowHandle(windowHandle); + if(DEBUG) { + System.err.println("WindowsWGLDrawableFactory.dummySurfaceLifecycleHook.create: "+ms); + } + } + } + @Override + public final void destroy(ProxySurface s) { + final GDISurface ms = (GDISurface)s; + if(0 != ms.getWindowHandle()) { + GDI.ShowWindow(ms.getWindowHandle(), GDI.SW_HIDE); + GDIUtil.DestroyDummyWindow(ms.getWindowHandle()); + ms.setWindowHandle(0); + if(DEBUG) { + System.err.println("WindowsWGLDrawableFactory.dummySurfaceLifecycleHook.destroy: "+ms); + } + } + } + @Override + public final int getWidth(ProxySurface s) { + return s.initialWidth; + } + @Override + public final int getHeight(ProxySurface s) { + return s.initialHeight; + } + + @Override + public String toString() { + return "GDISurfaceLifecycleHook[]"; + } + }; + + + @Override + protected final ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) { + final WindowsGraphicsDevice device = new WindowsGraphicsDevice(deviceReq.getConnection(), deviceReq.getUnitID()); + final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx); + final WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen); + return new GDISurface(cfg, windowHandle, 0, 0, upstream); } @Override diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java index 408d8b074..209589b29 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java @@ -48,11 +48,13 @@ import javax.media.opengl.GLPbuffer; import javax.media.opengl.GLProfile; import com.jogamp.nativewindow.MutableGraphicsConfiguration; +import com.jogamp.opengl.GLExtensions; import jogamp.nativewindow.windows.DWM_BLURBEHIND; import jogamp.nativewindow.windows.GDI; import jogamp.nativewindow.windows.MARGINS; import jogamp.nativewindow.windows.PIXELFORMATDESCRIPTOR; +import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLGraphicsConfigurationUtil; public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable { @@ -160,7 +162,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio } if (!WGLUtil.SetPixelFormat(hdc, caps.getPFDID(), caps.getPFD())) { - throw new GLException("Unable to set pixel format " + caps + + throw new GLException("Unable to set pixel format " + caps.getPFDID() + " of " + caps + " for device context " + toHexString(hdc) + ": error code " + GDI.GetLastError()); } @@ -250,7 +252,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio } if(sharedResource.hasARBPBuffer()) { - WindowsWGLContext sharedCtx = sharedResource.getContext(); + GLContextImpl sharedCtx = sharedResource.getContext(); if(null != sharedCtx && sharedCtx.isExtensionAvailable(WindowsWGLDrawableFactory.WGL_NV_float_buffer)) { // pbo float buffer iattributes[niattribs++] = WGLExt.WGL_FLOAT_COMPONENTS_NV; // nvidia @@ -313,12 +315,12 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio int niattribs = fillAttribsForGeneralWGLARBQuery(sharedResource, iattributes); - if (!sharedResource.getContext().getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdID, 0, niattribs, iattributes, 0, iresults, 0)) { + if (!((WindowsWGLContext)sharedResource.getContext()).getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdID, 0, niattribs, iattributes, 0, iresults, 0)) { throw new GLException("wglARBPFID2GLCapabilities: Error getting pixel format attributes for pixel format " + pfdID + " of device context " + toHexString(hdc) + ", werr " + GDI.GetLastError()); } List bucket = new ArrayList(1); - final int winattrbits = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer); + final int winattrbits = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer, false); if(AttribList2GLCapabilities(bucket, glp, hdc, pfdID, iattributes, niattribs, iresults, winattrbits)) { return (WGLGLCapabilities) bucket.get(0); } @@ -342,7 +344,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio int[] pformatsTmp = new int[WindowsWGLGraphicsConfiguration.MAX_PFORMATS]; int[] numFormatsTmp = new int[1]; - if ( !sharedResource.getContext().getWGLExt().wglChoosePixelFormatARB(hdc, iattributes, 0, + if ( !((WindowsWGLContext)sharedResource.getContext()).getWGLExt().wglChoosePixelFormatARB(hdc, iattributes, 0, fattributes, 0, WindowsWGLGraphicsConfiguration.MAX_PFORMATS, pformatsTmp, 0, numFormatsTmp, 0)) @@ -374,7 +376,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio static List wglARBPFIDs2GLCapabilities(WindowsWGLDrawableFactory.SharedResource sharedResource, long hdc, int[] pfdIDs, GLProfile glp, boolean onscreen, boolean usePBuffer) { - final int winattrbits = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer); + final int winattrbits = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer, false); return wglARBPFIDs2GLCapabilitiesImpl(sharedResource, hdc, pfdIDs, glp, winattrbits); } @@ -398,7 +400,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio for(int i = 0; i= 1 && - sharedResource.getContext().getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdIDs[i], 0, niattribs, iattributes, 0, iresults, 0) ) { + ((WindowsWGLContext)sharedResource.getContext()).getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdIDs[i], 0, niattribs, iattributes, 0, iresults, 0) ) { AttribList2GLCapabilities(bucket, glp, hdc, pfdIDs[i], iattributes, niattribs, iresults, winattrbits); } else if (DEBUG) { System.err.println("wglARBPFIDs2GLCapabilities: Cannot get pixel format attributes for pixel format " + @@ -507,9 +509,9 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio throw new GLException("Render-to-texture-rectangle requires render-to-texture to be specified"); } - WindowsWGLContext sharedCtx = sharedResource.getContext(); + GLContextImpl sharedCtx = sharedResource.getContext(); if (rect) { - if (!sharedCtx.isExtensionAvailable("GL_NV_texture_rectangle")) { + if (!sharedCtx.isExtensionAvailable(GLExtensions.NV_texture_rectangle)) { throw new GLException("Render-to-texture-rectangle requires GL_NV_texture_rectangle extension"); } } @@ -658,7 +660,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio } static WGLGLCapabilities PFD2GLCapabilities(GLProfile glp, long hdc, int pfdID, boolean onscreen) { - final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, false); + final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, false, false); List capsBucket = new ArrayList(1); if( PFD2GLCapabilities(capsBucket, glp, hdc, pfdID, winattrmask) ) { return (WGLGLCapabilities) capsBucket.get(0); diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java index 850b64aa8..943c7fec4 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java @@ -52,6 +52,7 @@ import javax.media.opengl.GLProfile; import jogamp.nativewindow.windows.GDI; import jogamp.nativewindow.windows.PIXELFORMATDESCRIPTOR; +import jogamp.opengl.GLDrawableImpl; import jogamp.opengl.GLGraphicsConfigurationFactory; import jogamp.opengl.GLGraphicsConfigurationUtil; @@ -99,10 +100,10 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat if(null==absScreen) { absScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS); } - AbstractGraphicsDevice absDevice = absScreen.getDevice(); - + final AbstractGraphicsDevice absDevice = absScreen.getDevice(); + final GLDrawableFactory factory = GLDrawableFactory.getDesktopFactory(); capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( - capsChosen, GLDrawableFactory.getDesktopFactory().canCreateGLPbuffer(absDevice) ); + capsChosen, GLContext.isFBOAvailable(absDevice, capsChosen.getGLProfile()), factory.canCreateGLPbuffer(absDevice) ); return new WindowsWGLGraphicsConfiguration( absScreen, capsChosen, capsReq, (GLCapabilitiesChooser)chooser ); } @@ -112,9 +113,9 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat if(null == sharedResource) { throw new GLException("Shared resource for device n/a: "+device); } - WindowsWGLDrawable sharedDrawable = sharedResource.getDrawable(); + GLDrawableImpl sharedDrawable = sharedResource.getDrawable(); GLCapabilitiesImmutable capsChosen = sharedDrawable.getChosenGLCapabilities(); - WindowsWGLContext sharedContext = sharedResource.getContext(); + GLContext sharedContext = sharedResource.getContext(); List availableCaps = null; if ( sharedResource.needsCurrentContext4ARBPFDQueries() ) { @@ -150,7 +151,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat } static List getAvailableGLCapabilitiesARB(long hdc, WindowsWGLDrawableFactory.SharedResource sharedResource, GLProfile glProfile) { - int[] pformats = WindowsWGLGraphicsConfiguration.wglAllARBPFIDs(sharedResource.getContext(), hdc); + int[] pformats = WindowsWGLGraphicsConfiguration.wglAllARBPFIDs((WindowsWGLContext)sharedResource.getContext(), hdc); return WindowsWGLGraphicsConfiguration.wglARBPFIDs2AllGLCapabilities(sharedResource, hdc, pformats, glProfile); } @@ -265,7 +266,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat } AbstractGraphicsDevice device = config.getScreen().getDevice(); WindowsWGLDrawableFactory.SharedResource sharedResource = ((WindowsWGLDrawableFactory)factory).getOrCreateSharedResource(device); - WindowsWGLContext sharedContext = null; + GLContext sharedContext = null; if (null != sharedResource && sharedResource.needsCurrentContext4ARBPFDQueries()) { sharedContext = sharedResource.getContext(); if(GLContext.CONTEXT_NOT_CURRENT == sharedContext.makeCurrent()) { @@ -355,7 +356,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat System.err.println("updateGraphicsConfigurationARB: wglChoosePixelFormatARB failed with: "+capsChosen); } // 2nd choice: get all GLCapabilities available, no preferred recommendedIndex available - pformats = WindowsWGLGraphicsConfiguration.wglAllARBPFIDs(sharedResource.getContext(), hdc); + pformats = WindowsWGLGraphicsConfiguration.wglAllARBPFIDs((WindowsWGLContext)sharedResource.getContext(), hdc); if (DEBUG) { final int len = ( null != pformats ) ? pformats.length : 0; System.err.println("updateGraphicsConfigurationARB: NumFormats (wglAllARBPFIDs) " + len); @@ -451,7 +452,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat if(null == pformats) { pformats = WindowsWGLGraphicsConfiguration.wglAllGDIPFIDs(hdc); } - final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, false); + final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, false, false); for (int i = 0; i < pformats.length; i++) { WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(availableCaps, glProfile, hdc, pformats[i], winattrmask); diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11DummyGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11DummyGLXDrawable.java deleted file mode 100644 index 8914e2db9..000000000 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11DummyGLXDrawable.java +++ /dev/null @@ -1,102 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package jogamp.opengl.x11.glx; - -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLCapabilitiesImmutable; -import javax.media.opengl.GLDrawableFactory; -import javax.media.opengl.GLProfile; - -import jogamp.nativewindow.x11.X11Lib; - -import com.jogamp.nativewindow.WrappedSurface; -import com.jogamp.nativewindow.x11.X11GraphicsDevice; -import com.jogamp.nativewindow.x11.X11GraphicsScreen; - -public class X11DummyGLXDrawable extends X11OnscreenGLXDrawable { - private static final int f_dim = 64; - 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, - * hence we reuse the target's screen configuration. - */ - public X11DummyGLXDrawable(X11GraphicsScreen screen, GLDrawableFactory factory, GLCapabilitiesImmutable caps) { - super(factory, - new WrappedSurface(X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( - caps, caps, null, screen))); - this.realized = true; - - WrappedSurface ns = (WrappedSurface) getNativeSurface(); - X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)ns.getGraphicsConfiguration(); - - X11GraphicsDevice device = (X11GraphicsDevice) screen.getDevice(); - long dpy = device.getHandle(); - int scrn = screen.getIndex(); - int visualID = config.getXVisualID(); - - dummyWindow = X11Lib.CreateDummyWindow(dpy, scrn, visualID, f_dim, f_dim); - ns.setSurfaceHandle( dummyWindow ); - ns.surfaceSizeChanged(f_dim, f_dim); - - updateHandle(); - } - - public static X11DummyGLXDrawable create(X11GraphicsScreen screen, GLDrawableFactory factory, GLProfile glp) { - GLCapabilities caps = new GLCapabilities(glp); - return new X11DummyGLXDrawable(screen, factory, caps); - } - - public void setSize(int width, int height) { - } - - @Override - public int getWidth() { - return 1; - } - - @Override - public int getHeight() { - return 1; - } - - - @Override - protected void setRealizedImpl() { - super.setRealizedImpl(); - if(!realized) { - if(0!=dummyWindow) { - destroyHandle(); - X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeSurface().getGraphicsConfiguration(); - X11Lib.DestroyDummyWindow(config.getScreen().getDevice().getHandle(), dummyWindow); - } - } - } -} diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java index 53776386c..b847363e0 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java @@ -76,8 +76,15 @@ public class X11ExternalGLXContext extends X11GLXContext { long drawable = GLX.glXGetCurrentDrawable(); if (drawable == 0) { throw new GLException("Error: attempted to make an external GLDrawable without a drawable/context current"); - } + } int[] val = new int[1]; + + int w, h; + GLX.glXQueryDrawable(display, drawable, GLX.GLX_WIDTH, val, 0); + w=val[0]; + GLX.glXQueryDrawable(display, drawable, GLX.GLX_HEIGHT, val, 0); + h=val[0]; + GLX.glXQueryContext(display, ctx, GLX.GLX_SCREEN, val, 0); X11GraphicsScreen x11Screen = (X11GraphicsScreen) X11GraphicsScreen.createScreenDevice(display, val[0], false); @@ -97,8 +104,7 @@ public class X11ExternalGLXContext extends X11GLXContext { cfg = X11GLXGraphicsConfiguration.create(glp, x11Screen, val[0]); } - WrappedSurface ns = new WrappedSurface(cfg); - ns.setSurfaceHandle(drawable); + final WrappedSurface ns = new WrappedSurface(cfg, drawable, w, h, null); return new X11ExternalGLXContext(new Drawable(factory, ns), ctx); } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java index 3fabe7a13..8652e2d4a 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java @@ -87,10 +87,7 @@ public class X11ExternalGLXDrawable extends X11GLXDrawable { System.err.println("X11ExternalGLXDrawable: WARNING: forcing GLX_RGBA_TYPE for newly created contexts (current 0x"+Integer.toHexString(val[0])+")"); } } - WrappedSurface ns = new WrappedSurface(cfg); - ns.setSurfaceHandle(drawable); - ns.surfaceSizeChanged(w, h); - return new X11ExternalGLXDrawable(factory, ns); + return new X11ExternalGLXDrawable(factory, new WrappedSurface(cfg, drawable, w, h, null)); } @Override diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java index 0afadc677..e6b74a769 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java @@ -61,6 +61,7 @@ import jogamp.opengl.GLDrawableImpl; import com.jogamp.common.nio.Buffers; import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; +import com.jogamp.opengl.GLExtensions; public abstract class X11GLXContext extends GLContextImpl { private static final Map functionNameMap; @@ -83,8 +84,8 @@ public abstract class X11GLXContext extends GLContextImpl { functionNameMap.put("glFreeMemoryNV", "glXFreeMemoryNV"); extensionNameMap = new HashMap(); - extensionNameMap.put("GL_ARB_pbuffer", "GLX_SGIX_pbuffer"); - extensionNameMap.put("GL_ARB_pixel_format", "GLX_SGIX_pbuffer"); // good enough + extensionNameMap.put(GLExtensions.ARB_pbuffer, X11GLXDrawableFactory.GLX_SGIX_pbuffer); + extensionNameMap.put(GLExtensions.ARB_pixel_format, X11GLXDrawableFactory.GLX_SGIX_pbuffer); // good enough } X11GLXContext(GLDrawableImpl drawable, @@ -508,8 +509,8 @@ public abstract class X11GLXContext extends GLContextImpl { @Override public boolean isExtensionAvailable(String glExtensionName) { - if (glExtensionName.equals("GL_ARB_pbuffer") || - glExtensionName.equals("GL_ARB_pixel_format")) { + if (glExtensionName.equals(GLExtensions.ARB_pbuffer) || + glExtensionName.equals(GLExtensions.ARB_pixel_format)) { return getGLDrawable().getFactory().canCreateGLPbuffer( drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice() ); } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java index 9a563bdb8..8ffbf3951 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java @@ -49,6 +49,8 @@ import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; +import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; @@ -64,6 +66,7 @@ import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableFactoryImpl; import jogamp.opengl.GLDrawableImpl; import jogamp.opengl.GLDynamicLookupHelper; +import jogamp.opengl.GLGraphicsConfigurationUtil; import jogamp.opengl.SharedResourceRunner; import com.jogamp.common.util.VersionNumber; @@ -79,6 +82,8 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { public static final VersionNumber versionOneThree = new VersionNumber(1, 3, 0); public static final VersionNumber versionOneFour = new VersionNumber(1, 4, 0); + static final String GLX_SGIX_pbuffer = "GLX_SGIX_pbuffer"; + private static DesktopGLDynamicLookupHelper x11GLXDynamicLookupHelper = null; public X11GLXDrawableFactory() { @@ -153,8 +158,8 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { static class SharedResource implements SharedResourceRunner.Resource { X11GraphicsDevice device; X11GraphicsScreen screen; - X11DummyGLXDrawable drawable; - X11GLXContext context; + GLDrawableImpl drawable; + GLContextImpl context; String glXServerVendorName; boolean isGLXServerVendorATI; boolean isGLXServerVendorNVIDIA; @@ -164,7 +169,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { boolean glXMultisampleAvailable; SharedResource(X11GraphicsDevice dev, X11GraphicsScreen scrn, - X11DummyGLXDrawable draw, X11GLXContext ctx, + GLDrawableImpl draw, GLContextImpl ctx, VersionNumber glXServerVer, String glXServerVendor, boolean glXServerMultisampleAvail) { device = dev; screen = scrn; @@ -224,13 +229,15 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { @Override public SharedResourceRunner.Resource createSharedResource(String connection) { - X11GraphicsDevice sharedDevice = + final X11GraphicsDevice sharedDevice = new X11GraphicsDevice(X11Util.openDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT, - true); // own non-shared display connection, no locking + true); // own non-shared display connection, w/ locking // new X11GraphicsDevice(X11Util.openDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT, - // NativeWindowFactory.getNullToolkitLock(), true); // own non-shared display connection, no locking + // NativeWindowFactory.getNullToolkitLock(), true); // own non-shared display connection, w/o locking sharedDevice.lock(); try { + final X11GraphicsScreen sharedScreen = new X11GraphicsScreen(sharedDevice, 0); + if(!GLXUtil.isGLXAvailableOnServer(sharedDevice)) { throw new GLException("GLX not available on device/server: "+sharedDevice); } @@ -242,20 +249,20 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { X11Util.setMarkAllDisplaysUnclosable(true); X11Util.markDisplayUncloseable(sharedDevice.getHandle()); } - X11GraphicsScreen sharedScreen = new X11GraphicsScreen(sharedDevice, 0); - - GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP, false); + + final GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP, false); if (null == glp) { throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice); } - X11DummyGLXDrawable sharedDrawable = X11DummyGLXDrawable.create(sharedScreen, X11GLXDrawableFactory.this, glp); - if (null == sharedDrawable) { - throw new GLException("Couldn't create shared drawable for screen: "+sharedScreen+", "+glp); - } - X11GLXContext sharedContext = (X11GLXContext) sharedDrawable.createContext(null); + + final GLDrawableImpl sharedDrawable = createOnscreenDrawableImpl(createDummySurfaceImpl(sharedDevice, false, new GLCapabilities(glp), null, 64, 64)); + sharedDrawable.setRealized(true); + + final GLContextImpl sharedContext = (GLContextImpl) sharedDrawable.createContext(null); if (null == sharedContext) { throw new GLException("Couldn't create shared context for drawable: "+sharedDrawable); } + boolean madeCurrent = false; sharedContext.makeCurrent(); try { @@ -298,7 +305,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { if (null != sr.context) { // may cause JVM SIGSEGV: - sr.context.destroy(); + sr.context.destroy(); // will also pull the dummy MutuableSurface sr.context = null; } @@ -394,7 +401,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { if (target == null) { throw new IllegalArgumentException("Null target"); } - return new X11OnscreenGLXDrawable(this, target); + return new X11OnscreenGLXDrawable(this, target, false); } @Override @@ -495,40 +502,88 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } @Override - protected final NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice deviceReq, - GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, - GLCapabilitiesChooser chooser, - int width, int height) { - if(null == deviceReq) { - throw new InternalError("deviceReq is null"); - } - final SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(deviceReq); - if(null==sr) { - throw new InternalError("No SharedResource for: "+deviceReq); + protected final ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, + GLCapabilitiesImmutable capsChosen, + GLCapabilitiesImmutable capsRequested, + GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) { + final X11GraphicsDevice device; + if(createNewDevice) { + // Null X11 locking, due to private non-shared Display handle + device = new X11GraphicsDevice(X11Util.openDisplay(deviceReq.getConnection()), deviceReq.getUnitID(), NativeWindowFactory.getNullToolkitLock(), true); + } else { + device = (X11GraphicsDevice)deviceReq; } - final X11GraphicsScreen sharedScreen = (X11GraphicsScreen) sr.getScreen(); - final AbstractGraphicsDevice sharedDevice = sharedScreen.getDevice(); // should be same .. - - // create screen/device pair - Null X11 locking, due to private non-shared Display handle - final X11GraphicsDevice device = new X11GraphicsDevice(X11Util.openDisplay(sharedDevice.getConnection()), AbstractGraphicsDevice.DEFAULT_UNIT, NativeWindowFactory.getNullToolkitLock(), true); - final X11GraphicsScreen screen = new X11GraphicsScreen(device, sharedScreen.getIndex()); - - WrappedSurface ns = new WrappedSurface( - X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen) ); - if(ns != null) { - ns.surfaceSizeChanged(width, height); + final X11GraphicsScreen screen = new X11GraphicsScreen(device, 0); + final X11GLXGraphicsConfiguration config = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen); + if(null == config) { + throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen); } - return ns; + return new WrappedSurface( config, 0, width, height, lifecycleHook); } @Override - protected final ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice adevice, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) { - // FIXME device/windowHandle -> screen ?! - X11GraphicsDevice device = (X11GraphicsDevice) adevice; - X11GraphicsScreen screen = new X11GraphicsScreen(device, 0); - X11GLXGraphicsConfiguration cfg = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen); - WrappedSurface ns = new WrappedSurface(cfg, windowHandle); - return ns; + public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, + GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) { + final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(requestedCaps); + return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, width, height, dummySurfaceLifecycleHook); + } + private static final ProxySurface.UpstreamSurfaceHook dummySurfaceLifecycleHook = new ProxySurface.UpstreamSurfaceHook() { + @Override + public final void create(ProxySurface s) { + if( 0 == s.getSurfaceHandle() ) { + final X11GLXGraphicsConfiguration cfg = (X11GLXGraphicsConfiguration) s.getGraphicsConfiguration(); + final X11GraphicsScreen screen = (X11GraphicsScreen) cfg.getScreen(); + final X11GraphicsDevice device = (X11GraphicsDevice) screen.getDevice(); + if(0 == device.getHandle()) { + device.open(); + s.setImplBitfield(ProxySurface.OWN_DEVICE); + } + final long windowHandle = X11Lib.CreateDummyWindow(device.getHandle(), screen.getIndex(), cfg.getXVisualID(), s.getWidth(), s.getHeight()); + if(0 == windowHandle) { + throw new GLException("Creating dummy window failed w/ "+cfg+", "+s.getWidth()+"x"+s.getHeight()); + } + s.setSurfaceHandle(windowHandle); + if(DEBUG) { + System.err.println("X11GLXDrawableFactory.dummySurfaceLifecycleHook.create: "+s); + } + } + } + @Override + public final void destroy(ProxySurface s) { + if(0 != s.getSurfaceHandle()) { + final X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration) s.getGraphicsConfiguration(); + final X11GraphicsDevice device = (X11GraphicsDevice) config.getScreen().getDevice(); + X11Lib.DestroyDummyWindow(device.getHandle(), s.getSurfaceHandle()); + s.setSurfaceHandle(0); + if( 0 != ( ProxySurface.OWN_DEVICE & s.getImplBitfield() ) ) { + device.close(); + } + if(DEBUG) { + System.err.println("X11GLXDrawableFactory.dummySurfaceLifecycleHook.destroy: "+s); + } + } + } + @Override + public final int getWidth(ProxySurface s) { + return s.initialWidth; + } + @Override + public final int getHeight(ProxySurface s) { + return s.initialHeight; + } + @Override + public String toString() { + return "X11SurfaceLifecycleHook[]"; + } + }; + + + @Override + protected final ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) { + final X11GraphicsDevice device = new X11GraphicsDevice(X11Util.openDisplay(deviceReq.getConnection()), deviceReq.getUnitID(), NativeWindowFactory.getNullToolkitLock(), true); + final X11GraphicsScreen screen = new X11GraphicsScreen(device, screenIdx); + final X11GLXGraphicsConfiguration cfg = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen); + return new WrappedSurface(cfg, windowHandle, 0, 0, upstream); } @Override diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java index b54b5150c..b5b80e0b3 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java @@ -36,12 +36,14 @@ package jogamp.opengl.x11.glx; import java.util.ArrayList; import java.util.List; +import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.opengl.DefaultGLCapabilitiesChooser; import javax.media.opengl.GL; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; @@ -67,7 +69,8 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem } static X11GLXGraphicsConfiguration create(GLProfile glp, X11GraphicsScreen x11Screen, int fbcfgID) { - final long display = x11Screen.getDevice().getHandle(); + final AbstractGraphicsDevice device = x11Screen.getDevice(); + final long display = device.getHandle(); if(0==display) { throw new GLException("Display null of "+x11Screen); } @@ -80,7 +83,7 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem glp = GLProfile.getDefault(x11Screen.getDevice()); } final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory(); - final X11GLCapabilities caps = GLXFBConfig2GLCapabilities(glp, display, fbcfg, true, true, true, factory.isGLXMultisampleAvailable(x11Screen.getDevice())); + final X11GLCapabilities caps = GLXFBConfig2GLCapabilities(glp, device, fbcfg, true, true, true, factory.isGLXMultisampleAvailable(device)); if(null==caps) { throw new GLException("GLCapabilities null of "+toHexString(fbcfg)); } @@ -233,11 +236,11 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem return true; } - static int FBCfgDrawableTypeBits(final long display, final long fbcfg) { + static int FBCfgDrawableTypeBits(final AbstractGraphicsDevice device, GLProfile glp, final long fbcfg) { int val = 0; int[] tmp = new int[1]; - int fbtype = glXGetFBConfig(display, fbcfg, GLX.GLX_DRAWABLE_TYPE, tmp, 0); + int fbtype = glXGetFBConfig(device.getHandle(), fbcfg, GLX.GLX_DRAWABLE_TYPE, tmp, 0); if ( 0 != ( fbtype & GLX.GLX_WINDOW_BIT ) ) { val |= GLGraphicsConfigurationUtil.WINDOW_BIT; @@ -248,17 +251,20 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem if ( 0 != ( fbtype & GLX.GLX_PBUFFER_BIT ) ) { val |= GLGraphicsConfigurationUtil.PBUFFER_BIT; } + if ( GLContext.isFBOAvailable(device, glp) ) { + val |= GLGraphicsConfigurationUtil.FBO_BIT; + } return val; } - static X11GLCapabilities GLXFBConfig2GLCapabilities(GLProfile glp, long display, long fbcfg, + static X11GLCapabilities GLXFBConfig2GLCapabilities(GLProfile glp, AbstractGraphicsDevice device, long fbcfg, boolean relaxed, boolean onscreen, boolean usePBuffer, boolean isMultisampleAvailable) { ArrayList bucket = new ArrayList(); - final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer); - if( GLXFBConfig2GLCapabilities(bucket, glp, display, fbcfg, winattrmask, isMultisampleAvailable) ) { + final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer, false); + if( GLXFBConfig2GLCapabilities(bucket, glp, device, fbcfg, winattrmask, isMultisampleAvailable) ) { return (X11GLCapabilities) bucket.get(0); - } else if ( relaxed && GLXFBConfig2GLCapabilities(bucket, glp, display, fbcfg, GLGraphicsConfigurationUtil.ALL_BITS, isMultisampleAvailable) ) { + } else if ( relaxed && GLXFBConfig2GLCapabilities(bucket, glp, device, fbcfg, GLGraphicsConfigurationUtil.ALL_BITS, isMultisampleAvailable) ) { return (X11GLCapabilities) bucket.get(0); } return null; @@ -273,11 +279,12 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem } static boolean GLXFBConfig2GLCapabilities(List capsBucket, - GLProfile glp, long display, long fbcfg, + GLProfile glp, AbstractGraphicsDevice device, long fbcfg, int winattrmask, boolean isMultisampleAvailable) { - final int allDrawableTypeBits = FBCfgDrawableTypeBits(display, fbcfg); + final int allDrawableTypeBits = FBCfgDrawableTypeBits(device, glp, fbcfg); int drawableTypeBits = winattrmask & allDrawableTypeBits; - + + final long display = device.getHandle(); int fbcfgid = X11GLXGraphicsConfiguration.glXFBConfig2FBConfigID(display, fbcfg); XVisualInfo visualInfo = GLX.glXGetVisualFromFBConfig(display, fbcfg); if(null == visualInfo) { diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java index 8377d2453..331401c06 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java @@ -44,6 +44,7 @@ import javax.media.opengl.DefaultGLCapabilitiesChooser; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; @@ -161,7 +162,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF return null; } for (int i = 0; i < fbcfgsL.limit(); i++) { - if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, display, fbcfgsL.get(i), GLGraphicsConfigurationUtil.ALL_BITS, isMultisampleAvailable) ) { + if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, absDevice, fbcfgsL.get(i), GLGraphicsConfigurationUtil.ALL_BITS, isMultisampleAvailable) ) { if(DEBUG) { System.err.println("X11GLXGraphicsConfiguration.getAvailableGLCapabilitiesFBConfig: FBConfig invalid (2): ("+x11Screen+"): fbcfg: "+toHexString(fbcfgsL.get(i))); } @@ -209,7 +210,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF X11GraphicsDevice x11Device = (X11GraphicsDevice) x11Screen.getDevice(); X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory(); - capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, factory.canCreateGLPbuffer(x11Device) ); + capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, GLContext.isFBOAvailable(x11Device, capsChosen.getGLProfile()), factory.canCreateGLPbuffer(x11Device) ); boolean usePBuffer = capsChosen.isPBuffer(); X11GLXGraphicsConfiguration res = null; @@ -245,7 +246,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF } final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory(); - final X11GLCapabilities caps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glp, display, fbcfg, true, true, true, factory.isGLXMultisampleAvailable(absDevice)); + final X11GLCapabilities caps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glp, absDevice, fbcfg, true, true, true, factory.isGLXMultisampleAvailable(absDevice)); return new X11GLXGraphicsConfiguration(x11Screen, caps, caps, new DefaultGLCapabilitiesChooser()); } @@ -258,6 +259,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF GLProfile glProfile = capsChosen.getGLProfile(); boolean onscreen = capsChosen.isOnscreen(); boolean usePBuffer = capsChosen.isPBuffer(); + boolean useFBO = capsChosen.isFBO(); // Utilizing FBConfig // @@ -270,13 +272,12 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capsChosen, true, isMultisampleAvailable, display, screen); int[] count = { -1 }; List availableCaps = new ArrayList(); - final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer); - + final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer, useFBO); // 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice fbcfgsL = GLX.glXChooseFBConfig(display, screen, attribs, 0, count, 0); if (fbcfgsL != null && fbcfgsL.limit()>0) { for (int i = 0; i < fbcfgsL.limit(); i++) { - if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, display, fbcfgsL.get(i), winattrmask, isMultisampleAvailable) ) { + if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, absDevice, fbcfgsL.get(i), winattrmask, isMultisampleAvailable) ) { if(DEBUG) { System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: FBConfig invalid (1): ("+x11Screen+","+capsChosen+"): fbcfg: "+toHexString(fbcfgsL.get(i))); } @@ -309,7 +310,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF } for (int i = 0; i < fbcfgsL.limit(); i++) { - if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, display, fbcfgsL.get(i), winattrmask, isMultisampleAvailable) ) { + if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, absDevice, fbcfgsL.get(i), winattrmask, isMultisampleAvailable) ) { if(DEBUG) { System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: FBConfig invalid (2): ("+x11Screen+"): fbcfg: "+toHexString(fbcfgsL.get(i))); } @@ -338,7 +339,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF } GLProfile glProfile = capsChosen.getGLProfile(); - final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(capsChosen.isOnscreen(), false /* pbuffer */); + final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(capsChosen.isOnscreen(), false /* pbuffer */, false); List availableCaps = new ArrayList(); int recommendedIndex = -1; diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java index 9e22afa6d..363299321 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java @@ -51,10 +51,13 @@ public class X11OnscreenGLXDrawable extends X11GLXDrawable { long glXWindow; // GLXWindow, a GLXDrawable representation boolean useGLXWindow; - protected X11OnscreenGLXDrawable(GLDrawableFactory factory, NativeSurface component) { - super(factory, component, false); + protected X11OnscreenGLXDrawable(GLDrawableFactory factory, NativeSurface component, boolean realized) { + super(factory, component, realized); glXWindow=0; useGLXWindow=false; + if(realized) { + updateHandle(); + } } @Override diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java index cdf81ebd3..e1fe2f27e 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java @@ -43,7 +43,7 @@ package jogamp.opengl.x11.glx; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.NativeSurface; -import javax.media.nativewindow.SurfaceChangeable; +import javax.media.nativewindow.MutableSurface; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawableFactory; @@ -77,7 +77,7 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable { if (ns.getSurfaceHandle() != 0) { GLX.glXDestroyPbuffer(ns.getDisplayHandle(), ns.getSurfaceHandle()); } - ((SurfaceChangeable)ns).setSurfaceHandle(0); + ((MutableSurface)ns).setSurfaceHandle(0); } private void createPbuffer() { @@ -108,12 +108,14 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable { // Create the p-buffer. int niattribs = 0; - int[] iattributes = new int[5]; + int[] iattributes = new int[7]; iattributes[niattribs++] = GLX.GLX_PBUFFER_WIDTH; iattributes[niattribs++] = ns.getWidth(); iattributes[niattribs++] = GLX.GLX_PBUFFER_HEIGHT; iattributes[niattribs++] = ns.getHeight(); + iattributes[niattribs++] = GLX.GLX_LARGEST_PBUFFER; // exact + iattributes[niattribs++] = 0; iattributes[niattribs++] = 0; long pbuffer = GLX.glXCreatePbuffer(display, config.getFBConfig(), iattributes, 0); @@ -123,15 +125,7 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable { } // Set up instance variables - ((SurfaceChangeable)ns).setSurfaceHandle(pbuffer); - - // Determine the actual width and height we were able to create. - int[] tmp = new int[1]; - GLX.glXQueryDrawable(display, pbuffer, GLX.GLX_WIDTH, tmp, 0); - int width = tmp[0]; - GLX.glXQueryDrawable(display, pbuffer, GLX.GLX_HEIGHT, tmp, 0); - int height = tmp[0]; - ((SurfaceChangeable)ns).surfaceSizeChanged(width, height); + ((MutableSurface)ns).setSurfaceHandle(pbuffer); if (DEBUG) { System.err.println("Created pbuffer " + this); diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java index 1e7b89828..04627724c 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java @@ -43,7 +43,7 @@ package jogamp.opengl.x11.glx; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.NativeSurface; -import javax.media.nativewindow.SurfaceChangeable; +import javax.media.nativewindow.MutableSurface; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; @@ -93,7 +93,7 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable { pixmap = 0; throw new GLException("glXCreateGLXPixmap failed"); } - ((SurfaceChangeable)ns).setSurfaceHandle(drawable); + ((MutableSurface)ns).setSurfaceHandle(drawable); if (DEBUG) { System.err.println("Created pixmap " + toHexString(pixmap) + ", GLXPixmap " + toHexString(drawable) + @@ -133,7 +133,7 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable { X11Lib.XFreePixmap(display, pixmap); drawable = 0; pixmap = 0; - ((SurfaceChangeable)ns).setSurfaceHandle(0); + ((MutableSurface)ns).setSurfaceHandle(0); display = 0; } } diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m index 776284cfc..b81b43e54 100644 --- a/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m +++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m @@ -32,7 +32,6 @@ int texWidth; int texHeight; GLuint textureID; - struct timespec lastWaitTime; #ifdef HAS_CADisplayLink CADisplayLink* displayLink; #else @@ -41,6 +40,7 @@ int tc; struct timespec t0; @public + struct timespec lastWaitTime; GLint swapInterval; GLint swapIntervalCounter; pthread_mutex_t renderLock; diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface.m index 8ac9f4700..d3f703142 100644 --- a/src/jogl/native/macosx/MacOSXWindowSystemInterface.m +++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface.m @@ -503,7 +503,7 @@ NSView* getNSView(NSOpenGLContext* ctx) { NSOpenGLContext* createContext(NSOpenGLContext* share, NSView* view, - Bool isBackingLayerView, + Bool allowIncompleteView, NSOpenGLPixelFormat* fmt, Bool opaque, int* viewNotReady) @@ -512,13 +512,13 @@ NSOpenGLContext* createContext(NSOpenGLContext* share, getRendererInfo(); - DBG_PRINT("createContext.0: share %p, view %p, isBackingLayer %d, pixfmt %p, opaque %d\n", - share, view, (int)isBackingLayerView, fmt, opaque); + DBG_PRINT("createContext.0: share %p, view %p, allowIncompleteView %d, pixfmt %p, opaque %d\n", + share, view, (int)allowIncompleteView, fmt, opaque); if (view != NULL) { Bool viewReady = true; - if(!isBackingLayerView) { + if(!allowIncompleteView) { if ([view lockFocusIfCanDraw] == NO) { DBG_PRINT("createContext.1 [view lockFocusIfCanDraw] failed\n"); viewReady = false; @@ -527,7 +527,7 @@ NSOpenGLContext* createContext(NSOpenGLContext* share, if(viewReady) { NSRect frame = [view frame]; if ((frame.size.width == 0) || (frame.size.height == 0)) { - if(!isBackingLayerView) { + if(!allowIncompleteView) { [view unlockFocus]; } DBG_PRINT("createContext.2 view.frame size %dx%d\n", (int)frame.size.width, (int)frame.size.height); @@ -558,7 +558,7 @@ NSOpenGLContext* createContext(NSOpenGLContext* share, [ctx setValues:&zeroOpacity forParameter:NSOpenGLCPSurfaceOpacity]; } [ctx setView:view]; - if(!isBackingLayerView) { + if(!allowIncompleteView) { [view unlockFocus]; } } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/WrappedSurface.java b/src/nativewindow/classes/com/jogamp/nativewindow/WrappedSurface.java index 04f616daf..b7f6ba45d 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/WrappedSurface.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/WrappedSurface.java @@ -30,51 +30,49 @@ package com.jogamp.nativewindow; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.ProxySurface; -import javax.media.nativewindow.SurfaceChangeable; +public class WrappedSurface extends ProxySurface { + protected long surfaceHandle; -public class WrappedSurface extends ProxySurface implements SurfaceChangeable { - protected long surfaceHandle; - - public WrappedSurface(AbstractGraphicsConfiguration cfg) { - this(cfg, 0); - } - - public WrappedSurface(AbstractGraphicsConfiguration cfg, long handle) { - super(cfg); + public WrappedSurface(AbstractGraphicsConfiguration cfg, long handle, int initialWidth, int initialHeight, UpstreamSurfaceHook upstream) { + super(cfg, initialWidth, initialHeight, upstream); surfaceHandle=handle; } @Override - protected final void invalidateImpl() { + protected void invalidateImpl() { surfaceHandle = 0; } @Override - final public long getSurfaceHandle() { + public final long getSurfaceHandle() { return surfaceHandle; } @Override - final public void setSurfaceHandle(long surfaceHandle) { + public final void setSurfaceHandle(long surfaceHandle) { this.surfaceHandle=surfaceHandle; } - + @Override - final protected int lockSurfaceImpl() { - return LOCK_SUCCESS; + protected final int lockSurfaceImpl() { + return LOCK_SUCCESS; } @Override - final protected void unlockSurfaceImpl() { + protected final void unlockSurfaceImpl() { } @Override public String toString() { + final UpstreamSurfaceHook ush = getUpstreamSurfaceHook(); + final String ush_s = null != ush ? ( ush.getClass().getName() + ": " + ush ) : "nil"; + return "WrappedSurface[config " + getPrivateGraphicsConfiguration()+ ", displayHandle 0x" + Long.toHexString(getDisplayHandle()) + ", surfaceHandle 0x" + Long.toHexString(getSurfaceHandle()) + ", size " + getWidth() + "x" + getHeight() + - ", surfaceLock "+surfaceLock+"]"; + ", surfaceLock "+surfaceLock+ + ", upstreamSurfaceHook "+ush_s+"]"; } } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java index d161f2f34..389949e90 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java @@ -38,7 +38,7 @@ import javax.media.nativewindow.*; */ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneable { final long nativeDisplayID; - final EGLTerminateCallback eglTerminateCallback; + final EGLDisplayLifecycleCallback eglLifecycleCallback; /** * Hack to allow inject a EGL termination call. @@ -47,7 +47,14 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl * since then it can be utilized directly. *

      */ - public interface EGLTerminateCallback { + public interface EGLDisplayLifecycleCallback { + /** + * Implementation should issue an EGL.eglGetDisplay(nativeDisplayID) + * inclusive EGL.eglInitialize(eglDisplayHandle, ..) call. + * @param eglDisplayHandle + */ + public long eglGetAndInitDisplay(long nativeDisplayID); + /** * Implementation should issue an EGL.eglTerminate(eglDisplayHandle) call. * @param eglDisplayHandle @@ -61,28 +68,45 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl */ public EGLGraphicsDevice(String connection, int unitID) { super(NativeWindowFactory.TYPE_EGL, connection, unitID); - this.nativeDisplayID = 0; - this.eglTerminateCallback = null; + this.nativeDisplayID = 0 ; // EGL.EGL_DEFAULT_DISPLAY + this.eglLifecycleCallback = null; } - public EGLGraphicsDevice(long nativeDisplayID, long eglDisplay, String connection, int unitID, EGLTerminateCallback eglTerminateCallback) { + public EGLGraphicsDevice(long nativeDisplayID, long eglDisplay, String connection, int unitID, EGLDisplayLifecycleCallback eglLifecycleCallback) { super(NativeWindowFactory.TYPE_EGL, connection, unitID, eglDisplay); this.nativeDisplayID = nativeDisplayID; - this.eglTerminateCallback = eglTerminateCallback; + this.eglLifecycleCallback = eglLifecycleCallback; } public long getNativeDisplayID() { return nativeDisplayID; } + @Override public Object clone() { return super.clone(); } + + @Override + public boolean open() { + if(null != eglLifecycleCallback && 0 == handle) { + if(DEBUG) { + System.err.println(Thread.currentThread().getName() + " - EGLGraphicsDevice.open(): "+this); + } + handle = eglLifecycleCallback.eglGetAndInitDisplay(nativeDisplayID); + if(0 == handle) { + throw new NativeWindowException("EGLGraphicsDevice.open() failed: "+this); + } + return true; + } + return false; + } + @Override public boolean close() { - if(null != eglTerminateCallback) { + if(null != eglLifecycleCallback && 0 != handle) { if(DEBUG) { - System.err.println(Thread.currentThread().getName() + " - eglTerminate: "+this); + System.err.println(Thread.currentThread().getName() + " - EGLGraphicsDevice.close(): "+this); } - eglTerminateCallback.eglTerminate(handle); + eglLifecycleCallback.eglTerminate(handle); } return super.close(); } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java index 735d85fb1..0494bb408 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java @@ -43,7 +43,6 @@ import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice; import com.jogamp.nativewindow.windows.WindowsGraphicsDevice; import com.jogamp.nativewindow.x11.X11GraphicsDevice; -import jogamp.common.awt.AWTEDTExecutor; import jogamp.nativewindow.macosx.OSXUtil; public class SWTAccessor { @@ -204,8 +203,6 @@ public class SWTAccessor { if( null != OS_gtk_class ) { long widgedHandle = callStaticMethodL2L(OS_GTK_WIDGET_WINDOW, handle); long displayHandle = callStaticMethodL2L(OS_gdk_x11_drawable_get_xdisplay, widgedHandle); - // FIXME: May think about creating a private non-shared X11 Display handle, like we use to for AWT - // to avoid locking problems ! return new X11GraphicsDevice(displayHandle, AbstractGraphicsDevice.DEFAULT_UNIT, false); } if( NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false) ) { diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java index a02332413..7a98e3c25 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java @@ -33,7 +33,6 @@ package com.jogamp.nativewindow.x11; -import jogamp.nativewindow.Debug; import jogamp.nativewindow.x11.X11Lib; import jogamp.nativewindow.x11.X11Util; @@ -46,7 +45,7 @@ import javax.media.nativewindow.ToolkitLock; */ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneable { - final boolean closeDisplay; + final boolean handleOwner; /** Constructs a new X11GraphicsDevice corresponding to the given connection and default * {@link javax.media.nativewindow.ToolkitLock} via {@link NativeWindowFactory#getDefaultToolkitLock(String)}.
      @@ -56,7 +55,7 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl */ public X11GraphicsDevice(String connection, int unitID) { super(NativeWindowFactory.TYPE_X11, connection, unitID); - closeDisplay = false; + handleOwner = false; } /** Constructs a new X11GraphicsDevice corresponding to the given native display handle and default @@ -69,7 +68,7 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl if(0==display) { throw new NativeWindowException("null display"); } - closeDisplay = owner; + handleOwner = owner; } /** @@ -82,16 +81,39 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl if(0==display) { throw new NativeWindowException("null display"); } - closeDisplay = owner; + handleOwner = owner; } + public int getDefaultVisualID() { + // It still could be an AWT hold handle .. + final long display = getHandle(); + final int scrnIdx = X11Lib.DefaultScreen(display); + return (int) X11Lib.DefaultVisualID(display, scrnIdx); + } + + @Override public Object clone() { return super.clone(); } + @Override + public boolean open() { + if(handleOwner && 0 == handle) { + if(DEBUG) { + System.err.println(Thread.currentThread().getName() + " - X11GraphicsDevice.open(): "+this); + } + handle = X11Util.openDisplay(connection); + if(0 == handle) { + throw new NativeWindowException("X11GraphicsDevice.open() failed: "+this); + } + return true; + } + return false; + } + + @Override public boolean close() { - // FIXME: shall we respect the unitID ? - if(closeDisplay && 0 != handle) { + if(handleOwner && 0 != handle) { if(DEBUG) { System.err.println(Thread.currentThread().getName() + " - X11GraphicsDevice.close(): "+this); } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java index 94013ec38..014f4f688 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java @@ -56,13 +56,11 @@ public class X11GraphicsScreen extends DefaultGraphicsScreen implements Cloneabl return new X11GraphicsScreen(new X11GraphicsDevice(display, AbstractGraphicsDevice.DEFAULT_UNIT, owner), screenIdx); } - public long getDefaultVisualID() { + public int getVisualID() { // It still could be an AWT hold handle .. - long display = getDevice().getHandle(); - int scrnIdx = X11Lib.DefaultScreen(display); - return X11Lib.DefaultVisualID(display, scrnIdx); + return (int) X11Lib.DefaultVisualID(getDevice().getHandle(), getIndex()); } - + private static int fetchScreen(X11GraphicsDevice device, int screen) { // It still could be an AWT hold handle .. if(X11Util.XineramaIsEnabled(device.getHandle())) { diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java index 4979f1949..756e4451b 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java @@ -113,16 +113,33 @@ public interface AbstractGraphicsDevice extends Cloneable { */ public void unlock(); + /** + * Optionally [re]opening the device if handle is null. + *

      + * The default implementation is a NOP. + *

      + *

      + * Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice} + * or {@link com.jogamp.nativewindow.egl.EGLGraphicsDevice} + * issue the native open operation in case handle is null. + *

      + * + * @return true if the handle was null and opening was successful, otherwise false. + */ + public boolean open(); + /** - * Optionally closing the device. + * Optionally closing the device if handle is not null. *

      * The default implementation is a NOP, just setting the handle to null. *

      - * The specific implementing, ie {@link com.jogamp.nativewindow.x11.X11GraphicsDevice}, - * shall have a enable/disable like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice#setCloseDisplay(boolean, boolean)},
      - * which shall be invoked at creation time to determine ownership/role of freeing the resource.
      + *

      + * Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice} + * or {@link com.jogamp.nativewindow.egl.EGLGraphicsDevice} + * issue the native close operation or skip it depending on the handles's ownership. + *

      * - * @return true if the handle was not null, otherwise false. + * @return true if the handle was not null and closing was successful, otherwise false. */ public boolean close(); } diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java index 187959a67..583fde07f 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java @@ -97,22 +97,27 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice } } + @Override public final String getType() { return type; } + @Override public final String getConnection() { return connection; } + @Override public final int getUnitID() { return unitID; } + @Override public final String getUniqueID() { return uniqueID; } + @Override public final long getHandle() { return handle; } @@ -124,6 +129,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long) * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, javax.media.nativewindow.ToolkitLock) */ + @Override public final void lock() { toolkitLock.lock(); } @@ -135,10 +141,17 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long) * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, javax.media.nativewindow.ToolkitLock) */ + @Override public final void unlock() { toolkitLock.unlock(); } + + @Override + public boolean open() { + return false; + } + @Override public boolean close() { if(0 != handle) { handle = 0; diff --git a/src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java b/src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java new file mode 100644 index 000000000..ff53c8109 --- /dev/null +++ b/src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java @@ -0,0 +1,44 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package javax.media.nativewindow; + +/** + * Provides a {@link NativeSurface} with a mutable surfaceHandle + * via {@link #setSurfaceHandle(long)}. + * + * @see NativeSurface + */ +public interface MutableSurface extends NativeSurface { + + /** + * Sets the surface handle which is created outside of this implementation. + */ + public void setSurfaceHandle(long surfaceHandle); +} + diff --git a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java index 1dabc3dcd..7fc9789c2 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java @@ -28,38 +28,108 @@ package javax.media.nativewindow; - import jogamp.nativewindow.Debug; import jogamp.nativewindow.SurfaceUpdatedHelper; import com.jogamp.common.util.locks.LockFactory; import com.jogamp.common.util.locks.RecursiveLock; -public abstract class ProxySurface implements NativeSurface { +public abstract class ProxySurface implements NativeSurface, MutableSurface { public static final boolean DEBUG = Debug.debug("ProxySurface"); + + /** + * Implementation specific bitvalue stating the upstream's {@link AbstractGraphicsDevice} is owned by this {@link ProxySurface}. + * @see #setImplBitfield(int) + * @see #getImplBitfield() + */ + public static final int OWN_DEVICE = 1 << 7; + + /** + * Implementation specific bitvalue stating the upstream's {@link NativeSurface} is an invisible window, i.e. maybe incomplete. + * @see #setImplBitfield(int) + * @see #getImplBitfield() + */ + public static final int INVISIBLE_WINDOW = 1 << 8; - private SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper(); - private AbstractGraphicsConfiguration config; // control access due to delegation - protected RecursiveLock surfaceLock = LockFactory.createRecursiveLock(); + /** Interface allowing upstream caller to pass lifecycle actions and size info to a {@link ProxySurface} instance. */ + public interface UpstreamSurfaceHook { + /** called within {@link ProxySurface#createNotify()} within lock, before using surface. */ + public void create(ProxySurface s); + /** called within {@link ProxySurface#destroyNotify()} within lock, before clearing fields. */ + public void destroy(ProxySurface s); + + /** Returns the width of the upstream surface */ + public int getWidth(ProxySurface s); + /** Returns the height of the upstream surface */ + public int getHeight(ProxySurface s); + } + + private final SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper(); + private final AbstractGraphicsConfiguration config; // control access due to delegation + private final UpstreamSurfaceHook upstream; + public final int initialWidth; + public final int initialHeight; private long surfaceHandle_old; + protected RecursiveLock surfaceLock = LockFactory.createRecursiveLock(); protected long displayHandle; - protected int height; protected int scrnIndex; - protected int width; + protected int implBitfield; - public ProxySurface(AbstractGraphicsConfiguration cfg) { - invalidate(); - config = cfg; - displayHandle=cfg.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle(); - surfaceHandle_old = 0; + /** + * @param cfg the {@link AbstractGraphicsConfiguration} to be used + * @param initialWidth the initial width + * @param initialHeight the initial height + */ + protected ProxySurface(AbstractGraphicsConfiguration cfg, int initialWidth, int initialHeight, UpstreamSurfaceHook upstream) { + if(null == cfg) { + throw new IllegalArgumentException("null config"); + } + this.config = cfg; + this.upstream = upstream; + this.initialWidth = initialWidth; + this.initialHeight = initialHeight; + this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle(); + this.surfaceHandle_old = 0; + this.implBitfield = 0; } - void invalidate() { - displayHandle = 0; - invalidateImpl(); + public final UpstreamSurfaceHook getUpstreamSurfaceHook() { return upstream; } + + /** + * If a valid {@link UpstreamSurfaceHook} instance is passed in the + * {@link ProxySurface#ProxySurface(AbstractGraphicsConfiguration, int, int, UpstreamSurfaceHook) constructor}, + * {@link UpstreamSurfaceHook#create(ProxySurface)} is being issued and the proxy surface/window handles shall be set. + */ + public void createNotify() { + if(null != upstream) { + upstream.create(this); + } + this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle(); + this.surfaceHandle_old = 0; } - protected abstract void invalidateImpl(); - + + /** + * If a valid {@link UpstreamSurfaceHook} instance is passed in the + * {@link ProxySurface#ProxySurface(AbstractGraphicsConfiguration, int, int, UpstreamSurfaceHook) constructor}, + * {@link UpstreamSurfaceHook#destroy(ProxySurface)} is being issued and all fields are cleared. + */ + public void destroyNotify() { + if(null != upstream) { + upstream.destroy(this); + invalidateImpl(); + } + this.displayHandle = 0; + this.surfaceHandle_old = 0; + } + + /** + * Must be overridden by implementations allowing having a {@link UpstreamSurfaceHook} being passed. + * @see #destroyNotify() + */ + protected void invalidateImpl() { + throw new InternalError("UpstreamSurfaceHook given, but required method not implemented."); + } + @Override public final long getDisplayHandle() { return displayHandle; @@ -82,19 +152,23 @@ public abstract class ProxySurface implements NativeSurface { @Override public abstract long getSurfaceHandle(); + @Override + public abstract void setSurfaceHandle(long surfaceHandle); + @Override public final int getWidth() { - return width; + if(null != upstream) { + return upstream.getWidth(this); + } + return initialWidth; } @Override public final int getHeight() { - return height; - } - - public void surfaceSizeChanged(int width, int height) { - this.width = width; - this.height = height; + if(null != upstream) { + return upstream.getHeight(this); + } + return initialHeight; } @Override @@ -187,7 +261,10 @@ public abstract class ProxySurface implements NativeSurface { public final Thread getSurfaceLockOwner() { return surfaceLock.getOwner(); } - + @Override public abstract String toString(); + + public int getImplBitfield() { return implBitfield; } + public void setImplBitfield(int v) { implBitfield=v; } } diff --git a/src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java b/src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java deleted file mode 100644 index 956e68e61..000000000 --- a/src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - * You acknowledge that this software is not designed or intended for use - * in the design, construction, operation or maintenance of any nuclear - * facility. - * - * Sun gratefully acknowledges that this software was originally authored - * and developed by Kenneth Bradley Russell and Christopher John Kline. - */ - -package javax.media.nativewindow; - -public interface SurfaceChangeable { - - /** Sets the surface handle which is created outside of this implementation */ - public void setSurfaceHandle(long surfaceHandle); - - /** - * The surface's size has been determined or changed. - * Implementation shall update the stored surface size with the given ones. - */ - public void surfaceSizeChanged(int width, int height); - -} - diff --git a/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java b/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java index 4877d5c4f..4f68c6945 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java +++ b/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java @@ -34,8 +34,8 @@ import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.SurfaceUpdatedListener; public class SurfaceUpdatedHelper implements SurfaceUpdatedListener { - private Object surfaceUpdatedListenersLock = new Object(); - private ArrayList surfaceUpdatedListeners = new ArrayList(); + private final Object surfaceUpdatedListenersLock = new Object(); + private final ArrayList surfaceUpdatedListeners = new ArrayList(); // // Management Utils diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java index 42fd08df1..e81d61e0f 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java +++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java @@ -48,7 +48,7 @@ import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.Capabilities; import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.NativeWindowException; -import javax.media.nativewindow.SurfaceChangeable; +import javax.media.nativewindow.MutableSurface; import javax.media.nativewindow.util.Point; import com.jogamp.nativewindow.MutableGraphicsConfiguration; @@ -62,7 +62,7 @@ import jogamp.nativewindow.jawt.JAWT_DrawingSurfaceInfo; import jogamp.nativewindow.jawt.macosx.JAWT_MacOSXDrawingSurfaceInfo; import jogamp.nativewindow.macosx.OSXUtil; -public class MacOSXJAWTWindow extends JAWTWindow implements SurfaceChangeable { +public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface { public MacOSXJAWTWindow(Object comp, AbstractGraphicsConfiguration config) { super(comp, config); if(DEBUG) { @@ -103,24 +103,9 @@ public class MacOSXJAWTWindow extends JAWTWindow implements SurfaceChangeable { if(DEBUG) { System.err.println("MacOSXJAWTWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle)); } - sscSet &= 0 != surfaceHandle; // reset ssc flag if NULL surfaceHandle, ie. back to JAWT this.surfaceHandle = surfaceHandle; } - public void surfaceSizeChanged(int width, int height) { - sscSet = true; - sscWidth = width; - sscHeight = height; - } - - public int getWidth() { - return sscSet ? sscWidth : super.getWidth(); - } - - public int getHeight() { - return sscSet ? sscHeight: super.getHeight(); - } - protected JAWT fetchJAWTImpl() throws NativeWindowException { // use offscreen if supported and [ applet or requested ] return JAWTUtil.getJAWT(getShallUseOffscreenLayer() || isApplet()); @@ -280,8 +265,6 @@ public class MacOSXJAWTWindow extends JAWTWindow implements SurfaceChangeable { private long rootSurfaceLayerHandle = 0; // attached to the JAWT_SurfaceLayer private long surfaceHandle = 0; - private int sscWidth, sscHeight; - private boolean sscSet = false; // Workaround for instance of 4796548 private boolean firstLock = true; diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java index 4d472b01a..99fc9244e 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java +++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java @@ -63,19 +63,15 @@ public class OSXUtil { return (Point) GetLocationOnScreen0(windowOrView, src_x, src_y); } - public static long CreateNSView(int x, int y, int width, int height) { - return CreateNSView0(x, y, width, height); - } - public static void DestroyNSView(long nsView) { - DestroyNSView0(nsView); - } - public static long CreateNSWindow(int x, int y, int width, int height) { return CreateNSWindow0(x, y, width, height); } public static void DestroyNSWindow(long nsWindow) { DestroyNSWindow0(nsWindow); } + public static long GetNSView(long nsWindow) { + return GetNSView0(nsWindow); + } public static long CreateCALayer(int x, int y, int width, int height) { return CreateCALayer0(x, y, width, height); @@ -134,10 +130,9 @@ public class OSXUtil { private static native boolean initIDs0(); private static native Object GetLocationOnScreen0(long windowOrView, int src_x, int src_y); - private static native long CreateNSView0(int x, int y, int width, int height); - private static native void DestroyNSView0(long nsView); private static native long CreateNSWindow0(int x, int y, int width, int height); private static native void DestroyNSWindow0(long nsWindow); + private static native long GetNSView0(long nsWindow); private static native long CreateCALayer0(int x, int y, int width, int height); private static native void AddCASublayer0(long rootCALayer, long subCALayer); private static native void RemoveCASublayer0(long rootCALayer, long subCALayer); diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java index c24f64b32..e368aa6a1 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java +++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java @@ -31,6 +31,7 @@ package jogamp.nativewindow.windows; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; /** @@ -43,22 +44,49 @@ public class GDISurface extends ProxySurface { protected long windowHandle; protected long surfaceHandle; - public GDISurface(AbstractGraphicsConfiguration cfg, long windowHandle) { - super(cfg); - if(0 == windowHandle) { - throw new NativeWindowException("Error hwnd 0, werr: "+GDI.GetLastError()); - } + public GDISurface(AbstractGraphicsConfiguration cfg, long windowHandle, int initialWidth, int initialHeight, UpstreamSurfaceHook upstream) { + super(cfg, initialWidth, initialHeight, upstream); this.windowHandle=windowHandle; + this.surfaceHandle=0; } @Override - protected final void invalidateImpl() { - windowHandle=0; - surfaceHandle=0; + protected void invalidateImpl() { + if(0 != surfaceHandle) { + throw new NativeWindowException("didn't release surface Handle: "+this); + } + windowHandle = 0; + // surfaceHandle = 0; + } + + /** + * {@inheritDoc} + *

      + * Actually the window handle (HWND), since the surfaceHandle (HDC) is derived + * from it at {@link #lockSurface()}. + *

      + */ + @Override + public final void setSurfaceHandle(long surfaceHandle) { + this.windowHandle = surfaceHandle; + } + + /** + * Sets the window handle (HWND). + */ + public final void setWindowHandle(long windowHandle) { + this.windowHandle = windowHandle; + } + + public final long getWindowHandle() { + return windowHandle; } @Override final protected int lockSurfaceImpl() { + if (0 == windowHandle) { + throw new NativeWindowException("null window handle: "+this); + } if (0 != surfaceHandle) { throw new InternalError("surface not released"); } @@ -89,12 +117,15 @@ public class GDISurface extends ProxySurface { @Override final public String toString() { - return "GDISurface[config "+getPrivateGraphicsConfiguration()+ + final UpstreamSurfaceHook ush = getUpstreamSurfaceHook(); + final String ush_s = null != ush ? ( ush.getClass().getName() + ": " + ush ) : "nil"; + return getClass().getSimpleName()+"[config "+getPrivateGraphicsConfiguration()+ ", displayHandle 0x"+Long.toHexString(getDisplayHandle())+ ", windowHandle 0x"+Long.toHexString(windowHandle)+ ", surfaceHandle 0x"+Long.toHexString(getSurfaceHandle())+ ", size "+getWidth()+"x"+getHeight()+ - ", surfaceLock "+surfaceLock+"]"; + ", surfaceLock "+surfaceLock+ + ", upstreamSurfaceHook "+ush_s+"]"; } } diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m index e010fc440..ebfefe345 100644 --- a/src/nativewindow/native/macosx/OSXmisc.m +++ b/src/nativewindow/native/macosx/OSXmisc.m @@ -148,37 +148,6 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetLocationOnS return res; } -/* - * Class: Java_jogamp_nativewindow_macosx_OSXUtil - * Method: CreateNSView0 - * Signature: (IIIIZ)J - */ -JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateNSView0 - (JNIEnv *env, jclass unused, jint x, jint y, jint width, jint height) -{ - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSRect rect = NSMakeRect(x, y, width, height); - NSView * view = [[NSView alloc] initWithFrame: rect] ; - [view setCanDrawConcurrently: YES]; - [pool release]; - - return (jlong) (intptr_t) view; -} - -/* - * Class: Java_jogamp_nativewindow_macosx_OSXUtil - * Method: DestroyNSView0 - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyNSView0 - (JNIEnv *env, jclass unused, jlong nsView) -{ - NSView* view = (NSView*) (intptr_t) nsView; - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [view release]; - [pool release]; -} - /* * Class: Java_jogamp_nativewindow_macosx_OSXUtil * Method: CreateNSWindow0 @@ -222,6 +191,27 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyNSWindow0 [pool release]; } +/* + * Class: Java_jogamp_nativewindow_macosx_OSXUtil + * Method: GetNSView0 + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetNSView0 + (JNIEnv *env, jclass unused, jlong window) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + + DBG_PRINT( "contentView0 - window: %p (START)\n", win); + + jlong res = (jlong) ((intptr_t) [win contentView]); + + DBG_PRINT( "contentView0 - window: %p (END)\n", win); + + [pool release]; + return res; +} + /* * Class: Java_jogamp_nativewindow_macosx_OSXUtil * Method: CreateCALayer0 diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index 71e86d520..e8537fec5 100644 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -40,8 +40,20 @@ import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.WindowClosingProtocol; /** - * Specifying the public Window functionality for the - * using a Window and for shadowing one like {@link com.jogamp.newt.opengl.GLWindow}. + * Specifying NEWT's Window functionality: + *
        + *
      • On- and offscreen windows
      • + *
      • Keyboard and multi-pointer input
      • + *
      • Native reparenting
      • + *
      • Toggable fullscreen and decoration mode
      • + *
      • Transparency
      • + *
      • ... and more
      • + *
      + *

      + * One use case is {@link com.jogamp.newt.opengl.GLWindow}, which delegates + * window operation to an instance of this interface while providing OpenGL + * functionality. + *

      */ public interface Window extends NativeWindow, WindowClosingProtocol { public static final boolean DEBUG_MOUSE_EVENT = Debug.debug("Window.MouseEvent"); diff --git a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java index 44fcea49c..4db661eeb 100644 --- a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java +++ b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java @@ -43,7 +43,7 @@ public class KeyEvent extends InputEvent this.keyChar=keyChar; } - /** Only valid if delivered via {@link KeyListener#keyPressed(KeyEvent)} */ + /** Only valid on all platforms at {@link KeyListener#keyTyped(KeyEvent)} */ public char getKeyChar() { return keyChar; } diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index f08fbc8fa..c50ab77c4 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -124,6 +124,11 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind this.window.setLifecycleHook(new GLLifecycleHook()); } + @Override + public final Object getUpstreamWidget() { + return window; + } + /** * Creates a new GLWindow attaching a new Window referencing a * new default Screen and default Display with the given GLCapabilities. @@ -762,7 +767,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind System.err.println(GlueGenVersion.getInstance()); System.err.println(JoglVersion.getInstance()); - System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true).toString()); + System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString()); final GLProfile glp = GLProfile.getDefault(); final GLCapabilitiesImmutable caps = new GLCapabilities( glp ); diff --git a/src/newt/classes/jogamp/newt/OffscreenWindow.java b/src/newt/classes/jogamp/newt/OffscreenWindow.java index 050e24b6c..be543aba9 100644 --- a/src/newt/classes/jogamp/newt/OffscreenWindow.java +++ b/src/newt/classes/jogamp/newt/OffscreenWindow.java @@ -34,15 +34,24 @@ package jogamp.newt; -import javax.media.nativewindow.*; +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.GraphicsConfigurationFactory; +import javax.media.nativewindow.MutableSurface; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.ProxySurface; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.Point; -public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { +public class OffscreenWindow extends WindowImpl implements MutableSurface { long surfaceHandle = 0; - + ProxySurface.UpstreamSurfaceHook upstreamHook; + ProxySurface dummySurface; + public OffscreenWindow() { + upstreamHook = null; + dummySurface = null; } static long nextWindowHandle = 0x100; // start here - a marker @@ -52,6 +61,17 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { throw new NativeWindowException("Capabilities is onscreen"); } final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen(); + /** Cannot use OpenGL here .. + if(capsRequested instanceof GLCapabilitiesImmutable) { + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) capsRequested; + if(caps.isFBO() && GLContext.isFBOAvailable(aScreen.getDevice(), caps.getGLProfile()) ) { + final GLDrawableFactoryImpl factory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLCapabilitiesImmutable dummyCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(caps); + final ProxySurface dummySurface = factory.createDummySurfaceImpl(aScreen.getDevice(), false, dummyCaps, null, 64, 64); + upstreamHook = dummySurface.getUpstreamSurfaceHook(); + dummySurface.createNotify(); + } + } */ final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aScreen.getDevice()).chooseGraphicsConfiguration( capsRequested, capsRequested, capabilitiesChooser, aScreen); if (null == cfg) { @@ -68,13 +88,14 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { // nop } - public void surfaceSizeChanged(int width, int height) { - sizeChanged(false, width, height, false); - } - @Override public synchronized void destroy() { super.destroy(); + if(null != dummySurface) { + dummySurface.destroyNotify(); + dummySurface = null; + upstreamHook = null; + } surfaceHandle = 0; } @@ -84,8 +105,12 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { @Override public long getSurfaceHandle() { + if(null != dummySurface) { + return dummySurface.getSurfaceHandle(); + // return upstreamHook.getWidth(); + } return surfaceHandle; - } + } protected void requestFocusImpl(boolean reparented) { } diff --git a/src/newt/classes/jogamp/newt/driver/android/MD.java b/src/newt/classes/jogamp/newt/driver/android/MD.java index 403eae383..f2f30937b 100644 --- a/src/newt/classes/jogamp/newt/driver/android/MD.java +++ b/src/newt/classes/jogamp/newt/driver/android/MD.java @@ -43,7 +43,7 @@ public class MD { .append(JoglVersion.getInstance()).append(Platform.NEWLINE) .append(Platform.NEWLINE); - JoglVersion.getDefaultOpenGLInfo(sb, true); + JoglVersion.getDefaultOpenGLInfo(null, sb, true); return sb.toString(); } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java index 942994c13..fcca5c843 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java @@ -38,7 +38,7 @@ import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.NativeWindowException; -import javax.media.nativewindow.SurfaceChangeable; +import javax.media.nativewindow.MutableSurface; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.InsetsImmutable; import javax.media.nativewindow.util.Point; @@ -50,7 +50,7 @@ import jogamp.newt.driver.DriverUpdatePosition; import com.jogamp.newt.event.KeyEvent; -public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverClearFocus, DriverUpdatePosition { +public class MacWindow extends WindowImpl implements MutableSurface, DriverClearFocus, DriverUpdatePosition { static { MacDisplay.initSingleton(); @@ -131,10 +131,6 @@ public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverCl } } - public void surfaceSizeChanged(int width, int height) { - sizeChanged(false, width, height, false); - } - @Override protected void setTitleImpl(final String title) { setTitle0(getWindowHandle(), title); diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index f914467af..b58b99e38 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -972,7 +972,7 @@ static jint mods2JavaMods(NSUInteger mods) NSView* nsview = [self contentView]; if( ! [nsview isMemberOfClass:[NewtView class]] ) { - return; + return NO; } NewtView* view = (NewtView *) nsview; @@ -981,14 +981,14 @@ static jint mods2JavaMods(NSUInteger mods) DBG_PRINT( "*************** windowWillClose.0: %p\n", (void *)(intptr_t)javaWindowObject); if (javaWindowObject == NULL) { DBG_PRINT("windowWillClose: null javaWindowObject\n"); - return; + return NO; } int shallBeDetached = 0; JavaVM *jvmHandle = [view getJVMHandle]; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); if(NULL==env) { DBG_PRINT("windowWillClose: null JNIEnv\n"); - return; + return NO; } [view setDestroyNotifySent: true]; // earmark assumption of being closed diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java index a09cc76ac..b22be0a93 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java @@ -194,7 +194,7 @@ public class TestTextRendererNEWT00 extends UITestCase { pw.printf("%s-%03dx%03d-T%04d", objName, drawable.getWidth(), drawable.getHeight(), texSize[0]); final String filename = dir + sw +".png"; - if(screenshot.readPixels(drawable.getGL(), drawable, false)) { + if(screenshot.readPixels(drawable.getGL(), false)) { screenshot.write(new File(filename)); } } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java index a3182a30f..6378c1ee3 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java @@ -194,7 +194,7 @@ public abstract class GPURendererListenerBase01 implements GLEventListener { pw.printf("-%03dx%03d-Z%04d-T%04d-%s", drawable.getWidth(), drawable.getHeight(), (int)Math.abs(zoom), texSize[0], objName); final String filename = dir + tech + sw +".png"; - if(screenshot.readPixels(drawable.getGL(), drawable, false)) { + if(screenshot.readPixels(drawable.getGL(), false)) { screenshot.write(new File(filename)); } } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java index d0093ad0c..15daf70cd 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java @@ -180,7 +180,7 @@ public abstract class UIListenerBase01 implements GLEventListener { pw.printf("-%03dx%03d-Z%04d-T%04d-%s", drawable.getWidth(), drawable.getHeight(), (int)Math.abs(zoom), 0, objName); final String filename = dir + tech + sw +".png"; - if(screenshot.readPixels(drawable.getGL(), drawable, false)) { + if(screenshot.readPixels(drawable.getGL(), false)) { screenshot.write(new File(filename)); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java new file mode 100644 index 000000000..1a33845b3 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java @@ -0,0 +1,272 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.io.IOException; + +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import jogamp.opengl.GLFBODrawableImpl; + +import org.junit.Assert; +import org.junit.Test; + +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.OffscreenAutoDrawable; +import com.jogamp.opengl.test.junit.jogl.demos.es2.FBOMix2DemosES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; + +public class TestFBODrawableNEWT extends UITestCase { + + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + @Test + public void testGL2ES2_Demo1Normal() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } + + @Test + public void testGL2ES2_Demo1MSAA4() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } + + @Test + public void testGL2ES2_Demo2Normal() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + testGLFBODrawableImpl(caps, new MultisampleDemoES2(false)); + } + + @Test + public void testGL2ES2_Demo2MSAA4() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, new MultisampleDemoES2(true)); + } + + @Test + public void testGL2ES2_FBODemoNormal() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0); + demo.setDoRotation(false); + final GLCapabilities caps = new GLCapabilities(glp); + testGLFBODrawableImpl(caps, demo); + } + + @Test + public void testGL2ES2_FBODemoMSAA4() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0); + demo.setDoRotation(false); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, demo); + } + + @Test + public void testEGLES2_Demo0Normal() throws InterruptedException { + if( GLProfile.isAvailable(GLProfile.GLES2) ) { + final GLProfile glp = GLProfile.get(GLProfile.GLES2); + final GLCapabilities caps = new GLCapabilities(glp); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } else { + System.err.println("EGL ES2 n/a"); + } + } + + @Test + public void testEGLES2_Demo0MSAA4() throws InterruptedException { + if( GLProfile.isAvailable(GLProfile.GLES2) ) { + final GLProfile glp = GLProfile.get(GLProfile.GLES2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } else { + System.err.println("EGL ES2 n/a"); + } + } + + boolean skipShot = false; + + void testGLFBODrawableImpl(GLCapabilities caps, GLEventListener demo) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); + caps.setFBO(true); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLDrawable fboDrawable = factory.createOffscreenDrawable(null, caps, null, widthStep*szStep, heightStep*szStep); + Assert.assertNotNull(fboDrawable); + Assert.assertTrue("Not an FBO Drawable", fboDrawable instanceof GLFBODrawableImpl); + + fboDrawable.setRealized(true); + Assert.assertTrue(fboDrawable.isRealized()); + + final FBObject fbo = ((GLFBODrawableImpl)fboDrawable).getFBObject(); + + System.out.println("Realized: "+fboDrawable); + System.out.println("Realized: "+fboDrawable.getChosenGLCapabilities()); + System.out.println("Realized: "+fbo); + + final GLContext context = fboDrawable.createContext(null); + Assert.assertNotNull(context); + + int res = context.makeCurrent(); + Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); + context.release(); + + System.out.println("Post Create-Ctx: "+fbo); + final FBObject.Colorbuffer colorA = fbo.getColorbuffer(0); + Assert.assertNotNull(colorA); + final FBObject.RenderAttachment depthA = fbo.getDepthAttachment(); + Assert.assertNotNull(depthA); + + final OffscreenAutoDrawable glad = new OffscreenAutoDrawable(fboDrawable, context, null); + + glad.addGLEventListener(demo); + glad.addGLEventListener(new GLEventListener() { + volatile int displayCount=0; + volatile int reshapeCount=0; + public void init(GLAutoDrawable drawable) {} + public void dispose(GLAutoDrawable drawable) {} + public void display(GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + // System.err.println(Thread.currentThread().getName()+": ** display: "+displayCount+": step "+szStep+" "+drawable.getWidth()+"x"+drawable.getHeight()); + // System.err.println(Thread.currentThread().getName()+": ** FBO-THIS: "+fbo); + // System.err.println(Thread.currentThread().getName()+": ** FBO-SINK: "+fbo.getSamplingSinkFBO()); + // System.err.println(Thread.currentThread().getName()+": ** drawable-read: "+gl.getDefaultReadFramebuffer()); + if(skipShot) { + skipShot=false; + } else { + snapshot(getSimpleTestName("."), displayCount, "msaa"+fbo.getNumSamples(), gl, screenshot, TextureIO.PNG, null); + } + Assert.assertEquals(drawable.getWidth(), widthStep*szStep); + Assert.assertEquals(drawable.getHeight(), heightStep*szStep); + displayCount++; + } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + System.err.println(Thread.currentThread().getName()+": ** reshape: "+reshapeCount+": step "+szStep+" "+width+"x"+height+" - "+drawable.getWidth()+"x"+drawable.getHeight()); + Assert.assertEquals(drawable.getWidth(), widthStep*szStep); + Assert.assertEquals(drawable.getHeight(), heightStep*szStep); + reshapeCount++; + } + }); + + // 0 - szStep = 2 + glad.display(); + + // 1, 2 (resize + display) + szStep = 1; + skipShot=true; + glad.setSize(widthStep*szStep, heightStep*szStep); + glad.display(); + Assert.assertEquals(glad.getWidth(), widthStep*szStep); + Assert.assertEquals(glad.getHeight(), heightStep*szStep); + { + // Check whether the attachment reference are still valid! + FBObject.Colorbuffer _colorA = fbo.getColorbuffer(0); + Assert.assertNotNull(_colorA); + Assert.assertTrue(colorA == _colorA); + Assert.assertTrue(colorA.equals(_colorA)); + FBObject.RenderAttachment _depthA = fbo.getDepthAttachment(); + Assert.assertNotNull(_depthA); + Assert.assertTrue(depthA == _depthA); + Assert.assertTrue(depthA.equals(_depthA)); + + _colorA = fbo.getColorbuffer(colorA); + Assert.assertNotNull(_colorA); + Assert.assertTrue(colorA == _colorA); + Assert.assertTrue(colorA.equals(_colorA)); + } + + // 3, 4 (resize + display) + szStep = 4; + skipShot=true; + glad.setSize(widthStep*szStep, heightStep*szStep); + glad.display(); + Assert.assertEquals(glad.getWidth(), widthStep*szStep); + Assert.assertEquals(glad.getHeight(), heightStep*szStep); + { + // Check whether the attachment reference are still valid! + FBObject.Colorbuffer _colorA = fbo.getColorbuffer(0); + Assert.assertNotNull(_colorA); + Assert.assertTrue(colorA == _colorA); + final FBObject.RenderAttachment _depthA = fbo.getDepthAttachment(); + Assert.assertNotNull(_depthA); + Assert.assertTrue(depthA == _depthA); + + _colorA = fbo.getColorbuffer(colorA); + Assert.assertNotNull(_colorA); + Assert.assertTrue(colorA == _colorA); + } + + // 5 + glad.display(); + Assert.assertEquals(glad.getWidth(), widthStep*szStep); + Assert.assertEquals(glad.getHeight(), heightStep*szStep); + + // 6, 7 (resize + display) + szStep = 3; + skipShot=true; + glad.setSize(widthStep*szStep, heightStep*szStep); + glad.display(); + Assert.assertEquals(glad.getWidth(), widthStep*szStep); + Assert.assertEquals(glad.getHeight(), heightStep*szStep); + + glad.destroy(); + System.out.println("Fin: "+fboDrawable); + + // final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(fboDrawable, context); + } + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestFBODrawableNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java new file mode 100644 index 000000000..f7c83a03b --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java @@ -0,0 +1,266 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.test.junit.jogl.acore; + +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.FBObject.TextureAttachment; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; +import com.jogamp.opengl.util.texture.TextureIO; +import com.jogamp.opengl.FBObject.Attachment.Type; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NEWTGLContext; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import java.io.IOException; + +import javax.media.nativewindow.NativeSurface; +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GL2GL3; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLPipelineFactory; +import javax.media.opengl.GLProfile; +import javax.media.opengl.GLUniformData; + +import org.junit.Assert; +import org.junit.Test; + +public class TestFBOMRTNEWT01 extends UITestCase { + static long durationPerTest = 10*40*2; // ms + + @Test + public void test01() throws InterruptedException { + final int step = 4; + final int width = 800; + final int height = 600; + // preset .. + if(!GLProfile.isAvailable(GLProfile.GL2GL3)) { + System.err.println("Test requires GL2/GL3 profile."); + return; + } + final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOnscreenWindow( + new GLCapabilities(GLProfile.getGL2GL3()), width/step, height/step, true); + final GLDrawable drawable = winctx.context.getGLDrawable(); + GL2GL3 gl = winctx.context.getGL().getGL2GL3(); + gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, gl, null) ).getGL2GL3(); + System.err.println(winctx.context); + + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + // test code .. + final ShaderState st = new ShaderState(); + // st.setVerbose(true); + + final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader", + "shader/bin", "fbo-mrt-1", false); + final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader", + "shader/bin", "fbo-mrt-1", false); + final ShaderProgram sp0 = new ShaderProgram(); + sp0.add(gl, vp0, System.err); + sp0.add(gl, fp0, System.err); + Assert.assertTrue(0<=sp0.program()); + Assert.assertTrue(!sp0.inUse()); + Assert.assertTrue(!sp0.linked()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + st.attachShaderProgram(gl, sp0, false); + + final ShaderCode vp1 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader", + "shader/bin", "fbo-mrt-2", false); + final ShaderCode fp1 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader", + "shader/bin", "fbo-mrt-2", false); + final ShaderProgram sp1 = new ShaderProgram(); + sp1.add(gl, vp1, System.err); + sp1.add(gl, fp1, System.err); + Assert.assertTrue(0<=sp1.program()); + Assert.assertTrue(!sp1.inUse()); + Assert.assertTrue(!sp1.linked()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + st.attachShaderProgram(gl, sp1, true); + + final PMVMatrix pmvMatrix = new PMVMatrix(); + final GLUniformData pmvMatrixUniform = new GLUniformData("gcu_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + st.ownUniform(pmvMatrixUniform); + st.uniform(gl, pmvMatrixUniform); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + final GLArrayDataServer vertices0 = GLArrayDataServer.createGLSL("gca_Vertices", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + // st.bindAttribLocation(gl, 0, vertices0); + vertices0.putf(0); vertices0.putf(1); vertices0.putf(0); + vertices0.putf(1); vertices0.putf(1); vertices0.putf(0); + vertices0.putf(0); vertices0.putf(0); vertices0.putf(0); + vertices0.putf(1); vertices0.putf(0); vertices0.putf(0); + vertices0.seal(gl, true); + st.ownAttribute(vertices0, true); + vertices0.enableBuffer(gl, false); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + final GLArrayDataServer colors0 = GLArrayDataServer.createGLSL("gca_Colors", 4, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + // st.bindAttribLocation(gl, 1, colors0); + colors0.putf(1); colors0.putf(0); colors0.putf(1); colors0.putf(1); + colors0.putf(0); colors0.putf(0); colors0.putf(1); colors0.putf(1); + colors0.putf(0); colors0.putf(0); colors0.putf(0); colors0.putf(1); + colors0.putf(0); colors0.putf(1); colors0.putf(1); colors0.putf(1); + colors0.seal(gl, true); + st.ownAttribute(colors0, true); + colors0.enableBuffer(gl, false); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + final GLUniformData texUnit0 = new GLUniformData("gcs_TexUnit0", 0); + st.ownUniform(texUnit0); + st.uniform(gl, texUnit0); + final GLUniformData texUnit1 = new GLUniformData("gcs_TexUnit1", 1); + st.ownUniform(texUnit1); + st.uniform(gl, texUnit1); + + final GLArrayDataServer texCoords0 = GLArrayDataServer.createGLSL("gca_TexCoords", 2, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + // st.bindAttribLocation(gl, 2, texCoords0); + texCoords0.putf(0f); texCoords0.putf(1f); + texCoords0.putf(1f); texCoords0.putf(1f); + texCoords0.putf(0f); texCoords0.putf(0f); + texCoords0.putf(1f); texCoords0.putf(0f); + texCoords0.seal(gl, true); + st.ownAttribute(texCoords0, true); + texCoords0.enableBuffer(gl, false); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + final int texA0Point = 0; // attachment point for texA0 + final int texA1Point = 1; // attachment point for texA1 + + // FBO w/ 2 texture2D color buffers + final FBObject fbo_mrt = new FBObject(); + fbo_mrt.reset(gl, drawable.getWidth(), drawable.getHeight()); + final TextureAttachment texA0 = fbo_mrt.attachTexture2D(gl, texA0Point, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + final TextureAttachment texA1 = fbo_mrt.attachTexture2D(gl, texA1Point, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + fbo_mrt.attachRenderbuffer(gl, Type.DEPTH, 24); + Assert.assertTrue( fbo_mrt.isStatusValid() ) ; + fbo_mrt.unbind(gl); + + // misc GL setup + gl.glClearColor(1, 1, 1, 1); + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + // reshape + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glOrthof(0f, 1f, 0f, 1f, -10f, 10f); + pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + st.uniform(gl, pmvMatrixUniform); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + final int[] two_buffers = new int[] { GL.GL_COLOR_ATTACHMENT0+texA0Point, GL.GL_COLOR_ATTACHMENT0+texA1Point }; + final int[] bck_buffers = new int[] { GL2GL3.GL_BACK_LEFT }; + + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + int step_i = 0; + int[] last_snap_size = new int[] { 0, 0 }; + + for(int i=0; i buffer0, Green -> buffer1 + st.attachShaderProgram(gl, sp0, true); + vertices0.enableBuffer(gl, true); + colors0.enableBuffer(gl, true); + + fbo_mrt.bind(gl); + gl.glDrawBuffers(2, two_buffers, 0); + gl.glViewport(0, 0, fbo_mrt.getWidth(), fbo_mrt.getHeight()); + + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); + fbo_mrt.unbind(gl); + vertices0.enableBuffer(gl, false); + colors0.enableBuffer(gl, false); + + // pass 2 - mix buffer0, buffer1 and blue + // rg = buffer0.rg + buffer1.rg, b = Blue - length(rg); + st.attachShaderProgram(gl, sp1, true); + vertices0.enableBuffer(gl, true); + colors0.enableBuffer(gl, true); + texCoords0.enableBuffer(gl, true); + gl.glDrawBuffers(1, bck_buffers, 0); + + gl.glViewport(0, 0, drawable.getWidth(), drawable.getHeight()); + + gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit0.intValue()); + fbo_mrt.use(gl, texA0); + gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit1.intValue()); + fbo_mrt.use(gl, texA1); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); + fbo_mrt.unuse(gl); + vertices0.enableBuffer(gl, false); + colors0.enableBuffer(gl, false); + texCoords0.enableBuffer(gl, false); + + { + final NativeSurface ns = gl.getContext().getGLReadDrawable().getNativeSurface(); + if(last_snap_size[0] != ns.getWidth() && last_snap_size[1] != ns.getHeight()) { + gl.glFinish(); // sync .. no swap buffers yet! + snapshot(getSimpleTestName("."), step_i, null, gl, screenshot, TextureIO.PNG, null); // overwrite ok + last_snap_size[0] = ns.getWidth(); + last_snap_size[1] = ns.getHeight(); + } + } + + drawable.swapBuffers(); + Thread.sleep(50); + int j = (int) ( (long)i / (durationPerTest/(long)step) ) + 1; + if(j>step_i) { + int w = width/step * j; + int h = height/step * j; + System.err.println("resize: "+step_i+" -> "+j+" - "+w+"x"+h); + fbo_mrt.reset(gl, w, h); + winctx.window.setSize(w, h); + step_i = j; + } + } + + NEWTGLContext.destroyWindow(winctx); + } + + public static void main(String args[]) throws IOException { + System.err.println("main - start"); + for(int i=0; i "+num); + demo.setMSAA(num); + } + } + } + }); + + animator.start(); + // glWindow.setSkipContextReleaseThread(animator.getThread()); + + glWindow.setVisible(true); + + System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities()); + System.err.println("GL chosen: "+glWindow.getChosenCapabilities()); + System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); + + animator.setUpdateFPSFrames(60, showFPS ? System.err : null); + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()= 0; i--) { - immModeSink.glVertex3f((float) (radius * Math.cos(i * increment)), - (float) (radius * Math.sin(i * increment)), - 0f); - immModeSink.glVertex3f((float) (-1.0 * radius * Math.cos(i * increment)), - (float) (-1.0 * radius * Math.sin(i * increment)), - 0f); - } - immModeSink.glEnd(gl, false); - } - - public void dispose(GLAutoDrawable drawable) { - immModeSink.destroy(drawable.getGL()); - immModeSink = null; - } - - public void display(GLAutoDrawable drawable) { - GL2ES1 gl = drawable.getGL().getGL2ES1(); - if (multisample) { - gl.glEnable(GL.GL_MULTISAMPLE); - } - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - immModeSink.draw(gl, true); - if (multisample) { - gl.glDisable(GL.GL_MULTISAMPLE); - } - } - - // Unused routines - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { - } - - public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) { - } -} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java index 4b0caf898..478bd4543 100755 --- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java @@ -40,7 +40,6 @@ package com.jogamp.opengl.test.junit.jogl.caps; -import java.io.File; import java.lang.reflect.InvocationTargetException; import java.awt.BorderLayout; import java.awt.Frame; @@ -48,14 +47,15 @@ import java.awt.Frame; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; -import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import javax.media.opengl.awt.GLCanvas; +import com.jogamp.opengl.test.junit.jogl.demos.es1.MultisampleDemoES1; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; import org.junit.Test; @@ -75,13 +75,6 @@ public class TestMultisampleES1AWT extends UITestCase { org.junit.runner.JUnitCore.main(tstname); } - protected void snapshot(GLAutoDrawable drawable, boolean alpha, boolean flip, String filename) { - GLReadBufferUtil screenshot = new GLReadBufferUtil(alpha, false); - if(screenshot.readPixels(drawable.getGL(), drawable, flip)) { - screenshot.write(new File(filename)); - } - } - @Test public void testOnscreenMultiSampleAA0() throws InterruptedException, InvocationTargetException { testMultiSampleAAImpl(0); @@ -98,6 +91,7 @@ public class TestMultisampleES1AWT extends UITestCase { } private void testMultiSampleAAImpl(int reqSamples) throws InterruptedException, InvocationTargetException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); GLProfile glp = GLProfile.getMaxFixedFunc(true); GLCapabilities caps = new GLCapabilities(glp); GLCapabilitiesChooser chooser = new MultisampleChooser01(); @@ -110,14 +104,11 @@ public class TestMultisampleES1AWT extends UITestCase { canvas = new GLCanvas(caps, chooser, null, null); canvas.addGLEventListener(new MultisampleDemoES1(reqSamples>0?true:false)); canvas.addGLEventListener(new GLEventListener() { + int displayCount = 0; public void init(GLAutoDrawable drawable) {} public void dispose(GLAutoDrawable drawable) {} public void display(GLAutoDrawable drawable) { - final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities(); - final String pfmt = caps.getAlphaBits() > 0 ? "rgba" : "rgb_"; - final String aaext = caps.getSampleExtension(); - final int samples = caps.getSampleBuffers() ? caps.getNumSamples() : 0 ; - snapshot(drawable, false, false, getSimpleTestName(".")+"-F_rgb_-I_"+pfmt+"-S"+samples+"-"+aaext+"-"+drawable.getGLProfile().getName()+".png"); + snapshot(getSimpleTestName("."), displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null); } public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } }); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1NEWT.java index 2e47b6841..ed8e2bd85 100755 --- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1NEWT.java @@ -40,21 +40,20 @@ package com.jogamp.opengl.test.junit.jogl.caps; -import java.io.File; - import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; -import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import org.junit.Test; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es1.MultisampleDemoES1; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; public class TestMultisampleES1NEWT extends UITestCase { static long durationPerTest = 60; // ms @@ -71,13 +70,6 @@ public class TestMultisampleES1NEWT extends UITestCase { org.junit.runner.JUnitCore.main(tstname); } - protected void snapshot(GLAutoDrawable drawable, boolean alpha, boolean flip, String filename) { - GLReadBufferUtil screenshot = new GLReadBufferUtil(alpha, false); - if(screenshot.readPixels(drawable.getGL(), drawable, flip)) { - screenshot.write(new File(filename)); - } - } - @Test public void testOnscreenMultiSampleAA0() throws InterruptedException { testMultiSampleAAImpl(true, 0); @@ -119,6 +111,7 @@ public class TestMultisampleES1NEWT extends UITestCase { } private void testMultiSampleAAImpl(boolean onscreen, int reqSamples) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); GLProfile glp = GLProfile.getMaxFixedFunc(true); GLCapabilities caps = new GLCapabilities(glp); GLCapabilitiesChooser chooser = new MultisampleChooser01(); @@ -136,14 +129,11 @@ public class TestMultisampleES1NEWT extends UITestCase { window.setCapabilitiesChooser(chooser); window.addGLEventListener(new MultisampleDemoES1(reqSamples>0?true:false)); window.addGLEventListener(new GLEventListener() { + int displayCount = 0; public void init(GLAutoDrawable drawable) {} public void dispose(GLAutoDrawable drawable) {} public void display(GLAutoDrawable drawable) { - final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities(); - final String pfmt = caps.getAlphaBits() > 0 ? "rgba" : "rgb_"; - final String aaext = caps.getSampleExtension(); - final int samples = caps.getSampleBuffers() ? caps.getNumSamples() : 0 ; - snapshot(drawable, false, false, getSimpleTestName(".")+"-F_rgb_-I_"+pfmt+"-S"+samples+"-"+aaext+"-"+drawable.getGLProfile().getName()+".png"); + snapshot(getSimpleTestName("."), displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null); } public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } }); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES2NEWT.java new file mode 100644 index 000000000..b2dad1f39 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES2NEWT.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.test.junit.jogl.caps; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesChooser; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.Test; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; + +public class TestMultisampleES2NEWT extends UITestCase { + static long durationPerTest = 60; // ms + private GLWindow window; + + public static void main(String[] args) { + for(int i=0; i0) { + caps.setSampleBuffers(true); + caps.setNumSamples(reqSamples); + } + + window = GLWindow.create(caps); + window.setCapabilitiesChooser(chooser); + window.addGLEventListener(new MultisampleDemoES2(reqSamples>0?true:false)); + window.addGLEventListener(new GLEventListener() { + int displayCount = 0; + public void init(GLAutoDrawable drawable) {} + public void dispose(GLAutoDrawable drawable) {} + public void display(GLAutoDrawable drawable) { + snapshot(getSimpleTestName("."), displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + window.setSize(512, 512); + window.setVisible(true); + window.requestFocus(); + + Thread.sleep(durationPerTest); + + window.destroy(); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java index 5c82a43c6..e81d1b4af 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java @@ -129,12 +129,13 @@ public class GearsES1 implements GLEventListener { gl.glEnable(GL2ES1.GL_NORMALIZE); - if (drawable.getNativeSurface() instanceof Window) { - Window window = (Window) drawable.getNativeSurface(); + final Object upstreamWidget = drawable.getUpstreamWidget(); + if (upstreamWidget instanceof Window) { + final Window window = (Window) upstreamWidget; window.addMouseListener(gearsMouse); window.addKeyListener(gearsKeys); - } else if (GLProfile.isAWTAvailable() && drawable instanceof java.awt.Component) { - java.awt.Component comp = (java.awt.Component) drawable; + } else if (GLProfile.isAWTAvailable() && upstreamWidget instanceof java.awt.Component) { + final java.awt.Component comp = (java.awt.Component) upstreamWidget; new com.jogamp.newt.event.awt.AWTMouseAdapter(gearsMouse).addTo(comp); new com.jogamp.newt.event.awt.AWTKeyAdapter(gearsKeys).addTo(comp); } @@ -165,8 +166,9 @@ public class GearsES1 implements GLEventListener { public void dispose(GLAutoDrawable drawable) { System.err.println(Thread.currentThread()+" GearsES1.dispose ... "); - if (drawable.getNativeSurface() instanceof Window) { - Window window = (Window) drawable.getNativeSurface(); + final Object upstreamWidget = drawable.getUpstreamWidget(); + if (upstreamWidget instanceof Window) { + final Window window = (Window) upstreamWidget; window.removeMouseListener(gearsMouse); window.removeKeyListener(gearsKeys); } @@ -188,8 +190,9 @@ public class GearsES1 implements GLEventListener { GL2ES1 gl = drawable.getGL().getGL2ES1(); final boolean hasFocus; - if(drawable.getNativeSurface() instanceof NativeWindow) { - hasFocus = ((NativeWindow)drawable.getNativeSurface()).hasFocus(); + final Object upstreamWidget = drawable.getUpstreamWidget(); + if(upstreamWidget instanceof NativeWindow) { + hasFocus = ((NativeWindow)upstreamWidget).hasFocus(); } else { hasFocus = true; } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/MultisampleDemoES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/MultisampleDemoES1.java new file mode 100644 index 000000000..aad56581b --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/MultisampleDemoES1.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.test.junit.jogl.demos.es1; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES1; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; + +import com.jogamp.opengl.util.ImmModeSink; + +public class MultisampleDemoES1 implements GLEventListener { + + boolean multisample; + ImmModeSink immModeSink; + + public MultisampleDemoES1(boolean multisample) { + this.multisample = multisample; + } + + public void init(GLAutoDrawable drawable) { + System.err.println(); + System.err.println("Requested: " + drawable.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities()); + System.err.println(); + System.err.println("Chosen : " + drawable.getChosenGLCapabilities()); + System.err.println(); + GL2ES1 gl = drawable.getGL().getGL2ES1(); + if (multisample) { + gl.glEnable(GL.GL_MULTISAMPLE); + } + gl.glClearColor(0, 0, 0, 0); + // gl.glEnable(GL.GL_DEPTH_TEST); + // gl.glDepthFunc(GL.GL_LESS); + gl.glMatrixMode(GL2ES1.GL_MODELVIEW); + gl.glLoadIdentity(); + gl.glMatrixMode(GL2ES1.GL_PROJECTION); + gl.glLoadIdentity(); + gl.glOrtho(-1, 1, -1, 1, -1, 1); + if (multisample) { + gl.glDisable(GL.GL_MULTISAMPLE); + } + immModeSink = ImmModeSink.createFixed(gl, GL.GL_STATIC_DRAW, 40, + 3, GL.GL_FLOAT, // vertex + 0, GL.GL_FLOAT, // color + 0, GL.GL_FLOAT,// normal + 0, GL.GL_FLOAT); // texture + final int numSteps = 20; + final double increment = Math.PI / numSteps; + final double radius = 1; + immModeSink.glBegin(GL.GL_LINES); + for (int i = numSteps - 1; i >= 0; i--) { + immModeSink.glVertex3f((float) (radius * Math.cos(i * increment)), + (float) (radius * Math.sin(i * increment)), + 0f); + immModeSink.glVertex3f((float) (-1.0 * radius * Math.cos(i * increment)), + (float) (-1.0 * radius * Math.sin(i * increment)), + 0f); + } + immModeSink.glEnd(gl, false); + } + + public void dispose(GLAutoDrawable drawable) { + immModeSink.destroy(drawable.getGL()); + immModeSink = null; + } + + public void display(GLAutoDrawable drawable) { + GL2ES1 gl = drawable.getGL().getGL2ES1(); + if (multisample) { + gl.glEnable(GL.GL_MULTISAMPLE); + } + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + immModeSink.draw(gl, true); + if (multisample) { + gl.glDisable(GL.GL_MULTISAMPLE); + } + } + + // Unused routines + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + } + + public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) { + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java new file mode 100644 index 000000000..3dfbb4893 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java @@ -0,0 +1,309 @@ +/** + * Copyright (C) 2011 JogAmp Community. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.jogamp.opengl.test.junit.jogl.demos.es2; + +import java.nio.FloatBuffer; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.FBObject.TextureAttachment; +import com.jogamp.opengl.FBObject.Attachment.Type; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; + +public class FBOMix2DemosES2 implements GLEventListener { + private final GearsES2 demo0; + private final RedSquareES2 demo1; + private final int swapInterval; + private int numSamples; + private boolean demo0Only; + + + private final ShaderState st; + private final PMVMatrix pmvMatrix; + + private final FBObject fbo0; + private final FBObject fbo1; + + private TextureAttachment fbo0Tex; + private TextureAttachment fbo1Tex; + + private ShaderProgram sp0; + private GLUniformData pmvMatrixUniform; + private GLArrayDataServer interleavedVBO; + private GLUniformData texUnit0; + private GLUniformData texUnit1; + + public FBOMix2DemosES2(int swapInterval) { + demo0 = new GearsES2(-1); + demo0.setIsFBOSlave(true); + demo1 = new RedSquareES2(-1); + demo1.setIsFBOSlave(true); + this.swapInterval = swapInterval; + + st = new ShaderState(); + // st.setVerbose(true); + pmvMatrix = new PMVMatrix(); + + fbo0 = new FBObject(); + fbo1 = new FBObject(); + + numSamples = 0; + demo0Only = false; + } + + public void setDemo0Only(boolean v) { + this.demo0Only = v; + } + public boolean getDemo0Only() { return demo0Only; } + + public void setMSAA(int numSamples) { + this.numSamples=numSamples; + } + public int getMSAA() { return numSamples; } + + public void setDoRotation(boolean rotate) { demo1.setDoRotation(rotate); } + + static final String[] es2_prelude = { "#version 100\n", "precision mediump float;\n" }; + static final String gl2_prelude = "#version 110\n"; + + @Override + public void init(GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + demo0.init(drawable); + demo1.init(drawable); + + final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, FBOMix2DemosES2.class, "shader", + "shader/bin", "texture01_xxx", true); + final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, FBOMix2DemosES2.class, "shader", + "shader/bin", "texture02_xxx", true); + + // Prelude shader code w/ GLSL profile specifics [ 1. pre-proc, 2. other ] + int fp0Pos; + if(gl.isGLES2()) { + vp0.insertShaderSource(0, 0, es2_prelude[0]); + fp0Pos = fp0.insertShaderSource(0, 0, es2_prelude[0]); + } else { + vp0.insertShaderSource(0, 0, gl2_prelude); + fp0Pos = fp0.insertShaderSource(0, 0, gl2_prelude); + } + if(gl.isGLES2()) { + fp0Pos = fp0.insertShaderSource(0, fp0Pos, es2_prelude[1]); + } + + sp0 = new ShaderProgram(); + sp0.add(gl, vp0, System.err); + sp0.add(gl, fp0, System.err); + st.attachShaderProgram(gl, sp0, true); + + pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + st.ownUniform(pmvMatrixUniform); + st.uniform(gl, pmvMatrixUniform); + + interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW); + { + interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER); + //interleavedVBO.addGLSLSubArray("mgl_Normal", 3, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER); + + FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer(); + + for(int i=0; i<4; i++) { + ib.put(s_quadVertices, i*3, 3); + ib.put(s_quadColors, i*4, 4); + //ib.put(s_cubeNormals, i*3, 3); + ib.put(s_quadTexCoords, i*2, 2); + } + } + interleavedVBO.seal(gl, true); + interleavedVBO.enableBuffer(gl, false); + st.ownAttribute(interleavedVBO, true); + + texUnit0 = new GLUniformData("mgl_Texture0", 0); + st.ownUniform(texUnit0); + st.uniform(gl, texUnit0); + texUnit1 = new GLUniformData("mgl_Texture1", 1); + st.ownUniform(texUnit1); + st.uniform(gl, texUnit1); + + st.useProgram(gl, false); + + System.err.println("**** Init"); + resetFBOs(gl, drawable); + + fbo0.attachRenderbuffer(gl, Type.DEPTH, 24); + fbo0.unbind(gl); + fbo1.attachRenderbuffer(gl, Type.DEPTH, 24); + fbo1.unbind(gl); + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + + numSamples=fbo0.getNumSamples(); + } + + /** Since we switch MSAA and non-MSAA we need to take extra care, i.e. sync msaa for both FBOs ..*/ + private void resetFBOs(GL gl, GLAutoDrawable drawable) { + // remove all texture attachments, since MSAA uses just color-render-buffer + // and non-MSAA uses texture2d-buffer + fbo0.detachAllColorbuffer(gl); + fbo1.detachAllColorbuffer(gl); + + fbo0.reset(gl, drawable.getWidth(), drawable.getHeight(), numSamples); + fbo1.reset(gl, drawable.getWidth(), drawable.getHeight(), numSamples); + if(fbo0.getNumSamples() != fbo1.getNumSamples()) { + throw new InternalError("sample size mismatch: \n\t0: "+fbo0+"\n\t1: "+fbo1); + } + numSamples = fbo0.getNumSamples(); + + if(numSamples>0) { + fbo0.attachColorbuffer(gl, 0, true); + fbo1.attachColorbuffer(gl, 0, true); + fbo0Tex = fbo0.getSamplingSink(); + fbo1Tex = fbo1.getSamplingSink(); + } else { + fbo0Tex = fbo0.attachTexture2D(gl, 0, true); + fbo1Tex = fbo1.attachTexture2D(gl, 0, true); + } + } + + @Override + public void dispose(GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + demo0.dispose(drawable); + demo1.dispose(drawable); + fbo0.destroy(gl); + fbo1.destroy(gl); + st.destroy(gl); + + fbo0Tex = null; + fbo1Tex = null; + sp0 = null; + pmvMatrixUniform = null; + interleavedVBO = null; + } + + @Override + public void display(GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + if( fbo0.getNumSamples() != numSamples ) { + System.err.println("**** NumSamples: "+fbo0.getNumSamples()+" -> "+numSamples); + resetFBOs(gl, drawable); + } + + if(0 < numSamples) { + gl.glEnable(GL.GL_MULTISAMPLE); + } + + fbo0.bind(gl); + demo0.display(drawable); + fbo0.unbind(gl); + + if(!demo0Only) { + fbo1.bind(gl); + demo1.display(drawable); + fbo1.unbind(gl); + } + + st.useProgram(gl, true); + gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit0.intValue()); + fbo0.use(gl, fbo0Tex); + if(!demo0Only) { + gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit1.intValue()); + fbo1.use(gl, fbo1Tex); + } + interleavedVBO.enableBuffer(gl, true); + + gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); + + interleavedVBO.enableBuffer(gl, false); + fbo0.unuse(gl); + if(!demo0Only) { + fbo1.unuse(gl); + } + + st.useProgram(gl, false); + } + + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + if(-1 != swapInterval) { + gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) + } + + // if(drawable.getWidth() == fbo0.getWidth() && drawable.getHeight() == fbo0.getHeight() ) { + System.err.println("**** Reshape: "+width+"x"+height); + resetFBOs(gl, drawable); + //} + + fbo0.bind(gl); + demo0.reshape(drawable, x, y, width, height); + fbo0.unbind(gl); + fbo1.bind(gl); + demo1.reshape(drawable, x, y, width, height); + fbo1.unbind(gl); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 10.0f); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + + st.useProgram(gl, true); + st.uniform(gl, pmvMatrixUniform); + st.useProgram(gl, false); + + } + + private static final float[] s_quadVertices = { + -1f, -1f, 0f, // LB + 1f, -1f, 0f, // RB + -1f, 1f, 0f, // LT + 1f, 1f, 0f // RT + }; + private static final float[] s_quadColors = { + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f }; + private static final float[] s_quadTexCoords = { + 0f, 0f, // LB + 1f, 0f, // RB + 0f, 1f, // LT + 1f, 1f // RT + }; +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java index 6aea5bb9c..38e8a15ce 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java @@ -65,6 +65,7 @@ public class GearsES2 implements GLEventListener { private int prevMouseX, prevMouseY; private boolean isInitialized = false; + boolean isFBOSlave = false; public GearsES2(int swapInterval) { this.swapInterval = swapInterval; @@ -74,6 +75,8 @@ public class GearsES2 implements GLEventListener { this.swapInterval = 1; } + public void setIsFBOSlave(boolean v) { isFBOSlave = v; } + public void setPMVUseBackingArray(boolean pmvUseBackingArray) { this.pmvUseBackingArray = pmvUseBackingArray; } @@ -115,7 +118,6 @@ public class GearsES2 implements GLEventListener { System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER)); System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION)); - gl.glEnable(GL.GL_CULL_FACE); gl.glEnable(GL.GL_DEPTH_TEST); st = new ShaderState(); @@ -168,13 +170,14 @@ public class GearsES2 implements GLEventListener { gear3 = new GearsObjectES2(gear3, pmvMatrix, pmvMatrixUniform, colorU); System.err.println("gear3 reused: "+gear3); } - - if (drawable.getNativeSurface() instanceof Window) { - Window window = (Window) drawable.getNativeSurface(); + + final Object upstreamWidget = drawable.getUpstreamWidget(); + if (upstreamWidget instanceof Window) { + final Window window = (Window) upstreamWidget; window.addMouseListener(gearsMouse); window.addKeyListener(gearsKeys); - } else if (GLProfile.isAWTAvailable() && drawable instanceof java.awt.Component) { - java.awt.Component comp = (java.awt.Component) drawable; + } else if (GLProfile.isAWTAvailable() && upstreamWidget instanceof java.awt.Component) { + final java.awt.Component comp = (java.awt.Component) upstreamWidget; new com.jogamp.newt.event.awt.AWTMouseAdapter(gearsMouse).addTo(comp); new com.jogamp.newt.event.awt.AWTKeyAdapter(gearsKeys).addTo(comp); } @@ -187,7 +190,9 @@ public class GearsES2 implements GLEventListener { System.err.println(Thread.currentThread()+" GearsES2.reshape "+x+"/"+y+" "+width+"x"+height+", swapInterval "+swapInterval); GL2ES2 gl = drawable.getGL().getGL2ES2(); - gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) + if(-1 != swapInterval) { + gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) + } st.useProgram(gl, true); pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); @@ -218,8 +223,9 @@ public class GearsES2 implements GLEventListener { } isInitialized = false; System.err.println(Thread.currentThread()+" GearsES2.dispose ... "); - if (drawable.getNativeSurface() instanceof Window) { - Window window = (Window) drawable.getNativeSurface(); + final Object upstreamWidget = drawable.getUpstreamWidget(); + if (upstreamWidget instanceof Window) { + final Window window = (Window) upstreamWidget; window.removeMouseListener(gearsMouse); window.removeKeyListener(gearsKeys); } @@ -235,6 +241,7 @@ public class GearsES2 implements GLEventListener { colorU = null; st.destroy(gl); st = null; + System.err.println(Thread.currentThread()+" GearsES2.dispose FIN"); } @@ -246,12 +253,16 @@ public class GearsES2 implements GLEventListener { GL2ES2 gl = drawable.getGL().getGL2ES2(); final boolean hasFocus; - if(drawable.getNativeSurface() instanceof NativeWindow) { - hasFocus = ((NativeWindow)drawable.getNativeSurface()).hasFocus(); + final Object upstreamWidget = drawable.getUpstreamWidget(); + if(upstreamWidget instanceof NativeWindow) { + hasFocus = ((NativeWindow)upstreamWidget).hasFocus(); } else { hasFocus = true; } - if(hasFocus) { + + gl.glEnable(GL.GL_CULL_FACE); + + if( isFBOSlave || hasFocus ) { gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); } else { gl.glClearColor(0.2f, 0.2f, 0.2f, 0.0f); @@ -278,7 +289,9 @@ public class GearsES2 implements GLEventListener { gear2.draw(gl, 3.1f, -2.0f, -2f * angle - 9.0f, GearsObject.green); gear3.draw(gl, -3.1f, 4.2f, -2f * angle - 25.0f, GearsObject.blue); pmvMatrix.glPopMatrix(); - st.useProgram(gl, false); + st.useProgram(gl, false); + + gl.glDisable(GL.GL_CULL_FACE); } boolean confinedFixedCenter = false; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/MultisampleDemoES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/MultisampleDemoES2.java new file mode 100644 index 000000000..5facc1a49 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/MultisampleDemoES2.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.test.junit.jogl.demos.es2; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import com.jogamp.opengl.util.ImmModeSink; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; + +public class MultisampleDemoES2 implements GLEventListener { + + private boolean multisample; + private final ShaderState st; + private final PMVMatrix pmvMatrix; + private ShaderProgram sp0; + private GLUniformData pmvMatrixUniform; + private ImmModeSink immModeSink; + + public MultisampleDemoES2(boolean multisample) { + this.multisample = multisample; + st = new ShaderState(); + st.setVerbose(true); + pmvMatrix = new PMVMatrix(); + } + + static final String[] es2_prelude = { "#version 100\n", "precision mediump float;\n" }; + static final String gl2_prelude = "#version 110\n"; + + public void init(GLAutoDrawable glad) { + final GL2ES2 gl = glad.getGL().getGL2ES2(); + System.err.println(); + System.err.println("Requested: " + glad.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities()); + System.err.println(); + System.err.println("Chosen : " + glad.getChosenGLCapabilities()); + System.err.println(); + + final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, MultisampleDemoES2.class, "shader", + "shader/bin", "mgl_default_xxx", true); + final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, MultisampleDemoES2.class, "shader", + "shader/bin", "mgl_default_xxx", true); + + // Prelude shader code w/ GLSL profile specifics [ 1. pre-proc, 2. other ] + int fp0Pos; + if(gl.isGLES2()) { + vp0.insertShaderSource(0, 0, es2_prelude[0]); + fp0Pos = fp0.insertShaderSource(0, 0, es2_prelude[0]); + } else { + vp0.insertShaderSource(0, 0, gl2_prelude); + fp0Pos = fp0.insertShaderSource(0, 0, gl2_prelude); + } + if(gl.isGLES2()) { + fp0Pos = fp0.insertShaderSource(0, fp0Pos, es2_prelude[1]); + } + + sp0 = new ShaderProgram(); + sp0.add(gl, vp0, System.err); + sp0.add(gl, fp0, System.err); + st.attachShaderProgram(gl, sp0, true); + + pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + st.ownUniform(pmvMatrixUniform); + st.uniform(gl, pmvMatrixUniform); + + // Using predef array names, see + // GLPointerFuncUtil.getPredefinedArrayIndexName(glArrayIndex); + immModeSink = ImmModeSink.createGLSL(gl, GL.GL_STATIC_DRAW, 40, + 3, GL.GL_FLOAT, // vertex + 4, GL.GL_FLOAT, // color + 0, GL.GL_FLOAT,// normal + 0, GL.GL_FLOAT); // texture + final int numSteps = 20; + final double increment = Math.PI / numSteps; + final double radius = 1; + immModeSink.glBegin(GL.GL_LINES); + for (int i = numSteps - 1; i >= 0; i--) { + immModeSink.glVertex3f((float) (radius * Math.cos(i * increment)), + (float) (radius * Math.sin(i * increment)), + 0f); + immModeSink.glColor4f( 1f, 1f, 1f, 1f ); + immModeSink.glVertex3f((float) (-1.0 * radius * Math.cos(i * increment)), + (float) (-1.0 * radius * Math.sin(i * increment)), + 0f); + immModeSink.glColor4f( 1f, 1f, 1f, 1f ); + } + immModeSink.glEnd(gl, false); + + st.useProgram(gl, false); + } + + public void dispose(GLAutoDrawable glad) { + final GL2ES2 gl = glad.getGL().getGL2ES2(); + immModeSink.destroy(gl); + immModeSink = null; + st.destroy(gl); + } + + public void display(GLAutoDrawable glad) { + final GL2ES2 gl = glad.getGL().getGL2ES2(); + if (multisample) { + gl.glEnable(GL.GL_MULTISAMPLE); + } + gl.glClearColor(0, 0, 0, 0); + // gl.glEnable(GL.GL_DEPTH_TEST); + // gl.glDepthFunc(GL.GL_LESS); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + st.useProgram(gl, true); + + immModeSink.draw(gl, true); + + st.useProgram(gl, false); + } + + // Unused routines + public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) { + System.err.println("reshape .."); + final GL2ES2 gl = glad.getGL().getGL2ES2(); + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + // pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f); + pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 10.0f); + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + + st.useProgram(gl, true); + st.uniform(gl, pmvMatrixUniform); + st.useProgram(gl, false); + } + + public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) { + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java index 6982d61b7..436c44759 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java @@ -27,9 +27,9 @@ */ package com.jogamp.opengl.test.junit.jogl.demos.es2; +import com.jogamp.newt.Window; import com.jogamp.newt.event.MouseAdapter; import com.jogamp.newt.event.MouseEvent; -import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.util.GLArrayDataServer; import com.jogamp.opengl.util.PMVMatrix; import com.jogamp.opengl.util.glsl.ShaderCode; @@ -37,10 +37,8 @@ import com.jogamp.opengl.util.glsl.ShaderProgram; import com.jogamp.opengl.util.glsl.ShaderState; import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; -import javax.media.opengl.GLAnimatorControl; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLEventListener; -import javax.media.opengl.GLRunnable; import javax.media.opengl.GLUniformData; public class RedSquareES2 implements GLEventListener { @@ -52,10 +50,11 @@ public class RedSquareES2 implements GLEventListener { long t0; private int swapInterval = 0; MyMouseAdapter myMouse = new MyMouseAdapter(); - GLWindow glWindow = null; + Window window = null; float aspect = 1.0f; boolean doRotate = true; boolean isInitialized = false; + boolean isFBOSlave = false; public RedSquareES2(int swapInterval) { this.swapInterval = swapInterval; @@ -65,6 +64,7 @@ public class RedSquareES2 implements GLEventListener { this.swapInterval = 1; } + public void setIsFBOSlave(boolean v) { isFBOSlave = v; } public void setAspect(float aspect) { this.aspect = aspect; } public void setDoRotation(boolean rotate) { this.doRotate = rotate; } @@ -129,13 +129,13 @@ public class RedSquareES2 implements GLEventListener { colors.enableBuffer(gl, false); // OpenGL Render Settings - gl.glClearColor(0, 0, 0, 0); gl.glEnable(GL2ES2.GL_DEPTH_TEST); st.useProgram(gl, false); - if (glad instanceof GLWindow) { - glWindow = (GLWindow) glad; - glWindow.addMouseListener(myMouse); + final Object upstreamWidget = glad.getUpstreamWidget(); + if (!isFBOSlave && upstreamWidget instanceof Window) { + window = (Window) upstreamWidget; + window.addMouseListener(myMouse); } t0 = System.currentTimeMillis(); System.err.println(Thread.currentThread()+" RedSquareES2.init FIN"); @@ -145,6 +145,7 @@ public class RedSquareES2 implements GLEventListener { long t1 = System.currentTimeMillis(); GL2ES2 gl = glad.getGL().getGL2ES2(); + gl.glClearColor(0, 0, 0, 0); gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); st.useProgram(gl, true); // One rotation every four seconds @@ -171,7 +172,9 @@ public class RedSquareES2 implements GLEventListener { System.err.println(Thread.currentThread()+" RedSquareES2.reshape "+x+"/"+y+" "+width+"x"+height+", swapInterval "+swapInterval); GL2ES2 gl = glad.getGL().getGL2ES2(); - gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) + if(-1 != swapInterval) { + gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) + } st.useProgram(gl, true); // Set location in front of camera @@ -192,9 +195,9 @@ public class RedSquareES2 implements GLEventListener { } isInitialized = false; System.err.println(Thread.currentThread()+" RedSquareES2.dispose ... "); - if (null != glWindow) { - glWindow.removeMouseListener(myMouse); - glWindow = null; + if (null != window) { + window.removeMouseListener(myMouse); + window = null; } GL2ES2 gl = glad.getGL().getGL2ES2(); st.destroy(gl); @@ -207,24 +210,9 @@ public class RedSquareES2 implements GLEventListener { class MyMouseAdapter extends MouseAdapter { public void mouseClicked(MouseEvent e) { System.err.println(e); - if(null != glWindow && e.getSource() == glWindow.getDelegatedWindow()) { - if(e.getX() < glWindow.getWidth()/2) { - glWindow.setFullscreen(!glWindow.isFullscreen()); - System.err.println("setFullscreen: "+glWindow.isFullscreen()); - } else { - glWindow.invoke(false, new GLRunnable() { - public boolean run(GLAutoDrawable drawable) { - GL gl = drawable.getGL(); - gl.setSwapInterval(gl.getSwapInterval()<=0?1:0); - System.err.println("setSwapInterval: "+gl.getSwapInterval()); - final GLAnimatorControl a = drawable.getAnimator(); - if( null != a ) { - a.resetFPSCounter(); - } - return true; - } - }); - } + if(null != window && e.getSource() == window) { + window.setFullscreen(!window.isFullscreen()); + System.err.println("setFullscreen: "+window.isFullscreen()); } } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java index b04bd07c1..9217e2b53 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java @@ -265,11 +265,12 @@ public class TextureSequenceCubeES2 implements GLEventListener { st.useProgram(gl, false); - if (drawable instanceof Window) { - Window window = (Window) drawable; + final Object upstreamWidget = drawable.getUpstreamWidget(); + if (upstreamWidget instanceof Window) { + final Window window = (Window) upstreamWidget; window.addMouseListener(mouseAction); - } else if (GLProfile.isAWTAvailable() && drawable instanceof java.awt.Component) { - java.awt.Component comp = (java.awt.Component) drawable; + } else if (GLProfile.isAWTAvailable() && upstreamWidget instanceof java.awt.Component) { + final java.awt.Component comp = (java.awt.Component) upstreamWidget; new com.jogamp.newt.event.awt.AWTMouseAdapter(mouseAction).addTo(comp); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java index 0b83aacd8..7f2713354 100755 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java @@ -163,8 +163,9 @@ public class MovieCube implements GLEventListener, GLMediaEventListener { mPlayer.start(); boolean added; - if (drawable instanceof Window) { - Window window = (Window) drawable; + final Object upstreamWidget = drawable.getUpstreamWidget(); + if (upstreamWidget instanceof Window) { + final Window window = (Window) upstreamWidget; window.addKeyListener(keyAction); added = true; } else { added = false; } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java index 8210065ab..e17c9e88b 100755 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java @@ -400,8 +400,9 @@ public class MovieSimple implements GLEventListener, GLMediaEventListener { startTime = System.currentTimeMillis(); - if (drawable instanceof Window) { - Window window = (Window) drawable; + final Object upstreamWidget = drawable.getUpstreamWidget(); + if (upstreamWidget instanceof Window) { + final Window window = (Window) upstreamWidget; window.addMouseListener(mouseAction); winWidth = window.getWidth(); winHeight = window.getHeight(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java index 04563d62e..797a16485 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java @@ -258,7 +258,6 @@ public class TestGearsES2NEWT extends UITestCase { public static void main(String args[]) throws IOException { int x=0, y=0, w=640, h=480; - boolean useSize = false; boolean usePos = false; for(int i=0; i= height. + * + * Draws the Gears demo in a window that's twice as wide than it is tall, + * and checks to see if a particular pixel in the right half of the frame + * is colored. + * + * @author Wade Walker (adapted from TestGearsGLJPanelAWT) + */ +public class TestGLJPanelAWTBug450 extends UITestCase { + static GLProfile glp; + static int width, height; + static int r_x, r_y; + /** Set this if test fails. Needed because we can't throw an exception + * all the way up the stack from where we test the pixel. */ + static boolean failed; + + @BeforeClass + public static void initClass() { + glp = GLProfile.getGL2ES2(); + Assert.assertNotNull(glp); + height = 256; + width = 2*height; + r_x = 5*height/4; // 5/8 * width + r_y = height/2; + } + + @AfterClass + public static void releaseClass() { + } + + protected void runTestGL(GLCapabilities caps) + throws AWTException, InterruptedException, InvocationTargetException + { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + JFrame frame = new JFrame("Swing GLJPanel"); + Assert.assertNotNull(frame); + + GLJPanel glJPanel = new GLJPanel(caps); + Assert.assertNotNull(glJPanel); + RedSquareES2 demo = new RedSquareES2(); + demo.setAspect((float)width/(float)height); + demo.setDoRotation(false); + glJPanel.addGLEventListener(demo); + glJPanel.addGLEventListener(new GLEventListener() { + int f = 0; + @Override + public void init(GLAutoDrawable drawable) { + // drawable.getGL().glClearColor(0, 0, 1, 1); + } + @Override + public void display(GLAutoDrawable drawable) { + // look at one pixel at the bottom of the frame, just right of + // the center line, and make sure it's not black + GL2 gl = GLUgl2.getCurrentGL2(); + ByteBuffer bytebuffer = ByteBuffer.allocateDirect( 3 ); + gl.glReadPixels( r_x, r_y, 1, 1, GL2.GL_BGR, GL2.GL_UNSIGNED_BYTE, bytebuffer ); + byte byte0 = bytebuffer.get( 0 ); + byte byte1 = bytebuffer.get( 1 ); + byte byte2 = bytebuffer.get( 2 ); + if( (byte0 == 0) && (byte1 == 0) && (byte2 == 0) ) { + failed = true; + } + if(0 == f) { + System.err.println("BGR ("+r_x+"/"+r_y+"): "+byte0+", "+byte1+", "+byte2+" - OK "+(!failed)); + snapshot(getSimpleTestName("."), f, null, gl, screenshot, TextureIO.PNG, null); + } + f++; + } + @Override + public void dispose(GLAutoDrawable drawable) {} + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + + FPSAnimator animator = new FPSAnimator(glJPanel, 60); + + final JFrame _frame = frame; + final GLJPanel _glJPanel = glJPanel; + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + _frame.getContentPane().add(_glJPanel, BorderLayout.CENTER); + _frame.setSize(width, height); + _frame.setVisible(true); + } } ) ; + + animator.setUpdateFPSFrames(1, null); + animator.start(); + Assert.assertEquals(true, animator.isAnimating()); + + while(animator.isAnimating() && animator.getTotalFPSDuration()= height. - * - * Draws the Gears demo in a window that's twice as wide than it is tall, - * and checks to see if a particular pixel in the right half of the frame - * is colored. - * - * @author Wade Walker (adapted from TestGearsGLJPanelAWT) - */ -public class TestGearsGLJPanelAWTBug450 extends UITestCase { - static GLProfile glp; - static int width, height; - static int r_x, r_y; - /** Set this if test fails. Needed because we can't throw an exception - * all the way up the stack from where we test the pixel. */ - static boolean failed; - - @BeforeClass - public static void initClass() { - glp = GLProfile.getGL2ES2(); - Assert.assertNotNull(glp); - height = 256; - width = 2*height; - r_x = 5*height/4; // 5/8 * width - r_y = height/2; - } - - @AfterClass - public static void releaseClass() { - } - - protected void snapshot(GLAutoDrawable drawable, boolean alpha, boolean flip, String filename) { - GLReadBufferUtil screenshot = new GLReadBufferUtil(alpha, false); - if(screenshot.readPixels(drawable.getGL(), drawable, flip)) { - screenshot.write(new File(filename)); - } - } - - protected void runTestGL(GLCapabilities caps) - throws AWTException, InterruptedException, InvocationTargetException - { - JFrame frame = new JFrame("Swing GLJPanel"); - Assert.assertNotNull(frame); - - GLJPanel glJPanel = new GLJPanel(caps); - Assert.assertNotNull(glJPanel); - RedSquareES2 demo = new RedSquareES2(); - demo.setAspect((float)width/(float)height); - demo.setDoRotation(false); - glJPanel.addGLEventListener(demo); - glJPanel.addGLEventListener(new GLEventListener() { - int f = 0; - @Override - public void init(GLAutoDrawable drawable) { - // drawable.getGL().glClearColor(0, 0, 1, 1); - } - @Override - public void display(GLAutoDrawable drawable) { - // look at one pixel at the bottom of the frame, just right of - // the center line, and make sure it's not black - GL2 gl = GLUgl2.getCurrentGL2(); - ByteBuffer bytebuffer = ByteBuffer.allocateDirect( 3 ); - gl.glReadPixels( r_x, r_y, 1, 1, GL2.GL_BGR, GL2.GL_UNSIGNED_BYTE, bytebuffer ); - byte byte0 = bytebuffer.get( 0 ); - byte byte1 = bytebuffer.get( 1 ); - byte byte2 = bytebuffer.get( 2 ); - if( (byte0 == 0) && (byte1 == 0) && (byte2 == 0) ) { - failed = true; - } - if(0 == f) { - System.err.println("BGR ("+r_x+"/"+r_y+"): "+byte0+", "+byte1+", "+byte2+" - OK "+(!failed)); - snapshot(drawable, true, false, getSimpleTestName(".")+".png"); - } - f++; - } - @Override - public void dispose(GLAutoDrawable drawable) {} - @Override - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } - }); - - FPSAnimator animator = new FPSAnimator(glJPanel, 60); - - final JFrame _frame = frame; - final GLJPanel _glJPanel = glJPanel; - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - _frame.getContentPane().add(_glJPanel, BorderLayout.CENTER); - _frame.setSize(width, height); - _frame.setVisible(true); - } } ) ; - - animator.setUpdateFPSFrames(1, null); - animator.start(); - Assert.assertEquals(true, animator.isAnimating()); - - while(animator.isAnimating() && animator.getTotalFPSDuration() buffer0, Green -> buffer1 - st.attachShaderProgram(gl, sp0, true); - vertices0.enableBuffer(gl, true); - colors0.enableBuffer(gl, true); - - fbo_mrt.bind(gl); - gl.glDrawBuffers(2, two_buffers, 0); - gl.glViewport(0, 0, fbo_mrt.getWidth(), fbo_mrt.getHeight()); - - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); - fbo_mrt.unbind(gl); - vertices0.enableBuffer(gl, false); - colors0.enableBuffer(gl, false); - - // pass 2 - mix buffer0, buffer1 and blue - // rg = buffer0.rg + buffer1.rg, b = Blue - length(rg); - st.attachShaderProgram(gl, sp1, true); - vertices0.enableBuffer(gl, true); - colors0.enableBuffer(gl, true); - texCoords0.enableBuffer(gl, true); - gl.glDrawBuffers(1, bck_buffers, 0); - - gl.glViewport(0, 0, drawable.getWidth(), drawable.getHeight()); - fbo_mrt.use(gl, 0); - fbo_mrt.use(gl, 1); - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); - fbo_mrt.unuse(gl); - vertices0.enableBuffer(gl, false); - colors0.enableBuffer(gl, false); - texCoords0.enableBuffer(gl, false); - - drawable.swapBuffers(); - Thread.sleep(50); - } - - NEWTGLContext.destroyWindow(winctx); - } - - public static void main(String args[]) throws IOException { - System.err.println("main - start"); - for(int i=0; i 0 ? "rgba" : "rgb_"; - snapshot(drawable, true, false, getSimpleTestName(".")+"-F_rgba-I_"+pfmt+"-"+drawable.getGLProfile().getName()+".png"); - snapshot(drawable, false, false, getSimpleTestName(".")+"-F_rgb_-I_"+pfmt+"-"+drawable.getGLProfile().getName()+".png"); + snapshot(getSimpleTestName("."), f, null, drawable.getGL(), screenshotRGBA, TextureIO.PNG, null); + snapshot(getSimpleTestName("."), f, null, drawable.getGL(), screenshotRGB, TextureIO.PNG, null); + f++; } public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } }); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01NEWT.java index b5b12035d..5681df0ad 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite01NEWT.java @@ -28,8 +28,6 @@ package com.jogamp.opengl.test.junit.jogl.util.texture; -import java.io.File; - import com.jogamp.newt.opengl.GLWindow; import javax.media.opengl.GLAutoDrawable; @@ -37,6 +35,7 @@ import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -62,32 +61,26 @@ public class TestGLReadBufferUtilTextureIOWrite01NEWT extends UITestCase { height = 256; } - protected void snapshot(GLAutoDrawable drawable, boolean alpha, boolean flip, String filename) { - GLReadBufferUtil screenshot = new GLReadBufferUtil(alpha, false); - if(screenshot.readPixels(drawable.getGL(), drawable, flip)) { - screenshot.write(new File(filename)); - } - } - @Test public void testOnscreenWritePNG_TGA_PAM() throws InterruptedException { + final GLReadBufferUtil screenshotRGB = new GLReadBufferUtil(false, false); + final GLReadBufferUtil screenshotRGBA = new GLReadBufferUtil(true, false); GLWindow glWindow = GLWindow.create(caps); Assert.assertNotNull(glWindow); glWindow.setTitle("Shared Gears NEWT Test"); glWindow.setSize(width, height); glWindow.addGLEventListener(new GearsES2(1)); glWindow.addGLEventListener(new GLEventListener() { + int f = 0; public void init(GLAutoDrawable drawable) {} public void dispose(GLAutoDrawable drawable) {} public void display(GLAutoDrawable drawable) { - final String pfmt = drawable.getChosenGLCapabilities().getAlphaBits() > 0 ? "rgba" : "rgb_"; - // snapshot(drawable, false, true, getSimpleTestName(".")+"-rgb_-"+drawable.getGLProfile().getName()+".ppm"); - snapshot(drawable, true, false, getSimpleTestName(".")+"-F_rgba-I_"+pfmt+"-"+drawable.getGLProfile().getName()+".png"); - snapshot(drawable, true, false, getSimpleTestName(".")+"-F_rgba-I_"+pfmt+"-"+drawable.getGLProfile().getName()+".tga"); - snapshot(drawable, true, true, getSimpleTestName(".")+"-F_rgba-I_"+pfmt+"-"+drawable.getGLProfile().getName()+".pam"); - snapshot(drawable, false, false, getSimpleTestName(".")+"-F_rgb_-I_"+pfmt+"-"+drawable.getGLProfile().getName()+".png"); - snapshot(drawable, false, false, getSimpleTestName(".")+"-F_rgb_-I_"+pfmt+"-"+drawable.getGLProfile().getName()+".tga"); - snapshot(drawable, false, true, getSimpleTestName(".")+"-F_rgb_-I_"+pfmt+"-"+drawable.getGLProfile().getName()+".pam"); + snapshot(getSimpleTestName("."), f++, null, drawable.getGL(), screenshotRGBA, TextureIO.PNG, null); + snapshot(getSimpleTestName("."), f++, null, drawable.getGL(), screenshotRGB, TextureIO.PNG, null); + snapshot(getSimpleTestName("."), f++, null, drawable.getGL(), screenshotRGBA, TextureIO.TGA, null); + snapshot(getSimpleTestName("."), f++, null, drawable.getGL(), screenshotRGB, TextureIO.TGA, null); + snapshot(getSimpleTestName("."), f++, null, drawable.getGL(), screenshotRGBA, TextureIO.PAM, null); + snapshot(getSimpleTestName("."), f++, null, drawable.getGL(), screenshotRGB, TextureIO.PAM, null); } public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } }); @@ -98,18 +91,21 @@ public class TestGLReadBufferUtilTextureIOWrite01NEWT extends UITestCase { @Test public void testOffscreenWritePNG() throws InterruptedException { + final GLReadBufferUtil screenshotRGB = new GLReadBufferUtil(false, false); + final GLReadBufferUtil screenshotRGBA = new GLReadBufferUtil(true, false); final GLCapabilities caps2 = WindowUtilNEWT.fixCaps(caps, false, true, false); GLWindow glWindow = GLWindow.create(caps2); Assert.assertNotNull(glWindow); glWindow.setSize(width, height); glWindow.addGLEventListener(new GearsES2(1)); glWindow.addGLEventListener(new GLEventListener() { + int f = 0; public void init(GLAutoDrawable drawable) {} public void dispose(GLAutoDrawable drawable) {} public void display(GLAutoDrawable drawable) { - final String pfmt = drawable.getChosenGLCapabilities().getAlphaBits() > 0 ? "rgba" : "rgb_"; - snapshot(drawable, true, false, getSimpleTestName(".")+"-F_rgba-I_"+pfmt+"-"+drawable.getGLProfile().getName()+".png"); - snapshot(drawable, false, false, getSimpleTestName(".")+"-F_rgb_-I_"+pfmt+"-"+drawable.getGLProfile().getName()+".png"); + snapshot(getSimpleTestName("."), f, null, drawable.getGL(), screenshotRGBA, TextureIO.PNG, null); + snapshot(getSimpleTestName("."), f, null, drawable.getGL(), screenshotRGB, TextureIO.PNG, null); + f++; } public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } }); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02AWT.java index 10dd4ea70..43641fe6d 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02AWT.java @@ -30,9 +30,6 @@ package com.jogamp.opengl.test.junit.jogl.util.texture; import java.awt.Dimension; import java.awt.Frame; -import java.io.File; -import java.io.PrintWriter; -import java.io.StringWriter; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; @@ -45,6 +42,7 @@ import jogamp.nativewindow.jawt.JAWTUtil; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.UITestCase; @@ -71,20 +69,6 @@ public class TestGLReadBufferUtilTextureIOWrite02AWT extends UITestCase { height = 64; } - protected void snapshot(GLAutoDrawable drawable, GLReadBufferUtil screenshot, int i) { - final StringWriter filename = new StringWriter(); - { - final PrintWriter pw = new PrintWriter(filename); - final String pfmt = drawable.getChosenGLCapabilities().getAlphaBits() > 0 ? "rgba" : "rgb_"; - pw.printf("%s-F_rgba-I_%s-%s-n%03d-%04dx%04d.png", - getSimpleTestName("."), pfmt, drawable.getGLProfile().getName(), i, drawable.getWidth(), drawable.getHeight()); - } - drawable.getGL().glFinish(); // poor mans sync .. - if(screenshot.readPixels(drawable.getGL(), drawable, false)) { - screenshot.write(new File(filename.toString())); - } - } - protected void testWritePNGWithResizeImpl(boolean offscreenLayer) throws InterruptedException { if(!offscreenLayer && JAWTUtil.isOffscreenLayerRequired()) { System.err.println("onscreen layer n/a"); @@ -127,7 +111,7 @@ public class TestGLReadBufferUtilTextureIOWrite02AWT extends UITestCase { if(snap) { System.err.println("XXX: ["+fw_old+", "+dw_old+"], "+fw+"x"+fh+", "+dw+"x"+dh+", sz_changed "+sz_changed+", snap "+snap); c=0; - snapshot(drawable, screenshot, i++); + snapshot(getSimpleTestName("."), i++, null, drawable.getGL(), screenshot, TextureIO.PNG, null); dw_old = dw; fw_old = fw; Threading.invoke(true, new Runnable() { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02NEWT.java index ed0791f7c..d1ffa84cf 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestGLReadBufferUtilTextureIOWrite02NEWT.java @@ -28,10 +28,6 @@ package com.jogamp.opengl.test.junit.jogl.util.texture; -import java.io.File; -import java.io.PrintWriter; -import java.io.StringWriter; - import com.jogamp.newt.opengl.GLWindow; import javax.media.opengl.GLAutoDrawable; @@ -41,6 +37,7 @@ import javax.media.opengl.GLProfile; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -66,19 +63,6 @@ public class TestGLReadBufferUtilTextureIOWrite02NEWT extends UITestCase { height = 64; } - protected void snapshot(GLAutoDrawable drawable, GLReadBufferUtil screenshot, int i) { - final StringWriter filename = new StringWriter(); - { - final PrintWriter pw = new PrintWriter(filename); - final String pfmt = drawable.getChosenGLCapabilities().getAlphaBits() > 0 ? "rgba" : "rgb_"; - pw.printf("%s-F_rgba-I_%s-%s-n%03d-%04dx%04d.png", - getSimpleTestName("."), pfmt, drawable.getGLProfile().getName(), i, drawable.getWidth(), drawable.getHeight()); - } - if(screenshot.readPixels(drawable.getGL(), drawable, false)) { - screenshot.write(new File(filename.toString())); - } - } - private void testWritePNGWithResizeImpl(boolean offscreen) throws InterruptedException { final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); final GLCapabilities caps2 = offscreen ? WindowUtilNEWT.fixCaps(caps, false, true, false) : caps; @@ -110,7 +94,7 @@ public class TestGLReadBufferUtilTextureIOWrite02NEWT extends UITestCase { if(snap) { System.err.println("XXX: ["+dw_old+"], "+dw+"x"+dh+", sz_changed "+sz_changed+", snap "+snap); c=0; - snapshot(drawable, screenshot, i++); + snapshot(getSimpleTestName("."), i++, null, drawable.getGL(), screenshot, TextureIO.PNG, null); dw_old = dw; new Thread() { @Override diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java index 068732696..0d4f2b01e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java @@ -52,7 +52,6 @@ import com.jogamp.opengl.util.GLReadBufferUtil; import java.awt.Dimension; import java.awt.Frame; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URLConnection; @@ -96,16 +95,10 @@ public class TestPNGTextureFromFileAWT extends UITestCase { testTextureStream = null; } - protected void snapshot(GLAutoDrawable drawable, String filename) { - GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); - if(screenshot.readPixels(drawable.getGL(), drawable, false)) { - screenshot.write(new File(filename)); - } - } - public void testImpl(boolean useFFP, final InputStream istream, final boolean useAWTIIOP) throws InterruptedException, IOException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); GLProfile glp; if(useFFP && GLProfile.isAvailable(GLProfile.GL2GL3)) { glp = GLProfile.getGL2GL3(); @@ -137,7 +130,7 @@ public class TestPNGTextureFromFileAWT extends UITestCase { // the bug submitter was doing it final GLEventListener gle = useFFP ? new TextureDraw01GL2Listener( texData ) : new TextureDraw01ES2Listener( texData ) ; glc.addGLEventListener(gle); - glc.addGLEventListener(new GLEventListener() { + glc.addGLEventListener(new GLEventListener() { boolean shot = false; @Override public void init(GLAutoDrawable drawable) {} @@ -147,7 +140,7 @@ public class TestPNGTextureFromFileAWT extends UITestCase { // 1 snapshot if(null!=((TextureDraw01Accessor)gle).getTexture() && !shot) { shot = true; - snapshot(drawable, getSimpleTestName(".")+".png"); + snapshot(getSimpleTestName("."), 0, null, drawable.getGL(), screenshot, TextureIO.PNG, null); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java index d973dea2d..b4faafbe7 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java @@ -48,7 +48,6 @@ import com.jogamp.opengl.util.texture.TextureIO; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.GLReadBufferUtil; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URLConnection; @@ -80,14 +79,8 @@ public class TestPNGTextureFromFileNEWT extends UITestCase { testTextureStream = null; } - protected void snapshot(GLAutoDrawable drawable, String filename) { - GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); - if(screenshot.readPixels(drawable.getGL(), drawable, false)) { - screenshot.write(new File(filename)); - } - } - public void testImpl(boolean useFFP, final InputStream istream) throws InterruptedException, IOException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); GLProfile glp; if(useFFP && GLProfile.isAvailable(GLProfile.GL2GL3)) { glp = GLProfile.getGL2GL3(); @@ -119,7 +112,7 @@ public class TestPNGTextureFromFileNEWT extends UITestCase { // 1 snapshot if(null!=((TextureDraw01Accessor)gle).getTexture() && !shot) { shot = true; - snapshot(drawable, getSimpleTestName(".")+".png"); + snapshot(getSimpleTestName("."), 0, null, drawable.getGL(), screenshot, TextureIO.PNG, null); } } diff --git a/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java b/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java index 672675fab..c07d5b741 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java +++ b/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java @@ -28,7 +28,17 @@ package com.jogamp.opengl.test.junit.util; +import java.io.File; +import java.io.PrintWriter; +import java.io.StringWriter; + +import javax.media.opengl.GL; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLDrawable; + import com.jogamp.common.util.locks.SingletonInstance; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; import org.junit.Assume; import org.junit.Before; @@ -108,6 +118,49 @@ public abstract class UITestCase { } static final String unsupportedTestMsg = "Test not supported on this platform."; - + + /** + * Takes a snapshot of the drawable's current framebuffer. Example filenames: + *
      +     * TestFBODrawableNEWT.test01-F_rgba-I_rgba-S0_default-GL2-n0004-0800x0600.png
      +     * TestFBODrawableNEWT.test01-F_rgba-I_rgba-S0_default-GL2-n0005-0800x0600.png
      +     * 
      + * + * @param simpleTestName will be used as the filename prefix + * @param sn sequential number + * @param postSNDetail optional detail to be added to the filename after sn + * @param gl the current GL context object. It's read drawable is being used as the pixel source and to gather some details which will end up in the filename. + * @param readBufferUtil the {@link GLReadBufferUtil} to be used to read the pixels for the screenshot. + * @param fileSuffix Optional file suffix without a dot defining the file type, i.e. "png". + * If null the "png" as defined in {@link TextureIO#PNG} is being used. + * @param destPath Optional platform dependent file path. It shall use {@link File#separatorChar} as is directory separator. + * It shall not end with a directory separator, {@link File#separatorChar}. + * If null the current working directory is being used. + */ + public static void snapshot(String simpleTestName, int sn, String postSNDetail, GL gl, GLReadBufferUtil readBufferUtil, String fileSuffix, String destPath) { + if(null == fileSuffix) { + fileSuffix = TextureIO.PNG; + } + final StringWriter filenameSW = new StringWriter(); + { + final GLDrawable drawable = gl.getContext().getGLReadDrawable(); + final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities(); + final String F_pfmt = readBufferUtil.hasAlpha() ? "rgba" : "rgb_"; + final String pfmt = caps.getAlphaBits() > 0 ? "rgba" : "rgb_"; + final String aaext = caps.getSampleExtension(); + final int samples = caps.getNumSamples() ; + postSNDetail = null != postSNDetail ? "-"+postSNDetail : ""; + final PrintWriter pw = new PrintWriter(filenameSW); + pw.printf("%s-n%04d%s-F_%s-I_%s-S%d_%s-%s-%04dx%04d.%s", + simpleTestName, sn, postSNDetail, F_pfmt, pfmt, samples, aaext, drawable.getGLProfile().getName(), + drawable.getWidth(), drawable.getHeight(), fileSuffix); + } + final String filename = null != destPath ? destPath + File.separator + filenameSW.toString() : filenameSW.toString(); + System.err.println(Thread.currentThread().getName()+": ** screenshot: "+filename); + gl.glFinish(); // just make sure rendering finished .. + if(readBufferUtil.readPixels(gl, false)) { + readBufferUtil.write(new File(filename)); + } + } } -- cgit v1.2.3 From 4a08de4511a627c3d87d6a33debbd561962c0312 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 20 Jul 2012 14:08:49 +0200 Subject: GLCapabilities Native Aquisition: Set alpha bits at last - due to it's auto setting by setSampleBuffers(true) and setBackgroundOpaque(false) This bug lead to X11 GLCapabilities rgba: 8/8/8/1 - which ofc is invalid. Sideeffect was a bad selected GLXFB configuration and the GLContext couldn't be made current. Patch sets alpha bits reflecting reality carefully after opaque/samples. Added API doc note. --- .../media/opengl/DefaultGLCapabilitiesChooser.java | 3 +- .../jogamp/opengl/GLGraphicsConfigurationUtil.java | 4 +- .../opengl/egl/EGLGraphicsConfiguration.java | 37 +++++++-------- .../egl/EGLGraphicsConfigurationFactory.java | 8 ++-- .../macosx/cgl/MacOSXCGLGraphicsConfiguration.java | 5 ++- .../opengl/windows/wgl/WGLGLCapabilities.java | 8 +++- .../jogamp/opengl/x11/glx/X11GLXContext.java | 2 +- .../x11/glx/X11GLXGraphicsConfiguration.java | 52 +++++++++++----------- .../javax/media/nativewindow/Capabilities.java | 15 +++++-- .../junit/jogl/caps/TestMultisampleES2NEWT.java | 9 ++-- .../test/junit/jogl/caps/TestTranslucencyAWT.java | 1 - .../parenting/TestTranslucentParentingAWT.java | 1 - 12 files changed, 82 insertions(+), 63 deletions(-) (limited to 'src/jogl/classes/jogamp/opengl') diff --git a/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java b/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java index 1b84bd9bd..5fa8ce32d 100644 --- a/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java +++ b/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java @@ -117,6 +117,7 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser { final int availnum = available.size(); if (DEBUG) { + Thread.dumpStack(); System.err.println("Desired: " + gldes); System.err.println("Available: " + availnum); for (int i = 0; i < available.size(); i++) { @@ -241,7 +242,7 @@ public class DefaultGLCapabilitiesChooser implements GLCapabilitiesChooser { if (i > 0) { System.err.print(","); } - System.err.print(" " + scores[i]); + System.err.print(" " + i +": " + scores[i]); } System.err.println(" ]"); } diff --git a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java index 900d6a2a0..3f38f33bc 100644 --- a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java +++ b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java @@ -177,14 +177,16 @@ public class GLGraphicsConfigurationUtil { return capsRequested; } + /** Fix opaque setting while preserve alpha bits */ public static GLCapabilitiesImmutable fixOpaqueGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean isOpaque) { GLCapabilities caps2 = null; if( capsRequested.isBackgroundOpaque() != isOpaque) { - // fix caps .. + final int alphaBits = capsRequested.getAlphaBits(); caps2 = (GLCapabilities) capsRequested.cloneMutable(); caps2.setBackgroundOpaque(isOpaque); + caps2.setAlphaBits(alphaBits); return caps2; } return capsRequested; diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java index 214b36493..73867fb40 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java @@ -209,24 +209,6 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple return false; } - if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_RED_SIZE, val)) { - caps.setRedBits(val.get(0)); - } - if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_GREEN_SIZE, val)) { - caps.setGreenBits(val.get(0)); - } - if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_BLUE_SIZE, val)) { - caps.setBlueBits(val.get(0)); - } - if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_ALPHA_SIZE, val)) { - caps.setAlphaBits(val.get(0)); - } - if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_STENCIL_SIZE, val)) { - caps.setStencilBits(val.get(0)); - } - if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_DEPTH_SIZE, val)) { - caps.setDepthBits(val.get(0)); - } if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_SAMPLES, val)) { caps.setSampleBuffers(val.get(0)>0?true:false); caps.setNumSamples(val.get(0)); @@ -262,6 +244,25 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple caps.setTransparentAlphaValue(val.get(0)==EGL.EGL_DONT_CARE?-1:val.get(0)); } */ } + // ALPHA shall be set at last - due to it's auto setting by the above (!opaque / samples) + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_RED_SIZE, val)) { + caps.setRedBits(val.get(0)); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_GREEN_SIZE, val)) { + caps.setGreenBits(val.get(0)); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_BLUE_SIZE, val)) { + caps.setBlueBits(val.get(0)); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_ALPHA_SIZE, val)) { + caps.setAlphaBits(val.get(0)); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_STENCIL_SIZE, val)) { + caps.setStencilBits(val.get(0)); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_DEPTH_SIZE, val)) { + caps.setDepthBits(val.get(0)); + } return GLGraphicsConfigurationUtil.addGLCapabilitiesPermutations(capsBucket, caps, drawableTypeBits ); } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java index 6be9cb547..d79c351a0 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java @@ -253,12 +253,12 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact // // rgb888 - d16, s4 final GLCapabilities fixedCaps = new GLCapabilities(glp); + fixedCaps.setSampleBuffers(true); + fixedCaps.setNumSamples(4); fixedCaps.setRedBits(8); fixedCaps.setGreenBits(8); fixedCaps.setBlueBits(8); fixedCaps.setDepthBits(16); - fixedCaps.setSampleBuffers(true); - fixedCaps.setNumSamples(4); if( !capsChosen.isOnscreen() ) { fixedCaps.setOnscreen(false); fixedCaps.setPBuffer(capsChosen.isPBuffer()); @@ -291,12 +291,12 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact // // rgb565 - d16, s4 final GLCapabilities fixedCaps = new GLCapabilities(glp); + fixedCaps.setSampleBuffers(true); + fixedCaps.setNumSamples(4); fixedCaps.setRedBits(5); fixedCaps.setGreenBits(6); fixedCaps.setBlueBits(5); fixedCaps.setDepthBits(16); - fixedCaps.setSampleBuffers(true); - fixedCaps.setNumSamples(4); if( !capsChosen.isOnscreen() ) { fixedCaps.setOnscreen(false); fixedCaps.setPBuffer(capsChosen.isPBuffer()); diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java index 421e1ef96..202644bb3 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java @@ -281,6 +281,7 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration glp = GLProfile.get(GLProfile.GL2); } GLCapabilities caps = new GLCapabilities(glp); + int alphaBits = 0; for (int i = 0; i < len; i++) { int attr = cglInternalAttributeToken[i+off]; switch (attr) { @@ -317,7 +318,8 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration break; case CGL.NSOpenGLPFAAlphaSize: - caps.setAlphaBits(ivalues[i]); + // ALPHA shall be set at last - due to it's auto setting by !opaque / samples + alphaBits = ivalues[i]; break; case CGL.NSOpenGLPFADepthSize: @@ -350,6 +352,7 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration break; } } + caps.setAlphaBits(alphaBits); return caps; } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java index e255a0672..6a4ce5a4e 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java @@ -52,10 +52,11 @@ public class WGLGLCapabilities extends GLCapabilities { public boolean setValuesByGDI() { arb_pixelformat = -1; + // ALPHA shall be set at last - due to it's auto setting by !opaque / samples setRedBits(pfd.getCRedBits()); setGreenBits(pfd.getCGreenBits()); setBlueBits(pfd.getCBlueBits()); - setAlphaBits(pfd.getCAlphaBits()); + setAlphaBits(pfd.getCAlphaBits()); setAccumRedBits(pfd.getCAccumRedBits()); setAccumGreenBits(pfd.getCAccumGreenBits()); setAccumBlueBits(pfd.getCAccumBlueBits()); @@ -77,6 +78,7 @@ public class WGLGLCapabilities extends GLCapabilities { public boolean setValuesByARB(final int[] iattribs, final int niattribs, final int[] iresults) { arb_pixelformat = 1; + int alphaBits = 0; for (int i = 0; i < niattribs; i++) { int attr = iattribs[i]; switch (attr) { @@ -143,7 +145,8 @@ public class WGLGLCapabilities extends GLCapabilities { break; case WGLExt.WGL_ALPHA_BITS_ARB: - setAlphaBits(iresults[i]); + // ALPHA shall be set at last - due to it's auto setting by !opaque / samples + alphaBits = iresults[i]; break; case WGLExt.WGL_ACCUM_RED_BITS_ARB: @@ -174,6 +177,7 @@ public class WGLGLCapabilities extends GLCapabilities { throw new GLException("Unknown pixel format attribute " + iattribs[i]); } } + setAlphaBits(alphaBits); return true; } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java index e6b74a769..e1e25be67 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java @@ -152,7 +152,7 @@ public abstract class X11GLXContext extends GLContextImpl { throw new InternalError("Given readDrawable but no driver support"); } } catch (RuntimeException re) { - if(TRACE_SWITCH) { + if(DEBUG || TRACE_SWITCH) { System.err.println(getThreadName()+": Warning: X11GLXContext.glXMakeContextCurrent failed: "+re+", with "+ "dpy "+toHexString(dpy)+ ", write "+toHexString(writeDrawable)+ diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java index b5b80e0b3..95b1cc457 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java @@ -308,19 +308,6 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem } GLCapabilities res = new X11GLCapabilities(visualInfo, fbcfg, fbcfgid, glp); - res.setDoubleBuffered(glXGetFBConfig(display, fbcfg, GLX.GLX_DOUBLEBUFFER, tmp, 0) != 0); - res.setStereo (glXGetFBConfig(display, fbcfg, GLX.GLX_STEREO, tmp, 0) != 0); - res.setHardwareAccelerated(glXGetFBConfig(display, fbcfg, GLX.GLX_CONFIG_CAVEAT, tmp, 0) != GLX.GLX_SLOW_CONFIG); - res.setDepthBits (glXGetFBConfig(display, fbcfg, GLX.GLX_DEPTH_SIZE, tmp, 0)); - res.setStencilBits (glXGetFBConfig(display, fbcfg, GLX.GLX_STENCIL_SIZE, tmp, 0)); - res.setRedBits (glXGetFBConfig(display, fbcfg, GLX.GLX_RED_SIZE, tmp, 0)); - res.setGreenBits (glXGetFBConfig(display, fbcfg, GLX.GLX_GREEN_SIZE, tmp, 0)); - res.setBlueBits (glXGetFBConfig(display, fbcfg, GLX.GLX_BLUE_SIZE, tmp, 0)); - res.setAlphaBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ALPHA_SIZE, tmp, 0)); - res.setAccumRedBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_RED_SIZE, tmp, 0)); - res.setAccumGreenBits(glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_GREEN_SIZE, tmp, 0)); - res.setAccumBlueBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_BLUE_SIZE, tmp, 0)); - res.setAccumAlphaBits(glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_ALPHA_SIZE, tmp, 0)); if (isMultisampleAvailable) { res.setSampleBuffers(glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLE_BUFFERS, tmp, 0) != 0); res.setNumSamples (glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLES, tmp, 0)); @@ -336,6 +323,20 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem res.setTransparentBlueValue(xrmask.getBlueMask()); res.setTransparentAlphaValue(alphaMask); } + // ALPHA shall be set at last - due to it's auto setting by the above (!opaque / samples) + res.setDoubleBuffered(glXGetFBConfig(display, fbcfg, GLX.GLX_DOUBLEBUFFER, tmp, 0) != 0); + res.setStereo (glXGetFBConfig(display, fbcfg, GLX.GLX_STEREO, tmp, 0) != 0); + res.setHardwareAccelerated(glXGetFBConfig(display, fbcfg, GLX.GLX_CONFIG_CAVEAT, tmp, 0) != GLX.GLX_SLOW_CONFIG); + res.setRedBits (glXGetFBConfig(display, fbcfg, GLX.GLX_RED_SIZE, tmp, 0)); + res.setGreenBits (glXGetFBConfig(display, fbcfg, GLX.GLX_GREEN_SIZE, tmp, 0)); + res.setBlueBits (glXGetFBConfig(display, fbcfg, GLX.GLX_BLUE_SIZE, tmp, 0)); + res.setAlphaBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ALPHA_SIZE, tmp, 0)); + res.setAccumRedBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_RED_SIZE, tmp, 0)); + res.setAccumGreenBits(glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_GREEN_SIZE, tmp, 0)); + res.setAccumBlueBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_BLUE_SIZE, tmp, 0)); + res.setAccumAlphaBits(glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_ALPHA_SIZE, tmp, 0)); + res.setDepthBits (glXGetFBConfig(display, fbcfg, GLX.GLX_DEPTH_SIZE, tmp, 0)); + res.setStencilBits (glXGetFBConfig(display, fbcfg, GLX.GLX_STENCIL_SIZE, tmp, 0)); try { res.setPbufferFloatingPointBuffers(glXGetFBConfig(display, fbcfg, GLXExt.GLX_FLOAT_COMPONENTS_NV, tmp, 0) != GL.GL_FALSE); @@ -429,18 +430,7 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem // Note: use of hardware acceleration is determined by // glXCreateContext, not by the XVisualInfo. Optimistically claim // that all GLCapabilities have the capability to be hardware - // accelerated. - res.setHardwareAccelerated(true); - res.setDepthBits (glXGetConfig(display, info, GLX.GLX_DEPTH_SIZE, tmp, 0)); - res.setStencilBits (glXGetConfig(display, info, GLX.GLX_STENCIL_SIZE, tmp, 0)); - res.setRedBits (glXGetConfig(display, info, GLX.GLX_RED_SIZE, tmp, 0)); - res.setGreenBits (glXGetConfig(display, info, GLX.GLX_GREEN_SIZE, tmp, 0)); - res.setBlueBits (glXGetConfig(display, info, GLX.GLX_BLUE_SIZE, tmp, 0)); - res.setAlphaBits (glXGetConfig(display, info, GLX.GLX_ALPHA_SIZE, tmp, 0)); - res.setAccumRedBits (glXGetConfig(display, info, GLX.GLX_ACCUM_RED_SIZE, tmp, 0)); - res.setAccumGreenBits(glXGetConfig(display, info, GLX.GLX_ACCUM_GREEN_SIZE, tmp, 0)); - res.setAccumBlueBits (glXGetConfig(display, info, GLX.GLX_ACCUM_BLUE_SIZE, tmp, 0)); - res.setAccumAlphaBits(glXGetConfig(display, info, GLX.GLX_ACCUM_ALPHA_SIZE, tmp, 0)); + // accelerated. if (isMultisampleEnabled) { res.setSampleBuffers(glXGetConfig(display, info, GLX.GLX_SAMPLE_BUFFERS, tmp, 0) != 0); res.setNumSamples (glXGetConfig(display, info, GLX.GLX_SAMPLES, tmp, 0)); @@ -456,6 +446,18 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem res.setTransparentBlueValue(xrmask.getBlueMask()); res.setTransparentAlphaValue(alphaMask); } + // ALPHA shall be set at last - due to it's auto setting by the above (!opaque / samples) + res.setHardwareAccelerated(true); + res.setDepthBits (glXGetConfig(display, info, GLX.GLX_DEPTH_SIZE, tmp, 0)); + res.setStencilBits (glXGetConfig(display, info, GLX.GLX_STENCIL_SIZE, tmp, 0)); + res.setRedBits (glXGetConfig(display, info, GLX.GLX_RED_SIZE, tmp, 0)); + res.setGreenBits (glXGetConfig(display, info, GLX.GLX_GREEN_SIZE, tmp, 0)); + res.setBlueBits (glXGetConfig(display, info, GLX.GLX_BLUE_SIZE, tmp, 0)); + res.setAlphaBits (glXGetConfig(display, info, GLX.GLX_ALPHA_SIZE, tmp, 0)); + res.setAccumRedBits (glXGetConfig(display, info, GLX.GLX_ACCUM_RED_SIZE, tmp, 0)); + res.setAccumGreenBits(glXGetConfig(display, info, GLX.GLX_ACCUM_GREEN_SIZE, tmp, 0)); + res.setAccumBlueBits (glXGetConfig(display, info, GLX.GLX_ACCUM_BLUE_SIZE, tmp, 0)); + res.setAccumAlphaBits(glXGetConfig(display, info, GLX.GLX_ACCUM_ALPHA_SIZE, tmp, 0)); return GLGraphicsConfigurationUtil.addGLCapabilitiesPermutations(capsBucket, res, drawableTypeBits); } diff --git a/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java b/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java index 196f23598..cb33aec5e 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java +++ b/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java @@ -211,9 +211,18 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable { return alphaBits; } - /** Sets the number of bits requested for the color buffer's alpha - component. On some systems only the color depth, which is the - sum of the red, green, and blue bits, is considered. */ + /** + * Sets the number of bits requested for the color buffer's alpha + * component. On some systems only the color depth, which is the + * sum of the red, green, and blue bits, is considered. + *

      + * Note: If alpha bits are zero, they are set to one + * by {@link #setBackgroundOpaque(boolean)} and it's OpenGL specialization GLCapabilities::setSampleBuffers(boolean).
      + * Ensure to call this method after the above to ensure a zero value.
      + * The above automated settings takes into account, that the user calls this method to request alpha bits, + * not to reflect a current state. Nevertheless if this is the case - call it at last. + *

      + */ public void setAlphaBits(int alphaBits) { this.alphaBits = alphaBits; } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES2NEWT.java index b2dad1f39..02fcae6ef 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES2NEWT.java @@ -57,7 +57,6 @@ import com.jogamp.opengl.util.texture.TextureIO; public class TestMultisampleES2NEWT extends UITestCase { static long durationPerTest = 60; // ms - private GLWindow window; public static void main(String[] args) { for(int i=0; i0?true:false)); window.addGLEventListener(new GLEventListener() { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyAWT.java index 8e720965c..7cce5d1e4 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyAWT.java @@ -65,7 +65,6 @@ public class TestTranslucencyAWT extends UITestCase { public static void initClass() { size = new Dimension(400,200); glCaps = new GLCapabilities(null); - glCaps.setAlphaBits(8); glCaps.setBackgroundOpaque(false); } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentParentingAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentParentingAWT.java index 57b8517a6..373c83fce 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentParentingAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentParentingAWT.java @@ -69,7 +69,6 @@ public class TestTranslucentParentingAWT extends UITestCase { public static void initClass() { size = new Dimension(400,200); glCaps = new GLCapabilities(null); - glCaps.setAlphaBits(8); glCaps.setBackgroundOpaque(false); } -- cgit v1.2.3 From 72785ac35aa7c95bc675f3d773c6a7764b5b0ddc Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 20 Jul 2012 15:44:00 +0200 Subject: Fix OSX regression of commit 20bf031db719f7baa4c6e74734fc999061e08fe2 - handling w/ non NSView handles (pbuffer) --- .../jogamp/opengl/macosx/cgl/MacOSXCGLContext.java | 17 ++++++++++++++++- .../jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java | 4 ++++ .../opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java | 6 ++++++ src/jogl/native/macosx/MacOSXWindowSystemInterface.m | 2 +- .../classes/jogamp/nativewindow/macosx/OSXUtil.java | 5 +++++ src/nativewindow/native/macosx/OSXmisc.m | 6 ++++++ 6 files changed, 38 insertions(+), 2 deletions(-) (limited to 'src/jogl/classes/jogamp/opengl') diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java index 4bf2a3c9d..cb79e1560 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java @@ -54,6 +54,7 @@ import javax.media.opengl.GLContext; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import jogamp.nativewindow.macosx.OSXUtil; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableImpl; import jogamp.opengl.GLGraphicsConfigurationUtil; @@ -430,6 +431,19 @@ public abstract class MacOSXCGLContext extends GLContextImpl @Override public long create(long share, int ctp, int major, int minor) { long ctx = 0; + final long nsViewHandle; + if(drawable instanceof MacOSXCGLDrawable) { + // we allow null here! (special pbuffer case) + nsViewHandle = ((MacOSXCGLDrawable)MacOSXCGLContext.this.drawable).getNSViewHandle(); + } else { + // we only allow a valid NSView here + final long aHandle = drawable.getHandle(); + if( OSXUtil.isNSView(aHandle) ) { + nsViewHandle = aHandle; + } else { + throw new RuntimeException("Anonymous drawable instance's handle not of type NSView: "+drawable.getClass().getName()+", "+drawable); + } + } final NativeSurface surface = drawable.getNativeSurface(); final MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) surface.getGraphicsConfiguration(); final OffscreenLayerSurface backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(surface, true); @@ -456,6 +470,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl System.err.println("NS create chosenCaps: "+chosenCaps); System.err.println("NS create pixelFormat: "+toHexString(pixelFormat)); System.err.println("NS create drawable native-handle: "+toHexString(drawable.getHandle())); + System.err.println("NS create drawable NSView-handle: "+toHexString(nsViewHandle)); System.err.println("NS create screen refresh-rate: "+sRefreshRate+" hz, "+screenVSyncTimeout+" micros"); // Thread.dumpStack(); } @@ -463,7 +478,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl int[] viewNotReady = new int[1]; // Try to allocate a context with this ctx = CGL.createContext(share, - drawable.getHandle(), allowIncompleteView, + nsViewHandle, allowIncompleteView, pixelFormat, chosenCaps.isBackgroundOpaque(), viewNotReady, 0); diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java index 841edb2b0..af767f0c3 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java @@ -105,6 +105,10 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl { @Override protected void setRealizedImpl() { } + + protected long getNSViewHandle() { + return GLBackendType.NSOPENGL == openGLMode ? getHandle() : 0; + } protected void registerContext(MacOSXCGLContext ctx) { // NOTE: we need to keep track of the created contexts in order to diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java index b144c020d..8f2f386af 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java @@ -94,6 +94,12 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable { registerContext(ctx); return ctx; } + + @Override + protected long getNSViewHandle() { + // pbuffer handle is NSOpenGLPixelBuffer + return 0; + } @Override public long getHandle() { diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface.m index d3f703142..f774f8f4a 100644 --- a/src/jogl/native/macosx/MacOSXWindowSystemInterface.m +++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface.m @@ -515,7 +515,7 @@ NSOpenGLContext* createContext(NSOpenGLContext* share, DBG_PRINT("createContext.0: share %p, view %p, allowIncompleteView %d, pixfmt %p, opaque %d\n", share, view, (int)allowIncompleteView, fmt, opaque); - if (view != NULL) { + if (view != nil) { Bool viewReady = true; if(!allowIncompleteView) { diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java index 99fc9244e..4767dff18 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java +++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java @@ -59,6 +59,10 @@ public class OSXUtil { return false; } + public static boolean isNSView(long object) { + return isNSView0(object); + } + public static Point GetLocationOnScreen(long windowOrView, int src_x, int src_y) { return (Point) GetLocationOnScreen0(windowOrView, src_x, src_y); } @@ -129,6 +133,7 @@ public class OSXUtil { } */ private static native boolean initIDs0(); + private static native boolean isNSView0(long object); private static native Object GetLocationOnScreen0(long windowOrView, int src_x, int src_y); private static native long CreateNSWindow0(int x, int y, int width, int height); private static native void DestroyNSWindow0(long nsWindow); diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m index ebfefe345..37fa4c88f 100644 --- a/src/nativewindow/native/macosx/OSXmisc.m +++ b/src/nativewindow/native/macosx/OSXmisc.m @@ -92,6 +92,12 @@ Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0(JNIEnv *env, jclass _unused) { return JNI_TRUE; } +JNIEXPORT jboolean JNICALL +Java_jogamp_nativewindow_macosx_OSXUtil_isNSView0(JNIEnv *env, jclass _unused, jlong object) { + NSObject *nsObj = (NSObject*) (intptr_t) object; + return [nsObj isMemberOfClass:[NSView class]]; +} + /* * Class: Java_jogamp_nativewindow_macosx_OSXUtil * Method: getLocationOnScreen0 -- cgit v1.2.3 From e58e7739379147af8c7b875f6e8a7cdb40e342bc Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 20 Jul 2012 22:05:32 +0200 Subject: Fix OSX OffscreenLayerSurface (OLS) regressions (pbuffer based) - Use pbuffer (still), don't set FBO (invisible) - OLS (only impl is JAWTWindow now) stores the attached layer handle created and attached by the GLContext implementation, so 'others' may detach it -> NewtCanvasAWT - NewtCanvasAWT.removeNotify() needs to ask the OLS to detach the layer since it's parent will be gone. - MacOSXCGLContext destroy allows a removed OLS (see above) --- make/scripts/tests.sh | 5 ++--- .../classes/jogamp/opengl/GLDrawableFactoryImpl.java | 5 +++-- .../jogamp/opengl/macosx/cgl/MacOSXCGLContext.java | 13 +++++++------ .../com/jogamp/nativewindow/awt/JAWTWindow.java | 18 +++++++++++++++--- .../media/nativewindow/OffscreenLayerSurface.java | 9 +++++++-- .../classes/com/jogamp/newt/awt/NewtCanvasAWT.java | 10 ++++++++-- 6 files changed, 42 insertions(+), 18 deletions(-) (limited to 'src/jogl/classes/jogamp/opengl') diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index af99b8e72..19297ae25 100755 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -407,10 +407,9 @@ function testawtswt() { # osx: #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingFocusTraversal01AWT $* #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingOffscreenLayer01GLCanvasAWT $* -#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingOffscreenLayer02NewtCanvasAWT $* -testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES2NEWT $* +#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingOffscreenLayer01GLCanvasAWT $* +testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingOffscreenLayer02NewtCanvasAWT $* $spath/count-edt-start.sh java-run.log diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java index 897d3fcaf..34bb8704a 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java @@ -143,9 +143,10 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { // layered surface -> Offscreen/[FBO|PBuffer] final GLCapabilities chosenCapsMod = (GLCapabilities) chosenCaps.cloneMutable(); chosenCapsMod.setOnscreen(false); - if( isFBOAvailable ) { + /* if( isFBOAvailable ) { // FIXME JAU: FBO n/a yet chosenCapsMod.setFBO(true); - } else if(canCreateGLPbuffer(adevice)) { + } else */ + if( canCreateGLPbuffer(adevice) ) { chosenCapsMod.setPBuffer(true); } else { chosenCapsMod.setFBO(false); diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java index cb79e1560..82525cfde 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java @@ -444,9 +444,10 @@ public abstract class MacOSXCGLContext extends GLContextImpl throw new RuntimeException("Anonymous drawable instance's handle not of type NSView: "+drawable.getClass().getName()+", "+drawable); } } - final NativeSurface surface = drawable.getNativeSurface(); + final NativeSurface surface = drawable.getNativeSurface(); final MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) surface.getGraphicsConfiguration(); final OffscreenLayerSurface backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(surface, true); + boolean allowIncompleteView = null != backingLayerHost; if( !allowIncompleteView && surface instanceof ProxySurface ) { allowIncompleteView = 0 != ( ProxySurface.INVISIBLE_WINDOW & ((ProxySurface)surface).getImplBitfield() ) ; @@ -519,10 +520,10 @@ public abstract class MacOSXCGLContext extends GLContextImpl texWidth = drawable.getWidth(); texHeight = drawable.getHeight(); } - nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, nsOpenGLLayerPFmt, drawable.getHandle(), fixedCaps.isBackgroundOpaque(), texWidth, texHeight); if(0>=texWidth || 0>=texHeight || !drawable.isRealized()) { throw new GLException("Drawable not realized yet or invalid texture size, texSize "+texWidth+"x"+texHeight+", "+drawable); } + nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, nsOpenGLLayerPFmt, drawable.getHandle(), fixedCaps.isBackgroundOpaque(), texWidth, texHeight); if (DEBUG) { System.err.println("NS create nsOpenGLLayer "+toHexString(nsOpenGLLayer)+", texSize "+texWidth+"x"+texHeight+", "+drawable); } @@ -545,11 +546,11 @@ public abstract class MacOSXCGLContext extends GLContextImpl System.err.println("NS destroy nsOpenGLLayer "+toHexString(nsOpenGLLayer)); } final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(surface, true); - if(null == ols) { - throw new InternalError("XXX: "+ols); + if(null != ols && ols.isSurfaceLayerAttached()) { + // still having a valid OLS attached to surface (parent OLS could have been removed) + ols.detachSurfaceLayer(); } - CGL.releaseNSOpenGLLayer(nsOpenGLLayer); - ols.detachSurfaceLayer(nsOpenGLLayer); + CGL.releaseNSOpenGLLayer(nsOpenGLLayer); CGL.deletePixelFormat(nsOpenGLLayerPFmt); nsOpenGLLayerPFmt = 0; nsOpenGLLayer = 0; diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java index cffe495f7..d4b927cf1 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java @@ -81,6 +81,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, protected long drawable; protected Rectangle bounds; protected Insets insets; + private long offscreenSurfaceLayer; private long drawable_old; @@ -106,6 +107,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, invalidate(); this.component = windowObject; this.isApplet = false; + this.offscreenSurfaceLayer = 0; } @Override @@ -196,6 +198,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, System.err.println("JAWTWindow.attachSurfaceHandle(): 0x"+Long.toHexString(layerHandle) + ", bounds "+bounds); } attachSurfaceLayerImpl(layerHandle); + offscreenSurfaceLayer = layerHandle; } finally { unlockSurface(); } @@ -206,25 +209,34 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, * {@inheritDoc} */ @Override - public final void detachSurfaceLayer(final long layerHandle) throws NativeWindowException { + public final void detachSurfaceLayer() throws NativeWindowException { if( !isOffscreenLayerSurfaceEnabled() ) { throw new java.lang.UnsupportedOperationException("Not an offscreen layer surface"); } + if( 0 == offscreenSurfaceLayer) { + throw new NativeWindowException("No offscreen layer attached: "+this); + } int lockRes = lockSurface(); if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) { throw new NativeWindowException("Could not lock (offscreen layer): "+this); } try { if(DEBUG) { - System.err.println("JAWTWindow.detachSurfaceHandle(): 0x"+Long.toHexString(layerHandle)); + System.err.println("JAWTWindow.detachSurfaceHandle(): 0x"+Long.toHexString(offscreenSurfaceLayer)); } - detachSurfaceLayerImpl(layerHandle); + detachSurfaceLayerImpl(offscreenSurfaceLayer); + offscreenSurfaceLayer = 0; } finally { unlockSurface(); } } protected abstract void detachSurfaceLayerImpl(final long layerHandle); + @Override + public final boolean isSurfaceLayerAttached() { + return 0 != offscreenSurfaceLayer; + } + // // SurfaceUpdateListener // diff --git a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java index dd36509ba..f7dbc6c27 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java @@ -42,7 +42,12 @@ public interface OffscreenLayerSurface { * Detaches a previously attached offscreen layer from this offscreen layer surface. * @see #attachSurfaceLayer(long) * @see #isOffscreenLayerSurfaceEnabled() - * @throws NativeWindowException if {@link #isOffscreenLayerSurfaceEnabled()} == false + * @throws NativeWindowException if {@link #isOffscreenLayerSurfaceEnabled()} == false + * or no surface layer is attached. */ - public void detachSurfaceLayer(final long layerHandle) throws NativeWindowException; + public void detachSurfaceLayer() throws NativeWindowException; + + /** Returns true if a surface layer is attached, otherwise false. */ + public boolean isSurfaceLayerAttached(); + } diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index 9af4a02ae..cd0e9aab6 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -42,7 +42,9 @@ import java.security.PrivilegedAction; import java.util.Set; import javax.media.nativewindow.NativeWindow; +import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.OffscreenLayerOption; +import javax.media.nativewindow.OffscreenLayerSurface; import javax.media.nativewindow.WindowClosingProtocol; import javax.swing.MenuSelectionManager; @@ -368,6 +370,10 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto if(DEBUG) { System.err.println("NewtCanvasAWT.removeNotify: "+newtChild+", from "+cont); } + final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(newtChild, true); + if(null != ols && ols.isSurfaceLayerAttached()) { + ols.detachSurfaceLayer(); + } reparentWindow(false, cont); super.removeNotify(); } @@ -413,7 +419,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto // since this it is completely covered by the newtChild (z-order). setFocusable(true); } else { - configureNewtChild(false); + configureNewtChild(false); newtChild.setVisible(false); newtChild.reparentWindow(null); if(null != jawtWindow) { @@ -445,7 +451,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto NewtFactoryAWT.destroyNativeWindow(jawtWindow); jawtWindow=null; } - newtChild.setVisible(false); + newtChild.setVisible(false); newtChild.reparentWindow(null); newtChild.destroy(); newtChild=null; -- cgit v1.2.3 From 4b5a0f6557d7152ec770bc13ad3c494449de0529 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sun, 22 Jul 2012 04:16:55 +0200 Subject: Fix Bug 606 - New AWT threading implementation breaks .. ; Fix GLAutoDrawable multi-threading w/ proper pattern (hope so) Considering code changes and remarks: 3ed491213f8f7f05d7b9866b50d764370d8ff5f6 1a91ec5c8b6fd9d9db7bc115569c369fe7b38e9b 3334a924309a9361a448d69bc707d4cce416b430 4f27bcecf7484dc041551f52a5c49e2884cb3867 It seems necessary to have - recursive locking employed for all semantic actions which changes drawable & context (and the Window resource) - to avoid deadlock, we have to ensure the locked code segment will not spawn off to another thread, or a thread holds the lock, spawns of an action requiring the lock. .. sure - other read-only methods (flags, ..) shall at least utilize a safe local copy of a volatile field if further use to produce the result is necessary. - flags like sendReshape require to be volatile to guarantee it's being processed Patch impacts: AWT/SWT GLCanvas, GLAutoDrawableBase [and it's specializations] and hopefully closes any loopholes of missing a cache hit, etc. If you review this and find optimizations, i.e. removing a lock due to semantics etc, don't hold back and discuss it, please. --- .../classes/com/jogamp/opengl/swt/GLCanvas.java | 172 ++++++----- .../javax/media/opengl/GLAutoDrawableDelegate.java | 44 ++- .../classes/javax/media/opengl/awt/GLCanvas.java | 317 +++++++++++---------- .../classes/jogamp/opengl/GLAutoDrawableBase.java | 249 +++++++++++----- .../classes/jogamp/opengl/GLDrawableHelper.java | 17 +- src/jogl/classes/jogamp/opengl/GLPbufferImpl.java | 29 +- .../classes/com/jogamp/newt/opengl/GLWindow.java | 36 +-- src/newt/classes/jogamp/newt/WindowImpl.java | 99 +++---- .../jogl/acore/TestGLAutoDrawableDelegateNEWT.java | 10 +- .../acore/TestGLContextDrawableSwitchNEWT.java | 10 +- .../jogl/acore/TestGLContextSurfaceLockNEWT.java | 92 ++++-- 11 files changed, 649 insertions(+), 426 deletions(-) (limited to 'src/jogl/classes/jogamp/opengl') diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java index 0d9d3ddf5..64ee1c1ad 100644 --- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java +++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java @@ -63,25 +63,13 @@ import org.eclipse.swt.widgets.Shell; import com.jogamp.common.GlueGenVersion; import com.jogamp.common.os.Platform; import com.jogamp.common.util.VersionUtil; +import com.jogamp.common.util.locks.LockFactory; +import com.jogamp.common.util.locks.RecursiveLock; import com.jogamp.nativewindow.swt.SWTAccessor; import com.jogamp.opengl.JoglVersion; /** * Native SWT Canvas implementing GLAutoDrawable - *

      - * FIXME: If this instance runs in multithreading mode, see {@link Threading#isSingleThreaded()} (impossible), - * proper recursive locking is required for drawable/context @ destroy and display. - * Recreation etc could pull those instances while animating! - * Simply locking before using drawable/context offthread - * would allow a deadlock situation! - *

      - *

      - * NOTE: [MT-0] Methods utilizing [volatile] drawable/context are not synchronized. - In case any of the methods are called outside of a locked state - extra care should be added. Maybe we shall expose locking facilities to the user. - However, since the user shall stick to the GLEventListener model while utilizing - GLAutoDrawable implementations, she is safe due to the implicit locked state. - *

      */ public class GLCanvas extends Canvas implements GLAutoDrawable { @@ -97,8 +85,9 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { //private static final boolean useSWTThread = ThreadingImpl.getMode() != ThreadingImpl.WORKER; /* GL Stuff */ + private final RecursiveLock lock = LockFactory.createRecursiveLock(); private final GLDrawableHelper helper = new GLDrawableHelper(); - private volatile GLDrawable drawable; // volatile avoids locking all accessors. FIXME still need to sync destroy/display + private volatile GLDrawable drawable; // volatile: avoid locking for read-only access private GLContext context; /* Native window surface */ @@ -112,7 +101,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { private final GLCapabilitiesImmutable glCapsRequested; /* Flag indicating whether an unprocessed reshape is pending. */ - private volatile boolean sendReshape; + private volatile boolean sendReshape; // volatile: maybe written by WindowManager thread w/o locking /* * Invokes init(...) on all GLEventListeners. Assumes context is current when run. @@ -141,10 +130,16 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { }; /* Action to make specified context current prior to running displayAction */ - private final Runnable makeCurrentAndDisplayAction = new Runnable() { + private final Runnable makeCurrentAndDisplayOnEDTAction = new Runnable() { @Override public void run() { - helper.invokeGL(drawable, context, displayAction, initAction); + final RecursiveLock _lock = lock; + _lock.lock(); + try { + helper.invokeGL(drawable, context, displayAction, initAction); + } finally { + _lock.unlock(); + } } }; @@ -157,10 +152,16 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { }; /* Swaps buffers, making the GLContext current first */ - private final Runnable makeCurrentAndSwapBuffersAction = new Runnable() { + private final Runnable makeCurrentAndSwapBuffersOnEDTAction = new Runnable() { @Override public void run() { - helper.invokeGL(drawable, context, swapBuffersAction, initAction); + final RecursiveLock _lock = lock; + _lock.lock(); + try { + helper.invokeGL(drawable, context, swapBuffersAction, initAction); + } finally { + _lock.unlock(); + } } }; @@ -181,16 +182,33 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { private final Runnable disposeOnEDTGLAction = new Runnable() { @Override public void run() { - helper.disposeGL(GLCanvas.this, drawable, context, postDisposeGLAction); - } - }; - - private final Runnable disposeGraphicsDeviceAction = new Runnable() { - @Override - public void run() { - if (null != device) { - device.close(); - device = null; + final RecursiveLock _lock = lock; + _lock.lock(); + try { + if (null != drawable && null != context) { + boolean animatorPaused = false; + final GLAnimatorControl animator = getAnimator(); + if (null != animator) { + animatorPaused = animator.pause(); + } + + if(context.isCreated()) { + helper.disposeGL(GLCanvas.this, drawable, context, postDisposeGLAction); + } + + if (animatorPaused) { + animator.resume(); + } + } + // SWT is owner of the device handle, not us. + // Hence close() operation is a NOP. + if (null != device) { + device.close(); + device = null; + } + SWTAccessor.setRealized(GLCanvas.this, false); // unrealize .. + } finally { + _lock.unlock(); } } }; @@ -229,7 +247,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { clientArea = GLCanvas.this.getClientArea(); - /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite) */ + /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite). + * Note: SWT is owner of the native handle, hence no closing operation will be a NOP. */ device = SWTAccessor.getDevice(this); /* Since we have no means of querying the screen index yet, assume 0. Good choice due to Xinerama alike settings anyways. */ final int screenIdx = 0; @@ -345,7 +364,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { @Override public void display() { - runInGLThread(makeCurrentAndDisplayAction); + runInGLThread(makeCurrentAndDisplayOnEDTAction); } @Override @@ -370,7 +389,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { @Override public GL getGL() { - return (null == context) ? null : context.getGL(); + final GLContext _context = context; + return (null == _context) ? null : _context.getGL(); } @Override @@ -400,27 +420,35 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { @Override public GLContext setContext(GLContext newCtx) { - final GLContext oldCtx = context; - final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); - context=(GLContextImpl)newCtx; - if(newCtxCurrent) { - context.makeCurrent(); + final RecursiveLock _lock = lock; + _lock.lock(); + try { + final GLContext oldCtx = context; + final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); + context=(GLContextImpl)newCtx; + if(newCtxCurrent) { + context.makeCurrent(); + } + return oldCtx; + } finally { + _lock.unlock(); } - return oldCtx; } @Override public void setContextCreationFlags(final int arg0) { additionalCtxCreationFlags = arg0; - if(null != context) { - context.setContextCreationFlags(additionalCtxCreationFlags); + final GLContext _context = context; + if(null != _context) { + _context.setContextCreationFlags(additionalCtxCreationFlags); } } @Override public GL setGL(final GL arg0) { - if (null != context) { - context.setGL(arg0); + final GLContext _context = context; + if (null != _context) { + _context.setGL(arg0); return arg0; } return null; @@ -428,12 +456,18 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { @Override public GLContext createContext(final GLContext shareWith) { - if(drawable != null) { - final GLContext _ctx = drawable.createContext(shareWith); - _ctx.setContextCreationFlags(additionalCtxCreationFlags); - return _ctx; + final RecursiveLock _lock = lock; + _lock.lock(); + try { + if(drawable != null) { + final GLContext _ctx = drawable.createContext(shareWith); + _ctx.setContextCreationFlags(additionalCtxCreationFlags); + return _ctx; + } + return null; + } finally { + _lock.unlock(); } - return null; } @Override @@ -452,7 +486,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { @Override public GLDrawableFactory getFactory() { - return (drawable != null) ? drawable.getFactory() : null; + final GLDrawable _drawable = drawable; + return (_drawable != null) ? _drawable.getFactory() : null; } @Override @@ -462,17 +497,20 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { @Override public long getHandle() { - return (drawable != null) ? drawable.getHandle() : 0; + final GLDrawable _drawable = drawable; + return (_drawable != null) ? _drawable.getHandle() : 0; } @Override public NativeSurface getNativeSurface() { - return (drawable != null) ? drawable.getNativeSurface() : null; + final GLDrawable _drawable = drawable; + return (_drawable != null) ? _drawable.getNativeSurface() : null; } @Override public boolean isRealized() { - return (drawable != null) ? drawable.isRealized() : false; + final GLDrawable _drawable = drawable; + return (_drawable != null) ? _drawable.isRealized() : false; } @Override @@ -482,41 +520,19 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { @Override public void swapBuffers() throws GLException { - runInGLThread(makeCurrentAndSwapBuffersAction); + runInGLThread(makeCurrentAndSwapBuffersOnEDTAction); } // FIXME: API of update() method ? @Override public void update() { - // FIXME: display(); + // FIXME: display(); ? } @Override public void dispose() { - if (null != drawable && null != context) { // drawable is volatile! - boolean animatorPaused = false; - final GLAnimatorControl animator = getAnimator(); - if (null != animator) { - // can't remove us from animator for recreational addNotify() - animatorPaused = animator.pause(); - } - - if(context.isCreated()) { - runInGLThread(disposeOnEDTGLAction); - } - - if (animatorPaused) { - animator.resume(); - } - } - final Display display = getDisplay(); - - if (display.getThread() == Thread.currentThread()) { - disposeGraphicsDeviceAction.run(); - } else { - display.syncExec(disposeGraphicsDeviceAction); - } - super.dispose(); + runInGLThread(disposeOnEDTGLAction); + super.dispose(); } /** diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java index 1f6166719..76959f3f4 100644 --- a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java +++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java @@ -67,18 +67,18 @@ public class GLAutoDrawableDelegate extends GLAutoDrawableBase { } // - // make protected methods accessible + // expose default methods // - public void defaultWindowRepaintOp() { + public final void windowRepaintOp() { super.defaultWindowRepaintOp(); } - public void defaultWindowResizedOp() { + public final void windowResizedOp() { super.defaultWindowResizedOp(); } - public void defaultWindowDestroyNotifyOp() { + public final void windowDestroyNotifyOp() { super.defaultWindowDestroyNotifyOp(); } @@ -89,6 +89,9 @@ public class GLAutoDrawableDelegate extends GLAutoDrawableBase { private final RecursiveLock lock = LockFactory.createRecursiveLock(); // instance wide lock private final Object upstreamWidget; + @Override + protected final RecursiveLock getLock() { return lock; } + @Override public final Object getUpstreamWidget() { return upstreamWidget; @@ -97,39 +100,21 @@ public class GLAutoDrawableDelegate extends GLAutoDrawableBase { /** * {@inheritDoc} *

      - * This implementation calls {@link #defaultDestroyOp()}. + * This implementation calls {@link #defaultDestroy()}. *

      *

      * User still needs to destroy the upstream window, which details are hidden from this aspect. + * This can be performed by overriding {@link #destroyImplInLock()}. *

      */ @Override - public void destroy() { - lock.lock(); - try { - defaultDestroyOp(); - } finally { - lock.unlock(); - } + public final void destroy() { + defaultDestroy(); } @Override public void display() { - if( sendDestroy ) { - sendDestroy=false; - destroy(); - return; - } - - lock.lock(); // sync: context/drawable could been recreated/destroyed while animating - try { - if( null != drawable && drawable.isRealized() && null != context ) { - // surface is locked/unlocked implicit by context's makeCurrent/release - helper.invokeGL(drawable, context, defaultDisplayAction, defaultInitAction); - } - } finally { - lock.unlock(); - } + defaultDisplay(); } // @@ -145,4 +130,9 @@ public class GLAutoDrawableDelegate extends GLAutoDrawableBase { public final void setRealized(boolean realized) { } + @Override + public final void swapBuffers() throws GLException { + defaultSwapBuffers(); + } + } diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index c2e36ef9b..694a081b8 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -84,6 +84,8 @@ import javax.media.opengl.Threading; import com.jogamp.common.GlueGenVersion; import com.jogamp.common.util.VersionUtil; +import com.jogamp.common.util.locks.LockFactory; +import com.jogamp.common.util.locks.RecursiveLock; import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration; import com.jogamp.nativewindow.awt.AWTGraphicsDevice; import com.jogamp.nativewindow.awt.AWTGraphicsScreen; @@ -132,20 +134,6 @@ import jogamp.opengl.GLDrawableHelper; *
        *
      • sun.awt.noerasebackground=true
      • *
      - *

      - * FIXME: If this instance runs in multithreading mode, see {@link Threading#isSingleThreaded()} (default: single-thread), - * proper recursive locking is required for drawable/context @ destroy and display. - * Recreation etc could pull those instances while animating! - * Simply locking before using drawable/context offthread - * would allow a deadlock situation! - *

      - *

      - * NOTE: [MT-0] Methods utilizing [volatile] drawable/context are not synchronized. - In case any of the methods are called outside of a locked state - extra care should be added. Maybe we shall expose locking facilities to the user. - However, since the user shall stick to the GLEventListener model while utilizing - GLAutoDrawable implementations, she is safe due to the implicit locked state. - *

      */ @SuppressWarnings("serial") @@ -153,11 +141,12 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing private static final boolean DEBUG = Debug.debug("GLCanvas"); + private final RecursiveLock lock = LockFactory.createRecursiveLock(); private final GLDrawableHelper helper = new GLDrawableHelper(); private AWTGraphicsConfiguration awtConfig; - private volatile GLDrawable drawable; // volatile avoids locking all accessors. FIXME still need to sync destroy/display + private volatile GLDrawable drawable; // volatile: avoid locking for read-only access private GLContextImpl context; - private boolean sendReshape = false; + private volatile boolean sendReshape = false; // volatile: maybe written by EDT w/o locking // copy of the cstr args, mainly for recreation private GLCapabilitiesImmutable capsReqUser; @@ -278,8 +267,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing @Override public final boolean isOffscreenLayerSurfaceEnabled() { - if(null != drawable) { - return ((JAWTWindow)drawable.getNativeSurface()).isOffscreenLayerSurfaceEnabled(); + final GLDrawable _drawable = drawable; + if(null != _drawable) { + return ((JAWTWindow)_drawable.getNativeSurface()).isOffscreenLayerSurfaceEnabled(); } return false; } @@ -398,12 +388,18 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing @Override public GLContext createContext(final GLContext shareWith) { - if(drawable != null) { - final GLContext _ctx = drawable.createContext(shareWith); - _ctx.setContextCreationFlags(additionalCtxCreationFlags); - return _ctx; + final RecursiveLock _lock = lock; + _lock.lock(); + try { + if(drawable != null) { + final GLContext _ctx = drawable.createContext(shareWith); + _ctx.setContextCreationFlags(additionalCtxCreationFlags); + return _ctx; + } + return null; + } finally { + _lock.unlock(); } - return null; } @Override @@ -412,7 +408,8 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing @Override public boolean isRealized() { - return (null != drawable) ? drawable.isRealized() : false; + final GLDrawable _drawable = drawable; + return ( null != _drawable ) ? _drawable.isRealized() : false; } @Override @@ -427,50 +424,13 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing @Override public void display() { - if( !validateGLDrawable() ) { - if(DEBUG) { - System.err.println(getThreadName()+": Info: GLCanvas display - skipped GL render, drawable not valid yet"); - } - return; // not yet available .. - } Threading.invoke(true, displayOnEDTAction, getTreeLock()); - awtWindowClosingProtocol.addClosingListenerOneShot(); } private void dispose(boolean regenerate) { - final GLAnimatorControl animator = getAnimator(); - if(DEBUG) { - System.err.println(getThreadName()+": Info: dispose("+regenerate+") - START, hasContext " + - (null!=context) + ", hasDrawable " + (null!=drawable)+", "+animator); - Thread.dumpStack(); - } - - if(null!=drawable && null!=context) { // drawable is volatile! - boolean animatorPaused = false; - if(null!=animator) { - // can't remove us from animator for recreational addNotify() - animatorPaused = animator.pause(); - } - - disposeRegenerate=regenerate; - - if(context.isCreated()) { - Threading.invoke(true, disposeOnEDTAction, getTreeLock()); - } - - if(animatorPaused) { - animator.resume(); - } - } - - if(!regenerate) { - disposeAbstractGraphicsDevice(); - } - - if(DEBUG) { - System.err.println(getThreadName()+": dispose("+regenerate+") - END, "+animator); - } + disposeRegenerate=regenerate; + Threading.invoke(true, disposeOnEDTAction, getTreeLock()); } /** @@ -530,43 +490,49 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing @SuppressWarnings("deprecation") @Override public void addNotify() { - if(DEBUG) { - System.err.println(getThreadName()+": Info: addNotify - start, bounds: "+this.getBounds()); - Thread.dumpStack(); - } - - /** - * 'super.addNotify()' determines the GraphicsConfiguration, - * while calling this class's overriden 'getGraphicsConfiguration()' method - * after which it creates the native peer. - * Hence we have to set the 'awtConfig' before since it's GraphicsConfiguration - * is being used in getGraphicsConfiguration(). - * This code order also allows recreation, ie re-adding the GLCanvas. - */ - awtConfig = chooseGraphicsConfiguration(capsReqUser, capsReqUser, chooser, device); - if(null==awtConfig) { - throw new GLException("Error: NULL AWTGraphicsConfiguration"); - } - - // before native peer is valid: X11 - disableBackgroundErase(); - - // issues getGraphicsConfiguration() and creates the native peer - super.addNotify(); - - // after native peer is valid: Windows - disableBackgroundErase(); - - if (!Beans.isDesignTime()) { - createDrawableAndContext(); - } - - // init drawable by paint/display makes the init sequence more equal - // for all launch flavors (applet/javaws/..) - // validateGLDrawable(); - - if(DEBUG) { - System.err.println(getThreadName()+": Info: addNotify - end: peer: "+getPeer()); + final RecursiveLock _lock = lock; + _lock.lock(); + try { + if(DEBUG) { + System.err.println(getThreadName()+": Info: addNotify - start, bounds: "+this.getBounds()); + Thread.dumpStack(); + } + + /** + * 'super.addNotify()' determines the GraphicsConfiguration, + * while calling this class's overriden 'getGraphicsConfiguration()' method + * after which it creates the native peer. + * Hence we have to set the 'awtConfig' before since it's GraphicsConfiguration + * is being used in getGraphicsConfiguration(). + * This code order also allows recreation, ie re-adding the GLCanvas. + */ + awtConfig = chooseGraphicsConfiguration(capsReqUser, capsReqUser, chooser, device); + if(null==awtConfig) { + throw new GLException("Error: NULL AWTGraphicsConfiguration"); + } + + // before native peer is valid: X11 + disableBackgroundErase(); + + // issues getGraphicsConfiguration() and creates the native peer + super.addNotify(); + + // after native peer is valid: Windows + disableBackgroundErase(); + + if (!Beans.isDesignTime()) { + createDrawableAndContext(); + } + + // init drawable by paint/display makes the init sequence more equal + // for all launch flavors (applet/javaws/..) + // validateGLDrawable(); + + if(DEBUG) { + System.err.println(getThreadName()+": Info: addNotify - end: peer: "+getPeer()); + } + } finally { + _lock.unlock(); } } @@ -585,23 +551,24 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing } private boolean validateGLDrawable() { - boolean realized = false; - if (!Beans.isDesignTime()) { - if ( null != drawable ) { // OK: drawable is volatile - realized = drawable.isRealized(); - if ( !realized && 0 < drawable.getWidth() * drawable.getHeight() ) { - // make sure drawable realization happens on AWT EDT, due to AWTTree lock - AWTEDTExecutor.singleton.invoke(true, setRealizedOnEDTAction); - realized = true; - sendReshape=true; // ensure a reshape is being send .. - if(DEBUG) { - System.err.println(getThreadName()+": Realized Drawable: "+drawable.toString()); - Thread.dumpStack(); - } + final GLDrawable _drawable = drawable; + if ( null != _drawable ) { + if( _drawable.isRealized() ) { + return true; + } + if (!Beans.isDesignTime() && + 0 < _drawable.getWidth() * _drawable.getHeight() ) { + // make sure drawable realization happens on AWT EDT, due to AWTTree lock + AWTEDTExecutor.singleton.invoke(true, setRealizedOnEDTAction); + sendReshape=true; // ensure a reshape is being send .. + if(DEBUG) { + System.err.println(getThreadName()+": Realized Drawable: "+_drawable.toString()); + Thread.dumpStack(); } + return true; } } - return realized; + return false; } private Runnable setRealizedOnEDTAction = new Runnable() { @Override @@ -633,9 +600,6 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing try { dispose(false); } finally { - context=null; - drawable=null; - awtConfig=null; super.removeNotify(); } } @@ -655,7 +619,8 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing @Override public void reshape(int x, int y, int width, int height) { super.reshape(x, y, width, height); - if(null != drawable && drawable.isRealized() && !drawable.getChosenGLCapabilities().isOnscreen()) { + final GLDrawable _drawable = drawable; + if(null != _drawable && _drawable.isRealized() && !_drawable.getChosenGLCapabilities().isOnscreen()) { dispose(true); } else { sendReshape = true; @@ -710,13 +675,19 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing @Override public GLContext setContext(GLContext newCtx) { - final GLContext oldCtx = context; - final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); - context=(GLContextImpl)newCtx; - if(newCtxCurrent) { - context.makeCurrent(); + final RecursiveLock _lock = lock; + _lock.lock(); + try { + final GLContext oldCtx = context; + final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); + context=(GLContextImpl)newCtx; + if(newCtxCurrent) { + context.makeCurrent(); + } + return oldCtx; + } finally { + _lock.unlock(); } - return oldCtx; } @Override @@ -729,15 +700,15 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing if (Beans.isDesignTime()) { return null; } - GLContext ctx = getContext(); - return (ctx == null) ? null : ctx.getGL(); + final GLContext _context = context; + return (_context == null) ? null : _context.getGL(); } @Override public GL setGL(GL gl) { - GLContext ctx = getContext(); - if (ctx != null) { - ctx.setGL(gl); + final GLContext _context = context; + if (_context != null) { + _context.setGL(gl); return gl; } return null; @@ -762,8 +733,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing @Override public void setContextCreationFlags(int flags) { additionalCtxCreationFlags = flags; - if(null != context) { - context.setContextCreationFlags(additionalCtxCreationFlags); + final GLContext _context = context; + if(null != _context) { + _context.setContextCreationFlags(additionalCtxCreationFlags); } } @@ -796,26 +768,30 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing @Override public NativeSurface getNativeSurface() { - return (null != drawable) ? drawable.getNativeSurface() : null; + final GLDrawable _drawable = drawable; + return (null != _drawable) ? _drawable.getNativeSurface() : null; } @Override public long getHandle() { - return (null != drawable) ? drawable.getHandle() : 0; + final GLDrawable _drawable = drawable; + return (null != _drawable) ? _drawable.getHandle() : 0; } @Override public GLDrawableFactory getFactory() { - return (null != drawable) ? drawable.getFactory() : null; + final GLDrawable _drawable = drawable; + return (null != _drawable) ? _drawable.getFactory() : null; } @Override public String toString() { - final int dw = (null!=drawable) ? drawable.getWidth() : -1; - final int dh = (null!=drawable) ? drawable.getHeight() : -1; + final GLDrawable _drawable = drawable; + final int dw = (null!=_drawable) ? _drawable.getWidth() : -1; + final int dh = (null!=_drawable) ? _drawable.getHeight() : -1; return "AWT-GLCanvas[Realized "+isRealized()+ - ",\n\t"+((null!=drawable)?drawable.getClass().getName():"null-drawable")+ + ",\n\t"+((null!=_drawable)?_drawable.getClass().getName():"null-drawable")+ ",\n\tFactory "+getFactory()+ ",\n\thandle 0x"+Long.toHexString(getHandle())+ ",\n\tDrawable size "+dw+"x"+dh+ @@ -829,7 +805,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing // private boolean disposeRegenerate; - private final Runnable postDisposeAction = new Runnable() { + private final Runnable postDisposeOnEDTAction = new Runnable() { @Override public void run() { context=null; @@ -859,7 +835,47 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing private final Runnable disposeOnEDTAction = new Runnable() { @Override public void run() { - helper.disposeGL(GLCanvas.this, drawable, context, postDisposeAction); + final RecursiveLock _lock = lock; + _lock.lock(); + try { + final GLAnimatorControl animator = getAnimator(); + + if(DEBUG) { + System.err.println(getThreadName()+": Info: dispose("+disposeRegenerate+") - START, hasContext " + + (null!=context) + ", hasDrawable " + (null!=drawable)+", "+animator); + Thread.dumpStack(); + } + + if(null!=drawable && null!=context) { + boolean animatorPaused = false; + if(null!=animator) { + // can't remove us from animator for recreational addNotify() + animatorPaused = animator.pause(); + } + + if(context.isCreated()) { + helper.disposeGL(GLCanvas.this, drawable, context, postDisposeOnEDTAction); + } + + if(animatorPaused) { + animator.resume(); + } + } + + if(!disposeRegenerate) { + if(null != awtConfig) { + disposeAbstractGraphicsDevice(); + } + awtConfig=null; + } + + if(DEBUG) { + System.err.println(getThreadName()+": dispose("+disposeRegenerate+") - END, "+animator); + } + + } finally { + _lock.unlock(); + } } }; @@ -879,7 +895,6 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing if(DEBUG) { System.err.println(getThreadName()+": GLCanvas.dispose(false): closed GraphicsDevice: "+adeviceMsg+", result: "+closed); } - awtConfig=null; } } }; @@ -890,7 +905,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing * * @see #chooseGraphicsConfiguration(javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, java.awt.GraphicsDevice) */ - void disposeAbstractGraphicsDevice() { + private void disposeAbstractGraphicsDevice() { if( EventQueue.isDispatchThread() || Thread.holdsLock(getTreeLock()) ) { disposeAbstractGraphicsDeviceAction.run(); } else { @@ -941,14 +956,30 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing private final Runnable displayOnEDTAction = new Runnable() { @Override public void run() { - helper.invokeGL(drawable, context, displayAction, initAction); + final RecursiveLock _lock = lock; + _lock.lock(); + try { + if( validateGLDrawable() ) { + helper.invokeGL(drawable, context, displayAction, initAction); + } else if(DEBUG) { + System.err.println(getThreadName()+": Info: GLCanvas display - skipped GL render, drawable not valid yet"); + } + } finally { + _lock.unlock(); + } } }; private final Runnable swapBuffersOnEDTAction = new Runnable() { @Override public void run() { - helper.invokeGL(drawable, context, swapBuffersAction, initAction); + final RecursiveLock _lock = lock; + _lock.lock(); + try { + helper.invokeGL(drawable, context, swapBuffersAction, initAction); + } finally { + _lock.unlock(); + } } }; diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java index 5c6d7446a..fe6d0fd76 100644 --- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java +++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java @@ -46,6 +46,7 @@ import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; import javax.media.opengl.GLRunnable; +import com.jogamp.common.util.locks.RecursiveLock; import com.jogamp.opengl.util.Animator; @@ -63,11 +64,11 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { protected final GLDrawableHelper helper = new GLDrawableHelper(); protected final FPSCounterImpl fpsCounter = new FPSCounterImpl(); - protected GLDrawableImpl drawable; + protected volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access protected GLContextImpl context; protected int additionalCtxCreationFlags = 0; - protected boolean sendReshape = false; - protected boolean sendDestroy = false; + protected volatile boolean sendReshape = false; // volatile: maybe written by WindowManager thread w/o locking + protected volatile boolean sendDestroy = false; // volatile: maybe written by WindowManager thread w/o locking public GLAutoDrawableBase(GLDrawableImpl drawable, GLContextImpl context) { this.drawable = drawable; @@ -75,31 +76,47 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { resetFPSCounter(); } + protected abstract RecursiveLock getLock(); + /** Returns the delegated GLDrawable */ public final GLDrawable getDelegatedDrawable() { return drawable; } /** Default implementation to handle repaint events from the windowing system */ - protected void defaultWindowRepaintOp() { - if( null != drawable && drawable.isRealized() ) { - if( !drawable.getNativeSurface().isSurfaceLockedByOtherThread() && !helper.isAnimatorAnimating() ) { + protected final void defaultWindowRepaintOp() { + final GLDrawable _drawable = drawable; + if( null != _drawable && _drawable.isRealized() ) { + if( !_drawable.getNativeSurface().isSurfaceLockedByOtherThread() && !helper.isAnimatorAnimating() ) { display(); } - } + } } /** Default implementation to handle resize events from the windowing system */ - protected void defaultWindowResizedOp() { - if( null!=drawable ) { + protected final void defaultWindowResizedOp() { + final GLDrawable _drawable = drawable; + if( null!=_drawable ) { if(DEBUG) { System.err.println("GLAutoDrawableBase.sizeChanged: ("+Thread.currentThread().getName()+"): "+getWidth()+"x"+getHeight()+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); } - sendReshape = true; - defaultWindowRepaintOp(); + sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock + if( _drawable.isRealized() ) { + if( !_drawable.getNativeSurface().isSurfaceLockedByOtherThread() && !helper.isAnimatorAnimating() ) { + display(); + } + } } } - /** Default implementation to handle destroy notifications from the windowing system */ - protected void defaultWindowDestroyNotifyOp() { + /** + * Default implementation to handle destroy notifications from the windowing system. + * + *

      + * If the {@link NativeSurface} does not implement {@link WindowClosingProtocol} + * or {@link WindowClosingMode#DISPOSE_ON_CLOSE} is enabled (default), + * {@link #defaultDestroy()} is being called. + *

      + */ + protected final void defaultWindowDestroyNotifyOp() { final NativeSurface ns = getNativeSurface(); final boolean shallClose; if(ns instanceof WindowClosingProtocol) { @@ -108,27 +125,66 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { shallClose = true; } if( shallClose ) { - // Is an animator thread perform rendering? - if (helper.isExternalAnimatorRunning()) { - // Pause animations before initiating safe destroy. - final GLAnimatorControl ctrl = helper.getAnimator(); - final boolean isPaused = ctrl.pause(); - destroy(); - if(isPaused) { - ctrl.resume(); - } - } else if (null != ns && ns.isSurfaceLockedByOtherThread()) { - // surface is locked by another thread - // Flag that destroy should be performed on the next - // attempt to display. - sendDestroy = true; - } else { - // Without an external thread animating or locking the - // surface, we are safe. - destroy (); - } + destroyAvoidAwareOfLocking(); } } + + /** + * Calls {@link #destroy()} + * directly if the following requirements are met: + *
        + *
      • An {@link GLAnimatorControl} is bound (see {@link #getAnimator()}) and running on another thread. + * Here we pause the animation while issuing the destruction.
      • + *
      • Surface is not locked by another thread (considered anonymous).
      • + *
      + *

      + * Otherwise destroy is being flagged to be called within the next + * call of display(). + *

      + *

      + * This method is being used to avoid deadlock if + * destruction is desired by other threads, e.g. the window manager. + *

      + * @see #defaultWindowDestroyNotifyOp() + * @see #defaultDisplay() + */ + protected final void destroyAvoidAwareOfLocking() { + final NativeSurface ns = getNativeSurface(); + + final GLAnimatorControl ctrl = helper.getAnimator(); + + // Is an animator thread perform rendering? + if ( helper.isAnimatorRunningOnOtherThread() ) { + // Pause animations before initiating safe destroy. + final boolean isPaused = ctrl.pause(); + destroy(); + if(isPaused) { + ctrl.resume(); + } + } else if (null != ns && ns.isSurfaceLockedByOtherThread()) { + // surface is locked by another thread + // Flag that destroy should be performed on the next + // attempt to display. + sendDestroy = true; // async, but avoiding deadlock + } else { + // Without an external thread animating or locking the + // surface, we are safe. + destroy(); + } + } + + /** + * Calls {@link #destroyImplInLock()} while claiming the lock. + */ + protected final void defaultDestroy() { + final RecursiveLock lock = getLock(); + lock.lock(); + try { + destroyImplInLock(); + } finally { + lock.unlock(); + } + } /** * Default implementation to destroys the drawable and context of this GLAutoDrawable: @@ -137,24 +193,42 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { *
    • destroys the GLContext, if valid
    • *
    • destroys the GLDrawable, if valid
    • *
    + *

    Method assumes the lock is being hold.

    + *

    Override it to extend it to destroy your resources, i.e. the actual window. + * In such case call super.destroyImplInLock first.

    */ - protected void defaultDestroyOp() { - if( null != drawable && drawable.isRealized() ) { - if( null != context && context.isCreated() ) { + protected void destroyImplInLock() { + final GLContext _context = context; + final GLDrawable _drawable = drawable; + if( null != _drawable && _drawable.isRealized() ) { + if( null != _context && _context.isCreated() ) { // Catch dispose GLExceptions by GLEventListener, just 'print' them // so we can continue with the destruction. try { - helper.disposeGL(this, drawable, context, null); + helper.disposeGL(this, _drawable, _context, null); } catch (GLException gle) { gle.printStackTrace(); } } - drawable.setRealized(false); + _drawable.setRealized(false); } context = null; drawable = null; } + public final void defaultSwapBuffers() throws GLException { + final RecursiveLock _lock = getLock(); + _lock.lock(); + try { + if(drawable!=null && context != null) { + drawable.swapBuffers(); + helper.invokeGL(drawable, context, defaultSwapAction, defaultInitAction); + } + } finally { + _lock.unlock(); + } + } + // // GLAutoDrawable // @@ -179,6 +253,30 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { fpsCounter.tickFPS(); } }; + protected final void defaultDisplay() { + if( sendDestroy ) { + sendDestroy=false; + destroy(); + return; + } + final RecursiveLock _lock = getLock(); + _lock.lock(); + try { + if( null != context ) { + // surface is locked/unlocked implicit by context's makeCurrent/release + helper.invokeGL(drawable, context, defaultDisplayAction, defaultInitAction); + } + } finally { + _lock.unlock(); + } + } + + protected final Runnable defaultSwapAction = new Runnable() { + @Override + public final void run() { + drawable.swapBuffers(); + } } ; + @Override public final GLContext getContext() { return context; @@ -186,27 +284,35 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { @Override public final GLContext setContext(GLContext newCtx) { - final GLContext oldCtx = context; - final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); - context=(GLContextImpl)newCtx; - if(newCtxCurrent) { - context.makeCurrent(); + final RecursiveLock lock = getLock(); + lock.lock(); + try { + final GLContext oldCtx = context; + final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); + context=(GLContextImpl)newCtx; + if(newCtxCurrent) { + context.makeCurrent(); + } + return oldCtx; + } finally { + lock.unlock(); } - return oldCtx; } @Override public final GL getGL() { - if (context == null) { + final GLContext _context = context; + if (_context == null) { return null; } - return context.getGL(); + return _context.getGL(); } @Override public final GL setGL(GL gl) { - if (context != null) { - context.setGL(gl); + final GLContext _context = context; + if (_context != null) { + _context.setGL(gl); return gl; } return null; @@ -261,8 +367,9 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { @Override public final void setContextCreationFlags(int flags) { additionalCtxCreationFlags = flags; - if(null != context) { - context.setContextCreationFlags(additionalCtxCreationFlags); + final GLContext _context = context; + if(null != _context) { + _context.setContextCreationFlags(additionalCtxCreationFlags); } } @@ -331,27 +438,36 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { @Override public final GLContext createContext(final GLContext shareWith) { - if(drawable != null) { - final GLContext _ctx = drawable.createContext(shareWith); - _ctx.setContextCreationFlags(additionalCtxCreationFlags); - return _ctx; + final RecursiveLock lock = getLock(); + lock.lock(); + try { + if(drawable != null) { + final GLContext _ctx = drawable.createContext(shareWith); + _ctx.setContextCreationFlags(additionalCtxCreationFlags); + return _ctx; + } + return null; + } finally { + lock.unlock(); } - return null; } @Override public final boolean isRealized() { - return null != drawable ? drawable.isRealized() : false; + final GLDrawable _drawable = drawable; + return null != _drawable ? _drawable.isRealized() : false; } @Override public int getWidth() { - return null != drawable ? drawable.getWidth() : 0; + final GLDrawable _drawable = drawable; + return null != _drawable ? _drawable.getWidth() : 0; } @Override public int getHeight() { - return null != drawable ? drawable.getHeight() : 0; + final GLDrawable _drawable = drawable; + return null != _drawable ? _drawable.getHeight() : 0; } /** @@ -373,30 +489,27 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { return helper.getSkipContextReleaseThread(); } - @Override - public final void swapBuffers() throws GLException { - if(drawable!=null && context != null) { - drawable.swapBuffers(); - } - } - @Override public final GLCapabilitiesImmutable getChosenGLCapabilities() { - return null != drawable ? drawable.getChosenGLCapabilities() : null; + final GLDrawable _drawable = drawable; + return null != _drawable ? _drawable.getChosenGLCapabilities() : null; } @Override public final GLProfile getGLProfile() { - return null != drawable ? drawable.getGLProfile() : null; + final GLDrawable _drawable = drawable; + return null != _drawable ? _drawable.getGLProfile() : null; } @Override public final NativeSurface getNativeSurface() { - return null != drawable ? drawable.getNativeSurface() : null; + final GLDrawable _drawable = drawable; + return null != _drawable ? _drawable.getNativeSurface() : null; } @Override public final long getHandle() { - return null != drawable ? drawable.getHandle() : 0; + final GLDrawable _drawable = drawable; + return null != _drawable ? _drawable.getHandle() : 0; } } diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java index 0c01aa676..090c5fe69 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java @@ -189,8 +189,9 @@ public class GLDrawableHelper { */ public final void dispose(GLAutoDrawable drawable) { synchronized(listenersLock) { - for (int i=0; i < listeners.size(); i++) { - listeners.get(i).dispose(drawable); + final ArrayList _listeners = listeners; + for (int i=0; i < _listeners.size(); i++) { + _listeners.get(i).dispose(drawable); } } } @@ -209,8 +210,9 @@ public class GLDrawableHelper { /** The default init action to be called once after ctx is being created @ 1st makeCurrent(). */ public final void init(GLAutoDrawable drawable) { synchronized(listenersLock) { - for (int i=0; i < listeners.size(); i++) { - final GLEventListener listener = listeners.get(i) ; + final ArrayList _listeners = listeners; + for (int i=0; i < _listeners.size(); i++) { + final GLEventListener listener = _listeners.get(i) ; // If make current ctx, invoked by invokGL(..), results in a new ctx, init gets called. // This may happen not just for initial setup, but for ctx recreation due to resource change (drawable/window), @@ -232,8 +234,9 @@ public class GLDrawableHelper { } private final void displayImpl(GLAutoDrawable drawable) { synchronized(listenersLock) { - for (int i=0; i < listeners.size(); i++) { - final GLEventListener listener = listeners.get(i) ; + final ArrayList _listeners = listeners; + for (int i=0; i < _listeners.size(); i++) { + final GLEventListener listener = _listeners.get(i) ; // GLEventListener may need to be init, // in case this one is added after the realization of the GLAutoDrawable init( listener, drawable, true /* sendReshape */) ; @@ -324,7 +327,7 @@ public class GLDrawableHelper { } } - public final boolean isExternalAnimatorRunning() { + public final boolean isAnimatorRunningOnOtherThread() { return ( null != animatorCtrl ) ? animatorCtrl.isStarted() && animatorCtrl.getThread() != Thread.currentThread() : false ; } diff --git a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java index bbc28e283..6b64120fe 100644 --- a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java @@ -42,10 +42,14 @@ package jogamp.opengl; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLPbuffer; +import com.jogamp.common.util.locks.LockFactory; +import com.jogamp.common.util.locks.RecursiveLock; + /** Platform-independent class exposing pbuffer functionality to applications. This class is not exposed in the public API as it would probably add no value; however it implements the GLDrawable @@ -101,7 +105,7 @@ public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer { // // GLDrawable delegation // - + @Override public final void setRealized(boolean realized) { } @@ -109,6 +113,10 @@ public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer { // // GLAutoDrawable completion // + private final RecursiveLock lock = LockFactory.createRecursiveLock(); // instance wide lock + + @Override + protected final RecursiveLock getLock() { return lock; } @Override public final Object getUpstreamWidget() { @@ -117,7 +125,7 @@ public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer { @Override public void destroy() { - defaultDestroyOp(); + defaultDestroy(); } @Override @@ -126,12 +134,23 @@ public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer { } @Override - public void display() { - if( null != drawable && drawable.isRealized() && null != context ) { - helper.invokeGL(drawable, context, defaultDisplayAction, initAction); + public final void display() { + final RecursiveLock _lock = lock; + _lock.lock(); // sync: context/drawable could been recreated/destroyed while animating + try { + if( null != context ) { + helper.invokeGL(drawable, context, defaultDisplayAction, initAction); + } + } finally { + _lock.unlock(); } } + @Override + public final void swapBuffers() throws GLException { + defaultSwapBuffers(); + } + //---------------------------------------------------------------------- // Internals only below this point // diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index 32d44502f..2205aec8e 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -53,6 +53,7 @@ import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; import jogamp.newt.WindowImpl; @@ -62,6 +63,7 @@ import jogamp.opengl.GLDrawableImpl; import com.jogamp.common.GlueGenVersion; import com.jogamp.common.util.VersionUtil; +import com.jogamp.common.util.locks.RecursiveLock; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Screen; import com.jogamp.newt.Window; @@ -87,13 +89,6 @@ import com.jogamp.opengl.JoglVersion; * you can inject {@link javax.media.opengl.GLRunnable} objects * via {@link #invoke(boolean, javax.media.opengl.GLRunnable)} to the OpenGL command stream.
    *

    - *

    - * NOTE: [MT-0] Methods utilizing [volatile] drawable/context are not synchronized. - In case any of the methods are called outside of a locked state - extra care should be added. Maybe we shall expose locking facilities to the user. - However, since the user shall stick to the GLEventListener model while utilizing - GLAutoDrawable implementations, she is safe due to the implicit locked state. - *

    */ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Window, NEWTEventConsumer, FPSCounter { private final WindowImpl window; @@ -437,7 +432,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind //e1.printStackTrace(); } - defaultDestroyOp(); + destroyImplInLock(); if(Window.DEBUG_IMPLEMENTATION) { System.err.println("GLWindow.destroy() "+WindowImpl.getThreadName()+", fin"); @@ -515,6 +510,11 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind private GLContext sharedContext = null; + @Override + protected final RecursiveLock getLock() { + return window.getLock(); + } + /** * Specifies an {@link javax.media.opengl.GLContext OpenGL context} to share with.
    * At native creation, {@link #setVisible(boolean) setVisible(true)}, @@ -537,19 +537,18 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind return; } - window.lockWindow(); // sync: context/drawable could have been recreated/destroyed while animating + final RecursiveLock lock = window.getLock(); + lock.lock(); // sync: context/drawable could have been recreated/destroyed while animating try { - if( null == context && 0 display + setVisible(true); } } finally { - window.unlockWindow(); + lock.unlock(); } } @@ -559,7 +558,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind private GLDrawableFactory factory; @Override - public GLDrawableFactory getFactory() { + public final GLDrawableFactory getFactory() { return factory; } @@ -567,6 +566,11 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind public final void setRealized(boolean realized) { } + @Override + public final void swapBuffers() throws GLException { + defaultSwapBuffers(); + } + //---------------------------------------------------------------------- // NEWTEventConsumer // diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index 002144b2f..b12e42680 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -564,9 +564,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer @Override public final int lockSurface() throws NativeWindowException, RuntimeException { - windowLock.lock(); - surfaceLock.lock(); - int res = surfaceLock.getHoldCount() == 1 ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ? + final RecursiveLock _wlock = windowLock; + final RecursiveLock _slock = surfaceLock; + _wlock.lock(); + _slock.lock(); + int res = _slock.getHoldCount() == 1 ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ? if ( LOCK_SURFACE_NOT_READY == res ) { try { @@ -583,8 +585,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } finally { if (LOCK_SURFACE_NOT_READY >= res) { - surfaceLock.unlock(); - windowLock.unlock(); + _slock.unlock(); + _wlock.unlock(); } } } @@ -593,10 +595,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer @Override public final void unlockSurface() { - surfaceLock.validateLocked(); - windowLock.validateLocked(); + final RecursiveLock _slock = surfaceLock; + final RecursiveLock _wlock = windowLock; + _slock.validateLocked(); + _wlock.validateLocked(); - if (surfaceLock.getHoldCount() == 1) { + if (_slock.getHoldCount() == 1) { final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice(); try { unlockSurfaceImpl(); @@ -604,8 +608,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer adevice.unlock(); } } - surfaceLock.unlock(); - windowLock.unlock(); + _slock.unlock(); + _wlock.unlock(); } @Override @@ -618,21 +622,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer return surfaceLock.getOwner(); } - public final void lockWindow() { - windowLock.lock(); - } - public final void unlockWindow() { - windowLock.unlock(); + public final RecursiveLock getLock() { + return windowLock; } - public final boolean isWindowLockedByOtherThread() { - return windowLock.isLockedByOtherThread(); - } - - public final Thread getWindowLockOwner() { - return windowLock.getOwner(); - } - public long getSurfaceHandle() { return windowHandle; // default: return window handle } @@ -670,11 +663,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer public Point getLocationOnScreen(Point storage) { if(isNativeValid()) { Point d; - windowLock.lock(); + final RecursiveLock _lock = windowLock; + _lock.lock(); try { d = getLocationOnScreenImpl(0, 0); } finally { - windowLock.unlock(); + _lock.unlock(); } if(null!=d) { if(null!=storage) { @@ -717,7 +711,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer boolean nativeWindowCreated = false; boolean madeVisible = false; - windowLock.lock(); + final RecursiveLock _lock = windowLock; + _lock.lock(); try { if(null!=lifecycleHook) { lifecycleHook.resetCounter(); @@ -739,7 +734,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer madeVisible = nativeWindowCreated; } // always flag visible, allowing a retry .. - WindowImpl.this.visible = true; + WindowImpl.this.visible = true; } else if(WindowImpl.this.visible != visible) { if(isNativeValid()) { setVisibleImpl(visible, getX(), getY(), getWidth(), getHeight()); @@ -766,7 +761,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer System.err.println("Window setVisible: END ("+getThreadName()+") "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+WindowImpl.this.visible+", nativeWindowCreated: "+nativeWindowCreated+", madeVisible: "+madeVisible); } } finally { - windowLock.unlock(); + _lock.unlock(); } if( nativeWindowCreated || madeVisible ) { sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener @@ -801,7 +796,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer public final void run() { boolean recreate = false; - windowLock.lock(); + final RecursiveLock _lock = windowLock; + _lock.lock(); try { if ( !isFullscreen() && ( getWidth() != width || getHeight() != height ) ) { recreate = isNativeValid() && !getGraphicsConfiguration().getChosenCapabilities().isOnscreen(); @@ -842,7 +838,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer if(recreate) { screen.removeReference(); // bring back ref-count } - windowLock.unlock(); + _lock.unlock(); } } } @@ -863,7 +859,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer if(null!=lifecycleHook) { lifecycleHook.destroyActionPreLock(); } - windowLock.lock(); + final RecursiveLock _lock = windowLock; + _lock.lock(); try { if(DEBUG_IMPLEMENTATION) { System.err.println("Window DestroyAction() "+getThreadName()); @@ -917,7 +914,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer hasFocus = false; parentWindowHandle = 0; - windowLock.unlock(); + _lock.unlock(); } if(animatorPaused) { lifecycleHook.resumeRenderingAction(); @@ -1002,8 +999,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer int width = getWidth(); int height = getHeight(); boolean wasVisible; - - windowLock.lock(); + + final RecursiveLock _lock = windowLock; + _lock.lock(); try { if(isNativeValid()) { // force recreation if offscreen, since it may become onscreen @@ -1220,7 +1218,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer System.err.println("Window.reparentWindow: END-1 ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+ Display.hashCodeNullSafe(parentWindow)+" "+x+"/"+y+" "+width+"x"+height); } } finally { - windowLock.unlock(); + _lock.unlock(); } if(wasVisible) { switch (operation) { @@ -1245,7 +1243,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private class ReparentActionRecreate implements Runnable { public final void run() { - windowLock.lock(); + final RecursiveLock _lock = windowLock; + _lock.lock(); try { visible = true; if(DEBUG_IMPLEMENTATION) { @@ -1253,7 +1252,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } setVisible(true); // native creation } finally { - windowLock.unlock(); + _lock.unlock(); } } } @@ -1291,7 +1290,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } public final void run() { - windowLock.lock(); + final RecursiveLock _lock = windowLock; + _lock.lock(); try { if(WindowImpl.this.undecorated != undecorated) { // set current state @@ -1311,7 +1311,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } } finally { - windowLock.unlock(); + _lock.unlock(); } sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener } @@ -1333,7 +1333,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } public final void run() { - windowLock.lock(); + final RecursiveLock _lock = windowLock; + _lock.lock(); try { if(WindowImpl.this.alwaysOnTop != alwaysOnTop) { // set current state @@ -1353,7 +1354,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } } finally { - windowLock.unlock(); + _lock.unlock(); } sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener } @@ -1545,7 +1546,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer "\n, ParentWindow "+parentWindow+ "\n, ParentWindowHandle "+toHexString(parentWindowHandle)+" ("+(0!=getParentWindowHandle())+")"+ "\n, WindowHandle "+toHexString(getWindowHandle())+ - "\n, SurfaceHandle "+toHexString(getSurfaceHandle())+ " (lockedExt window "+isWindowLockedByOtherThread()+", surface "+isSurfaceLockedByOtherThread()+")"+ + "\n, SurfaceHandle "+toHexString(getSurfaceHandle())+ " (lockedExt window "+windowLock.isLockedByOtherThread()+", surface "+isSurfaceLockedByOtherThread()+")"+ "\n, Pos "+getX()+"/"+getY()+" (auto "+autoPosition()+"), size "+getWidth()+"x"+getHeight()+ "\n, Visible "+isVisible()+", focus "+hasFocus()+ "\n, Undecorated "+undecorated+" ("+isUndecorated()+")"+ @@ -1675,7 +1676,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } public final void run() { - windowLock.lock(); + final RecursiveLock _lock = windowLock; + _lock.lock(); try { if(DEBUG_IMPLEMENTATION) { System.err.println("Window setPosition: "+getX()+"/"+getY()+" -> "+x+"/"+y+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)); @@ -1689,7 +1691,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } } finally { - windowLock.unlock(); + _lock.unlock(); } } } @@ -1718,7 +1720,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer public boolean fsOn() { return fullscreen; } public final void run() { - windowLock.lock(); + final RecursiveLock _lock = windowLock; + _lock.lock(); try { // set current state WindowImpl.this.fullscreen = fullscreen; @@ -1795,7 +1798,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } } finally { - windowLock.unlock(); + _lock.unlock(); } sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener } @@ -1917,7 +1920,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer // special repaint treatment case WindowEvent.EVENT_WINDOW_REPAINT: // queue repaint event in case window is locked, ie in operation - if( null != getWindowLockOwner() ) { + if( null != windowLock.getOwner() ) { // make sure only one repaint event is queued if(!repaintQueued) { repaintQueued=true; @@ -1936,7 +1939,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer // common treatment case WindowEvent.EVENT_WINDOW_RESIZED: // queue event in case window is locked, ie in operation - if( null != getWindowLockOwner() ) { + if( null != windowLock.getOwner() ) { final boolean discardTO = QUEUED_EVENT_TO <= System.currentTimeMillis()-e.getWhen(); if(DEBUG_IMPLEMENTATION) { System.err.println("Window.consumeEvent: "+Thread.currentThread().getName()+" - queued "+e+", discard-to "+discardTO); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java index eb716677d..426b7734f 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java @@ -87,8 +87,8 @@ public class TestGLAutoDrawableDelegateNEWT extends UITestCase { final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window) { @Override - public void destroy() { - super.destroy(); // destroys drawable/context + protected void destroyImplInLock() { + super.destroyImplInLock(); // destroys drawable/context window.destroy(); // destroys the actual window } }; @@ -97,15 +97,15 @@ public class TestGLAutoDrawableDelegateNEWT extends UITestCase { window.addWindowListener(new WindowAdapter() { @Override public void windowRepaint(WindowUpdateEvent e) { - glad.defaultWindowRepaintOp(); + glad.windowRepaintOp(); } @Override public void windowResized(WindowEvent e) { - glad.defaultWindowResizedOp(); + glad.windowResizedOp(); } @Override public void windowDestroyNotify(WindowEvent e) { - glad.defaultWindowDestroyNotifyOp(); + glad.windowDestroyNotifyOp(); } }); window.addWindowListener(wl); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java index 06aa29b4f..92b4c5238 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java @@ -90,8 +90,8 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase { final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, null, window) { @Override - public void destroy() { - super.destroy(); // destroys drawable/context + protected void destroyImplInLock() { + super.destroyImplInLock(); window.destroy(); // destroys the actual window } }; @@ -100,15 +100,15 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase { window.addWindowListener(new WindowAdapter() { @Override public void windowRepaint(WindowUpdateEvent e) { - glad.defaultWindowRepaintOp(); + glad.windowRepaintOp(); } @Override public void windowResized(WindowEvent e) { - glad.defaultWindowResizedOp(); + glad.windowResizedOp(); } @Override public void windowDestroyNotify(WindowEvent e) { - glad.defaultWindowDestroyNotifyOp(); + glad.windowDestroyNotifyOp(); } }); window.addWindowListener(wl); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextSurfaceLockNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextSurfaceLockNEWT.java index 78988c0e5..b3516d6b4 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextSurfaceLockNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextSurfaceLockNEWT.java @@ -33,9 +33,9 @@ import java.io.IOException; import javax.media.nativewindow.NativeSurface; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; -import org.junit.Assert; import org.junit.Test; import com.jogamp.newt.opengl.GLWindow; @@ -69,7 +69,7 @@ public class TestGLContextSurfaceLockNEWT extends UITestCase { } public void run() { - System.err.println("Animatr "+id+": PRE: "+Thread.currentThread().getName()); + System.err.println("Animatr "+id+", count "+frameCount+": PRE: "+Thread.currentThread().getName()); for(int c=0; c Date: Tue, 24 Jul 2012 00:14:02 +0200 Subject: Fix GraphicsConfigurationFactory: Map factory to device-type _and_ capabilities-type; Add a pre-set nativeVisualID to chooseGraphicsConfiguration(..) Map factory to device-type _and_ capabilities-type: - Allows using different GraphicsConfigurationFactory implementations for different capabilities-types. Previous impl. failed to use an OpenGL agnostic CapabilitiesImmutable for 'chooseGraphicsConfiguration(..)' since only the GL aware factory was mapped. The latter failed since it expected a GLCapabilitiesImmutable. - The passed capabilities-type as well as device-type given at getFactory(..) is traversed top-to-down to find a most suitable factory: For-All devT := getTopDownDeviceTypes(deviceType) For-All capsT := getTopDownCapabilitiesTypes(capabilitiesType) f = factory.get(devT, capsT); if(f) { return f; } end end Add a pre-set nativeVisualID to chooseGraphicsConfiguration(..) - In situations where a native visualID is already chosen [by external means for example], but we still need to query a matching GraphicsConfiguration - we require to pass a non VisualIDHolder.VID_UNDEFINED nativeVisualID. We had a hack implemented before within some implementations and their static calls, however an agnostic mechanism is required to implement new NativeSurface/Window's platform agnostic. - X11GLXGraphicsConfigurationFactory: respect a pre-set xvisualID - X11GLXDrawableFactory.createProxySurfaceImpl(..) queries the given windowHandle's visualID and 'chooses' the configuration accordingly. If the visualID is undefined an exception is thrown, since window is invalid. These mechanics are implicit for Windows and OSX. Fix X11GLXGraphicsConfiguration.updateGraphicsConfiguration(): - Skip any action if a valid X11GLCapabilities is already chosen, i.e. w/ visualID. Otherwise choose a suitable configuration incl. visualID. The latter is quite impossible and invalid, since visualID must be defined at window creation time and the update method is issued with a valid window. X11 - Misc: - Added 'int jogamp.nativewindow.x11.X11Lib.GetVisualIDFromWindow(..)' - All returned visualID's are of type 'int' --- make/config/nativewindow/x11-CustomJavaCode.java | 4 +- .../javax/media/opengl/GLDrawableFactory.java | 3 +- .../classes/javax/media/opengl/awt/GLCanvas.java | 9 +- .../jogamp/opengl/GLDrawableFactoryImpl.java | 3 + .../opengl/egl/EGLGraphicsConfiguration.java | 6 +- .../egl/EGLGraphicsConfigurationFactory.java | 16 +- .../cgl/MacOSXCGLGraphicsConfigurationFactory.java | 4 +- .../MacOSXAWTCGLGraphicsConfigurationFactory.java | 8 +- .../WindowsWGLGraphicsConfigurationFactory.java | 4 +- .../WindowsAWTWGLGraphicsConfigurationFactory.java | 8 +- .../opengl/x11/glx/X11ExternalGLXContext.java | 5 +- .../opengl/x11/glx/X11GLXDrawableFactory.java | 15 +- .../x11/glx/X11GLXGraphicsConfiguration.java | 29 ++- .../glx/X11GLXGraphicsConfigurationFactory.java | 113 ++++++++--- .../nativewindow/awt/AWTGraphicsConfiguration.java | 4 +- .../jogamp/nativewindow/x11/X11GraphicsDevice.java | 2 +- .../jogamp/nativewindow/x11/X11GraphicsScreen.java | 2 +- .../nativewindow/GraphicsConfigurationFactory.java | 226 +++++++++++++++++---- .../DefaultGraphicsConfigurationFactoryImpl.java | 2 +- .../x11/X11GraphicsConfigurationFactory.java | 18 +- .../awt/X11AWTGraphicsConfigurationFactory.java | 16 +- src/nativewindow/native/x11/Xmisc.c | 30 ++- src/newt/classes/jogamp/newt/OffscreenWindow.java | 5 +- .../classes/jogamp/newt/driver/awt/AWTCanvas.java | 6 +- .../jogamp/newt/driver/broadcom/egl/Window.java | 5 +- .../jogamp/newt/driver/intel/gdl/Window.java | 4 +- .../classes/jogamp/newt/driver/kd/KDWindow.java | 5 +- .../jogamp/newt/driver/macosx/MacWindow.java | 5 +- .../jogamp/newt/driver/windows/WindowsWindow.java | 5 +- .../classes/jogamp/newt/driver/x11/X11Window.java | 4 +- 30 files changed, 422 insertions(+), 144 deletions(-) (limited to 'src/jogl/classes/jogamp/opengl') diff --git a/make/config/nativewindow/x11-CustomJavaCode.java b/make/config/nativewindow/x11-CustomJavaCode.java index 73439fcc7..56aec4725 100644 --- a/make/config/nativewindow/x11-CustomJavaCode.java +++ b/make/config/nativewindow/x11-CustomJavaCode.java @@ -24,7 +24,9 @@ /** Entry point to C language function: XVisualInfo * XGetVisualInfo(Display * , long, XVisualInfo * , int * ); */ private static native java.nio.ByteBuffer XGetVisualInfo1(long arg0, long arg1, java.nio.ByteBuffer arg2, Object arg3, int arg3_byte_offset); - public static native long DefaultVisualID(long display, int screen); + public static native int GetVisualIDFromWindow(long display, long window); + + public static native int DefaultVisualID(long display, int screen); public static native long CreateDummyWindow(long display, int screen_index, int visualID, int width, int height); public static native void DestroyDummyWindow(long display, long window); diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java index 612a02f14..9a0d2cb99 100644 --- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java +++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java @@ -434,7 +434,8 @@ public abstract class GLDrawableFactory { /** * Creates a proxy {@link NativeSurface} w/ defined surface handle, i.e. a {@link WrappedSurface} or {@link GDISurface} instance. *

    - * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}. + * It's {@link AbstractGraphicsConfiguration} is properly set according to the given + * windowHandle's native visualID if set or the given {@link GLCapabilitiesImmutable}. *

    *

    * Lifecycle (destruction) of the given surface handle shall be handled by the caller. diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index 694a081b8..03fd78ac7 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -60,6 +60,7 @@ import java.util.ArrayList; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.OffscreenLayerOption; +import javax.media.nativewindow.VisualIDHolder; import javax.media.nativewindow.WindowClosingProtocol; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.AbstractGraphicsScreen; @@ -1062,9 +1063,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing if( EventQueue.isDispatchThread() || Thread.holdsLock(getTreeLock()) ) { config = (AWTGraphicsConfiguration) - GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class).chooseGraphicsConfiguration(capsChosen, + GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class, GLCapabilitiesImmutable.class).chooseGraphicsConfiguration(capsChosen, capsRequested, - chooser, aScreen); + chooser, aScreen, VisualIDHolder.VID_UNDEFINED); } else { try { final ArrayList bucket = new ArrayList(1); @@ -1072,9 +1073,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing @Override public void run() { AWTGraphicsConfiguration c = (AWTGraphicsConfiguration) - GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class).chooseGraphicsConfiguration(capsChosen, + GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class, GLCapabilitiesImmutable.class).chooseGraphicsConfiguration(capsChosen, capsRequested, - chooser, aScreen); + chooser, aScreen, VisualIDHolder.VID_UNDEFINED); bucket.add(c); } }); diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java index 34bb8704a..f092288fb 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java @@ -381,6 +381,9 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { if(null == device) { throw new GLException("No shared device for requested: "+deviceReq); } + if(0 == windowHandle) { + throw new IllegalArgumentException("Null windowHandle"); + } device.lock(); try { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java index 73867fb40..716a6e6f1 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java @@ -42,6 +42,7 @@ import java.util.List; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.VisualIDHolder; import javax.media.opengl.DefaultGLCapabilitiesChooser; @@ -96,9 +97,10 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple } void updateGraphicsConfiguration() { + CapabilitiesImmutable capsChosen = getChosenCapabilities(); EGLGraphicsConfiguration newConfig = (EGLGraphicsConfiguration) - GraphicsConfigurationFactory.getFactory(getScreen().getDevice()).chooseGraphicsConfiguration( - getChosenCapabilities(), getRequestedCapabilities(), chooser, getScreen()); + GraphicsConfigurationFactory.getFactory(getScreen().getDevice(), capsChosen).chooseGraphicsConfiguration( + capsChosen, getRequestedCapabilities(), chooser, getScreen(), VisualIDHolder.VID_UNDEFINED); if(null!=newConfig) { // FIXME: setScreen( ... ); setChosenCapabilities(newConfig.getChosenCapabilities()); diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java index d79c351a0..0b21d2054 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java @@ -81,27 +81,27 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact // become the pre-selector for X11/.. to match the native visual id w/ EGL, if native ES is selected final String nwType = NativeWindowFactory.getNativeWindowType(false); if(NativeWindowFactory.TYPE_X11 == nwType) { - nativeGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, eglFactory); + nativeGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, GLCapabilitiesImmutable.class, eglFactory); } /* else if(NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false)) { nativeGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.windows.WindowsGraphicsDevice.class, eglFactory); } else if(NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false)) { } */ // become the selector for KD/EGL .. - kdeglGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.egl.EGLGraphicsDevice.class, eglFactory); + kdeglGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.egl.EGLGraphicsDevice.class, GLCapabilitiesImmutable.class, eglFactory); } static void unregisterFactory() { final String nwType = NativeWindowFactory.getNativeWindowType(false); if(NativeWindowFactory.TYPE_X11 == nwType) { - GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, nativeGraphicsConfigurationFactory); + GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, GLCapabilitiesImmutable.class, nativeGraphicsConfigurationFactory); } /* else if(NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false)) { GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.windows.WindowsGraphicsDevice.class, nativeGraphicsConfigurationFactory); } else if(NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false)) { } */ nativeGraphicsConfigurationFactory = null; - GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.egl.EGLGraphicsDevice.class, kdeglGraphicsConfigurationFactory); + GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.egl.EGLGraphicsDevice.class, GLCapabilitiesImmutable.class, kdeglGraphicsConfigurationFactory); kdeglGraphicsConfigurationFactory = null; } @@ -110,7 +110,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl ( CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, - CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) { + CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) { if (absScreen == null) { throw new IllegalArgumentException("This NativeWindowFactory accepts only AbstractGraphicsDevice objects"); } @@ -140,7 +140,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact cfg = chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable) capsChosen, (GLCapabilitiesImmutable) capsRequested, (GLCapabilitiesChooser) chooser, - absScreen, VisualIDHolder.VID_UNDEFINED, false); + absScreen, nativeVisualID, false); } else { // handle non native cases (X11, ..) if(null == nativeGraphicsConfigurationFactory) { @@ -154,7 +154,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact cfg = chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable) capsChosen, (GLCapabilitiesImmutable) capsRequested, (GLCapabilitiesChooser) chooser, - absScreen, VisualIDHolder.VID_UNDEFINED, false); + absScreen, nativeVisualID, false); if(null == cfg || VisualIDHolder.VID_UNDEFINED == cfg.getVisualID(VIDType.NATIVE)) { cfg = null; if(DEBUG) { @@ -167,7 +167,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact if(DEBUG) { System.err.println("EGLGraphicsConfigurationFactory.choose..: Delegate to "+nativeGraphicsConfigurationFactory.getClass().getSimpleName()); } - cfg = nativeGraphicsConfigurationFactory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, absScreen); + cfg = nativeGraphicsConfigurationFactory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, absScreen, nativeVisualID); } } return cfg; diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java index 1a9070aef..f138e7557 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java @@ -50,14 +50,14 @@ import javax.media.opengl.GLCapabilitiesImmutable; public class MacOSXCGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory { static void registerFactory() { - GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice.class, new MacOSXCGLGraphicsConfigurationFactory()); + GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice.class, GLCapabilitiesImmutable.class, new MacOSXCGLGraphicsConfigurationFactory()); } private MacOSXCGLGraphicsConfigurationFactory() { } protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl( CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, - CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) { + CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) { return chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, absScreen, false); } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java index a6fa01bad..edf9b7c84 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java @@ -58,14 +58,14 @@ import jogamp.opengl.macosx.cgl.MacOSXCGLGraphicsConfiguration; public class MacOSXAWTCGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory { public static void registerFactory() { - GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, new MacOSXAWTCGLGraphicsConfigurationFactory()); + GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, GLCapabilitiesImmutable.class, new MacOSXAWTCGLGraphicsConfigurationFactory()); } private MacOSXAWTCGLGraphicsConfigurationFactory() { } protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl( CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, - CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) { + CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) { GraphicsDevice device = null; if (absScreen != null && !(absScreen instanceof AWTGraphicsScreen)) { @@ -103,9 +103,9 @@ public class MacOSXAWTCGLGraphicsConfigurationFactory extends GLGraphicsConfigur GraphicsConfiguration gc = device.getDefaultConfiguration(); MacOSXCGLGraphicsConfiguration macConfig = (MacOSXCGLGraphicsConfiguration) - GraphicsConfigurationFactory.getFactory(macDevice).chooseGraphicsConfiguration(capsChosen, + GraphicsConfigurationFactory.getFactory(macDevice, capsChosen).chooseGraphicsConfiguration(capsChosen, capsRequested, - chooser, macScreen); + chooser, macScreen, nativeVisualID); if (macConfig == null) { throw new GLException("Unable to choose a GraphicsConfiguration: "+capsChosen+",\n\t"+chooser+"\n\t"+macScreen); diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java index 943c7fec4..00ed91bb4 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java @@ -69,13 +69,13 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat static VisualIDHolder.VIDComparator PfdIDComparator = new VisualIDHolder.VIDComparator(VisualIDHolder.VIDType.WIN32_PFD); static void registerFactory() { - GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.windows.WindowsGraphicsDevice.class, new WindowsWGLGraphicsConfigurationFactory()); + GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.windows.WindowsGraphicsDevice.class, GLCapabilitiesImmutable.class, new WindowsWGLGraphicsConfigurationFactory()); } private WindowsWGLGraphicsConfigurationFactory() { } protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl( - CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) { + CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) { if (! (capsChosen instanceof GLCapabilitiesImmutable) ) { throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilities objects - chosen"); diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java index bd64b58a4..3b2ff133a 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java @@ -63,14 +63,14 @@ import javax.media.opengl.GLDrawableFactory; public class WindowsAWTWGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory { public static void registerFactory() { - GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, new WindowsAWTWGLGraphicsConfigurationFactory()); + GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, GLCapabilitiesImmutable.class, new WindowsAWTWGLGraphicsConfigurationFactory()); } private WindowsAWTWGLGraphicsConfigurationFactory() { } protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl( CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, - CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) { + CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) { GraphicsDevice device = null; if (absScreen != null && !(absScreen instanceof AWTGraphicsScreen)) { @@ -105,11 +105,11 @@ public class WindowsAWTWGLGraphicsConfigurationFactory extends GLGraphicsConfigu WindowsGraphicsDevice winDevice = new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); DefaultGraphicsScreen winScreen = new DefaultGraphicsScreen(winDevice, awtScreen.getIndex()); - GraphicsConfigurationFactory configFactory = GraphicsConfigurationFactory.getFactory(winDevice); + GraphicsConfigurationFactory configFactory = GraphicsConfigurationFactory.getFactory(winDevice, capsChosen); WindowsWGLGraphicsConfiguration winConfig = (WindowsWGLGraphicsConfiguration) configFactory.chooseGraphicsConfiguration(capsChosen, capsRequested, - chooser, winScreen); + chooser, winScreen, nativeVisualID); if (winConfig == null) { throw new GLException("Unable to choose a GraphicsConfiguration: "+capsChosen+",\n\t"+chooser+"\n\t"+winScreen); } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java index b847363e0..1f3edbd8a 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java @@ -41,6 +41,7 @@ package jogamp.opengl.x11.glx; import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.VisualIDHolder; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawableFactory; @@ -94,9 +95,9 @@ public class X11ExternalGLXContext extends X11GLXContext { // of 0, which doesn't work in a subsequent call to glXChooseFBConfig; if this happens, // create and use a default config (this has been observed when running on CentOS 5.5 inside // of VMWare Server 2.0 with the Mesa 6.5.1 drivers) - if( X11GLXGraphicsConfiguration.GLXFBConfigIDValid(display, x11Screen.getIndex(), val[0]) ) { + if( VisualIDHolder.VID_UNDEFINED == val[0] || !X11GLXGraphicsConfiguration.GLXFBConfigIDValid(display, x11Screen.getIndex(), val[0]) ) { GLCapabilities glcapsDefault = new GLCapabilities(GLProfile.getDefault()); - cfg = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(glcapsDefault, glcapsDefault, null, x11Screen); + cfg = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(glcapsDefault, glcapsDefault, null, x11Screen, VisualIDHolder.VID_UNDEFINED); if(DEBUG) { System.err.println("X11ExternalGLXContext invalid FBCONFIG_ID "+val[0]+", using default cfg: " + cfg); } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java index 8ffbf3951..b2e74f9d4 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java @@ -50,6 +50,7 @@ import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.ProxySurface; import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; +import javax.media.nativewindow.VisualIDHolder; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesImmutable; @@ -514,7 +515,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { device = (X11GraphicsDevice)deviceReq; } final X11GraphicsScreen screen = new X11GraphicsScreen(device, 0); - final X11GLXGraphicsConfiguration config = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen); + final X11GLXGraphicsConfiguration config = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED); if(null == config) { throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen); } @@ -582,7 +583,17 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { protected final ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) { final X11GraphicsDevice device = new X11GraphicsDevice(X11Util.openDisplay(deviceReq.getConnection()), deviceReq.getUnitID(), NativeWindowFactory.getNullToolkitLock(), true); final X11GraphicsScreen screen = new X11GraphicsScreen(device, screenIdx); - final X11GLXGraphicsConfiguration cfg = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen); + final int xvisualID = X11Lib.GetVisualIDFromWindow(device.getHandle(), windowHandle); + if(VisualIDHolder.VID_UNDEFINED == xvisualID) { + throw new GLException("Undefined VisualID of window 0x"+Long.toHexString(windowHandle)+", window probably invalid"); + } + if(DEBUG) { + System.err.println("X11GLXDrawableFactory.createProxySurfaceImpl 0x"+Long.toHexString(windowHandle)+": visualID 0x"+Integer.toHexString(xvisualID)); + } + final X11GLXGraphicsConfiguration cfg = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, xvisualID); + if(DEBUG) { + System.err.println("X11GLXDrawableFactory.createProxySurfaceImpl 0x"+Long.toHexString(windowHandle)+": "+cfg); + } return new WrappedSurface(cfg, windowHandle, 0, 0, upstream); } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java index 95b1cc457..b458fffe1 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java @@ -37,7 +37,9 @@ import java.util.ArrayList; import java.util.List; import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.GraphicsConfigurationFactory; +import javax.media.nativewindow.VisualIDHolder; import javax.media.opengl.DefaultGLCapabilitiesChooser; import javax.media.opengl.GL; import javax.media.opengl.GLCapabilities; @@ -102,16 +104,25 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem } void updateGraphicsConfiguration() { - X11GLXGraphicsConfiguration newConfig = (X11GLXGraphicsConfiguration) - GraphicsConfigurationFactory.getFactory(getScreen().getDevice()).chooseGraphicsConfiguration( - getChosenCapabilities(), getRequestedCapabilities(), chooser, getScreen()); - if(null!=newConfig) { - // FIXME: setScreen( ... ); - setXVisualInfo(newConfig.getXVisualInfo()); - setChosenCapabilities(newConfig.getChosenCapabilities()); - if(DEBUG) { - System.err.println("updateGraphicsConfiguration: "+this); + final CapabilitiesImmutable aChosenCaps = getChosenCapabilities(); + if( !(aChosenCaps instanceof X11GLCapabilities) || VisualIDHolder.VID_UNDEFINED == aChosenCaps.getVisualID(VIDType.X11_XVISUAL) ) { + // This case is actually quite impossible, since on X11 the visualID and hence GraphicsConfiguration + // must be determined _before_ window creation! + final X11GLXGraphicsConfiguration newConfig = (X11GLXGraphicsConfiguration) + GraphicsConfigurationFactory.getFactory(getScreen().getDevice(), aChosenCaps).chooseGraphicsConfiguration( + aChosenCaps, getRequestedCapabilities(), chooser, getScreen(), VisualIDHolder.VID_UNDEFINED); + if(null!=newConfig) { + // FIXME: setScreen( ... ); + setXVisualInfo(newConfig.getXVisualInfo()); + setChosenCapabilities(newConfig.getChosenCapabilities()); + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.updateGraphicsConfiguration updated:"+this); + } + } else { + throw new GLException("No native VisualID pre-chosen and update failed: "+this); } + } else if (DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.updateGraphicsConfiguration kept:"+this); } } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java index 331401c06..234b06bdb 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java @@ -40,6 +40,7 @@ import javax.media.nativewindow.CapabilitiesChooser; import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.VisualIDHolder; +import javax.media.nativewindow.VisualIDHolder.VIDType; import javax.media.opengl.DefaultGLCapabilitiesChooser; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; @@ -74,20 +75,24 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF static GraphicsConfigurationFactory fallbackX11GraphicsConfigurationFactory = null; static void registerFactory() { final GraphicsConfigurationFactory newFactory = new X11GLXGraphicsConfigurationFactory(); - final GraphicsConfigurationFactory oldFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, newFactory); + final GraphicsConfigurationFactory oldFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, GLCapabilitiesImmutable.class, newFactory); if(oldFactory == newFactory) { throw new InternalError("GraphicsConfigurationFactory lifecycle impl. error"); } - if(null == oldFactory) { - throw new InternalError("Missing fallback GraphicsConfigurationFactory"); + if(null != oldFactory) { + fallbackX11GraphicsConfigurationFactory = oldFactory; + } else { + fallbackX11GraphicsConfigurationFactory = GraphicsConfigurationFactory.getFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, CapabilitiesImmutable.class); + if( null == fallbackX11GraphicsConfigurationFactory ) { + throw new InternalError("Missing fallback GraphicsConfigurationFactory"); + } } - fallbackX11GraphicsConfigurationFactory = oldFactory; } private X11GLXGraphicsConfigurationFactory() { } protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl( - CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) { + CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) { if (!(absScreen instanceof X11GraphicsScreen)) { throw new IllegalArgumentException("Only X11GraphicsScreen are allowed here"); } @@ -109,12 +114,12 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF if(DEBUG) { System.err.println("No GLX available, fallback to "+fallbackX11GraphicsConfigurationFactory.getClass().getSimpleName()+" for: "+absScreen); } - return fallbackX11GraphicsConfigurationFactory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, absScreen); + return fallbackX11GraphicsConfigurationFactory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, absScreen, VisualIDHolder.VID_UNDEFINED); } throw new InternalError("No GLX and no fallback GraphicsConfigurationFactory available for: "+absScreen); } return chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable)capsChosen, (GLCapabilitiesImmutable)capsRequested, - (GLCapabilitiesChooser)chooser, (X11GraphicsScreen)absScreen); + (GLCapabilitiesChooser)chooser, (X11GraphicsScreen)absScreen, nativeVisualID); } protected static List getAvailableCapabilities(X11GLXDrawableFactory factory, AbstractGraphicsDevice device) { @@ -199,7 +204,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF static X11GLXGraphicsConfiguration chooseGraphicsConfigurationStatic(GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsReq, GLCapabilitiesChooser chooser, - X11GraphicsScreen x11Screen) { + X11GraphicsScreen x11Screen, int xvisualID) { if (x11Screen == null) { throw new IllegalArgumentException("AbstractGraphicsScreen is null"); } @@ -215,19 +220,19 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF X11GLXGraphicsConfiguration res = null; if( factory.isGLXVersionGreaterEqualOneThree(x11Device) ) { - res = chooseGraphicsConfigurationFBConfig(capsChosen, capsReq, chooser, x11Screen); + res = chooseGraphicsConfigurationFBConfig(capsChosen, capsReq, chooser, x11Screen, xvisualID); } if(null==res) { if(usePBuffer) { - throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig for "+capsChosen); + throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig for visualID "+toHexString(xvisualID)+", "+capsChosen); } - res = chooseGraphicsConfigurationXVisual(capsChosen, capsReq, chooser, x11Screen); + res = chooseGraphicsConfigurationXVisual(capsChosen, capsReq, chooser, x11Screen, xvisualID); } if(null==res) { - throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig and XVisual for "+capsChosen); + throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig and XVisual for visualID "+toHexString(xvisualID)+", "+x11Screen+", "+capsChosen); } if(DEBUG) { - System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationStatic("+x11Screen+","+capsChosen+"): "+res); + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationStatic(visualID "+toHexString(xvisualID)+", "+x11Screen+","+capsChosen+"): "+res); } return res; } @@ -253,7 +258,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF private static X11GLXGraphicsConfiguration chooseGraphicsConfigurationFBConfig(GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsReq, GLCapabilitiesChooser chooser, - X11GraphicsScreen x11Screen) { + X11GraphicsScreen x11Screen, int xvisualID) { int recommendedIndex = -1; PointerBuffer fbcfgsL = null; GLProfile glProfile = capsChosen.getGLProfile(); @@ -273,8 +278,11 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF int[] count = { -1 }; List availableCaps = new ArrayList(); final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer, useFBO); - // 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice - fbcfgsL = GLX.glXChooseFBConfig(display, screen, attribs, 0, count, 0); + // 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice, + // skipped if xvisualID is given + if( VisualIDHolder.VID_UNDEFINED == xvisualID ) { + fbcfgsL = GLX.glXChooseFBConfig(display, screen, attribs, 0, count, 0); + } if (fbcfgsL != null && fbcfgsL.limit()>0) { for (int i = 0; i < fbcfgsL.limit(); i++) { if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, absDevice, fbcfgsL.get(i), winattrmask, isMultisampleAvailable) ) { @@ -317,6 +325,33 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF } } } + + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: got configs: "+availableCaps.size()); + for(int i=0; i chosenIndex ) { if (DEBUG) { @@ -333,7 +368,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF private static X11GLXGraphicsConfiguration chooseGraphicsConfigurationXVisual(GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsReq, GLCapabilitiesChooser chooser, - X11GraphicsScreen x11Screen) { + X11GraphicsScreen x11Screen, int xvisualID) { if (chooser == null) { chooser = new DefaultGLCapabilitiesChooser(); } @@ -351,14 +386,18 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF final boolean isMultisampleAvailable = factory.isGLXMultisampleAvailable(absDevice); int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capsChosen, false, isMultisampleAvailable, display, screen); + XVisualInfo recommendedVis = null; // 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice - XVisualInfo recommendedVis = GLX.glXChooseVisual(display, screen, attribs, 0); - if (DEBUG) { - System.err.print("glXChooseVisual recommended "); - if (recommendedVis == null) { - System.err.println("null visual"); - } else { - System.err.println("visual id " + toHexString(recommendedVis.getVisualid())); + // skipped if xvisualID is given + if( VisualIDHolder.VID_UNDEFINED == xvisualID ) { + recommendedVis = GLX.glXChooseVisual(display, screen, attribs, 0); + if (DEBUG) { + System.err.print("glXChooseVisual recommended "); + if (recommendedVis == null) { + System.err.println("null visual"); + } else { + System.err.println("visual id " + toHexString(recommendedVis.getVisualid())); + } } } @@ -384,6 +423,32 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF } } + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationXVisual: got configs: "+availableCaps.size()); + for(int i=0; i chosenIndex ) { if (DEBUG) { diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java index 61d5e5c0d..2a152ff35 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java @@ -95,8 +95,8 @@ public class AWTGraphicsConfiguration extends DefaultGraphicsConfiguration imple GraphicsConfiguration gc = awtGraphicsDevice.getDefaultConfiguration(); capsChosen = AWTGraphicsConfiguration.setupCapabilitiesRGBABits(capsRequested, gc); } - final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(awtDevice); - final AbstractGraphicsConfiguration config = factory.chooseGraphicsConfiguration(capsChosen, capsRequested, null, awtScreen); + final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(awtDevice, capsChosen); + final AbstractGraphicsConfiguration config = factory.chooseGraphicsConfiguration(capsChosen, capsRequested, null, awtScreen, VisualIDHolder.VID_UNDEFINED); if(config instanceof AWTGraphicsConfiguration) { return (AWTGraphicsConfiguration) config; } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java index 7a98e3c25..5e4d6f41a 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java @@ -88,7 +88,7 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl // It still could be an AWT hold handle .. final long display = getHandle(); final int scrnIdx = X11Lib.DefaultScreen(display); - return (int) X11Lib.DefaultVisualID(display, scrnIdx); + return X11Lib.DefaultVisualID(display, scrnIdx); } @Override diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java index 014f4f688..5f3c220ca 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java @@ -58,7 +58,7 @@ public class X11GraphicsScreen extends DefaultGraphicsScreen implements Cloneabl public int getVisualID() { // It still could be an AWT hold handle .. - return (int) X11Lib.DefaultVisualID(getDevice().getHandle(), getIndex()); + return X11Lib.DefaultVisualID(getDevice().getHandle(), getIndex()); } private static int fetchScreen(X11GraphicsDevice device, int screen) { diff --git a/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java b/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java index 2610f2cfa..c3fdc6798 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java +++ b/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java @@ -36,9 +36,15 @@ package javax.media.nativewindow; import com.jogamp.common.util.ReflectionUtil; import jogamp.nativewindow.Debug; import jogamp.nativewindow.DefaultGraphicsConfigurationFactoryImpl; + +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; +import java.util.List; import java.util.Map; +import java.util.Set; /** * Provides the mechanism by which the graphics configuration for a @@ -59,8 +65,43 @@ import java.util.Map; public abstract class GraphicsConfigurationFactory { protected static final boolean DEBUG; - private static Map, GraphicsConfigurationFactory> registeredFactories; - private static Class abstractGraphicsDeviceClass; + private static class DeviceCapsType { + public final Class deviceType; + public final Class capsType; + private final int hash32; + + public DeviceCapsType(Class deviceType, Class capsType) { + this.deviceType = deviceType; + this.capsType = capsType; + + // 31 * x == (x << 5) - x + int hash32 = 31 + deviceType.hashCode(); + hash32 = ((hash32 << 5) - hash32) + capsType.hashCode(); + this.hash32 = hash32; + } + + public final int hashCode() { + return hash32; + } + + public final boolean equals(Object obj) { + if(this == obj) { return true; } + if (obj instanceof DeviceCapsType) { + DeviceCapsType dct = (DeviceCapsType)obj; + return deviceType == dct.deviceType && capsType == dct.capsType; + } + return false; + } + + @Override + public final String toString() { + return "DeviceCapsType["+deviceType.getName()+", "+capsType.getName()+"]"; + } + + } + + private static final Map registeredFactories; + private static final DeviceCapsType defaultDeviceCapsType; static boolean initialized = false; static { @@ -69,7 +110,8 @@ public abstract class GraphicsConfigurationFactory { System.err.println(Thread.currentThread().getName()+" - Info: GraphicsConfigurationFactory."); // Thread.dumpStack(); } - abstractGraphicsDeviceClass = javax.media.nativewindow.AbstractGraphicsDevice.class; + registeredFactories = Collections.synchronizedMap(new HashMap()); + defaultDeviceCapsType = new DeviceCapsType(AbstractGraphicsDevice.class, CapabilitiesImmutable.class); } public static synchronized void initSingleton() { @@ -79,14 +121,13 @@ public abstract class GraphicsConfigurationFactory { if(DEBUG) { System.err.println(Thread.currentThread().getName()+" - GraphicsConfigurationFactory.initSingleton()"); } - registeredFactories = Collections.synchronizedMap(new HashMap, GraphicsConfigurationFactory>()); // Register the default no-op factory for arbitrary // AbstractGraphicsDevice implementations, including // AWTGraphicsDevice instances -- the OpenGL binding will take // care of handling AWTGraphicsDevices on X11 platforms (as // well as X11GraphicsDevices in non-AWT situations) - registerFactory(abstractGraphicsDeviceClass, new DefaultGraphicsConfigurationFactoryImpl()); + registerFactory(defaultDeviceCapsType.deviceType, defaultDeviceCapsType.capsType, new DefaultGraphicsConfigurationFactoryImpl()); if (NativeWindowFactory.TYPE_X11.equals(NativeWindowFactory.getNativeWindowType(true))) { try { @@ -112,7 +153,6 @@ public abstract class GraphicsConfigurationFactory { System.err.println(Thread.currentThread().getName()+" - GraphicsConfigurationFactory.shutdown()"); } registeredFactories.clear(); - registeredFactories = null; } } @@ -133,74 +173,175 @@ public abstract class GraphicsConfigurationFactory { protected GraphicsConfigurationFactory() { } - /** Returns the factory for use with the given type of - AbstractGraphicsDevice. */ - public static GraphicsConfigurationFactory getFactory(AbstractGraphicsDevice device) { + /** + * Returns the graphics configuration factory for use with the + * given device and capability. + * + * @see #getFactory(Class, Class) + */ + public static GraphicsConfigurationFactory getFactory(AbstractGraphicsDevice device, CapabilitiesImmutable caps) { if (device == null) { - return getFactory(AbstractGraphicsDevice.class); + throw new IllegalArgumentException("null device"); + } + if (caps == null) { + throw new IllegalArgumentException("null caps"); } - return getFactory(device.getClass()); + return getFactory(device.getClass(), caps.getClass()); } /** * Returns the graphics configuration factory for use with the - * given class, which must implement the {@link - * AbstractGraphicsDevice} interface. + * given device and capability class. + *

    + * Note: Registered device types maybe classes or interfaces, where capabilities types are interfaces only. + *

    + * + *

    + * Pseudo code for finding a suitable factory is: + *

    +        For-All devT := getTopDownDeviceTypes(deviceType)
    +            For-All capsT := getTopDownCapabilitiesTypes(capabilitiesType)
    +               f = factory.get(devT, capsT);
    +               if(f) { return f; }
    +            end
    +        end
    +     * 
    + *

    * - * @throws IllegalArgumentException if the given class does not implement AbstractGraphicsDevice + * @param deviceType the minimum capabilities class type accepted, must implement or extend {@link AbstractGraphicsDevice} + * @param capabilitiesType the minimum capabilities class type accepted, must implement or extend {@link CapabilitiesImmutable} + * + * @throws IllegalArgumentException if the deviceType does not implement {@link AbstractGraphicsDevice} or + * capabilitiesType does not implement {@link CapabilitiesImmutable} */ - public static GraphicsConfigurationFactory getFactory(Class abstractGraphicsDeviceImplementor) + public static GraphicsConfigurationFactory getFactory(Class deviceType, Class capabilitiesType) throws IllegalArgumentException, NativeWindowException { - if (!(abstractGraphicsDeviceClass.isAssignableFrom(abstractGraphicsDeviceImplementor))) { + if (!(defaultDeviceCapsType.deviceType.isAssignableFrom(deviceType))) { throw new IllegalArgumentException("Given class must implement AbstractGraphicsDevice"); } - - GraphicsConfigurationFactory factory = null; - Class clazz = abstractGraphicsDeviceImplementor; - while (clazz != null) { - factory = registeredFactories.get(clazz); - if (factory != null) { - if(DEBUG) { - System.err.println("GraphicsConfigurationFactory.getFactory() "+abstractGraphicsDeviceImplementor+" -> "+factory); + if (!(defaultDeviceCapsType.capsType.isAssignableFrom(capabilitiesType))) { + throw new IllegalArgumentException("Given capabilities class must implement CapabilitiesImmutable"); + } + if(DEBUG) { + Thread.dumpStack(); + System.err.println("GraphicsConfigurationFactory.getFactory: "+deviceType.getName()+", "+capabilitiesType.getName()); + dumpFactories(); + } + + final List> deviceTypes = getAllAssignableClassesFrom(defaultDeviceCapsType.deviceType, deviceType, false); + if(DEBUG) { + System.err.println("GraphicsConfigurationFactory.getFactory() deviceTypes: " + deviceTypes); + } + final List> capabilitiesTypes = getAllAssignableClassesFrom(defaultDeviceCapsType.capsType, capabilitiesType, true); + if(DEBUG) { + System.err.println("GraphicsConfigurationFactory.getFactory() capabilitiesTypes: " + capabilitiesTypes); + } + for(int j=0; j interfaceDevice = deviceTypes.get(j); + for(int i=0; i interfaceCaps = capabilitiesTypes.get(i); + final DeviceCapsType dct = new DeviceCapsType(interfaceDevice, interfaceCaps); + final GraphicsConfigurationFactory factory = registeredFactories.get(dct); + if (factory != null) { + if(DEBUG) { + System.err.println("GraphicsConfigurationFactory.getFactory() found "+dct+" -> "+factory); + } + return factory; } - return factory; } - clazz = clazz.getSuperclass(); } // Return the default - factory = registeredFactories.get(abstractGraphicsDeviceClass); + final GraphicsConfigurationFactory factory = registeredFactories.get(defaultDeviceCapsType); if(DEBUG) { - System.err.println("GraphicsConfigurationFactory.getFactory() DEFAULT "+abstractGraphicsDeviceClass+" -> "+factory); + System.err.println("GraphicsConfigurationFactory.getFactory() DEFAULT "+defaultDeviceCapsType+" -> "+factory); } return factory; } + private static ArrayList> getAllAssignableClassesFrom(Class superClassOrInterface, Class fromClass, boolean interfacesOnly) { + // Using a todo list avoiding a recursive loop! + final ArrayList> inspectClasses = new ArrayList>(); + final ArrayList> resolvedInterfaces = new ArrayList>(); + inspectClasses.add(fromClass); + for(int j=0; j clazz = inspectClasses.get(j); + getAllAssignableClassesFrom(superClassOrInterface, clazz, interfacesOnly, resolvedInterfaces, inspectClasses); + } + return resolvedInterfaces; + } + private static void getAllAssignableClassesFrom(Class superClassOrInterface, Class fromClass, boolean interfacesOnly, List> resolvedInterfaces, List> inspectClasses) { + final ArrayList> types = new ArrayList>(); + if( superClassOrInterface.isAssignableFrom(fromClass) && !resolvedInterfaces.contains(fromClass)) { + if( !interfacesOnly || fromClass.isInterface() ) { + types.add(fromClass); + } + } + types.addAll(Arrays.asList(fromClass.getInterfaces())); + + for(int i=0; i iface = types.get(i); + if( superClassOrInterface.isAssignableFrom(iface) && !resolvedInterfaces.contains(iface) ) { + resolvedInterfaces.add(iface); + if( !superClassOrInterface.equals(iface) && !inspectClasses.contains(iface) ) { + inspectClasses.add(iface); // safe add to todo list, avoiding a recursive nature + } + } + } + final Class parentClass = fromClass.getSuperclass(); + if( null != parentClass && superClassOrInterface.isAssignableFrom(parentClass) && !inspectClasses.contains(parentClass) ) { + inspectClasses.add(parentClass); // safe add to todo list, avoiding a recursive nature + } + } + private static void dumpFactories() { + Set dcts = registeredFactories.keySet(); + int i=0; + for(Iterator iter = dcts.iterator(); iter.hasNext(); ) { + DeviceCapsType dct = iter.next(); + System.err.println("Factory #"+i+": "+dct+" -> "+registeredFactories.get(dct)); + i++; + } + } - /** Registers a GraphicsConfigurationFactory handling graphics - * device objects of the given class. This does not need to be - * called by end users, only implementors of new + /** + * Registers a GraphicsConfigurationFactory handling + * the given graphics device and capability class. + *

    + * This does not need to be called by end users, only implementors of new * GraphicsConfigurationFactory subclasses. - * + *

    + * + *

    + * Note: Registered device types maybe classes or interfaces, where capabilities types are interfaces only. + *

    + * + *

    See {@link #getFactory(Class, Class)} for a description of the find algorithm.

    + * + * @param deviceType the minimum capabilities class type accepted, must implement or extend interface {@link AbstractGraphicsDevice} + * @param capabilitiesType the minimum capabilities class type accepted, must extend interface {@link CapabilitiesImmutable} * @return the previous registered factory, or null if none * @throws IllegalArgumentException if the given class does not implement AbstractGraphicsDevice */ - protected static GraphicsConfigurationFactory registerFactory(Class abstractGraphicsDeviceImplementor, GraphicsConfigurationFactory factory) + protected static GraphicsConfigurationFactory registerFactory(Class abstractGraphicsDeviceImplementor, Class capabilitiesType, GraphicsConfigurationFactory factory) throws IllegalArgumentException { - if (!(abstractGraphicsDeviceClass.isAssignableFrom(abstractGraphicsDeviceImplementor))) { - throw new IllegalArgumentException("Given class must implement AbstractGraphicsDevice"); + if (!(defaultDeviceCapsType.deviceType.isAssignableFrom(abstractGraphicsDeviceImplementor))) { + throw new IllegalArgumentException("Given device class must implement AbstractGraphicsDevice"); } + if (!(defaultDeviceCapsType.capsType.isAssignableFrom(capabilitiesType))) { + throw new IllegalArgumentException("Given capabilities class must implement CapabilitiesImmutable"); + } + final DeviceCapsType dct = new DeviceCapsType(abstractGraphicsDeviceImplementor, capabilitiesType); final GraphicsConfigurationFactory prevFactory; if(null == factory) { - prevFactory = registeredFactories.remove(abstractGraphicsDeviceImplementor); + prevFactory = registeredFactories.remove(dct); if(DEBUG) { - System.err.println("GraphicsConfigurationFactory.registerFactory() remove "+abstractGraphicsDeviceImplementor+ + System.err.println("GraphicsConfigurationFactory.registerFactory() remove "+dct+ ", deleting: "+prevFactory); } } else { - prevFactory = registeredFactories.put(abstractGraphicsDeviceImplementor, factory); + prevFactory = registeredFactories.put(dct, factory); if(DEBUG) { - System.err.println("GraphicsConfigurationFactory.registerFactory() put "+abstractGraphicsDeviceImplementor+" -> "+factory+ + System.err.println("GraphicsConfigurationFactory.registerFactory() put "+dct+" -> "+factory+ ", overridding: "+prevFactory); } } @@ -244,6 +385,7 @@ public abstract class GraphicsConfigurationFactory { * @param capsRequested the original requested capabilities * @param chooser the choosing implementation * @param screen the referring Screen + * @param nativeVisualID if not {@link VisualIDHolder#VID_UNDEFINED} it reflects a pre-chosen visualID of the native platform's windowing system. * @return the complete GraphicsConfiguration * * @throws IllegalArgumentException if the data type of the passed @@ -258,7 +400,7 @@ public abstract class GraphicsConfigurationFactory { public final AbstractGraphicsConfiguration chooseGraphicsConfiguration(CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, - AbstractGraphicsScreen screen) + AbstractGraphicsScreen screen, int nativeVisualID) throws IllegalArgumentException, NativeWindowException { if(null==capsChosen) { throw new NativeWindowException("Chosen Capabilities are null"); @@ -275,7 +417,7 @@ public abstract class GraphicsConfigurationFactory { } device.lock(); try { - return chooseGraphicsConfigurationImpl(capsChosen, capsRequested, chooser, screen); + return chooseGraphicsConfigurationImpl(capsChosen, capsRequested, chooser, screen, nativeVisualID); } finally { device.unlock(); } @@ -283,7 +425,7 @@ public abstract class GraphicsConfigurationFactory { protected abstract AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, - CapabilitiesChooser chooser, AbstractGraphicsScreen screen) + CapabilitiesChooser chooser, AbstractGraphicsScreen screen, int nativeVisualID) throws IllegalArgumentException, NativeWindowException; } diff --git a/src/nativewindow/classes/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java b/src/nativewindow/classes/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java index f34b740d4..52e9c8308 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java +++ b/src/nativewindow/classes/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java @@ -37,7 +37,7 @@ import javax.media.nativewindow.*; public class DefaultGraphicsConfigurationFactoryImpl extends GraphicsConfigurationFactory { protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl( - CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen screen) { + CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen screen, int nativeVisualID) { return new DefaultGraphicsConfiguration(screen, capsChosen, capsRequested); } } diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java index 070f87216..b11dd1df1 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java +++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java @@ -39,33 +39,39 @@ import javax.media.nativewindow.CapabilitiesChooser; import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.VisualIDHolder; import com.jogamp.nativewindow.x11.X11GraphicsConfiguration; import com.jogamp.nativewindow.x11.X11GraphicsScreen; public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactory { public static void registerFactory() { - GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, new X11GraphicsConfigurationFactory()); + GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, CapabilitiesImmutable.class, new X11GraphicsConfigurationFactory()); } private X11GraphicsConfigurationFactory() { } protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl( - CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen screen) + CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen screen, int nativeVisualID) throws IllegalArgumentException, NativeWindowException { if(!(screen instanceof X11GraphicsScreen)) { throw new NativeWindowException("Only valid X11GraphicsScreen are allowed"); } - final X11Capabilities x11CapsChosen = new X11Capabilities(getXVisualInfo(screen, capsChosen)); - AbstractGraphicsConfiguration res = new X11GraphicsConfiguration((X11GraphicsScreen)screen, x11CapsChosen, capsRequested, x11CapsChosen.getXVisualInfo()); + final X11Capabilities x11CapsChosen; + if(VisualIDHolder.VID_UNDEFINED == nativeVisualID) { + x11CapsChosen = new X11Capabilities(getXVisualInfo(screen, capsChosen)); + } else { + x11CapsChosen = new X11Capabilities(getXVisualInfo(screen, nativeVisualID)); + } + final AbstractGraphicsConfiguration res = new X11GraphicsConfiguration((X11GraphicsScreen)screen, x11CapsChosen, capsRequested, x11CapsChosen.getXVisualInfo()); if(DEBUG) { - System.err.println("X11GraphicsConfigurationFactory.chooseGraphicsConfigurationImpl("+screen+","+capsChosen+"): "+res); + System.err.println("X11GraphicsConfigurationFactory.chooseGraphicsConfigurationImpl(visualID 0x"+Integer.toHexString(nativeVisualID)+", "+screen+","+capsChosen+"): "+res); } return res; } - public static XVisualInfo getXVisualInfo(AbstractGraphicsScreen screen, long visualID) + public static XVisualInfo getXVisualInfo(AbstractGraphicsScreen screen, int visualID) { XVisualInfo xvi_temp = XVisualInfo.create(); xvi_temp.setVisualid(visualID); diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java b/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java index b6bf63d44..1de03e8be 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java +++ b/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java @@ -61,14 +61,14 @@ import jogamp.nativewindow.x11.X11Util; public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFactory { public static void registerFactory() { - GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, new X11AWTGraphicsConfigurationFactory()); + GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, CapabilitiesImmutable.class, new X11AWTGraphicsConfigurationFactory()); } private X11AWTGraphicsConfigurationFactory() { } protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl( CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, - CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) { + CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) { if (absScreen != null && !(absScreen instanceof AWTGraphicsScreen)) { throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only AWTGraphicsScreen objects"); @@ -77,18 +77,18 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac absScreen = AWTGraphicsScreen.createDefault(); } - return chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, (AWTGraphicsScreen)absScreen); + return chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, (AWTGraphicsScreen)absScreen, nativeVisualID); } public static AWTGraphicsConfiguration chooseGraphicsConfigurationStatic( CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, - CapabilitiesChooser chooser, AWTGraphicsScreen awtScreen) { + CapabilitiesChooser chooser, AWTGraphicsScreen awtScreen, int nativeVisualID) { if(DEBUG) { System.err.println("X11AWTGraphicsConfigurationFactory: got "+awtScreen); } final GraphicsDevice device = ((AWTGraphicsDevice)awtScreen.getDevice()).getGraphicsDevice(); - + final long displayHandleAWT = X11SunJDKReflection.graphicsDeviceGetDisplay(device); final long displayHandle; boolean owner = false; @@ -121,8 +121,8 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac System.err.println("X11AWTGraphicsConfigurationFactory: made "+x11Screen); } - final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(x11Device); - AbstractGraphicsConfiguration aConfig = factory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, x11Screen); + final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(x11Device, capsChosen); + AbstractGraphicsConfiguration aConfig = factory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, x11Screen, nativeVisualID); if (aConfig == null) { throw new NativeWindowException("Unable to choose a GraphicsConfiguration (1): "+capsChosen+",\n\t"+chooser+"\n\t"+x11Screen); } @@ -160,7 +160,7 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac // try again using an AWT Colormodel compatible configuration GraphicsConfiguration gc = device.getDefaultConfiguration(); capsChosen = AWTGraphicsConfiguration.setupCapabilitiesRGBABits(capsChosen, gc); - aConfig = factory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, x11Screen); + aConfig = factory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, x11Screen, nativeVisualID); if (aConfig == null) { throw new NativeWindowException("Unable to choose a GraphicsConfiguration (2): "+capsChosen+",\n\t"+chooser+"\n\t"+x11Screen); } diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c index 21771c9aa..fcba8580c 100644 --- a/src/nativewindow/native/x11/Xmisc.c +++ b/src/nativewindow/native/x11/Xmisc.c @@ -362,14 +362,40 @@ Java_jogamp_nativewindow_x11_X11Lib_XGetVisualInfo1__JJLjava_nio_ByteBuffer_2Lja return jbyteCopy; } -JNIEXPORT jlong JNICALL +JNIEXPORT jint JNICALL +Java_jogamp_nativewindow_x11_X11Lib_GetVisualIDFromWindow(JNIEnv *env, jclass _unused, jlong display, jlong window) { + Display * dpy = (Display *)(intptr_t)display; + Window w = (Window) window; + XWindowAttributes xwa; + jlong r = 0; // undefinded + + if(NULL==dpy) { + NativewindowCommon_throwNewRuntimeException(env, "invalid display connection.."); + return; + } + + NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 1, 0, 1); + memset(&xwa, 0, sizeof(XWindowAttributes)); + XGetWindowAttributes(dpy, w, &xwa); + if(NULL != xwa.visual) { + r = (jint) XVisualIDFromVisual( xwa.visual ); + } else { + r = 0; + } + NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1); + + return r; +} + + +JNIEXPORT jint JNICALL Java_jogamp_nativewindow_x11_X11Lib_DefaultVisualID(JNIEnv *env, jclass _unused, jlong display, jint screen) { jlong r; if(0==display) { NativewindowCommon_FatalError(env, "invalid display connection.."); } NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 1, 0, 0); - r = (jlong) XVisualIDFromVisual( DefaultVisual( (Display*) (intptr_t) display, screen ) ); + r = (jint) XVisualIDFromVisual( DefaultVisual( (Display*) (intptr_t) display, screen ) ); NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 0, 0, 0); return r; } diff --git a/src/newt/classes/jogamp/newt/OffscreenWindow.java b/src/newt/classes/jogamp/newt/OffscreenWindow.java index be543aba9..ba98ca3af 100644 --- a/src/newt/classes/jogamp/newt/OffscreenWindow.java +++ b/src/newt/classes/jogamp/newt/OffscreenWindow.java @@ -40,6 +40,7 @@ import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.MutableSurface; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.VisualIDHolder; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.Point; @@ -72,8 +73,8 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface { dummySurface.createNotify(); } } */ - final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aScreen.getDevice()).chooseGraphicsConfiguration( - capsRequested, capsRequested, capabilitiesChooser, aScreen); + final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aScreen.getDevice(), capsRequested).chooseGraphicsConfiguration( + capsRequested, capsRequested, capabilitiesChooser, aScreen, VisualIDHolder.VID_UNDEFINED); if (null == cfg) { throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java b/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java index 5a49dd57c..a7950048a 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java +++ b/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java @@ -46,6 +46,7 @@ import javax.media.nativewindow.CapabilitiesChooser; import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.VisualIDHolder; import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration; @@ -53,6 +54,7 @@ import com.jogamp.nativewindow.awt.AWTGraphicsDevice; import com.jogamp.nativewindow.awt.AWTGraphicsScreen; import com.jogamp.newt.Window; +@SuppressWarnings("serial") public class AWTCanvas extends Canvas { private GraphicsDevice device; private GraphicsConfiguration chosen; @@ -252,9 +254,9 @@ public class AWTCanvas extends Canvas { AWTGraphicsScreen.createScreenDevice(device, AbstractGraphicsDevice.DEFAULT_UNIT): AWTGraphicsScreen.createDefault(); AWTGraphicsConfiguration config = (AWTGraphicsConfiguration) - GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class).chooseGraphicsConfiguration(capsChosen, + GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class, capsChosen.getClass()).chooseGraphicsConfiguration(capsChosen, capsRequested, - chooser, aScreen); + chooser, aScreen, VisualIDHolder.VID_UNDEFINED); if (config == null) { throw new NativeWindowException("Error: Couldn't fetch AWTGraphicsConfiguration"); } diff --git a/src/newt/classes/jogamp/newt/driver/broadcom/egl/Window.java b/src/newt/classes/jogamp/newt/driver/broadcom/egl/Window.java index ed1d0511a..223ad6484 100644 --- a/src/newt/classes/jogamp/newt/driver/broadcom/egl/Window.java +++ b/src/newt/classes/jogamp/newt/driver/broadcom/egl/Window.java @@ -37,6 +37,7 @@ package jogamp.newt.driver.broadcom.egl; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.VisualIDHolder; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.Point; import javax.media.opengl.GLCapabilitiesImmutable; @@ -57,8 +58,8 @@ public class Window extends jogamp.newt.WindowImpl { } // query a good configuration, however chose the final one by the native queried egl-cfg-id // after creation at {@link #windowCreated(int, int, int)}. - final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration( - capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen()); + final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration( + capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED); if (null == cfg) { throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java index 09e0e3016..d5c75abd4 100644 --- a/src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java +++ b/src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java @@ -54,8 +54,8 @@ public class Window extends jogamp.newt.WindowImpl { final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen(); final AbstractGraphicsDevice aDevice = getScreen().getDisplay().getGraphicsDevice(); - final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aDevice).chooseGraphicsConfiguration( - capsRequested, capsRequested, capabilitiesChooser, aScreen); + final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aDevice, capsRequested).chooseGraphicsConfiguration( + capsRequested, capsRequested, capabilitiesChooser, aScreen, VisualIDHolder.VID_UNDEFINED); if (null == cfg) { throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } diff --git a/src/newt/classes/jogamp/newt/driver/kd/KDWindow.java b/src/newt/classes/jogamp/newt/driver/kd/KDWindow.java index bb76d21ff..9f9d6948e 100644 --- a/src/newt/classes/jogamp/newt/driver/kd/KDWindow.java +++ b/src/newt/classes/jogamp/newt/driver/kd/KDWindow.java @@ -37,6 +37,7 @@ package jogamp.newt.driver.kd; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.VisualIDHolder; import javax.media.nativewindow.VisualIDHolder.VIDType; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.Point; @@ -59,8 +60,8 @@ public class KDWindow extends WindowImpl { if(0!=getParentWindowHandle()) { throw new RuntimeException("Window parenting not supported (yet)"); } - final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration( - capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen()); + final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration( + capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED); if (null == cfg) { throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java index fcca5c843..720d4ee4c 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java @@ -39,6 +39,7 @@ import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.MutableSurface; +import javax.media.nativewindow.VisualIDHolder; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.InsetsImmutable; import javax.media.nativewindow.util.Point; @@ -61,8 +62,8 @@ public class MacWindow extends WindowImpl implements MutableSurface, DriverClear @Override protected void createNativeImpl() { - final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration( - capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen()); + final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration( + capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED); if (null == cfg) { throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java b/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java index 5e636d982..34d76a148 100644 --- a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java +++ b/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java @@ -41,6 +41,7 @@ import jogamp.newt.WindowImpl; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.VisualIDHolder; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.InsetsImmutable; import javax.media.nativewindow.util.Point; @@ -119,8 +120,8 @@ public class WindowsWindow extends WindowImpl { protected void createNativeImpl() { final WindowsScreen screen = (WindowsScreen) getScreen(); final WindowsDisplay display = (WindowsDisplay) screen.getDisplay(); - final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(display.getGraphicsDevice()).chooseGraphicsConfiguration( - capsRequested, capsRequested, capabilitiesChooser, screen.getGraphicsScreen()); + final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(display.getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration( + capsRequested, capsRequested, capabilitiesChooser, screen.getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED); if (null == cfg) { throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } diff --git a/src/newt/classes/jogamp/newt/driver/x11/X11Window.java b/src/newt/classes/jogamp/newt/driver/x11/X11Window.java index 9a5074c29..5501f5a3c 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/X11Window.java +++ b/src/newt/classes/jogamp/newt/driver/x11/X11Window.java @@ -63,9 +63,9 @@ public class X11Window extends WindowImpl { protected void createNativeImpl() { final X11Screen screen = (X11Screen) getScreen(); final X11Display display = (X11Display) screen.getDisplay(); - final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(display.getGraphicsDevice()); + final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(display.getGraphicsDevice(), capsRequested); final AbstractGraphicsConfiguration cfg = factory.chooseGraphicsConfiguration( - capsRequested, capsRequested, capabilitiesChooser, screen.getGraphicsScreen()); + capsRequested, capsRequested, capabilitiesChooser, screen.getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED); if(DEBUG_IMPLEMENTATION) { System.err.println("X11Window.createNativeImpl() factory: "+factory+", chosen config: "+cfg); } -- cgit v1.2.3 From 7bb5885fc3a904f49e22f0c8cbf747d9b189a7ba Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 25 Jul 2012 04:23:35 +0200 Subject: SWT Update: SWT GLCanvas creates lazy when resource is ready; Create new NewtCanvasSWT allowing to parent NEWT windows natively. SWT GLCanvas creates lazy when resource is ready - Ensures drawable and context are created when size > zero and native visualID is valid. The latter is platform dependent. - Note that you cannot utilize custom GLCapabilities w/ this one, since the configurations is already realized - use NewtCanvasSWT. Create new NewtCanvasSWT allowing to parent NEWT windows natively: - Similar to NewtCanvasAWT - Allows attaching / detaching NEWT windows NewtCanvasAWT: Public setNEWTChild(..) fixed Added test cases for the above - tested on Linux, OSX and Windows w/ SWT Note: As usual for OSX, add -XstartOnFirstThread Details: - NEWT Display has new method: 'EDTUtil setEDTUtil(EDTUtil)' allowing to set a custom event dispatch utility. We use this to set our SWTEDTUtil for using NEWT w/ SWT complying w/ SWT threading constraints. --- etc/profile.jogl | 5 + make/build-common.xml | 2 + make/build-newt.xml | 19 +- make/build-test.xml | 99 ++-- make/scripts/java-win64-dbg.bat | 4 +- make/scripts/tests-x64.bat | 25 +- make/scripts/tests.sh | 19 +- make/stub_includes/win32/wingdi.h | 2 + .../gluegen/opengl/BuildComposablePipeline.java | 2 +- .../classes/com/jogamp/opengl/swt/GLCanvas.java | 199 +++++--- src/jogl/classes/jogamp/opengl/GLContextImpl.java | 1 - .../com/jogamp/nativewindow/swt/SWTAccessor.java | 25 + .../media/nativewindow/NativeWindowFactory.java | 17 + .../jogamp/nativewindow/macosx/OSXUtil.java | 35 +- src/nativewindow/native/macosx/OSXmisc.m | 74 ++- src/newt/classes/com/jogamp/newt/Display.java | 17 + .../classes/com/jogamp/newt/awt/NewtCanvasAWT.java | 74 ++- .../classes/com/jogamp/newt/opengl/GLWindow.java | 1 - .../classes/com/jogamp/newt/swt/NewtCanvasSWT.java | 508 +++++++++++++++++++++ .../classes/com/jogamp/newt/swt/SWTEDTUtil.java | 99 ++++ src/newt/classes/jogamp/newt/DisplayImpl.java | 40 +- src/newt/classes/jogamp/newt/WindowImpl.java | 11 +- .../newt/awt/event/AWTParentWindowAdapter.java | 21 +- .../classes/jogamp/newt/driver/awt/AWTDisplay.java | 11 +- .../jogamp/newt/driver/macosx/MacWindow.java | 5 +- .../jogamp/newt/driver/windows/WindowsWindow.java | 11 +- src/newt/native/MacWindow.m | 56 ++- .../test/junit/jogl/swt/TestNewtCanvasSWTGLn.java | 233 ++++++++++ .../test/junit/jogl/swt/TestSWTAccessor02GLn.java | 278 ----------- .../junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java | 55 ++- .../junit/newt/parenting/TestParenting01aSWT.java | 210 +++++++++ .../junit/newt/parenting/TestParenting04AWT.java | 239 ++++++++++ .../junit/newt/parenting/TestParenting04SWT.java | 264 +++++++++++ 33 files changed, 2158 insertions(+), 503 deletions(-) create mode 100644 src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java create mode 100644 src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor02GLn.java create mode 100644 src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04SWT.java (limited to 'src/jogl/classes/jogamp/opengl') diff --git a/etc/profile.jogl b/etc/profile.jogl index 4402adde6..7dd51919d 100755 --- a/etc/profile.jogl +++ b/etc/profile.jogl @@ -25,6 +25,9 @@ function concat_jogl_list() ARCH=`uname -m` KERNEL=`uname -s | awk ' { printf "%s",tolower($0) ; } '` +if [ "$KERNEL" = "sunos" ] ; then + KERNEL="solaris" +fi uname -a | grep -i LINUX && OSS=x11 uname -a | grep -i Darwin && OSS=osx @@ -99,6 +102,8 @@ export JOGL_CLASSPATH if [ "$KERNEL" = "linux" ] ; then SWT_SUB="gtk" +elif [ "$KERNEL" = "solaris" ] ; then + SWT_SUB="gtk" elif [ "$KERNEL" = "darwin" ] ; then SWT_SUB="cocoa" KERNEL="macosx" diff --git a/make/build-common.xml b/make/build-common.xml index 8d440a766..4de5de58b 100644 --- a/make/build-common.xml +++ b/make/build-common.xml @@ -362,6 +362,7 @@ + @@ -374,6 +375,7 @@ + diff --git a/make/build-newt.xml b/make/build-newt.xml index a6be5042e..776708857 100644 --- a/make/build-newt.xml +++ b/make/build-newt.xml @@ -107,6 +107,9 @@ + + @@ -135,11 +138,16 @@ + + + + - + @@ -707,6 +715,13 @@ + + + + + + - + diff --git a/make/build-test.xml b/make/build-test.xml index 51eadfebd..f295ae321 100644 --- a/make/build-test.xml +++ b/make/build-test.xml @@ -427,7 +427,7 @@ - - + - - @@ -491,40 +489,71 @@ - - - - - - - - - - - - - - - - + + + + - + - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/make/scripts/java-win64-dbg.bat b/make/scripts/java-win64-dbg.bat index 109755d2e..c8a90454d 100755 --- a/make/scripts/java-win64-dbg.bat +++ b/make/scripts/java-win64-dbg.bat @@ -18,7 +18,7 @@ set CP_ALL=.;%BLD_DIR%\jar\jogl-all.jar;%BLD_DIR%\jar\jogl-test.jar;..\..\gluege echo CP_ALL %CP_ALL% -set D_ARGS="-Djogl.debug.GLContext" "-Djogl.debug.FBObject" +REM set D_ARGS="-Djogl.debug.GLContext" "-Djogl.debug.FBObject" REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.DontQuery" REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.QueryNativeTK" REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" @@ -37,7 +37,7 @@ REM set D_ARGS="-Djogl.debug=all" REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLContext" "-Djogl.debug.GLContext.TraceSwitch" "-Djogl.debug.DebugGL" "-Djogl.debug.TraceGL" REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLContext" "-Djogl.debug.GLContext.TraceSwitch" "-Djogl.windows.useWGLVersionOf5WGLGDIFuncSet" REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLContext" "-Djogl.debug.GLContext.TraceSwitch" -REM set D_ARGS="-Dnewt.debug.Window" +set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Display" REM set D_ARGS="-Djogl.debug.GLDebugMessageHandler" "-Djogl.debug.DebugGL" "-Djogl.debug.TraceGL" REM set D_ARGS="-Djogl.debug.DebugGL" "-Djogl.debug.GLDebugMessageHandler" "-Djogl.debug.GLSLCode" REM set D_ARGS="-Djogl.debug.GLContext" "-Dnewt.debug=all" diff --git a/make/scripts/tests-x64.bat b/make/scripts/tests-x64.bat index 0b3711784..6d3e46af6 100755 --- a/make/scripts/tests-x64.bat +++ b/make/scripts/tests-x64.bat @@ -28,22 +28,29 @@ REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.glsl.TestTransf REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLSimple01NEWT -time 2000 REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestParenting01AWT -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01bAWT %* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01cAWT -time 50000 REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestListenerCom01AWT REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01NEWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting02NEWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01bAWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01cAWT -time 50000 +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting03AWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting03bAWT -time 100000 +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParentingFocusTraversal01AWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParentingOffscreenLayer01AWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01aSWT $* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting04AWT $* +scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting04SWT $* + +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor03AWTGLn $* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTGLn $* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestWindows01NEWT REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestGLWindows01NEWT REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestGLWindows02NEWTAnimated -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01NEWT REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestFocus01SwingAWTRobot %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestFocus02SwingAWTRobot %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.nativewindow.TestRecursiveToolkitLockCORE -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting03AWT %* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParentingFocusTraversal01AWT %* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParentingOffscreenLayer01AWT %* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting03bAWT -time 100000 REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestFocus02SwingAWTRobot REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestScreenMode00NEWT @@ -56,8 +63,6 @@ REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.Mo REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.TexCubeES2 %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestDisplayLifecycle01NEWT -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01NEWT -REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting02NEWT %* REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestCloseNewtAWT REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleAWT -time 10000 @@ -96,7 +101,7 @@ REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMe REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestMapBuffer01NEWT REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01 -scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.glsl.TestFBOMRTNEWT01 %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT %* diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 13e172770..af6218968 100755 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -61,7 +61,7 @@ function jrun() { #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all" #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all -Djogamp.debug.Lock" #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all" - #D_ARGS="-Djogl.debug=all -Dnewt.debug=all" + D_ARGS="-Dnewt.debug.Window" #D_ARGS="-Djogl.debug.GLDrawable" #D_ARGS="-Djogl.debug.EGLDrawableFactory.DontQuery -Djogl.debug.GLDrawable" #D_ARGS="-Djogl.debug.EGLDrawableFactory.QueryNativeTK -Djogl.debug.GLDrawable" @@ -145,7 +145,8 @@ function jrun() { echo CLASSPATH $CLASSPATH X_ARGS="-Djava.awt.headless=false $X_ARGS" else - export CLASSPATH=$JOGAMP_ALL_NOAWT_CLASSPATH + export CLASSPATH=$JOGAMP_ALL_AWT_CLASSPATH + #export CLASSPATH=$JOGAMP_ALL_NOAWT_CLASSPATH #export CLASSPATH=$JOGAMP_MOBILE_CLASSPATH #export CLASSPATH=.:$GLUEGEN_JAR:$JOGL_BUILD_DIR/jar/atomic/jogl-core.jar:$JOGL_BUILD_DIR/jar/atomic/jogl-gldesktop.jar:$JOGL_BUILD_DIR/jar/atomic/jogl-os-x11.jar:$JOGL_BUILD_DIR/jar/atomic/jogl-util.jar:$JOGL_BUILD_DIR/jar/atomic/nativewindow-core.jar:$JOGL_BUILD_DIR/jar/atomic/nativewindow-os-x11.jar:$JOGL_BUILD_DIR/jar/atomic/newt-core.jar:$JOGL_BUILD_DIR/jar/atomic/newt-driver-x11.jar:$JOGL_BUILD_DIR/jar/atomic/newt-ogl.jar:$JOGL_BUILD_DIR/jar/jogl-test.jar:$SWT_CLASSPATH:$JUNIT_JAR:$ANT_JARS X_ARGS="-Djava.awt.headless=true $X_ARGS" @@ -298,13 +299,17 @@ function testawtswt() { # #testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTEclipseGLCanvas01GLn $* #testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $* -#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $* -#testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor02GLn $* +#testswt com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTGLn $* # -# awtswt (testawtswt) +# awtswt (testawtswt) +# Per default (unit tests) all test are performed this way +# with OSX: -XstartOnFirstThread # +#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTEclipseGLCanvas01GLn $* #testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor03AWTGLn $* +#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $* +#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTGLn $* # # newt.awt (testawt) @@ -321,6 +326,9 @@ function testawtswt() { #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01cSwingAWT $* #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting02AWT $* #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting03AWT $* +#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting04AWT $* +#testawtswt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01aSWT $* +testawtswt com.jogamp.opengl.test.junit.newt.parenting.TestParenting04SWT $* #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingFocusTraversal01AWT $* #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingOffscreenLayer01GLCanvasAWT $* #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingOffscreenLayer02NewtCanvasAWT $* @@ -402,7 +410,6 @@ function testawtswt() { #testawt com.jogamp.opengl.test.junit.newt.TestFocus02SwingAWTRobot $* #linux: -testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor02GLn $* # ?? # osx: #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingFocusTraversal01AWT $* diff --git a/make/stub_includes/win32/wingdi.h b/make/stub_includes/win32/wingdi.h index 2d3e33275..7a88582c2 100644 --- a/make/stub_includes/win32/wingdi.h +++ b/make/stub_includes/win32/wingdi.h @@ -44,6 +44,8 @@ WINUSERAPI BOOL WINAPI DestroyWindow(HWND hWnd); WINUSERAPI DWORD WINAPI GetObjectType(HGDIOBJ h); WINUSERAPI BOOL WINAPI IsWindowVisible(HWND hWnd); WINUSERAPI BOOL WINAPI IsWindow(HWND hWnd); +WINUSERAPI HWND WINAPI GetParent(HWND hWnd); +WINUSERAPI HWND WINAPI SetParent(HWND hWndChild,HWND hWndNewParent); WINUSERAPI HANDLE WINAPI GetCurrentProcess(void); WINUSERAPI BOOL WINAPI GetProcessAffinityMask(HANDLE hProcess,PDWORD_PTR lpProcessAffinityMask,PDWORD_PTR lpSystemAffinityMask); diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java index 1d9cf3668..5334d45cf 100644 --- a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java +++ b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java @@ -410,7 +410,7 @@ public class BuildComposablePipeline { output.flush(); output.close(); - System.out.println("wrote to file: " + file); // JAU + System.out.println("wrote to file: " + file); } /** Get the name of the object through which API calls should be routed. */ diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java index 64ee1c1ad..8d237162c 100644 --- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java +++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java @@ -45,6 +45,7 @@ import javax.media.opengl.GLProfile; import javax.media.opengl.GLRunnable; import javax.media.opengl.Threading; +import jogamp.opengl.Debug; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableHelper; @@ -70,8 +71,12 @@ import com.jogamp.opengl.JoglVersion; /** * Native SWT Canvas implementing GLAutoDrawable + * + *

    Note: To employ custom GLCapabilities, NewtCanvasSWT shall be used instead.

    + * */ public class GLCanvas extends Canvas implements GLAutoDrawable { + private static final boolean DEBUG = Debug.debug("GLCanvas"); /* * Flag for whether the SWT thread should be used for OpenGL calls when in single-threaded mode. This is controlled @@ -87,18 +92,20 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { /* GL Stuff */ private final RecursiveLock lock = LockFactory.createRecursiveLock(); private final GLDrawableHelper helper = new GLDrawableHelper(); + + private final GLContext shareWith; + private final GLCapabilitiesImmutable capsRequested; + private final GLCapabilitiesChooser capsChooser; + private volatile GLDrawable drawable; // volatile: avoid locking for read-only access private GLContext context; /* Native window surface */ private AbstractGraphicsDevice device; - private final long nativeWindowHandle; - private final ProxySurface proxySurface; /* Construction parameters stored for GLAutoDrawable accessor methods */ private int additionalCtxCreationFlags = 0; - private final GLCapabilitiesImmutable glCapsRequested; /* Flag indicating whether an unprocessed reshape is pending. */ private volatile boolean sendReshape; // volatile: maybe written by WindowManager thread w/o locking @@ -218,6 +225,37 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { */ private volatile Rectangle clientArea; + /** + * Creates an instance using {@link #GLCanvas(Composite, int, GLCapabilitiesImmutable, GLCapabilitiesChooser, GLContext)} + * on the SWT thread. + * + * @param parent + * Required (non-null) parent Composite. + * @param style + * Optional SWT style bit-field. The {@link SWT#NO_BACKGROUND} bit is set before passing this up to the + * Canvas constructor, so OpenGL handles the background. + * @param caps + * Optional GLCapabilities. If not provided, the default capabilities for the default GLProfile for the + * graphics device determined by the parent Composite are used. Note that the GLCapabilities that are + * actually used may differ based on the capabilities of the graphics device. + * @param chooser + * Optional GLCapabilitiesChooser to customize the selection of the used GLCapabilities based on the + * requested GLCapabilities, and the available capabilities of the graphics device. + * @param shareWith + * Optional GLContext to share state (textures, vbos, shaders, etc.) with. + * @return a new instance + */ + public static GLCanvas create(final Composite parent, final int style, final GLCapabilitiesImmutable caps, + final GLCapabilitiesChooser chooser, final GLContext shareWith) { + final GLCanvas[] res = new GLCanvas[] { null }; + parent.getDisplay().syncExec(new Runnable() { + public void run() { + res[0] = new GLCanvas( parent, style, caps, chooser, shareWith ); + } + }); + return res[0]; + } + /** * Creates a new SWT GLCanvas. * @@ -250,35 +288,26 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite). * Note: SWT is owner of the native handle, hence no closing operation will be a NOP. */ device = SWTAccessor.getDevice(this); - /* Since we have no means of querying the screen index yet, assume 0. Good choice due to Xinerama alike settings anyways. */ - final int screenIdx = 0; - /* Native handle for the control, used to associate with GLContext */ - nativeWindowHandle = SWTAccessor.getWindowHandle(this); /* Select default GLCapabilities if none was provided, otherwise clone provided caps to ensure safety */ if(null == caps) { caps = new GLCapabilities(GLProfile.getDefault(device)); } - glCapsRequested = caps; - - final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(caps.getGLProfile()); - - /* Create a NativeWindow proxy for the SWT canvas */ - proxySurface = glFactory.createProxySurface(device, screenIdx, nativeWindowHandle, caps, chooser, swtCanvasUpStreamHook); - - /* Associate a GL surface with the proxy */ - drawable = glFactory.createGLDrawable(proxySurface); - drawable.setRealized(true); - - context = drawable.createContext(shareWith); - + this.capsRequested = caps; + this.capsChooser = chooser; + this.shareWith = shareWith; + + // post create .. when ready + drawable = null; + context = null; + /* Register SWT listeners (e.g. PaintListener) to render/resize GL surface. */ /* TODO: verify that these do not need to be manually de-registered when destroying the SWT component */ addPaintListener(new PaintListener() { @Override public void paintControl(final PaintEvent arg0) { - if (!helper.isExternalAnimatorAnimating()) { - display(); + if ( !helper.isExternalAnimatorAnimating() ) { + display(); // checks: null != drawable } } }); @@ -291,39 +320,93 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { }); } private final ProxySurface.UpstreamSurfaceHook swtCanvasUpStreamHook = new ProxySurface.UpstreamSurfaceHook() { - @Override - public final void create(ProxySurface s) { /* nop */ } - - @Override - public final void destroy(ProxySurface s) { /* nop */ } - - @Override - public final int getWidth(ProxySurface s) { - return clientArea.width; - } - - @Override - public final int getHeight(ProxySurface s) { - return clientArea.height; - } - - @Override - public String toString() { - return "SETUpstreamSurfaceHook[upstream: "+GLCanvas.this.toString()+"]"; - } - + @Override + public final void create(ProxySurface s) { /* nop */ } + + @Override + public final void destroy(ProxySurface s) { /* nop */ } + + @Override + public final int getWidth(ProxySurface s) { + return clientArea.width; + } + + @Override + public final int getHeight(ProxySurface s) { + return clientArea.height; + } + + @Override + public String toString() { + return "SWTCanvasUpstreamSurfaceHook[upstream: "+GLCanvas.this.toString()+", "+clientArea.width+"x"+clientArea.height+"]"; + } }; protected final void updateSizeCheck() { - clientArea = GLCanvas.this.getClientArea(); - if (clientArea != null && - proxySurface.getWidth() != clientArea.width && - proxySurface.getHeight() != clientArea.height) { + final Rectangle oClientArea = clientArea; + final Rectangle nClientArea = GLCanvas.this.getClientArea(); + if ( nClientArea != null && + ( nClientArea.width != oClientArea.width || nClientArea.height != oClientArea.height ) + ) { + clientArea = nClientArea; // write back new value sendReshape = true; // Mark for OpenGL reshape next time the control is painted } - sendReshape = false; + } + + @Override + public void display() { + if( null != drawable || validateDrawableAndContext() ) { + runInGLThread(makeCurrentAndDisplayOnEDTAction); + } } + + /** assumes drawable == null ! */ + protected final boolean validateDrawableAndContext() { + if( GLCanvas.this.isDisposed() ) { + return false; + } + final Rectangle nClientArea = clientArea; + if(0 == nClientArea.width * nClientArea.height) { + return false; + } + + final RecursiveLock _lock = lock; + _lock.lock(); + try { + final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(capsRequested.getGLProfile()); + + /* Native handle for the control, used to associate with GLContext */ + final long nativeWindowHandle = SWTAccessor.getWindowHandle(this); + + /* Create a NativeWindow proxy for the SWT canvas */ + ProxySurface proxySurface = null; + try { + proxySurface = glFactory.createProxySurface(device, 0 /* screenIdx */, nativeWindowHandle, + capsRequested, capsChooser, swtCanvasUpStreamHook); + } catch (GLException gle) { + // not ready yet .. + if(DEBUG) { System.err.println(gle.getMessage()); } + } + + if(null != proxySurface) { + /* Associate a GL surface with the proxy */ + drawable = glFactory.createGLDrawable(proxySurface); + drawable.setRealized(true); + + context = drawable.createContext(shareWith); + } + } finally { + _lock.unlock(); + } + final boolean res = null != drawable; + if(DEBUG && res) { + System.err.println("SWT GLCanvas realized! "+this+", "+drawable); + Thread.dumpStack(); + } + return res; + } + @Override public final Object getUpstreamWidget() { return this; @@ -362,11 +445,6 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { dispose(); } - @Override - public void display() { - runInGLThread(makeCurrentAndDisplayOnEDTAction); - } - @Override public GLAnimatorControl getAnimator() { return helper.getAnimator(); @@ -379,7 +457,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { @Override public GLContext getContext() { - return context; + return null != drawable ? context : null; } @Override @@ -472,7 +550,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { @Override public GLCapabilitiesImmutable getChosenGLCapabilities() { - return (GLCapabilitiesImmutable)proxySurface.getGraphicsConfiguration().getChosenCapabilities(); + final GLDrawable _drawable = drawable; + return null != _drawable ? (GLCapabilitiesImmutable)_drawable.getChosenGLCapabilities() : null; } /** @@ -481,7 +560,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { * @return Non-null GLCapabilities. */ public GLCapabilitiesImmutable getRequestedGLCapabilities() { - return (GLCapabilitiesImmutable)proxySurface.getGraphicsConfiguration().getRequestedCapabilities(); + final GLDrawable _drawable = drawable; + return null != _drawable ? (GLCapabilitiesImmutable)_drawable.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities() : null; } @Override @@ -492,7 +572,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { @Override public GLProfile getGLProfile() { - return glCapsRequested.getGLProfile(); + return capsRequested.getGLProfile(); } @Override @@ -523,10 +603,9 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { runInGLThread(makeCurrentAndSwapBuffersOnEDTAction); } - // FIXME: API of update() method ? @Override public void update() { - // FIXME: display(); ? + // don't paint background etc .. nop avoids flickering } @Override @@ -551,7 +630,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { * @see Platform#AWT_AVAILABLE * @see Platform#getOSType() */ - private void runInGLThread(final Runnable action) { + private static void runInGLThread(final Runnable action) { if(Platform.OSType.MACOS == Platform.OS_TYPE) { SWTAccessor.invoke(true, action); } else { diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index e730bc62e..bf6a0ee6e 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -338,7 +338,6 @@ public abstract class GLContextImpl extends GLContext { if (TRACE_SWITCH) { System.err.println(getThreadName() + ": GLContextImpl.destroy.X: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle) + ", isShared "+GLContextShareSet.isShared(this)+" - "+lock); - Thread.dumpStack(); // JAU } } } finally { diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java index 0494bb408..ba07d97dc 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java @@ -34,16 +34,21 @@ import java.lang.reflect.Method; import org.eclipse.swt.graphics.GCData; import org.eclipse.swt.widgets.Control; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.DefaultGraphicsScreen; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeWindowFactory; +import javax.media.nativewindow.VisualIDHolder; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice; import com.jogamp.nativewindow.windows.WindowsGraphicsDevice; import com.jogamp.nativewindow.x11.X11GraphicsDevice; +import com.jogamp.nativewindow.x11.X11GraphicsScreen; import jogamp.nativewindow.macosx.OSXUtil; +import jogamp.nativewindow.x11.X11Lib; public class SWTAccessor { static final Field swt_control_handle; @@ -213,6 +218,26 @@ public class SWTAccessor { } throw new UnsupportedOperationException("n/a for this windowing system: "+NativeWindowFactory.getNativeWindowType(false)); } + public static AbstractGraphicsScreen getScreen(AbstractGraphicsDevice device, int screen) { + if( null != OS_gtk_class ) { + return new X11GraphicsScreen((X11GraphicsDevice)device, screen); + } + if( NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false) || + NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false) ) { + return new DefaultGraphicsScreen(device, screen); + } + throw new UnsupportedOperationException("n/a for this windowing system: "+NativeWindowFactory.getNativeWindowType(false)); + } + public static int getNativeVisualID(AbstractGraphicsDevice device, long windowHandle) { + if( null != OS_gtk_class ) { + return X11Lib.GetVisualIDFromWindow(device.getHandle(), windowHandle); + } + if( NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false) || + NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false) ) { + return VisualIDHolder.VID_UNDEFINED; + } + throw new UnsupportedOperationException("n/a for this windowing system: "+NativeWindowFactory.getNativeWindowType(false)); + } public static long getWindowHandle(Control swtControl) { long handle = getHandle(swtControl); diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java index b85ad47f2..6faa9890c 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java @@ -561,4 +561,21 @@ public abstract class NativeWindowFactory { } return null; } + + /** + * Returns true if the given visualID is valid for further processing, i.e. OpenGL usage, + * otherwise return false. + *

    + * On certain platforms, i.e. X11, a valid visualID is required at window creation. + * Other platforms may determine it later on, e.g. OSX and Windows.

    + *

    + * If the visualID is {@link VisualIDHolder#VID_UNDEFINED} and the platform requires it + * at creation time (see above), it is not valid for further processing. + *

    + */ + public static boolean isNativeVisualIDValidForProcessing(int visualID) { + return NativeWindowFactory.TYPE_X11 != NativeWindowFactory.getNativeWindowType(false) || + VisualIDHolder.VID_UNDEFINED != visualID ; + } + } diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java index 4767dff18..894084fce 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java +++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java @@ -28,6 +28,7 @@ package jogamp.nativewindow.macosx; import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.Point; import jogamp.nativewindow.Debug; @@ -63,8 +64,37 @@ public class OSXUtil { return isNSView0(object); } - public static Point GetLocationOnScreen(long windowOrView, int src_x, int src_y) { - return (Point) GetLocationOnScreen0(windowOrView, src_x, src_y); + /** + * In case the windowOrView is top-level, + * you shall set topLevel to true where + * insets gets into account to compute the client position as follows: + *
    +      if(topLevel) {
    +          // top-level position -> client window position
    +          final Insets insets = GetInsets(windowOrView);
    +          los.setX(los.getX() + insets.getLeftWidth());
    +          los.setY(los.getY() + insets.getTopHeight());
    +      }
    +     * 
    + * @param windowOrView + * @param topLevel + * @param src_x + * @param src_y + * @return the client position + */ + public static Point GetLocationOnScreen(long windowOrView, boolean topLevel, int src_x, int src_y) { + final Point los = (Point) GetLocationOnScreen0(windowOrView, src_x, src_y); + if(topLevel) { + // top-level position -> client window position + final Insets insets = GetInsets(windowOrView); + los.setX(los.getX() + insets.getLeftWidth()); + los.setY(los.getY() + insets.getTopHeight()); + } + return los; + } + + public static Insets GetInsets(long windowOrView) { + return (Insets) GetInsets0(windowOrView); } public static long CreateNSWindow(int x, int y, int width, int height) { @@ -135,6 +165,7 @@ public class OSXUtil { private static native boolean initIDs0(); private static native boolean isNSView0(long object); private static native Object GetLocationOnScreen0(long windowOrView, int src_x, int src_y); + private static native Object GetInsets0(long windowOrView); private static native long CreateNSWindow0(int x, int y, int width, int height); private static native void DestroyNSWindow0(long nsWindow); private static native long GetNSView0(long nsWindow); diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m index 37fa4c88f..2c853a43d 100644 --- a/src/nativewindow/native/macosx/OSXmisc.m +++ b/src/nativewindow/native/macosx/OSXmisc.m @@ -52,12 +52,18 @@ static const char * const ClazzNameRunnable = "java/lang/Runnable"; static jmethodID runnableRunID = NULL; -static const char * const ClazzNamePoint = "javax/media/nativewindow/util/Point"; static const char * const ClazzAnyCstrName = ""; + +static const char * const ClazzNamePoint = "javax/media/nativewindow/util/Point"; static const char * const ClazzNamePointCstrSignature = "(II)V"; static jclass pointClz = NULL; static jmethodID pointCstr = NULL; +static const char * const ClazzNameInsets = "javax/media/nativewindow/util/Insets"; +static const char * const ClazzNameInsetsCstrSignature = "(IIII)V"; +static jclass insetsClz = NULL; +static jmethodID insetsCstr = NULL; + static int _initialized=0; JNIEXPORT jboolean JNICALL @@ -79,6 +85,21 @@ Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0(JNIEnv *env, jclass _unused) { ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature); } + c = (*env)->FindClass(env, ClazzNameInsets); + if(NULL==c) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't find %s", ClazzNameInsets); + } + insetsClz = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + if(NULL==insetsClz) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't use %s", ClazzNameInsets); + } + insetsCstr = (*env)->GetMethodID(env, insetsClz, ClazzAnyCstrName, ClazzNameInsetsCstrSignature); + if(NULL==insetsCstr) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't fetch %s.%s %s", + ClazzNameInsets, ClazzAnyCstrName, ClazzNameInsetsCstrSignature); + } + c = (*env)->FindClass(env, ClazzNameRunnable); if(NULL==c) { NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't find %s", ClazzNameRunnable); @@ -154,6 +175,49 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetLocationOnS return res; } +/* + * Class: Java_jogamp_nativewindow_macosx_OSXUtil + * Method: getInsets0 + * Signature: (J)Ljavax/media/nativewindow/util/Insets; + */ +JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetInsets0 + (JNIEnv *env, jclass unused, jlong winOrView) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + NSObject *nsObj = (NSObject*) (intptr_t) winOrView; + NSWindow* win = NULL; + NSView* view = NULL; + jint il,ir,it,ib; + + if( [nsObj isKindOfClass:[NSWindow class]] ) { + win = (NSWindow*) nsObj; + view = [win contentView]; + } else if( nsObj != NULL && [nsObj isKindOfClass:[NSView class]] ) { + view = (NSView*) nsObj; + win = [view window]; + } else { + NativewindowCommon_throwNewRuntimeException(env, "neither win not view %p\n", nsObj); + } + + NSRect frameRect = [win frame]; + NSRect contentRect = [win contentRectForFrameRect: frameRect]; + + // note: this is a simplistic implementation which doesn't take + // into account DPI and scaling factor + CGFloat l = contentRect.origin.x - frameRect.origin.x; + il = (jint)l; // l + ir = (jint)(frameRect.size.width - (contentRect.size.width + l)); // r + it = (jint)(frameRect.size.height - contentRect.size.height); // t + ib = (jint)(contentRect.origin.y - frameRect.origin.y); // b + + jobject res = (*env)->NewObject(env, insetsClz, insetsCstr, il, ir, it, ib); + + [pool release]; + + return res; +} + /* * Class: Java_jogamp_nativewindow_macosx_OSXUtil * Method: CreateNSWindow0 @@ -172,6 +236,12 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateNSWindow0 defer: YES]; [myWindow setReleasedWhenClosed: YES]; // default [myWindow setPreservesContentDuringLiveResize: YES]; + // Remove animations +NS_DURING + // Available >= 10.7 - Removes default animations + [myWindow setAnimationBehavior: NSWindowAnimationBehaviorNone]; +NS_HANDLER +NS_ENDHANDLER // invisible .. [myWindow setOpaque: NO]; @@ -229,7 +299,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateCALayer0 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; CALayer* layer = [[CALayer alloc] init]; - DBG_PRINT("CALayer::CreateCALayer.0: %p %d/%d %dx%d (refcnt %d)\n", layer, x, y, width, height, (int)[layer retainCount]); + DBG_PRINT("CALayer::CreateCALayer.0: %p %d/%d %dx%d (refcnt %d)\n", layer, (int)x, (int)y, (int)width, (int)height, (int)[layer retainCount]); // avoid zero size if(0 == width) { width = 32; } if(0 == height) { height = 32; } diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java index 7b6849a30..1e9a0e9eb 100644 --- a/src/newt/classes/com/jogamp/newt/Display.java +++ b/src/newt/classes/com/jogamp/newt/Display.java @@ -141,6 +141,23 @@ public abstract class Display { */ public abstract String getType(); + /** + * Sets a new {@link EDTUtil} and returns the previous one. + *

    + * If newEDTUtil is null, + * the device's default EDTUtil is created and used. + *

    + *

    + * If a previous one exists and it differs from the new one, + * it's being stopped, wait-until-idle and reset to allow restart. + *

    + *

    + * If newEDTUtil is not null and equals the previous one, + * null is returned and no change is being made. + *

    + */ + public abstract EDTUtil setEDTUtil(EDTUtil newEDTUtil); + public abstract EDTUtil getEDTUtil(); public abstract boolean isEDTRunning(); diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index cd0e9aab6..6f0028a77 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -263,17 +263,35 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto private final FocusPropertyChangeListener focusPropertyChangeListener = new FocusPropertyChangeListener(); private volatile KeyboardFocusManager keyboardFocusManager = null; - /** sets a new NEWT child, provoking reparenting. */ - private NewtCanvasAWT setNEWTChild(Window child) { - if(newtChild!=child) { - newtChild = child; - if(isDisplayable()) { - // reparent right away, addNotify has been called already - final java.awt.Container cont = AWTMisc.getContainer(this); - reparentWindow( (null!=child) ? true : false, cont ); - } + /** + * Sets a new NEWT child, provoking reparenting. + *

    + * A previously detached newChild will be released to top-level status + * and made invisible. + *

    + *

    + * Note: When switching NEWT child's, detaching the previous first via setNEWTChild(null) + * produced much cleaner visual results. + *

    + * @return the previous attached newt child. + */ + public Window setNEWTChild(Window newChild) { + final Window prevChild = newtChild; + if(DEBUG) { + System.err.println("NewtCanvasAWT.setNEWTChild.0: win "+newtWinHandleToHexString(prevChild)+" -> "+newtWinHandleToHexString(newChild)); + } + final java.awt.Container cont = AWTMisc.getContainer(this); + // remove old one + if(null != newtChild) { + reparentWindow( false, cont ); + newtChild = null; } - return this; + // add new one, reparent only if ready + newtChild = newChild; + if( isDisplayable() && null != newChild) { + reparentWindow( true, cont ); + } + return prevChild; } /** @return the current NEWT child */ @@ -306,13 +324,13 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto awtKeyAdapter.removeFrom(this); awtKeyAdapter = null; } - newtChild.setKeyboardFocusHandler(null); if(null != keyboardFocusManager) { keyboardFocusManager.removePropertyChangeListener("focusOwner", focusPropertyChangeListener); keyboardFocusManager = null; } if( null != newtChild ) { + newtChild.setKeyboardFocusHandler(null); if(attach) { if(null == jawtWindow.getGraphicsConfiguration()) { throw new InternalError("XXX"); @@ -360,7 +378,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto // if ( isShowing() == true ) -> Container is already visible. System.err.println("NewtCanvasAWT.addNotify: "+newtChild+", "+this+", visible "+isVisible()+", showing "+isShowing()+ ", displayable "+isDisplayable()+" -> "+cont); - } + } reparentWindow(true, cont); } @@ -375,6 +393,12 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto ols.detachSurfaceLayer(); } reparentWindow(false, cont); + + if(null != jawtWindow) { + NewtFactoryAWT.destroyNativeWindow(jawtWindow); + jawtWindow=null; + } + super.removeNotify(); } @@ -382,14 +406,19 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto if(null==newtChild) { return; // nop } + if(DEBUG) { + System.err.println("NewtCanvasAWT.reparentWindow.0: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()); + } newtChild.setFocusAction(null); // no AWT focus traversal .. if(add) { - jawtWindow = NewtFactoryAWT.getNativeWindow(this, newtChild.getRequestedCapabilities()); - jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer); if(DEBUG) { System.err.println("NewtCanvasAWT.reparentWindow: newtChild: "+newtChild); } + if(null == jawtWindow) { + jawtWindow = NewtFactoryAWT.getNativeWindow(this, newtChild.getRequestedCapabilities()); + jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer); + } final int w; final int h; if(isPreferredSizeSet()) { @@ -413,7 +442,6 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto newtChild.setVisible(true); configureNewtChild(true); newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener - newtChild.windowRepaint(0, 0, w, h); // force this AWT Canvas to be focus-able, // since this it is completely covered by the newtChild (z-order). @@ -422,10 +450,9 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto configureNewtChild(false); newtChild.setVisible(false); newtChild.reparentWindow(null); - if(null != jawtWindow) { - NewtFactoryAWT.destroyNativeWindow(jawtWindow); - jawtWindow=null; - } + } + if(DEBUG) { + System.err.println("NewtCanvasAWT.reparentWindow.X: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()); } } @@ -451,7 +478,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto NewtFactoryAWT.destroyNativeWindow(jawtWindow); jawtWindow=null; } - newtChild.setVisible(false); + newtChild.setVisible(false); newtChild.reparentWindow(null); newtChild.destroy(); newtChild=null; @@ -569,5 +596,12 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto } } } + + static String newtWinHandleToHexString(Window w) { + return null != w ? toHexString(w.getWindowHandle()) : "nil"; + } + static String toHexString(long l) { + return "0x"+Long.toHexString(l); + } } diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index 2205aec8e..d662a743a 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -480,7 +480,6 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind } if(Window.DEBUG_IMPLEMENTATION) { System.err.println("GLWindow.setVisibleActionPost("+visible+", "+nativeWindowCreated+") "+WindowImpl.getThreadName()+", fin: dt "+ (System.nanoTime()-t0)/1e6 +"ms"); - Thread.dumpStack(); // JAU } } diff --git a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java new file mode 100644 index 000000000..f45b864fa --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java @@ -0,0 +1,508 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + + +package com.jogamp.newt.swt; + +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.Capabilities; +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.nativewindow.GraphicsConfigurationFactory; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindow; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.nativewindow.SurfaceUpdatedListener; +import javax.media.nativewindow.WindowClosingProtocol; +import javax.media.nativewindow.util.Insets; +import javax.media.nativewindow.util.InsetsImmutable; +import javax.media.nativewindow.util.Point; + +import jogamp.nativewindow.macosx.OSXUtil; +import jogamp.newt.Debug; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ControlAdapter; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Composite; + +import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.Display; +import com.jogamp.newt.Window; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.util.EDTUtil; + +public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol { + private static final boolean DEBUG = Debug.debug("Window"); + private static final boolean isOSX = NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false); + + /** SWT EDTUtil associated w/ parent's SWT Display */ + private final EDTUtil swtEDTUtil; + + private final AbstractGraphicsScreen screen; + + private WindowClosingMode newtChildCloseOp = WindowClosingMode.DISPOSE_ON_CLOSE; + private volatile Rectangle clientArea; + + private volatile SWTNativeWindow nativeWindow; + private volatile Window newtChild = null; + + /** + * Creates an instance using {@link #NewtCanvasSWT(Composite, int, Window)} + * on the SWT thread. + * + *

    + * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation + * via {@link Display#setEDTUtil(EDTUtil)}. + *

    + * + * @param parent the SWT composite + * @param style additional styles to SWT#NO_BACKGROUND + * @param child optional preassigned {@link #Window}, maybe null + * @return a new instance + */ + public static NewtCanvasSWT create(final Composite parent, final int style, final Window child) { + final NewtCanvasSWT[] res = new NewtCanvasSWT[] { null }; + parent.getDisplay().syncExec( new Runnable() { + public void run() { + res[0] = new NewtCanvasSWT( parent, style, child); + } + }); + return res[0]; + } + + /** + * Instantiates a NewtCanvas with a NEWT child. + * + *

    + * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation + * via {@link Display#setEDTUtil(EDTUtil)}. + *

    + * + * @param parent the SWT composite + * @param style additional styles to SWT#NO_BACKGROUND + * @param child optional preassigned {@link #Window}, maybe null + */ + public NewtCanvasSWT(final Composite parent, final int style, Window child) { + super(parent, style | SWT.NO_BACKGROUND); + + swtEDTUtil = new SWTEDTUtil(parent.getDisplay()); + + SWTAccessor.setRealized(this, true); + + clientArea = getClientArea(); + + final AbstractGraphicsDevice device = SWTAccessor.getDevice(this); + screen = SWTAccessor.getScreen(device, 0); + nativeWindow = null; + + if(null != child) { + setNEWTChild(child); + } + + /* Register SWT listeners (e.g. PaintListener) to render/resize GL surface. */ + /* TODO: verify that these do not need to be manually de-registered when destroying the SWT component */ + addPaintListener(new PaintListener() { + @Override + public void paintControl(final PaintEvent arg0) { + if( null != nativeWindow || validateNative() ) { + if( null !=newtChild ) { + newtChild.windowRepaint(0, 0, clientArea.width, clientArea.height); + } + } + } + }); + + addControlListener(new ControlAdapter() { + @Override + public void controlResized(final ControlEvent arg0) { + updateSizeCheck(); + } + }); + } + + /** assumes nativeWindow == null ! */ + protected final boolean validateNative() { + if( isDisposed() ) { + return false; + } + updateSizeCheck(); + final Rectangle nClientArea = clientArea; + if(0 == nClientArea.width * nClientArea.height) { + return false; + } + + /* Native handle for the control, used to associate with GLContext */ + final long nativeWindowHandle = SWTAccessor.getWindowHandle(this); + final int visualID = SWTAccessor.getNativeVisualID(screen.getDevice(), nativeWindowHandle); + final boolean visualIDValid = NativeWindowFactory.isNativeVisualIDValidForProcessing(visualID); + if(DEBUG) { + System.err.println("NewtCanvasSWT.validateNative() windowHandle 0x"+Long.toHexString(nativeWindowHandle)+", visualID 0x"+Integer.toHexString(visualID)+", valid "+visualIDValid); + } + if( visualIDValid ) { + /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite). + * Note: SWT is owner of the native handle, hence no closing operation will be a NOP. */ + final CapabilitiesImmutable caps = new Capabilities(); + final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(screen.getDevice(), caps); + final AbstractGraphicsConfiguration config = factory.chooseGraphicsConfiguration( caps, caps, null, screen, visualID ); + if(DEBUG) { + System.err.println("NewtCanvasSWT.validateNative() factory: "+factory+", windowHandle 0x"+Long.toHexString(nativeWindowHandle)+", visualID 0x"+Integer.toHexString(visualID)+", chosen config: "+config); + // Thread.dumpStack(); + } + if (null == config) { + throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); + } + + nativeWindow = new SWTNativeWindow(config, nativeWindowHandle); + reparentWindow( true ); + } + + return null != nativeWindow; + } + + protected final void updateSizeCheck() { + final Rectangle oClientArea = clientArea; + final Rectangle nClientArea = getClientArea(); + if ( nClientArea != null && + ( nClientArea.width != oClientArea.width || nClientArea.height != oClientArea.height ) + ) { + clientArea = nClientArea; // write back new value + if( null != newtChild ) { + newtChild.setSize(clientArea.width, clientArea.height); + } + } + } + + @Override + public void update() { + // don't paint background etc .. nop avoids flickering + } + + /** + * Destroys this resource: + *
      + *
    • Make the NEWT Child invisible
    • + *
    • Disconnects the NEWT Child from this Canvas NativeWindow, reparent to NULL
    • + *
    • Issues destroy() on the NEWT Child
    • + *
    • Remove reference to the NEWT Child
    • + *
    + * @see Window#destroy() + */ + @Override + public void dispose() { + if( null != newtChild ) { + if(DEBUG) { + System.err.println("NewtCanvasSWT.dispose.0: EDTUtil cur "+newtChild.getScreen().getDisplay().getEDTUtil()+ + ",\n\t"+newtChild); + } + configureNewtChild(false); + newtChild.setVisible(false); + newtChild.reparentWindow(null); + newtChild.destroy(); + newtChild = null; + } + nativeWindow = null; + super.dispose(); + } + + /** @return this SWT Canvas NativeWindow representation, may be null in case it has not been realized. */ + public NativeWindow getNativeWindow() { return nativeWindow; } + + public WindowClosingMode getDefaultCloseOperation() { + return newtChildCloseOp; // FIXME + } + + public WindowClosingMode setDefaultCloseOperation(WindowClosingMode op) { + return newtChildCloseOp = op; // FIXME + } + + + boolean isParent() { + return null!=newtChild ; + } + + boolean isFullscreen() { + return null != newtChild && newtChild.isFullscreen(); + } + + /** + * Sets a new NEWT child, provoking reparenting. + *

    + * A previously detached newChild will be released to top-level status + * and made invisible. + *

    + *

    + * Note: When switching NEWT child's, detaching the previous first via setNEWTChild(null) + * produced much cleaner visual results. + *

    + *

    + * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation + * via {@link Display#setEDTUtil(EDTUtil)}. + *

    + * @return the previous attached newt child. + */ + public Window setNEWTChild(final Window newChild) { + final Window prevChild = newtChild; + if(DEBUG) { + System.err.println("NewtCanvasSWT.setNEWTChild.0: win "+newtWinHandleToHexString(prevChild)+" -> "+newtWinHandleToHexString(newChild)); + } + // remove old one + if(null != newtChild) { + reparentWindow( false ); + newtChild = null; + } + // add new one, reparent only if ready + newtChild = newChild; + if(null != nativeWindow && null != newChild) { + reparentWindow( true ); + } + return prevChild; + } + + /** @return the current NEWT child */ + public Window getNEWTChild() { + return newtChild; + } + + @Override + public boolean setParent(Composite parent) { + return super.setParent(parent); + } + + /* package */ void configureNewtChild(boolean attach) { + + if( null != newtChild ) { + newtChild.setKeyboardFocusHandler(null); + if(attach) { + newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE); + } else { + newtChild.setFocusAction(null); + newtChild.setDefaultCloseOperation(newtChildCloseOp); + } + } + } + + void reparentWindow(boolean add) { + if( null == newtChild ) { + return; // nop + } + if(DEBUG) { + System.err.println("NewtCanvasSWT.reparentWindow.0: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()); + } + + newtChild.setFocusAction(null); // no AWT focus traversal .. + if(add) { + updateSizeCheck(); + final int w = clientArea.width; + final int h = clientArea.height; + + newtChild.getScreen().getDisplay().setEDTUtil(swtEDTUtil); + + newtChild.setSize(w, h); + newtChild.reparentWindow(nativeWindow); + newtChild.setVisible(true); + configureNewtChild(true); + newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener + + // force this SWT Canvas to be focus-able, + // since this it is completely covered by the newtChild (z-order). + setEnabled(true); + } else { + configureNewtChild(false); + newtChild.setVisible(false); + newtChild.reparentWindow(null); + } + if(DEBUG) { + System.err.println("NewtCanvasSWT.reparentWindow.X: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()); + } + } + + private final void requestFocusNEWTChild() { + if( null != newtChild ) { + newtChild.setFocusAction(null); + newtChild.requestFocus(); + } + } + + @Override + public boolean forceFocus() { + final boolean res = NewtCanvasSWT.super.forceFocus(); + requestFocusNEWTChild(); + return res; + } + + private class SWTNativeWindow implements NativeWindow { + private final AbstractGraphicsConfiguration config; + private final long nativeWindowHandle; + private final InsetsImmutable insets; // only required to allow proper client position calculation on OSX + + public SWTNativeWindow(AbstractGraphicsConfiguration config, long nativeWindowHandle) { + this.config = config; + this.nativeWindowHandle = nativeWindowHandle; + if(isOSX) { + this.insets = OSXUtil.GetInsets(nativeWindowHandle); + } else { + this.insets = new Insets(0, 0, 0, 0); + } + } + + @Override + public int lockSurface() throws NativeWindowException, RuntimeException { + return NativeSurface.LOCK_SUCCESS; + } + + @Override + public void unlockSurface() { } + + @Override + public boolean isSurfaceLockedByOtherThread() { + return false; + } + + @Override + public Thread getSurfaceLockOwner() { + return null; + } + + @Override + public boolean surfaceSwap() { + return false; + } + + @Override + public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { } + + @Override + public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException { + } + + @Override + public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) { } + + @Override + public long getSurfaceHandle() { + return 0; + } + + @Override + public int getWidth() { + return clientArea.width; + } + + @Override + public int getHeight() { + return clientArea.height; + } + + @Override + public AbstractGraphicsConfiguration getGraphicsConfiguration() { + return config; + } + + @Override + public long getDisplayHandle() { + return config.getScreen().getDevice().getHandle(); + } + + @Override + public int getScreenIndex() { + return config.getScreen().getIndex(); + } + + @Override + public void surfaceUpdated(Object updater, NativeSurface ns, long when) { } + + @Override + public void destroy() { } + + @Override + public NativeWindow getParent() { + return null; + } + + @Override + public long getWindowHandle() { + return nativeWindowHandle; + } + + @Override + public InsetsImmutable getInsets() { + return insets; + } + + @Override + public int getX() { + return 0; + } + + @Override + public int getY() { + return 0; + } + + @Override + public Point getLocationOnScreen(Point point) { + if( isOSX ) { + final Point los = OSXUtil.GetLocationOnScreen(nativeWindowHandle, false, 0, 0); + // top-level position -> client window position + los.setX(los.getX() + insets.getLeftWidth()); + los.setY(los.getY() + insets.getTopHeight()); + if(null!=point) { + return point.translate(los); + } else { + return los; + } + } else { + // client position on 'normal' windowing systems is 0/0 + if(null == point) { + point = new Point(0, 0); + } + return point; + } + } + + @Override + public boolean hasFocus() { + return isFocusControl(); + } + }; + + static String newtWinHandleToHexString(Window w) { + return null != w ? toHexString(w.getWindowHandle()) : "nil"; + } + static String toHexString(long l) { + return "0x"+Long.toHexString(l); + } +} + diff --git a/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java b/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java new file mode 100644 index 000000000..3538caad2 --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java @@ -0,0 +1,99 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.newt.swt; + +import org.eclipse.swt.widgets.Display; + +import com.jogamp.newt.util.EDTUtil; + +/** + * Simple {@link EDTUtil} implementation utilizing the SWT UI thread + * of the given {@link Display}. + */ +public class SWTEDTUtil implements EDTUtil { + private final Display swtDisplay; + + public SWTEDTUtil(Display swtDisplay) { + this.swtDisplay = swtDisplay; + } + + public final Display getDisplay() { + return swtDisplay; + } + + @Override + public long getPollPeriod() { + return 0; + } + + @Override + public void setPollPeriod(long ms) { + } + + @Override + public void reset() { + } + + @Override + public void start() { + } + + @Override + public boolean isCurrentThreadEDT() { + return swtDisplay.getThread() == Thread.currentThread(); + } + + @Override + public boolean isRunning() { + return true; + } + + @Override + public void invokeStop(Runnable finalTask) { + swtDisplay.syncExec(finalTask); + } + + @Override + public void invoke(boolean wait, Runnable task) { + if(wait) { + swtDisplay.syncExec(task); + } else { + swtDisplay.asyncExec(task); + } + } + + @Override + public void waitUntilIdle() { + // all sync .. + } + + @Override + public void waitUntilStopped() { + // all sync .. + } +} diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java index b10561c5b..b178bb5d3 100644 --- a/src/newt/classes/jogamp/newt/DisplayImpl.java +++ b/src/newt/classes/jogamp/newt/DisplayImpl.java @@ -101,7 +101,9 @@ public abstract class DisplayImpl extends Display { display.hashCode = display.fqname.hashCode(); displayList.add(display); } - display.createEDTUtil(); + if(null == display.edtUtil) { + display.setEDTUtil(null); // device's default if EDT is used, or null + } if(DEBUG) { System.err.println("Display.create() NEW: "+display+" "+getThreadName()); } @@ -168,15 +170,45 @@ public abstract class DisplayImpl extends Display { return true; } - protected void createEDTUtil() { + protected EDTUtil createEDTUtil() { + final EDTUtil def; if(NewtFactory.useEDT()) { - edtUtil = new DefaultEDTUtil(Thread.currentThread().getThreadGroup(), "Display-"+getFQName(), dispatchMessagesRunnable); + def = new DefaultEDTUtil(Thread.currentThread().getThreadGroup(), "Display-"+getFQName(), dispatchMessagesRunnable); if(DEBUG) { - System.err.println("Display.createNative("+getFQName()+") Create EDTUtil: "+edtUtil.getClass().getName()); + System.err.println("Display.createNative("+getFQName()+") Create EDTUtil: "+def.getClass().getName()); } + } else { + def = null; } + return def; } + @Override + public EDTUtil setEDTUtil(EDTUtil newEDTUtil) { + if(null == newEDTUtil) { + newEDTUtil = createEDTUtil(); + } + if( newEDTUtil == edtUtil ) { + if(DEBUG) { + System.err.println("Display.setEDTUtil: "+newEDTUtil+" - keep!"); + } + return null; // no change + } + final EDTUtil oldEDTUtil = edtUtil; + if(DEBUG) { + System.err.println("Display.setEDTUtil: "+oldEDTUtil+" -> "+newEDTUtil); + } + if(null != oldEDTUtil) { + stopEDT( new Runnable() { public void run() {} } ); + // ready for restart .. + oldEDTUtil.waitUntilStopped(); + oldEDTUtil.reset(); + } + edtUtil = newEDTUtil; + return oldEDTUtil; + } + + @Override public final EDTUtil getEDTUtil() { return edtUtil; } diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index b12e42680..606101ade 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -445,9 +445,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer protected abstract void closeNativeImpl(); /** - * The native implementation must invoke {@link #focusChanged(boolean, boolean)} - * to change the focus state, if force == false. - * This may happen asynchronous within {@link #TIMEOUT_NATIVEWINDOW}. + * Async request which shall be performed within {@link #TIMEOUT_NATIVEWINDOW}. + *

    + * If if force == false the native implementation + * may only request focus if not yet owner.

    + *

    + * {@link #focusChanged(boolean, boolean)} should be called + * to notify about the focus traversal. + *

    * * @param force if true, bypass {@link #focusChanged(boolean, boolean)} and force focus request */ diff --git a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java index ce8ed7c49..747e2368e 100644 --- a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java +++ b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java @@ -34,6 +34,7 @@ import javax.media.nativewindow.NativeWindow; import jogamp.newt.driver.DriverUpdatePosition; +import com.jogamp.newt.Window; import com.jogamp.newt.event.awt.AWTAdapter; import com.jogamp.newt.event.awt.AWTWindowAdapter; @@ -92,19 +93,20 @@ public class AWTParentWindowAdapter if(DEBUG_IMPLEMENTATION) { System.err.println("AWT: componentResized: "+comp); } - getNewtWindow().runOnEDTIfAvail(false, new Runnable() { + final Window newtWindow = getNewtWindow(); + newtWindow.runOnEDTIfAvail(false, new Runnable() { public void run() { int cw = comp.getWidth(); int ch = comp.getHeight(); if( 0 < cw * ch ) { - if( getNewtWindow().getWidth() != cw || getNewtWindow().getHeight() != ch ) { - getNewtWindow().setSize(cw, ch); - if(comp.isVisible() != getNewtWindow().isVisible()) { - getNewtWindow().setVisible(comp.isVisible()); + if( newtWindow.getWidth() != cw || newtWindow.getHeight() != ch ) { + newtWindow.setSize(cw, ch); + if(comp.isVisible() != newtWindow.isVisible()) { + newtWindow.setVisible(comp.isVisible()); } } - } else if(getNewtWindow().isVisible()) { - getNewtWindow().setVisible(false); + } else if(newtWindow.isVisible()) { + newtWindow.setVisible(false); } }}); } @@ -113,8 +115,9 @@ public class AWTParentWindowAdapter if(DEBUG_IMPLEMENTATION) { System.err.println("AWT: componentMoved: "+e); } - if(getNewtWindow().getDelegatedWindow() instanceof DriverUpdatePosition) { - ((DriverUpdatePosition)getNewtWindow().getDelegatedWindow()).updatePosition(); + final Window newtWindow = getNewtWindow(); + if(newtWindow.getDelegatedWindow() instanceof DriverUpdatePosition) { + ((DriverUpdatePosition)newtWindow.getDelegatedWindow()).updatePosition(); } } diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java b/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java index 166da5c1c..65f8b4715 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java +++ b/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java @@ -36,6 +36,7 @@ package jogamp.newt.driver.awt; import com.jogamp.nativewindow.awt.AWTGraphicsDevice; import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.util.EDTUtil; import jogamp.newt.DisplayImpl; @@ -54,13 +55,17 @@ public class AWTDisplay extends DisplayImpl { protected void closeNativeImpl() { } @Override - protected void createEDTUtil() { + protected EDTUtil createEDTUtil() { + final EDTUtil def; if(NewtFactory.useEDT()) { - edtUtil = AWTEDTUtil.getSingleton(); + def = AWTEDTUtil.getSingleton(); if(DEBUG) { - System.err.println("AWTDisplay.createNative("+getFQName()+") Create EDTUtil: "+edtUtil.getClass().getName()); + System.err.println("AWTDisplay.createNative("+getFQName()+") Create EDTUtil: "+def.getClass().getName()); } + } else { + def = null; } + return def; } protected void dispatchMessagesNative() { /* nop */ } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java index 720d4ee4c..27d7a1679 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java @@ -150,7 +150,7 @@ public class MacWindow extends WindowImpl implements MutableSurface, DriverClear System.err.println("MacWindow: clearFocus() - requestFocusParent, isOffscreenInstance "+isOffscreenInstance); } if(!isOffscreenInstance) { - requestFocusParent0(getWindowHandle()); + resignFocus0(getWindowHandle()); } else { focusChanged(false, false); } @@ -360,7 +360,6 @@ public class MacWindow extends WindowImpl implements MutableSurface, DriverClear if(recreate && 0==surfaceHandle) { throw new NativeWindowException("Internal Error - recreate, window but no view"); } - orderOut0(getWindowHandle()); close0(getWindowHandle()); setWindowHandle(0); } else { @@ -397,7 +396,7 @@ public class MacWindow extends WindowImpl implements MutableSurface, DriverClear private native boolean lockSurface0(long window); private native void unlockSurface0(long window); private native void requestFocus0(long window, boolean force); - private native void requestFocusParent0(long window); + private native void resignFocus0(long window); /** in case of a child window, it actually only issues orderBack(..) */ private native void orderOut0(long window); private native void orderFront0(long window); diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java b/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java index 34d76a148..6a8c81f3d 100644 --- a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java +++ b/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java @@ -151,8 +151,8 @@ public class WindowsWindow extends WindowImpl { } protected void closeNativeImpl() { - if (hdc != 0) { - if(windowHandleClose != 0) { + if(windowHandleClose != 0) { + if (hdc != 0) { try { GDI.ReleaseDC(windowHandleClose, hdc); } catch (Throwable t) { @@ -162,11 +162,8 @@ public class WindowsWindow extends WindowImpl { } } } - hdc = 0; - hdc_old = 0; - } - if(windowHandleClose != 0) { try { + GDI.SetParent(windowHandleClose, 0); // detach first, experience hang w/ SWT parent GDI.DestroyWindow(windowHandleClose); } catch (Throwable t) { if(DEBUG_IMPLEMENTATION) { @@ -177,6 +174,8 @@ public class WindowsWindow extends WindowImpl { windowHandleClose = 0; } } + hdc = 0; + hdc_old = 0; } protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index 01cbd80ec..bbadc9dd0 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -599,6 +599,15 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_createWindow0 } DBG_PRINT( "createWindow0 - is visible.1: %d\n", [myWindow isVisible]); + // Remove animations for child windows + if(NULL != parentWindow) { +NS_DURING + // Available >= 10.7 - Removes default animations + [myWindow setAnimationBehavior: NSWindowAnimationBehaviorNone]; +NS_HANDLER +NS_ENDHANDLER + } + #ifdef VERBOSE_ON int dbgIdx = 1; #endif @@ -734,7 +743,7 @@ NS_ENDHANDLER if(NULL!=pWin) { [mWin detachFromParent: pWin]; } - [mWin orderOut: mWin]; + [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO]; DBG_PRINT( "windowClose.1 - %p,%d view %p,%d, parent %p\n", mWin, getRetainCount(mWin), mView, getRetainCount(mView), pWin); @@ -742,11 +751,6 @@ NS_ENDHANDLER // Only release window, if release is not yet in process. // E.g. destroyNotifySent:=true set by NewtMacWindow::windowWillClose(), i.e. window-close was clicked. if(!destroyNotifySent) { - // '[mWin close]' causes a crash at exit. - // This probably happens b/c it sends events to the main loop - // but our resources are gone ?! - // However, issuing a simple release seems to work quite well. - // [mWin release]; [mWin performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO]; } @@ -806,11 +810,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocus0 DBG_PRINT( "requestFocus - window: %p, force %d, hasFocus %d (START)\n", mWin, force, hasFocus); [mWin makeFirstResponder: nil]; - [mWin performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:YES]; - [mWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:YES]; - // This will occasionally cause a free of non allocated object crash: - // [mWin orderFrontRegardless]; - // [mWin makeKeyWindow]; + [mWin performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:NO]; + [mWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:NO]; DBG_PRINT( "requestFocus - window: %p, force %d (END)\n", mWin, force); @@ -819,26 +820,27 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocus0 /* * Class: jogamp_newt_driver_macosx_MacWindow - * Method: requestFocusParent0 + * Method: resignFocus0 * Signature: (J)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocusParent0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_resignFocus0 (JNIEnv *env, jobject window, jlong w) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* mWin = (NSWindow*) ((intptr_t) w); NSWindow* pWin = [mWin parentWindow]; -#ifdef VERBOSE_ON BOOL hasFocus = [mWin isKeyWindow]; -#endif - DBG_PRINT( "requestFocusParent0 - window: %p, parent: %p, hasFocus %d (START)\n", mWin, pWin, hasFocus ); - if(NULL != pWin) { - [pWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:YES]; - // This will occasionally cause a free of non allocated object crash: - // [pWin makeKeyWindow]; + DBG_PRINT( "requestFocusParent0 - window: %p, parent %p, hasFocus %d (START)\n", mWin, pWin, hasFocus ); + if( hasFocus ) { + if(NULL != pWin) { + // [mWin performSelectorOnMainThread:@selector(makeFirstResponder:) withObject:pWin waitUntilDone:NO]; + [pWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:NO]; + } else { + [mWin performSelectorOnMainThread:@selector(resignKeyWindow) withObject:nil waitUntilDone:NO]; + } } - DBG_PRINT( "requestFocusParent0 - window: %p, parent: %p (END)\n", mWin, pWin); + DBG_PRINT( "requestFocusParent0 - window: %p (END)\n", mWin); [pool release]; } @@ -856,9 +858,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_orderFront0 DBG_PRINT( "orderFront0 - window: %p (START)\n", win); - [win performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:YES]; - // This will occasionally cause a free of non allocated object crash: - // [win orderFrontRegardless]; + [win performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:NO]; DBG_PRINT( "orderFront0 - window: %p (END)\n", win); @@ -880,13 +880,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_orderOut0 DBG_PRINT( "orderOut0 - window: (parent %p) %p (START)\n", pWin, mWin); if(NULL == pWin) { - [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:YES]; - // This will occasionally cause a free of non allocated object crash: - // [mWin orderOut: mWin]; + [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO]; } else { - [mWin performSelectorOnMainThread:@selector(orderBack:) withObject:mWin waitUntilDone:YES]; - // This will occasionally cause a free of non allocated object crash: - // [mWin orderBack: mWin]; + [mWin performSelectorOnMainThread:@selector(orderBack:) withObject:mWin waitUntilDone:NO]; } DBG_PRINT( "orderOut0 - window: (parent %p) %p (END)\n", pWin, mWin); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java new file mode 100644 index 000000000..6a27e6f27 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java @@ -0,0 +1,233 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.swt; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.After; +import org.junit.Test; + +import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.swt.NewtCanvasSWT; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; + +/** + * Tests that a basic SWT app can open without crashing under different GL profiles + * _and_ custom GLCapabilities. + *

    + * Uses JOGL's NewtCanvasSWT, which allows to be a native container of a NEWT Window.
    + * This method allows utilizing custom GLCapability settings, + * independent from the already instantiated SWT visual. + *

    + *

    + * Note that {@link SWTAccessor#invoke(boolean, Runnable)} is still used to comply w/ + * SWT running on Mac OSX, i.e. to enforce UI action on the main thread. + *

    + */ +public class TestNewtCanvasSWTGLn extends UITestCase { + + static int duration = 250; + + static final int iwidth = 640; + static final int iheight = 480; + + Display display = null; + Shell shell = null; + Composite composite = null; + + @BeforeClass + public static void startup() { + System.out.println( "GLProfile " + GLProfile.glAvailabilityToString() ); + } + + @Before + public void init() { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display = new Display(); + Assert.assertNotNull( display ); + shell = new Shell( display ); + Assert.assertNotNull( shell ); + shell.setLayout( new FillLayout() ); + composite = new Composite( shell, SWT.NONE ); + composite.setLayout( new FillLayout() ); + Assert.assertNotNull( composite ); + }}); + } + + @After + public void release() { + Assert.assertNotNull( display ); + Assert.assertNotNull( shell ); + Assert.assertNotNull( composite ); + try { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + composite.dispose(); + shell.dispose(); + display.dispose(); + }}); + } + catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + display = null; + shell = null; + composite = null; + } + + protected void runTestAGL( GLCapabilitiesImmutable caps, GLEventListener demo, + boolean postAttach, boolean useAnimator ) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); + + final GLWindow glWindow1 = GLWindow.create(caps); + Assert.assertNotNull(glWindow1); + Assert.assertEquals(false, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow1.isNativeValid()); + Assert.assertNull(glWindow1.getParent()); + glWindow1.addGLEventListener(demo); + glWindow1.addGLEventListener(new GLEventListener() { + int displayCount = 0; + public void init(final GLAutoDrawable drawable) { } + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { } + public void display(final GLAutoDrawable drawable) { + if(displayCount < 3) { + snapshot(getSimpleTestName("."), displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + } + } + public void dispose(final GLAutoDrawable drawable) { } + }); + + final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( composite, 0, postAttach ? null : glWindow1 ); + Assert.assertNotNull( canvas1 ); + + SWTAccessor.invoke(true, new Runnable() { + public void run() { + shell.setText( getSimpleTestName(".") ); + shell.setSize( 640, 480 ); + shell.open(); + } + }); + + if(postAttach) { + canvas1.setNEWTChild(glWindow1); + } + + // canvas1.update(); + + Animator anim; + if(useAnimator) { + anim = new Animator(glWindow1); + anim.start(); + } else { + anim = null; + } + + long lStartTime = System.currentTimeMillis(); + long lEndTime = lStartTime + duration; + try { + while( (System.currentTimeMillis() < lEndTime) && !canvas1.isDisposed() ) { + if( !display.readAndDispatch() ) { + // blocks on linux .. display.sleep(); + Thread.sleep(10); + } + } + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + if(null != anim) { + anim.stop(); + } + + canvas1.dispose(); + } + + @Test + public void preAttach_WithAnimator() throws InterruptedException { + runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), false /* postAttach */, true /* animator */); + } + + @Test + public void preAttach_NoAnimator() throws InterruptedException { + runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), false /* postAttach */, false /* animator */); + } + + @Test + public void postAttach_WithAnimator() throws InterruptedException { + runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), true /* postAttach */, true /* animator */); + } + + @Test + public void test_MultisampleAndAlpha() throws InterruptedException { + GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2()); + caps.setSampleBuffers(true); + caps.setNumSamples(2); + runTestAGL( caps, new MultisampleDemoES2(true), false /* postAttach */, false /* animator */); + } + + static int atoi(String a) { + int i=0; + try { + i = Integer.parseInt(a); + } catch (Exception ex) { ex.printStackTrace(); } + return i; + } + + public static void main(String args[]) { + for(int i=0; i - * Uses JOGL's SWTAccessor only. - *

    - * @author Wade Walker, et.al. - */ -public class TestSWTAccessor02GLn extends UITestCase { - - static int duration = 250; - - static final int iwidth = 640; - static final int iheight = 480; - - Display display = null; - Shell shell = null; - Composite composite = null; - - @BeforeClass - public static void startup() { - System.out.println( "GLProfile " + GLProfile.glAvailabilityToString() ); - } - - @Before - public void init() { - SWTAccessor.invoke(true, new Runnable() { - public void run() { - display = new Display(); - Assert.assertNotNull( display ); - shell = new Shell( display ); - Assert.assertNotNull( shell ); - shell.setLayout( new FillLayout() ); - composite = new Composite( shell, SWT.NONE ); - composite.setLayout( new FillLayout() ); - Assert.assertNotNull( composite ); - }}); - } - - @After - public void release() { - Assert.assertNotNull( display ); - Assert.assertNotNull( shell ); - Assert.assertNotNull( composite ); - try { - SWTAccessor.invoke(true, new Runnable() { - public void run() { - composite.dispose(); - shell.dispose(); - display.dispose(); - }}); - } - catch( Throwable throwable ) { - throwable.printStackTrace(); - Assume.assumeNoException( throwable ); - } - display = null; - shell = null; - composite = null; - } - - protected void runTestAGL( GLProfile glprofile ) throws InterruptedException { - GLCapabilities caps = new GLCapabilities(glprofile); - GLDrawableFactory factory = GLDrawableFactory.getFactory(glprofile); - - // need SWT.NO_BACKGROUND to prevent SWT from clearing the window - // at the wrong times (we use glClear for this instead) - final Canvas canvas = new Canvas( composite, SWT.NO_BACKGROUND); - Assert.assertNotNull( canvas ); - SWTAccessor.setRealized(canvas, true); - - AbstractGraphicsDevice device = SWTAccessor.getDevice(canvas); - long nativeWindowHandle = SWTAccessor.getWindowHandle(canvas); - System.err.println("*** device: " + device); - System.err.println("*** window handle: 0x" + Long.toHexString(nativeWindowHandle)); - - final SWTUpstreamHook swtUpstreamHook = new SWTUpstreamHook(canvas); - canvas.addControlListener(swtUpstreamHook); - - final ProxySurface proxySurface = factory.createProxySurface(device, 0, nativeWindowHandle, caps, null, swtUpstreamHook); - Assert.assertNotNull( proxySurface ); - System.err.println("*** ProxySurface: " + proxySurface); - - final GLDrawable drawable = factory.createGLDrawable(proxySurface); - Assert.assertNotNull( drawable ); - drawable.setRealized(true); - System.err.println("*** Drawable: " + drawable); - Assert.assertTrue( drawable.isRealized() ); - - final GLContext glcontext = drawable.createContext(null); - // trigger native creation .. - if( GLContext.CONTEXT_NOT_CURRENT < glcontext.makeCurrent() ) { - glcontext.release(); - } - - final boolean[] sizeMissing = new boolean[] { false }; - - // fix the viewport when the user resizes the window - canvas.addListener( SWT.Resize, new Listener() { - public void handleEvent( Event event ) { - Rectangle rectangle = canvas.getClientArea(); - boolean glok=false; - if( GLContext.CONTEXT_NOT_CURRENT < glcontext.makeCurrent() ) { - glok=true; - GL2ES1 gl = glcontext.getGL().getGL2ES1(); - OneTriangle.setup( gl, rectangle.width, rectangle.height ); - glcontext.release(); - } else { - sizeMissing[0] = true; - } - System.err.println("resize: glok " + glok); - } - }); - - // draw the triangle when the OS tells us that any part of the window needs drawing - canvas.addPaintListener( new PaintListener() { - public void paintControl( PaintEvent paintevent ) { - Rectangle rectangle = canvas.getClientArea(); - boolean glok=false; - if( GLContext.CONTEXT_NOT_CURRENT < glcontext.makeCurrent() ) { - glok=true; - GL2ES1 gl = glcontext.getGL().getGL2ES1(); - if(sizeMissing[0]) { - OneTriangle.setup( gl, rectangle.width, rectangle.height); - sizeMissing[0] = false; - } - OneTriangle.render( gl, rectangle.width, rectangle.height); - drawable.swapBuffers(); - glcontext.release(); - } - System.err.println("paint: glok " + glok); - } - }); - - shell.setText( getClass().getName() ); - shell.setSize( 640, 480 ); - shell.open(); - - long lStartTime = System.currentTimeMillis(); - long lEndTime = lStartTime + duration; - try { - while( (System.currentTimeMillis() < lEndTime) && !canvas.isDisposed() ) { - if( !display.readAndDispatch() ) { - // blocks on linux .. display.sleep(); - Thread.sleep(10); - } - } - } catch( Throwable throwable ) { - throwable.printStackTrace(); - Assume.assumeNoException( throwable ); - } - glcontext.destroy(); - drawable.setRealized(false); - canvas.dispose(); - } - private static class SWTUpstreamHook implements ProxySurface.UpstreamSurfaceHook, ControlListener { - private Canvas c; - Rectangle clientArea; - public SWTUpstreamHook(Canvas c) { - this.c = c ; - this.clientArea = c.getClientArea(); - } - @Override - public final void create(ProxySurface s) { /* nop */ } - - @Override - public final void destroy(ProxySurface s) { /* nop */ } - - @Override - public final int getWidth(ProxySurface s) { - return clientArea.width; - } - @Override - public final int getHeight(ProxySurface s) { - return clientArea.width; - } - - @Override - public void controlResized(final ControlEvent arg0) { - clientArea = c.getClientArea(); - } - @Override - public void controlMoved(ControlEvent e) { - } - @Override - public String toString() { - final String us_s = null != c ? c.toString() : "nil"; - return "SETUpstreamSurfaceHook[upstream: "+us_s+"]"; - } - }; - - @Test - public void test() throws InterruptedException { - GLProfile glprofile = GLProfile.getGL2ES1(); - runTestAGL( glprofile ); - } - - static int atoi(String a) { - int i=0; - try { - i = Integer.parseInt(a); - } catch (Exception ex) { ex.printStackTrace(); } - return i; - } - - public static void main(String args[]) { - for(int i=0; i *

    + * Note: To employ custom GLCapabilities, NewtCanvasSWT shall be used. + *

    + *

    * Note that {@link SWTAccessor#invoke(boolean, Runnable)} is still used to comply w/ * SWT running on Mac OSX, i.e. to enforce UI action on the main thread. *

    @@ -116,34 +121,32 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase { composite = null; } - protected void runTestAGL( GLProfile glprofile ) throws InterruptedException { - // need SWT.NO_BACKGROUND to prevent SWT from clearing the window - // at the wrong times (we use glClear for this instead) - final GLCapabilitiesImmutable caps = new GLCapabilities( glprofile ); + protected void runTestAGL( GLCapabilitiesImmutable caps, GLEventListener demo ) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); - final GLCanvas canvas = new GLCanvas( composite, 0, caps, null, null); + final GLCanvas canvas = GLCanvas.create( composite, 0, caps, null, null); Assert.assertNotNull( canvas ); + canvas.addGLEventListener( demo ); canvas.addGLEventListener(new GLEventListener() { - public void init(final GLAutoDrawable drawable) { - System.err.println(Thread.currentThread().getName()+" - SWT Canvas - GLEventListener - init()"); - } - public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { - System.err.println(Thread.currentThread().getName()+" - SWT Canvas - GLEventListener - reshape()"); - OneTriangle.setup( drawable.getGL().getGL2(), width, height ); - } + int displayCount = 0; + public void init(final GLAutoDrawable drawable) { } + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { } public void display(final GLAutoDrawable drawable) { - OneTriangle.render( drawable.getGL().getGL2(), drawable.getWidth(), drawable.getHeight()); + if(displayCount < 3) { + snapshot(getSimpleTestName("."), displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + } } - public void dispose(final GLAutoDrawable drawable) { - System.err.println(Thread.currentThread().getName()+" - SWT Canvas - GLEventListener - dispose()"); - } - }); + public void dispose(final GLAutoDrawable drawable) { } + }); - shell.setText( getClass().getName() ); - shell.setSize( 640, 480 ); - shell.open(); - + SWTAccessor.invoke(true, new Runnable() { + public void run() { + shell.setText( getSimpleTestName(".") ); + shell.setSize( 640, 480 ); + shell.open(); + } } ); + long lStartTime = System.currentTimeMillis(); long lEndTime = lStartTime + duration; try { @@ -157,13 +160,15 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase { throwable.printStackTrace(); Assume.assumeNoException( throwable ); } - canvas.dispose(); + SWTAccessor.invoke(true, new Runnable() { + public void run() { + canvas.dispose(); + } } ); } @Test public void test() throws InterruptedException { - GLProfile glprofile = GLProfile.getGL2ES1(); - runTestAGL( glprofile ); + runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2() ); } static int atoi(String a) { diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java new file mode 100644 index 000000000..11aef7c24 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java @@ -0,0 +1,210 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.newt.parenting; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.junit.After; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.Window; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.swt.NewtCanvasSWT; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Simple visibility test .. + */ +public class TestParenting01aSWT extends UITestCase { + static int width, height; + static long durationPerTest = 800; + static GLCapabilities glCaps; + + Display display = null; + Shell shell = null; + Composite composite1 = null; + + @BeforeClass + public static void initClass() { + width = 640; + height = 480; + glCaps = new GLCapabilities(null); + } + + @Before + public void init() { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display = new Display(); + Assert.assertNotNull( display ); + shell = new Shell( display ); + Assert.assertNotNull( shell ); + shell.setLayout( new FillLayout() ); + composite1 = new Composite( shell, SWT.NONE ); + composite1.setLayout( new FillLayout() ); + Assert.assertNotNull( composite1 ); + }}); + } + + @After + public void release() { + Assert.assertNotNull( display ); + Assert.assertNotNull( shell ); + Assert.assertNotNull( composite1 ); + try { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + composite1.dispose(); + shell.dispose(); + display.dispose(); + }}); + } + catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + display = null; + shell = null; + composite1 = null; + } + + @Test + public void testWindowParenting01CreateVisibleDestroy1() throws InterruptedException, InvocationTargetException { + + GLWindow glWindow1 = GLWindow.create(glCaps); + Assert.assertNotNull(glWindow1); + Assert.assertEquals(false, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow1.isNativeValid()); + Assert.assertNull(glWindow1.getParent()); + glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy"); + GLEventListener demo1 = new RedSquareES2(); + setDemoFields(demo1, glWindow1, false); + glWindow1.addGLEventListener(demo1); + + final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( composite1, 0, glWindow1 ); + Assert.assertNotNull(canvas1); + Assert.assertEquals(false, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow1.isNativeValid()); + Assert.assertNull(glWindow1.getParent()); + + SWTAccessor.invoke(true, new Runnable() { + public void run() { + shell.setText( getSimpleTestName(".") ); + shell.setSize( 640, 480 ); + shell.open(); + } + }); + + // visible test + Assert.assertEquals(canvas1.getNativeWindow(),glWindow1.getParent()); + + for(int i=0; i*10 2 + if(detachFirst) { + canvas1.setNEWTChild(null); + canvas2.setNEWTChild(null); + } else { + canvas2.setNEWTChild(null); // free g2 of w2 + } + canvas1.setNEWTChild(glWindow2); // put g2 -> w1. free g1 of w1 + canvas2.setNEWTChild(glWindow1); // put g1 -> w2 + frame1.validate(); + frame2.validate(); + } + }); + break; + case 1: + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + // 2 -> 1 + if(detachFirst) { + canvas1.setNEWTChild(null); + canvas2.setNEWTChild(null); + } else { + canvas2.setNEWTChild(null); + } + canvas1.setNEWTChild(glWindow1); + canvas2.setNEWTChild(glWindow2); + frame1.validate(); + frame2.validate(); + } + }); + break; + } + } + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.dispose(); + frame2.dispose(); + } } ); + glWindow1.destroy(); + glWindow2.destroy(); + Assert.assertEquals(false, glWindow1.isNativeValid()); + Assert.assertEquals(false, glWindow2.isNativeValid()); + } + + public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) { + Assert.assertNotNull(demo); + Assert.assertNotNull(glWindow); + Window window = glWindow.getDelegatedWindow(); + if(debug) { + MiscUtils.setFieldIfExists(demo, "glDebug", true); + MiscUtils.setFieldIfExists(demo, "glTrace", true); + } + if(!MiscUtils.setFieldIfExists(demo, "window", window)) { + MiscUtils.setFieldIfExists(demo, "glWindow", glWindow); + } + } + + static int atoi(String a) { + int i=0; + try { + i = Integer.parseInt(a); + } catch (Exception ex) { ex.printStackTrace(); } + return i; + } + + public static void main(String args[]) throws IOException { + for(int i=0; i 2 + if(detachFirst) { + canvas1.setNEWTChild(null); + canvas2.setNEWTChild(null); + } else { + canvas2.setNEWTChild(null); // free g2 of w2 + } + canvas1.setNEWTChild(glWindow2); // put g2 -> w1. free g1 of w1 + canvas2.setNEWTChild(glWindow1); // put g1 -> w2 + } } ); + break; + case 1: + SWTAccessor.invoke(true, new Runnable() { + public void run() { + // 2 -> 1 + if(detachFirst) { + canvas1.setNEWTChild(null); + canvas2.setNEWTChild(null); + } else { + canvas2.setNEWTChild(null); + } + canvas1.setNEWTChild(glWindow1); + canvas2.setNEWTChild(glWindow2); + } } ); + break; + } + } + + canvas1.dispose(); + canvas2.dispose(); + Assert.assertEquals(false, glWindow1.isNativeValid()); + Assert.assertEquals(false, glWindow2.isNativeValid()); + } + + public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) { + Assert.assertNotNull(demo); + Assert.assertNotNull(glWindow); + Window window = glWindow.getDelegatedWindow(); + if(debug) { + MiscUtils.setFieldIfExists(demo, "glDebug", true); + MiscUtils.setFieldIfExists(demo, "glTrace", true); + } + if(!MiscUtils.setFieldIfExists(demo, "window", window)) { + MiscUtils.setFieldIfExists(demo, "glWindow", glWindow); + } + } + + static int atoi(String a) { + int i=0; + try { + i = Integer.parseInt(a); + } catch (Exception ex) { ex.printStackTrace(); } + return i; + } + + public static void main(String args[]) throws IOException { + for(int i=0; i Date: Fri, 3 Aug 2012 01:38:37 +0300 Subject: Fix X11 Display Connection leak w/ new GLAutoDrawableBase code when used w/ offscreen drawables, reported by Mark Raynsford New common GLAutoDrawableBase missed to close the AbstractGraphicsDevice in case it has been created and dedicated for the passed GLDrawable. This detailed knowledge is only known to the creator, hence it is passed in the constructor and is being passed through all specializations. Further more the new X11/GLX impl. of GLDrawableFactory's 'createMutableSurfaceImpl' always creates it's own private X11 display connection to avoid locking / threading issues. Since the old implementation reused the shared display connection which is prone to threading issues, this bug was not visible before. Also fixed the unit test TestNEWTCloseX11DisplayBug565, now correctly validating that no display connection is left over after a new cycle of create/destroy of onscreen and offscreen drawables. --- make/scripts/tests.sh | 6 ++-- .../com/jogamp/opengl/OffscreenAutoDrawable.java | 13 ++++++-- .../javax/media/opengl/GLAutoDrawableDelegate.java | 14 +++++--- .../classes/jogamp/opengl/GLAutoDrawableBase.java | 39 ++++++++++++++++------ .../jogamp/opengl/GLDrawableFactoryImpl.java | 2 +- src/jogl/classes/jogamp/opengl/GLPbufferImpl.java | 4 +-- .../classes/jogamp/nativewindow/x11/X11Util.java | 2 +- .../classes/com/jogamp/newt/opengl/GLWindow.java | 2 +- .../test/junit/jogl/acore/TestFBODrawableNEWT.java | 2 +- .../jogl/acore/TestGLAutoDrawableDelegateNEWT.java | 2 +- .../acore/TestGLContextDrawableSwitchNEWT.java | 2 +- .../jogl/acore/TestNEWTCloseX11DisplayBug565.java | 8 ++--- 12 files changed, 64 insertions(+), 32 deletions(-) (limited to 'src/jogl/classes/jogamp/opengl') diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index af6218968..43d04c6bd 100755 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -61,7 +61,7 @@ function jrun() { #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all" #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all -Djogamp.debug.Lock" #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all" - D_ARGS="-Dnewt.debug.Window" + #D_ARGS="-Dnewt.debug.Window" #D_ARGS="-Djogl.debug.GLDrawable" #D_ARGS="-Djogl.debug.EGLDrawableFactory.DontQuery -Djogl.debug.GLDrawable" #D_ARGS="-Djogl.debug.EGLDrawableFactory.QueryNativeTK -Djogl.debug.GLDrawable" @@ -217,7 +217,7 @@ function testawtswt() { #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFloatUtil01MatrixMatrixMultNOUI $* -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestNEWTCloseX11DisplayBug565 $* +testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestNEWTCloseX11DisplayBug565 $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLWindowNEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile01NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestShutdownCompleteNEWT $* @@ -328,7 +328,7 @@ function testawtswt() { #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting03AWT $* #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting04AWT $* #testawtswt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01aSWT $* -testawtswt com.jogamp.opengl.test.junit.newt.parenting.TestParenting04SWT $* +#testawtswt com.jogamp.opengl.test.junit.newt.parenting.TestParenting04SWT $* #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingFocusTraversal01AWT $* #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingOffscreenLayer01GLCanvasAWT $* #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingOffscreenLayer02NewtCanvasAWT $* diff --git a/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java b/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java index 1ea8595c6..8450ffdb0 100644 --- a/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java +++ b/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java @@ -28,6 +28,7 @@ package com.jogamp.opengl; +import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.opengl.GLAutoDrawableDelegate; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; @@ -45,8 +46,16 @@ import jogamp.opengl.GLFBODrawableImpl; */ public class OffscreenAutoDrawable extends GLAutoDrawableDelegate { - public OffscreenAutoDrawable(GLDrawable drawable, GLContext context, Object upstreamWidget) { - super(drawable, context, upstreamWidget); + /** + * @param drawable a valid {@link GLDrawable}, may not be realized yet. + * @param context a valid {@link GLContext}, may not be made current (created) yet. + * @param ownDevice pass true if {@link AbstractGraphicsDevice#close()} shall be issued, + * otherwise pass false. Closing the device is required in case + * the drawable is created w/ it's own new instance, e.g. offscreen drawables, + * and no further lifecycle handling is applied. + */ + public OffscreenAutoDrawable(GLDrawable drawable, GLContext context, boolean ownDevice) { + super(drawable, context, null, ownDevice); } /** diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java index 76959f3f4..67e81270d 100644 --- a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java +++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java @@ -28,6 +28,8 @@ package javax.media.opengl; +import javax.media.nativewindow.AbstractGraphicsDevice; + import com.jogamp.common.util.locks.LockFactory; import com.jogamp.common.util.locks.RecursiveLock; @@ -57,12 +59,16 @@ public class GLAutoDrawableDelegate extends GLAutoDrawableBase { public static final boolean DEBUG = Debug.debug("GLAutoDrawableDelegate"); /** - * @param drawable - * @param context + * @param drawable a valid {@link GLDrawable}, may not be realized yet. + * @param context a valid {@link GLContext}, may not be made current (created) yet. * @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}. + * @param ownDevice pass true if {@link AbstractGraphicsDevice#close()} shall be issued, + * otherwise pass false. Closing the device is required in case + * the drawable is created w/ it's own new instance, e.g. offscreen drawables, + * and no further lifecycle handling is applied. */ - public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context, Object upstreamWidget) { - super((GLDrawableImpl)drawable, (GLContextImpl)context); + public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context, Object upstreamWidget, boolean ownDevice) { + super((GLDrawableImpl)drawable, (GLContextImpl)context, ownDevice); this.upstreamWidget = null; } diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java index fe6d0fd76..cc4e1b434 100644 --- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java +++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java @@ -30,6 +30,8 @@ package jogamp.opengl; import java.io.PrintStream; +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.WindowClosingProtocol; import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode; @@ -66,13 +68,23 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { protected volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access protected GLContextImpl context; + protected final boolean ownDevice; protected int additionalCtxCreationFlags = 0; protected volatile boolean sendReshape = false; // volatile: maybe written by WindowManager thread w/o locking protected volatile boolean sendDestroy = false; // volatile: maybe written by WindowManager thread w/o locking - public GLAutoDrawableBase(GLDrawableImpl drawable, GLContextImpl context) { + /** + * @param drawable a valid {@link GLDrawableImpl}, may not be realized yet. + * @param context a valid {@link GLContextImpl}, may not be made current (created) yet. + * @param ownDevice pass true if {@link AbstractGraphicsDevice#close()} shall be issued, + * otherwise pass false. Closing the device is required in case + * the drawable is created w/ it's own new instance, e.g. offscreen drawables, + * and no further lifecycle handling is applied. + */ + public GLAutoDrawableBase(GLDrawableImpl drawable, GLContextImpl context, boolean ownDevice) { this.drawable = drawable; this.context = context; + this.ownDevice = ownDevice; resetFPSCounter(); } @@ -174,7 +186,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { } /** - * Calls {@link #destroyImplInLock()} while claiming the lock. + * Calls {@link #destroyImplInLock()} while claiming the lock. */ protected final void defaultDestroy() { final RecursiveLock lock = getLock(); @@ -200,17 +212,22 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { protected void destroyImplInLock() { final GLContext _context = context; final GLDrawable _drawable = drawable; - if( null != _drawable && _drawable.isRealized() ) { - if( null != _context && _context.isCreated() ) { - // Catch dispose GLExceptions by GLEventListener, just 'print' them - // so we can continue with the destruction. - try { - helper.disposeGL(this, _drawable, _context, null); - } catch (GLException gle) { - gle.printStackTrace(); + if( null != _drawable ) { + if( _drawable.isRealized() ) { + if( null != _context && _context.isCreated() ) { + // Catch dispose GLExceptions by GLEventListener, just 'print' them + // so we can continue with the destruction. + try { + helper.disposeGL(this, _drawable, _context, null); + } catch (GLException gle) { + gle.printStackTrace(); + } } + _drawable.setRealized(false); + } + if( ownDevice ) { + _drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice().close(); } - _drawable.setRealized(false); } context = null; drawable = null; diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java index f092288fb..f7808294b 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java @@ -245,7 +245,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { if(null==drawable) { throw new GLException("Could not create Pbuffer drawable for: "+device+", "+capsChosen+", "+width+"x"+height); } - return new GLPbufferImpl( drawable, shareWith); + return new GLPbufferImpl( drawable, shareWith, true); } //--------------------------------------------------------------------------- diff --git a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java index 6b64120fe..32f4cb696 100644 --- a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java @@ -58,8 +58,8 @@ import com.jogamp.common.util.locks.RecursiveLock; public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer { private int floatMode; - public GLPbufferImpl(GLDrawableImpl pbufferDrawable, GLContext sharedContext) { - super(pbufferDrawable, null); // drawable := pbufferDrawable + public GLPbufferImpl(GLDrawableImpl pbufferDrawable, GLContext sharedContext, boolean ownDevice) { + super(pbufferDrawable, null, ownDevice); // drawable := pbufferDrawable GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) drawable.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities(); diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java index fcc374751..7b46a1df0 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java +++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java @@ -255,7 +255,7 @@ public class X11Util { */ public static int shutdown(boolean realXCloseOpenAndPendingDisplays, boolean verbose) { int num=0; - if(DEBUG||verbose||pendingDisplayList.size() > 0) { + if(DEBUG || verbose || openDisplayMap.size() > 0 || pendingDisplayList.size() > 0) { System.err.println("X11Util.Display: Shutdown (close open / pending Displays: "+realXCloseOpenAndPendingDisplays+ ", open (no close attempt): "+openDisplayMap.size()+"/"+openDisplayList.size()+ ", pending (not closed, marked uncloseable): "+pendingDisplayList.size()+")"); diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index d662a743a..0fc1b4e89 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -97,7 +97,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind * Constructor. Do not call this directly -- use {@link #create()} instead. */ protected GLWindow(Window window) { - super(null, null); + super(null, null, false); this.window = (WindowImpl) window; this.window.setHandleDestroyNotify(false); window.addWindowListener(new WindowAdapter() { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java index 1a33845b3..7977347a7 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java @@ -167,7 +167,7 @@ public class TestFBODrawableNEWT extends UITestCase { final FBObject.RenderAttachment depthA = fbo.getDepthAttachment(); Assert.assertNotNull(depthA); - final OffscreenAutoDrawable glad = new OffscreenAutoDrawable(fboDrawable, context, null); + final OffscreenAutoDrawable glad = new OffscreenAutoDrawable(fboDrawable, context, true); glad.addGLEventListener(demo); glad.addGLEventListener(new GLEventListener() { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java index 426b7734f..96d9b2e28 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java @@ -85,7 +85,7 @@ public class TestGLAutoDrawableDelegateNEWT extends UITestCase { Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); context.release(); - final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window) { + final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window, false) { @Override protected void destroyImplInLock() { super.destroyImplInLock(); // destroys drawable/context diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java index 92b4c5238..cece4c6d5 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java @@ -88,7 +88,7 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase { drawable.setRealized(true); Assert.assertTrue(drawable.isRealized()); - final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, null, window) { + final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, null, window, false) { @Override protected void destroyImplInLock() { super.destroyImplInLock(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java index e14d5b800..33a9b7799 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestNEWTCloseX11DisplayBug565.java @@ -43,10 +43,10 @@ public class TestNEWTCloseX11DisplayBug565 { if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) { final int openD = X11Util.getOpenDisplayConnectionNumber() - open0; - if(openD>1) { + if( openD > 0) { X11Util.dumpOpenDisplayConnections(); X11Util.dumpPendingDisplayConnections(); - Assert.assertTrue("More than 1 new open display connections", false); + Assert.assertEquals("New display connection didn't close", 0, openD); } } } @@ -86,10 +86,10 @@ public class TestNEWTCloseX11DisplayBug565 { if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) { final int openD = X11Util.getOpenDisplayConnectionNumber() - open0; - if(openD>1) { + if(openD > 0) { X11Util.dumpOpenDisplayConnections(); X11Util.dumpPendingDisplayConnections(); - Assert.assertTrue("More than 1 new open display connections", false); + Assert.assertEquals("New display connection didn't close", 0, openD); } } } -- cgit v1.2.3