From fa6ba9d70d4fe47f05facc72608fb10c889f9d09 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sun, 14 Sep 2014 01:14:38 +0200 Subject: GLJPanel: Allow reconfiguration of offscreen's GLCapabilitiesImmutable Offscreen's GLCapabilitiesImmutable reconfiguration will dispose a realized instance and issues recreation via initializeBackendImpl() immedietly. Implementation performs operation on AWT-EDT. Tests: - TestGearsES2GLJPanelAWT: - Toggle MSAA via 'm' - TestGearsGLJPanelAWT: - Toggle MSAA via 'm' - Toggle Bitmap via 'b' --- .../classes/javax/media/opengl/awt/GLJPanel.java | 63 +++++++++++++++++----- .../demos/es2/awt/TestGearsES2GLJPanelAWT.java | 19 +++++++ .../jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java | 51 ++++++++++++++++++ 3 files changed, 119 insertions(+), 14 deletions(-) diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index ee1ac5f5c..baa85cae3 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -251,9 +251,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing // private AWTGLPixelBufferProvider customPixelBufferProvider = null; /** Requested single buffered offscreen caps */ - private final GLCapabilitiesImmutable reqOffscreenCaps; - private final GLProfile glProfile; - private final GLDrawableFactoryImpl factory; + private volatile GLCapabilitiesImmutable reqOffscreenCaps; + private volatile GLDrawableFactoryImpl factory; private final GLCapabilitiesChooser chooser; private int additionalCtxCreationFlags = 0; @@ -360,8 +359,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing caps.setDoubleBuffered(false); reqOffscreenCaps = caps; } - this.glProfile = reqOffscreenCaps.getGLProfile(); - this.factory = GLDrawableFactoryImpl.getFactoryImpl(glProfile); + this.factory = GLDrawableFactoryImpl.getFactoryImpl( reqOffscreenCaps.getGLProfile() ); // pre-fetch, reqOffscreenCaps may changed this.chooser = chooser; helper = new GLDrawableHelper(); @@ -464,7 +462,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } } - protected void dispose() { + protected void dispose(final Runnable post) { if(DEBUG) { System.err.println(getThreadName()+": GLJPanel.dispose() - start"); // Thread.dumpStack(); @@ -487,15 +485,14 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing backend.destroy(); isInitialized = false; } + if( null != post ) { + post.run(); + } if( animatorPaused ) { animator.resume(); } } - hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; - hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; - nativePixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; - nativePixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; if(DEBUG) { System.err.println(getThreadName()+": GLJPanel.dispose() - stop"); @@ -645,7 +642,12 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing public void removeNotify() { awtWindowClosingProtocol.removeClosingListener(); - dispose(); + dispose(null); + hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; + hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; + nativePixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; + nativePixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; + super.removeNotify(); } @@ -1180,9 +1182,41 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing return reqOffscreenCaps; } + /** + * Set a new requested {@link GLCapabilitiesImmutable} for this GLJPanel + * allowing reconfiguration. + *

+ * Method shall be invoked from the {@link #isThreadGLCapable() AWT-EDT thread}. + * In case it is not invoked on the AWT-EDT thread, an attempt is made to do so. + *

+ *

+ * Method will dispose a previous {@link #isRealized() realized} GLContext and offscreen backend! + *

+ * @param caps new capabilities. + */ + public final void setRequestedGLCapabilities(final GLCapabilitiesImmutable caps) { + if( null == caps ) { + throw new IllegalArgumentException("null caps"); + } + Threading.invoke(true, + new Runnable() { + @Override + public void run() { + dispose( new Runnable() { + @Override + public void run() { + // switch to new caps and re-init backend + // after actual dispose, but before resume animator + reqOffscreenCaps = caps; + initializeBackendImpl(); + } } ); + } + }, getTreeLock()); + } + @Override public final GLProfile getGLProfile() { - return glProfile; + return reqOffscreenCaps.getGLProfile(); } @Override @@ -1273,12 +1307,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing if ( oglPipelineUsable() ) { backend = new J2DOGLBackend(); } else { - backend = new OffscreenBackend(glProfile, customPixelBufferProvider); + backend = new OffscreenBackend(customPixelBufferProvider); } isInitialized = false; } if (!isInitialized) { + this.factory = GLDrawableFactoryImpl.getFactoryImpl( reqOffscreenCaps.getGLProfile() ); // reqOffscreenCaps may have changed backend.initialize(); } return isInitialized; @@ -1578,7 +1613,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing // For saving/restoring of OpenGL state during ReadPixels private final GLPixelStorageModes psm = new GLPixelStorageModes(); - OffscreenBackend(final GLProfile glp, final AWTGLPixelBufferProvider custom) { + OffscreenBackend(final AWTGLPixelBufferProvider custom) { if(null == custom) { pixelBufferProvider = getSingleAWTGLPixelBufferProvider(); } else { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java index dd16b88cc..9841bb35e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java @@ -213,6 +213,25 @@ public class TestGearsES2GLJPanelAWT extends UITestCase { hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)"); setTitle(frame, glJPanel, caps); Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1); + } else if(e.getKeyChar()=='m') { + final GLCapabilitiesImmutable capsPre = glJPanel.getChosenGLCapabilities(); + final GLCapabilities capsNew = new GLCapabilities(capsPre.getGLProfile()); + capsNew.copyFrom(capsPre); + final boolean msaa; + if( capsPre.getSampleBuffers() ) { + capsNew.setSampleBuffers(false); + msaa = false; + } else { + capsNew.setSampleBuffers(true); + capsNew.setNumSamples(4); + msaa = true; + } + System.err.println("[set MSAA "+msaa+" Caps had]: "+capsPre); + System.err.println("[set MSAA "+msaa+" Caps new]: "+capsNew); + System.err.println("XXX-A1: "+animator.toString()); + glJPanel.setRequestedGLCapabilities(capsNew); + System.err.println("XXX-A2: "+animator.toString()); + System.err.println("XXX: "+glJPanel.toString()); } } }; new AWTKeyAdapter(kl, glJPanel).addTo(glJPanel); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java index 3650e4955..f47a9b794 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java @@ -30,6 +30,7 @@ package com.jogamp.opengl.test.junit.jogl.demos.gl2.awt; import javax.media.opengl.*; +import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.TraceKeyAdapter; import com.jogamp.newt.event.TraceWindowAdapter; import com.jogamp.newt.event.awt.AWTKeyAdapter; @@ -121,6 +122,56 @@ public class TestGearsGLJPanelAWT extends UITestCase { new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter), glJPanel).addTo(glJPanel); new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), glJPanel).addTo(frame); + final com.jogamp.newt.event.KeyListener kl = new com.jogamp.newt.event.KeyAdapter() { + @Override + public void keyPressed(final KeyEvent e) { + if( e.isAutoRepeat() ) { + return; + } + if(e.getKeyChar()=='m') { + final GLCapabilitiesImmutable capsPre = glJPanel.getChosenGLCapabilities(); + final GLCapabilities capsNew = new GLCapabilities(capsPre.getGLProfile()); + capsNew.copyFrom(capsPre); + final boolean msaa; + if( capsPre.getSampleBuffers() ) { + capsNew.setSampleBuffers(false); + capsNew.setDoubleBuffered(false); + msaa = false; + } else { + capsNew.setSampleBuffers(true); + capsNew.setNumSamples(4); + msaa = true; + } + System.err.println("[set MSAA "+msaa+" Caps had]: "+capsPre); + System.err.println("[set MSAA "+msaa+" Caps new]: "+capsNew); + System.err.println("XXX-A1: "+animator.toString()); + glJPanel.setRequestedGLCapabilities(capsNew); + System.err.println("XXX-A2: "+animator.toString()); + System.err.println("XXX: "+glJPanel.toString()); + } else if(e.getKeyChar()=='b') { + final GLCapabilitiesImmutable capsPre = glJPanel.getChosenGLCapabilities(); + final GLCapabilities capsNew = new GLCapabilities(capsPre.getGLProfile()); + capsNew.copyFrom(capsPre); + final boolean bmp; + if( capsPre.isBitmap() ) { + capsNew.setBitmap(false); // auto-choose + bmp = false; + } else { + capsNew.setBitmap(true); + capsNew.setFBO(false); + capsNew.setPBuffer(false); + bmp = true; + } + System.err.println("[set Bitmap "+bmp+" Caps had]: "+capsPre); + System.err.println("[set Bitmap "+bmp+" Caps new]: "+capsNew); + System.err.println("XXX-A1: "+animator.toString()); + glJPanel.setRequestedGLCapabilities(capsNew); + System.err.println("XXX-A2: "+animator.toString()); + System.err.println("XXX: "+glJPanel.toString()); + } + } }; + new AWTKeyAdapter(kl, glJPanel).addTo(glJPanel); + final long t0 = System.currentTimeMillis(); long t1 = t0; boolean triggerSnap = false; -- cgit v1.2.3